diff options
Diffstat (limited to 'WebKit')
295 files changed, 19114 insertions, 5599 deletions
diff --git a/WebKit/Android.mk b/WebKit/Android.mk index b3de259..5e79d5a 100644 --- a/WebKit/Android.mk +++ b/WebKit/Android.mk @@ -21,6 +21,7 @@ LOCAL_SRC_FILES := \ android/WebCoreSupport/DragClientAndroid.cpp \ android/WebCoreSupport/EditorClientAndroid.cpp \ android/WebCoreSupport/FrameLoaderClientAndroid.cpp \ + android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp \ \ android/RenderSkinAndroid.cpp \ android/RenderSkinButton.cpp \ @@ -40,6 +41,7 @@ LOCAL_SRC_FILES := \ android/jni/WebFrameView.cpp \ android/jni/WebHistory.cpp \ android/jni/WebIconDatabase.cpp \ + android/jni/WebStorage.cpp \ android/jni/WebSettings.cpp \ android/jni/WebViewCore.cpp \ \ @@ -52,13 +54,17 @@ LOCAL_SRC_FILES := \ android/nav/SelectText.cpp \ android/nav/WebView.cpp \ \ + android/plugins/ANPBitmapInterface.cpp \ android/plugins/ANPCanvasInterface.cpp \ android/plugins/ANPLogInterface.cpp \ android/plugins/ANPMatrixInterface.cpp \ android/plugins/ANPPaintInterface.cpp \ + android/plugins/ANPPathInterface.cpp \ android/plugins/ANPSoundInterface.cpp \ + android/plugins/ANPSurfaceInterface.cpp \ android/plugins/ANPTypefaceInterface.cpp \ android/plugins/ANPWindowInterface.cpp \ + android/plugins/PluginSurface.cpp \ android/plugins/PluginTimer.cpp \ android/plugins/PluginViewBridgeAndroid.cpp \ android/plugins/PluginWidgetAndroid.cpp \ diff --git a/WebKit/ChangeLog b/WebKit/ChangeLog index 457e527..d7d9265 100644 --- a/WebKit/ChangeLog +++ b/WebKit/ChangeLog @@ -1,3 +1,114 @@ +2009-03-16 Darin Adler <darin@apple.com> + + Reviewed by Dan Bernstein. + + * English.lproj/Localizable.strings: Updated. + * StringsNotToBeLocalized.txt: Updated for recent changes. + +2009-03-13 Greg Bolsinga <bolsinga@apple.com> + + Reviewed by Simon Fraser. + + Update Geolocation perimission dialogs to be asynchronous. + https://bugs.webkit.org/show_bug.cgi?id=24505 + + Add WebGeolocation, a wrapper around WebCore::Geolocation. It mimics the + coding style set by WebSecurityOrigin. + + * WebKit.xcodeproj/project.pbxproj: + +2009-03-13 Anders Carlsson <andersca@apple.com> + + Reviewed by Dan Bernstein. + + <rdar://problem/6610666> Revise the Cocoa event model text API + + Remove nptextinput.h + + * WebKit.xcodeproj/project.pbxproj: + +2009-03-03 David Kilzer <ddkilzer@apple.com> + + <rdar://problem/6581203> WebCore and WebKit should install the same set of headers during installhdrs phase as build phase + + Reviewed by Mark Rowe. + + The fix is to add INSTALLHDRS_COPY_PHASE = YES and + INSTALLHDRS_SCRIPT_PHASE = YES to WebKit.xcconfig, then to + make sure various build phase scripts work with the installhdrs + build phase. + + * WebKit.xcodeproj/project.pbxproj: + - Added shell code to prevent running "Check For Global + Initializers", "Check For Exit Time Destructors" and "Check + For Weak VTables" scripts during the installhdrs build phase. + - Removed UMBRELLA_FRAMEWORKS_DIR from the Debug and Release + targets since it's no longer needed after defining + WEBCORE_PRIVATE_HEADERS_DIR in WebKit.xcconfig. + +2009-03-03 David Kilzer <ddkilzer@apple.com> + + Remove last vestiges of JAVASCRIPTCORE_PRIVATE_HEADERS_DIR from WebKit + + Reviewed by Adam Roben. + + Use of JAVASCRIPTCORE_PRIVATE_HEADERS_DIR was removed in r37465 + since NPAPI headers had migrated from JavaScriptCore to WebCore + before that. + + * WebKit.xcodeproj/project.pbxproj: Removed + JAVASCRIPTCORE_PRIVATE_HEADERS_DIR build setting from from Debug + and Release configurations. + +2009-03-02 Anders Carlsson <andersca@apple.com> + + WebNetscapePluginPackage.mm is an Objective-C++ file. + + * WebKit.xcodeproj/project.pbxproj: + +2009-03-02 Anders Carlsson <andersca@apple.com> + + Reviewed by John Sullivan. + + Rename WebNetscapePluginPackage.m to WebNetscapePluginPackage.mm + + * WebKit.xcodeproj/project.pbxproj: + +2009-02-20 Anders Carlsson <andersca@apple.com> + + Reviewed by Dan Bernstein. + + Add new files. + + * WebKit.xcodeproj/project.pbxproj: + +2009-02-13 Darin Adler <darin@apple.com> + + * StringsNotToBeLocalized.txt: Updated for recent changes. + +2009-02-07 Darin Adler <darin@apple.com> + + * StringsNotToBeLocalized.txt: Updated for recent changes. + +2009-02-04 Timothy Hatcher <timothy@apple.com> + + Removed the WebDefaultScriptDebugDelegate now that we have CallScriptDebugDelegate. + + <rdar://problem/6508457> Launching widget in Dashcode debugger is + super-slow due forwardInvocation: calling debug delegate + + Reviewed by Oliver Hunt. + + * WebKit.xcodeproj/project.pbxproj: + +2009-02-02 Anders Carlsson <andersca@apple.com> + + Reviewed by Dan Bernstein. + + Remove WebKitPluginContainerView.{h|mm}, they aren't used anywhere. + + * WebKit.xcodeproj/project.pbxproj: + 2009-01-26 Mark Rowe <mrowe@apple.com> Rubber-stamped by Sam Weinig. diff --git a/WebKit/English.lproj/Localizable.strings b/WebKit/English.lproj/Localizable.strings Binary files differindex c1584f9..2bd823c 100644 --- a/WebKit/English.lproj/Localizable.strings +++ b/WebKit/English.lproj/Localizable.strings diff --git a/WebKit/StringsNotToBeLocalized.txt b/WebKit/StringsNotToBeLocalized.txt index 2cc5d69..07fe282 100644 --- a/WebKit/StringsNotToBeLocalized.txt +++ b/WebKit/StringsNotToBeLocalized.txt @@ -7,6 +7,7 @@ " >>>" " Mac OS X %@; %@) AppleWebKit/%@ (KHTML, like Gecko) %@" " Mac OS X %@; %@) AppleWebKit/%@ (KHTML, like Gecko)" +" Version/3.2.1" " webViewDrawResizer delegate call" "#" "%" @@ -42,6 +43,7 @@ "," "-" "-1px" +"-createPluginMIMETypesPreferences" "-khtml-text-decorations-in-effect" "." "._" @@ -103,16 +105,16 @@ "BEGIN:VCARD" "BP_CreatePluginMIMETypesPreferences" "CFDictionaryPropertyBag" -"CFNetwork" -"CFNetwork_debug" -"CFURLCacheCopySharedURLCache" "CSS" "Content-Encoding" "Content-Length" "Content-Type" +"D" "DCMDictionaryServiceWindowShow" "DELEGATE METHODS" "DOCBASE" +"DOMHTMLObjectElement" +"DOMNode" "DYLD_FRAMEWORK_PATH" "DefaultDownloadDelegate" "DefaultPolicyDelegate" @@ -127,6 +129,7 @@ "FastMallocReturnedSize" "FrameName" "GEN_DOMObject" +"GET" "GroupName" "HIDictionaryWindowShow" "Helvetica" @@ -159,7 +162,6 @@ "Library/Internet Plug-Ins" "LresultFromObject" "Lucida Grande" -"MIMEType" "MIME\\Database\\Content Type" "MainPageJavaScript.js" "MemoryStream" @@ -224,6 +226,7 @@ "UseBackForwardList" "User-Agent" "Volumes" +"W" "WEBKIT_UNSET_DYLD_FRAMEWORK_PATH" "WebActionButtonKey" "WebActionElementKey" @@ -307,6 +310,7 @@ "WebKitHistoryItemLimit" "WebKitInspectorAttached" "WebKitInspectorAttachedViewHeight" +"WebKitInspectorHiddenPanels" "WebKitLogLevel" "WebKitOmitPDFSupport" "WebKitOriginalBottomMargin" @@ -399,6 +403,7 @@ "\n--------------------------------------------\n" "\r" "\xFF\xD8\xFF\xE0" +"_isUsingAcceleratedCompositing" "_top" "a" "ab" @@ -435,6 +440,7 @@ "com.adobe.dreamweaver-9.0" "com.apple.Aperture" "com.apple.AppKit" +"com.apple.Automator" "com.apple.Dictionary" "com.apple.HIWebView" "com.apple.JavaAppletPlugin" @@ -447,13 +453,14 @@ "com.apple.WebKit.PluginAgent" "com.apple.hiview" "com.apple.iWeb" +"com.apple.installer" "com.apple.mail" "com.apple.quicktime.webplugin" "com.apple.universalaccess" "com.lizardtech.NPDjVu" "com.macromedia.fireworks" +"com.microsoft.SilverlightPlugin" "com.microsoft.WMP.defaultplugin" -"copyData" "cpuType" "dir" "displayTitle" @@ -464,11 +471,15 @@ "file:" "frameName" "ftp:" +"groupName" "htm" "html" +"http" +"http:" "http://" "http://www.google.com/search?q=" "https" +"https:" "i" "icon.db" "image.pict" @@ -486,6 +497,7 @@ "javascript:" "js" "lastVisitWasFailure" +"lastVisitWasHTTPNonGet" "lastVisitedDate" "line-through" "lineNumber" @@ -497,7 +509,6 @@ "mainFrameIcon" "mainFrameTitle" "mainFrameURL" -"mainResource" "mimeType" "name: %@\npath: %@\nmimeTypes:\n%@\npluginDescription:%@" "nullplugin" @@ -506,14 +517,13 @@ "pluginspage" "r" "r+b" +"redirectURLs" "rgb(%.0f,%.0f,%.0f)" "rgba(%.0f,%.0f,%.0f,%f)" "s" "sourceURL" "src" "sub" -"subframeArchives" -"subresources" "text/calendar" "text/directory" "text/html" @@ -530,13 +540,13 @@ "text/x-vcalendar" "text/x-vcard" "text/x-vcf" -"textEncodingName" "tiff" "txt" "u" "userAgent" "utf-16" "vImagePermuteChannels_ARGB8888" +"visibleName" "visitCount" "webkit-fake-url" "webplugin" @@ -555,25 +565,22 @@ WebKit/mac/Misc/WebCache.mm:"Images" WebKit/mac/Misc/WebKitLogging.h:"<not running on main thread>" WebKit/mac/Misc/WebKitVersionChecks.m:"WebKit" WebKit/mac/Misc/WebNSNotificationCenterExtras.m -WebKit/mac/Misc/WebNSObjectExtras.mm:"object" -WebKit/mac/Misc/WebNSObjectExtras.mm:"selector" -WebKit/mac/Misc/WebNSObjectExtras.mm:"result" WebKit/mac/Misc/WebNSPasteboardExtras.mm WebKit/mac/Misc/WebNSURLExtras.mm:"file" WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.mm:" OK\n" WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.mm:": " WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.mm:"HTTP " WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.mm:"identity" +WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.mm:"%@ Plug-in Host - %@" WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm:" OK\n" WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm:": " WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm:"HTTP " WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm:"identity" WebKit/mac/Plugins/WebBasePluginPackage.mm:"Java Applet Plugin Enabler" -WebKit/mac/Plugins/WebNetscapePluginPackage.m:"RealPlayer Plugin" -WebKit/mac/Plugins/WebNetscapePluginPackage.m:"main" +WebKit/mac/Plugins/WebNetscapePluginPackage.mm:"RealPlayer Plugin" +WebKit/mac/Plugins/WebNetscapePluginPackage.mm:"main" WebKit/mac/Plugins/WebNetscapePluginView.mm:"height" WebKit/mac/Plugins/WebNetscapePluginView.mm:"width" -WebKit/mac/Plugins/nptextinput.h WebKit/mac/WebCoreSupport/WebChromeClient.mm:"dialog" WebKit/mac/WebCoreSupport/WebChromeClient.mm:"fullscreen" WebKit/mac/WebCoreSupport/WebChromeClient.mm:"height" @@ -592,7 +599,6 @@ WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm:"height" WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm:"width" WebKit/mac/WebCoreSupport/WebInspectorClient.mm:"Web Inspector 2" WebKit/mac/WebCoreSupport/WebInspectorClient.mm:"inspector" -WebKit/mac/WebView/WebArchive.mm:"result" WebKit/mac/WebView/WebHTMLView.mm:"'%@'" WebKit/mac/WebView/WebHTMLView.mm:"Version:" WebKit/mac/WebView/WebHTMLView.mm:"applet" @@ -605,6 +611,8 @@ WebKit/mac/WebView/WebHTMLView.mm:"direction" WebKit/mac/WebView/WebHTMLView.mm:"font" WebKit/mac/WebView/WebHTMLView.mm:"head" WebKit/mac/WebView/WebHTMLView.mm:"italic" +WebKit/mac/WebView/WebHTMLView.mm:"jpeg" +WebKit/mac/WebView/WebHTMLView.mm:"jpg" WebKit/mac/WebView/WebHTMLView.mm:"menu" WebKit/mac/WebView/WebHTMLView.mm:"none" WebKit/mac/WebView/WebHTMLView.mm:"normal" @@ -619,15 +627,14 @@ WebKit/mac/WebView/WebHTMLView.mm:"underline" WebKit/mac/WebView/WebHTMLView.mm:"white" WebKit/mac/WebView/WebPreferenceKeysPrivate.h WebKit/mac/WebView/WebPreferences.mm -WebKit/mac/WebView/WebResource.mm:"URL" -WebKit/mac/WebView/WebResource.mm:"data" -WebKit/mac/WebView/WebResource.mm:"response" -WebKit/mac/WebView/WebResource.mm:"result" WebKit/mac/WebView/WebView.mm:"At least one WebView is still open." WebKit/mac/WebView/WebView.mm:"At least one WebView was closed with fast teardown." WebKit/mac/WebView/WebView.mm:"Preferences" WebKit/mac/WebView/WebView.mm:"Search With Google" WebKit/mac/WebView/WebView.mm:"control" +WebKit/mac/WebView/WebView.mm:"data" +WebKit/mac/WebView/WebView.mm:"decoder" +WebKit/mac/WebView/WebView.mm:"frame" WebKit/mac/WebView/WebView.mm:"return " WebKit/win/AccessibleBase.cpp WebKit/win/DOMCoreClasses.h diff --git a/WebKit/WebKit.xcodeproj/project.pbxproj b/WebKit/WebKit.xcodeproj/project.pbxproj index 698deb2..0df3e64 100644 --- a/WebKit/WebKit.xcodeproj/project.pbxproj +++ b/WebKit/WebKit.xcodeproj/project.pbxproj @@ -23,9 +23,10 @@ 1A4DF5230EC8C74D006BD4B4 /* WebNetscapePluginView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A4DF5210EC8C74D006BD4B4 /* WebNetscapePluginView.mm */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; }; 1A4DF5E40EC8D104006BD4B4 /* WebBaseNetscapePluginView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A4DF5E20EC8D104006BD4B4 /* WebBaseNetscapePluginView.h */; }; 1A4DF5E50EC8D104006BD4B4 /* WebBaseNetscapePluginView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A4DF5E30EC8D104006BD4B4 /* WebBaseNetscapePluginView.mm */; }; + 1A74A28E0F4F75400082E228 /* WebTextInputWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A74A28C0F4F75400082E228 /* WebTextInputWindowController.h */; }; + 1A74A28F0F4F75400082E228 /* WebTextInputWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A74A28D0F4F75400082E228 /* WebTextInputWindowController.m */; }; 1A77B02E0EE7730500C8A1F9 /* WebPluginRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A77B02C0EE7730500C8A1F9 /* WebPluginRequest.h */; }; 1A77B02F0EE7730500C8A1F9 /* WebPluginRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A77B02D0EE7730500C8A1F9 /* WebPluginRequest.m */; }; - 1A7F9C4C0DD3DDEA0028F8A5 /* nptextinput.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A7F9C4B0DD3DDEA0028F8A5 /* nptextinput.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1A8DED500EE88B8A00F25022 /* HostedNetscapePluginStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A8DED4E0EE88B8A00F25022 /* HostedNetscapePluginStream.h */; }; 1A8DED510EE88B8A00F25022 /* HostedNetscapePluginStream.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A8DED4F0EE88B8A00F25022 /* HostedNetscapePluginStream.mm */; }; 1AAF58940EDCCF15008D883D /* WebKitPluginAgent.defs in Headers */ = {isa = PBXBuildFile; fileRef = 1AAF588A0EDCCEA3008D883D /* WebKitPluginAgent.defs */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -109,8 +110,6 @@ 65EEDE58084FFC9E0002DB25 /* WebNSFileManagerExtras.m in Sources */ = {isa = PBXBuildFile; fileRef = 65EEDE56084FFC9E0002DB25 /* WebNSFileManagerExtras.m */; }; 65FFB7FC0AD0B7D30048CD05 /* WebDocumentLoaderMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 65FFB7FA0AD0B7D30048CD05 /* WebDocumentLoaderMac.h */; }; 65FFB7FD0AD0B7D30048CD05 /* WebDocumentLoaderMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 65FFB7FB0AD0B7D30048CD05 /* WebDocumentLoaderMac.mm */; }; - 7E6FEF0108985A3E00C44C3F /* WebDefaultScriptDebugDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E6FEEFF08985A3E00C44C3F /* WebDefaultScriptDebugDelegate.h */; }; - 7E6FEF0208985A3E00C44C3F /* WebDefaultScriptDebugDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E6FEF0008985A3E00C44C3F /* WebDefaultScriptDebugDelegate.m */; }; 7E6FEF0808985A7200C44C3F /* WebScriptDebugDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E6FEF0508985A7200C44C3F /* WebScriptDebugDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 7E6FEF0908985A7200C44C3F /* WebScriptDebugDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7E6FEF0608985A7200C44C3F /* WebScriptDebugDelegate.mm */; }; 9304B3000B02341500F7850D /* WebIconDatabaseInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 9304B2FF0B02341500F7850D /* WebIconDatabaseInternal.h */; }; @@ -242,7 +241,7 @@ 939810D00824BF01008DF038 /* WebPanelAuthenticationHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 93154EF203A41270008635CE /* WebPanelAuthenticationHandler.m */; }; 939810D10824BF01008DF038 /* WebBaseNetscapePluginStream.mm in Sources */ = {isa = PBXBuildFile; fileRef = F5A672BA0263866E01000102 /* WebBaseNetscapePluginStream.mm */; }; 939810D30824BF01008DF038 /* WebBasePluginPackage.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83E4AF47036652150000E506 /* WebBasePluginPackage.mm */; }; - 939810D60824BF01008DF038 /* WebNetscapePluginPackage.m in Sources */ = {isa = PBXBuildFile; fileRef = F5F7171F0288493C018635CA /* WebNetscapePluginPackage.m */; }; + 939810D60824BF01008DF038 /* WebNetscapePluginPackage.mm in Sources */ = {isa = PBXBuildFile; fileRef = F5F7171F0288493C018635CA /* WebNetscapePluginPackage.mm */; }; 939810D90824BF01008DF038 /* WebNullPluginView.mm in Sources */ = {isa = PBXBuildFile; fileRef = F5883BE1025E5E9D01000102 /* WebNullPluginView.mm */; }; 939810DA0824BF01008DF038 /* WebPluginController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8467275D0367158500CA2ACA /* WebPluginController.mm */; }; 939810DB0824BF01008DF038 /* WebPluginDatabase.mm in Sources */ = {isa = PBXBuildFile; fileRef = F5F717210288493C018635CA /* WebPluginDatabase.mm */; }; @@ -303,8 +302,6 @@ A7D3C5BC0B5773C5002CA450 /* WebPasteboardHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D3C5BA0B5773C5002CA450 /* WebPasteboardHelper.h */; }; A7D3C5BD0B5773C5002CA450 /* WebPasteboardHelper.mm in Sources */ = {isa = PBXBuildFile; fileRef = A7D3C5BB0B5773C5002CA450 /* WebPasteboardHelper.mm */; }; ABDDF20D08EB0DDC001E1241 /* WebDownloadInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = ABDDF20C08EB0DDC001E1241 /* WebDownloadInternal.h */; }; - BCDFA8F90C10B6F500D3A10C /* WebKitPluginContainerView.h in Headers */ = {isa = PBXBuildFile; fileRef = BCDFA8F80C10B6F500D3A10C /* WebKitPluginContainerView.h */; }; - BCDFA9130C10B93E00D3A10C /* WebKitPluginContainerView.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCDFA9120C10B93E00D3A10C /* WebKitPluginContainerView.mm */; }; C0167BF80D7F5DD00028696E /* WebScriptDebugger.h in Headers */ = {isa = PBXBuildFile; fileRef = C0167BF60D7F5DD00028696E /* WebScriptDebugger.h */; }; C0167BF90D7F5DD00028696E /* WebScriptDebugger.mm in Sources */ = {isa = PBXBuildFile; fileRef = C0167BF70D7F5DD00028696E /* WebScriptDebugger.mm */; }; DD7CDEE70A23BA9E00069928 /* WebTypesInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = DD7CDEE60A23BA9E00069928 /* WebTypesInternal.h */; }; @@ -317,6 +314,9 @@ EDE983810BCDF5FE00FDAE28 /* WebNSArrayExtras.m in Sources */ = {isa = PBXBuildFile; fileRef = EDE9837F0BCDF5FE00FDAE28 /* WebNSArrayExtras.m */; }; F834AAD70E64B1C700E2737C /* WebTextIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = F834AAD50E64B1C700E2737C /* WebTextIterator.h */; settings = {ATTRIBUTES = (Private, ); }; }; F834AAD80E64B1C700E2737C /* WebTextIterator.mm in Sources */ = {isa = PBXBuildFile; fileRef = F834AAD60E64B1C700E2737C /* WebTextIterator.mm */; }; + FEF52DFA0F6748F200FF70EE /* WebGeolocation.mm in Sources */ = {isa = PBXBuildFile; fileRef = FEF52DF70F6748F200FF70EE /* WebGeolocation.mm */; }; + FEF52DFB0F6748F200FF70EE /* WebGeolocationInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF52DF80F6748F200FF70EE /* WebGeolocationInternal.h */; }; + FEF52DFC0F6748F200FF70EE /* WebGeolocationPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF52DF90F6748F200FF70EE /* WebGeolocationPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -336,9 +336,10 @@ 1A4DF5210EC8C74D006BD4B4 /* WebNetscapePluginView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebNetscapePluginView.mm; sourceTree = "<group>"; }; 1A4DF5E20EC8D104006BD4B4 /* WebBaseNetscapePluginView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebBaseNetscapePluginView.h; sourceTree = "<group>"; }; 1A4DF5E30EC8D104006BD4B4 /* WebBaseNetscapePluginView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebBaseNetscapePluginView.mm; sourceTree = "<group>"; }; + 1A74A28C0F4F75400082E228 /* WebTextInputWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebTextInputWindowController.h; sourceTree = "<group>"; }; + 1A74A28D0F4F75400082E228 /* WebTextInputWindowController.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = WebTextInputWindowController.m; sourceTree = "<group>"; }; 1A77B02C0EE7730500C8A1F9 /* WebPluginRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPluginRequest.h; sourceTree = "<group>"; }; 1A77B02D0EE7730500C8A1F9 /* WebPluginRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebPluginRequest.m; sourceTree = "<group>"; }; - 1A7F9C4B0DD3DDEA0028F8A5 /* nptextinput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nptextinput.h; sourceTree = "<group>"; }; 1A8DED4E0EE88B8A00F25022 /* HostedNetscapePluginStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HostedNetscapePluginStream.h; sourceTree = "<group>"; }; 1A8DED4F0EE88B8A00F25022 /* HostedNetscapePluginStream.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = HostedNetscapePluginStream.mm; sourceTree = "<group>"; }; 1AAF588A0EDCCEA3008D883D /* WebKitPluginAgent.defs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.mig; path = WebKitPluginAgent.defs; sourceTree = "<group>"; }; @@ -478,8 +479,6 @@ 65FFB7FB0AD0B7D30048CD05 /* WebDocumentLoaderMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = WebDocumentLoaderMac.mm; sourceTree = "<group>"; }; 7082F56F038EADAA00A80180 /* WebKitNSStringExtras.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebKitNSStringExtras.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; 7082F570038EADAA00A80180 /* WebKitNSStringExtras.m */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebKitNSStringExtras.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; - 7E6FEEFF08985A3E00C44C3F /* WebDefaultScriptDebugDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebDefaultScriptDebugDelegate.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; - 7E6FEF0008985A3E00C44C3F /* WebDefaultScriptDebugDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebDefaultScriptDebugDelegate.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; 7E6FEF0508985A7200C44C3F /* WebScriptDebugDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebScriptDebugDelegate.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; 7E6FEF0608985A7200C44C3F /* WebScriptDebugDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebScriptDebugDelegate.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; 830E81E005853AC000AD0891 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = "<absolute>"; }; @@ -547,8 +546,6 @@ A7D3C5BA0B5773C5002CA450 /* WebPasteboardHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPasteboardHelper.h; sourceTree = "<group>"; }; A7D3C5BB0B5773C5002CA450 /* WebPasteboardHelper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPasteboardHelper.mm; sourceTree = "<group>"; }; ABDDF20C08EB0DDC001E1241 /* WebDownloadInternal.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebDownloadInternal.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; - BCDFA8F80C10B6F500D3A10C /* WebKitPluginContainerView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebKitPluginContainerView.h; sourceTree = "<group>"; }; - BCDFA9120C10B93E00D3A10C /* WebKitPluginContainerView.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = WebKitPluginContainerView.mm; sourceTree = "<group>"; }; BE4FBECB0653DF47005EDE15 /* WebEditingDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebEditingDelegate.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; BE6DC39904C62C4E004D0EF6 /* WebNSURLExtras.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebNSURLExtras.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; BE6DC39A04C62C4E004D0EF6 /* WebNSURLExtras.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebNSURLExtras.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; @@ -609,7 +606,7 @@ F5E0A76E02B8FEE401C1A525 /* WebURLsWithTitles.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebURLsWithTitles.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; F5E0A76F02B8FEE401C1A525 /* WebURLsWithTitles.m */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebURLsWithTitles.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; F5F7171E0288493C018635CA /* WebNetscapePluginPackage.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebNetscapePluginPackage.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; - F5F7171F0288493C018635CA /* WebNetscapePluginPackage.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebNetscapePluginPackage.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; + F5F7171F0288493C018635CA /* WebNetscapePluginPackage.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; indentWidth = 4; path = WebNetscapePluginPackage.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; F5F717200288493C018635CA /* WebPluginDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebPluginDatabase.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; F5F717210288493C018635CA /* WebPluginDatabase.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; indentWidth = 4; path = WebPluginDatabase.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; F5F717230288493C018635CA /* npapi.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; indentWidth = 4; path = npapi.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; @@ -636,6 +633,9 @@ F834AAD60E64B1C700E2737C /* WebTextIterator.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebTextIterator.mm; sourceTree = "<group>"; }; F8CA15B5029A39D901000122 /* WebAuthenticationPanel.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebAuthenticationPanel.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; F8CA15B6029A39D901000122 /* WebAuthenticationPanel.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebAuthenticationPanel.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; + FEF52DF70F6748F200FF70EE /* WebGeolocation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebGeolocation.mm; sourceTree = "<group>"; }; + FEF52DF80F6748F200FF70EE /* WebGeolocationInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebGeolocationInternal.h; sourceTree = "<group>"; }; + FEF52DF90F6748F200FF70EE /* WebGeolocationPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebGeolocationPrivate.h; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -747,6 +747,8 @@ 1AAF588D0EDCCEA3008D883D /* WebKitPluginHost.defs */, 1AAF588E0EDCCEA3008D883D /* WebKitPluginHostTypes.defs */, 1AAF5D080EDDE71D008D883D /* WebKitPluginHostTypes.h */, + 1A74A28C0F4F75400082E228 /* WebTextInputWindowController.h */, + 1A74A28D0F4F75400082E228 /* WebTextInputWindowController.m */, ); path = Hosted; sourceTree = "<group>"; @@ -941,8 +943,6 @@ BE95BEE505FD0805006E1513 /* WebDefaultEditingDelegate.m */, 5152FADF033FC50400CA2ACD /* WebDefaultPolicyDelegate.h */, 5152FAE0033FC50400CA2ACD /* WebDefaultPolicyDelegate.m */, - 7E6FEEFF08985A3E00C44C3F /* WebDefaultScriptDebugDelegate.h */, - 7E6FEF0008985A3E00C44C3F /* WebDefaultScriptDebugDelegate.m */, 515E27CF0458CA4B00CA2D3A /* WebDefaultUIDelegate.h */, 515E27D00458CA4B00CA2D3A /* WebDefaultUIDelegate.m */, ); @@ -964,13 +964,12 @@ 226E9E6909D0AA8200F3A2BC /* WebNetscapeDeprecatedFunctions.c */, 226E9E6809D0AA8200F3A2BC /* WebNetscapeDeprecatedFunctions.h */, F5F7171E0288493C018635CA /* WebNetscapePluginPackage.h */, - F5F7171F0288493C018635CA /* WebNetscapePluginPackage.m */, + F5F7171F0288493C018635CA /* WebNetscapePluginPackage.mm */, 1A4DF5200EC8C74D006BD4B4 /* WebNetscapePluginView.h */, 1A4DF5210EC8C74D006BD4B4 /* WebNetscapePluginView.mm */, 1A77B02C0EE7730500C8A1F9 /* WebPluginRequest.h */, 1A77B02D0EE7730500C8A1F9 /* WebPluginRequest.m */, F5F717230288493C018635CA /* npapi.mm */, - 1A7F9C4B0DD3DDEA0028F8A5 /* nptextinput.h */, ); name = "Netscape Plug-ins"; sourceTree = "<group>"; @@ -979,8 +978,6 @@ isa = PBXGroup; children = ( 51863EFC065419EB00E9E8DD /* WebJavaPlugIn.h */, - BCDFA8F80C10B6F500D3A10C /* WebKitPluginContainerView.h */, - BCDFA9120C10B93E00D3A10C /* WebKitPluginContainerView.mm */, 848DFF840365FE6A00CA2ACA /* WebPlugin.h */, 848DFF850365FE6A00CA2ACA /* WebPluginContainer.h */, 65E1150307EFFEBF009B8BF7 /* WebPluginContainerCheck.h */, @@ -1108,6 +1105,9 @@ 4BF99F8F0AE050BC00815C2B /* WebEditorClient.mm */, 931633EA0AEDFF930062B92D /* WebFrameLoaderClient.h */, 931633EE0AEDFFAE0062B92D /* WebFrameLoaderClient.mm */, + FEF52DF70F6748F200FF70EE /* WebGeolocation.mm */, + FEF52DF80F6748F200FF70EE /* WebGeolocationInternal.h */, + FEF52DF90F6748F200FF70EE /* WebGeolocationPrivate.h */, 51494CD40C7EBDE0004178C5 /* WebIconDatabaseClient.h */, 51494CD50C7EBDE0004178C5 /* WebIconDatabaseClient.mm */, 9CE1F8A302A5C6F30ECA2ACD /* WebImageRendererFactory.m */, @@ -1256,7 +1256,6 @@ 9398104E0824BF01008DF038 /* WebDefaultContextMenuDelegate.h in Headers */, 9398108D0824BF01008DF038 /* WebDefaultEditingDelegate.h in Headers */, 9398104F0824BF01008DF038 /* WebDefaultPolicyDelegate.h in Headers */, - 7E6FEF0108985A3E00C44C3F /* WebDefaultScriptDebugDelegate.h in Headers */, 939810760824BF01008DF038 /* WebDefaultUIDelegate.h in Headers */, 939810500824BF01008DF038 /* WebDocument.h in Headers */, 9398107F0824BF01008DF038 /* WebDocumentInternal.h in Headers */, @@ -1315,7 +1314,6 @@ 1AAF58940EDCCF15008D883D /* WebKitPluginAgent.defs in Headers */, 1AAF58950EDCCF15008D883D /* WebKitPluginAgentReply.defs in Headers */, 1AAF58960EDCCF15008D883D /* WebKitPluginClient.defs in Headers */, - BCDFA8F90C10B6F500D3A10C /* WebKitPluginContainerView.h in Headers */, 1AAF58970EDCCF15008D883D /* WebKitPluginHost.defs in Headers */, 1AAF58980EDCCF15008D883D /* WebKitPluginHostTypes.defs in Headers */, 1AAF5D090EDDE71D008D883D /* WebKitPluginHostTypes.h in Headers */, @@ -1394,8 +1392,10 @@ 939810460824BF01008DF038 /* WebViewFactory.h in Headers */, 9398109B0824BF01008DF038 /* WebViewInternal.h in Headers */, 939810710824BF01008DF038 /* WebViewPrivate.h in Headers */, - 1A7F9C4C0DD3DDEA0028F8A5 /* nptextinput.h in Headers */, 1A2DBE9F0F251E3A0036F8A6 /* ProxyInstance.h in Headers */, + 1A74A28E0F4F75400082E228 /* WebTextInputWindowController.h in Headers */, + FEF52DFB0F6748F200FF70EE /* WebGeolocationInternal.h in Headers */, + FEF52DFC0F6748F200FF70EE /* WebGeolocationPrivate.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1517,7 +1517,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ -f ../WebKitTools/Scripts/check-for-weak-vtables ]; then\n ../WebKitTools/Scripts/check-for-weak-vtables || exit $?\nfi"; + shellScript = "if [ \"${ACTION}\" = \"installhdrs\" ]; then\n exit 0;\nfi\n\nif [ -f ../WebKitTools/Scripts/check-for-weak-vtables ]; then\n ../WebKitTools/Scripts/check-for-weak-vtables || exit $?\nfi"; }; 5D2F7DB70C687A5A00B5B72B /* Update Info.plist with version information */ = { isa = PBXShellScriptBuildPhase; @@ -1547,7 +1547,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ -f ../WebKitTools/Scripts/check-for-exit-time-destructors ]; then\n ../WebKitTools/Scripts/check-for-exit-time-destructors || exit $?\nfi"; + shellScript = "if [ \"${ACTION}\" = \"installhdrs\" ]; then\n exit 0;\nfi\n\nif [ -f ../WebKitTools/Scripts/check-for-exit-time-destructors ]; then\n ../WebKitTools/Scripts/check-for-exit-time-destructors || exit $?\nfi"; }; 939811300824BF01008DF038 /* Make Frameworks Symbolic Link */ = { isa = PBXShellScriptBuildPhase; @@ -1577,7 +1577,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ -f ../WebKitTools/Scripts/check-for-global-initializers ]; then\n ../WebKitTools/Scripts/check-for-global-initializers || exit $?\nfi"; + shellScript = "if [ \"${ACTION}\" = \"installhdrs\" ]; then\n exit 0;\nfi\n\nif [ -f ../WebKitTools/Scripts/check-for-global-initializers ]; then\n ../WebKitTools/Scripts/check-for-global-initializers || exit $?\nfi"; }; /* End PBXShellScriptBuildPhase section */ @@ -1615,7 +1615,6 @@ 939810EF0824BF01008DF038 /* WebDefaultContextMenuDelegate.mm in Sources */, 9398111B0824BF01008DF038 /* WebDefaultEditingDelegate.m in Sources */, 939810F00824BF01008DF038 /* WebDefaultPolicyDelegate.m in Sources */, - 7E6FEF0208985A3E00C44C3F /* WebDefaultScriptDebugDelegate.m in Sources */, 9398110A0824BF01008DF038 /* WebDefaultUIDelegate.m in Sources */, 65FFB7FD0AD0B7D30048CD05 /* WebDocumentLoaderMac.mm in Sources */, 9398110B0824BF01008DF038 /* WebDownload.m in Sources */, @@ -1647,7 +1646,6 @@ 939810C40824BF01008DF038 /* WebKitNSStringExtras.m in Sources */, 1AAF5D0F0EDDE7A7008D883D /* WebKitPluginAgent.defs in Sources */, 1AAF5D000EDDE604008D883D /* WebKitPluginClient.defs in Sources */, - BCDFA9130C10B93E00D3A10C /* WebKitPluginContainerView.mm in Sources */, 1AAF5CF10EDDE586008D883D /* WebKitPluginHost.defs in Sources */, 939810C50824BF01008DF038 /* WebKitStatistics.m in Sources */, 9398110E0824BF01008DF038 /* WebKitSystemBits.m in Sources */, @@ -1674,7 +1672,7 @@ 1AEA66D50DC6B1FF003D12BF /* WebNetscapePluginEventHandler.mm in Sources */, 1AEA66D90DC6B209003D12BF /* WebNetscapePluginEventHandlerCarbon.mm in Sources */, 1AEA6A510DC8CE2F003D12BF /* WebNetscapePluginEventHandlerCocoa.mm in Sources */, - 939810D60824BF01008DF038 /* WebNetscapePluginPackage.m in Sources */, + 939810D60824BF01008DF038 /* WebNetscapePluginPackage.mm in Sources */, 1A4DF5230EC8C74D006BD4B4 /* WebNetscapePluginView.mm in Sources */, 1C68F670095B5FC100C2984E /* WebNodeHighlight.m in Sources */, 1C68F672095B5FC100C2984E /* WebNodeHighlightView.m in Sources */, @@ -1704,6 +1702,8 @@ 939810E80824BF01008DF038 /* WebViewFactory.mm in Sources */, 939810DD0824BF01008DF038 /* npapi.mm in Sources */, 1A2DBEA00F251E3A0036F8A6 /* ProxyInstance.mm in Sources */, + 1A74A28F0F4F75400082E228 /* WebTextInputWindowController.m in Sources */, + FEF52DFA0F6748F200FF70EE /* WebGeolocation.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1764,12 +1764,10 @@ buildSettings = { DEBUG_DEFINES = "$(DEBUG_DEFINES_debug) ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH"; INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)"; - JAVASCRIPTCORE_PRIVATE_HEADERS_DIR = "$(BUILT_PRODUCTS_DIR)/JavaScriptCore.framework/PrivateHeaders"; OTHER_LDFLAGS = ( "$(OTHER_LDFLAGS)", "-l$(WEBKIT_SYSTEM_INTERFACE_LIBRARY)", ); - UMBRELLA_FRAMEWORKS_DIR = "$(BUILT_PRODUCTS_DIR)"; }; name = Debug; }; @@ -1779,12 +1777,10 @@ buildSettings = { DEBUG_DEFINES = "$(DEBUG_DEFINES_$(CURRENT_VARIANT)) ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH"; INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)"; - JAVASCRIPTCORE_PRIVATE_HEADERS_DIR = "$(BUILT_PRODUCTS_DIR)/JavaScriptCore.framework/PrivateHeaders"; OTHER_LDFLAGS = ( "$(OTHER_LDFLAGS)", "-l$(WEBKIT_SYSTEM_INTERFACE_LIBRARY)", ); - UMBRELLA_FRAMEWORKS_DIR = "$(BUILT_PRODUCTS_DIR)"; }; name = Release; }; diff --git a/WebKit/android/RenderSkinButton.cpp b/WebKit/android/RenderSkinButton.cpp index c878cb9..0f792a7 100644 --- a/WebKit/android/RenderSkinButton.cpp +++ b/WebKit/android/RenderSkinButton.cpp @@ -90,8 +90,7 @@ void RenderSkinButton::Draw(SkCanvas* canvas, const IntRect& r, RenderSkinAndroi static_cast<unsigned>(RenderSkinAndroid::kNumStates)); // Set up the ninepatch information for drawing. - SkRect bounds; - android_setrect(&bounds, r); + SkRect bounds(r); const PatchData& pd = gFiles[newState]; int marginValue = pd.margin + pd.outset; diff --git a/WebKit/android/RenderSkinCombo.cpp b/WebKit/android/RenderSkinCombo.cpp index 902f2c0..870c13e 100644 --- a/WebKit/android/RenderSkinCombo.cpp +++ b/WebKit/android/RenderSkinCombo.cpp @@ -27,6 +27,7 @@ #include "RenderSkinCombo.h" #include "Document.h" +#include "Element.h" #include "Node.h" #include "SkCanvas.h" #include "SkNinePatch.h" @@ -58,7 +59,8 @@ bool RenderSkinCombo::Draw(SkCanvas* canvas, Node* element, int x, int y, int wi { if (!s_decoded) return true; - State state = element && element->isEnabled() ? kNormal : kDisabled; + + State state = (element->isElementNode() && static_cast<Element*>(element)->isEnabledFormControl()) ? kNormal : kDisabled; if (height < (s_margin<<1) + 1) { height = (s_margin<<1) + 1; } diff --git a/WebKit/android/RenderSkinRadio.cpp b/WebKit/android/RenderSkinRadio.cpp index 2fca175..ff5e908 100644 --- a/WebKit/android/RenderSkinRadio.cpp +++ b/WebKit/android/RenderSkinRadio.cpp @@ -28,6 +28,8 @@ #include "android_graphics.h" #include "Document.h" +#include "Element.h" +#include "InputElement.h" #include "IntRect.h" #include "Node.h" #include "RenderSkinAndroid.h" @@ -60,11 +62,12 @@ void RenderSkinRadio::Draw(SkCanvas* canvas, Node* element, const IntRect& ir, if (!s_decoded || !element) { return; } - SkRect r; - android_setrect(&r, ir); + SkRect r(ir); int saveLayerCount = 0; int saveScaleCount = 0; - if (!element->isEnabled()) { + + if (!element->isElementNode() || + !static_cast<Element*>(element)->isEnabledFormControl()) { saveLayerCount = canvas->saveLayerAlpha(&r, 0x80); } SkScalar width = r.width(); @@ -72,7 +75,12 @@ void RenderSkinRadio::Draw(SkCanvas* canvas, Node* element, const IntRect& ir, SkScalar scale = SkScalarDiv(width, SIZE); saveScaleCount = canvas->scale(scale, scale); } - canvas->drawBitmap(s_bitmap[element->isChecked() + 2*(!isCheckBox)], + bool checked = false; + if (InputElement* inputElement = toInputElement(static_cast<Element*>(element))) { + checked = inputElement->isChecked(); + } + + canvas->drawBitmap(s_bitmap[checked + 2*(!isCheckBox)], r.fLeft, r.fTop, NULL); if (saveLayerCount != 0) { canvas->restoreToCount(saveLayerCount); diff --git a/WebKit/android/TimeCounter.cpp b/WebKit/android/TimeCounter.cpp index b423441..5f69cf6 100644 --- a/WebKit/android/TimeCounter.cpp +++ b/WebKit/android/TimeCounter.cpp @@ -31,19 +31,21 @@ #include "CString.h" #include "Cache.h" #include "KURL.h" -#include "GCController.h" -#include "JSDOMWindow.h" #include "Node.h" -#include "Nodes.h" #include "SystemTime.h" #include "StyleBase.h" + +#if USE(JSC) +#include "JSDOMWindow.h" #include <runtime/JSGlobalObject.h> #include <runtime/JSLock.h> +#endif + #include <utils/Log.h> -using namespace JSC; using namespace WebCore; using namespace WTF; +using namespace JSC; namespace android { @@ -66,7 +68,9 @@ uint32_t TimeCounter::sStartTime[TimeCounter::TotalTimeCounterCount]; static const char* timeCounterNames[] = { "css parsing", "javascript", + "javascript init", "javascript parsing", + "javascript execution", "calculate style", "Java callback (frame bridge)", "parsing (may include calcStyle or Java callback)", @@ -113,11 +117,12 @@ void TimeCounter::report(const KURL& url, int live, int dead, size_t arenaSize) } LOGD("Current cache has %d bytes live and %d bytes dead", live, dead); LOGD("Current render arena takes %d bytes", arenaSize); +#if USE(JSC) JSLock lock(false); Heap::Statistics jsHeapStatistics = JSDOMWindow::commonJSGlobalData()->heap.statistics(); LOGD("Current JavaScript heap size is %d and has %d bytes free", jsHeapStatistics.size, jsHeapStatistics.free); - LOGD("Current JavaScript nodes use %d bytes", JSC::Node::reportJavaScriptNodesSize()); +#endif LOGD("Current CSS styles use %d bytes", StyleBase::reportStyleSize()); LOGD("Current DOM nodes use %d bytes", WebCore::Node::reportDOMNodesSize()); } diff --git a/WebKit/android/TimeCounter.h b/WebKit/android/TimeCounter.h index 054141b..c78d10f 100644 --- a/WebKit/android/TimeCounter.h +++ b/WebKit/android/TimeCounter.h @@ -44,7 +44,9 @@ public: // function base counters CSSParseTimeCounter, JavaScriptTimeCounter, + JavaScriptInitTimeCounter, JavaScriptParseTimeCounter, + JavaScriptExecuteTimeCounter, CalculateStyleTimeCounter, JavaCallbackTimeCounter, ParsingTimeCounter, diff --git a/WebKit/android/TimerClient.h b/WebKit/android/TimerClient.h index 09f9fc0..f8cbb9d 100644 --- a/WebKit/android/TimerClient.h +++ b/WebKit/android/TimerClient.h @@ -35,6 +35,7 @@ namespace android { virtual void setSharedTimerCallback(void(*f)()) = 0; virtual void setSharedTimer(long long timemillis) = 0; virtual void stopSharedTimer() = 0; + virtual void signalServiceFuncPtrQueue() = 0; }; } diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp index 7b09975..71d9f59 100644 --- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp +++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp @@ -29,6 +29,7 @@ #include "ChromeClientAndroid.h" #include "CString.h" +#include "DatabaseTracker.h" #include "Document.h" #include "PlatformString.h" #include "FloatRect.h" @@ -142,10 +143,10 @@ bool ChromeClientAndroid::menubarVisible() { notImplemented(); return false; } void ChromeClientAndroid::setResizable(bool) { notImplemented(); } // This function is called by the JavaScript bindings to print usually an error to -// a message console. -void ChromeClientAndroid::addMessageToConsole(const String& message, unsigned int lineNumber, const String& sourceID) { - notImplemented(); - LOGD("Console: %s line: %d source: %s\n", message.latin1().data(), lineNumber, sourceID.latin1().data()); +// a message console. Pass the message to the java side so that the client can +// handle it as it sees fit. +void ChromeClientAndroid::addMessageToConsole(MessageSource, MessageLevel, const String& message, unsigned int lineNumber, const String& sourceID) { + android::WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view())->addMessageToConsole(message, lineNumber, sourceID); } bool ChromeClientAndroid::canRunBeforeUnloadConfirmPanel() { return true; } @@ -167,7 +168,7 @@ void ChromeClientAndroid::closeWindowSoon() mainFrame->loader()->stopAllLoaders(); // Remove all event listeners so that no javascript can execute as a result // of mouse/keyboard events. - mainFrame->document()->removeAllEventListenersFromAllNodes(); + mainFrame->document()->removeAllEventListeners(); // Close the window. m_webFrame->closeWindow(android::WebViewCore::getWebViewCore(mainFrame->view())); } @@ -248,13 +249,16 @@ PlatformWidget ChromeClientAndroid::platformWindow() const { return viewBridge; } -// new to webkit4 (Feb 27, 2009) void ChromeClientAndroid::contentsSizeChanged(Frame*, const IntSize&) const { notImplemented(); } -// new to webkit4 (Feb 27, 2009) +void ChromeClientAndroid::scrollRectIntoView(const IntRect&, const ScrollView*) const +{ + notImplemented(); +} + void ChromeClientAndroid::formStateDidChange(const Node*) { notImplemented(); @@ -264,9 +268,69 @@ void ChromeClientAndroid::mouseDidMoveOverElement(const HitTestResult&, unsigned void ChromeClientAndroid::setToolTip(const String&) {} void ChromeClientAndroid::print(Frame*) {} -void ChromeClientAndroid::exceededDatabaseQuota(Frame*, const String&) {} +/* + * This function is called on the main (webcore) thread by SQLTransaction::deliverQuotaIncreaseCallback. + * The way that the callback mechanism is designed inside SQLTransaction means that there must be a new quota + * (which may be equal to the old quota if the user did not allow more quota) when this function returns. As + * we call into the browser thread to ask what to do with the quota, we block here and get woken up when the + * browser calls the native WebViewCore::SetDatabaseQuota method with the new quota value. + */ +#if ENABLE(DATABASE) +void ChromeClientAndroid::exceededDatabaseQuota(Frame* frame, const String& name) +{ + SecurityOrigin* origin = frame->document()->securityOrigin(); + + // TODO: This default quota value should be pulled from the web browser + // settings. For now, settle for 5 meg. + const unsigned long long defaultQuota = 1024 * 1024 * 5; + + + if (WebCore::DatabaseTracker::tracker().hasEntryForOrigin(origin)) { + // We want to wait on a new quota from the UI thread. Reset the m_newQuota variable to represent we haven't received a new quota. + m_newQuota = -1; + + // This origin is being tracked and has exceeded it's quota. Call into + // the Java side of things to inform the user. + const unsigned long long currentQuota = WebCore::DatabaseTracker::tracker().quotaForOrigin(origin); + android::WebViewCore::getWebViewCore(frame->view())->exceededDatabaseQuota(frame->document()->documentURI(), name, currentQuota); + + // We've sent notification to the browser so now wait for it to come back. + m_quotaThreadLock.lock(); + while (m_newQuota == -1) { + m_quotaThreadCondition.wait(m_quotaThreadLock); + } + m_quotaThreadLock.unlock(); + + // Update the DatabaseTracker with the new quota value (if the user declined + // new quota, this may equal the old quota) + DatabaseTracker::tracker().setQuota(origin, m_newQuota); + } else { + // This origin is not being tracked, so set it's entry in the Origins table + // to the default quota, casusing it to be tracked from now on. + DatabaseTracker::tracker().setQuota(origin, defaultQuota); + } +} +#endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +void ChromeClientAndroid::reachedMaxAppCacheSize(int64_t spaceNeeded) +{ + // FIXME: Free some space. + notImplemented(); +} +#endif -// new to change 38068 (Nov 6, 2008) +void ChromeClientAndroid::requestGeolocationPermissionForFrame(Frame*, Geolocation*) { notImplemented(); } void ChromeClientAndroid::runOpenPanel(Frame*, PassRefPtr<FileChooser>) { notImplemented(); } +bool ChromeClientAndroid::setCursor(PlatformCursorHandle) +{ + notImplemented(); + return false; +} + +void ChromeClientAndroid::wakeUpMainThreadWithNewQuota(long newQuota) { + MutexLocker locker(m_quotaThreadLock); + m_newQuota = newQuota; + m_quotaThreadCondition.signal(); +} } diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h index 7343c88..93426b8 100644 --- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h +++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h @@ -28,6 +28,8 @@ #include "ChromeClient.h" +#include "Threading.h" + using namespace WebCore; namespace android { @@ -75,7 +77,7 @@ namespace android { virtual void setResizable(bool); - virtual void addMessageToConsole(const String& message, unsigned int lineNumber, const String& sourceID); + virtual void addMessageToConsole(MessageSource, MessageLevel, const String& message, unsigned int lineNumber, const String& sourceID); virtual bool canRunBeforeUnloadConfirmPanel(); virtual bool runBeforeUnloadConfirmPanel(const String& message, Frame* frame); @@ -98,6 +100,7 @@ namespace android { virtual IntRect windowToScreen(const IntRect&) const; virtual PlatformWidget platformWindow() const; virtual void contentsSizeChanged(Frame*, const IntSize&) const; + virtual void scrollRectIntoView(const IntRect&, const ScrollView*) const; // End methods used by HostWindow. virtual void mouseDidMoveOverElement(const HitTestResult&, unsigned int); @@ -105,19 +108,30 @@ namespace android { virtual void setToolTip(const String&); virtual void print(Frame*); - +#if ENABLE(DATABASE) virtual void exceededDatabaseQuota(Frame*, const String&); - +#endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); +#endif + virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*); virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>); + virtual bool setCursor(PlatformCursorHandle); // Notification that the given form element has changed. This function // will be called frequently, so handling should be very fast. virtual void formStateDidChange(const Node*); - // Android-specific + virtual PassOwnPtr<HTMLParserQuirks> createHTMLParserQuirks() { return 0; } + + // Android-specific void setWebFrame(android::WebFrame* webframe); + void wakeUpMainThreadWithNewQuota(long newQuota); private: android::WebFrame* m_webFrame; + WTF::ThreadCondition m_quotaThreadCondition; + WTF::Mutex m_quotaThreadLock; + long m_newQuota; }; } diff --git a/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp b/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp index 780ea53..4918ee9 100644 --- a/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp +++ b/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp @@ -215,10 +215,11 @@ void EditorClientAndroid::redo() {} // functions new to Jun-07 tip of tree merge: void EditorClientAndroid::showSpellingUI(bool) {} -void EditorClientAndroid::getGuessesForWord(String const&, Vector<String>&) {} +void EditorClientAndroid::getGuessesForWord(String const&, WTF::Vector<String>&) {} bool EditorClientAndroid::spellingUIIsShowing() { return false; } -void EditorClientAndroid::checkGrammarOfString(unsigned short const*, int, Vector<GrammarDetail>&, int*, int*) {} +void EditorClientAndroid::checkGrammarOfString(unsigned short const*, int, WTF::Vector<GrammarDetail>&, int*, int*) {} void EditorClientAndroid::checkSpellingOfString(unsigned short const*, int, int*, int*) {} +String EditorClientAndroid::getAutoCorrectSuggestionForMisspelledWord(const String&) { return String(); } void EditorClientAndroid::textFieldDidEndEditing(Element*) {} void EditorClientAndroid::textDidChangeInTextArea(Element*) {} void EditorClientAndroid::textDidChangeInTextField(Element*) {} diff --git a/WebKit/android/WebCoreSupport/EditorClientAndroid.h b/WebKit/android/WebCoreSupport/EditorClientAndroid.h index 42e9c43..9697d66 100644 --- a/WebKit/android/WebCoreSupport/EditorClientAndroid.h +++ b/WebKit/android/WebCoreSupport/EditorClientAndroid.h @@ -94,12 +94,13 @@ public: virtual void ignoreWordInSpellDocument(const String&); virtual void learnWord(const String&); virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength); - virtual void checkGrammarOfString(const UChar*, int length, Vector<GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength); + virtual String getAutoCorrectSuggestionForMisspelledWord(const String& misspelledWorld); + virtual void checkGrammarOfString(const UChar*, int length, WTF::Vector<GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength); virtual void updateSpellingUIWithGrammarString(const String&, const GrammarDetail& detail); virtual void updateSpellingUIWithMisspelledWord(const String&); virtual void showSpellingUI(bool show); virtual bool spellingUIIsShowing(); - virtual void getGuessesForWord(const String&, Vector<String>& guesses); + virtual void getGuessesForWord(const String&, WTF::Vector<String>& guesses); virtual void setInputMethodState(bool); // Android specific: diff --git a/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp index 5a07278..b81e5f3 100644 --- a/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp +++ b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp @@ -29,14 +29,14 @@ #include "android_graphics.h" #include "CString.h" #include "DocumentLoader.h" +#include "DOMImplementation.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameLoaderClientAndroid.h" #include "FrameTree.h" #include "GraphicsContext.h" -// HTMLFormElement needed for a bad include -#include "HTMLFormElement.h" #include "HTMLFrameOwnerElement.h" +#include "HTMLPlugInElement.h" #include "IconDatabase.h" #include "MIMETypeRegistry.h" #include "NotImplemented.h" @@ -45,11 +45,6 @@ #include "PlatformString.h" #include "PluginDatabase.h" #include "PluginView.h" -#ifdef ANDROID_PLUGINS -// Removed. -#else -#include "PluginViewBridgeAndroid.h" -#endif #include "ProgressTracker.h" #include "RenderPart.h" #include "ResourceError.h" @@ -110,7 +105,7 @@ void FrameLoaderClientAndroid::makeRepresentation(DocumentLoader*) { void FrameLoaderClientAndroid::forceLayout() { ASSERT(m_frame); - m_frame->forceLayout(); + m_frame->view()->forceLayout(); // FIXME, should we adjust view size here? m_frame->view()->adjustViewSize(); } @@ -190,6 +185,10 @@ bool FrameLoaderClientAndroid::dispatchDidLoadResourceFromMemoryCache(DocumentLo return false; } +void FrameLoaderClientAndroid::dispatchDidLoadResourceByXMLHttpRequest(unsigned long identifier, const ScriptString&) { + return; +} + void FrameLoaderClientAndroid::dispatchDidHandleOnloadEvents() { } @@ -225,10 +224,12 @@ void FrameLoaderClientAndroid::dispatchDidReceiveIcon() { WebCore::Image* icon = WebCore::iconDatabase()->iconForPageURL( url, WebCore::IntSize(16, 16)); // If the request fails, try the original request url. - if (!icon) + if (!icon) { + DocumentLoader* docLoader = m_frame->loader()->activeDocumentLoader(); + KURL originalURL = docLoader->originalRequest().url(); icon = WebCore::iconDatabase()->iconForPageURL( - m_frame->loader()->originalRequestURL().string(), - WebCore::IntSize(16, 16)); + originalURL, WebCore::IntSize(16, 16)); + } // There is a bug in webkit where cancelling an icon load is treated as a // failure. When this is fixed, we can ASSERT again that we have an icon. if (icon) { @@ -256,8 +257,7 @@ void FrameLoaderClientAndroid::dispatchDidReceiveTitle(const String& title) { } void FrameLoaderClientAndroid::dispatchDidCommitLoad() { - ASSERT(m_frame); - WebViewCore::getWebViewCore(m_frame->view())->updateFrameGeneration(m_frame); + verifiedOk(); } static void loadDataIntoFrame(Frame* frame, KURL baseUrl, const String& url, @@ -568,17 +568,21 @@ void FrameLoaderClientAndroid::finishedLoading(DocumentLoader* docLoader) { void FrameLoaderClientAndroid::updateGlobalHistory() { ASSERT(m_frame); - ASSERT(m_frame->loader()->documentLoader()); - KURL url; - DocumentLoader* loader = m_frame->loader()->documentLoader(); - if (loader->urlForHistoryReflectsServerRedirect()) - url = loader->url(); - else - url = loader->urlForHistory(); - m_webFrame->updateVisitedHistory(url, false); + + DocumentLoader* docLoader = m_frame->loader()->documentLoader(); + ASSERT(docLoader); + + // Code copied from FrameLoader.cpp:createHistoryItem + // Only add this URL to the database if it is a valid page + if (docLoader->unreachableURL().isEmpty() + && docLoader->response().httpStatusCode() < 400) { + m_webFrame->updateVisitedHistory(docLoader->urlForHistory(), false); + if (!docLoader->serverRedirectSourceForHistory().isNull()) + m_webFrame->updateVisitedHistory(KURL(docLoader->serverRedirectDestinationForHistory()), false); + } } -void FrameLoaderClientAndroid::updateGlobalHistoryForRedirectWithoutHistoryItem() { +void FrameLoaderClientAndroid::updateGlobalHistoryRedirectLinks() { // Note, do we need to do anything where there is no HistoryItem? If we call // updateGlobalHistory(), we will add bunch of "data:xxx" urls for gmail.com // which is not what we want. Opt to do nothing now. @@ -653,7 +657,9 @@ bool FrameLoaderClientAndroid::canShowMIMEType(const String& mimeType) const { if (MIMETypeRegistry::isSupportedImageResourceMIMEType(mimeType) || MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType) || MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType) || - PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType)) + PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType) || + DOMImplementation::isTextMIMEType(mimeType) || + DOMImplementation::isXMLMIMEType(mimeType)) return true; return false; } @@ -674,7 +680,6 @@ String FrameLoaderClientAndroid::generatedMIMETypeForURLScheme(const String& URL void FrameLoaderClientAndroid::frameLoadCompleted() { // copied from Apple port, without this back with sub-frame will trigger ASSERT ASSERT(m_frame); - m_frame->loader()->setPreviousHistoryItem(0); } void FrameLoaderClientAndroid::saveViewStateToItem(HistoryItem* item) { @@ -687,7 +692,8 @@ void FrameLoaderClientAndroid::saveViewStateToItem(HistoryItem* item) { ASSERT(bridge); // store the current scale (only) for the top frame if (!m_frame->tree()->parent()) { - bridge->setScale(WebViewCore::getWebViewCore(m_frame->view())->scale()); + float scale = WebViewCore::getWebViewCore(m_frame->view())->scale(); + bridge->setScale((int)(scale * 100)); } WebCore::notifyHistoryItemChanged(item); @@ -735,8 +741,7 @@ void FrameLoaderClientAndroid::didFinishLoad() { } void FrameLoaderClientAndroid::prepareForDataSourceReplacement() { - ASSERT(m_frame); - m_frame->loader()->detachChildren(); + verifiedOk(); } PassRefPtr<DocumentLoader> FrameLoaderClientAndroid::createDocumentLoader( @@ -786,19 +791,16 @@ void FrameLoaderClientAndroid::transitionToCommittedForNewPage() { m_frame->setView(NULL); // Create a new FrameView and associate it with the saved webFrameView - FrameView* view = new FrameView(m_frame); - webFrameView->setView(view); + RefPtr<FrameView> view = FrameView::create(m_frame); + webFrameView->setView(view.get()); Release(webFrameView); // Give the new FrameView to the Frame m_frame->setView(view); - // Deref since FrameViews are created with a ref of 1 - view->deref(); - if (m_frame->ownerRenderer()) - m_frame->ownerRenderer()->setWidget(view); + m_frame->ownerRenderer()->setWidget(view.get()); m_frame->view()->initScrollbars(); @@ -830,15 +832,13 @@ WTF::PassRefPtr<WebCore::Frame> FrameLoaderClientAndroid::createFrame(const KURL parent->tree()->appendChild(newFrame); newFrame->tree()->setName(name); // Create a new FrameView and WebFrameView for the child frame to draw into. - FrameView* frameView = new WebCore::FrameView(newFrame); - WebFrameView* webFrameView = new WebFrameView(frameView, + RefPtr<FrameView> frameView = FrameView::create(newFrame); + WebFrameView* webFrameView = new WebFrameView(frameView.get(), WebViewCore::getWebViewCore(parent->view())); // frameView Retains webFrameView, so call Release for webFrameView Release(webFrameView); // Attach the frameView to the newFrame. newFrame->setView(frameView); - // setView() refs the frameView so call deref on the frameView - frameView->deref(); newFrame->init(); newFrame->selection()->setFocused(true); LOGV("::WebCore:: createSubFrame returning %p", newFrame); @@ -894,7 +894,7 @@ static bool isYouTubeUrl(const KURL& url, const String& mimeType) Widget* FrameLoaderClientAndroid::createPlugin( const IntSize& size, - Element* element, + HTMLPlugInElement* element, const KURL& url, const WTF::Vector<String, 0u>& names, const WTF::Vector<String, 0u>& values, @@ -902,8 +902,7 @@ Widget* FrameLoaderClientAndroid::createPlugin( bool loadManually) { // Create an iframe for youtube urls. if (isYouTubeUrl(url, mimeType)) { - RefPtr<Frame> frame = createFrame(blankURL(), String(), - static_cast<HTMLFrameOwnerElement*>(element), + RefPtr<Frame> frame = createFrame(blankURL(), String(), element, String(), false, 0, 0); if (frame) { // grab everything after /v/ @@ -949,7 +948,7 @@ void FrameLoaderClientAndroid::redirectDataToPlugin(Widget* pluginWidget) { notImplemented(); } -Widget* FrameLoaderClientAndroid::createJavaAppletWidget(const IntSize&, Element*, +Widget* FrameLoaderClientAndroid::createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL& baseURL, const WTF::Vector<String>& paramNames, const WTF::Vector<String>& paramValues) { // don't support widget yet @@ -979,17 +978,17 @@ ObjectContentType FrameLoaderClientAndroid::objectContentType(const KURL& url, } return ObjectContentFrame; } - if (equalIgnoringCase(mimeType, "text/html") || - equalIgnoringCase(mimeType, "text/xml") || - equalIgnoringCase(mimeType, "text/") || - equalIgnoringCase(mimeType, "application/xml") || - equalIgnoringCase(mimeType, "application/xhtml+xml") || - equalIgnoringCase(mimeType, "application/x-javascript")) - return ObjectContentFrame; + if (Image::supportsType(mimeType)) return ObjectContentImage; - // Use OtherPlugin so embed and object tags draw the null plugin view - return ObjectContentOtherPlugin; + + if (PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType)) + return ObjectContentOtherPlugin; + + if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType)) + return ObjectContentFrame; + + return ObjectContentNone; } // This function allows the application to set the correct CSS media @@ -1009,6 +1008,9 @@ void FrameLoaderClientAndroid::windowObjectCleared() { m_webFrame->windowObjectCleared(m_frame); } +void FrameLoaderClientAndroid::documentElementAvailable() { +} + // functions new to Jun-07 tip of tree merge: ResourceError FrameLoaderClientAndroid::blockedError(ResourceRequest const& request) { return ResourceError(String(), InternalErrorFileDoesNotExist, String(), String()); diff --git a/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h index 9d71c9d..d491750 100644 --- a/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h +++ b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h @@ -71,6 +71,7 @@ namespace android { virtual void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier); virtual void dispatchDidFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError&); virtual bool dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length); + virtual void dispatchDidLoadResourceByXMLHttpRequest(unsigned long identifier, const ScriptString&); virtual void dispatchDidHandleOnloadEvents(); virtual void dispatchDidReceiveServerRedirectForProvisionalLoad(); @@ -122,7 +123,7 @@ namespace android { virtual void finishedLoading(DocumentLoader*); virtual void updateGlobalHistory(); - virtual void updateGlobalHistoryForRedirectWithoutHistoryItem(); + virtual void updateGlobalHistoryRedirectLinks(); virtual bool shouldGoToHistoryItem(HistoryItem*) const; #ifdef ANDROID_HISTORY_CLIENT @@ -168,17 +169,18 @@ namespace android { virtual WTF::PassRefPtr<Frame> createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight); - virtual Widget* createPlugin(const IntSize&, Element*, const KURL&, + virtual Widget* createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const WTF::Vector<WebCore::String, 0u>&, const WTF::Vector<String, 0u>&, const String&, bool); virtual void redirectDataToPlugin(Widget* pluginWidget); - virtual Widget* createJavaAppletWidget(const IntSize&, Element*, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues); + virtual Widget* createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL& baseURL, const WTF::Vector<String>& paramNames, const WTF::Vector<String>& paramValues); virtual ObjectContentType objectContentType(const KURL& url, const String& mimeType); virtual String overrideMediaType() const; virtual void windowObjectCleared(); + virtual void documentElementAvailable(); virtual void didPerformFirstNavigation() const; virtual void registerForIconNotification(bool listen = true); diff --git a/WebKit/android/WebCoreSupport/InspectorClientAndroid.h b/WebKit/android/WebCoreSupport/InspectorClientAndroid.h index 9eb85e5..2fb3d2a 100644 --- a/WebKit/android/WebCoreSupport/InspectorClientAndroid.h +++ b/WebKit/android/WebCoreSupport/InspectorClientAndroid.h @@ -57,6 +57,7 @@ public: virtual void populateSetting(const String&, InspectorController::Setting&) {} virtual void storeSetting(const String&, const InspectorController::Setting&) {} virtual void removeSetting(const String&) {} + virtual String hiddenPanels() { return String(); } }; } diff --git a/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp b/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp new file mode 100644 index 0000000..2465e29 --- /dev/null +++ b/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp @@ -0,0 +1,285 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(VIDEO) + +#include "MediaPlayerPrivateAndroid.h" +#include "WebCoreJni.h" +#include "WebViewCore.h" +#include "jni_utility.h" + +#include <JNIHelp.h> +using namespace android; + +namespace WebCore { + +static const char* g_ProxyJavaClass = "android/webkit/HTML5VideoViewProxy"; + +struct MediaPlayerPrivate::JavaGlue +{ + jobject m_javaProxy; + jmethodID m_getInstance; + jmethodID m_play; + jmethodID m_createView; + jmethodID m_attachView; + jmethodID m_removeView; +}; + +MediaPlayerPrivate::~MediaPlayerPrivate() +{ + if (m_glue->m_javaProxy) { + JNIEnv* env = JSC::Bindings::getJNIEnv(); + if (env) { + env->CallVoidMethod(m_glue->m_javaProxy, m_glue->m_removeView); + env->DeleteGlobalRef(m_glue->m_javaProxy); + } + } + + delete m_glue; +} + +void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar) +{ + registrar(create, getSupportedTypes, supportsType); +} + +void MediaPlayerPrivate::load(const String& url) +{ + // To be able to create our java player, we need a Context object. To get + // the Context object, we need a WebViewCore java object. To get a java + // WebViewCore object, we need a WebCore::FrameView pointer. To get + // the FrameView pointer, the MediaPlayer::setFrameView() must have been + // called. However, that method is called only after the MediaPlayerClient + // is called back and informed that enough data has been loaded. + // We therefore need to fake a readyStateChanged callback before creating + // the java player. + m_player->readyStateChanged(); + // We now have a RenderVideo created and the MediaPlayer must have + // been updated with a FrameView. Create our JavaPlayer. + createJavaPlayerIfNeeded(); + // Save the URl. + m_url = url; +} + +void MediaPlayerPrivate::cancelLoad() +{ +} + +void MediaPlayerPrivate::play() +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + if (!env || !m_glue->m_javaProxy || !m_url.length()) + return; + + FrameView* frameView = m_player->frameView(); + if (!frameView) + return; + + WebViewCore* webViewCore = WebViewCore::getWebViewCore(frameView); + ASSERT(webViewCore); + jstring jUrl = env->NewString((unsigned short *)m_url.characters(), m_url.length()); + env->CallVoidMethod(m_glue->m_javaProxy, m_glue->m_play, jUrl); + env->DeleteLocalRef(jUrl); + checkException(env); +} + +void MediaPlayerPrivate::pause() +{ +} + +IntSize MediaPlayerPrivate::naturalSize() const +{ + return IntSize(300, 150); +} + +bool MediaPlayerPrivate::hasVideo() const +{ + return false; +} + +void MediaPlayerPrivate::setVisible(bool) +{ +} + +float MediaPlayerPrivate::duration() const +{ + return 100; +} + +float MediaPlayerPrivate::currentTime() const +{ + return 0; +} + +void MediaPlayerPrivate::seek(float time) +{ +} + +bool MediaPlayerPrivate::seeking() const +{ + return false; +} + +void MediaPlayerPrivate::setEndTime(float time) +{ +} + +void MediaPlayerPrivate::setRate(float) +{ +} + +bool MediaPlayerPrivate::paused() const +{ + return true; +} + +void MediaPlayerPrivate::setVolume(float) +{ +} + +MediaPlayer::NetworkState MediaPlayerPrivate::networkState() const +{ + return MediaPlayer::Loaded; +} + +MediaPlayer::ReadyState MediaPlayerPrivate::readyState() const +{ + return MediaPlayer::HaveEnoughData; +} + +float MediaPlayerPrivate::maxTimeSeekable() const +{ + return 0; +} + +float MediaPlayerPrivate::maxTimeBuffered() const +{ + return 0; +} + +int MediaPlayerPrivate::dataRate() const +{ + return 0; +} + +unsigned MediaPlayerPrivate::totalBytes() const +{ + return 0; +} + +unsigned MediaPlayerPrivate::bytesLoaded() const +{ + return 0; +} + +void MediaPlayerPrivate::setSize(const IntSize&) +{ +} + +void MediaPlayerPrivate::paint(GraphicsContext*, const IntRect& r) +{ + createJavaPlayerIfNeeded(); + JNIEnv* env = JSC::Bindings::getJNIEnv(); + if (!env) + return; + + IntSize size = m_player->size(); + env->CallVoidMethod(m_glue->m_javaProxy, m_glue->m_attachView, + r.x(), r.y(), size.width(), size.height()); +} + +MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player) +{ + return new MediaPlayerPrivate(player); +} + +void MediaPlayerPrivate::getSupportedTypes(HashSet<String>&) +{ +} + +MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs) +{ + return MediaPlayer::IsNotSupported; +} + +MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) : m_player(player), m_glue(NULL) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + if (!env) + return; + + jclass clazz = env->FindClass(g_ProxyJavaClass); + if (!clazz) + return; + + m_glue = new JavaGlue; + m_glue->m_getInstance = env->GetStaticMethodID(clazz, "getInstance", "(Landroid/webkit/WebViewCore;)Landroid/webkit/HTML5VideoViewProxy;"); + m_glue->m_play = env->GetMethodID(clazz, "play", "(Ljava/lang/String;)V"); + m_glue->m_createView = env->GetMethodID(clazz, "createView", "()V"); + m_glue->m_attachView = env->GetMethodID(clazz, "attachView", "(IIII)V"); + m_glue->m_removeView = env->GetMethodID(clazz, "removeView", "()V"); + m_glue->m_javaProxy = NULL; + env->DeleteLocalRef(clazz); + // An exception is raised if any of the above fails. + checkException(env); +} + +void MediaPlayerPrivate::createJavaPlayerIfNeeded() +{ + // Check if we have been already created. + if (m_glue->m_javaProxy) + return; + + FrameView* frameView = m_player->frameView(); + if (!frameView) + return; + + JNIEnv* env = JSC::Bindings::getJNIEnv(); + if (!env) + return; + + jclass clazz = env->FindClass(g_ProxyJavaClass); + if (!clazz) + return; + + WebViewCore* webViewCore = WebViewCore::getWebViewCore(frameView); + ASSERT(webViewCore); + + // Get the HTML5VideoViewProxy instance + jobject obj = env->CallStaticObjectMethod(clazz, m_glue->m_getInstance, webViewCore->getJavaObject().get()); + m_glue->m_javaProxy = env->NewGlobalRef(obj); + // Create our VideoView object. + env->CallVoidMethod(obj, m_glue->m_createView); + // Clean up. + env->DeleteLocalRef(obj); + env->DeleteLocalRef(clazz); + checkException(env); +} + +} + +#endif // VIDEO diff --git a/WebKit/android/jni/JavaBridge.cpp b/WebKit/android/jni/JavaBridge.cpp index d0f7f0e..7c4636f 100644 --- a/WebKit/android/jni/JavaBridge.cpp +++ b/WebKit/android/jni/JavaBridge.cpp @@ -34,6 +34,9 @@ #include "KeyGeneratorClient.h" #include "KURL.h" #include "NetworkStateNotifier.h" +#include "Page.h" +#include "PluginClient.h" +#include "PluginDatabase.h" #include "Timer.h" #include "TimerClient.h" #include "jni_utility.h" @@ -56,7 +59,7 @@ static jfieldID gJavaBridge_ObjectID; // ---------------------------------------------------------------------------- -class JavaBridge : public TimerClient, public CookieClient, public KeyGeneratorClient +class JavaBridge : public TimerClient, public CookieClient, public PluginClient, public KeyGeneratorClient { public: JavaBridge(JNIEnv* env, jobject obj); @@ -68,10 +71,12 @@ public: virtual void setSharedTimer(long long timemillis); virtual void stopSharedTimer(); - virtual void setCookies(WebCore::KURL const& url, WebCore::KURL const& docURL, WebCore::String const& value); + virtual void setCookies(WebCore::KURL const& url, WebCore::String const& value); virtual WebCore::String cookies(WebCore::KURL const& url); virtual bool cookiesEnabled(); + virtual WTF::Vector<WebCore::String> getPluginDirectories(); + virtual WTF::Vector<String> getSupportedKeyStrengthList(); virtual WebCore::String getSignedPublicKeyAndChallengeString(unsigned index, const WebCore::String& challenge, const WebCore::KURL& url); @@ -82,7 +87,7 @@ public: //////////////////////////////////////////// - void signalServiceFuncPtrQueue(); + virtual void signalServiceFuncPtrQueue(); // jni functions static void Constructor(JNIEnv* env, jobject obj); @@ -92,6 +97,7 @@ public: static void SetNetworkOnLine(JNIEnv* env, jobject obj, jboolean online); static void SetDeferringTimers(JNIEnv* env, jobject obj, jboolean defer); static void ServiceFuncPtrQueue(JNIEnv*); + static void UpdatePluginDirectories(JNIEnv* env, jobject obj, jobjectArray array, jboolean reload); private: jobject mJavaObject; @@ -100,13 +106,13 @@ private: jmethodID mSetCookies; jmethodID mCookies; jmethodID mCookiesEnabled; + jmethodID mGetPluginDirectories; jmethodID mSignalFuncPtrQueue; jmethodID mGetKeyStrengthList; jmethodID mGetSignedPublicKey; }; static void (*sSharedTimerFiredCallback)(); -static JavaBridge* gJavaBridge; JavaBridge::JavaBridge(JNIEnv* env, jobject obj) { @@ -115,9 +121,10 @@ JavaBridge::JavaBridge(JNIEnv* env, jobject obj) mSetSharedTimer = env->GetMethodID(clazz, "setSharedTimer", "(J)V"); mStopSharedTimer = env->GetMethodID(clazz, "stopSharedTimer", "()V"); - mSetCookies = env->GetMethodID(clazz, "setCookies", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + mSetCookies = env->GetMethodID(clazz, "setCookies", "(Ljava/lang/String;Ljava/lang/String;)V"); mCookies = env->GetMethodID(clazz, "cookies", "(Ljava/lang/String;)Ljava/lang/String;"); mCookiesEnabled = env->GetMethodID(clazz, "cookiesEnabled", "()Z"); + mGetPluginDirectories = env->GetMethodID(clazz, "getPluginDirectories", "()[Ljava/lang/String;"); mSignalFuncPtrQueue = env->GetMethodID(clazz, "signalServiceFuncPtrQueue", "()V"); mGetKeyStrengthList = env->GetMethodID(clazz, "getKeyStrengthList", "()[Ljava/lang/String;"); mGetSignedPublicKey = env->GetMethodID(clazz, "getSignedPublicKey", "(ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); @@ -132,10 +139,10 @@ JavaBridge::JavaBridge(JNIEnv* env, jobject obj) JavaSharedClient::SetTimerClient(this); JavaSharedClient::SetCookieClient(this); + JavaSharedClient::SetPluginClient(this); JavaSharedClient::SetKeyGeneratorClient(this); - gJavaBridge = this; -} - +} + JavaBridge::~JavaBridge() { if (mJavaObject) { @@ -146,6 +153,7 @@ JavaBridge::~JavaBridge() JavaSharedClient::SetTimerClient(NULL); JavaSharedClient::SetCookieClient(NULL); + JavaSharedClient::SetPluginClient(NULL); JavaSharedClient::SetKeyGeneratorClient(NULL); } @@ -166,19 +174,16 @@ JavaBridge::stopSharedTimer() } void -JavaBridge::setCookies(WebCore::KURL const& url, WebCore::KURL const& docUrl, WebCore::String const& value) +JavaBridge::setCookies(WebCore::KURL const& url, WebCore::String const& value) { JNIEnv* env = JSC::Bindings::getJNIEnv(); const WebCore::String& urlStr = url.string(); jstring jUrlStr = env->NewString(urlStr.characters(), urlStr.length()); - const WebCore::String& docUrlStr = docUrl.string(); - jstring jDocUrlStr = env->NewString(docUrlStr.characters(), docUrlStr.length()); jstring jValueStr = env->NewString(value.characters(), value.length()); AutoJObject obj = getRealObject(env, mJavaObject); - env->CallVoidMethod(obj.get(), mSetCookies, jUrlStr, jDocUrlStr, jValueStr); + env->CallVoidMethod(obj.get(), mSetCookies, jUrlStr, jValueStr); env->DeleteLocalRef(jUrlStr); - env->DeleteLocalRef(jDocUrlStr); env->DeleteLocalRef(jValueStr); } @@ -207,6 +212,25 @@ JavaBridge::cookiesEnabled() return (ret != 0); } +WTF::Vector<WebCore::String> +JavaBridge::getPluginDirectories() +{ + WTF::Vector<WebCore::String> directories; + JNIEnv* env = JSC::Bindings::getJNIEnv(); + AutoJObject obj = getRealObject(env, mJavaObject); + jobjectArray array = (jobjectArray) + env->CallObjectMethod(obj.get(), mGetPluginDirectories); + int count = env->GetArrayLength(array); + for (int i = 0; i < count; i++) { + jstring dir = (jstring) env->GetObjectArrayElement(array, i); + directories.append(to_string(env, dir)); + env->DeleteLocalRef(dir); + } + env->DeleteLocalRef(array); + checkException(env); + return directories; +} + void JavaBridge::setSharedTimerCallback(void (*f)()) { @@ -262,14 +286,6 @@ WebCore::String JavaBridge::getSignedPublicKeyAndChallengeString(unsigned index, // ---------------------------------------------------------------------------- -// visible to Shared -void AndroidSignalServiceFuncPtrQueue() -{ - gJavaBridge->signalServiceFuncPtrQueue(); -} - -// ---------------------------------------------------------------------------- - void JavaBridge::Constructor(JNIEnv* env, jobject obj) { JavaBridge* javaBridge = new JavaBridge(env, obj); @@ -312,16 +328,28 @@ void JavaBridge::SetNetworkOnLine(JNIEnv* env, jobject obj, jboolean online) WebCore::networkStateNotifier().networkStateChange(online); } -void JavaBridge::SetDeferringTimers(JNIEnv* env, jobject obj, jboolean defer) -{ - WebCore::setDeferringTimers(defer); -} - void JavaBridge::ServiceFuncPtrQueue(JNIEnv*) { JavaSharedClient::ServiceFunctionPtrQueue(); } +void JavaBridge::UpdatePluginDirectories(JNIEnv* env, jobject obj, + jobjectArray array, jboolean reload) { + WTF::Vector<WebCore::String> directories; + int count = env->GetArrayLength(array); + for (int i = 0; i < count; i++) { + jstring dir = (jstring) env->GetObjectArrayElement(array, i); + directories.append(to_string(env, dir)); + env->DeleteLocalRef(dir); + } + checkException(env); + WebCore::PluginDatabase *pluginDatabase = + WebCore::PluginDatabase::installedPlugins(); + pluginDatabase->setPluginDirectories(directories); + // refreshPlugins() should refresh both PluginDatabase and Page's PluginData + WebCore::Page::refreshPlugins(reload); +} + // ---------------------------------------------------------------------------- /* @@ -339,10 +367,10 @@ static JNINativeMethod gWebCoreJavaBridgeMethods[] = { (void*) JavaBridge::SetCacheSize }, { "setNetworkOnLine", "(Z)V", (void*) JavaBridge::SetNetworkOnLine }, - { "setDeferringTimers", "(Z)V", - (void*) JavaBridge::SetDeferringTimers }, { "nativeServiceFuncPtrQueue", "()V", (void*) JavaBridge::ServiceFuncPtrQueue }, + { "nativeUpdatePluginDirectories", "([Ljava/lang/String;Z)V", + (void*) JavaBridge::UpdatePluginDirectories } }; int register_javabridge(JNIEnv* env) diff --git a/WebKit/android/jni/JavaSharedClient.cpp b/WebKit/android/jni/JavaSharedClient.cpp index bf52ecd..2eec7b9 100644 --- a/WebKit/android/jni/JavaSharedClient.cpp +++ b/WebKit/android/jni/JavaSharedClient.cpp @@ -25,52 +25,54 @@ #include "config.h" #include "JavaSharedClient.h" -#define LOG_TAG "JavaSharedClient" -#include "utils/Log.h" +#include "TimerClient.h" #include "SkDeque.h" #include "SkThread.h" namespace android { - void AndroidSignalServiceFuncPtrQueue(); - TimerClient* JavaSharedClient::GetTimerClient() { - //LOG_ASSERT(gTimerClient != NULL, "gTimerClient not initialized!!!"); return gTimerClient; } CookieClient* JavaSharedClient::GetCookieClient() { - //LOG_ASSERT(gCookieClient != NULL, "gCookieClient not initialized!!!"); return gCookieClient; } + PluginClient* JavaSharedClient::GetPluginClient() + { + return gPluginClient; + } + KeyGeneratorClient* JavaSharedClient::GetKeyGeneratorClient() { - //LOG_ASSERT(gKeyGeneratorClient != NULL, "gKeyGeneratorClient not initialized!!!"); return gKeyGeneratorClient; } void JavaSharedClient::SetTimerClient(TimerClient* client) { - //LOG_ASSERT(gTimerClient == NULL || client == NULL, "gTimerClient already set, aborting..."); gTimerClient = client; } void JavaSharedClient::SetCookieClient(CookieClient* client) { - //LOG_ASSERT(gCookieClient == NULL || client == NULL, "gCookieClient already set, aborting..."); gCookieClient = client; } + void JavaSharedClient::SetPluginClient(PluginClient* client) + { + gPluginClient = client; + } + void JavaSharedClient::SetKeyGeneratorClient(KeyGeneratorClient* client) { - //LOG_ASSERT(gKeyGeneratorClient == NULL || client == NULL, "gKeyGeneratorClient already set, aborting..."); gKeyGeneratorClient = client; } TimerClient* JavaSharedClient::gTimerClient = NULL; CookieClient* JavaSharedClient::gCookieClient = NULL; + PluginClient* JavaSharedClient::gPluginClient = NULL; KeyGeneratorClient* JavaSharedClient::gKeyGeneratorClient = NULL; /////////////////////////////////////////////////////////////////////////// @@ -94,7 +96,7 @@ namespace android { gFuncPtrQMutex.release(); - android::AndroidSignalServiceFuncPtrQueue(); + gTimerClient->signalServiceFuncPtrQueue(); } void JavaSharedClient::ServiceFunctionPtrQueue() diff --git a/WebKit/android/jni/JavaSharedClient.h b/WebKit/android/jni/JavaSharedClient.h index 862b508..bf59969 100644 --- a/WebKit/android/jni/JavaSharedClient.h +++ b/WebKit/android/jni/JavaSharedClient.h @@ -30,6 +30,7 @@ namespace android { class TimerClient; class CookieClient; + class PluginClient; class KeyGeneratorClient; class JavaSharedClient @@ -37,20 +38,23 @@ namespace android { public: static TimerClient* GetTimerClient(); static CookieClient* GetCookieClient(); + static PluginClient* GetPluginClient(); static KeyGeneratorClient* GetKeyGeneratorClient(); static void SetTimerClient(TimerClient* client); static void SetCookieClient(CookieClient* client); + static void SetPluginClient(PluginClient* client); static void SetKeyGeneratorClient(KeyGeneratorClient* client); // can be called from any thread, to be executed in webkit thread static void EnqueueFunctionPtr(void (*proc)(void*), void* payload); // only call this from webkit thread static void ServiceFunctionPtrQueue(); - + private: static TimerClient* gTimerClient; static CookieClient* gCookieClient; + static PluginClient* gPluginClient; static KeyGeneratorClient* gKeyGeneratorClient; }; } diff --git a/WebKit/android/jni/PictureSet.cpp b/WebKit/android/jni/PictureSet.cpp index ac3f38a..e8fcba5 100644 --- a/WebKit/android/jni/PictureSet.cpp +++ b/WebKit/android/jni/PictureSet.cpp @@ -263,7 +263,7 @@ bool PictureSet::draw(SkCanvas* canvas) SkPath pathClip; area.getBoundaryPath(&pathClip); canvas->clipPath(pathClip); - pathClip.computeBounds(&pathBounds, SkPath::kFast_BoundsType); + pathBounds = pathClip.getBounds(); } else { pathBounds.set(area.getBounds()); canvas->clipRect(pathBounds); diff --git a/WebKit/android/jni/WebCoreFrameBridge.cpp b/WebKit/android/jni/WebCoreFrameBridge.cpp index e2299c8..46e1fdc 100644 --- a/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -41,14 +41,16 @@ #include "EditorClientAndroid.h" #include "Element.h" #include "Font.h" +#include "FormState.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameLoaderClientAndroid.h" +#include "FrameLoadRequest.h" #include "FrameTree.h" #include "FrameView.h" -#include "GCController.h" #include "GraphicsContext.h" #include "HistoryItem.h" +#include "HTMLCollection.h" #include "HTMLElement.h" #include "HTMLFormElement.h" #include "HTMLInputElement.h" @@ -56,9 +58,18 @@ #include "IconDatabase.h" #include "Image.h" #include "InspectorClientAndroid.h" + +#if USE(JSC) +#include "GCController.h" #include "JSDOMWindow.h" #include <runtime/InitializeThreading.h> #include <runtime/JSLock.h> +#elif USE(V8) +#include "V8InitializeThreading.h" +#include "jni_npobject.h" +#include "jni_instance.h" +#endif // USE(JSC) + #include "KURL.h" #include "Page.h" #include "PageCache.h" @@ -82,11 +93,17 @@ #include "WebViewCore.h" #include "wds/DebugServer.h" +#if USE(JSC) #include <runtime_root.h> #include <runtime_object.h> +#endif // USE(JSC) + #include <jni_utility.h> #include "jni.h" + +#if USE(JSC) #include "jni_instance.h" +#endif // USE(JSC) #include <JNIHelp.h> #include <SkGraphics.h> @@ -96,12 +113,8 @@ #ifdef ANDROID_INSTRUMENT #include "TimeCounter.h" -#include <runtime/JSLock.h> #endif -using namespace JSC; -using namespace JSC::Bindings; - namespace android { // ---------------------------------------------------------------------------- @@ -152,7 +165,7 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* mJavaFrame->mObj = adoptGlobalRef(env, obj); mJavaFrame->mHistoryList = adoptGlobalRef(env, historyList); mJavaFrame->mStartLoadingResource = env->GetMethodID(clazz, "startLoadingResource", - "(ILjava/lang/String;Ljava/lang/String;Ljava/util/HashMap;[BIZZ)Landroid/webkit/LoadListener;"); + "(ILjava/lang/String;Ljava/lang/String;Ljava/util/HashMap;[BIZ)Landroid/webkit/LoadListener;"); mJavaFrame->mLoadStarted = env->GetMethodID(clazz, "loadStarted", "(Ljava/lang/String;Landroid/graphics/Bitmap;IZ)V"); mJavaFrame->mTransitionToCommitted = env->GetMethodID(clazz, "transitionToCommitted", @@ -247,6 +260,7 @@ static jobject createJavaMapFromHTTPHeaders(JNIEnv* env, const WebCore::HTTPHead env->DeleteLocalRef(val); } } + env->DeleteLocalRef(mapClass); return hashMap; @@ -255,7 +269,7 @@ static jobject createJavaMapFromHTTPHeaders(JNIEnv* env, const WebCore::HTTPHead WebCoreResourceLoader* WebFrame::startLoadingResource(WebCore::ResourceHandle* loader, const WebCore::ResourceRequest& request, - bool isHighPriority, bool synchronous) + bool synchronous) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); @@ -340,7 +354,7 @@ WebFrame::startLoadingResource(WebCore::ResourceHandle* loader, jobject jLoadListener = env->CallObjectMethod(mJavaFrame->frame(env).get(), mJavaFrame->mStartLoadingResource, (int)loader, jUrlStr, jMethodStr, jHeaderMap, - jPostDataStr, cacheMode, isHighPriority, synchronous); + jPostDataStr, cacheMode, synchronous); env->DeleteLocalRef(jUrlStr); env->DeleteLocalRef(jMethodStr); @@ -570,17 +584,11 @@ WebFrame::canHandleRequest(const WebCore::ResourceRequest& request) #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif - // Internal loads are ok but any request that is due to a user hitting a key - // should be checked. - bool userGesture = false; -#ifdef ANDROID_USER_GESTURE - userGesture = request.userGesture(); -#endif // always handle "POST" in place if (equalIgnoringCase(request.httpMethod(), "POST")) return true; WebCore::KURL requestUrl = request.url(); - if (!mUserInitiatedClick && !userGesture && + if (!mUserInitiatedClick && (requestUrl.protocolIs("http") || requestUrl.protocolIs("https") || requestUrl.protocolIs("file") || requestUrl.protocolIs("about") || requestUrl.protocolIs("javascript"))) @@ -680,7 +688,12 @@ static void CallPolicyFunction(JNIEnv* env, jobject obj, jint func, jint decisio static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAssetManager, jobject historyList) { +#if USE(JSC) JSC::initializeThreading(); +#elif USE(V8) + V8::initializeThreading(); +#endif + #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter); #endif @@ -723,17 +736,15 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss WebViewCore* webViewCore = new WebViewCore(env, javaview, frame); // Create a FrameView - WebCore::FrameView* frameView = new WebCore::FrameView(frame); + RefPtr<WebCore::FrameView> frameView = WebCore::FrameView::create(frame); // Create a WebFrameView - WebFrameView* webFrameView = new WebFrameView(frameView, webViewCore); + WebFrameView* webFrameView = new WebFrameView(frameView.get(), webViewCore); // As webFrameView Retains webViewCore, release our ownership Release(webViewCore); // As frameView Retains webFrameView, release our ownership Release(webFrameView); // Attach the frameView to the frame and release our ownership frame->setView(frameView); - frameView->deref(); - // Set the frame to active to turn on keyboard focus. frame->init(); frame->selection()->setFocused(true); @@ -805,6 +816,7 @@ static void PostUrl(JNIEnv *env, jobject obj, jstring url, jbyteArray postData) WebCore::KURL kurl(WebCore::KURL(), to_string(env, url)); WebCore::ResourceRequest request(kurl); + request.setHTTPMethod("POST"); request.setHTTPContentType("application/x-www-form-urlencoded"); if (postData) { @@ -815,8 +827,8 @@ static void PostUrl(JNIEnv *env, jobject obj, jstring url, jbyteArray postData) } LOGV("PostUrl %s", kurl.string().latin1().data()); - pFrame->loader()->loadPostRequest(request, String(), String(), false, - WebCore::FrameLoadTypeStandard, 0, 0, true); + WebCore::FrameLoadRequest frameRequest(request); + pFrame->loader()->loadFrameRequest(frameRequest, false, false, 0, 0); } static void LoadData(JNIEnv *env, jobject obj, jstring baseUrl, jstring data, @@ -950,21 +962,22 @@ static jobject StringByEvaluatingJavaScriptFromString(JNIEnv *env, jobject obj, return env->NewString((unsigned short*)result.characters(), len); } +#if USE(JSC) // Wrap the JavaInstance used when binding custom javascript interfaces. Use a // weak reference so that the gc can collect the WebView. Override virtualBegin // and virtualEnd and swap the weak reference for the real object. -class WeakJavaInstance : public JavaInstance { +class WeakJavaInstance : public JSC::Bindings::JavaInstance { public: static PassRefPtr<WeakJavaInstance> create(jobject obj, - PassRefPtr<RootObject> root) { + PassRefPtr<JSC::Bindings::RootObject> root) { return adoptRef(new WeakJavaInstance(obj, root)); } protected: - WeakJavaInstance(jobject instance, PassRefPtr<RootObject> rootObject) - : JavaInstance(instance, rootObject) + WeakJavaInstance(jobject instance, PassRefPtr<JSC::Bindings::RootObject> rootObject) + : JSC::Bindings::JavaInstance(instance, rootObject) { - JNIEnv* env = getJNIEnv(); + JNIEnv* env = JSC::Bindings::getJNIEnv(); // JavaInstance creates a global ref to instance in its constructor. env->DeleteGlobalRef(_instance->_instance); // Set the object to our WeakReference wrapper. @@ -973,7 +986,7 @@ protected: virtual void virtualBegin() { _weakRef = _instance->_instance; - JNIEnv* env = getJNIEnv(); + JNIEnv* env = JSC::Bindings::getJNIEnv(); // This is odd. getRealObject returns an AutoJObject which is used to // cleanly create and delete a local reference. But, here we need to // maintain the local reference across calls to virtualBegin() and @@ -990,16 +1003,17 @@ protected: // Call the base class method first to pop the local frame. INHERITED::virtualEnd(); // Get rid of the local reference to the real object. - getJNIEnv()->DeleteLocalRef(_realObject); + JSC::Bindings::getJNIEnv()->DeleteLocalRef(_realObject); // Point back to the WeakReference. _instance->_instance = _weakRef; } private: - typedef JavaInstance INHERITED; + typedef JSC::Bindings::JavaInstance INHERITED; jobject _realObject; jobject _weakRef; }; +#endif // USE(JSC) static void AddJavascriptInterface(JNIEnv *env, jobject obj, jint nativeFramePointer, jobject javascriptObj, jstring interfaceName) @@ -1014,6 +1028,7 @@ static void AddJavascriptInterface(JNIEnv *env, jobject obj, jint nativeFramePoi env->GetJavaVM(&vm); LOGV("::WebCore:: addJSInterface: %p", pFrame); +#if USE(JSC) // Copied from qwebframe.cpp JSC::JSLock lock(false); WebCore::JSDOMWindow *window = WebCore::toJSDOMWindow(pFrame); @@ -1034,6 +1049,24 @@ static void AddJavascriptInterface(JNIEnv *env, jobject obj, jint nativeFramePoi checkException(env); } } +#endif // USE(JSC) + +#if USE(V8) + if (pFrame) { + const char* name = JSC::Bindings::getCharactersFromJStringInEnv(env, interfaceName); + NPObject* obj = JSC::Bindings::JavaInstanceToNPObject(new JSC::Bindings::JavaInstance(javascriptObj)); + pFrame->script()->bindToWindowObject(pFrame, name, obj); + // JavaInstanceToNPObject calls NPN_RetainObject on the + // returned one (see CreateV8ObjectForNPObject in V8NPObject.cpp). + // BindToWindowObject also increases obj's ref count and decrease + // the ref count when the object is not reachable from JavaScript + // side. Code here must release the reference count increased by + // JavaInstanceToNPObject. + NPN_ReleaseObject(obj); + JSC::Bindings::releaseCharactersForJString(interfaceName, name); + } +#endif + } static void SetCacheDisabled(JNIEnv *env, jobject obj, jboolean disabled) @@ -1056,22 +1089,25 @@ static void ClearCache(JNIEnv *env, jobject obj) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter); - +#if USE(JSC) JSC::JSLock lock(false); JSC::Heap::Statistics jsHeapStatistics = WebCore::JSDOMWindow::commonJSGlobalData()->heap.statistics(); LOGD("About to gc and JavaScript heap size is %d and has %d bytes free", jsHeapStatistics.size, jsHeapStatistics.free); +#endif // USE(JSC) LOGD("About to clear cache and current cache has %d bytes live and %d bytes dead", cache()->getLiveSize(), cache()->getDeadSize()); -#endif +#endif // ANDROID_INSTRUMENT if (!WebCore::cache()->disabled()) { // Disabling the cache will remove all resources from the cache. They may // still live on if they are referenced by some Web page though. WebCore::cache()->setDisabled(true); WebCore::cache()->setDisabled(false); } +#if USE(JSC) // force JavaScript to GC when clear cache WebCore::gcController().garbageCollectSoon(); +#endif // USE(JSC) } static jboolean DocumentHasImages(JNIEnv *env, jobject obj) diff --git a/WebKit/android/jni/WebCoreFrameBridge.h b/WebKit/android/jni/WebCoreFrameBridge.h index f554117..5bfd1fb 100644 --- a/WebKit/android/jni/WebCoreFrameBridge.h +++ b/WebKit/android/jni/WebCoreFrameBridge.h @@ -63,7 +63,6 @@ class WebFrame : public WebCoreRefObject { virtual WebCoreResourceLoader* startLoadingResource(WebCore::ResourceHandle*, const WebCore::ResourceRequest& request, - bool isHighPriority, bool synchronous); void reportError(int errorCode, const WebCore::String& description, diff --git a/WebKit/android/jni/WebCoreJni.cpp b/WebKit/android/jni/WebCoreJni.cpp index f9d9cc9..b757e3a 100644 --- a/WebKit/android/jni/WebCoreJni.cpp +++ b/WebKit/android/jni/WebCoreJni.cpp @@ -33,15 +33,6 @@ namespace android { -extern int register_webframe(JNIEnv*); -extern int register_javabridge(JNIEnv*); -extern int register_resource_loader(JNIEnv*); -extern int register_webviewcore(JNIEnv*); -extern int register_webhistory(JNIEnv*); -extern int register_webicondatabase(JNIEnv*); -extern int register_websettings(JNIEnv*); -extern int register_webview(JNIEnv*); - // Class, constructor, and get method on WeakReference jclass gWeakRefClass; jmethodID gWeakRefInit; @@ -93,41 +84,11 @@ WebCore::String to_string(JNIEnv* env, jstring str) return ret; } -} - -struct RegistrationMethod { - const char* name; - int (*func)(JNIEnv*); -}; - -static RegistrationMethod gWebCoreRegMethods[] = { - { "JavaBridge", android::register_javabridge }, - { "WebFrame", android::register_webframe }, - { "WebCoreResourceLoader", android::register_resource_loader }, - { "WebViewCore", android::register_webviewcore }, - { "WebHistory", android::register_webhistory }, - { "WebIconDatabase", android::register_webicondatabase }, - { "WebSettings", android::register_websettings }, - { "WebView", android::register_webview } -}; - -EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) -{ - // Save the JavaVM pointer for use globally. - JSC::Bindings::setJavaVM(vm); - - JNIEnv* env = NULL; - jint result = -1; - - if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { - LOGE("GetEnv failed!"); - return result; - } - LOG_ASSERT(env, "Could not retrieve the env!"); - +int register_webcorejni(JNIEnv* env) { // Instantiate the WeakReference fields. - android::gWeakRefClass = env->FindClass("java/lang/ref/WeakReference"); - LOG_ASSERT(android::gWeakRefClass, "Could not find WeakReference"); + jclass weakRef = env->FindClass("java/lang/ref/WeakReference"); + LOG_ASSERT(weakRef, "Could not find WeakReference"); + android::gWeakRefClass = (jclass)env->NewGlobalRef(weakRef); android::gWeakRefInit = env->GetMethodID(android::gWeakRefClass, "<init>", "(Ljava/lang/Object;)V"); LOG_ASSERT(android::gWeakRefInit, @@ -136,20 +97,7 @@ EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) "()Ljava/lang/Object;"); LOG_ASSERT(android::gWeakRefInit, "Could not find get method for WeakReference"); + return JNI_OK; +} - const RegistrationMethod* method = gWebCoreRegMethods; - const RegistrationMethod* end = method + sizeof(gWebCoreRegMethods)/sizeof(RegistrationMethod); - while (method != end) { - if (method->func(env) < 0) { - LOGE("%s registration failed!", method->name); - return result; - } - method++; - } - - // Initialize rand() function. The rand() function is used in - // FileSystemAndroid to create a random temporary filename. - srand(time(NULL)); - - return JNI_VERSION_1_4; } diff --git a/WebKit/android/jni/WebCoreJniOnLoad.cpp b/WebKit/android/jni/WebCoreJniOnLoad.cpp new file mode 100644 index 0000000..c6b0022 --- /dev/null +++ b/WebKit/android/jni/WebCoreJniOnLoad.cpp @@ -0,0 +1,100 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#define LOG_TAG "webcoreglue" + +#include "config.h" + +#include "jni_utility.h" +#include <jni.h> +#include <utils/Log.h> + +namespace android { + +extern int register_webframe(JNIEnv*); +extern int register_javabridge(JNIEnv*); +extern int register_resource_loader(JNIEnv*); +extern int register_webviewcore(JNIEnv*); +extern int register_webhistory(JNIEnv*); +extern int register_webicondatabase(JNIEnv*); +extern int register_websettings(JNIEnv*); +extern int register_webview(JNIEnv*); +extern int register_webcorejni(JNIEnv*); + +#if ENABLE(DATABASE) +extern int register_webstorage(JNIEnv*); +#endif + +} + +struct RegistrationMethod { + const char* name; + int (*func)(JNIEnv*); +}; + +static RegistrationMethod gWebCoreRegMethods[] = { + { "JavaBridge", android::register_javabridge }, + { "WebFrame", android::register_webframe }, + { "WebCoreResourceLoader", android::register_resource_loader }, + { "WebCoreJni", android::register_webcorejni }, + { "WebViewCore", android::register_webviewcore }, + { "WebHistory", android::register_webhistory }, + { "WebIconDatabase", android::register_webicondatabase }, + { "WebSettings", android::register_websettings }, +#if ENABLE(DATABASE) + { "WebStorage", android::register_webstorage }, +#endif + { "WebView", android::register_webview } +}; + +EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) +{ + // Save the JavaVM pointer for use globally. + JSC::Bindings::setJavaVM(vm); + + JNIEnv* env = NULL; + jint result = -1; + + if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { + LOGE("GetEnv failed!"); + return result; + } + LOG_ASSERT(env, "Could not retrieve the env!"); + + const RegistrationMethod* method = gWebCoreRegMethods; + const RegistrationMethod* end = method + sizeof(gWebCoreRegMethods)/sizeof(RegistrationMethod); + while (method != end) { + if (method->func(env) < 0) { + LOGE("%s registration failed!", method->name); + return result; + } + method++; + } + + // Initialize rand() function. The rand() function is used in + // FileSystemAndroid to create a random temporary filename. + srand(time(NULL)); + + return JNI_VERSION_1_4; +} diff --git a/WebKit/android/jni/WebCoreResourceLoader.cpp b/WebKit/android/jni/WebCoreResourceLoader.cpp index d4eda81..5ccd09c 100644 --- a/WebKit/android/jni/WebCoreResourceLoader.cpp +++ b/WebKit/android/jni/WebCoreResourceLoader.cpp @@ -134,7 +134,7 @@ void WebCoreResourceLoader::SetResponseHeader(JNIEnv* env, jobject obj, jint nat jint WebCoreResourceLoader::CreateResponse(JNIEnv* env, jobject obj, jstring url, jint statusCode, jstring statusText, jstring mimeType, jlong expectedLength, - jstring encoding, jlong expireTime) + jstring encoding) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::ResourceTimeCounter); @@ -160,10 +160,6 @@ jint WebCoreResourceLoader::CreateResponse(JNIEnv* env, jobject obj, jstring url response->setHTTPStatusText(status); LOGV("Response setStatusText: %s", status.latin1().data()); } - // FIXME: This assumes that time_t is a long and that long is the same size as int. - if ((unsigned long)expireTime > INT_MAX) - expireTime = INT_MAX; - response->setExpirationDate((time_t)expireTime); return (int)response; } @@ -286,7 +282,7 @@ static JNINativeMethod gResourceloaderMethods[] = { /* name, signature, funcPtr */ { "nativeSetResponseHeader", "(ILjava/lang/String;Ljava/lang/String;)V", (void*) WebCoreResourceLoader::SetResponseHeader }, - { "nativeCreateResponse", "(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;JLjava/lang/String;J)I", + { "nativeCreateResponse", "(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;JLjava/lang/String;)I", (void*) WebCoreResourceLoader::CreateResponse }, { "nativeReceivedResponse", "(I)V", (void*) WebCoreResourceLoader::ReceivedResponse }, diff --git a/WebKit/android/jni/WebCoreResourceLoader.h b/WebKit/android/jni/WebCoreResourceLoader.h index 5dd5abe..60c0d0e 100644 --- a/WebKit/android/jni/WebCoreResourceLoader.h +++ b/WebKit/android/jni/WebCoreResourceLoader.h @@ -58,7 +58,7 @@ public: // Native jni functions static void SetResponseHeader(JNIEnv*, jobject, jint, jstring, jstring); static jint CreateResponse(JNIEnv*, jobject, jstring, jint, jstring, - jstring, jlong, jstring, jlong); + jstring, jlong, jstring); static void ReceivedResponse(JNIEnv*, jobject, jint); static void AddData(JNIEnv*, jobject, jbyteArray, jint); static void Finished(JNIEnv*, jobject); diff --git a/WebKit/android/jni/WebFrameView.cpp b/WebKit/android/jni/WebFrameView.cpp index f9a9a5b..0ab7410 100644 --- a/WebKit/android/jni/WebFrameView.cpp +++ b/WebKit/android/jni/WebFrameView.cpp @@ -84,12 +84,9 @@ void WebFrameView::draw(WebCore::GraphicsContext* ctx, const WebCore::IntRect& r transRect.move(-bounds.x(), -bounds.y()); // Translate the canvas, add a clip. - SkRect r; - android_setrect(&r, transRect); - canvas->save(); canvas->translate(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y())); - canvas->clipRect(r); + canvas->clipRect(transRect); } mFrameView->paintContents(ctx, transRect); if (canvas) diff --git a/WebKit/android/jni/WebHistory.cpp b/WebKit/android/jni/WebHistory.cpp index cd6e0f1..aa80bf0 100644 --- a/WebKit/android/jni/WebHistory.cpp +++ b/WebKit/android/jni/WebHistory.cpp @@ -120,7 +120,7 @@ static void WebHistoryClose(JNIEnv* env, jobject obj, jint frame) while (child) { // Use the old history item since the current one may have a // deleted parent. - WebCore::HistoryItem* item = parent->childItemWithName(child->tree()->name()); + WebCore::HistoryItem* item = parent->childItemWithTarget(child->tree()->name()); child->loader()->setCurrentHistoryItem(item); // Append the first child to the queue if it exists. if (WebCore::Frame* f = child->tree()->firstChild()) @@ -153,7 +153,6 @@ static void WebHistoryRestoreIndex(JNIEnv* env, jobject obj, jint frame, jint in // Update the current and previous history item. WebCore::FrameLoader* loader = pFrame->loader(); loader->setCurrentHistoryItem(currentItem); - loader->setPreviousHistoryItem(list->backItem()); // load the current page with FrameLoadTypeIndexedBackForward so that it // will use cache when it is possible diff --git a/WebKit/android/jni/WebSettings.cpp b/WebKit/android/jni/WebSettings.cpp index 407544a..7d2b12d 100644 --- a/WebKit/android/jni/WebSettings.cpp +++ b/WebKit/android/jni/WebSettings.cpp @@ -28,17 +28,15 @@ #include <config.h> #include <wtf/Platform.h> +#include "ApplicationCacheStorage.h" +#include "DatabaseTracker.h" +#include "DocLoader.h" #include "Document.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameView.h" -#include "DocLoader.h" #include "Page.h" #include "RenderTable.h" -#ifdef ANDROID_PLUGINS -#include "PlatformString.h" -#include "PluginDatabase.h" -#endif #include "Settings.h" #include "WebCoreFrameBridge.h" #include "WebCoreJni.h" @@ -46,11 +44,6 @@ #include <JNIHelp.h> #include <utils/misc.h> -namespace WebCore { -// Defined in FileSystemAndroid.cpp -extern String sPluginPath; -} - namespace android { struct FieldIds { @@ -85,8 +78,20 @@ struct FieldIds { #endif mJavaScriptEnabled = env->GetFieldID(clazz, "mJavaScriptEnabled", "Z"); mPluginsEnabled = env->GetFieldID(clazz, "mPluginsEnabled", "Z"); -#ifdef ANDROID_PLUGINS - mPluginsPath = env->GetFieldID(clazz, "mPluginsPath", "Ljava/lang/String;"); +#if ENABLE(DATABASE) + mDatabaseEnabled = env->GetFieldID(clazz, "mDatabaseEnabled", "Z"); +#endif +#if ENABLE(DOM_STORAGE) + mDomStorageEnabled = env->GetFieldID(clazz, "mDomStorageEnabled", "Z"); +#endif +#if ENABLE(DATABASE) || ENABLE(DOM_STORAGE) + // The databases saved to disk for both the SQL and DOM Storage APIs are stored + // in the same base directory. + mDatabasePath = env->GetFieldID(clazz, "mDatabasePath", "Ljava/lang/String;"); +#endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + mAppCacheEnabled = env->GetFieldID(clazz, "mAppCacheEnabled", "Z"); + mAppCachePath = env->GetFieldID(clazz, "mAppCachePath", "Ljava/lang/String;"); #endif mJavaScriptCanOpenWindowsAutomatically = env->GetFieldID(clazz, "mJavaScriptCanOpenWindowsAutomatically", "Z"); @@ -112,11 +117,12 @@ struct FieldIds { LOG_ASSERT(mLoadsImagesAutomatically, "Could not find field mLoadsImagesAutomatically"); #ifdef ANDROID_BLOCK_NETWORK_IMAGE LOG_ASSERT(mBlockNetworkImage, "Could not find field mBlockNetworkImage"); -#endif +#endif LOG_ASSERT(mJavaScriptEnabled, "Could not find field mJavaScriptEnabled"); LOG_ASSERT(mPluginsEnabled, "Could not find field mPluginsEnabled"); -#ifdef ANDROID_PLUGINS - LOG_ASSERT(mPluginsPath, "Could not find field mPluginsPath"); +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + LOG_ASSERT(mAppCacheEnabled, "Could not find field mAppCacheEnabled"); + LOG_ASSERT(mAppCachePath, "Could not find field mAppCachePath"); #endif LOG_ASSERT(mJavaScriptCanOpenWindowsAutomatically, "Could not find field mJavaScriptCanOpenWindowsAutomatically"); @@ -155,18 +161,28 @@ struct FieldIds { #endif jfieldID mJavaScriptEnabled; jfieldID mPluginsEnabled; -#ifdef ANDROID_PLUGINS - jfieldID mPluginsPath; +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + jfieldID mAppCacheEnabled; + jfieldID mAppCachePath; #endif jfieldID mJavaScriptCanOpenWindowsAutomatically; jfieldID mUseWideViewport; jfieldID mSupportMultipleWindows; jfieldID mShrinksStandaloneImagesToFit; jfieldID mUseDoubleTree; - // Ordinal() method and value field for enums jmethodID mOrdinal; jfieldID mTextSizeValue; + +#if ENABLE(DATABASE) + jfieldID mDatabaseEnabled; +#endif +#if ENABLE(DOM_STORAGE) + jfieldID mDomStorageEnabled; +#endif +#if ENABLE(DATABASE) || ENABLE(DOM_STORAGE) + jfieldID mDatabasePath; +#endif }; static struct FieldIds* gFieldIds; @@ -273,47 +289,17 @@ public: flag = env->GetBooleanField(obj, gFieldIds->mPluginsEnabled); s->setPluginsEnabled(flag); -#ifdef ANDROID_PLUGINS - ::WebCore::PluginDatabase *pluginDatabase = - ::WebCore::PluginDatabase::installedPlugins(); - str = (jstring)env->GetObjectField(obj, gFieldIds->mPluginsPath); +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + flag = env->GetBooleanField(obj, gFieldIds->mAppCacheEnabled); + s->setOfflineWebApplicationCacheEnabled(flag); + str = (jstring)env->GetObjectField(obj, gFieldIds->mAppCachePath); if (str) { - WebCore::String pluginsPath = to_string(env, str); - // When a new browser Tab is created, the corresponding - // Java WebViewCore object will sync (with the native - // side) its associated WebSettings at initialization - // time. However, at that point, the WebSettings object's - // mPluginsPaths member is set to the empty string. The - // real plugin path will be set later by the tab and the - // WebSettings will be synced again. - // - // There is no point in instructing WebCore's - // PluginDatabase instance to set the plugin path to the - // empty string. Furthermore, if the PluginDatabase - // instance is already initialized, setting the path to - // the empty string will cause the PluginDatabase to - // forget about the plugin files it has already - // inspected. When the path is subsequently set to the - // correct value, the PluginDatabase will attempt to load - // and initialize plugins that are already loaded and - // initialized. - if (pluginsPath.length()) { - s->setPluginsPath(pluginsPath); - // Set the plugin directories to this single entry. - Vector< ::WebCore::String > paths(1); - paths[0] = pluginsPath; - pluginDatabase->setPluginDirectories(paths); - // Set the home directory for plugin temporary files - WebCore::sPluginPath = paths[0]; - // Reload plugins. We call Page::refreshPlugins() instead - // of pluginDatabase->refresh(), as we need to ensure that - // the list of mimetypes exposed by the browser are also - // updated. - WebCore::Page::refreshPlugins(false); + WebCore::String path = to_string(env, str); + if (path.length()) { + WebCore::cacheStorage().setCacheDirectory(path); } } #endif - flag = env->GetBooleanField(obj, gFieldIds->mJavaScriptCanOpenWindowsAutomatically); s->setJavaScriptCanOpenWindowsAutomatically(flag); @@ -328,9 +314,22 @@ public: #endif flag = env->GetBooleanField(obj, gFieldIds->mShrinksStandaloneImagesToFit); s->setShrinksStandaloneImagesToFit(flag); -#if USE(LOW_BANDWIDTH_DISPLAY) - flag = env->GetBooleanField(obj, gFieldIds->mUseDoubleTree); - pFrame->loader()->setUseLowBandwidthDisplay(flag); +#if ENABLE(DATABASE) + flag = env->GetBooleanField(obj, gFieldIds->mDatabaseEnabled); + s->setDatabasesEnabled(flag); + str = (jstring)env->GetObjectField(obj, gFieldIds->mDatabasePath); + WebCore::DatabaseTracker::tracker().setDatabaseDirectoryPath(to_string(env, str)); +#endif +#if ENABLE(DOM_STORAGE) + flag = env->GetBooleanField(obj, gFieldIds->mDomStorageEnabled); + s->setLocalStorageEnabled(flag); + str = (jstring)env->GetObjectField(obj, gFieldIds->mDatabasePath); + if (str) { + WebCore::String localStorageDatabasePath = to_string(env,str); + if (localStorageDatabasePath.length()) { + s->setLocalStorageDatabasePath(localStorageDatabasePath); + } + } #endif } }; diff --git a/WebKit/android/jni/WebStorage.cpp b/WebKit/android/jni/WebStorage.cpp new file mode 100644 index 0000000..aa83892 --- /dev/null +++ b/WebKit/android/jni/WebStorage.cpp @@ -0,0 +1,166 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(DATABASE) + +#include <JNIHelp.h> + +#include <WebCore/loader/appcache/ApplicationCacheStorage.h> +#include <WebCore/page/SecurityOrigin.h> +#include <WebCore/storage/DatabaseTracker.h> + +#include "JavaSharedClient.h" +#include "jni_utility.h" +#include "KURL.h" +#include "WebCoreJni.h" + +namespace android { + +static jobject GetOrigins(JNIEnv* env, jobject obj) +{ + Vector<RefPtr<WebCore::SecurityOrigin> > coreOrigins; + WebCore::DatabaseTracker::tracker().origins(coreOrigins); + Vector<WebCore::KURL> manifestUrls; + if (WebCore::cacheStorage().manifestURLs(&manifestUrls)) { + int size = manifestUrls.size(); + for (int i = 0; i < size; ++i) { + RefPtr<WebCore::SecurityOrigin> manifestOrigin = WebCore::SecurityOrigin::create(manifestUrls[i]); + if (manifestOrigin.get() == 0) + continue; + coreOrigins.append(manifestOrigin); + } + } + + jclass setClass = env->FindClass("java/util/HashSet"); + jmethodID cid = env->GetMethodID(setClass, "<init>", "()V"); + jmethodID mid = env->GetMethodID(setClass, "add", "(Ljava/lang/Object;)Z"); + jobject set = env->NewObject(setClass, cid); + + for (unsigned i = 0; i < coreOrigins.size(); ++i) { + WebCore::SecurityOrigin* origin = coreOrigins[i].get(); + WebCore::String url = origin->toString(); + jstring jUrl = env->NewString(url.characters(), url.length()); + env->CallBooleanMethod(set, mid, jUrl); + env->DeleteLocalRef(jUrl); + } + + return set; +} + +static unsigned long long GetQuotaForOrigin(JNIEnv* env, jobject obj, jstring origin) +{ + WebCore::String originStr = to_string(env, origin); + RefPtr<WebCore::SecurityOrigin> securityOrigin = WebCore::SecurityOrigin::createFromString(originStr); + unsigned long long quota = WebCore::DatabaseTracker::tracker().quotaForOrigin(securityOrigin.get()); + return quota; +} + +static unsigned long long GetUsageForOrigin(JNIEnv* env, jobject obj, jstring origin) +{ + WebCore::String originStr = to_string(env, origin); + RefPtr<WebCore::SecurityOrigin> securityOrigin = WebCore::SecurityOrigin::createFromString(originStr); + unsigned long long usage = WebCore::DatabaseTracker::tracker().usageForOrigin(securityOrigin.get()); + Vector<WebCore::KURL> manifestUrls; + if (!WebCore::cacheStorage().manifestURLs(&manifestUrls)) + return usage; + int size = manifestUrls.size(); + for (int i = 0; i < size; ++i) { + RefPtr<WebCore::SecurityOrigin> manifestOrigin = WebCore::SecurityOrigin::create(manifestUrls[i]); + if (manifestOrigin.get() == 0) + continue; + if (manifestOrigin->isSameSchemeHostPort(securityOrigin.get())) { + int64_t size = 0; + WebCore::cacheStorage().cacheGroupSize(manifestUrls[i].string(), &size); + usage += size; + } + } + return usage; +} + +static void SetQuotaForOrigin(JNIEnv* env, jobject obj, jstring origin, unsigned long long quota) +{ + WebCore::String originStr = to_string(env, origin); + RefPtr<WebCore::SecurityOrigin> securityOrigin = WebCore::SecurityOrigin::createFromString(originStr); + WebCore::DatabaseTracker::tracker().setQuota(securityOrigin.get(), quota); +} + +static void DeleteOrigin(JNIEnv* env, jobject obj, jstring origin) +{ + WebCore::String originStr = to_string(env, origin); + RefPtr<WebCore::SecurityOrigin> securityOrigin = WebCore::SecurityOrigin::createFromString(originStr); + WebCore::DatabaseTracker::tracker().deleteOrigin(securityOrigin.get()); + + Vector<WebCore::KURL> manifestUrls; + if (!WebCore::cacheStorage().manifestURLs(&manifestUrls)) + return; + int size = manifestUrls.size(); + for (int i = 0; i < size; ++i) { + RefPtr<WebCore::SecurityOrigin> manifestOrigin = WebCore::SecurityOrigin::create(manifestUrls[i]); + if (manifestOrigin.get() == 0) + continue; + if (manifestOrigin->isSameSchemeHostPort(securityOrigin.get())) + WebCore::cacheStorage().deleteCacheGroup(manifestUrls[i]); + } +} + +static void DeleteAllData(JNIEnv* env, jobject obj) +{ + WebCore::DatabaseTracker::tracker().deleteAllDatabases(); + WebCore::cacheStorage().empty(); +} + +/* + * JNI registration + */ +static JNINativeMethod gWebStorageMethods[] = { + { "nativeGetOrigins", "()Ljava/util/Set;", + (void*) GetOrigins }, + { "nativeGetUsageForOrigin", "(Ljava/lang/String;)J", + (void*) GetUsageForOrigin }, + { "nativeGetQuotaForOrigin", "(Ljava/lang/String;)J", + (void*) GetQuotaForOrigin }, + { "nativeSetQuotaForOrigin", "(Ljava/lang/String;J)V", + (void*) SetQuotaForOrigin }, + { "nativeDeleteOrigin", "(Ljava/lang/String;)V", + (void*) DeleteOrigin }, + { "nativeDeleteAllData", "()V", + (void*) DeleteAllData } +}; + +int register_webstorage(JNIEnv* env) +{ + jclass webStorage = env->FindClass("android/webkit/WebStorage"); + LOG_ASSERT(webStorage, "Unable to find class android.webkit.WebStorage"); + + return jniRegisterNativeMethods(env, "android/webkit/WebStorage", + gWebStorageMethods, NELEM(gWebStorageMethods)); +} + +} + +#endif //ENABLE(DATABASE) + diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp index f1cb3fa..9f457f4 100644 --- a/WebKit/android/jni/WebViewCore.cpp +++ b/WebKit/android/jni/WebViewCore.cpp @@ -31,14 +31,18 @@ #include "AtomicString.h" #include "CachedNode.h" #include "CachedRoot.h" +#include "ChromeClientAndroid.h" #include "Color.h" +#include "DatabaseTracker.h" #include "Document.h" #include "Element.h" #include "Editor.h" #include "EditorClientAndroid.h" #include "EventHandler.h" #include "EventNames.h" +#include "FocusController.h" #include "Font.h" +#include "Frame.h" #include "FrameLoader.h" #include "FrameLoaderClientAndroid.h" #include "FrameTree.h" @@ -64,11 +68,13 @@ #include "Page.h" #include "PlatformKeyboardEvent.h" #include "PlatformString.h" -#include "PluginInfoStore.h" #include "PluginWidgetAndroid.h" +#include "PluginView.h" #include "Position.h" #include "ProgressTracker.h" +#include "RenderBox.h" #include "RenderLayer.h" +#include "RenderPart.h" #include "RenderText.h" #include "RenderTextControl.h" #include "RenderThemeAndroid.h" @@ -76,11 +82,13 @@ #include "ResourceRequest.h" #include "SelectionController.h" #include "Settings.h" +#include "SkANP.h" #include "SkTemplates.h" #include "SkTypes.h" #include "SkCanvas.h" #include "SkPicture.h" #include "SkUtils.h" +#include "SurfaceCallback.h" #include "StringImpl.h" #include "Text.h" #include "TypingCommand.h" @@ -92,6 +100,11 @@ #include "jni_utility.h" #include <wtf/CurrentTime.h> +#if USE(V8) +#include "CString.h" +#include "ScriptController.h" +#endif + #if DEBUG_NAV_UI #include "SkTime.h" #endif @@ -155,14 +168,18 @@ struct WebViewCore::JavaGlue { jmethodID m_jsUnload; jmethodID m_jsInterrupt; jmethodID m_didFirstLayout; - jmethodID m_sendMarkNodeInvalid; - jmethodID m_sendNotifyFocusSet; jmethodID m_sendNotifyProgressFinished; - jmethodID m_sendRecomputeFocus; jmethodID m_sendViewInvalidate; jmethodID m_updateTextfield; + jmethodID m_clearTextEntry; jmethodID m_restoreScale; jmethodID m_needTouchEvents; + jmethodID m_requestKeyboard; + jmethodID m_exceededDatabaseQuota; + jmethodID m_addMessageToConsole; + jmethodID m_createSurface; + jmethodID m_destroySurface; + jmethodID m_attachSurface; AutoJObject object(JNIEnv* env) { return getRealObject(env, m_obj); } @@ -180,9 +197,8 @@ static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], const } Mutex WebViewCore::gFrameCacheMutex; -Mutex WebViewCore::gFrameGenerationMutex; -Mutex WebViewCore::gRecomputeFocusMutex; Mutex WebViewCore::gButtonMutex; +Mutex WebViewCore::gCursorBoundsMutex; Mutex WebViewCore::m_contentMutex; WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* mainframe) @@ -191,7 +207,6 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_mainFrame = mainframe; m_popupReply = 0; - m_buildGeneration = 0; m_moveGeneration = 0; m_generation = 0; m_lastGeneration = 0; @@ -202,7 +217,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_maxYScroll = 240/4; m_textGeneration = 0; m_screenWidth = 320; - m_scale = 100; + m_scale = 1; LOG_ASSERT(m_mainFrame, "Uh oh, somehow a frameview was made without an initial frame!"); @@ -220,15 +235,19 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_javaGlue->m_jsPrompt = GetJMethod(env, clazz, "jsPrompt", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); m_javaGlue->m_jsUnload = GetJMethod(env, clazz, "jsUnload", "(Ljava/lang/String;Ljava/lang/String;)Z"); m_javaGlue->m_jsInterrupt = GetJMethod(env, clazz, "jsInterrupt", "()Z"); - m_javaGlue->m_didFirstLayout = GetJMethod(env, clazz, "didFirstLayout", "()V"); - m_javaGlue->m_sendMarkNodeInvalid = GetJMethod(env, clazz, "sendMarkNodeInvalid", "(I)V"); - m_javaGlue->m_sendNotifyFocusSet = GetJMethod(env, clazz, "sendNotifyFocusSet", "()V"); + m_javaGlue->m_didFirstLayout = GetJMethod(env, clazz, "didFirstLayout", "(Z)V"); m_javaGlue->m_sendNotifyProgressFinished = GetJMethod(env, clazz, "sendNotifyProgressFinished", "()V"); - m_javaGlue->m_sendRecomputeFocus = GetJMethod(env, clazz, "sendRecomputeFocus", "()V"); m_javaGlue->m_sendViewInvalidate = GetJMethod(env, clazz, "sendViewInvalidate", "(IIII)V"); m_javaGlue->m_updateTextfield = GetJMethod(env, clazz, "updateTextfield", "(IZLjava/lang/String;I)V"); + m_javaGlue->m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "()V"); m_javaGlue->m_restoreScale = GetJMethod(env, clazz, "restoreScale", "(I)V"); m_javaGlue->m_needTouchEvents = GetJMethod(env, clazz, "needTouchEvents", "(Z)V"); + m_javaGlue->m_requestKeyboard = GetJMethod(env, clazz, "requestKeyboard", "(Z)V"); + m_javaGlue->m_exceededDatabaseQuota = GetJMethod(env, clazz, "exceededDatabaseQuota", "(Ljava/lang/String;Ljava/lang/String;J)V"); + m_javaGlue->m_addMessageToConsole = GetJMethod(env, clazz, "addMessageToConsole", "(Ljava/lang/String;ILjava/lang/String;)V"); + m_javaGlue->m_createSurface = GetJMethod(env, clazz, "createSurface", "(I)Landroid/view/SurfaceView;"); + m_javaGlue->m_destroySurface = GetJMethod(env, clazz, "destroySurface", "(Landroid/view/SurfaceView;)V"); + m_javaGlue->m_attachSurface = GetJMethod(env, clazz, "attachSurface", "(Landroid/view/SurfaceView;IIII)V"); env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this); @@ -260,6 +279,8 @@ WebViewCore* WebViewCore::getWebViewCore(const WebCore::FrameView* view) WebViewCore* WebViewCore::getWebViewCore(const WebCore::ScrollView* view) { WebFrameView* webFrameView = static_cast<WebFrameView*>(view->platformWidget()); + if (!webFrameView) + return 0; return webFrameView->webViewCore(); } @@ -280,16 +301,22 @@ void WebViewCore::reset(bool fromConstructor) m_lastFocused = 0; m_lastFocusedBounds = WebCore::IntRect(0,0,0,0); + m_lastMoveGeneration = 0; clearContent(); m_updatedFrameCache = true; m_frameCacheOutOfDate = true; - m_blockFocusChange = false; m_snapAnchorNode = 0; - m_useReplay = false; m_skipContentDraw = false; m_findIsUp = false; m_domtree_version = 0; m_check_domtree_version = true; + m_progressDone = false; + m_hasCursorBounds = false; + + m_scrollOffsetX = 0; + m_scrollOffsetY = 0; + m_screenWidth = 0; + m_screenHeight = 0; } static bool layoutIfNeededRecursive(WebCore::Frame* f) @@ -303,7 +330,7 @@ static bool layoutIfNeededRecursive(WebCore::Frame* f) if (v->needsLayout()) v->layout(f->tree()->parent()); - + WebCore::Frame* child = f->tree()->firstChild(); bool success = true; while (child) { @@ -314,6 +341,16 @@ static bool layoutIfNeededRecursive(WebCore::Frame* f) return success && !v->needsLayout(); } +CacheBuilder& WebViewCore::cacheBuilder() +{ + return FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder(); +} + +WebCore::Node* WebViewCore::currentFocus() +{ + return cacheBuilder().currentFocus(); +} + void WebViewCore::recordPicture(SkPicture* picture) { // if there is no document yet, just return @@ -374,6 +411,71 @@ void WebViewCore::recordPictureSet(PictureSet* content) WebCore::FrameView* view = m_mainFrame->view(); int width = view->contentsWidth(); int height = view->contentsHeight(); + + // Use the contents width and height as a starting point. + SkIRect contentRect; + contentRect.set(0, 0, width, height); + SkIRect total(contentRect); + + // Traverse all the frames and add their sizes if they are in the visible + // rectangle. + for (WebCore::Frame* frame = m_mainFrame->tree()->traverseNext(); frame; + frame = frame->tree()->traverseNext()) { + // If the frame doesn't have an owner then it is the top frame and the + // view size is the frame size. + WebCore::RenderPart* owner = frame->ownerRenderer(); + if (owner) { + int x = owner->x(); + int y = owner->y(); + + // Traverse the tree up to the parent to find the absolute position + // of this frame. + WebCore::Frame* parent = frame->tree()->parent(); + while (parent) { + WebCore::RenderPart* parentOwner = parent->ownerRenderer(); + if (parentOwner) { + x += parentOwner->x(); + y += parentOwner->y(); + } + parent = parent->tree()->parent(); + } + // Use the owner dimensions so that padding and border are + // included. + int right = x + owner->width(); + int bottom = y + owner->height(); + SkIRect frameRect = {x, y, right, bottom}; + // Ignore a width or height that is smaller than 1. Some iframes + // have small dimensions in order to be hidden. The iframe + // expansion code does not expand in that case so we should ignore + // them here. + if (frameRect.width() > 1 && frameRect.height() > 1 + && SkIRect::Intersects(total, frameRect)) + total.join(x, y, right, bottom); + } + } + + // If the new total is larger than the content, resize the view to include + // all the content. + if (!contentRect.contains(total)) { + // Resize the view to change the overflow clip. + view->resize(total.fRight, total.fBottom); + + // We have to force a layout in order for the clip to change. + m_mainFrame->contentRenderer()->setNeedsLayoutAndPrefWidthsRecalc(); + view->forceLayout(); + + // Relayout similar to above + m_skipContentDraw = true; + bool success = layoutIfNeededRecursive(m_mainFrame); + m_skipContentDraw = false; + if (!success) + return; + + // Set the computed content width + width = view->contentsWidth(); + height = view->contentsHeight(); + } + content->checkDimensions(width, height, &m_addInval); // The inval region may replace existing pictures. The existing pictures @@ -395,33 +497,38 @@ void WebViewCore::recordPictureSet(PictureSet* content) if (content->build()) rebuildPictureSet(content); } // WebViewCoreRecordTimeCounter - CacheBuilder& builder = FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder(); - WebCore::Node* oldFocusNode = builder.currentFocus(); + WebCore::Node* oldFocusNode = currentFocus(); m_frameCacheOutOfDate = true; WebCore::IntRect oldBounds = oldFocusNode ? oldFocusNode->getRect() : WebCore::IntRect(0,0,0,0); - DBG_NAV_LOGD("m_lastFocused=%p oldFocusNode=%p" - " m_lastFocusedBounds={%d,%d,%d,%d} oldBounds={%d,%d,%d,%d}", - m_lastFocused, oldFocusNode, - m_lastFocusedBounds.x(), m_lastFocusedBounds.y(), m_lastFocusedBounds.width(), m_lastFocusedBounds.height(), - oldBounds.x(), oldBounds.y(), oldBounds.width(), oldBounds.height()); unsigned latestVersion = 0; if (m_check_domtree_version) { - // as domTreeVersion only increment, we can just check the sum to see + // as domTreeVersion only increment, we can just check the sum to see // whether we need to update the frame cache for (Frame* frame = m_mainFrame; frame; frame = frame->tree()->traverseNext()) { latestVersion += frame->document()->domTreeVersion(); } } - if (m_lastFocused != oldFocusNode || m_lastFocusedBounds != oldBounds || m_findIsUp - || (m_check_domtree_version && latestVersion != m_domtree_version)) { - m_lastFocused = oldFocusNode; - m_lastFocusedBounds = oldBounds; - DBG_NAV_LOGD("call updateFrameCache m_domtree_version=%d latest=%d", - m_domtree_version, latestVersion); - m_domtree_version = latestVersion; - updateFrameCache(); + DBG_NAV_LOGD("m_lastFocused=%p oldFocusNode=%p" + " m_lastFocusedBounds={%d,%d,%d,%d} oldBounds={%d,%d,%d,%d}" + " m_check_domtree_version=%s latestVersion=%d m_domtree_version=%d", + m_lastFocused, oldFocusNode, + m_lastFocusedBounds.x(), m_lastFocusedBounds.y(), + m_lastFocusedBounds.width(), m_lastFocusedBounds.height(), + oldBounds.x(), oldBounds.y(), oldBounds.width(), oldBounds.height(), + m_check_domtree_version ? "true" : "false", + latestVersion, m_domtree_version); + if (m_lastFocused == oldFocusNode && m_lastFocusedBounds == oldBounds + && !m_findIsUp + && (!m_check_domtree_version || latestVersion == m_domtree_version)) + { + return; } + m_lastFocused = oldFocusNode; + m_lastFocusedBounds = oldBounds; + m_domtree_version = latestVersion; + DBG_NAV_LOG("call updateFrameCache"); + updateFrameCache(); } void WebViewCore::updateButtonList(WTF::Vector<Container>* buttons) @@ -477,7 +584,7 @@ void WebViewCore::copyContentToPicture(SkPicture* picture) m_contentMutex.lock(); PictureSet copyContent = PictureSet(m_content); m_contentMutex.unlock(); - + int w = copyContent.width(); int h = copyContent.height(); copyContent.draw(picture->beginRecording(w, h, PICT_RECORD_FLAGS)); @@ -508,6 +615,18 @@ bool WebViewCore::drawContent(SkCanvas* canvas, SkColor color) return tookTooLong; } +bool WebViewCore::pictureReady() +{ + bool done; + m_contentMutex.lock(); + PictureSet copyContent = PictureSet(m_content); + done = m_progressDone; + m_contentMutex.unlock(); + DBG_NAV_LOGD("done=%s empty=%s", done ? "true" : "false", + copyContent.isEmpty() ? "true" : "false"); + return done || !copyContent.isEmpty(); +} + SkPicture* WebViewCore::rebuildPicture(const SkIRect& inval) { WebCore::FrameView* view = m_mainFrame->view(); @@ -558,12 +677,13 @@ void WebViewCore::rebuildPictureSet(PictureSet* pictureSet) bool WebViewCore::recordContent(SkRegion* region, SkIPoint* point) { DBG_SET_LOG("start"); + float progress = (float) m_mainFrame->page()->progress()->estimatedProgress(); m_contentMutex.lock(); PictureSet contentCopy(m_content); + m_progressDone = progress <= 0.0f || progress >= 1.0f; m_contentMutex.unlock(); recordPictureSet(&contentCopy); - float progress = (float) m_mainFrame->page()->progress()->estimatedProgress(); - if (progress > 0.0f && progress < 1.0f && contentCopy.isEmpty()) { + if (!m_progressDone && contentCopy.isEmpty()) { DBG_SET_LOGD("empty (progress=%g)", progress); return false; } @@ -609,22 +729,6 @@ void WebViewCore::scrollTo(int x, int y, bool animate) checkException(env); } -void WebViewCore::sendMarkNodeInvalid(WebCore::Node* node) -{ - LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); - JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_sendMarkNodeInvalid, (int) node); - checkException(env); -} - -void WebViewCore::sendNotifyFocusSet() -{ - LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); - JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_sendNotifyFocusSet); - checkException(env); -} - void WebViewCore::sendNotifyProgressFinished() { LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); @@ -633,16 +737,8 @@ void WebViewCore::sendNotifyProgressFinished() checkException(env); } -void WebViewCore::sendRecomputeFocus() -{ - LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); - JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_sendRecomputeFocus); - checkException(env); -} - void WebViewCore::viewInvalidate(const WebCore::IntRect& rect) -{ +{ LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); env->CallVoidMethod(m_javaGlue->object(env).get(), @@ -656,7 +752,7 @@ void WebViewCore::scrollBy(int dx, int dy, bool animate) if (!(dx | dy)) return; JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_scrollBy, + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_scrollBy, dx, dy, animate); checkException(env); } @@ -671,10 +767,8 @@ void WebViewCore::contentDraw() void WebViewCore::contentInvalidate(const WebCore::IntRect &r) { DBG_SET_LOGD("rect={%d,%d,w=%d,h=%d}", r.x(), r.y(), r.width(), r.height()); - SkIRect rect, max; - android_setrect(&rect, r); - max.set(0, 0, INT_MAX, INT_MAX); - if (!rect.intersect(max)) + SkIRect rect(r); + if (!rect.intersect(0, 0, INT_MAX, INT_MAX)) return; m_addInval.op(rect, SkRegion::kUnion_Op); DBG_SET_LOGD("m_addInval={%d,%d,r=%d,b=%d}", @@ -706,13 +800,17 @@ void WebViewCore::didFirstLayout() DEBUG_NAV_UI_LOGD("%s", __FUNCTION__); LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); - const WebCore::KURL& url = m_mainFrame->loader()->url(); + WebCore::FrameLoader* loader = m_mainFrame->loader(); + const WebCore::KURL& url = loader->url(); if (url.isEmpty()) return; LOGV("::WebCore:: didFirstLayout %s", url.string().ascii().data()); + WebCore::FrameLoadType loadType = loader->loadType(); + JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_didFirstLayout); + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_didFirstLayout, + loadType == WebCore::FrameLoadTypeStandard); checkException(env); DBG_NAV_LOG("call updateFrameCache"); @@ -743,9 +841,14 @@ void WebViewCore::needTouchEvents(bool need) #endif } -void WebViewCore::notifyFocusSet() +void WebViewCore::requestKeyboard(bool showKeyboard) { - sendNotifyFocusSet(); + DEBUG_NAV_UI_LOGD("%s", __FUNCTION__); + LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); + + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_requestKeyboard, showKeyboard); + checkException(env); } void WebViewCore::notifyProgressFinished() @@ -780,9 +883,10 @@ void WebViewCore::doMaxScroll(CacheBuilder::Direction dir) this->scrollBy(dx, dy, true); } -void WebViewCore::setScrollOffset(int dx, int dy) +void WebViewCore::setScrollOffset(int moveGeneration, int dx, int dy) { - DBG_NAV_LOGD("{%d,%d}", dx, dy); + DBG_NAV_LOGD("{%d,%d} m_scrollOffset=(%d,%d)", dx, dy, + m_scrollOffsetX, m_scrollOffsetY); if (m_scrollOffsetX != dx || m_scrollOffsetY != dy) { m_scrollOffsetX = dx; m_scrollOffsetY = dy; @@ -791,8 +895,19 @@ void WebViewCore::setScrollOffset(int dx, int dy) // testing work correctly. m_mainFrame->view()->platformWidget()->setLocation(m_scrollOffsetX, m_scrollOffsetY); - m_mainFrame->sendScrollEvent(); + m_mainFrame->eventHandler()->sendScrollEvent(); + + // update the currently visible screen + sendPluginVisibleScreen(); } + gCursorBoundsMutex.lock(); + bool hasCursorBounds = m_hasCursorBounds; + Frame* frame = (Frame*) m_cursorFrame; + IntPoint location = m_cursorLocation; + gCursorBoundsMutex.unlock(); + if (!hasCursorBounds) + return; + moveMouseIfLatest(moveGeneration, frame, location.x(), location.y()); } void WebViewCore::setGlobalBounds(int x, int y, int h, int v) @@ -801,23 +916,25 @@ void WebViewCore::setGlobalBounds(int x, int y, int h, int v) m_mainFrame->view()->platformWidget()->setWindowBounds(x, y, h, v); } -void WebViewCore::setSizeScreenWidthAndScale(int width, int height, - int screenWidth, int scale, int realScreenWidth, int screenHeight) +void WebViewCore::setSizeScreenWidthAndScale(int width, int height, + int screenWidth, float scale, int realScreenWidth, int screenHeight) { WebCoreViewBridge* window = m_mainFrame->view()->platformWidget(); int ow = window->width(); int oh = window->height(); window->setSize(width, height); int osw = m_screenWidth; - DBG_NAV_LOGD("old:(w=%d,h=%d,sw=%d,scale=%d) new:(w=%d,h=%d,sw=%d,scale=%d)", + DBG_NAV_LOGD("old:(w=%d,h=%d,sw=%d,scale=%d) new:(w=%d,h=%d,sw=%d,scale=%g)", ow, oh, osw, m_scale, width, height, screenWidth, scale); m_screenWidth = screenWidth; - m_scale = scale; + m_screenHeight = screenHeight; + if (scale >= 0) // negative means ignore + m_scale = scale; m_maxXScroll = screenWidth >> 2; m_maxYScroll = (screenWidth * height / width) >> 2; if (ow != width || oh != height || osw != screenWidth) { WebCore::RenderObject *r = m_mainFrame->contentRenderer(); - DBG_NAV_LOGD("renderer=%p view=(w=%d,h=%d)", r, + DBG_NAV_LOGD("renderer=%p view=(w=%d,h=%d)", r, realScreenWidth, screenHeight); if (r) { // get current screen center position @@ -836,7 +953,7 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height, offset = WebCore::IntPoint(screenCenter.x() - bounds.x(), screenCenter.y() - bounds.y()); if (offset.x() < 0 || offset.x() > realScreenWidth || - offset.y() < 0 || offset.y() > screenHeight) + offset.y() < 0 || offset.y() > screenHeight) { DBG_NAV_LOGD("offset out of bounds:(x=%d,y=%d)", offset.x(), offset.y()); @@ -844,18 +961,21 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height, } } r->setNeedsLayoutAndPrefWidthsRecalc(); - m_mainFrame->forceLayout(); + m_mainFrame->view()->forceLayout(); // scroll to restore current screen center if (!node) return; const WebCore::IntRect& newBounds = node->getRect(); DBG_NAV_LOGD("nb:(x=%d,y=%d,w=%d," - "h=%d,ns=%d)", newBounds.x(), newBounds.y(), + "h=%d,ns=%d)", newBounds.x(), newBounds.y(), newBounds.width(), newBounds.height()); scrollBy(newBounds.x() - bounds.x(), newBounds.y() - bounds.y(), false); } } + + // update the currently visible screen + sendPluginVisibleScreen(); } void WebViewCore::dumpDomTree(bool useFile) @@ -901,14 +1021,13 @@ void WebViewCore::dumpRenderTree(bool useFile) void WebViewCore::dumpNavTree() { #if DUMP_NAV_CACHE - FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder().mDebug.print(); + cacheBuilder().mDebug.print(); #endif } WebCore::String WebViewCore::retrieveHref(WebCore::Frame* frame, WebCore::Node* node) { - CacheBuilder& builder = FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder(); - if (!builder.validNode(frame, node)) + if (!CacheBuilder::validNode(m_mainFrame, frame, node)) return WebCore::String(); if (!node->hasTagName(WebCore::HTMLNames::aTag)) return WebCore::String(); @@ -916,24 +1035,50 @@ WebCore::String WebViewCore::retrieveHref(WebCore::Frame* frame, WebCore::Node* return anchor->href(); } -bool WebViewCore::prepareFrameCache() +void WebViewCore::updateCacheOnNodeChange() +{ + gCursorBoundsMutex.lock(); + bool hasCursorBounds = m_hasCursorBounds; + Frame* frame = (Frame*) m_cursorFrame; + Node* node = (Node*) m_cursorNode; + IntRect bounds = m_cursorHitBounds; + gCursorBoundsMutex.unlock(); + if (!hasCursorBounds || !node) + return; + if (CacheBuilder::validNode(m_mainFrame, frame, node)) { + RenderObject* renderer = node->renderer(); + if (renderer) { + IntRect absBox = renderer->absoluteBoundingBoxRect(); + int globalX, globalY; + CacheBuilder::GetGlobalOffset(frame, &globalX, &globalY); + absBox.move(globalX, globalY); + if (absBox == bounds) + return; + DBG_NAV_LOGD("absBox=(%d,%d,%d,%d) bounds=(%d,%d,%d,%d)", + absBox.x(), absBox.y(), absBox.width(), absBox.height(), + bounds.x(), bounds.y(), bounds.width(), bounds.height()); + } + } + DBG_NAV_LOGD("updateFrameCache node=%p", node); + updateFrameCache(); +} + +void WebViewCore::updateFrameCache() { if (!m_frameCacheOutOfDate) { DBG_NAV_LOG("!m_frameCacheOutOfDate"); - return false; + return; } #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreBuildNavTimeCounter); #endif m_frameCacheOutOfDate = false; #if DEBUG_NAV_UI - DBG_NAV_LOG("m_frameCacheOutOfDate was true"); m_now = SkTime::GetMSecs(); #endif m_temp = new CachedRoot(); m_temp->init(m_mainFrame, &m_history); - m_temp->setGeneration(++m_buildGeneration); - CacheBuilder& builder = FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder(); + CacheBuilder& builder = cacheBuilder(); WebCore::Settings* settings = m_mainFrame->page()->settings(); builder.allowAllTextDetection(); #ifdef ANDROID_META_SUPPORT @@ -951,15 +1096,9 @@ bool WebViewCore::prepareFrameCache() recordPicture(m_tempPict); m_temp->setPicture(m_tempPict); m_temp->setTextGeneration(m_textGeneration); - return true; -} - -void WebViewCore::releaseFrameCache(bool newCache) -{ - if (!newCache) { - DBG_NAV_LOG("!newCache"); - return; - } + WebCoreViewBridge* window = m_mainFrame->view()->platformWidget(); + m_temp->setVisibleRect(WebCore::IntRect(m_scrollOffsetX, + m_scrollOffsetY, window->width(), window->height())); gFrameCacheMutex.lock(); delete m_frameCacheKit; delete m_navPictureKit; @@ -973,70 +1112,6 @@ void WebViewCore::releaseFrameCache(bool newCache) cachedFocusNode ? cachedFocusNode->nodePointer() : 0); #endif gFrameCacheMutex.unlock(); - notifyFocusSet(); - // it's tempting to send an invalidate here, but it's a bad idea - // the cache is now up to date, but the focus is not -- the event - // may need to be recomputed from the prior history. An invalidate - // will draw the stale location causing the ring to flash at the wrong place. -} - -void WebViewCore::updateFrameCache() -{ - m_useReplay = false; - releaseFrameCache(prepareFrameCache()); -} - -void WebViewCore::removeFrameGeneration(WebCore::Frame* frame) -{ - DBG_NAV_LOGD("frame=%p m_generation=%d", frame, m_generation); - gFrameGenerationMutex.lock(); - int last = m_frameGenerations.size() - 1; - for (int index = 0; index <= last; index++) { - if (m_frameGenerations[index].m_frame == frame) { - DBG_NAV_LOGD("index=%d last=%d", index, last); - if (index != last) - m_frameGenerations[index] = m_frameGenerations[last]; - m_frameGenerations.removeLast(); - break; - } - } - gFrameGenerationMutex.unlock(); -} - -void WebViewCore::updateFrameGeneration(WebCore::Frame* frame) -{ - DBG_NAV_LOGD("frame=%p m_generation=%d", frame, m_generation); - gFrameGenerationMutex.lock(); - ++m_buildGeneration; - for (size_t index = 0; index < m_frameGenerations.size(); index++) { - if (m_frameGenerations[index].m_frame == frame) { - DBG_NAV_LOG("replace"); - m_frameGenerations[index].m_generation = m_buildGeneration; - goto done; - } - } - { - FrameGen frameGen = {frame, m_buildGeneration}; - m_frameGenerations.append(frameGen); - DBG_NAV_LOG("append"); - } -done: - gFrameGenerationMutex.unlock(); -} - -int WebViewCore::retrieveFrameGeneration(WebCore::Frame* frame) -{ - int result = INT_MAX; - gFrameGenerationMutex.lock(); - for (size_t index = 0; index < m_frameGenerations.size(); index++) { - if (m_frameGenerations[index].m_frame == frame) { - result = m_frameGenerations[index].m_generation; - break; - } - } - gFrameGenerationMutex.unlock(); - DBG_NAV_LOGD("frame=%p m_generation=%d result=%d", frame, m_generation, result); - return result; } /////////////////////////////////////////////////////////////////////////////// @@ -1060,7 +1135,7 @@ void WebViewCore::removePlugin(PluginWidgetAndroid* w) void WebViewCore::invalPlugin(PluginWidgetAndroid* w) { - const double PLUGIN_INVAL_DELAY = 0; // should this be non-zero? + const double PLUGIN_INVAL_DELAY = 1.0 / 60; if (!m_pluginInvalTimer.isActive()) { m_pluginInvalTimer.startOneShot(PLUGIN_INVAL_DELAY); @@ -1092,89 +1167,113 @@ void WebViewCore::drawPlugins() } } -/////////////////////////////////////////////////////////////////////////////// +void WebViewCore::sendPluginVisibleScreen() +{ + ANPRectI visibleRect; + visibleRect.left = m_scrollOffsetX; + visibleRect.top = m_scrollOffsetY; + visibleRect.right = m_scrollOffsetX + m_screenWidth; + visibleRect.bottom = m_scrollOffsetY + m_screenHeight; + + PluginWidgetAndroid** iter = m_plugins.begin(); + PluginWidgetAndroid** stop = m_plugins.end(); + for (; iter < stop; ++iter) { + (*iter)->setVisibleScreen(visibleRect, m_scale); + } +} + +void WebViewCore::sendPluginEvent(const ANPEvent& evt, ANPEventFlag flag) +{ + PluginWidgetAndroid** iter = m_plugins.begin(); + PluginWidgetAndroid** stop = m_plugins.end(); + for (; iter < stop; ++iter) { + if((*iter)->isAcceptingEvent(flag)) + (*iter)->sendEvent(evt); + } +} -void WebViewCore::setFinalFocus(WebCore::Frame* frame, WebCore::Node* node, - int x, int y, bool block) +void WebViewCore::sendPluginEvent(const ANPEvent& evt) { - DBG_NAV_LOGD("frame=%p node=%p x=%d y=%d", frame, node, x, y); - bool result = finalKitFocus(frame, node, x, y, false); - if (block) { - m_blockFocusChange = true; - if (!result && node) - touchUp(m_touchGeneration, 0, 0, 0, x, y, 0, true, true); + PluginWidgetAndroid** iter = m_plugins.begin(); + PluginWidgetAndroid** stop = m_plugins.end(); + for (; iter < stop; ++iter) { + (*iter)->sendEvent(evt); + } +} + +static PluginView* nodeIsPlugin(Node* node) { + RenderObject* renderer = node->renderer(); + if (renderer && renderer->isWidget()) { + Widget* widget = static_cast<RenderWidget*>(renderer)->widget(); + if (widget && widget->isPluginView()) + return static_cast<PluginView*>(widget); + } + return 0; +} + +Node* WebViewCore::cursorNodeIsPlugin() { + gCursorBoundsMutex.lock(); + bool hasCursorBounds = m_hasCursorBounds; + Frame* frame = (Frame*) m_cursorFrame; + Node* node = (Node*) m_cursorNode; + gCursorBoundsMutex.unlock(); + if (hasCursorBounds && CacheBuilder::validNode(m_mainFrame, frame, node) + && nodeIsPlugin(node)) { + return node; } + return 0; +} + + +void WebViewCore::updatePluginState(Frame* frame, Node* node, PluginState state) { + + // check that the node and frame pointers are (still) valid + if (!frame || !node || !CacheBuilder::validNode(m_mainFrame, frame, node)) + return; + + // check that the node is a plugin view + PluginView* pluginView = nodeIsPlugin(node); + if (!pluginView) + return; + + // create the event + ANPEvent event; + SkANP::InitEvent(&event, kLifecycle_ANPEventType); + + if (state == kLoseFocus_PluginState) + event.data.lifecycle.action = kLoseFocus_ANPLifecycleAction; + else if (state == kGainFocus_PluginState) + event.data.lifecycle.action = kGainFocus_ANPLifecycleAction; + else + return; + + // send the event + pluginView->platformPluginWidget()->sendEvent(event); } -void WebViewCore::setKitFocus(int moveGeneration, int buildGeneration, - WebCore::Frame* frame, WebCore::Node* node, int x, int y, - bool ignoreNullFocus) +/////////////////////////////////////////////////////////////////////////////// +void WebViewCore::moveMouseIfLatest(int moveGeneration, + WebCore::Frame* frame, int x, int y) { DBG_NAV_LOGD("m_moveGeneration=%d moveGeneration=%d" - " buildGeneration=%d frame=%p node=%p x=%d y=%d", - m_moveGeneration, moveGeneration, buildGeneration, frame, node, x, y); - if (m_blockFocusChange) { - DBG_NAV_LOG("m_blockFocusChange"); - return; - } + " frame=%p x=%d y=%d", + m_moveGeneration, moveGeneration, frame, x, y); if (m_moveGeneration > moveGeneration) { DBG_NAV_LOGD("m_moveGeneration=%d > moveGeneration=%d", m_moveGeneration, moveGeneration); return; // short-circuit if a newer move has already been generated } - if (!commonKitFocus(moveGeneration, buildGeneration, frame, node, x, y, - ignoreNullFocus)) - return; m_lastGeneration = moveGeneration; -} - -bool WebViewCore::commonKitFocus(int generation, int buildGeneration, - WebCore::Frame* frame, WebCore::Node* node, int x, int y, - bool ignoreNullFocus) -{ - DBG_NAV_LOGD("generation=%d buildGeneration=%d frame=%p" - " node=%p x=%d y=%d", generation, buildGeneration, frame, node, x, y); - m_useReplay = true; - bool newCache = prepareFrameCache(); // must wait for possible recompute before using - if (m_moveGeneration > generation) { - DBG_NAV_LOGD("m_moveGeneration=%d > generation=%d", - m_moveGeneration, generation); - releaseFrameCache(newCache); - return false; // short-circuit if a newer move has already been generated - } - // if the nav cache has been rebuilt since this focus request was generated, - // send a request back to the UI side to recompute the kit-side focus - if (m_buildGeneration > buildGeneration || (node && !FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder().validNode(frame, node))) { - DBG_NAV_LOGD("m_buildGeneration=%d > buildGeneration=%d", - m_buildGeneration, buildGeneration); - gRecomputeFocusMutex.lock(); - bool first = !m_recomputeEvents.size(); - m_recomputeEvents.append(generation); - gRecomputeFocusMutex.unlock(); - releaseFrameCache(newCache); - if (first) - sendRecomputeFocus(); - return false; - } - releaseFrameCache(newCache); - if (!node && ignoreNullFocus) - return true; - finalKitFocus(frame, node, x, y, false); - return true; + moveMouse(frame, x, y); } // Update mouse position and may change focused node. -// If donotChangeDOMFocus is true, the function does not changed focused node -// in the DOM tree. Changing the focus in DOM may trigger onblur event -// handler on the current focused node before firing mouse up and down events. -bool WebViewCore::finalKitFocus(WebCore::Frame* frame, WebCore::Node* node, - int x, int y, bool donotChangeDOMFocus) -{ - CacheBuilder& builder = FrameLoaderClientAndroid:: - get(m_mainFrame)->getCacheBuilder(); - if (!frame || builder.validNode(frame, NULL) == false) +void WebViewCore::moveMouse(WebCore::Frame* frame, int x, int y) +{ + DBG_NAV_LOGD("frame=%p x=%d y=%d scrollOffset=(%d,%d)", frame, + x, y, m_scrollOffsetX, m_scrollOffsetY); + if (!frame || CacheBuilder::validNode(m_mainFrame, frame, NULL) == false) frame = m_mainFrame; - WebCore::Node* oldFocusNode = builder.currentFocus(); // mouse event expects the position in the window coordinate m_mousePos = WebCore::IntPoint(x - m_scrollOffsetX, y - m_scrollOffsetY); // validNode will still return true if the node is null, as long as we have @@ -1183,86 +1282,7 @@ bool WebViewCore::finalKitFocus(WebCore::Frame* frame, WebCore::Node* node, WebCore::NoButton, WebCore::MouseEventMoved, 1, false, false, false, false, WTF::currentTime()); frame->eventHandler()->handleMouseMoveEvent(mouseEvent); - bool valid = builder.validNode(frame, node); - if (!donotChangeDOMFocus) { - WebCore::Document* oldDoc = oldFocusNode ? oldFocusNode->document() : 0; - if (!node) { - if (oldFocusNode) - oldDoc->setFocusedNode(0); - return false; - } else if (!valid) { - DBG_NAV_LOGD("sendMarkNodeInvalid node=%p", node); - sendMarkNodeInvalid(node); - if (oldFocusNode) - oldDoc->setFocusedNode(0); - return false; - } - // If we jump frames (docs), kill the focus on the old doc - if (oldFocusNode && node->document() != oldDoc) { - oldDoc->setFocusedNode(0); - } - if (!node->isTextNode()) - static_cast<WebCore::Element*>(node)->focus(false); - if (node->document()->focusedNode() != node) { - // This happens when Element::focus() fails as we may try to set the - // focus to a node which WebCore doesn't recognize as a focusable node. - // So we need to do some extra work, as it does in Element::focus(), - // besides calling Document::setFocusedNode. - if (oldFocusNode) { - // copied from clearSelectionIfNeeded in FocusController.cpp - WebCore::SelectionController* s = oldDoc->frame()->selection(); - if (!s->isNone()) - s->clear(); - } - //setFocus on things that WebCore doesn't recognize as supporting focus - //for instance, if there is an onclick element that does not support focus - node->document()->setFocusedNode(node); - } - } else { // !donotChangeDOMFocus - if (!node || !valid) - return false; - } - - DBG_NAV_LOGD("setFocusedNode node=%p", node); - builder.setLastFocus(node); - m_lastFocused = node; - m_lastFocusedBounds = node->getRect(); - return true; -} - -// helper function to find the frame that has focus -static WebCore::Frame* FocusedFrame(WebCore::Frame* frame) -{ - if (!frame) - return 0; - WebCore::Node* focusNode = FrameLoaderClientAndroid::get(frame)->getCacheBuilder().currentFocus(); - if (!focusNode) - return 0; - WebCore::Document* doc = focusNode->document(); - if (!doc) - return 0; - return doc->frame(); -} - -static WebCore::RenderTextControl* FocusedTextControl(WebCore::Frame* frame) -{ - WebCore::Node* focusNode = FrameLoaderClientAndroid::get(frame)->getCacheBuilder().currentFocus(); - WebCore::RenderObject* renderer = focusNode->renderer(); - if (renderer && (renderer->isTextField() || renderer->isTextArea())) { - return static_cast<WebCore::RenderTextControl*>(renderer); - } - return 0; -} - -WebCore::Frame* WebViewCore::changedKitFocus(WebCore::Frame* frame, - WebCore::Node* node, int x, int y) -{ - if (!frame || !node) - return m_mainFrame; - WebCore::Node* current = FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder().currentFocus(); - if (current == node) - return frame; - return finalKitFocus(frame, node, x, y, false) ? frame : m_mainFrame; + updateCacheOnNodeChange(); } static int findTextBoxIndex(WebCore::Node* node, const WebCore::IntPoint& pt) @@ -1300,7 +1320,7 @@ static int findTextBoxIndex(WebCore::Node* node, const WebCore::IntPoint& pt) "offset=%d pt.x=%d globalX=%d renderX=%d x=%d " "textBox->x()=%d textBox->start()=%d prior=%d current=%d next=%d", offset, pt.x(), globalX, absPt.x(), x, - textBox->xPos(), textBox->start(), prior, current, next + textBox->x(), textBox->start(), prior, current, next ); #endif return textBox->start() + offset; @@ -1420,114 +1440,91 @@ WebCore::String WebViewCore::getSelection(SkRegion* selRgn) return result; } -static void selectInFrame(WebCore::Frame* frame, int start, int end) +void WebViewCore::setSelection(int start, int end) { - WebCore::Document* doc = frame->document(); - if (!doc) - return; - - WebCore::Node* focus = doc->focusedNode(); + WebCore::Node* focus = currentFocus(); if (!focus) return; - WebCore::RenderObject* renderer = focus->renderer(); - if (renderer && (renderer->isTextField() || renderer->isTextArea())) { - WebCore::RenderTextControl* rtc = static_cast<WebCore::RenderTextControl*>(renderer); - if (start > end) { - int temp = start; - start = end; - end = temp; - } - rtc->setSelectionRange(start, end); - frame->revealSelection(); + if (!renderer || (!renderer->isTextField() && !renderer->isTextArea())) + return; + WebCore::RenderTextControl* rtc = static_cast<WebCore::RenderTextControl*>(renderer); + if (start > end) { + int temp = start; + start = end; + end = temp; } + rtc->setSelectionRange(start, end); + focus->document()->frame()->revealSelection(); + setFocusControllerActive(true); } -WebCore::Frame* WebViewCore::setSelection(WebCore::Frame* frame, WebCore::Node* node, - int x, int y, int start, int end) -{ - // FIXME: Consider using a generation number to avoid doing this many more times than necessary. - frame = changedKitFocus(frame, node, x, y); - if (!frame) - return 0; - selectInFrame(frame, start, end); - return frame; -} - -// Shortcut for no modifier keys -#define NO_MODIFIER_KEYS (static_cast<WebCore::PlatformKeyboardEvent::ModifierKey>(0)) - -WebCore::Frame* WebViewCore::deleteSelection(WebCore::Frame* frame, WebCore::Node* node, - int x, int y, int start, int end) +void WebViewCore::deleteSelection(int start, int end, int textGeneration) { - frame = setSelection(frame, node, x, y, start, end); - if (start != end) { - WebCore::PlatformKeyboardEvent downEvent(kKeyCodeDel, WebCore::VK_BACK, - WebCore::PlatformKeyboardEvent::KeyDown, 0, NO_MODIFIER_KEYS); - frame->eventHandler()->keyEvent(downEvent); - WebCore::PlatformKeyboardEvent upEvent(kKeyCodeDel, WebCore::VK_BACK, - WebCore::PlatformKeyboardEvent::KeyUp, 0, NO_MODIFIER_KEYS); - frame->eventHandler()->keyEvent(upEvent); - } - return frame; + setSelection(start, end); + if (start == end) + return; + WebCore::Node* focus = currentFocus(); + if (!focus) + return; + WebCore::TypingCommand::deleteSelection(focus->document()); + m_textGeneration = textGeneration; } -void WebViewCore::replaceTextfieldText(WebCore::Frame* frame, WebCore::Node* node, int x, int y, - int oldStart, int oldEnd, jstring replace, int start, int end) +void WebViewCore::replaceTextfieldText(int oldStart, + int oldEnd, const WebCore::String& replace, int start, int end, + int textGeneration) { - JNIEnv* env = JSC::Bindings::getJNIEnv(); - - WebCore::String webcoreString = to_string(env, replace); - frame = setSelection(frame, node, x, y, oldStart, oldEnd); - WebCore::TypingCommand::insertText(frame->document(), webcoreString, false); - selectInFrame(frame, start, end); + WebCore::Node* focus = currentFocus(); + if (!focus) + return; + setSelection(oldStart, oldEnd); + WebCore::TypingCommand::insertText(focus->document(), replace, + false); + setSelection(start, end); + m_textGeneration = textGeneration; } -void WebViewCore::passToJs(WebCore::Frame* frame, WebCore::Node* node, int x, int y, int generation, - jstring currentText, int keyCode, int keyValue, bool down, bool cap, bool fn, bool sym) +void WebViewCore::passToJs(int generation, const WebCore::String& current, + const PlatformKeyboardEvent& event) { - frame = changedKitFocus(frame, node, x, y); - // Construct the ModifierKey value - int mods = 0; - if (cap) { - mods |= WebCore::PlatformKeyboardEvent::ShiftKey; - } - if (fn) { - mods |= WebCore::PlatformKeyboardEvent::AltKey; + WebCore::Node* focus = currentFocus(); + if (!focus) { + DBG_NAV_LOG("!focus"); + clearTextEntry(); + return; } - if (sym) { - mods |= WebCore::PlatformKeyboardEvent::CtrlKey; + WebCore::RenderObject* renderer = focus->renderer(); + if (!renderer || (!renderer->isTextField() && !renderer->isTextArea())) { + DBG_NAV_LOGD("renderer==%p || not text", renderer); + clearTextEntry(); + return; } - WebCore::PlatformKeyboardEvent event(keyCode, keyValue, - down ? WebCore::PlatformKeyboardEvent::KeyDown : - WebCore::PlatformKeyboardEvent::KeyUp, - 0, static_cast<WebCore::PlatformKeyboardEvent::ModifierKey>(mods)); // Block text field updates during a key press. m_blockTextfieldUpdates = true; - frame->eventHandler()->keyEvent(event); + key(event); m_blockTextfieldUpdates = false; m_textGeneration = generation; - - WebCore::Node* currentFocus = FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder().currentFocus(); - // Make sure we have the same focus and it is a text field. - if (node == currentFocus && currentFocus) { - WebCore::RenderObject* renderer = currentFocus->renderer(); - if (renderer && (renderer->isTextField() || renderer->isTextArea())) { - WebCore::RenderTextControl* renderText = static_cast<WebCore::RenderTextControl*>(renderer); - JNIEnv* env = JSC::Bindings::getJNIEnv(); - WebCore::String current = to_string(env, currentText); - WebCore::String test = renderText->text(); - // If the text changed during the key event, update the UI text field. - if (test != current) - updateTextfield(currentFocus, false, test); - } + setFocusControllerActive(true); + WebCore::RenderTextControl* renderText = + static_cast<WebCore::RenderTextControl*>(renderer); + WebCore::String test = renderText->text(); + if (test == current) { + DBG_NAV_LOG("test == current"); + return; } + // If the text changed during the key event, update the UI text field. + updateTextfield(focus, false, test); +} + +void WebViewCore::setFocusControllerActive(bool active) +{ + m_mainFrame->page()->focusController()->setActive(active); } void WebViewCore::saveDocumentState(WebCore::Frame* frame) { - if (!FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder() - .validNode(frame, 0)) + if (!CacheBuilder::validNode(m_mainFrame, frame, 0)) frame = m_mainFrame; WebCore::HistoryItem *item = frame->loader()->currentHistoryItem(); @@ -1568,45 +1565,57 @@ public: // Special value for cancel. Do nothing. return; } - // If the select element no longer exists, do to a page change, etc, silently return. - if (!m_select || !FrameLoaderClientAndroid::get(m_viewImpl->m_mainFrame)->getCacheBuilder().validNode(m_frame, m_select)) - return; - if (-1 == index) { - if (m_select->selectedIndex() != -1) { -#ifdef ANDROID_DESELECT_SELECT - m_select->deselectItems(); -#endif - m_select->onChange(); - m_viewImpl->contentInvalidate(m_select->getRect()); - } + // If the select element no longer exists, due to a page change, etc, + // silently return. + if (!m_select || !CacheBuilder::validNode(m_viewImpl->m_mainFrame, + m_frame, m_select)) return; - } - WebCore::HTMLOptionElement* option = static_cast<WebCore::HTMLOptionElement*>( - m_select->item(m_select->listToOptionIndex(index))); - if (!option->selected()) { - option->setSelected(true); - m_select->onChange(); - m_viewImpl->contentInvalidate(m_select->getRect()); - } + // Use a pointer to HTMLSelectElement's superclass, where + // listToOptionIndex is public. + SelectElement* selectElement = m_select; + int optionIndex = selectElement->listToOptionIndex(index); + m_select->setSelectedIndex(optionIndex, true, false); + m_select->dispatchFormControlChangeEvent(); + m_viewImpl->contentInvalidate(m_select->getRect()); } // Response if the listbox allows multiple selection. array stores the listIndices // of selected positions. virtual void replyIntArray(const int* array, int count) { - // If the select element no longer exists, do to a page change, etc, silently return. - if (!m_select || !FrameLoaderClientAndroid::get(m_viewImpl->m_mainFrame)->getCacheBuilder().validNode(m_frame, m_select)) + // If the select element no longer exists, due to a page change, etc, + // silently return. + if (!m_select || !CacheBuilder::validNode(m_viewImpl->m_mainFrame, + m_frame, m_select)) return; -#ifdef ANDROID_DESELECT_SELECT - m_select->deselectItems(); -#endif + + // If count is 1 or 0, use replyInt. + SkASSERT(count > 1); + + const WTF::Vector<Element*>& items = m_select->listItems(); + int totalItems = static_cast<int>(items.size()); + // Keep track of the position of the value we are comparing against. + int arrayIndex = 0; + // The value we are comparing against. + int selection = array[arrayIndex]; WebCore::HTMLOptionElement* option; - for (int i = 0; i < count; i++) { - option = static_cast<WebCore::HTMLOptionElement*>( - m_select->item(m_select->listToOptionIndex(array[i]))); - option->setSelected(true); + for (int listIndex = 0; listIndex < totalItems; listIndex++) { + if (items[listIndex]->hasLocalName(WebCore::HTMLNames::optionTag)) { + option = static_cast<WebCore::HTMLOptionElement*>( + items[listIndex]); + if (listIndex == selection) { + option->setSelectedState(true); + arrayIndex++; + if (arrayIndex == count) + selection = -1; + else + selection = array[arrayIndex]; + } else + option->setSelectedState(false); + } } - m_viewImpl->contentInvalidate(m_select->getRect()); + m_select->dispatchFormControlChangeEvent(); + m_viewImpl->contentInvalidate(m_select->getRect()); } private: // The select element associated with this listbox. @@ -1685,40 +1694,32 @@ void WebViewCore::listBoxRequest(WebCoreReply* reply, const uint16_t** labels, s m_popupReply = reply; } -bool WebViewCore::key(int keyCode, UChar32 unichar, int repeatCount, bool isShift, bool isAlt, bool isDown) +bool WebViewCore::key(const PlatformKeyboardEvent& event) { - DBG_NAV_LOGD("key: keyCode=%d", keyCode); - WebCore::EventHandler* eventHandler = m_mainFrame->eventHandler(); - WebCore::Node* focusNode = FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder().currentFocus(); - if (focusNode) { + WebCore::Node* focusNode = currentFocus(); + if (focusNode) eventHandler = focusNode->document()->frame()->eventHandler(); - } - - int mods = 0; // PlatformKeyboardEvent::ModifierKey - if (isShift) { - mods |= WebCore::PlatformKeyboardEvent::ShiftKey; - } - if (isAlt) { - mods |= WebCore::PlatformKeyboardEvent::AltKey; - } - WebCore::PlatformKeyboardEvent evt(keyCode, unichar, - isDown ? WebCore::PlatformKeyboardEvent::KeyDown : WebCore::PlatformKeyboardEvent::KeyUp, - repeatCount, static_cast<WebCore::PlatformKeyboardEvent::ModifierKey> (mods)); - return eventHandler->keyEvent(evt); + DBG_NAV_LOGD("keyCode=%s unichar=%d focusNode=%p", + event.keyIdentifier().utf8().data(), event.unichar(), focusNode); + return eventHandler->keyEvent(event); } -bool WebViewCore::click() { - bool keyHandled = false; - WebCore::Node* focusNode = FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder().currentFocus(); - if (focusNode) { - WebFrame::getWebFrame(m_mainFrame)->setUserInitiatedClick(true); - keyHandled = handleMouseClick(focusNode->document()->frame(), focusNode); - WebFrame::getWebFrame(m_mainFrame)->setUserInitiatedClick(false); +// For when the user clicks the trackball +void WebViewCore::click(WebCore::Frame* frame, WebCore::Node* node) { + if (!node) { + WebCore::IntPoint pt = m_mousePos; + pt.move(m_scrollOffsetX, m_scrollOffsetY); + WebCore::HitTestResult hitTestResult = m_mainFrame->eventHandler()-> + hitTestResultAtPoint(pt, false); + node = hitTestResult.innerNode(); + frame = node->document()->frame(); + DBG_NAV_LOGD("m_mousePos=(%d,%d) m_scrollOffset=(%d,%d) pt=(%d,%d)" + " node=%p", m_mousePos.x(), m_mousePos.y(), + m_scrollOffsetX, m_scrollOffsetY, pt.x(), pt.y(), node); } - // match in setFinalFocus() - m_blockFocusChange = false; - return keyHandled; + if (node) + handleMouseClick(frame, node); } bool WebViewCore::handleTouchEvent(int action, int x, int y) @@ -1749,27 +1750,17 @@ bool WebViewCore::handleTouchEvent(int action, int x, int y) return preventDefault; } -void WebViewCore::touchUp(int touchGeneration, int buildGeneration, - WebCore::Frame* frame, WebCore::Node* node, int x, int y, int size, - bool isClick, bool retry) +void WebViewCore::touchUp(int touchGeneration, + WebCore::Frame* frame, WebCore::Node* node, int x, int y, int size) { if (m_touchGeneration > touchGeneration) { DBG_NAV_LOGD("m_touchGeneration=%d > touchGeneration=%d" " x=%d y=%d", m_touchGeneration, touchGeneration, x, y); return; // short circuit if a newer touch has been generated } - if (retry || isClick) - finalKitFocus(frame, node, x, y, true); // don't change DOM focus - else if (!commonKitFocus(touchGeneration, buildGeneration, - frame, node, x, y, false)) { - return; - } + moveMouse(frame, x, y); m_lastGeneration = touchGeneration; - // If this is just a touch and not a click, we have already done the change in focus, - // so just leave the function now. - if (!isClick) - return; - if (frame && FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder().validNode(frame, 0)) { + if (frame && CacheBuilder::validNode(m_mainFrame, frame, 0)) { frame->loader()->resetMultipleFormSubmissionProtection(); } EditorClientAndroid* client = static_cast<EditorClientAndroid*>(m_mainFrame->editor()->client()); @@ -1780,25 +1771,26 @@ void WebViewCore::touchUp(int touchGeneration, int buildGeneration, client->setFromClick(false); } +// Common code for both clicking with the trackball and touchUp bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* nodePtr) { - bool valid = framePtr == NULL || FrameLoaderClientAndroid::get( - m_mainFrame)->getCacheBuilder().validNode(framePtr, nodePtr); + bool valid = framePtr == NULL + || CacheBuilder::validNode(m_mainFrame, framePtr, nodePtr); WebFrame* webFrame = WebFrame::getWebFrame(m_mainFrame); if (valid && nodePtr) { // Need to special case area tags because an image map could have an area element in the middle // so when attempting to get the default, the point chosen would be follow the wrong link. if (nodePtr->hasTagName(WebCore::HTMLNames::areaTag)) { webFrame->setUserInitiatedClick(true); - WebCore::EventTargetNodeCast(nodePtr)->dispatchSimulatedClick(0, - true, true); + nodePtr->dispatchSimulatedClick(0, true, true); webFrame->setUserInitiatedClick(false); + DBG_NAV_LOG("area"); return true; } WebCore::RenderObject* renderer = nodePtr->renderer(); - if (renderer && renderer->isMenuList()) { + if (renderer && (renderer->isMenuList() || renderer->isListBox())) { WebCore::HTMLSelectElement* select = static_cast<WebCore::HTMLSelectElement*>(nodePtr); - const WTF::Vector<WebCore::HTMLElement*>& listItems = select->listItems(); + const WTF::Vector<WebCore::Element*>& listItems = select->listItems(); SkTDArray<const uint16_t*> names; SkTDArray<int> enabledArray; SkTDArray<int> selectedArray; @@ -1807,7 +1799,7 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node for (int i = 0; i < size; i++) { if (listItems[i]->hasTagName(WebCore::HTMLNames::optionTag)) { WebCore::HTMLOptionElement* option = static_cast<WebCore::HTMLOptionElement*>(listItems[i]); - *names.append() = stringConverter(option->text()); + *names.append() = stringConverter(option->textIndentedToRespectGroupLabel()); *enabledArray.append() = option->disabled() ? 0 : 1; if (multiple && option->selected()) *selectedArray.append() = i; @@ -1815,21 +1807,22 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node WebCore::HTMLOptGroupElement* optGroup = static_cast<WebCore::HTMLOptGroupElement*>(listItems[i]); *names.append() = stringConverter(optGroup->groupLabelText()); *enabledArray.append() = 0; - if (multiple) - *selectedArray.append() = 0; } } WebCoreReply* reply = new ListBoxReply(select, select->document()->frame(), this); + // Use a pointer to HTMLSelectElement's superclass, where + // optionToListIndex is public. + SelectElement* selectElement = select; listBoxRequest(reply, names.begin(), size, enabledArray.begin(), enabledArray.count(), multiple, selectedArray.begin(), multiple ? selectedArray.count() : - select->optionToListIndex(select->selectedIndex())); + selectElement->optionToListIndex(select->selectedIndex())); + DBG_NAV_LOG("menu list"); return true; } } if (!valid || !framePtr) framePtr = m_mainFrame; webFrame->setUserInitiatedClick(true); - DBG_NAV_LOGD("m_mousePos={%d,%d}", m_mousePos.x(), m_mousePos.y()); WebCore::PlatformMouseEvent mouseDown(m_mousePos, m_mousePos, WebCore::LeftButton, WebCore::MouseEventPressed, 1, false, false, false, false, WTF::currentTime()); @@ -1840,6 +1833,17 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node WTF::currentTime()); bool handled = framePtr->eventHandler()->handleMouseReleaseEvent(mouseUp); webFrame->setUserInitiatedClick(false); + + // If the user clicked on a textfield, make the focusController active + // so we show the blinking cursor. + WebCore::Node* focusNode = currentFocus(); + DBG_NAV_LOGD("m_mousePos={%d,%d} focusNode=%p handled=%s", m_mousePos.x(), + m_mousePos.y(), focusNode, handled ? "true" : "false"); + if (focusNode) { + WebCore::RenderObject* renderer = focusNode->renderer(); + if (renderer && (renderer->isTextField() || renderer->isTextArea())) + setFocusControllerActive(true); + } return handled; } @@ -1861,6 +1865,16 @@ void WebViewCore::popupReply(const int* array, int count) } } +void WebViewCore::addMessageToConsole(const WebCore::String& message, unsigned int lineNumber, const WebCore::String& sourceID) { + JNIEnv* env = JSC::Bindings::getJNIEnv(); + jstring jMessageStr = env->NewString((unsigned short *)message.characters(), message.length()); + jstring jSourceIDStr = env->NewString((unsigned short *)sourceID.characters(), sourceID.length()); + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_addMessageToConsole, jMessageStr, lineNumber, jSourceIDStr); + env->DeleteLocalRef(jMessageStr); + env->DeleteLocalRef(jSourceIDStr); + checkException(env); +} + void WebViewCore::jsAlert(const WebCore::String& url, const WebCore::String& text) { JNIEnv* env = JSC::Bindings::getJNIEnv(); @@ -1872,6 +1886,19 @@ void WebViewCore::jsAlert(const WebCore::String& url, const WebCore::String& tex checkException(env); } +void WebViewCore::exceededDatabaseQuota(const WebCore::String& url, const WebCore::String& databaseIdentifier, const unsigned long long currentQuota) +{ +#if ENABLE(DATABASE) + JNIEnv* env = JSC::Bindings::getJNIEnv(); + jstring jDatabaseIdentifierStr = env->NewString((unsigned short *)databaseIdentifier.characters(), databaseIdentifier.length()); + jstring jUrlStr = env->NewString((unsigned short *)url.characters(), url.length()); + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_exceededDatabaseQuota, jUrlStr, jDatabaseIdentifierStr, currentQuota); + env->DeleteLocalRef(jDatabaseIdentifierStr); + env->DeleteLocalRef(jUrlStr); + checkException(env); +#endif +} + bool WebViewCore::jsConfirm(const WebCore::String& url, const WebCore::String& text) { JNIEnv* env = JSC::Bindings::getJNIEnv(); @@ -1956,6 +1983,13 @@ void WebViewCore::updateTextfield(WebCore::Node* ptr, bool changeToPassword, checkException(env); } +void WebViewCore::clearTextEntry() +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_clearTextEntry); +} + void WebViewCore::setSnapAnchor(int x, int y) { m_snapAnchorNode = 0; @@ -2003,6 +2037,32 @@ void WebViewCore::setBackgroundColor(SkColor c) view->setBaseBackgroundColor(bcolor); } +jobject WebViewCore::createSurface(SurfaceCallback* cb) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + jobject surface = env->CallObjectMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_createSurface, (int) cb); + checkException(env); + return surface; +} + +void WebViewCore::destroySurface(jobject surface) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_destroySurface, surface); + checkException(env); +} + +void WebViewCore::attachSurface(jobject surface, int x, int y, int width, + int height) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_attachSurface, surface, x, y, width, height); + checkException(env); +} + //---------------------------------------------------------------------- // Native JNI methods //---------------------------------------------------------------------- @@ -2025,17 +2085,11 @@ static void SetSize(JNIEnv *env, jobject obj, jint width, jint height, WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); LOGV("webviewcore::nativeSetSize(%u %u)\n viewImpl: %p", (unsigned)width, (unsigned)height, viewImpl); LOG_ASSERT(viewImpl, "viewImpl not set in nativeSetSize"); - // convert the scale to an int - int s = (int) (scale * 100); - // a negative value indicates that we should not change the scale - if (scale < 0) - s = viewImpl->scale(); - - viewImpl->setSizeScreenWidthAndScale(width, height, screenWidth, s, + viewImpl->setSizeScreenWidthAndScale(width, height, screenWidth, scale, realScreenWidth, screenHeight); } -static void SetScrollOffset(JNIEnv *env, jobject obj, jint dx, jint dy) +static void SetScrollOffset(JNIEnv *env, jobject obj, jint gen, jint x, jint y) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); @@ -2043,7 +2097,7 @@ static void SetScrollOffset(JNIEnv *env, jobject obj, jint dx, jint dy) WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); LOG_ASSERT(viewImpl, "need viewImpl"); - viewImpl->setScrollOffset(dx, dy); + viewImpl->setScrollOffset(gen, x, y); } static void SetGlobalBounds(JNIEnv *env, jobject obj, jint x, jint y, jint h, @@ -2059,18 +2113,17 @@ static void SetGlobalBounds(JNIEnv *env, jobject obj, jint x, jint y, jint h, } static jboolean Key(JNIEnv *env, jobject obj, jint keyCode, jint unichar, - jint repeatCount, jboolean isShift, jboolean isAlt, jboolean isDown) + jint repeatCount, jboolean isShift, jboolean isAlt, jboolean isSym, + jboolean isDown) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); #endif - WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); - LOG_ASSERT(viewImpl, "viewImpl not set in Key"); - - return viewImpl->key(keyCode, unichar, repeatCount, isShift, isAlt, isDown); + return GET_NATIVE_VIEW(env, obj)->key(PlatformKeyboardEvent(keyCode, + unichar, repeatCount, isDown, isShift, isAlt, isSym)); } -static jboolean Click(JNIEnv *env, jobject obj) +static void Click(JNIEnv *env, jobject obj, int framePtr, int nodePtr) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); @@ -2078,62 +2131,64 @@ static jboolean Click(JNIEnv *env, jobject obj) WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); LOG_ASSERT(viewImpl, "viewImpl not set in Click"); - return viewImpl->click(); + viewImpl->click(reinterpret_cast<WebCore::Frame*>(framePtr), + reinterpret_cast<WebCore::Node*>(nodePtr)); } -static void DeleteSelection(JNIEnv *env, jobject obj, - jint frame, jint node, jint x, jint y, jint start, jint end) +static void DeleteSelection(JNIEnv *env, jobject obj, jint start, jint end, + jint textGeneration) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); #endif - LOGV("webviewcore::nativeDeleteSelection()\n"); WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); - LOG_ASSERT(viewImpl, "viewImpl not set in nativeDeleteSelection"); - viewImpl->deleteSelection((WebCore::Frame*) frame, (WebCore::Node*) node, - x, y, start, end); + viewImpl->deleteSelection(start, end, textGeneration); } -static void SetSelection(JNIEnv *env, jobject obj, - jint frame, jint node, jint x, jint y, jint start, jint end) +static void SetSelection(JNIEnv *env, jobject obj, jint start, jint end) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); #endif - LOGV("webviewcore::nativeSetSelection()\n"); WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); - LOG_ASSERT(viewImpl, "viewImpl not set in nativeDeleteSelection"); - viewImpl->setSelection((WebCore::Frame*) frame, (WebCore::Node*) node, - x, y, start, end); + viewImpl->setSelection(start, end); } static void ReplaceTextfieldText(JNIEnv *env, jobject obj, - jint framePtr, jint nodePtr, jint x, jint y, jint oldStart, jint oldEnd, - jstring replace, jint start, jint end) + jint oldStart, jint oldEnd, jstring replace, jint start, jint end, + jint textGeneration) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); #endif - LOGV("webviewcore::nativeReplaceTextfieldText()\n"); WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); - LOG_ASSERT(viewImpl, "viewImpl not set in nativeReplaceTextfieldText"); - viewImpl->replaceTextfieldText((WebCore::Frame*) framePtr, (WebCore::Node*) nodePtr, x, y, oldStart, - oldEnd, replace, start, end); + WebCore::String webcoreString = to_string(env, replace); + viewImpl->replaceTextfieldText(oldStart, + oldEnd, webcoreString, start, end, textGeneration); } -static void PassToJs(JNIEnv *env, jobject obj, jint frame, jint node, - jint x, jint y, jint generation, jstring currentText, jint keyCode, +static void PassToJs(JNIEnv *env, jobject obj, + jint generation, jstring currentText, jint keyCode, jint keyValue, jboolean down, jboolean cap, jboolean fn, jboolean sym) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); #endif - LOGV("webviewcore::nativePassToJs()\n"); + WebCore::String current = to_string(env, currentText); + GET_NATIVE_VIEW(env, obj)->passToJs(generation, current, + PlatformKeyboardEvent(keyCode, keyValue, 0, down, cap, fn, sym)); +} + +static void SetFocusControllerActive(JNIEnv *env, jobject obj, jboolean active) +{ +#ifdef ANDROID_INSTRUMENT + TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); +#endif + LOGV("webviewcore::nativeSetFocusControllerActive()\n"); WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); - LOG_ASSERT(viewImpl, "viewImpl not set in nativePassToJs"); - viewImpl->passToJs((WebCore::Frame*) frame, (WebCore::Node*) node, - x, y, generation, currentText, keyCode, keyValue, down, cap, fn, sym); + LOG_ASSERT(viewImpl, "viewImpl not set in nativeSetFocusControllerActive"); + viewImpl->setFocusControllerActive(active); } static void SaveDocumentState(JNIEnv *env, jobject obj, jint frame) @@ -2206,7 +2261,8 @@ static void SendListBoxChoices(JNIEnv* env, jobject obj, jbooleanArray jArray, viewImpl->popupReply(array, count); } -static jstring FindAddress(JNIEnv *env, jobject obj, jstring addr) +static jstring FindAddress(JNIEnv *env, jobject obj, jstring addr, + jboolean caseInsensitive) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); @@ -2219,7 +2275,7 @@ static jstring FindAddress(JNIEnv *env, jobject obj, jstring addr) const jchar* addrChars = env->GetStringChars(addr, 0); int start, end; bool success = CacheBuilder::FindAddress(addrChars, length, - &start, &end) == CacheBuilder::FOUND_COMPLETE; + &start, &end, caseInsensitive) == CacheBuilder::FOUND_COMPLETE; jstring ret = 0; if (success) { ret = env->NewString((jchar*) addrChars + start, end - start); @@ -2240,16 +2296,15 @@ static jboolean HandleTouchEvent(JNIEnv *env, jobject obj, jint action, jint x, } static void TouchUp(JNIEnv *env, jobject obj, jint touchGeneration, - jint buildGeneration, jint frame, jint node, jint x, jint y, jint size, - jboolean isClick, jboolean retry) + jint frame, jint node, jint x, jint y, jint size) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); #endif WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__); - viewImpl->touchUp(touchGeneration, buildGeneration, - (WebCore::Frame*) frame, (WebCore::Node*) node, x, y, size, isClick, retry); + viewImpl->touchUp(touchGeneration, + (WebCore::Frame*) frame, (WebCore::Node*) node, x, y, size); } static jstring RetrieveHref(JNIEnv *env, jobject obj, jint frame, @@ -2267,40 +2322,27 @@ static jstring RetrieveHref(JNIEnv *env, jobject obj, jint frame, return 0; } -static void SetFinalFocus(JNIEnv *env, jobject obj, jint frame, jint node, - jint x, jint y, jboolean block) -{ -#ifdef ANDROID_INSTRUMENT - TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); -#endif - WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); - LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__); - viewImpl->setFinalFocus((WebCore::Frame*) frame, (WebCore::Node*) node, x, - y, block); -} - -static void SetKitFocus(JNIEnv *env, jobject obj, jint moveGeneration, - jint buildGeneration, jint frame, jint node, jint x, jint y, - jboolean ignoreNullFocus) +static void MoveMouse(JNIEnv *env, jobject obj, jint frame, + jint x, jint y) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); #endif WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__); - viewImpl->setKitFocus(moveGeneration, buildGeneration, - (WebCore::Frame*) frame, (WebCore::Node*) node, x, y, - ignoreNullFocus); + viewImpl->moveMouse((WebCore::Frame*) frame, x, y); } -static void UnblockFocus(JNIEnv *env, jobject obj) +static void MoveMouseIfLatest(JNIEnv *env, jobject obj, jint moveGeneration, + jint frame, jint x, jint y) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); #endif WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__); - viewImpl->unblockFocus(); + viewImpl->moveMouseIfLatest(moveGeneration, + (WebCore::Frame*) frame, x, y); } static void UpdateFrameCache(JNIEnv *env, jobject obj) @@ -2427,16 +2469,28 @@ static void DumpNavTree(JNIEnv *env, jobject obj) viewImpl->dumpNavTree(); } -static void RefreshPlugins(JNIEnv *env, - jobject obj, - jboolean reloadOpenPages) +static void SetJsFlags(JNIEnv *env, jobject obj, jstring flags) { -#ifdef ANDROID_INSTRUMENT - TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); +#if USE(V8) + WebCore::String flagsString = to_string(env, flags); + WebCore::CString utf8String = flagsString.utf8(); + WebCore::ScriptController::setFlags(utf8String.data(), utf8String.length()); +#endif +} + + +// Called from the Java side to set a new quota for the origin in response. +// to a notification that the original quota was exceeded. +static void SetDatabaseQuota(JNIEnv* env, jobject obj, jlong quota) { +#if ENABLE(DATABASE) + WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); + Frame* frame = viewImpl->mainFrame(); + + // The main thread is blocked awaiting this response, so now we can wake it + // up. + ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(frame->page()->chrome()->client()); + chromeC->wakeUpMainThreadWithNewQuota(quota); #endif - // Refresh the list of plugins, optionally reloading all open - // pages. - WebCore::refreshPlugins(reloadOpenPages); } static void RegisterURLSchemeAsLocal(JNIEnv* env, jobject obj, jstring scheme) { @@ -2475,6 +2529,68 @@ static bool DrawContent(JNIEnv *env, jobject obj, jobject canv, jint color) return viewImpl->drawContent(canvas, color); } +static bool PictureReady(JNIEnv* env, jobject obj) +{ + return GET_NATIVE_VIEW(env, obj)->pictureReady(); +} + +static void UpdatePluginState(JNIEnv* env, jobject obj, jint framePtr, jint nodePtr, jint state) +{ +#ifdef ANDROID_INSTRUMENT + TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); +#endif + WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); + LOG_ASSERT(viewImpl, "viewImpl not set in nativeUpdatePluginState"); + viewImpl->updatePluginState((WebCore::Frame*) framePtr, (WebCore::Node*) nodePtr, + (PluginState) state); +} + +static void SurfaceChanged(JNIEnv* env, jobject obj, jint pointer, jint state, + jint format, jint width, jint height) +{ + // Be safe and check for a valid callback + if (!pointer) + return; + SurfaceCallback* cb = reinterpret_cast<SurfaceCallback*>(pointer); + switch (state) { + case 0: + cb->surfaceCreated(); + break; + case 1: + cb->surfaceChanged(format, width, height); + break; + case 2: + cb->surfaceDestroyed(); + break; + default: + break; + } +} + +static void Pause(JNIEnv* env, jobject obj) +{ + ANPEvent event; + SkANP::InitEvent(&event, kLifecycle_ANPEventType); + event.data.lifecycle.action = kPause_ANPLifecycleAction; + GET_NATIVE_VIEW(env, obj)->sendPluginEvent(event); +} + +static void Resume(JNIEnv* env, jobject obj) +{ + ANPEvent event; + SkANP::InitEvent(&event, kLifecycle_ANPEventType); + event.data.lifecycle.action = kResume_ANPLifecycleAction; + GET_NATIVE_VIEW(env, obj)->sendPluginEvent(event); +} + +static void FreeMemory(JNIEnv* env, jobject obj) +{ + ANPEvent event; + SkANP::InitEvent(&event, kLifecycle_ANPEventType); + event.data.lifecycle.action = kFreeMemory_ANPLifecycleAction; + GET_NATIVE_VIEW(env, obj)->sendPluginEvent(event); +} + // ---------------------------------------------------------------------------- /* @@ -2487,44 +2603,46 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) CopyContentToPicture }, { "nativeDrawContent", "(Landroid/graphics/Canvas;I)Z", (void*) DrawContent } , - { "nativeKey", "(IIIZZZ)Z", + { "nativeKey", "(IIIZZZZ)Z", (void*) Key }, - { "nativeClick", "()Z", + { "nativeClick", "(II)V", (void*) Click }, + { "nativePictureReady", "()Z", + (void*) PictureReady } , { "nativeSendListBoxChoices", "([ZI)V", (void*) SendListBoxChoices }, { "nativeSendListBoxChoice", "(I)V", (void*) SendListBoxChoice }, { "nativeSetSize", "(IIIFII)V", (void*) SetSize }, - { "nativeSetScrollOffset", "(II)V", + { "nativeSetScrollOffset", "(III)V", (void*) SetScrollOffset }, { "nativeSetGlobalBounds", "(IIII)V", (void*) SetGlobalBounds }, - { "nativeSetSelection", "(IIIIII)V", + { "nativeSetSelection", "(II)V", (void*) SetSelection } , - { "nativeDeleteSelection", "(IIIIII)V", + { "nativeDeleteSelection", "(III)V", (void*) DeleteSelection } , - { "nativeReplaceTextfieldText", "(IIIIIILjava/lang/String;II)V", + { "nativeReplaceTextfieldText", "(IILjava/lang/String;III)V", (void*) ReplaceTextfieldText } , - { "passToJs", "(IIIIILjava/lang/String;IIZZZZ)V", + { "nativeMoveMouse", "(III)V", + (void*) MoveMouse }, + { "nativeMoveMouseIfLatest", "(IIII)V", + (void*) MoveMouseIfLatest }, + { "passToJs", "(ILjava/lang/String;IIZZZZ)V", (void*) PassToJs } , + { "nativeSetFocusControllerActive", "(Z)V", + (void*) SetFocusControllerActive }, { "nativeSaveDocumentState", "(I)V", (void*) SaveDocumentState }, - { "nativeFindAddress", "(Ljava/lang/String;)Ljava/lang/String;", + { "nativeFindAddress", "(Ljava/lang/String;Z)Ljava/lang/String;", (void*) FindAddress }, { "nativeHandleTouchEvent", "(III)Z", (void*) HandleTouchEvent }, - { "nativeTouchUp", "(IIIIIIIZZ)V", + { "nativeTouchUp", "(IIIIII)V", (void*) TouchUp }, { "nativeRetrieveHref", "(II)Ljava/lang/String;", (void*) RetrieveHref }, - { "nativeSetFinalFocus", "(IIIIZ)V", - (void*) SetFinalFocus }, - { "nativeSetKitFocus", "(IIIIIIZ)V", - (void*) SetKitFocus }, - { "nativeUnblockFocus", "()V", - (void*) UnblockFocus }, { "nativeUpdateFrameCache", "()V", (void*) UpdateFrameCache }, { "nativeGetContentMinPrefWidth", "()I", @@ -2543,8 +2661,6 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) SetBackgroundColor }, { "nativeGetSelection", "(Landroid/graphics/Region;)Ljava/lang/String;", (void*) GetSelection }, - { "nativeRefreshPlugins", "(Z)V", - (void*) RefreshPlugins }, { "nativeRegisterURLSchemeAsLocal", "(Ljava/lang/String;)V", (void*) RegisterURLSchemeAsLocal }, { "nativeDumpDomTree", "(Z)V", @@ -2552,7 +2668,16 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { { "nativeDumpRenderTree", "(Z)V", (void*) DumpRenderTree }, { "nativeDumpNavTree", "()V", - (void*) DumpNavTree } + (void*) DumpNavTree }, + { "nativeSetDatabaseQuota", "(J)V", + (void*) SetDatabaseQuota }, + { "nativeSurfaceChanged", "(IIIII)V", + (void*) SurfaceChanged }, + { "nativePause", "()V", (void*) Pause }, + { "nativeResume", "()V", (void*) Resume }, + { "nativeFreeMemory", "()V", (void*) FreeMemory }, + { "nativeSetJsFlags", "(Ljava/lang/String;)V", (void*) SetJsFlags }, + { "nativeUpdatePluginState", "(III)V", (void*) UpdatePluginState }, }; int register_webviewcore(JNIEnv* env) diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h index 8f035f2..66ef470 100644 --- a/WebKit/android/jni/WebViewCore.h +++ b/WebKit/android/jni/WebViewCore.h @@ -26,6 +26,7 @@ #ifndef WEBVIEWCORE_H #define WEBVIEWCORE_H +#include "android_npapi.h" #include "CacheBuilder.h" #include "CachedHistory.h" #include "PictureSet.h" @@ -47,6 +48,7 @@ namespace WebCore { class RenderPart; class RenderText; class Node; + class PlatformKeyboardEvent; class RenderTextControl; class ScrollView; class TimerBase; @@ -57,9 +59,15 @@ class SkPicture; class SkIRect; namespace android { - + + enum PluginState { + kGainFocus_PluginState = 0, + kLoseFocus_PluginState = 1, + }; + class CachedRoot; class ListBoxReply; + class SurfaceCallback; class WebCoreReply : public WebCoreRefObject { public: @@ -132,12 +140,6 @@ namespace android { void offInvalidate(const WebCore::IntRect &rect); /** - * Called by webcore when the focus was set after returning to prior page - * used to rebuild and display any changes in focus - */ - void notifyFocusSet(); - - /** * Called by webcore when the progress indicator is done * used to rebuild and display any changes in focus */ @@ -149,7 +151,7 @@ namespace android { void didFirstLayout(); /** - * Notify the view to restore the screen width, which in turn restores + * Notify the view to restore the screen width, which in turn restores * the scale. */ void restoreScale(int); @@ -164,7 +166,7 @@ namespace android { */ void updateTextfield(WebCore::Node* pointer, bool changeToPassword, const WebCore::String& text); - + void clearTextEntry(); // JavaScript support void jsAlert(const WebCore::String& url, const WebCore::String& text); bool jsConfirm(const WebCore::String& url, const WebCore::String& text); @@ -173,6 +175,19 @@ namespace android { bool jsUnload(const WebCore::String& url, const WebCore::String& message); bool jsInterrupt(); + /** + * Tell the Java side that the origin has exceeded it's database quota. + * @param url The URL of the page that caused the quota overflow + * @param databaseIdentifier the id of the database that caused the + * quota overflow. + * @param currentQuota The current quota for the origin. + */ + void exceededDatabaseQuota(const WebCore::String& url, + const WebCore::String& databaseIdentifier, + const unsigned long long currentQuota); + + void addMessageToConsole(const String& message, unsigned int lineNumber, const String& sourceID); + // // Followings support calls from Java to native WebCore // @@ -180,37 +195,35 @@ namespace android { WebCore::String retrieveHref(WebCore::Frame* frame, WebCore::Node* node); WebCore::String getSelection(SkRegion* ); - + // Create a single picture to represent the drawn DOM (used by navcache) void recordPicture(SkPicture* picture); - + // Create a set of pictures to represent the drawn DOM, driven by // the invalidated region and the time required to draw (used to draw) void recordPictureSet(PictureSet* master); - void setFinalFocus(WebCore::Frame* frame, WebCore::Node* node, - int x, int y, bool block); - void setKitFocus(int moveGeneration, int buildGeneration, - WebCore::Frame* frame, WebCore::Node* node, int x, int y, - bool ignoreNullFocus); + void moveMouse(WebCore::Frame* frame, int x, int y); + void moveMouseIfLatest(int moveGeneration, + WebCore::Frame* frame, int x, int y); // set the scroll amount that webview.java is currently showing - void setScrollOffset(int dx, int dy); + void setScrollOffset(int moveGeneration, int dx, int dy); void setGlobalBounds(int x, int y, int h, int v); - void setSizeScreenWidthAndScale(int width, int height, int screenWidth, - int scale, int realScreenWidth, int screenHeight); + void setSizeScreenWidthAndScale(int width, int height, int screenWidth, + float scale, int realScreenWidth, int screenHeight); /** * Handle key events from Java. * @return Whether keyCode was handled by this class. */ - bool key(int keyCode, UChar32 unichar, int repeatCount, bool isShift, bool isAlt, bool isDown); + bool key(const WebCore::PlatformKeyboardEvent& event); /** - * Handle (mouse) click event from Java + * Handle (trackball) click event from Java */ - bool click(); + void click(WebCore::Frame* frame, WebCore::Node* node); /** * Handle touch event @@ -221,10 +234,9 @@ namespace android { * Handle motionUp event from the UI thread (called touchUp in the * WebCore thread). */ - void touchUp(int touchGeneration, int buildGeneration, - WebCore::Frame* frame, WebCore::Node* node, int x, int y, - int size, bool isClick, bool retry); - + void touchUp(int touchGeneration, + WebCore::Frame* frame, WebCore::Node* node, int x, int y, int size); + /** * Sets the index of the label from a popup */ @@ -232,33 +244,29 @@ namespace android { void popupReply(const int* array, int count); /** - * Delete text from start to end in the focused textfield. If there is no - * focus, or if start == end, silently fail, but set selection to that value. + * Delete text from start to end in the focused textfield. + * If start == end, set the selection, but perform no deletion. + * If there is no focus, silently fail. * If start and end are out of order, swap them. - * Use the frame, node, x, and y to ensure that the correct node is focused. - * Return a frame. Convenience so replaceTextfieldText can use this function. */ - WebCore::Frame* deleteSelection(WebCore::Frame* frame, WebCore::Node* node, int x, - int y,int start, int end); + void deleteSelection(int start, int end, int textGeneration); /** * Set the selection of the currently focused textfield to (start, end). * If start and end are out of order, swap them. - * Use the frame, node, x, and y to ensure that the correct node is focused. - * Return a frame. Convenience so deleteSelection can use this function. */ - WebCore::Frame* setSelection(WebCore::Frame* frame, WebCore::Node* node, int x, - int y,int start, int end); + void setSelection(int start, int end); /** - * In the currenlty focused textfield, represented by frame, node, x, and y (which - * are used to ensure it has focus), replace the characters from oldStart to oldEnd + * In the currently focused textfield, replace the characters from oldStart to oldEnd * (if oldStart == oldEnd, this will be an insert at that position) with replace, * and set the selection to (start, end). */ - void replaceTextfieldText(WebCore::Frame* frame, WebCore::Node* node, int x, int y, - int oldStart, int oldEnd, jstring replace, int start, int end); - void passToJs(WebCore::Frame* frame, WebCore::Node* node, int x, int y, int generation, - jstring currentText, int jKeyCode, int keyVal, bool down, bool cap, bool fn, bool sym); + void replaceTextfieldText(int oldStart, + int oldEnd, const WebCore::String& replace, int start, int end, + int textGeneration); + void passToJs(int generation, + const WebCore::String& , const WebCore::PlatformKeyboardEvent& ); + void setFocusControllerActive(bool active); void saveDocumentState(WebCore::Frame* frame); @@ -273,8 +281,8 @@ namespace android { void setBackgroundColor(SkColor c); void setSnapAnchor(int x, int y); void snapToAnchor(); - void unblockFocus() { m_blockFocusChange = false; } void updateFrameCache(); + void updateCacheOnNodeChange(); void dumpDomTree(bool); void dumpRenderTree(bool); void dumpNavTree(); @@ -288,34 +296,58 @@ namespace android { void invalPlugin(PluginWidgetAndroid*); void drawPlugins(); + // send the current screen size/zoom to all of the plugins in our list + void sendPluginVisibleScreen(); + + // send this event to all of the plugins in our list + void sendPluginEvent(const ANPEvent&); + + // send this event to all of the plugins who have the given flag set + void sendPluginEvent(const ANPEvent& evt, ANPEventFlag flag); + + // return the cursorNode if it is a plugin + Node* cursorNodeIsPlugin(); + + // notify the plugin of an update in state + void updatePluginState(Frame* frame, Node* node, PluginState state); + // Notify the Java side whether it needs to pass down the touch events void needTouchEvents(bool); + // Notify the Java side that webkit is requesting a keyboard + void requestKeyboard(bool); + + // Creates a SurfaceView for a plugin + jobject createSurface(SurfaceCallback* cb); + + // Destroys the SurfaceView after removing from the view system. + void destroySurface(jobject surface); + + // Positions the SurfaceView at x,y with dimensions width x height + void attachSurface(jobject surface, int x, int y, int width, int height); + // other public functions public: - void removeFrameGeneration(WebCore::Frame* ); - void updateFrameGeneration(WebCore::Frame* ); - // reset the picture set to empty void clearContent(); - + // flatten the picture set to a picture void copyContentToPicture(SkPicture* ); - + // draw the picture set with the specified background color bool drawContent(SkCanvas* , SkColor ); - + bool pictureReady(); + // record the inval area, and the picture size bool recordContent(SkRegion* , SkIPoint* ); int screenWidth() const { return m_screenWidth; } - int scale() const { return m_scale; } + float scale() const { return m_scale; } WebCore::Frame* mainFrame() const { return m_mainFrame; } - + // utility to split slow parts of the picture set void splitContent(); - + // these members are shared with webview.cpp - int retrieveFrameGeneration(WebCore::Frame* ); static Mutex gFrameCacheMutex; CachedRoot* m_frameCacheKit; // nav data being built by webcore SkPicture* m_navPictureKit; @@ -324,10 +356,14 @@ namespace android { int m_touchGeneration; // copy of state in WebViewNative triggered by touch int m_lastGeneration; // last action using up to date cache bool m_updatedFrameCache; - bool m_useReplay; bool m_findIsUp; - static Mutex gRecomputeFocusMutex; - WTF::Vector<int> m_recomputeEvents; + bool m_hasCursorBounds; + WebCore::IntRect m_cursorBounds; + WebCore::IntRect m_cursorHitBounds; + void* m_cursorFrame; + IntPoint m_cursorLocation; + void* m_cursorNode; + static Mutex gCursorBoundsMutex; // These two fields go together: we use the mutex to protect access to // m_buttons, so that we, and webview.cpp can look/modify the m_buttons // field safely from our respective threads @@ -337,6 +373,8 @@ namespace android { // internal functions private: + CacheBuilder& cacheBuilder(); + WebCore::Node* currentFocus(); // Compare the new set of buttons to the old one. All of the new // buttons either replace our old ones or should be added to our list. // Then check the old buttons to see if any are no longer needed. @@ -348,18 +386,13 @@ namespace android { bool multiple, const int selected[], size_t selectedCountOrSelection); friend class ListBoxReply; - struct FrameGen { - const WebCore::Frame* m_frame; - int m_generation; - }; - WTF::Vector<FrameGen> m_frameGenerations; - static Mutex gFrameGenerationMutex; struct JavaGlue; struct JavaGlue* m_javaGlue; WebCore::Frame* m_mainFrame; WebCoreReply* m_popupReply; WebCore::Node* m_lastFocused; WebCore::IntRect m_lastFocusedBounds; + int m_lastMoveGeneration; static Mutex m_contentMutex; // protects ui/core thread pictureset access PictureSet m_content; // the set of pictures to draw (accessed by UI too) SkRegion m_addInval; // the accumulated inval region (not yet drawn) @@ -373,45 +406,34 @@ namespace android { int m_textGeneration; CachedRoot* m_temp; SkPicture* m_tempPict; - int m_buildGeneration; int m_maxXScroll; int m_maxYScroll; int m_scrollOffsetX; // webview.java's current scroll in X int m_scrollOffsetY; // webview.java's current scroll in Y WebCore::IntPoint m_mousePos; bool m_frameCacheOutOfDate; - bool m_blockFocusChange; + bool m_progressDone; int m_lastPassed; int m_lastVelocity; CachedHistory m_history; WebCore::Node* m_snapAnchorNode; - int m_screenWidth; - int m_scale; + int m_screenWidth; // width of the visible rect in document coordinates + int m_screenHeight;// height of the visible rect in document coordinates + float m_scale; unsigned m_domtree_version; bool m_check_domtree_version; - + SkTDArray<PluginWidgetAndroid*> m_plugins; WebCore::Timer<WebViewCore> m_pluginInvalTimer; void pluginInvalTimerFired(WebCore::Timer<WebViewCore>*) { this->drawPlugins(); } - WebCore::Frame* changedKitFocus(WebCore::Frame* frame, - WebCore::Node* node, int x, int y); - bool commonKitFocus(int generation, int buildGeneration, - WebCore::Frame* frame, WebCore::Node* node, int x, int y, - bool ignoreNullFocus); - bool finalKitFocus(WebCore::Frame* frame, WebCore::Node* node, int x, int y, bool donotChangeDOMFocus); void doMaxScroll(CacheBuilder::Direction dir); SkPicture* rebuildPicture(const SkIRect& inval); void rebuildPictureSet(PictureSet* ); - void sendMarkNodeInvalid(WebCore::Node* ); - void sendNotifyFocusSet(); void sendNotifyProgressFinished(); - void sendRecomputeFocus(); bool handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* nodePtr); - bool prepareFrameCache(); - void releaseFrameCache(bool newCache); #if DEBUG_NAV_UI uint32_t m_now; #endif diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp index a49c614..56cb2ae 100644 --- a/WebKit/android/nav/CacheBuilder.cpp +++ b/WebKit/android/nav/CacheBuilder.cpp @@ -27,8 +27,8 @@ #include "CachedNode.h" #include "CachedRoot.h" #include "Document.h" +#include "EventListener.h" #include "EventNames.h" -#include "EventTargetNode.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameLoaderClientAndroid.h" @@ -45,6 +45,7 @@ #include "InlineTextBox.h" #include "KURL.h" #include "PluginView.h" +#include "RegisteredEventListener.h" #include "RenderImage.h" #include "RenderInline.h" #include "RenderListBox.h" @@ -88,8 +89,20 @@ Frame* CacheBuilder::FrameAnd(const CacheBuilder* cacheBuilder) { return loader->getFrame(); } + #if DUMP_NAV_CACHE +static bool hasEventListener(Node* node, const AtomicString& eventType) { + const RegisteredEventListenerVector& listeners = node->eventListeners(); + size_t size = listeners.size(); + for (size_t i = 0; i < size; ++i) { + const RegisteredEventListener& r = *listeners[i]; + if (r.eventType() == eventType) + return true; + } + return false; +} + #define DEBUG_BUFFER_SIZE 256 #define DEBUG_WRAP_SIZE 150 #define DEBUG_WRAP_MAX 170 @@ -345,24 +358,20 @@ void CacheBuilder::Debug::groups() { DUMP_NAV_LOGD("static DebugTestNode TEST%s_RECTS[] = {\n", name); do { String properties; - EventTargetNode* elementTarget = node->isEventTargetNode() ? - (EventTargetNode*) node : NULL; - if (elementTarget) { - if (elementTarget->getEventListener(eventNames().clickEvent)) - properties.append("ONCLICK | "); - if (elementTarget->getEventListener(eventNames().mousedownEvent)) - properties.append("MOUSEDOWN | "); - if (elementTarget->getEventListener(eventNames().mouseupEvent)) - properties.append("MOUSEUP | "); - if (elementTarget->getEventListener(eventNames().mouseoverEvent)) - properties.append("MOUSEOVER | "); - if (elementTarget->getEventListener(eventNames().mouseoutEvent)) - properties.append("MOUSEOUT | "); - if (elementTarget->getEventListener(eventNames().keydownEvent)) - properties.append("KEYDOWN | "); - if (elementTarget->getEventListener(eventNames().keyupEvent)) - properties.append("KEYUP | "); - } + if (hasEventListener(node, eventNames().clickEvent)) + properties.append("ONCLICK | "); + if (hasEventListener(node, eventNames().mousedownEvent)) + properties.append("MOUSEDOWN | "); + if (hasEventListener(node, eventNames().mouseupEvent)) + properties.append("MOUSEUP | "); + if (hasEventListener(node, eventNames().mouseoverEvent)) + properties.append("MOUSEOVER | "); + if (hasEventListener(node, eventNames().mouseoutEvent)) + properties.append("MOUSEOUT | "); + if (hasEventListener(node, eventNames().keydownEvent)) + properties.append("KEYDOWN | "); + if (hasEventListener(node, eventNames().keyupEvent)) + properties.append("KEYUP | "); if (CacheBuilder::HasFrame(node)) properties.append("FRAME | "); if (focus == node) { @@ -381,7 +390,7 @@ void CacheBuilder::Debug::groups() { properties.truncate(properties.length() - 3); IntRect rect = node->getRect(); if (node->hasTagName(HTMLNames::areaTag)) - rect = Builder(frame)->getAreaRect(static_cast<HTMLAreaElement*>(node)); + rect = getAreaRect(static_cast<HTMLAreaElement*>(node)); char buffer[DEBUG_BUFFER_SIZE]; memset(buffer, 0, sizeof(buffer)); mBuffer = buffer; @@ -437,7 +446,7 @@ void CacheBuilder::Debug::groups() { //print(renderer ? renderer->information().ascii() : "NO_RENDER_INFO"); if (node->isElementNode()) { Element* element = static_cast<Element*>(node); - NamedAttrMap* attrs = element->attributes(); + NamedNodeMap* attrs = element->attributes(); unsigned length = attrs->length(); if (length > 0) { newLine(); @@ -448,8 +457,6 @@ void CacheBuilder::Debug::groups() { } } } - if (renderer) - renderTree(renderer, 0, node, count); count++; newLine(); } while ((node = node->traverseNextNode()) != NULL); @@ -520,9 +527,10 @@ void CacheBuilder::Debug::groups() { mIndex += snprintf(&mBuffer[mIndex], mBufferSize - mIndex, ", %d, %d, %d", 0 /*textBox->spaceAdd()*/, textBox->start(), 0 /*textBox->textPos()*/); mIndex += snprintf(&mBuffer[mIndex], mBufferSize - mIndex, ", %d, %d, %d, %d", - textBox->xPos(), textBox->yPos(), textBox->width(), textBox->height()); + textBox->x(), textBox->y(), textBox->width(), textBox->height()); + int baseline = textBox->renderer()->style(textBox->isFirstLineStyle())->font().ascent(); mIndex += snprintf(&mBuffer[mIndex], mBufferSize - mIndex, ", %d }, // %d ", - textBox->baseline(), ++rectIndex); + baseline, ++rectIndex); wideString(node->textContent().characters() + textBox->start(), textBox->len(), true); DUMP_NAV_LOGD("%.*s\n", mIndex, mBuffer); textBox = textBox->nextTextBox(); @@ -553,8 +561,6 @@ bool CacheBuilder::Debug::isFocusable(Node* node) { return true; if (node->isFocusable()) return true; - if (node->isEventTargetNode()) - return true; if (CacheBuilder::AnyIsClick(node)) return false; if (CacheBuilder::HasTriggerEvent(node)) @@ -645,64 +651,6 @@ void CacheBuilder::Debug::setIndent(int indent) print(scratch); } -void CacheBuilder::Debug::renderTree(RenderObject* renderer, int indent, - Node* child, int count) -{ - char scratch[256]; - Node* node = renderer->node(); - if (node != child) { - count = ParentIndex(child, count, node); - if (renderer->isRenderBlock() == false) - goto tryParent; - RenderBlock* renderBlock = (RenderBlock*) renderer; - if (renderBlock->hasColumns() == false) - goto tryParent; - Vector<IntRect>* rects = renderBlock->columnRects(); - newLine(indent); - snprintf(scratch, sizeof(scratch), "// render parent=%d", count); - print(scratch); - for (size_t x = 0; x < rects->size(); x++) { - const IntRect& rect = rects->at(x); - snprintf(scratch, sizeof(scratch), "(%d,%d,%d,%d) ", rect.x(), - rect.y(), rect.width(), rect.height()); - print(scratch); - } - } - { - newLine(indent); - RenderStyle* style = renderer->style(); - EVisibility vis = style->visibility(); - ASSERT(vis == VISIBLE || vis == HIDDEN || vis == COLLAPSE); - snprintf(scratch, sizeof(scratch), - "// render style visible:%s opacity:%g width:%d height:%d" - " hasBackground:%s isInlineFlow:%s isBlockFlow:%s" - " textOverflow:%s", - vis == VISIBLE ? "visible" : vis == HIDDEN ? "hidden" : "collapse", - style->opacity(), 0 /*renderer->width()*/, 0 /*renderer->height()*/, - style->hasBackground() ? "true" : "false", - 0 /*renderer->isInlineFlow()*/ ? "true" : "false", - renderer->isBlockFlow() ? "true" : "false", - style->textOverflow() ? "true" : "false" - ); - print(scratch); - newLine(indent); - const IntRect& oRect = renderer->absoluteClippedOverflowRect(); - const IntRect& cRect = renderer->getOverflowClipRect(0,0); - snprintf(scratch, sizeof(scratch), - "// render xPos:%d yPos:%d overflowRect:{%d, %d, %d, %d} " - " getOverflowClipRect:{%d, %d, %d, %d} ", - 0 /*renderer->xPos()*/, 0 /*renderer->yPos()*/, - oRect.x(), oRect.y(), oRect.width(), oRect.height(), - cRect.x(), cRect.y(), cRect.width(), cRect.height() - ); - print(scratch); - } -tryParent: - RenderObject* parent = renderer->parent(); - if (parent) - renderTree(parent, indent + 2, node, count); -} - void CacheBuilder::Debug::uChar(const UChar* name, unsigned len, bool hex) { const UChar* end = name + len; bool wroteHex = false; @@ -773,7 +721,6 @@ void CacheBuilder::Debug::wideString(const String& str) { CacheBuilder::CacheBuilder() { - mLastKnownFocus = NULL; mAllowableTypes = ALL_CACHEDNODETYPES; #ifdef DUMP_NAV_CACHE_USING_PRINTF gNavCacheLogFile = NULL; @@ -807,20 +754,35 @@ void CacheBuilder::adjustForColumns(const ClipColumnTracker& track, } } +// Checks if a node has one of event listener types. +bool CacheBuilder::NodeHasEventListeners(Node* node, AtomicString* eventTypes, int length) { + const RegisteredEventListenerVector& listeners = node->eventListeners(); + size_t size = listeners.size(); + for (size_t i = 0; i < size; ++i) { + const RegisteredEventListener& r = *listeners[i]; + for (int j = 0; j < length; ++j) { + if (r.eventType() == eventTypes[j]) + return true; + } + } + return false; +} + bool CacheBuilder::AnyChildIsClick(Node* node) { + AtomicString eventTypes[5] = { + eventNames().clickEvent, + eventNames().mousedownEvent, + eventNames().mouseupEvent, + eventNames().keydownEvent, + eventNames().keyupEvent + }; + Node* child = node->firstChild(); while (child != NULL) { - if (child->isEventTargetNode()) { - EventTargetNode* target = (EventTargetNode*) child; - if (target->isFocusable() || - target->getEventListener(eventNames().clickEvent) || - target->getEventListener(eventNames().mousedownEvent) || - target->getEventListener(eventNames().mouseupEvent) || - target->getEventListener(eventNames().keydownEvent) || - target->getEventListener(eventNames().keyupEvent)) + if (child->isFocusable() || + NodeHasEventListeners(child, eventTypes, 5)) return true; - } if (AnyChildIsClick(child)) return true; child = child->nextSibling(); @@ -832,26 +794,32 @@ bool CacheBuilder::AnyIsClick(Node* node) { if (node->hasTagName(HTMLNames::bodyTag)) return AnyChildIsClick(node); - EventTargetNode* target = (EventTargetNode*) node; - if (target->getEventListener(eventNames().mouseoverEvent) == NULL && - target->getEventListener(eventNames().mouseoutEvent) == NULL && - target->getEventListener(eventNames().keydownEvent) == NULL && - target->getEventListener(eventNames().keyupEvent) == NULL) - return false; - if (target->getEventListener(eventNames().clickEvent)) - return false; - if (target->getEventListener(eventNames().mousedownEvent)) + + AtomicString eventTypeSetOne[4] = { + eventNames().mouseoverEvent, + eventNames().mouseoutEvent, + eventNames().keydownEvent, + eventNames().keyupEvent + }; + + if (!NodeHasEventListeners(node, eventTypeSetOne, 4)) return false; - if (target->getEventListener(eventNames().mouseupEvent)) + + AtomicString eventTypeSetTwo[3] = { + eventNames().clickEvent, + eventNames().mousedownEvent, + eventNames().mouseupEvent + }; + + if (NodeHasEventListeners(node, eventTypeSetTwo, 3)) return false; + return AnyChildIsClick(node); } void CacheBuilder::buildCache(CachedRoot* root) { Frame* frame = FrameAnd(this); - mLastKnownFocus = NULL; - m_areaBoundsMap.clear(); BuildFrame(frame, frame, root, (CachedFrame*) root); root->finishInit(); // set up frame parent pointers, child pointers setData((CachedFrame*) root); @@ -933,10 +901,8 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, Node* node = parent; int cacheIndex = 1; Node* focused = doc->focusedNode(); - if (focused) { - setLastFocus(focused); - cachedRoot->setFocusBounds(mLastKnownFocusBounds); - } + if (focused) + cachedRoot->setFocusBounds(focused->getRect()); int globalOffsetX, globalOffsetY; GetGlobalOffset(frame, &globalOffsetX, &globalOffsetY); while (walk.mMore || (node = node->traverseNextNode()) != NULL) { @@ -1004,39 +970,24 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, } RenderObject* nodeRenderer = node->renderer(); bool isTransparent = false; - bool hasFocusRing = true; + bool hasCursorRing = true; if (nodeRenderer != NULL) { RenderStyle* style = nodeRenderer->style(); if (style->visibility() == HIDDEN) continue; - if (nodeRenderer->isImage()) { // set all the area elements to have a link to their images - RenderImage* image = static_cast<RenderImage*>(nodeRenderer); - HTMLMapElement* map = image->imageMap(); - if (map) { - Node* node; - for (node = map->firstChild(); node; - node = node->traverseNextNode(map)) { - if (!node->hasTagName(HTMLNames::areaTag)) - continue; - HTMLAreaElement* area = static_cast<HTMLAreaElement*>(node); - m_areaBoundsMap.set(area, image); - } - } - } isTransparent = style->hasBackground() == false; #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR - hasFocusRing = style->tapHighlightColor().alpha() > 0; + hasCursorRing = style->tapHighlightColor().alpha() > 0; #endif } bool more = walk.mMore; walk.reset(); // GetGlobalBounds(node, &bounds, false); - bool computeFocusRings = false; + bool computeCursorRings = false; bool hasClip = false; bool hasMouseOver = false; bool isAnchor = false; bool isArea = node->hasTagName(HTMLNames::areaTag); - bool isInput = false; bool isPassword = false; bool isTextArea = false; bool isTextField = false; @@ -1055,8 +1006,6 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, IntRect bounds; IntRect absBounds; WTF::Vector<IntRect>* columns = NULL; - int minimumFocusableWidth = MINIMUM_FOCUSABLE_WIDTH; - int minimumFocusableHeight = MINIMUM_FOCUSABLE_HEIGHT; if (isArea) { HTMLAreaElement* area = static_cast<HTMLAreaElement*>(node); bounds = getAreaRect(area); @@ -1131,7 +1080,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, IntRect(0, 0, INT_MAX, INT_MAX); if (ConstructTextRects((WebCore::Text*) node, walk.mStart, (WebCore::Text*) walk.mFinalNode, walk.mEnd, globalOffsetX, - globalOffsetY, &bounds, clip, &cachedNode.focusRings()) == false) + globalOffsetY, &bounds, clip, &cachedNode.cursorRings()) == false) continue; absBounds = bounds; cachedNode.setBounds(bounds); @@ -1139,7 +1088,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, continue; if (bounds.height() < MINIMUM_FOCUSABLE_HEIGHT) continue; - computeFocusRings = true; + computeCursorRings = true; isUnclipped = true; // FIXME: to hide or partially occlude synthesized links, each // focus ring will also need the offset and length of characters // used to produce it @@ -1149,23 +1098,23 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, HTMLInputElement* input = (HTMLInputElement*) node; if (input->inputType() == HTMLInputElement::FILE) continue; - isInput = true; isTextField = input->isTextField(); + if (isTextField) + wantsKeyEvents = true; isPassword = input->inputType() == HTMLInputElement::PASSWORD; maxLength = input->maxLength(); name = input->name().string().copy(); isUnclipped = isTransparent; // can't detect if this is drawn on top (example: deviant.com login parts) } else if (node->hasTagName(HTMLNames::textareaTag)) - isTextArea = true; + isTextArea = wantsKeyEvents = true; else if (node->hasTagName(HTMLNames::aTag)) { const HTMLAnchorElement* anchorNode = (const HTMLAnchorElement*) node; if (!anchorNode->isFocusable() && !HasTriggerEvent(node)) continue; - EventTargetNode* target = (EventTargetNode*) node; - if (target->disabled()) + if (node->disabled()) continue; - hasMouseOver = target->getEventListener(eventNames().mouseoverEvent); + hasMouseOver = NodeHasEventListeners(node, &eventNames().mouseoverEvent, 1); isAnchor = true; KURL href = anchorNode->href(); if (!href.isEmpty() && !href.protocolIs("javascript")) @@ -1188,20 +1137,14 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, style->textAlign() == WebCore::RIGHT || style->textAlign() == WebCore::WEBKIT_RIGHT; } - minimumFocusableWidth += 4; - minimumFocusableHeight += 4; } takesFocus = true; - if (isAnchor) { - bounds = absBounds; - } else { + bounds = absBounds; + if (!isAnchor) { bool isFocusable = node->isKeyboardFocusable(NULL) || node->isMouseFocusable() || node->isFocusable(); if (isFocusable == false) { - if (node->isEventTargetNode() == false) - continue; - EventTargetNode* eventTargetNode = (EventTargetNode*) node; - if (eventTargetNode->disabled()) + if (node->disabled()) continue; bool overOrOut = HasOverOrOut(node); bool hasTrigger = HasTriggerEvent(node); @@ -1209,32 +1152,15 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, continue; takesFocus = hasTrigger; } - bounds = node->getRect(); - // For Bank of America site - if (isTextField && ((RenderBox*)nodeRenderer)->paddingLeft() > 100) { - int paddingLeft = ((RenderBox*)nodeRenderer)->paddingLeft(); - int paddingTop = ((RenderBox*)nodeRenderer)->paddingTop(); - int x = bounds.x() + paddingLeft; - int y = bounds.y() + paddingTop; - int width = bounds.width() - paddingLeft - ((RenderBox*)nodeRenderer)->paddingRight(); - int height = bounds.height() - paddingTop - ((RenderBox*)nodeRenderer)->paddingBottom(); - bounds.setLocation(IntPoint(x, y)); - bounds.setSize(IntSize(width, height)); - } - if (bounds.width() < minimumFocusableWidth) - continue; - if (bounds.height() < minimumFocusableHeight) - continue; - bounds.move(globalOffsetX, globalOffsetY); } - computeFocusRings = true; + computeCursorRings = true; keepNode: cachedNode.init(node); - if (computeFocusRings == false) { + if (computeCursorRings == false) { cachedNode.setBounds(bounds); - cachedNode.focusRings().append(bounds); + cachedNode.cursorRings().append(bounds); } else if (ConstructPartRects(node, bounds, cachedNode.boundsPtr(), - globalOffsetX, globalOffsetY, &cachedNode.focusRings()) == false) + globalOffsetX, globalOffsetY, &cachedNode.cursorRings()) == false) continue; keepTextNode: IntRect clip = hasClip ? bounds : absBounds; @@ -1254,22 +1180,21 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, clip.intersect(parentClip); hasClip = true; } - if (hasClip && cachedNode.clip(clip) == false) { + if (hasClip && !clip.isEmpty() && cachedNode.clip(clip) == false) { cachedNode.setBounds(clip); - cachedNode.focusRings().append(clip); + cachedNode.cursorRings().append(clip); isUnclipped = true; } cachedNode.setNavableRects(); cachedNode.setChildFrameIndex(-1); cachedNode.setExport(exported); - cachedNode.setHasFocusRing(hasFocusRing); + cachedNode.setHasCursorRing(hasCursorRing); cachedNode.setHasMouseOver(hasMouseOver); cachedNode.setHitBounds(absBounds); cachedNode.setIndex(cacheIndex); cachedNode.setIsAnchor(isAnchor); cachedNode.setIsArea(isArea); cachedNode.setIsFocus(isFocus); - cachedNode.setIsInput(isInput); cachedNode.setIsPassword(isPassword); cachedNode.setIsRtlText(isRtlText); cachedNode.setIsTextArea(isTextArea); @@ -1335,7 +1260,7 @@ bool CacheBuilder::CleanUpContainedNodes(CachedFrame* cachedFrame, lastNode->hasTagName(HTMLNames::bodyTag) || lastNode->hasTagName(HTMLNames::formTag)) { lastCached->setBounds(IntRect(0, 0, 0, 0)); - lastCached->focusRings().clear(); + lastCached->cursorRings().clear(); lastCached->setNavableRects(); return false; } @@ -1345,11 +1270,8 @@ bool CacheBuilder::CleanUpContainedNodes(CachedFrame* cachedFrame, lastNode->isKeyboardFocusable(NULL) == false && lastNode->isMouseFocusable() == false && lastNode->isFocusable() == false && - lastNode->isEventTargetNode() == true && HasOverOrOut(lastNode) == true && HasTriggerEvent(lastNode) == false; - if (cachedFrame->focusIndex() == lastChildIndex) - cachedFrame->setFocusIndex(last->mCachedNodeIndex); if (onlyChildCached->parent() == lastCached) onlyChildCached->setParentIndex(lastCached->parentIndex()); if (outerIsMouseMoveOnly || onlyChild->isKeyboardFocusable(NULL)) @@ -1535,11 +1457,13 @@ static bool validZip(int stateIndex, const UChar* zipPtr) #define MAX_PLACE_NAME_LENGTH 25 // the longest allowable one word place name -CacheBuilder::FoundState CacheBuilder::FindAddress(const UChar* chars, unsigned length, int* start, int* end) +CacheBuilder::FoundState CacheBuilder::FindAddress(const UChar* chars, + unsigned length, int* start, int* end, bool caseInsensitive) { FindState addressState; FindReset(&addressState); addressState.mWords[0] = addressState.mStarts[0] = chars; + addressState.mCaseInsensitive = caseInsensitive; FoundState state = FindPartialAddress(chars, chars, length, &addressState); if (state == FOUND_PARTIAL && addressState.mProgress == ZIP_CODE && addressState.mNumberCount == 0) { @@ -1760,6 +1684,8 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars } else if (s->mLetterCount >= MAX_PLACE_NAME_LENGTH) { break; } else if (s->mFirstLower != NULL) { + if (s->mCaseInsensitive) + goto resetWord; size_t length = chars - s->mFirstLower; if (length > 3) break; @@ -2381,14 +2307,28 @@ void CacheBuilder::FindResetNumber(FindState* state) state->mStorePtr = state->mStore; } -IntRect CacheBuilder::getAreaRect(const HTMLAreaElement* area) const +IntRect CacheBuilder::getAreaRect(const HTMLAreaElement* area) { - RenderImage* map = m_areaBoundsMap.get(area); - if (!map) - return IntRect(); - if (area->isDefault()) - return map->absoluteBoundingBoxRect(); - return area->getRect(map); + Node* node = area->document(); + while ((node = node->traverseNextNode()) != NULL) { + RenderObject* renderer = node->renderer(); + if (renderer && renderer->isRenderImage()) { + RenderImage* image = static_cast<RenderImage*>(renderer); + HTMLMapElement* map = image->imageMap(); + if (map) { + Node* n; + for (n = map->firstChild(); n; + n = n->traverseNextNode(map)) { + if (n == area) { + if (area->isDefault()) + return image->absoluteBoundingBoxRect(); + return area->getRect(image); + } + } + } + } + } + return IntRect(); } void CacheBuilder::GetGlobalOffset(Node* node, int* x, int * y) @@ -2432,20 +2372,26 @@ Frame* CacheBuilder::HasFrame(Node* node) bool CacheBuilder::HasOverOrOut(Node* node) { - EventTargetNode* target = (EventTargetNode*) node; - return target->getEventListener(eventNames().mouseoverEvent) || - target->getEventListener(eventNames().mouseoutEvent); + // eventNames are thread-local data, I avoid using 'static' variable here. + AtomicString eventTypes[2] = { + eventNames().mouseoverEvent, + eventNames().mouseoutEvent + }; + return NodeHasEventListeners(node, eventTypes, 2); } bool CacheBuilder::HasTriggerEvent(Node* node) { - EventTargetNode* target = (EventTargetNode*) node; - return target->getEventListener(eventNames().clickEvent) || - target->getEventListener(eventNames().mousedownEvent) || - target->getEventListener(eventNames().mouseupEvent) || - target->getEventListener(eventNames().keydownEvent) || - target->getEventListener(eventNames().keyupEvent); + AtomicString eventTypes[5] = { + eventNames().clickEvent, + eventNames().mousedownEvent, + eventNames().mouseupEvent, + eventNames().keydownEvent, + eventNames().keyupEvent + }; + + return NodeHasEventListeners(node, eventTypes, 5); } // #define EMAIL_PATTERN "x@y.d" // where 'x' is letters, numbers, and '-', '.', '_' ; 'y' is 'x' without the underscore, and 'd' is a valid domain @@ -2460,61 +2406,6 @@ bool CacheBuilder::IsDomainChar(UChar ch) return (body[ch >> 5] & 1 << (ch & 0x1f)) != 0; } -// does not find text to keep it fast -// (this assume text nodes are more rarely moved than other nodes) -Node* CacheBuilder::findByCenter(int x, int y) const -{ - DBG_NAV_LOGD("x=%d y=%d\n", x, y); - Frame* frame = FrameAnd(this); - Node* node = frame->document(); - ASSERT(node != NULL); - int globalOffsetX, globalOffsetY; - GetGlobalOffset(frame, &globalOffsetX, &globalOffsetY); - while ((node = node->traverseNextNode()) != NULL) { - Frame* child = HasFrame(node); - if (child != NULL) { - if (child->document() == NULL) - continue; - CacheBuilder* cacheBuilder = Builder(child); - // if (cacheBuilder->mViewBounds.isEmpty()) - // continue; - Node* result = cacheBuilder->findByCenter(x, y); - if (result != NULL) - return result; - } - if (node->isTextNode()) - continue; - IntRect bounds; - if (node->hasTagName(HTMLNames::areaTag)) { - HTMLAreaElement* area = static_cast<HTMLAreaElement*>(node); - bounds = getAreaRect(area); - bounds.move(globalOffsetX, globalOffsetY); - } else - bounds = node->getRect(); - if (bounds.isEmpty()) - continue; - bounds.move(globalOffsetX, globalOffsetY); - if (x != bounds.x() + (bounds.width() >> 1)) - continue; - if (y != bounds.y() + (bounds.height() >> 1)) - continue; - if (node->isKeyboardFocusable(NULL)) - return node; - if (node->isMouseFocusable()) - return node; - if (node->isFocusable()) - return node; - if (node->isEventTargetNode() == false) - continue; - if (AnyIsClick(node)) - continue; - if (HasTriggerEvent(node) == false) - continue; - return node; - } - return NULL; -} - bool CacheBuilder::isFocusableText(NodeWalk* walk, bool more, Node* node, CachedNodeType* type, String* exported) const { @@ -2733,29 +2624,6 @@ bool CacheBuilder::IsMailboxChar(UChar ch) return (body[ch >> 5] & 1 << (ch & 0x1f)) != 0; } -bool CacheBuilder::outOfDate() -{ - Node* kitFocusNode = currentFocus(); - if (mLastKnownFocus != kitFocusNode) { - DBG_NAV_LOGD("%s\n", "mLastKnownFocus != kitFocusNode"); - return true; - } - if (kitFocusNode == NULL) - return false; - IntRect kitBounds = kitFocusNode->getRect(); - bool result = kitBounds != mLastKnownFocusBounds; - if (result == true) - DBG_NAV_LOGD("%s\n", "kitBounds != mLastKnownFocusBounds"); - return result; -} - -void CacheBuilder::setLastFocus(Node* node) -{ - ASSERT(node); - mLastKnownFocus = node; - mLastKnownFocusBounds = node->getRect(); -} - bool CacheBuilder::setData(CachedFrame* cachedFrame) { Frame* frame = FrameAnd(this); @@ -2790,13 +2658,13 @@ bool CacheBuilder::setData(CachedFrame* cachedFrame) return true; } -bool CacheBuilder::validNode(void* matchFrame, void* matchNode) const +bool CacheBuilder::validNode(Frame* startFrame, void* matchFrame, + void* matchNode) { - Frame* frame = FrameAnd(this); - if (matchFrame == frame) { + if (matchFrame == startFrame) { if (matchNode == NULL) return true; - Node* node = frame->document(); + Node* node = startFrame->document(); while (node != NULL) { if (node == matchNode) { const IntRect& rect = node->hasTagName(HTMLNames::areaTag) ? @@ -2812,15 +2680,15 @@ bool CacheBuilder::validNode(void* matchFrame, void* matchNode) const DBG_NAV_LOGD("frame=%p valid node=%p invalid\n", matchFrame, matchNode); return false; } - Frame* child = frame->tree()->firstChild(); + Frame* child = startFrame->tree()->firstChild(); while (child) { - bool result = Builder(child)->validNode(matchFrame, matchNode); + bool result = validNode(child, matchFrame, matchNode); if (result) return result; child = child->tree()->nextSibling(); } #if DEBUG_NAV_UI - if (frame->tree()->parent() == NULL) + if (startFrame->tree()->parent() == NULL) DBG_NAV_LOGD("frame=%p node=%p false\n", matchFrame, matchNode); #endif return false; @@ -3020,7 +2888,7 @@ bool CacheBuilder::ConstructTextRects(Text* node, int start, if ((int) textBox->end() >= start) break; } while ((textBox = textBox->nextTextBox()) != NULL); - if (ConstructTextRect(node, textBox, start, relEnd, + if (textBox && ConstructTextRect(node, textBox, start, relEnd, x, y, focusBounds, clipBounds, result) == false) return false; } diff --git a/WebKit/android/nav/CacheBuilder.h b/WebKit/android/nav/CacheBuilder.h index 32ae0af..35bd623 100644 --- a/WebKit/android/nav/CacheBuilder.h +++ b/WebKit/android/nav/CacheBuilder.h @@ -31,7 +31,6 @@ #include "IntRect.h" #include "PlatformString.h" #include "TextDirection.h" -#include "wtf/HashMap.h" #include "wtf/Vector.h" #define NAVIGATION_MAX_PHONE_LENGTH 14 @@ -39,7 +38,8 @@ using namespace WebCore; namespace WebCore { - + +class AtomicString; class Document; class Frame; class HTMLAreaElement; @@ -47,7 +47,6 @@ class InlineTextBox; class Node; class PlatformGraphicsContext; class RenderFlow; -class RenderImage; class RenderObject; class RenderLayer; class Text; @@ -89,13 +88,11 @@ public: mAllowableTypes & ~EMAIL_CACHEDNODETYPE); } void disallowPhoneDetection() { mAllowableTypes = (CachedNodeType) ( mAllowableTypes & ~PHONE_CACHEDNODETYPE); } - static FoundState FindAddress(const UChar* , unsigned length, int* start, int* end); - Node* findByCenter(int x, int y) const; + static FoundState FindAddress(const UChar* , unsigned length, int* start, + int* end, bool caseInsensitive); static void GetGlobalOffset(Frame* , int* x, int * y); static void GetGlobalOffset(Node* , int* x, int * y); - bool outOfDate(); - void setLastFocus(Node* ); - bool validNode(void* framePtr, void* nodePtr) const; + static bool validNode(Frame* startFrame, void* framePtr, void* nodePtr); private: enum AddressProgress { NO_ADDRESS, @@ -167,6 +164,7 @@ private: bool mOpenParen; bool mInitialized; bool mContinuationNode; + bool mCaseInsensitive; }; struct ClipColumnTracker { IntRect mBounds; @@ -194,6 +192,7 @@ private: WTF::Vector<IntRect>* result, IntRect* focusBounds); static bool AnyIsClick(Node* node); static bool AnyChildIsClick(Node* node); + static bool NodeHasEventListeners(Node* node, AtomicString* eventTypes, int length); void BuildFrame(Frame* root, Frame* frame, CachedRoot* cachedRoot, CachedFrame* cachedFrame); bool CleanUpContainedNodes(CachedFrame* cachedFrame, @@ -213,7 +212,7 @@ private: static Frame* FrameAnd(CacheBuilder* focusNav); static Frame* FrameAnd(const CacheBuilder* focusNav); static CacheBuilder* Builder(Frame* ); - IntRect getAreaRect(const HTMLAreaElement* area) const; + static IntRect getAreaRect(const HTMLAreaElement* area); static Frame* HasFrame(Node* ); static bool HasOverOrOut(Node* ); static bool HasTriggerEvent(Node* ); @@ -226,10 +225,7 @@ private: bool setData(CachedFrame* ); Node* tryFocus(Direction direction); Node* trySegment(Direction direction, int mainStart, int mainEnd); - Node* mLastKnownFocus; - IntRect mLastKnownFocusBounds; CachedNodeType mAllowableTypes; - WTF::HashMap<const HTMLAreaElement* , RenderImage* > m_areaBoundsMap; #if DUMP_NAV_CACHE public: class Debug { @@ -251,7 +247,6 @@ private: void localName(Node* node); void newLine(int indent = 0); void print(const char* name, unsigned len); - void renderTree(RenderObject* , int indent, Node* , int count); void setIndent(int ); void uChar(const UChar* name, unsigned len, bool hex); void validateFrame(); diff --git a/WebKit/android/nav/CachedFrame.cpp b/WebKit/android/nav/CachedFrame.cpp index 0eefad1..4bf9805 100644 --- a/WebKit/android/nav/CachedFrame.cpp +++ b/WebKit/android/nav/CachedFrame.cpp @@ -36,7 +36,7 @@ namespace android { -bool CachedFrame::CheckBetween(Direction direction, const WebCore::IntRect& bestRect, +bool CachedFrame::CheckBetween(Direction direction, const WebCore::IntRect& bestRect, const WebCore::IntRect& prior, WebCore::IntRect* result) { int left, top, width, height; @@ -86,7 +86,7 @@ bool CachedFrame::checkBetween(BestData* best, Direction direction) do { WebCore::IntRect edges; Direction check = (Direction) (index & DIRECTION_MASK); - if (CheckBetween(check, bestRect, + if (CheckBetween(check, bestRect, history()->priorBounds(), &edges) == false) continue; WebCore::IntRect clip = mRoot->scrolledBounds(); @@ -96,7 +96,7 @@ bool CachedFrame::checkBetween(BestData* best, Direction direction) findClosest(&test, direction, check, &clip); if (test.mNode == NULL) continue; - if (direction == check) + if (direction == check) break; } while (++index < limit); if (test.mNode == NULL) @@ -105,47 +105,46 @@ bool CachedFrame::checkBetween(BestData* best, Direction direction) return true; } -bool CachedFrame::checkVisited(const CachedNode* node, Direction direction) const -{ - return history()->checkVisited(node, direction); +bool CachedFrame::checkVisited(const CachedNode* node, Direction direction) const +{ + return history()->checkVisited(node, direction); } -void CachedFrame::clearFocus() +void CachedFrame::clearCursor() { - if (mFocus < 0) + DBG_NAV_LOGD("mCursorIndex=%d", mCursorIndex); + if (mCursorIndex < CURSOR_SET) return; - CachedNode& focus = mCachedNodes[mFocus]; - focus.clearFocus(this); - mFocus = -1; + CachedNode& cursor = mCachedNodes[mCursorIndex]; + cursor.clearCursor(this); + mCursorIndex = CURSOR_CLEARED; // initialized and explicitly cleared } -// the thing that sucks is that when you're on a link, you want to navigate next door to a link just like this one, but can't make it -// so with all my other sucky compares, maybe there needs to be one that prefers links that are aligned with the current focus... - // returns 0 if test is preferable to best, 1 if not preferable, or -1 if unknown -int CachedFrame::compare(BestData& testData, const BestData& bestData, const CachedNode* focus) const +int CachedFrame::compare(BestData& testData, const BestData& bestData, + const CachedNode* cursor) const { if (testData.mNode->tabIndex() != bestData.mNode->tabIndex()) { if (testData.mNode->tabIndex() < bestData.mNode->tabIndex() - || (focus && focus->tabIndex() < bestData.mNode->tabIndex())) { + || (cursor && cursor->tabIndex() < bestData.mNode->tabIndex())) { testData.mNode->setCondition(CachedNode::HIGHER_TAB_INDEX); return REJECT_TEST; } return TEST_IS_BEST; } -// start here; - // if the test minor axis line intersects the line segment between focus center and best center, choose it + // if the test minor axis line intersects the line segment between cursor + // center and best center, choose it // give more weight to exact major axis alignment (rows, columns) if (testData.mInNav != bestData.mInNav) { if (bestData.mInNav) { - testData.mNode->setCondition(CachedNode::IN_FOCUS); + testData.mNode->setCondition(CachedNode::IN_CURSOR); return REJECT_TEST; } return TEST_IS_BEST; } if (testData.mInNav) { if (bestData.mMajorDelta < testData.mMajorDelta) { - testData.mNode->setCondition(CachedNode::CLOSER_IN_FOCUS); + testData.mNode->setCondition(CachedNode::CLOSER_IN_CURSOR); return REJECT_TEST; } if (testData.mMajorDelta < bestData.mMajorDelta) @@ -157,13 +156,6 @@ int CachedFrame::compare(BestData& testData, const BestData& bestData, const Cac } if ((testData.mMajorDelta ^ bestData.mMajorDelta) < 0) // one above, one below (or one left, one right) return TEST_IS_BEST; -// SkFixed focusMultiplier = SK_Fixed1; -// if (focus != NULL) { -// if (testData.mMajorDelta < bestData.mMajorDelta) { -// // use bestData.mMajorDelta, -// } else if (bestData.mMajorDelta < testData.mMajorDelta) { -// -// } bool bestInWorking = bestData.inOrSubsumesWorking(); bool testInWorking = testData.inOrSubsumesWorking(); if (bestInWorking && testData.mWorkingOutside && testData.mNavOutside) { @@ -183,9 +175,9 @@ int CachedFrame::compare(BestData& testData, const BestData& bestData, const Cac return TEST_IS_BEST; } #if 01 // hopefully butt test will remove need for this - if (testData.mFocusChild != bestData.mFocusChild) { - if (bestData.mFocusChild) { - testData.mNode->setCondition(CachedNode::IN_FOCUS_CHILDREN); + if (testData.mCursorChild != bestData.mCursorChild) { + if (bestData.mCursorChild) { + testData.mNode->setCondition(CachedNode::IN_CURSOR_CHILDREN); return REJECT_TEST; } return TEST_IS_BEST; @@ -210,7 +202,7 @@ int CachedFrame::compare(BestData& testData, const BestData& bestData, const Cac } if (testOverlap && testData.mMajorDelta < bestData.mMajorDelta) return TEST_IS_BEST; - if (bestOverlap && bestData.mMajorDelta2 < testData.mMajorDelta2) { + if (bestOverlap && bestData.mMajorDelta2 < testData.mMajorDelta2) { testData.mNode->setCondition(CachedNode::CLOSER_TOP); return REJECT_TEST; } @@ -218,7 +210,7 @@ int CachedFrame::compare(BestData& testData, const BestData& bestData, const Cac return TEST_IS_BEST; #if 01 if (bestOverlap && ((bestData.mSideDistance <= 0 && testData.mSideDistance > 0) || - abs(bestData.mSideDistance) < abs(testData.mSideDistance))) { + abs(bestData.mSideDistance) < abs(testData.mSideDistance))) { testData.mNode->setCondition(CachedNode::LEFTMOST); return REJECT_TEST; } @@ -240,7 +232,7 @@ int CachedFrame::compare(BestData& testData, const BestData& bestData, const Cac // and off by a lot causes sideDistance to have little or no effect // try elliptical distance -- lengthen side contribution // these ASSERTs should not fire, but do fire on mail.google.com - // can't debug yet, won't reproduce + // can't debug yet, won't reproduce ASSERT(testDistance >= 0); ASSERT(bestDistance >= 0); testDistance += testDistance; // multiply by 2 @@ -295,23 +287,36 @@ int CachedFrame::compare(BestData& testData, const BestData& bestData, const Cac return UNDECIDED; } -const CachedNode* CachedFrame::currentFocus(const CachedFrame** framePtr) const +const CachedNode* CachedFrame::currentCursor(const CachedFrame** framePtr) const { if (framePtr) *framePtr = this; - if (mFocus < 0) + if (mCursorIndex < CURSOR_SET) return NULL; - const CachedNode* result = &mCachedNodes[mFocus]; + const CachedNode* result = &mCachedNodes[mCursorIndex]; + const CachedFrame* frame = hasFrame(result); + if (frame != NULL) + return frame->currentCursor(framePtr); + (const_cast<CachedNode*>(result))->fixUpCursorRects(mRoot); + return result; +} + +const CachedNode* CachedFrame::currentFocus(const CachedFrame** framePtr) const +{ + if (framePtr) + *framePtr = this; + if (mFocusIndex < 0) + return NULL; + const CachedNode* result = &mCachedNodes[mFocusIndex]; const CachedFrame* frame = hasFrame(result); if (frame != NULL) return frame->currentFocus(framePtr); - (const_cast<CachedNode*>(result))->fixUpFocusRects(); return result; } -bool CachedFrame::directionChange() const -{ - return history()->directionChange(); +bool CachedFrame::directionChange() const +{ + return history()->directionChange(); } #ifdef BROWSER_DEBUG @@ -320,18 +325,20 @@ CachedNode* CachedFrame::find(WebCore::Node* node) // !!! probably debugging onl for (CachedNode* test = mCachedNodes.begin(); test != mCachedNodes.end(); test++) if (node == test->webCoreNode()) return test; - for (CachedFrame* frame = mCachedFrames.begin(); frame != mCachedFrames.end(); + for (CachedFrame* frame = mCachedFrames.begin(); frame != mCachedFrames.end(); frame++) { CachedNode* result = frame->find(node); if (result != NULL) return result; } - return NULL; + return NULL; } #endif -const CachedNode* CachedFrame::findBestAt(const WebCore::IntRect& rect, int* best, - bool* inside, const CachedNode** directHit, const CachedFrame** framePtr, int* x, int* y) const +const CachedNode* CachedFrame::findBestAt(const WebCore::IntRect& rect, + int* best, bool* inside, const CachedNode** directHit, + const CachedFrame** framePtr, int* x, int* y, + bool checkForHiddenStart) const { const CachedNode* result = NULL; int rectWidth = rect.width(); @@ -345,13 +352,13 @@ const CachedNode* CachedFrame::findBestAt(const WebCore::IntRect& rect, int* bes BestData testData; testData.mNode = test; testData.mMouseBounds = testData.mNodeBounds = test->getBounds(); - bool checkForHidden = true; + bool checkForHidden = checkForHiddenStart; for (size_t part = 0; part < parts; part++) { - if (test->focusRings().at(part).intersects(rect)) { + if (test->cursorRings().at(part).intersects(rect)) { if (checkForHidden && mRoot->maskIfHidden(&testData) == true) break; checkForHidden = false; - WebCore::IntRect testRect = test->focusRings().at(part); + WebCore::IntRect testRect = test->cursorRings().at(part); testRect.intersect(testData.mMouseBounds); if (testRect.contains(center)) { // We have a direct hit. @@ -372,12 +379,12 @@ const CachedNode* CachedFrame::findBestAt(const WebCore::IntRect& rect, int* bes } } if (NULL != *directHit) { - // If we have a direct hit already, there is no need to - // calculate the distances, or check the other focusring parts + // If we have a direct hit already, there is no need to + // calculate the distances, or check the other parts break; } WebCore::IntRect both = rect; - int smaller = testRect.width() < testRect.height() ? + int smaller = testRect.width() < testRect.height() ? testRect.width() : testRect.height(); smaller -= rectWidth; int inset = smaller < rectWidth ? smaller : rectWidth; @@ -390,7 +397,7 @@ const CachedNode* CachedFrame::findBestAt(const WebCore::IntRect& rect, int* bes bool testInside = testRect.contains(center); if (*inside && !testInside) continue; - WebCore::IntPoint testCenter = WebCore::IntPoint(testRect.x() + + WebCore::IntPoint testCenter = WebCore::IntPoint(testRect.x() + (testRect.width() >> 1), testRect.y() + (testRect.height() >> 1)); int dx = testCenter.x() - center.x(); int dy = testCenter.y() - center.y(); @@ -406,10 +413,10 @@ const CachedNode* CachedFrame::findBestAt(const WebCore::IntRect& rect, int* bes } } } - for (const CachedFrame* frame = mCachedFrames.begin(); + for (const CachedFrame* frame = mCachedFrames.begin(); frame != mCachedFrames.end(); frame++) { - const CachedNode* frameResult = frame->findBestAt(rect, best, inside, directHit, - framePtr, x, y); + const CachedNode* frameResult = frame->findBestAt(rect, best, inside, + directHit, framePtr, x, y, checkForHiddenStart); if (NULL != frameResult) result = frameResult; } @@ -424,7 +431,7 @@ const CachedFrame* CachedFrame::findBestFrameAt(int x, int y) const if (mLocalViewBounds.contains(x, y) == false) return NULL; const CachedFrame* result = this; - for (const CachedFrame* frame = mCachedFrames.begin(); + for (const CachedFrame* frame = mCachedFrames.begin(); frame != mCachedFrames.end(); frame++) { const CachedFrame* frameResult = frame->findBestFrameAt(x, y); if (NULL != frameResult) @@ -433,7 +440,7 @@ const CachedFrame* CachedFrame::findBestFrameAt(int x, int y) const return result; } -const CachedNode* CachedFrame::findBestHitAt(const WebCore::IntRect& rect, +const CachedNode* CachedFrame::findBestHitAt(const WebCore::IntRect& rect, int* best, const CachedFrame** framePtr, int* x, int* y) const { const CachedNode* result = NULL; @@ -453,21 +460,21 @@ const CachedNode* CachedFrame::findBestHitAt(const WebCore::IntRect& rect, if (mRoot->maskIfHidden(&testData) == true) continue; const WebCore::IntRect& bounds = testData.mMouseBounds; - WebCore::IntPoint testCenter = WebCore::IntPoint(bounds.x() + + WebCore::IntPoint testCenter = WebCore::IntPoint(bounds.x() + (bounds.width() >> 1), bounds.y() + (bounds.height() >> 1)); int dx = testCenter.x() - center.x(); int dy = testCenter.y() - center.y(); int distance = dx * dx + dy * dy; - if (*best <= distance) + if (*best <= distance) continue; *best = distance; result = test; *framePtr = this; - const WebCore::IntRect& focusRect = test->focusRings().at(0); - *x = focusRect.x() + (focusRect.width() >> 1); - *y = focusRect.y() + (focusRect.height() >> 1); + const WebCore::IntRect& cursorRect = test->cursorRings().at(0); + *x = cursorRect.x() + (cursorRect.width() >> 1); + *y = cursorRect.y() + (cursorRect.height() >> 1); } - for (const CachedFrame* frame = mCachedFrames.begin(); + for (const CachedFrame* frame = mCachedFrames.begin(); frame != mCachedFrames.end(); frame++) { const CachedNode* frameResult = frame->findBestHitAt(rect, best, framePtr, x, y); @@ -478,7 +485,7 @@ const CachedNode* CachedFrame::findBestHitAt(const WebCore::IntRect& rect, } void CachedFrame::findClosest(BestData* bestData, Direction originalDirection, - Direction direction, WebCore::IntRect* clip) const + Direction direction, WebCore::IntRect* clip) const { const CachedNode* test = mCachedNodes.begin(); while ((test = test->traverseNextNode()) != NULL) { @@ -491,13 +498,13 @@ void CachedFrame::findClosest(BestData* bestData, Direction originalDirection, } if (test->noSecondChance()) continue; - if (test->isFocusable(*clip) == false) + if (test->isNavable(*clip) == false) continue; if (checkVisited(test, originalDirection) == false) continue; size_t partMax = test->navableRects(); for (size_t part = 0; part < partMax; part++) { - WebCore::IntRect testBounds = test->focusRings().at(part); + WebCore::IntRect testBounds = test->cursorRings().at(part); if (clip->intersects(testBounds) == false) continue; if (clip->contains(testBounds) == false) { @@ -516,7 +523,7 @@ void CachedFrame::findClosest(BestData* bestData, Direction originalDirection, continue; } int distance; - // seems like distance for UP for instance needs to be 'test top closest to + // seems like distance for UP for instance needs to be 'test top closest to // clip bottom' -- keep the old code but try this instead switch (direction) { #if 0 @@ -530,74 +537,72 @@ void CachedFrame::findClosest(BestData* bestData, Direction originalDirection, case UP: distance = clip->bottom() - testBounds.y(); break; case DOWN: distance = testBounds.bottom() - clip->y(); break; #endif - default: + default: distance = 0; ASSERT(0); } if (distance < bestData->mDistance) { bestData->mNode = test; bestData->mFrame = this; bestData->mDistance = distance; - bestData->mMouseBounds = bestData->mNodeBounds = - test->focusRings().at(part); + bestData->mMouseBounds = bestData->mNodeBounds = + test->cursorRings().at(part); CachedHistory* cachedHistory = history(); switch (direction) { - case LEFT: - bestData->setLeftDirection(cachedHistory); + case LEFT: + bestData->setLeftDirection(cachedHistory); break; - case RIGHT: - bestData->setRightDirection(cachedHistory); + case RIGHT: + bestData->setRightDirection(cachedHistory); break; - case UP: - bestData->setUpDirection(cachedHistory); + case UP: + bestData->setUpDirection(cachedHistory); break; - case DOWN: - bestData->setDownDirection(cachedHistory); + case DOWN: + bestData->setDownDirection(cachedHistory); break; - default: - ASSERT(0); + default: + ASSERT(0); } } } } } -bool CachedFrame::finishInit() +void CachedFrame::finishInit() { CachedNode* lastCached = lastNode(); lastCached->setLast(); CachedFrame* child = mCachedFrames.begin(); while (child != mCachedFrames.end()) { child->mParent = this; - if (child->finishInit()) - setFocusIndex(child->indexInParent()); + child->finishInit(); child++; } - return focusIndex() > 0; } -const CachedNode* CachedFrame::frameDown(const CachedNode* test, const CachedNode* limit, BestData* bestData, - const CachedNode* focus) const +const CachedNode* CachedFrame::frameDown(const CachedNode* test, const CachedNode* limit, BestData* bestData, + const CachedNode* cursor) const { BestData originalData = *bestData; do { - if (moveInFrame(&CachedFrame::frameDown, test, bestData, focus)) + if (moveInFrame(&CachedFrame::frameDown, test, bestData, cursor)) continue; BestData testData; - if (frameNodeCommon(testData, test, bestData, &originalData, focus) == REJECT_TEST) + if (frameNodeCommon(testData, test, bestData, &originalData, cursor) == REJECT_TEST) continue; if (checkVisited(test, DOWN) == false) continue; size_t parts = test->navableRects(); for (size_t part = 0; part < parts; part++) { - testData.mNodeBounds = test->focusRings().at(part); + testData.mNodeBounds = test->cursorRings().at(part); if (testData.setDownDirection(history())) continue; - int result = framePartCommon(testData, test, bestData, focus); + int result = framePartCommon(testData, test, bestData, cursor); if (result == REJECT_TEST) continue; if (result == 0 && limit == NULL) { // retry all data up to this point, since smaller may have replaced node preferable to larger BestData innerData = testData; - frameDown(document(), test, &innerData, focus); + frameDown(document(), test, &innerData, cursor); if (checkVisited(innerData.mNode, DOWN)) { *bestData = innerData; continue; @@ -607,37 +612,37 @@ const CachedNode* CachedFrame::frameDown(const CachedNode* test, const CachedNod *bestData = testData; } } while ((test = test->traverseNextNode()) != limit); - ASSERT(focus == NULL || bestData->mNode != focus); - // does the best contain something (or, is it contained by an area which is not the focus?) + ASSERT(cursor == NULL || bestData->mNode != cursor); + // does the best contain something (or, is it contained by an area which is not the cursor?) // if so, is the conainer/containee should have been chosen, but wasn't -- so there's a better choice // in the doc list prior to this choice - // + // return bestData->mNode; } -const CachedNode* CachedFrame::frameLeft(const CachedNode* test, const CachedNode* limit, BestData* bestData, - const CachedNode* focus) const +const CachedNode* CachedFrame::frameLeft(const CachedNode* test, const CachedNode* limit, BestData* bestData, + const CachedNode* cursor) const { BestData originalData = *bestData; do { - if (moveInFrame(&CachedFrame::frameLeft, test, bestData, focus)) + if (moveInFrame(&CachedFrame::frameLeft, test, bestData, cursor)) continue; BestData testData; - if (frameNodeCommon(testData, test, bestData, &originalData, focus) == REJECT_TEST) + if (frameNodeCommon(testData, test, bestData, &originalData, cursor) == REJECT_TEST) continue; if (checkVisited(test, LEFT) == false) continue; size_t parts = test->navableRects(); for (size_t part = 0; part < parts; part++) { - testData.mNodeBounds = test->focusRings().at(part); + testData.mNodeBounds = test->cursorRings().at(part); if (testData.setLeftDirection(history())) continue; - int result = framePartCommon(testData, test, bestData, focus); + int result = framePartCommon(testData, test, bestData, cursor); if (result == REJECT_TEST) continue; if (result == 0 && limit == NULL) { // retry all data up to this point, since smaller may have replaced node preferable to larger BestData innerData = testData; - frameLeft(document(), test, &innerData, focus); + frameLeft(document(), test, &innerData, cursor); if (checkVisited(innerData.mNode, LEFT)) { *bestData = innerData; continue; @@ -647,12 +652,12 @@ const CachedNode* CachedFrame::frameLeft(const CachedNode* test, const CachedNod *bestData = testData; } } while ((test = test->traverseNextNode()) != limit); // FIXME ??? left and up should use traversePreviousNode to choose reverse document order - ASSERT(focus == NULL || bestData->mNode != focus); + ASSERT(cursor == NULL || bestData->mNode != cursor); return bestData->mNode; } int CachedFrame::frameNodeCommon(BestData& testData, const CachedNode* test, BestData* bestData, BestData* originalData, - const CachedNode* focus) const + const CachedNode* cursor) const { testData.mFrame = this; testData.mNode = test; @@ -662,34 +667,34 @@ int CachedFrame::frameNodeCommon(BestData& testData, const CachedNode* test, Bes return REJECT_TEST; } if (mRoot->scrolledBounds().intersects(test->bounds()) == false) { - testData.mNode->setCondition(CachedNode::FOCUSABLE); + testData.mNode->setCondition(CachedNode::NAVABLE); return REJECT_TEST; } -// if (isFocusable(test, &testData.mNodeBounds, walk) == false) { -// testData.mNode->setCondition(CachedNode::FOCUSABLE); +// if (isNavable(test, &testData.mNodeBounds, walk) == false) { +// testData.mNode->setCondition(CachedNode::NAVABLE); // return REJECT_TEST; // } // - if (test == focus) { - testData.mNode->setCondition(CachedNode::NOT_FOCUS_NODE); + if (test == cursor) { + testData.mNode->setCondition(CachedNode::NOT_CURSOR_NODE); return REJECT_TEST; } -// if (test->bounds().contains(mRoot->focusBounds())) { -// testData.mNode->setCondition(CachedNode::NOT_ENCLOSING_FOCUS); +// if (test->bounds().contains(mRoot->cursorBounds())) { +// testData.mNode->setCondition(CachedNode::NOT_ENCLOSING_CURSOR); // return REJECT_TEST; // } - void* par = focus ? focus->parentGroup() : NULL; - testData.mFocusChild = test->parentGroup() == par; + void* par = cursor ? cursor->parentGroup() : NULL; + testData.mCursorChild = test->parentGroup() == par; #if 0 // not debugged - if (focus && focus->hasMouseOver() && test->hasMouseOver() == false && - focus->bounds().contains(test->bounds())) + if (cursor && cursor->hasMouseOver() && test->hasMouseOver() == false && + cursor->bounds().contains(test->bounds())) return REJECT_TEST; #endif - if (bestData->mNode == NULL) + if (bestData->mNode == NULL) return TEST_IS_BEST; #if 0 // not debugged - if (focus && focus->hasMouseOver() && test->hasMouseOver() == false && - focus->bounds().contains(test->bounds())) + if (cursor && cursor->hasMouseOver() && test->hasMouseOver() == false && + cursor->bounds().contains(test->bounds())) return REJECT_TEST; if (test->hasMouseOver() != bestData->mNode->hasMouseOver()) { if (test->hasMouseOver()) { @@ -703,15 +708,15 @@ int CachedFrame::frameNodeCommon(BestData& testData, const CachedNode* test, Bes test->setCondition(CachedNode::ANCHOR_IN_ANCHOR); return REJECT_TEST; } - } - } + } + } #endif - if (focus && testData.mNode->parentIndex() != bestData->mNode->parentIndex()) { - int focusParentIndex = focus->parentIndex(); - if (focusParentIndex >= 0) { - if (bestData->mNode->parentIndex() == focusParentIndex) + if (cursor && testData.mNode->parentIndex() != bestData->mNode->parentIndex()) { + int cursorParentIndex = cursor->parentIndex(); + if (cursorParentIndex >= 0) { + if (bestData->mNode->parentIndex() == cursorParentIndex) return REJECT_TEST; - if (testData.mNode->parentIndex() == focusParentIndex) + if (testData.mNode->parentIndex() == cursorParentIndex) return TEST_IS_BEST; } } @@ -743,15 +748,15 @@ int CachedFrame::frameNodeCommon(BestData& testData, const CachedNode* test, Bes } int CachedFrame::framePartCommon(BestData& testData, - const CachedNode* test, BestData* bestData, const CachedNode* focus) const + const CachedNode* test, BestData* bestData, const CachedNode* cursor) const { - if (testData.mNodeBounds.contains(mRoot->focusBounds())) { - testData.mNode->setCondition(CachedNode::NOT_ENCLOSING_FOCUS); + if (cursor && testData.mNodeBounds.contains(cursor->bounds())) { + testData.mNode->setCondition(CachedNode::NOT_ENCLOSING_CURSOR); return REJECT_TEST; } testData.setDistances(); if (bestData->mNode != NULL) { - int compared = compare(testData, *bestData, focus); + int compared = compare(testData, *bestData, cursor); if (compared == 0 && test->isArea() == false && bestData->mNode->isArea() == false) goto pickTest; if (compared >= 0) @@ -761,29 +766,29 @@ pickTest: return -1; // pick test } -const CachedNode* CachedFrame::frameRight(const CachedNode* test, const CachedNode* limit, BestData* bestData, - const CachedNode* focus) const +const CachedNode* CachedFrame::frameRight(const CachedNode* test, const CachedNode* limit, BestData* bestData, + const CachedNode* cursor) const { BestData originalData = *bestData; do { - if (moveInFrame(&CachedFrame::frameRight, test, bestData, focus)) + if (moveInFrame(&CachedFrame::frameRight, test, bestData, cursor)) continue; BestData testData; - if (frameNodeCommon(testData, test, bestData, &originalData, focus) == REJECT_TEST) + if (frameNodeCommon(testData, test, bestData, &originalData, cursor) == REJECT_TEST) continue; if (checkVisited(test, RIGHT) == false) continue; size_t parts = test->navableRects(); for (size_t part = 0; part < parts; part++) { - testData.mNodeBounds = test->focusRings().at(part); + testData.mNodeBounds = test->cursorRings().at(part); if (testData.setRightDirection(history())) continue; - int result = framePartCommon(testData, test, bestData, focus); + int result = framePartCommon(testData, test, bestData, cursor); if (result == REJECT_TEST) continue; if (result == 0 && limit == NULL) { // retry all data up to this point, since smaller may have replaced node preferable to larger BestData innerData = testData; - frameRight(document(), test, &innerData, focus); + frameRight(document(), test, &innerData, cursor); if (checkVisited(innerData.mNode, RIGHT)) { *bestData = innerData; continue; @@ -793,33 +798,33 @@ const CachedNode* CachedFrame::frameRight(const CachedNode* test, const CachedNo *bestData = testData; } } while ((test = test->traverseNextNode()) != limit); - ASSERT(focus == NULL || bestData->mNode != focus); + ASSERT(cursor == NULL || bestData->mNode != cursor); return bestData->mNode; } -const CachedNode* CachedFrame::frameUp(const CachedNode* test, const CachedNode* limit, BestData* bestData, - const CachedNode* focus) const +const CachedNode* CachedFrame::frameUp(const CachedNode* test, const CachedNode* limit, BestData* bestData, + const CachedNode* cursor) const { BestData originalData = *bestData; do { - if (moveInFrame(&CachedFrame::frameUp, test, bestData, focus)) + if (moveInFrame(&CachedFrame::frameUp, test, bestData, cursor)) continue; BestData testData; - if (frameNodeCommon(testData, test, bestData, &originalData, focus) == REJECT_TEST) + if (frameNodeCommon(testData, test, bestData, &originalData, cursor) == REJECT_TEST) continue; if (checkVisited(test, UP) == false) continue; size_t parts = test->navableRects(); for (size_t part = 0; part < parts; part++) { - testData.mNodeBounds = test->focusRings().at(part); + testData.mNodeBounds = test->cursorRings().at(part); if (testData.setUpDirection(history())) continue; - int result = framePartCommon(testData, test, bestData, focus); + int result = framePartCommon(testData, test, bestData, cursor); if (result == REJECT_TEST) continue; if (result == 0 && limit == NULL) { // retry all data up to this point, since smaller may have replaced node preferable to larger BestData innerData = testData; - frameUp(document(), test, &innerData, focus); + frameUp(document(), test, &innerData, cursor); if (checkVisited(innerData.mNode, UP)) { *bestData = innerData; continue; @@ -829,56 +834,66 @@ const CachedNode* CachedFrame::frameUp(const CachedNode* test, const CachedNode* *bestData = testData; } } while ((test = test->traverseNextNode()) != limit); // FIXME ??? left and up should use traversePreviousNode to choose reverse document order - ASSERT(focus == NULL || bestData->mNode != focus); + ASSERT(cursor == NULL || bestData->mNode != cursor); return bestData->mNode; } const CachedFrame* CachedFrame::hasFrame(const CachedNode* node) const -{ - return node->isFrame() ? &mCachedFrames[node->childFrameIndex()] : NULL; +{ + return node->isFrame() ? &mCachedFrames[node->childFrameIndex()] : NULL; +} + +void CachedFrame::hideCursor() +{ + DBG_NAV_LOGD("mCursorIndex=%d", mCursorIndex); + if (mCursorIndex < CURSOR_SET) + return; + CachedNode& cursor = mCachedNodes[mCursorIndex]; + cursor.hideCursor(this); } -CachedHistory* CachedFrame::history() const -{ - return mRoot->rootHistory(); +CachedHistory* CachedFrame::history() const +{ + return mRoot->rootHistory(); } -void CachedFrame::init(const CachedRoot* root, int childFrameIndex, +void CachedFrame::init(const CachedRoot* root, int childFrameIndex, WebCore::Frame* frame) { mContents = WebCore::IntRect(0, 0, 0, 0); // fixed up for real in setData() mLocalViewBounds = WebCore::IntRect(0, 0, 0, 0); mViewBounds = WebCore::IntRect(0, 0, 0, 0); mRoot = root; - mFocus = -1; + mCursorIndex = CURSOR_UNINITIALIZED; // not explicitly cleared + mFocusIndex = -1; mFrame = frame; mParent = NULL; // set up parents after stretchy arrays are set up - mIndex = childFrameIndex; + mIndexInParent = childFrameIndex; } -int CachedFrame::minWorkingHorizontal() const -{ - return history()->minWorkingHorizontal(); +int CachedFrame::minWorkingHorizontal() const +{ + return history()->minWorkingHorizontal(); } -int CachedFrame::minWorkingVertical() const -{ +int CachedFrame::minWorkingVertical() const +{ return history()->minWorkingVertical(); } - -int CachedFrame::maxWorkingHorizontal() const -{ - return history()->maxWorkingHorizontal(); + +int CachedFrame::maxWorkingHorizontal() const +{ + return history()->maxWorkingHorizontal(); } - -int CachedFrame::maxWorkingVertical() const -{ - return history()->maxWorkingVertical(); + +int CachedFrame::maxWorkingVertical() const +{ + return history()->maxWorkingVertical(); } -bool CachedFrame::moveInFrame(MoveInDirection moveInDirection, +bool CachedFrame::moveInFrame(MoveInDirection moveInDirection, const CachedNode* test, BestData* bestData, - const CachedNode* focus) const + const CachedNode* cursor) const { const CachedFrame* frame = hasFrame(test); if (frame == NULL) @@ -886,25 +901,25 @@ bool CachedFrame::moveInFrame(MoveInDirection moveInDirection, const CachedNode* childDoc = frame->validDocument(); if (childDoc == NULL) return true; - (frame->*moveInDirection)(childDoc, NULL, bestData, focus); + (frame->*moveInDirection)(childDoc, NULL, bestData, cursor); return true; } const WebCore::IntRect& CachedFrame::_navBounds() const -{ - return history()->navBounds(); +{ + return history()->navBounds(); } void CachedFrame::resetClippedOut() { - for (CachedNode* test = mCachedNodes.begin(); test != mCachedNodes.end(); test++) + for (CachedNode* test = mCachedNodes.begin(); test != mCachedNodes.end(); test++) { if (test->clippedOut()) { test->setDisabled(false); test->setClippedOut(false); } } - for (CachedFrame* frame = mCachedFrames.begin(); frame != mCachedFrames.end(); + for (CachedFrame* frame = mCachedFrames.begin(); frame != mCachedFrames.end(); frame++) { frame->resetClippedOut(); } @@ -913,14 +928,14 @@ void CachedFrame::resetClippedOut() bool CachedFrame::sameFrame(const CachedFrame* test) const { ASSERT(test); - if (mIndex != test->mIndex) + if (mIndexInParent != test->mIndexInParent) return false; - if (mIndex == -1) // index within parent's array of children, or -1 if root + if (mIndexInParent == -1) // index within parent's array of children, or -1 if root return true; return mParent->sameFrame(test->mParent); } -void CachedFrame::setData() +void CachedFrame::setData() { if (this != mRoot) { mViewBounds = mLocalViewBounds; @@ -942,17 +957,17 @@ void CachedFrame::setData() } } -bool CachedFrame::setFocus(WebCore::Frame* frame, WebCore::Node* node, +bool CachedFrame::setCursor(WebCore::Frame* frame, WebCore::Node* node, int x, int y) { if (NULL == node) { - const_cast<CachedRoot*>(mRoot)->setCachedFocus(NULL, NULL); + const_cast<CachedRoot*>(mRoot)->setCursor(NULL, NULL); return true; } if (mFrame != frame) { - for (CachedFrame* testF = mCachedFrames.begin(); testF != mCachedFrames.end(); + for (CachedFrame* testF = mCachedFrames.begin(); testF != mCachedFrames.end(); testF++) { - if (testF->setFocus(frame, node, x, y)) + if (testF->setCursor(frame, node, x, y)) return true; } DBG_NAV_LOGD("no frame frame=%p node=%p", frame, node); @@ -965,17 +980,17 @@ bool CachedFrame::setFocus(WebCore::Frame* frame, WebCore::Node* node, if (test->nodePointer() != node && first) continue; size_t partMax = test->navableRects(); - WTF::Vector<WebCore::IntRect>& focusRings = test->focusRings(); + WTF::Vector<WebCore::IntRect>& cursorRings = test->cursorRings(); for (size_t part = 0; part < partMax; part++) { - const WebCore::IntRect& testBounds = focusRings.at(part); + const WebCore::IntRect& testBounds = cursorRings.at(part); if (testBounds.contains(x, y) == false) continue; - if (test->isFocus()) { - DBG_NAV_LOGD("already set? test=%d frame=%p node=%p x=%d y=%d", + if (test->isCursor()) { + DBG_NAV_LOGD("already set? test=%d frame=%p node=%p x=%d y=%d", test->index(), frame, node, x, y); - return true; + return false; } - const_cast<CachedRoot*>(mRoot)->setCachedFocus(this, test); + const_cast<CachedRoot*>(mRoot)->setCursor(this, test); return true; } } @@ -1034,11 +1049,11 @@ int CachedFrame::BestData::isContainer(CachedFrame::BestData* other) // mMouseOver = other->mNode; return other->mNode->isArea() ? -1 : 1; } - return 0; + return 0; } // distance scale factor factor as a 16.16 scalar -SkFixed CachedFrame::BestData::Overlap(int span, int left, int right) +SkFixed CachedFrame::BestData::Overlap(int span, int left, int right) { unsigned result; if (left > 0 && left < span && right > span) @@ -1077,11 +1092,11 @@ void CachedFrame::BestData::setDistances() bool CachedFrame::BestData::setDownDirection(const CachedHistory* history) { - const WebCore::IntRect& navBounds = history->navBounds(); + const WebCore::IntRect& navBounds = history->navBounds(); mMajorButt = mNodeBounds.y() - navBounds.bottom(); int testX = mNodeBounds.x(); int testRight = mNodeBounds.right(); - setNavOverlap(navBounds.width(), navBounds.right() - testX, + setNavOverlap(navBounds.width(), navBounds.right() - testX, testRight - navBounds.x()); if (canBeReachedByAnotherDirection()) { mNode->setCondition(CachedNode::BEST_DIRECTION); @@ -1089,7 +1104,7 @@ bool CachedFrame::BestData::setDownDirection(const CachedHistory* history) } int inNavTop = mNodeBounds.y() - navBounds.y(); mMajorDelta2 = inNavTop; - mMajorDelta = mMajorDelta2 + ((mNodeBounds.height() - + mMajorDelta = mMajorDelta2 + ((mNodeBounds.height() - navBounds.height()) >> 1); if (mMajorDelta2 <= 1 && mMajorDelta <= 1) { mNode->setCondition(CachedNode::CENTER_FURTHER); // never move up or sideways @@ -1099,7 +1114,7 @@ bool CachedFrame::BestData::setDownDirection(const CachedHistory* history) setNavInclusion(testRight - navBounds.right(), navBounds.x() - testX); bool subsumes = navBounds.height() > 0 && inOrSubsumesNav(); if (inNavTop <= 0 && inNavBottom <= 0 && subsumes) { - mNode->setCondition(CachedNode::NOT_ENCLOSING_FOCUS); + mNode->setCondition(CachedNode::NOT_ENCLOSING_CURSOR); return REJECT_TEST; } int maxV = history->maxWorkingVertical(); @@ -1110,18 +1125,18 @@ bool CachedFrame::BestData::setDownDirection(const CachedHistory* history) mNode->setCondition(CachedNode::OVERLAP_OR_EDGE_FURTHER); return REJECT_TEST; } - mInNav = history->directionChange() && inNavTop >= 0 && - inNavBottom > 0 && subsumes; + mInNav = history->directionChange() && inNavTop >= 0 && + inNavBottom > 0 && subsumes; return false; } bool CachedFrame::BestData::setLeftDirection(const CachedHistory* history) { - const WebCore::IntRect& navBounds = history->navBounds(); + const WebCore::IntRect& navBounds = history->navBounds(); mMajorButt = navBounds.x() - mNodeBounds.right(); int testY = mNodeBounds.y(); int testBottom = mNodeBounds.bottom(); - setNavOverlap(navBounds.height(), navBounds.bottom() - testY, + setNavOverlap(navBounds.height(), navBounds.bottom() - testY, testBottom - navBounds.y()); if (canBeReachedByAnotherDirection()) { mNode->setCondition(CachedNode::BEST_DIRECTION); @@ -1129,7 +1144,7 @@ bool CachedFrame::BestData::setLeftDirection(const CachedHistory* history) } int inNavRight = navBounds.right() - mNodeBounds.right(); mMajorDelta2 = inNavRight; - mMajorDelta = mMajorDelta2 - ((navBounds.width() - + mMajorDelta = mMajorDelta2 - ((navBounds.width() - mNodeBounds.width()) >> 1); if (mMajorDelta2 <= 1 && mMajorDelta <= 1) { mNode->setCondition(CachedNode::CENTER_FURTHER); // never move right or sideways @@ -1139,7 +1154,7 @@ bool CachedFrame::BestData::setLeftDirection(const CachedHistory* history) setNavInclusion(navBounds.y() - testY, testBottom - navBounds.bottom()); bool subsumes = navBounds.width() > 0 && inOrSubsumesNav(); if (inNavLeft <= 0 && inNavRight <= 0 && subsumes) { - mNode->setCondition(CachedNode::NOT_ENCLOSING_FOCUS); + mNode->setCondition(CachedNode::NOT_ENCLOSING_CURSOR); return REJECT_TEST; } int maxH = history->maxWorkingHorizontal(); @@ -1150,18 +1165,18 @@ bool CachedFrame::BestData::setLeftDirection(const CachedHistory* history) mNode->setCondition(CachedNode::OVERLAP_OR_EDGE_FURTHER); return REJECT_TEST; } - mInNav = history->directionChange() && inNavLeft >= 0 && + mInNav = history->directionChange() && inNavLeft >= 0 && inNavRight > 0 && subsumes; /* both L/R in or out */ return false; } bool CachedFrame::BestData::setRightDirection(const CachedHistory* history) { - const WebCore::IntRect& navBounds = history->navBounds(); + const WebCore::IntRect& navBounds = history->navBounds(); mMajorButt = mNodeBounds.x() - navBounds.right(); int testY = mNodeBounds.y(); int testBottom = mNodeBounds.bottom(); - setNavOverlap(navBounds.height(), navBounds.bottom() - testY, + setNavOverlap(navBounds.height(), navBounds.bottom() - testY, testBottom - navBounds.y()); if (canBeReachedByAnotherDirection()) { mNode->setCondition(CachedNode::BEST_DIRECTION); @@ -1169,7 +1184,7 @@ bool CachedFrame::BestData::setRightDirection(const CachedHistory* history) } int inNavLeft = mNodeBounds.x() - navBounds.x(); mMajorDelta2 = inNavLeft; - mMajorDelta = mMajorDelta2 + ((mNodeBounds.width() - + mMajorDelta = mMajorDelta2 + ((mNodeBounds.width() - navBounds.width()) >> 1); if (mMajorDelta2 <= 1 && mMajorDelta <= 1) { mNode->setCondition(CachedNode::CENTER_FURTHER); // never move left or sideways @@ -1179,7 +1194,7 @@ bool CachedFrame::BestData::setRightDirection(const CachedHistory* history) setNavInclusion(testBottom - navBounds.bottom(), navBounds.y() - testY); bool subsumes = navBounds.width() > 0 && inOrSubsumesNav(); if (inNavLeft <= 0 && inNavRight <= 0 && subsumes) { - mNode->setCondition(CachedNode::NOT_ENCLOSING_FOCUS); + mNode->setCondition(CachedNode::NOT_ENCLOSING_CURSOR); return REJECT_TEST; } int maxH = history->maxWorkingHorizontal(); @@ -1190,18 +1205,18 @@ bool CachedFrame::BestData::setRightDirection(const CachedHistory* history) mNode->setCondition(CachedNode::OVERLAP_OR_EDGE_FURTHER); return REJECT_TEST; } - mInNav = history->directionChange() && inNavLeft >= 0 && + mInNav = history->directionChange() && inNavLeft >= 0 && inNavRight > 0 && subsumes; /* both L/R in or out */ return false; } bool CachedFrame::BestData::setUpDirection(const CachedHistory* history) { - const WebCore::IntRect& navBounds = history->navBounds(); + const WebCore::IntRect& navBounds = history->navBounds(); mMajorButt = navBounds.y() - mNodeBounds.bottom(); int testX = mNodeBounds.x(); int testRight = mNodeBounds.right(); - setNavOverlap(navBounds.width(), navBounds.right() - testX, + setNavOverlap(navBounds.width(), navBounds.right() - testX, testRight - navBounds.x()); if (canBeReachedByAnotherDirection()) { mNode->setCondition(CachedNode::BEST_DIRECTION); @@ -1209,7 +1224,7 @@ bool CachedFrame::BestData::setUpDirection(const CachedHistory* history) } int inNavBottom = navBounds.bottom() - mNodeBounds.bottom(); mMajorDelta2 = inNavBottom; - mMajorDelta = mMajorDelta2 - ((navBounds.height() - + mMajorDelta = mMajorDelta2 - ((navBounds.height() - mNodeBounds.height()) >> 1); if (mMajorDelta2 <= 1 && mMajorDelta <= 1) { mNode->setCondition(CachedNode::CENTER_FURTHER); // never move down or sideways @@ -1219,7 +1234,7 @@ bool CachedFrame::BestData::setUpDirection(const CachedHistory* history) setNavInclusion(navBounds.x() - testX, testRight - navBounds.right()); bool subsumes = navBounds.height() > 0 && inOrSubsumesNav(); if (inNavTop <= 0 && inNavBottom <= 0 && subsumes) { - mNode->setCondition(CachedNode::NOT_ENCLOSING_FOCUS); + mNode->setCondition(CachedNode::NOT_ENCLOSING_CURSOR); return REJECT_TEST; } int maxV = history->maxWorkingVertical(); @@ -1230,36 +1245,38 @@ bool CachedFrame::BestData::setUpDirection(const CachedHistory* history) mNode->setCondition(CachedNode::OVERLAP_OR_EDGE_FURTHER); return REJECT_TEST; } - mInNav = history->directionChange() && inNavTop >= 0 && + mInNav = history->directionChange() && inNavTop >= 0 && inNavBottom > 0 && subsumes; /* both L/R in or out */ return false; } void CachedFrame::BestData::setNavInclusion(int left, int right) { - // if left and right <= 0, test node is completely in umbra of focus + // if left and right <= 0, test node is completely in umbra of cursor // prefer leftmost center - // if left and right > 0, test node subsumes focus + // if left and right > 0, test node subsumes cursor mNavDelta = left; mNavDelta2 = right; } void CachedFrame::BestData::setNavOverlap(int span, int left, int right) { - mNavOutside = left < MIN_OVERLAP || right < MIN_OVERLAP; // if left or right < 0, test node is not in umbra of focus + // if left or right < 0, test node is not in umbra of cursor + mNavOutside = left < MIN_OVERLAP || right < MIN_OVERLAP; mNavOverlap = Overlap(span, left, right); // prefer smallest negative left } -void CachedFrame::BestData::setWorkingInclusion(int left, int right) +void CachedFrame::BestData::setWorkingInclusion(int left, int right) { mWorkingDelta = left; mWorkingDelta2 = right; } // distance scale factor factor as a 16.16 scalar -void CachedFrame::BestData::setWorkingOverlap(int span, int left, int right) +void CachedFrame::BestData::setWorkingOverlap(int span, int left, int right) { - mWorkingOutside = left < MIN_OVERLAP || right < MIN_OVERLAP; // if left or right < 0, test node is not in umbra of focus + // if left or right < 0, test node is not in umbra of cursor + mWorkingOutside = left < MIN_OVERLAP || right < MIN_OVERLAP; mWorkingOverlap = Overlap(span, left, right); mPreferred = left <= 0 ? 0 : left; } @@ -1273,7 +1290,7 @@ void CachedFrame::BestData::setWorkingOverlap(int span, int left, int right) CachedFrame* CachedFrame::Debug::base() const { CachedFrame* nav = (CachedFrame*) ((char*) this - OFFSETOF(CachedFrame, mDebug)); - return nav; + return nav; } void CachedFrame::Debug::print() const @@ -1283,12 +1300,12 @@ void CachedFrame::Debug::print() const DEBUG_PRINT_RECT("", BOUNDS, mLocalViewBounds); DEBUG_PRINT_RECT("//", VIEW, mViewBounds); DUMP_NAV_LOGD("// CachedNode mCachedNodes={ // count=%d\n", b->mCachedNodes.size()); - for (CachedNode* node = b->mCachedNodes.begin(); + for (CachedNode* node = b->mCachedNodes.begin(); node != b->mCachedNodes.end(); node++) node->mDebug.print(); DUMP_NAV_LOGD("// }; // end of nodes\n"); DUMP_NAV_LOGD("// CachedFrame mCachedFrames={ // count=%d\n", b->mCachedFrames.size()); - for (CachedFrame* child = b->mCachedFrames.begin(); + for (CachedFrame* child = b->mCachedFrames.begin(); child != b->mCachedFrames.end(); child++) { child->mDebug.print(); @@ -1296,9 +1313,10 @@ void CachedFrame::Debug::print() const DUMP_NAV_LOGD("// }; // end of child frames\n"); DUMP_NAV_LOGD("// void* mFrame=(void*) %p;\n", b->mFrame); DUMP_NAV_LOGD("// CachedFrame* mParent=%p;\n", b->mParent); - DUMP_NAV_LOGD("// int mIndex=%d;\n", b->mIndex); + DUMP_NAV_LOGD("// int mIndexInParent=%d;\n", b->mIndexInParent); DUMP_NAV_LOGD("// const CachedRoot* mRoot=%p;\n", b->mRoot); - DUMP_NAV_LOGD("// int mFocus=%d;\n", b->mFocus); + DUMP_NAV_LOGD("// int mCursorIndex=%d;\n", b->mCursorIndex); + DUMP_NAV_LOGD("// int mFocusIndex=%d;\n", b->mFocusIndex); } bool CachedFrame::Debug::validate(const CachedNode* node) const @@ -1308,7 +1326,7 @@ bool CachedFrame::Debug::validate(const CachedNode* node) const return false; if (node >= b->mCachedNodes.begin() && node < b->mCachedNodes.end()) return true; - for (const CachedFrame* child = b->mCachedFrames.begin(); + for (const CachedFrame* child = b->mCachedFrames.begin(); child != b->mCachedFrames.end(); child++) if (child->mDebug.validate(node)) return true; diff --git a/WebKit/android/nav/CachedFrame.h b/WebKit/android/nav/CachedFrame.h index dc20e15..0df5489 100644 --- a/WebKit/android/nav/CachedFrame.h +++ b/WebKit/android/nav/CachedFrame.h @@ -60,31 +60,39 @@ public: TEST_IS_BEST, REJECT_TEST }; + enum CursorInit { + CURSOR_UNINITIALIZED = -2, + CURSOR_CLEARED = -1, + CURSOR_SET = 0 + }; CachedFrame() {} void add(CachedNode& node) { mCachedNodes.append(node); } void addFrame(CachedFrame& child) { mCachedFrames.append(child); } bool checkVisited(const CachedNode* , CachedFrame::Direction ) const; size_t childCount() { return mCachedFrames.size(); } - void clearFocus(); + void clearCursor(); + const CachedNode* currentCursor() const { return currentCursor(NULL); } + const CachedNode* currentCursor(const CachedFrame** ) const; const CachedNode* currentFocus() const { return currentFocus(NULL); } const CachedNode* currentFocus(const CachedFrame** ) const; bool directionChange() const; const CachedNode* document() const { return mCachedNodes.begin(); } bool empty() const { return mCachedNodes.size() < 2; } // must have 1 past doc - const CachedNode* findBestAt(const WebCore::IntRect& , int* best, bool* inside, - const CachedNode** , const CachedFrame** , int* x, int* y) const; + const CachedNode* findBestAt(const WebCore::IntRect& , int* best, + bool* inside, const CachedNode** , const CachedFrame** , int* x, + int* y, bool checkForHidden) const; const CachedFrame* findBestFrameAt(int x, int y) const; const CachedNode* findBestHitAt(const WebCore::IntRect& , int* best, const CachedFrame** , int* x, int* y) const; - bool finishInit(); + void finishInit(); CachedFrame* firstChild() { return mCachedFrames.begin(); } const CachedFrame* firstChild() const { return mCachedFrames.begin(); } - int focusIndex() const { return mFocus; } void* framePointer() const { return mFrame; } CachedNode* getIndex(int index) { return index >= 0 ? &mCachedNodes[index] : NULL; } const CachedFrame* hasFrame(const CachedNode* node) const; - int indexInParent() const { return mIndex; } + void hideCursor(); + int indexInParent() const { return mIndexInParent; } void init(const CachedRoot* root, int index, WebCore::Frame* frame); const CachedFrame* lastChild() const { return &mCachedFrames.last(); } CachedNode* lastNode() { return &mCachedNodes.last(); } @@ -96,9 +104,11 @@ public: void resetClippedOut(); void setContentsSize(int width, int height) { mContents.setWidth(width); mContents.setHeight(height); } + bool setCursor(WebCore::Frame* , WebCore::Node* , int x, int y); + void setCursorIndex(int index) { mCursorIndex = index; } void setData(); bool setFocus(WebCore::Frame* , WebCore::Node* , int x, int y); - void setFocusIndex(int focusIndex) const { mFocus = focusIndex; } + void setFocusIndex(int index) { mFocusIndex = index; } void setLocalViewBounds(const WebCore::IntRect& bounds) { mLocalViewBounds = bounds; } int size() { return mCachedNodes.size(); } const CachedNode* validDocument() const; @@ -121,7 +131,7 @@ protected: SkFixed mWorkingOverlap; // this and below are fuzzy answers instead of bools SkFixed mNavOverlap; SkFixed mPreferred; - bool mFocusChild; + bool mCursorChild; bool mInNav; bool mNavOutside; bool mWorkingOutside; @@ -186,9 +196,10 @@ protected: WTF::Vector<CachedFrame> mCachedFrames; void* mFrame; // WebCore::Frame*, used only to compare pointers CachedFrame* mParent; - int mIndex; // index within parent's array of children, or -1 if root + int mCursorIndex; + int mFocusIndex; + int mIndexInParent; // index within parent's array of children, or -1 if root const CachedRoot* mRoot; - mutable int mFocus; private: CachedHistory* history() const; #ifdef BROWSER_DEBUG diff --git a/WebKit/android/nav/CachedHistory.cpp b/WebKit/android/nav/CachedHistory.cpp index f75f237..7aca1ad 100644 --- a/WebKit/android/nav/CachedHistory.cpp +++ b/WebKit/android/nav/CachedHistory.cpp @@ -84,8 +84,6 @@ void CachedHistory::reset() // mLastScroll = 0; mPriorBounds = WebCore::IntRect(0, 0, 0, 0); mDirectionChange = false; - mFocusIsInput = false; - mPriorIsInput = false; mDidFirstLayout = false; mPriorMove = mLastMove = CachedFrame::UNINITIALIZED; mMinWorkingHorizontal = mMinWorkingVertical = INT_MIN; @@ -93,24 +91,22 @@ void CachedHistory::reset() } void CachedHistory::setWorking(CachedFrame::Direction newMove, - const CachedNode* focus, const WebCore::IntRect& viewBounds) + const CachedNode* cursor, const WebCore::IntRect& viewBounds) { CachedFrame::Direction lastAxis = (CachedFrame::Direction) (mLastMove & ~CachedFrame::RIGHT_DOWN); // up, left or uninitialized CachedFrame::Direction newAxis = (CachedFrame::Direction) (newMove & ~CachedFrame::RIGHT_DOWN); bool change = newAxis != lastAxis; mDirectionChange = change && mLastMove != CachedFrame::UNINITIALIZED; - if (focus != NULL || mLastMove != CachedFrame::UNINITIALIZED) { + if (cursor != NULL || mLastMove != CachedFrame::UNINITIALIZED) { mPriorMove = mLastMove; mLastMove = newMove; } const WebCore::IntRect* navBounds = &mNavBounds; - if (focus != NULL) { - WebCore::IntRect focusBounds; - focus->getBounds(&focusBounds); - if (focusBounds.isEmpty() == false) - mNavBounds = focusBounds; - mPriorIsInput = mFocusIsInput; - mFocusIsInput = focus->isInput(); // focus->localName() == "input"; + if (cursor != NULL) { + WebCore::IntRect cursorBounds; + cursor->getBounds(&cursorBounds); + if (cursorBounds.isEmpty() == false) + mNavBounds = cursorBounds; } if (change) { // uninitialized or change in direction if (lastAxis != CachedFrame::LEFT && navBounds->height() > 0) { @@ -121,18 +117,6 @@ void CachedHistory::setWorking(CachedFrame::Direction newMove, mMinWorkingVertical = navBounds->x(); mMaxWorkingVertical = navBounds->right(); } - } else if (mPriorIsInput) { - if (newAxis == CachedFrame::UP_DOWN) { - if (mPriorBounds.x() == mMinWorkingVertical && mPriorBounds.right() == mMaxWorkingVertical) { - mMinWorkingVertical = navBounds->x(); - mMaxWorkingVertical = navBounds->right(); - } - } else { - if (mPriorBounds.y() == mMinWorkingHorizontal && mPriorBounds.bottom() == mMaxWorkingHorizontal) { - mMinWorkingHorizontal = navBounds->y(); - mMaxWorkingHorizontal = navBounds->bottom(); - } - } } pinMaxMin(viewBounds); } @@ -176,11 +160,11 @@ void CachedHistory::Debug::print(CachedRoot* root) const } DUMP_NAV_LOGD("// };\n"); // DUMP_NAV_LOGD("// int mLastScroll=%d;\n", b->mLastScroll); + DEBUG_PRINT_RECT(mMouseBounds); DEBUG_PRINT_RECT(mNavBounds); DEBUG_PRINT_RECT(mPriorBounds); DEBUG_PRINT_BOOL(mDirectionChange); - DEBUG_PRINT_BOOL(mFocusIsInput); - DEBUG_PRINT_BOOL(mPriorIsInput); + DEBUG_PRINT_BOOL(mDidFirstLayout); DUMP_NAV_LOGD("// CachedFrame::Direction mLastMove=%s, mPriorMove=%s;\n", direction(b->mLastMove), direction(b->mPriorMove)); int max = b->mMaxWorkingHorizontal; diff --git a/WebKit/android/nav/CachedHistory.h b/WebKit/android/nav/CachedHistory.h index e48d44b..1ae62b9 100644 --- a/WebKit/android/nav/CachedHistory.h +++ b/WebKit/android/nav/CachedHistory.h @@ -50,6 +50,7 @@ public: const WebCore::IntRect& navBounds() const { return mNavBounds; } const WebCore::IntRect& priorBounds() const { return mPriorBounds; } void setDidFirstLayout(bool did) { mDidFirstLayout = did; } + void setMouseBounds(const WebCore::IntRect& loc) { mMouseBounds = loc; } void setNavBounds(const WebCore::IntRect& loc) { mNavBounds = loc; } void setWorking(CachedFrame::Direction , const CachedNode* focus, const WebCore::IntRect& viewBounds); @@ -60,12 +61,10 @@ private: const CachedNode* mNode; CachedFrame::Direction mDirection; } mVisited[NAVIGATION_VISIT_DEPTH]; - WebCore::IntRect mMouseBounds; // constricted bounds, if focus ring is partially visible - WebCore::IntRect mNavBounds; // focus ring bounds plus optional keystroke movement - WebCore::IntRect mPriorBounds; // prior chosen focus ring (for reversing narrowing) + WebCore::IntRect mMouseBounds; // constricted bounds, if cursor ring is partially visible + WebCore::IntRect mNavBounds; // cursor ring bounds plus optional keystroke movement + WebCore::IntRect mPriorBounds; // prior chosen cursor ring (for reversing narrowing) bool mDirectionChange; - bool mFocusIsInput; // defer max/min to non-focus node if focus is too broad - bool mPriorIsInput; // defer max/min to non-focus node if focus is too broad bool mDidFirstLayout; // set true when page is newly laid out CachedFrame::Direction mLastMove; CachedFrame::Direction mPriorMove; diff --git a/WebKit/android/nav/CachedNode.cpp b/WebKit/android/nav/CachedNode.cpp index b786677..cab1f15 100644 --- a/WebKit/android/nav/CachedNode.cpp +++ b/WebKit/android/nav/CachedNode.cpp @@ -24,8 +24,8 @@ */ #include "CachedPrefix.h" -#include "CachedFrame.h" #include "CachedHistory.h" +#include "CachedRoot.h" #include "Node.h" #include "PlatformString.h" @@ -34,13 +34,13 @@ namespace android { -void CachedNode::clearFocus(CachedFrame* parent) +void CachedNode::clearCursor(CachedFrame* parent) { if (isFrame()) { CachedFrame* child = const_cast<CachedFrame*>(parent->hasFrame(this)); - child->clearFocus(); + child->clearCursor(); } - mIsFocus = false; + mIsCursor = false; } bool CachedNode::Clip(const WebCore::IntRect& outer, WebCore::IntRect* inner, @@ -73,24 +73,40 @@ bool CachedNode::Clip(const WebCore::IntRect& outer, WebCore::IntRect* inner, bool CachedNode::clip(const WebCore::IntRect& bounds) { - return Clip(bounds, &mBounds, &mFocusRing); + return Clip(bounds, &mBounds, &mCursorRing); } #define OVERLAP 3 -void CachedNode::fixUpFocusRects() +void CachedNode::fixUpCursorRects(const CachedRoot* root) { - if (mFixedUpFocusRects) + if (mFixedUpCursorRects) return; - mFixedUpFocusRects = true; + mFixedUpCursorRects = true; + // if the hit-test rect doesn't intersect any other rect, use it + if (mHitBounds != mBounds && mHitBounds.contains(mBounds) && + root->checkRings(mCursorRing, mHitBounds)) { + DBG_NAV_LOGD("use mHitBounds (%d,%d,%d,%d)", mHitBounds.x(), + mHitBounds.y(), mHitBounds.width(), mHitBounds.height()); + mUseHitBounds = true; + return; + } if (mNavableRects <= 1) return; + // if there is more than 1 rect, and the bounds doesn't intersect + // any other cursor ring bounds, use it + if (root->checkRings(mCursorRing, mBounds)) { + DBG_NAV_LOGD("use mBounds (%d,%d,%d,%d)", mBounds.x(), + mBounds.y(), mBounds.width(), mBounds.height()); + mUseBounds = true; + return; + } #if DEBUG_NAV_UI { - WebCore::IntRect* boundsPtr = mFocusRing.begin() - 1; - const WebCore::IntRect* const boundsEnd = mFocusRing.begin() + mFocusRing.size(); + WebCore::IntRect* boundsPtr = mCursorRing.begin() - 1; + const WebCore::IntRect* const boundsEnd = mCursorRing.begin() + mCursorRing.size(); while (++boundsPtr < boundsEnd) - LOGD("%s %d:(%d, %d, %d, %d)\n", __FUNCTION__, boundsPtr - mFocusRing.begin(), + LOGD("%s %d:(%d, %d, %d, %d)\n", __FUNCTION__, boundsPtr - mCursorRing.begin(), boundsPtr->x(), boundsPtr->y(), boundsPtr->width(), boundsPtr->height()); } #endif @@ -98,16 +114,16 @@ void CachedNode::fixUpFocusRects() bool again; do { again = false; - size_t size = mFocusRing.size(); - WebCore::IntRect* unitBoundsPtr = mFocusRing.begin() - 1; - const WebCore::IntRect* const unitBoundsEnd = mFocusRing.begin() + size; + size_t size = mCursorRing.size(); + WebCore::IntRect* unitBoundsPtr = mCursorRing.begin() - 1; + const WebCore::IntRect* const unitBoundsEnd = mCursorRing.begin() + size; while (++unitBoundsPtr < unitBoundsEnd) { // any other unitBounds to the left or right of this one? int unitTop = unitBoundsPtr->y(); int unitBottom = unitBoundsPtr->bottom(); int unitLeft = unitBoundsPtr->x(); int unitRight = unitBoundsPtr->right(); - WebCore::IntRect* testBoundsPtr = mFocusRing.begin() - 1; + WebCore::IntRect* testBoundsPtr = mCursorRing.begin() - 1; while (++testBoundsPtr < unitBoundsEnd) { if (unitBoundsPtr == testBoundsPtr) continue; @@ -135,7 +151,7 @@ void CachedNode::fixUpFocusRects() WebCore::IntRect candidate = WebCore::IntRect(candidateLeft, candidateTop, candidateRight - candidateLeft, candidateBottom - candidateTop); // does a different unit bounds intersect the candidate? if so, don't add - WebCore::IntRect* checkBoundsPtr = mFocusRing.begin() - 1; + WebCore::IntRect* checkBoundsPtr = mCursorRing.begin() - 1; while (++checkBoundsPtr < unitBoundsEnd) { if (checkBoundsPtr->intersects(candidate) == false) continue; @@ -163,10 +179,10 @@ void CachedNode::fixUpFocusRects() candidateRight - candidateLeft, candidateBottom - candidateTop); ASSERT(candidate.isEmpty() == false); #if DEBUG_NAV_UI - LOGD("%s %d:(%d, %d, %d, %d)\n", __FUNCTION__, mFocusRing.size(), + LOGD("%s %d:(%d, %d, %d, %d)\n", __FUNCTION__, mCursorRing.size(), candidate.x(), candidate.y(), candidate.width(), candidate.height()); #endif - mFocusRing.append(candidate); + mCursorRing.append(candidate); again = true; goto tryAgain; nextCheck: @@ -179,14 +195,23 @@ tryAgain: } -void CachedNode::focusRingBounds(WebCore::IntRect* bounds) const +void CachedNode::cursorRingBounds(WebCore::IntRect* bounds) const { int partMax = mNavableRects; ASSERT(partMax > 0); - *bounds = mFocusRing[0]; + *bounds = mCursorRing[0]; for (int partIndex = 1; partIndex < partMax; partIndex++) - bounds->unite(mFocusRing[partIndex]); - bounds->inflate(FOCUS_RING_HIT_TEST_RADIUS); + bounds->unite(mCursorRing[partIndex]); + bounds->inflate(CURSOR_RING_HIT_TEST_RADIUS); +} + +void CachedNode::hideCursor(CachedFrame* parent) +{ + if (isFrame()) { + CachedFrame* child = const_cast<CachedFrame*>(parent->hasFrame(this)); + child->hideCursor(); + } + mIsHidden = true; } void CachedNode::init(WebCore::Node* node) @@ -203,8 +228,8 @@ void CachedNode::move(int x, int y) { mBounds.move(x, y); // mHitTestBounds will be moved by caller - WebCore::IntRect* first = mFocusRing.begin(); - WebCore::IntRect* last = first + mFocusRing.size(); + WebCore::IntRect* first = mCursorRing.begin(); + WebCore::IntRect* last = first + mCursorRing.size(); --first; while (++first != last) first->move(x, y); @@ -216,10 +241,10 @@ bool CachedNode::partRectsContains(const CachedNode* other) const int outerMax = mNavableRects; int innerMax = other->mNavableRects; do { - const WebCore::IntRect& outerBounds = mFocusRing[outerIndex]; + const WebCore::IntRect& outerBounds = mCursorRing[outerIndex]; int innerIndex = 0; do { - const WebCore::IntRect& innerBounds = other->mFocusRing[innerIndex]; + const WebCore::IntRect& innerBounds = other->mCursorRing[innerIndex]; if (innerBounds.contains(outerBounds)) return true; } while (++innerIndex < innerMax); @@ -249,10 +274,10 @@ const char* CachedNode::Debug::condition(Condition t) const case BUTTED_UP: return "BUTTED_UP"; break; case CENTER_FURTHER: return "CENTER_FURTHER"; break; case CLOSER: return "CLOSER"; break; - case CLOSER_IN_FOCUS: return "CLOSER_IN_FOCUS"; break; + case CLOSER_IN_CURSOR: return "CLOSER_IN_CURSOR"; break; case CLOSER_OVERLAP: return "CLOSER_OVERLAP"; break; case CLOSER_TOP: return "CLOSER_TOP"; break; - case FOCUSABLE: return "FOCUSABLE"; break; + case NAVABLE: return "NAVABLE"; break; case FURTHER: return "FURTHER"; break; case IN_UMBRA: return "IN_UMBRA"; break; case IN_WORKING: return "IN_WORKING"; break; @@ -264,11 +289,10 @@ const char* CachedNode::Debug::condition(Condition t) const case CHILD: return "CHILD"; break; case DISABLED: return "DISABLED"; break; case HIGHER_TAB_INDEX: return "HIGHER_TAB_INDEX"; break; - case IN_FOCUS: return "IN_FOCUS"; break; - case IN_FOCUS_CHILDREN: return "IN_FOCUS_CHILDREN"; break; - case NOT_ENCLOSING_FOCUS: return "NOT_ENCLOSING_FOCUS"; break; - // case NOT_FOCUS_CHILD: return "NOT_FOCUS_CHILD"; break; - case NOT_FOCUS_NODE: return "NOT_FOCUS_NODE"; break; + case IN_CURSOR: return "IN_CURSOR"; break; + case IN_CURSOR_CHILDREN: return "IN_CURSOR_CHILDREN"; break; + case NOT_ENCLOSING_CURSOR: return "NOT_ENCLOSING_CURSOR"; break; + case NOT_CURSOR_NODE: return "NOT_CURSOR_NODE"; break; case OUTSIDE_OF_BEST: return "OUTSIDE_OF_BEST"; break; case OUTSIDE_OF_ORIGINAL: return "OUTSIDE_OF_ORIGINAL"; break; default: return "???"; @@ -302,9 +326,9 @@ void CachedNode::Debug::print() const DUMP_NAV_LOGD("%.*s\"\n", index, scratch); DEBUG_PRINT_RECT(mBounds); DEBUG_PRINT_RECT(mHitBounds); - const WTF::Vector<WebCore::IntRect>& rects = b->focusRings(); + const WTF::Vector<WebCore::IntRect>& rects = b->cursorRings(); size_t size = rects.size(); - DUMP_NAV_LOGD("// IntRect focusRings={ // size=%d\n", size); + DUMP_NAV_LOGD("// IntRect cursorRings={ // size=%d\n", size); for (size_t i = 0; i < size; i++) DUMP_NAV_LOGD(" // {%d, %d, %d, %d}, // %d\n", rects[i].x(), rects[i].y(), rects[i].width(), rects[i].height(), i); @@ -322,13 +346,14 @@ void CachedNode::Debug::print() const DUMP_NAV_LOGD("// Type mType=%s;\n", type(b->mType)); DEBUG_PRINT_BOOL(mClippedOut); DEBUG_PRINT_BOOL(mDisabled); - DEBUG_PRINT_BOOL(mFixedUpFocusRects); - DEBUG_PRINT_BOOL(mHasFocusRing); + DEBUG_PRINT_BOOL(mFixedUpCursorRects); + DEBUG_PRINT_BOOL(mHasCursorRing); DEBUG_PRINT_BOOL(mHasMouseOver); DEBUG_PRINT_BOOL(mIsAnchor); DEBUG_PRINT_BOOL(mIsArea); + DEBUG_PRINT_BOOL(mIsCursor); DEBUG_PRINT_BOOL(mIsFocus); - DEBUG_PRINT_BOOL(mIsInput); + DEBUG_PRINT_BOOL(mIsHidden); DEBUG_PRINT_BOOL(mIsParentAnchor); DEBUG_PRINT_BOOL(mIsPassword); DEBUG_PRINT_BOOL(mIsRtlText); @@ -337,6 +362,8 @@ void CachedNode::Debug::print() const DEBUG_PRINT_BOOL(mIsTransparent); DEBUG_PRINT_BOOL(mIsUnclipped); DEBUG_PRINT_BOOL(mLast); + DEBUG_PRINT_BOOL(mUseBounds); + DEBUG_PRINT_BOOL(mUseHitBounds); DEBUG_PRINT_BOOL(mWantsKeyEvents); DUMP_NAV_LOGD("\n"); } diff --git a/WebKit/android/nav/CachedNode.h b/WebKit/android/nav/CachedNode.h index aa64982..2efbaf7 100644 --- a/WebKit/android/nav/CachedNode.h +++ b/WebKit/android/nav/CachedNode.h @@ -40,6 +40,7 @@ namespace WebCore { namespace android { class CachedFrame; +class CachedRoot; class CachedNode { public: @@ -53,10 +54,10 @@ public: BUTTED_UP, CENTER_FURTHER, CLOSER, - CLOSER_IN_FOCUS, + CLOSER_IN_CURSOR, CLOSER_OVERLAP, CLOSER_TOP, - FOCUSABLE, + NAVABLE, FURTHER, IN_UMBRA, IN_WORKING, @@ -70,11 +71,10 @@ public: CHILD, DISABLED, HIGHER_TAB_INDEX, - IN_FOCUS, - IN_FOCUS_CHILDREN, - NOT_ENCLOSING_FOCUS, - // NOT_FOCUS_CHILD, - NOT_FOCUS_NODE, + IN_CURSOR, + IN_CURSOR_CHILDREN, + NOT_ENCLOSING_CURSOR, + NOT_CURSOR_NODE, OUTSIDE_OF_BEST, // containership OUTSIDE_OF_ORIGINAL, // containership CONDITION_SIZE // FIXME: test that CONDITION_SIZE fits in mCondition @@ -88,41 +88,43 @@ public: WebCore::IntRect* boundsPtr() { return &mBounds; } int childFrameIndex() const { return mChildFrameIndex; } void clearCondition() const { mCondition = NOT_REJECTED; } - void clearFocus(CachedFrame* ); + void clearCursor(CachedFrame* ); static bool Clip(const WebCore::IntRect& outer, WebCore::IntRect* inner, WTF::Vector<WebCore::IntRect>* rings); bool clip(const WebCore::IntRect& ); bool clippedOut() { return mClippedOut; } + void cursorRingBounds(WebCore::IntRect* ) const; bool disabled() const { return mDisabled; } const CachedNode* document() const { return &this[-mIndex]; } - void fixUpFocusRects(); - void focusRingBounds(WebCore::IntRect* ) const; - WTF::Vector<WebCore::IntRect>& focusRings() { return mFocusRing; } - const WTF::Vector<WebCore::IntRect>& focusRings() const { return mFocusRing; } + void fixUpCursorRects(const CachedRoot* root); + WTF::Vector<WebCore::IntRect>& cursorRings() { return mCursorRing; } + const WTF::Vector<WebCore::IntRect>& cursorRings() const { return mCursorRing; } const WebCore::IntRect& getBounds() const { return mBounds; } void getBounds(WebCore::IntRect* bounds) const { *bounds = mBounds; } const WebCore::String& getExport() const { return mExport; } - bool hasFocusRing() const { return mHasFocusRing; } + bool hasCursorRing() const { return !mIsHidden && mHasCursorRing; } bool hasMouseOver() const { return mHasMouseOver; } + void hideCursor(CachedFrame* ); const WebCore::IntRect& hitBounds() const { return mHitBounds; } int index() const { return mIndex; } void init(WebCore::Node* node); bool isAnchor() const { return mIsAnchor; } + bool isCursor() const { return mIsCursor; } bool isArea() const { return mIsArea; } bool isFocus() const { return mIsFocus; } - bool isFocusable(const WebCore::IntRect& clip) const { + bool isFrame() const { return mChildFrameIndex >= 0 ; } + bool isNavable(const WebCore::IntRect& clip) const { return clip.intersects(mBounds); } - bool isFrame() const { return mChildFrameIndex >= 0 ; } - bool isInput() const { return mIsInput; } bool isPassword() const { return mIsPassword; } + bool isPlugin() const { + return mWantsKeyEvents && !mIsTextArea && !mIsTextField; + } bool isRtlText() const { return mIsRtlText; } bool isTextArea() const { return mIsTextArea; } bool isTextField() const { return mIsTextField; } bool isTransparent() const { return mIsTransparent; } bool isUnclipped() const { return mIsUnclipped; } - bool isWantsKeyEvents() const { return mWantsKeyEvents; } - int maxLength() const { return mMaxLength; }; void move(int x, int y); const WebCore::String& name() const { return mName; } @@ -140,14 +142,14 @@ public: void setCondition(Condition condition) const { mCondition = condition; } void setDisabled(bool disabled) { mDisabled = disabled; } void setExport(const WebCore::String& exported) { mExport = exported; } - void setHasFocusRing(bool hasFocusRing) { mHasFocusRing = hasFocusRing; } + void setHasCursorRing(bool hasRing) { mHasCursorRing = hasRing; } void setHasMouseOver(bool hasMouseOver) { mHasMouseOver = hasMouseOver; } void setHitBounds(const WebCore::IntRect& bounds) { mHitBounds = bounds; } void setIndex(int index) { mIndex = index; } void setIsAnchor(bool isAnchor) { mIsAnchor = isAnchor; } void setIsArea(bool isArea) { mIsArea = isArea; } + void setIsCursor(bool isCursor) { mIsCursor = isCursor; } void setIsFocus(bool isFocus) { mIsFocus = isFocus; } - void setIsInput(bool isInput) { mIsInput = isInput; } void setIsParentAnchor(bool isAnchor) { mIsParentAnchor = isAnchor; } void setIsPassword(bool isPassword) { mIsPassword = isPassword; } void setIsRtlText(bool isRtlText) { mIsRtlText = isRtlText; } @@ -158,23 +160,27 @@ public: void setLast() { mLast = true; } void setMaxLength(int maxLength) { mMaxLength = maxLength; } void setName(const WebCore::String& name) { mName = name; } - void setNavableRects() { mNavableRects = mFocusRing.size(); } + void setNavableRects() { mNavableRects = mCursorRing.size(); } void setParentGroup(void* group) { mParentGroup = group; } void setParentIndex(int parent) { mParentIndex = parent; } void setTabIndex(int index) { mTabIndex = index; } void setTextSize(int textSize) { mTextSize = textSize; } void setType(CachedNodeType type) { mType = type; } void setWantsKeyEvents(bool wantsKeys) { mWantsKeyEvents = wantsKeys; } + void show() { mIsHidden = false; } int tabIndex() const { return mTabIndex; } const CachedNode* traverseNextNode() const { return mLast ? NULL : &this[1]; } int textSize() const { return mTextSize; } CachedNodeType type() const { return mType; } + bool useBounds() const { return mUseBounds; } + bool useHitBounds() const { return mUseHitBounds; } + bool wantsKeyEvents() const { return mWantsKeyEvents; } private: WebCore::String mExport; WebCore::String mName; WebCore::IntRect mBounds; WebCore::IntRect mHitBounds; - WTF::Vector<WebCore::IntRect> mFocusRing; + WTF::Vector<WebCore::IntRect> mCursorRing; void* mNode; // WebCore::Node*, only used to match pointers void* mParentGroup; // WebCore::Node*, only used to match pointers int mChildFrameIndex; // set to -1 if node is not a frame @@ -188,13 +194,14 @@ private: CachedNodeType mType : 3; bool mClippedOut : 1; bool mDisabled : 1; - bool mFixedUpFocusRects : 1; - bool mHasFocusRing : 1; + bool mFixedUpCursorRects : 1; + bool mHasCursorRing : 1; bool mHasMouseOver : 1; bool mIsAnchor : 1; bool mIsArea : 1; + bool mIsCursor : 1; bool mIsFocus : 1; - bool mIsInput : 1; + bool mIsHidden : 1; bool mIsParentAnchor : 1; bool mIsPassword : 1; bool mIsRtlText : 1; @@ -203,6 +210,8 @@ private: bool mIsTransparent : 1; bool mIsUnclipped : 1; bool mLast : 1; // true if this is the last node in a group + bool mUseBounds : 1; + bool mUseHitBounds : 1; bool mWantsKeyEvents : 1; // true for nodes like plugins #ifdef BROWSER_DEBUG public: diff --git a/WebKit/android/nav/CachedRoot.cpp b/WebKit/android/nav/CachedRoot.cpp index a123e55..7da4bd3 100644 --- a/WebKit/android/nav/CachedRoot.cpp +++ b/WebKit/android/nav/CachedRoot.cpp @@ -24,6 +24,7 @@ */ #include "CachedPrefix.h" +#include "android_graphics.h" #include "CachedHistory.h" #include "CachedNode.h" #include "SkBitmap.h" @@ -57,18 +58,18 @@ public: kDrawText_Type, kDrawTextOnPath_Type }; - + static bool isTextType(Type t) { return t == kDrawPosTextH_Type || t == kDrawText_Type; } - + CommonCheck() : mType(kNo_Type), mAllOpaque(true), mIsOpaque(true) { setEmpty(); } - bool doRect(Type type) { + bool doRect(Type type) { mType = type; - return doIRect(mUnion); + return doIRect(mUnion); } bool joinGlyphs(const SkIRect& rect) { @@ -77,7 +78,7 @@ public: mUnion.join(rect); return isGlyph; } - + void setAllOpaque(bool opaque) { mAllOpaque = opaque; } void setEmpty() { mUnion.setEmpty(); } void setIsOpaque(bool opaque) { mIsOpaque = opaque; } @@ -112,16 +113,16 @@ public: class BoundsCheck : public CommonCheck { public: - BoundsCheck() { + BoundsCheck() { mAllDrawnIn.setEmpty(); mLastAll.setEmpty(); mLastOver.setEmpty(); } - + static int Area(SkIRect test) { return test.width() * test.height(); } - + void checkLast() { if (mAllDrawnIn.isEmpty()) return; @@ -131,16 +132,16 @@ public: } mAllDrawnIn.setEmpty(); } - + bool hidden() { return (mLastAll.isEmpty() && mLastOver.isEmpty()) || mDrawnOver.contains(mBounds); } - + virtual bool onIRect(const SkIRect& rect) { if (joinGlyphs(rect)) return false; - bool interestingType = mType == kDrawBitmap_Type || + bool interestingType = mType == kDrawBitmap_Type || mType == kDrawRect_Type || isTextType(mType); if (SkIRect::Intersects(mBounds, rect) == false) { #if DEBUG_NAV_UI && !defined BROWSER_DEBUG @@ -154,7 +155,7 @@ public: } if (interestingType == false) return false; - if (mBoundsSlop.contains(rect) || + if (mBoundsSlop.contains(rect) || (mBounds.fLeft == rect.fLeft && mBounds.fRight == rect.fRight && mBounds.fTop >= rect.fTop && mBounds.fBottom <= rect.fBottom) || (mBounds.fTop == rect.fTop && mBounds.fBottom == rect.fBottom && @@ -176,15 +177,15 @@ public: // should the opaqueness of the bitmap disallow its ability to draw over? // not sure that this test is needed (mType != kDrawBitmap_Type || - (mIsOpaque && mAllOpaque)) && -#endif + (mIsOpaque && mAllOpaque)) && +#endif mLastAll.isEmpty() == false) mDrawnOver.op(rect, SkRegion::kUnion_Op); } else { // FIXME -// sometimes the text is not drawn entirely inside the focus area, even though +// sometimes the text is not drawn entirely inside the cursor area, even though // it is the correct text. Until I figure out why, I allow text drawn at the -// end that is not covered up by something else to represent the focusable link +// end that is not covered up by something else to represent the link // example that triggers this that should be figured out: // http://cdn.labpixies.com/campaigns/blackjack/blackjack.html?lang=en&country=US&libs=assets/feature/core // ( http://tinyurl.com/ywsyzb ) @@ -201,7 +202,7 @@ public: } return false; } - + SkIRect mBounds; SkIRect mBoundsSlop; SkRegion mDrawnOver; @@ -257,7 +258,7 @@ public: SkCanvas::drawSprite(bitmap, left, top, paint); } - virtual void drawText(const void* text, size_t byteLength, SkScalar x, + virtual void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint) { mBounder.setEmpty(); mBounder.setType(CommonCheck::kDrawGlyph_Type); @@ -265,7 +266,7 @@ public: mBounder.doRect(CommonCheck::kDrawText_Type); } - virtual void drawPosText(const void* text, size_t byteLength, + virtual void drawPosText(const void* text, size_t byteLength, const SkPoint pos[], const SkPaint& paint) { mBounder.setEmpty(); mBounder.setType(CommonCheck::kDrawGlyph_Type); @@ -294,8 +295,8 @@ public: mBounder.doRect(CommonCheck::kDrawPosTextH_Type); } - virtual void drawTextOnPath(const void* text, size_t byteLength, - const SkPath& path, const SkMatrix* matrix, + virtual void drawTextOnPath(const void* text, size_t byteLength, + const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) { mBounder.setEmpty(); mBounder.setType(CommonCheck::kDrawGlyph_Type); @@ -307,7 +308,7 @@ public: mBounder.setType(CommonCheck::kDrawPicture_Type); SkCanvas::drawPicture(picture); } - + virtual int saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) { int depth = SkCanvas::saveLayer(bounds, paint, flags); @@ -326,7 +327,7 @@ public: } SkCanvas::restore(); } - + int mTransparentLayer; CommonCheck& mBounder; }; @@ -337,20 +338,20 @@ and returns via center() the optimal amount to scroll in x to display the paragraph of text. The caller of CenterCheck has configured (but not allocated) a bitmap -the height and three times the width of the view. The picture is drawn centered -in the bitmap, so text that would be revealed, if the view was scrolled up to +the height and three times the width of the view. The picture is drawn centered +in the bitmap, so text that would be revealed, if the view was scrolled up to a view-width to the left or right, is considered. */ class CenterCheck : public CommonCheck { public: - CenterCheck(int x, int y, int width) : mX(x), mY(y), + CenterCheck(int x, int y, int width) : mX(x), mY(y), mHitLeft(x), mHitRight(x), mMostLeft(INT_MAX), mMostRight(-INT_MAX), mViewLeft(width), mViewRight(width << 1) { - mHit.set(x - CENTER_SLOP, y - CENTER_SLOP, + mHit.set(x - CENTER_SLOP, y - CENTER_SLOP, x + CENTER_SLOP, y + CENTER_SLOP); mPartial.setEmpty(); } - + int center() { doRect(); // process the final line of text /* If the touch coordinates aren't near any text, return 0 */ @@ -381,12 +382,12 @@ public: center = 0; // paragraph is already fully visible #endif } - DBG_NAV_LOGD("scroll: leftOver=%d rightOver=%d center=%d", + DBG_NAV_LOGD("scroll: leftOver=%d rightOver=%d center=%d", leftOver, rightOver, center); return center; } - -protected: + +protected: virtual bool onIRect(const SkIRect& rect) { if (joinGlyphs(rect)) // assembles glyphs into a text string return false; @@ -394,9 +395,9 @@ protected: return false; /* Text on one line may be broken into several parts. Reassemble the text into a rectangle before considering it. */ - if (rect.fTop < mPartial.fBottom && rect.fBottom > + if (rect.fTop < mPartial.fBottom && rect.fBottom > mPartial.fTop && mPartial.fRight + CENTER_SLOP >= rect.fLeft) { - DBG_NAV_LOGD("join mPartial=(%d, %d, %d, %d) rect=(%d, %d, %d, %d)", + DBG_NAV_LOGD("join mPartial=(%d, %d, %d, %d) rect=(%d, %d, %d, %d)", mPartial.fLeft, mPartial.fTop, mPartial.fRight, mPartial.fBottom, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom); mPartial.join(rect); @@ -406,11 +407,11 @@ protected: doRect(); // process the previous line of text mPartial = rect; return false; - } - + } + void doRect() { - /* Record the outer bounds of the lines of text that was 'hit' by the + /* Record the outer bounds of the lines of text that was 'hit' by the touch coordinates, given some slop */ if (SkIRect::Intersects(mPartial, mHit)) { if (mHitLeft > mPartial.fLeft) @@ -439,10 +440,10 @@ protected: mMostLeft = leftOver; if (mMostRight < rightOver) mMostRight = rightOver; - DBG_NAV_LOGD("leftOver=%d rightOver=%d mMostLeft=%d mMostRight=%d", + DBG_NAV_LOGD("leftOver=%d rightOver=%d mMostLeft=%d mMostRight=%d", leftOver, rightOver, mMostLeft, mMostRight); } - + static const int CENTER_SLOP = 10; // space between text parts and lines /* const */ SkIRect mHit; // sloppy hit rectangle SkIRect mPartial; // accumulated text bounds, per line @@ -463,7 +464,7 @@ public: } // Currently webkit's bitmap draws always seem to be cull'd before this entry -// point is called, so we assume that any bitmap that gets here is inside our +// point is called, so we assume that any bitmap that gets here is inside our // tiny clip (may not be true in the future) virtual void commonDrawBitmap(const SkBitmap& bitmap, const SkMatrix& , const SkPaint& ) { @@ -490,14 +491,14 @@ public: mMinX = mMinJiggle = abs(delta); mMaxWidth = width + mMinX; } - + int jiggle() { if (mMinJiggle > mMaxJiggle) return mDelta; int avg = (mMinJiggle + mMaxJiggle + 1) >> 1; return mDelta < 0 ? -avg : avg; } - + virtual bool onIRect(const SkIRect& rect) { if (joinGlyphs(rect)) return false; @@ -530,14 +531,45 @@ public: int mMaxWidth; }; -bool CachedRoot::adjustForScroll(BestData* best, CachedFrame::Direction direction, +class RingCheck : public CommonCheck { +public: + RingCheck(const WTF::Vector<WebCore::IntRect>& rings, + const WebCore::IntPoint& location) : mSuccess(true) { + const WebCore::IntRect* r; + for (r = rings.begin(); r != rings.end(); r++) { + SkIRect fatter = {r->x(), r->y(), r->right(), r->bottom()}; + fatter.inset(-CURSOR_RING_HIT_TEST_RADIUS, -CURSOR_RING_HIT_TEST_RADIUS); + DBG_NAV_LOGD("fat=(%d,%d,r=%d,b=%d)", fatter.fLeft, fatter.fTop, + fatter.fRight, fatter.fBottom); + mRings.op(fatter, SkRegion::kUnion_Op); + } + DBG_NAV_LOGD("translate=(%d,%d)", -location.x(), -location.y()); + mRings.translate(-location.x(), -location.y()); + } + + virtual bool onIRect(const SkIRect& rect) { + if (mSuccess && mType == kDrawGlyph_Type) { + DBG_NAV_LOGD("contains (%d,%d,r=%d,b=%d) == %s", rect.fLeft, rect.fTop, + rect.fRight, rect.fBottom, mRings.contains(rect) ? "true" : + "false"); + mSuccess &= mRings.contains(rect); + } + return false; + } + + bool success() { return mSuccess; } + SkRegion mRings; + bool mSuccess; +}; + +bool CachedRoot::adjustForScroll(BestData* best, CachedFrame::Direction direction, WebCore::IntPoint* scrollPtr, bool findClosest) -{ +{ WebCore::IntRect newOutset; const CachedNode* newNode = best->mNode; // see if there's a middle node - // if the middle node is in the visited list, - // or if none was computed and the newNode is in the visited list, + // if the middle node is in the visited list, + // or if none was computed and the newNode is in the visited list, // treat result as NULL if (newNode != NULL && findClosest) { if (best->bounds().intersects(mHistory->mPriorBounds) == false && @@ -547,13 +579,13 @@ bool CachedRoot::adjustForScroll(BestData* best, CachedFrame::Direction directio innerMove(document(), best, direction, scrollPtr, false); return true; } - newNode->focusRingBounds(&newOutset); + newNode->cursorRingBounds(&newOutset); } int delta; bool newNodeInView = scrollDelta(newOutset, direction, &delta); - if (delta && scrollPtr && (newNode == NULL || newNodeInView == false || + if (delta && scrollPtr && (newNode == NULL || newNodeInView == false || (best->mNavOutside && best->mWorkingOutside))) - *scrollPtr = WebCore::IntPoint(direction & UP_DOWN ? 0 : delta, + *scrollPtr = WebCore::IntPoint(direction & UP_DOWN ? 0 : delta, direction & UP_DOWN ? delta : 0); return false; } @@ -562,14 +594,14 @@ bool CachedRoot::adjustForScroll(BestData* best, CachedFrame::Direction directio int CachedRoot::checkForCenter(int x, int y) const { int width = mViewBounds.width(); - CenterCheck centerCheck(x + width - mViewBounds.x(), y - mViewBounds.y(), + CenterCheck centerCheck(x + width - mViewBounds.x(), y - mViewBounds.y(), width); BoundsCanvas checker(¢erCheck); SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, width * 3, mViewBounds.height()); checker.setBitmapDevice(bitmap); - checker.translate(SkIntToScalar(width - mViewBounds.x()), + checker.translate(SkIntToScalar(width - mViewBounds.x()), SkIntToScalar(-mViewBounds.y())); checker.drawPicture(*mPicture); return centerCheck.center(); @@ -585,25 +617,45 @@ void CachedRoot::checkForJiggle(int* xDeltaPtr) const bitmap.setConfig(SkBitmap::kARGB_8888_Config, mViewBounds.width() + absDelta, mViewBounds.height()); checker.setBitmapDevice(bitmap); - checker.translate(SkIntToScalar(-mViewBounds.x() - + checker.translate(SkIntToScalar(-mViewBounds.x() - (xDelta < 0 ? xDelta : 0)), SkIntToScalar(-mViewBounds.y())); checker.drawPicture(*mPicture); *xDeltaPtr = jiggleCheck.jiggle(); } +bool CachedRoot::checkRings(const WTF::Vector<WebCore::IntRect>& rings, + const WebCore::IntRect& bounds) const +{ + if (!mPicture) + return false; + RingCheck ringCheck(rings, bounds.location()); + BoundsCanvas checker(&ringCheck); + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(), + bounds.height()); + checker.setBitmapDevice(bitmap); + checker.translate(SkIntToScalar(-bounds.x()), SkIntToScalar(-bounds.y())); + checker.drawPicture(*mPicture); + DBG_NAV_LOGD("bounds=(%d,%d,r=%d,b=%d) success=%s", + bounds.x(), bounds.y(), bounds.right(), bounds.bottom(), + ringCheck.success() ? "true" : "false"); + return ringCheck.success(); +} + const CachedNode* CachedRoot::findAt(const WebCore::IntRect& rect, - const CachedFrame** framePtr, int* x, int* y) const + const CachedFrame** framePtr, int* x, int* y, bool checkForHidden) const { int best = INT_MAX; bool inside = false; (const_cast<CachedRoot*>(this))->resetClippedOut(); const CachedNode* directHit = NULL; - const CachedNode* node = findBestAt(rect, &best, &inside, &directHit, framePtr, x, y); - DBG_NAV_LOGD("node=%d (%p)", node == NULL ? 0 : node->index(), + const CachedNode* node = findBestAt(rect, &best, &inside, &directHit, + framePtr, x, y, checkForHidden); + DBG_NAV_LOGD("node=%d (%p)", node == NULL ? 0 : node->index(), node == NULL ? NULL : node->nodePointer()); if (node == NULL) { node = findBestHitAt(rect, &best, framePtr, x, y); - DBG_NAV_LOGD("node=%d (%p)", node == NULL ? 0 : node->index(), + DBG_NAV_LOGD("node=%d (%p)", node == NULL ? 0 : node->index(), node == NULL ? NULL : node->nodePointer()); } if (node == NULL) { @@ -613,13 +665,19 @@ const CachedNode* CachedRoot::findAt(const WebCore::IntRect& rect, return node; } -WebCore::IntPoint CachedRoot::focusLocation() const +WebCore::IntPoint CachedRoot::cursorLocation() const { const WebCore::IntRect& bounds = mHistory->mNavBounds; - return WebCore::IntPoint(bounds.x() + (bounds.width() >> 1), + return WebCore::IntPoint(bounds.x() + (bounds.width() >> 1), bounds.y() + (bounds.height() >> 1)); } +WebCore::IntPoint CachedRoot::focusLocation() const +{ + return WebCore::IntPoint(mFocusBounds.x() + (mFocusBounds.width() >> 1), + mFocusBounds.y() + (mFocusBounds.height() >> 1)); +} + // These reset the values because we only want to get the selection the first time. // After that, the selection is no longer accurate. int CachedRoot::getAndResetSelectionEnd() @@ -636,14 +694,27 @@ int CachedRoot::getAndResetSelectionStart() return start; } -void CachedRoot::getSimulatedMousePosition(WebCore::IntPoint* point) +void CachedRoot::getSimulatedMousePosition(WebCore::IntPoint* point) const { #ifndef NDEBUG ASSERT(CachedFrame::mDebug.mInUse); #endif const WebCore::IntRect& mouseBounds = mHistory->mMouseBounds; - point->setX(mouseBounds.x() + (mouseBounds.width() >> 1)); - point->setY(mouseBounds.y() + (mouseBounds.height() >> 1)); + int x = mouseBounds.x(); + int y = mouseBounds.y(); + int width = mouseBounds.width(); + int height = mouseBounds.height(); + point->setX(x + (width >> 1)); // default to box center + point->setY(y + (height >> 1)); + const CachedNode* cursor = currentCursor(); + if (cursor && cursor->bounds().contains(mHistory->mMouseBounds)) { + if (cursor->isTextField()) // if text field, return end of line + point->setX(x + width - 1); + else if (cursor->isTextArea()) { // if text area, return start + point->setX(x + 1); + point->setY(y + 1); + } + } #if DEBUG_NAV_UI && !defined BROWSER_DEBUG const WebCore::IntRect& navBounds = mHistory->mNavBounds; LOGD("%s mHistory->mNavBounds={%d,%d,%d,%d} " @@ -654,7 +725,7 @@ void CachedRoot::getSimulatedMousePosition(WebCore::IntPoint* point) #endif } -void CachedRoot::init(WebCore::Frame* frame, CachedHistory* history) +void CachedRoot::init(WebCore::Frame* frame, CachedHistory* history) { CachedFrame::init(this, -1, frame); reset(); @@ -671,18 +742,19 @@ bool CachedRoot::innerDown(const CachedNode* test, BestData* bestData) const mScrolledBounds.setHeight(mScrolledBounds.height() + mMaxYScroll); int testTop = mScrolledBounds.y(); int viewBottom = mViewBounds.bottom(); - if (mFocusBounds.isEmpty() == false && - mFocusBounds.bottom() > viewBottom && viewBottom < mContents.height()) + const WebCore::IntRect& navBounds = mHistory->mNavBounds; + if (navBounds.isEmpty() == false && + navBounds.bottom() > viewBottom && viewBottom < mContents.height()) return false; - if (mHistory->mNavBounds.isEmpty() == false) { - int navTop = mHistory->mNavBounds.y(); + if (navBounds.isEmpty() == false) { + int navTop = navBounds.y(); int scrollBottom; if (testTop < navTop && navTop < (scrollBottom = mScrolledBounds.bottom())) { mScrolledBounds.setHeight(scrollBottom - navTop); mScrolledBounds.setY(navTop); } } - frameDown(test, NULL, bestData, currentFocus()); + frameDown(test, NULL, bestData, currentCursor()); return true; } @@ -695,62 +767,60 @@ bool CachedRoot::innerLeft(const CachedNode* test, BestData* bestData) const mScrolledBounds.setWidth(mScrolledBounds.width() + mMaxXScroll); int testRight = mScrolledBounds.right(); int viewLeft = mViewBounds.x(); - if (mFocusBounds.isEmpty() == false && - mFocusBounds.x() < viewLeft && viewLeft > mContents.x()) + const WebCore::IntRect& navBounds = mHistory->mNavBounds; + if (navBounds.isEmpty() == false && + navBounds.x() < viewLeft && viewLeft > mContents.x()) return false; - if (mHistory->mNavBounds.isEmpty() == false) { - int navRight = mHistory->mNavBounds.right(); + if (navBounds.isEmpty() == false) { + int navRight = navBounds.right(); int scrollLeft; if (testRight > navRight && navRight > (scrollLeft = mScrolledBounds.x())) mScrolledBounds.setWidth(navRight - scrollLeft); } - frameLeft(test, NULL, bestData, currentFocus()); + frameLeft(test, NULL, bestData, currentCursor()); return true; } -void CachedRoot::innerMove(const CachedNode* node, BestData* bestData, +void CachedRoot::innerMove(const CachedNode* node, BestData* bestData, Direction direction, WebCore::IntPoint* scroll, bool firstCall) { bestData->reset(); - mFocusChild = false; - bool outOfFocus = mFocus < 0; - bool firstTime = mHistory->didFirstLayout() && outOfFocus; + bool outOfCursor = mCursorIndex == CURSOR_CLEARED; #if DEBUG_NAV_UI && !defined BROWSER_DEBUG - LOGD("%s mHistory->didFirstLayout()=%s && mFocus=%d\n", __FUNCTION__, - mHistory->didFirstLayout() ? "true" : "false", mFocus); + LOGD("%s mHistory->didFirstLayout()=%s && mCursorIndex=%d\n", __FUNCTION__, + mHistory->didFirstLayout() ? "true" : "false", mCursorIndex); #endif - if (firstTime) + if (mHistory->didFirstLayout() && mCursorIndex < CURSOR_SET) { mHistory->reset(); - const CachedNode* focus = currentFocus(); - mHistory->setWorking(direction, focus, mViewBounds); - mFocusBounds = WebCore::IntRect(0, 0, 0, 0); - if (focus != NULL) - focus->getBounds(&mFocusBounds); + outOfCursor = true; + } + const CachedNode* cursor = currentCursor(); + mHistory->setWorking(direction, cursor, mViewBounds); bool findClosest = false; if (mScrollOnly == false) { switch (direction) { case LEFT: - if (outOfFocus) - mHistory->mNavBounds = WebCore::IntRect(mViewBounds.right(), + if (outOfCursor) + mHistory->mNavBounds = WebCore::IntRect(mViewBounds.right(), mViewBounds.y(), 1, mViewBounds.height()); findClosest = innerLeft(node, bestData); break; - case RIGHT: - if (outOfFocus) + case RIGHT: + if (outOfCursor) mHistory->mNavBounds = WebCore::IntRect(mViewBounds.x() - 1, mViewBounds.y(), 1, mViewBounds.height()); findClosest = innerRight(node, bestData); break; case UP: - if (outOfFocus) - mHistory->mNavBounds = WebCore::IntRect(mViewBounds.x(), + if (outOfCursor) + mHistory->mNavBounds = WebCore::IntRect(mViewBounds.x(), mViewBounds.bottom(), mViewBounds.width(), 1); findClosest = innerUp(node, bestData); break; case DOWN: - if (outOfFocus) - mHistory->mNavBounds = WebCore::IntRect(mViewBounds.x(), + if (outOfCursor) + mHistory->mNavBounds = WebCore::IntRect(mViewBounds.x(), mViewBounds.y() - 1, mViewBounds.width(), 1); findClosest = innerDown(node, bestData); break; @@ -766,7 +836,7 @@ void CachedRoot::innerMove(const CachedNode* node, BestData* bestData, return; if (bestData->mNode != NULL) { mHistory->addToVisited(bestData->mNode, direction); - mHistory->mNavBounds = mFocusBounds = bestData->mNodeBounds; + mHistory->mNavBounds = bestData->mNodeBounds; mHistory->mMouseBounds = bestData->mMouseBounds; } else if (scroll->x() != 0 || scroll->y() != 0) { WebCore::IntRect newBounds = mHistory->mNavBounds; @@ -795,18 +865,19 @@ bool CachedRoot::innerRight(const CachedNode* test, BestData* bestData) const mScrolledBounds.setWidth(mScrolledBounds.width() + mMaxXScroll); int testLeft = mScrolledBounds.x(); int viewRight = mViewBounds.right(); - if (mFocusBounds.isEmpty() == false && - mFocusBounds.right() > viewRight && viewRight < mContents.width()) + const WebCore::IntRect& navBounds = mHistory->mNavBounds; + if (navBounds.isEmpty() == false && + navBounds.right() > viewRight && viewRight < mContents.width()) return false; - if (mHistory->mNavBounds.isEmpty() == false) { - int navLeft = mHistory->mNavBounds.x(); + if (navBounds.isEmpty() == false) { + int navLeft = navBounds.x(); int scrollRight; if (testLeft < navLeft && navLeft < (scrollRight = mScrolledBounds.right())) { mScrolledBounds.setWidth(scrollRight - navLeft); mScrolledBounds.setX(navLeft); } } - frameRight(test, NULL, bestData, currentFocus()); + frameRight(test, NULL, bestData, currentCursor()); return true; } @@ -819,16 +890,17 @@ bool CachedRoot::innerUp(const CachedNode* test, BestData* bestData) const mScrolledBounds.setHeight(mScrolledBounds.height() + mMaxYScroll); int testBottom = mScrolledBounds.bottom(); int viewTop = mViewBounds.y(); - if (mFocusBounds.isEmpty() == false && - mFocusBounds.y() < viewTop && viewTop > mContents.y()) + const WebCore::IntRect& navBounds = mHistory->mNavBounds; + if (navBounds.isEmpty() == false && + navBounds.y() < viewTop && viewTop > mContents.y()) return false; - if (mHistory->mNavBounds.isEmpty() == false) { - int navBottom = mHistory->mNavBounds.bottom(); + if (navBounds.isEmpty() == false) { + int navBottom = navBounds.bottom(); int scrollTop; if (testBottom > navBottom && navBottom > (scrollTop = mScrolledBounds.y())) mScrolledBounds.setHeight(navBottom - scrollTop); } - frameUp(test, NULL, bestData, currentFocus()); + frameUp(test, NULL, bestData, currentCursor()); return true; } @@ -856,7 +928,7 @@ bool CachedRoot::maskIfHidden(BestData* best) const if (bestNode->isUnclipped()) return false; // given the picture matching this nav cache - // create an SkBitmap with dimensions of the focus intersected w/ extended view + // create an SkBitmap with dimensions of the cursor intersected w/ extended view const WebCore::IntRect& nodeBounds = bestNode->getBounds(); WebCore::IntRect bounds = nodeBounds; bounds.intersect(mScrolledBounds); @@ -870,7 +942,7 @@ bool CachedRoot::maskIfHidden(BestData* best) const marginBounds.intersect(mScrolledBounds); BoundsCheck boundsCheck; BoundsCanvas checker(&boundsCheck); - boundsCheck.mBounds.set(leftMargin, topMargin, + boundsCheck.mBounds.set(leftMargin, topMargin, leftMargin + bounds.width(), topMargin + bounds.height()); boundsCheck.mBoundsSlop = boundsCheck.mBounds; boundsCheck.mBoundsSlop.inset(-kSlop, -kSlop); @@ -878,8 +950,8 @@ bool CachedRoot::maskIfHidden(BestData* best) const bitmap.setConfig(SkBitmap::kARGB_8888_Config, marginBounds.width(), marginBounds.height()); checker.setBitmapDevice(bitmap); - // insert probes to be called when the data corresponding to this focus ring is drawn - // need to know if focus ring was generated by text, image, or parent (like div) + // insert probes to be called when the data corresponding to this ring is drawn + // need to know if ring was generated by text, image, or parent (like div) // ? need to know (like imdb menu bar) to give up sometimes (when?) checker.translate(SkIntToScalar(leftMargin - bounds.x()), SkIntToScalar(topMargin - bounds.y())); @@ -938,17 +1010,17 @@ bool CachedRoot::maskIfHidden(BestData* best) const #if DEBUG_NAV_UI && !defined BROWSER_DEBUG const SkIRect& modded = boundsCheck.mBounds; LOGD("%s partially occluded node:%p (%d) old:{%d,%d,%d,%d} new:{%d,%d,%d,%d}\n", - __FUNCTION__, best->mNode, best->mNode->index(), + __FUNCTION__, best->mNode, best->mNode->index(), orig.fLeft, orig.fTop, orig.fRight, orig.fBottom, base.fLeft, base.fTop, base.fRight, base.fBottom); #endif - best->mMouseBounds = WebCore::IntRect(bounds.x() + base.fLeft - kMargin, + best->mMouseBounds = WebCore::IntRect(bounds.x() + base.fLeft - kMargin, bounds.y() + base.fTop - kMargin, base.width(), base.height()); } return false; } -const CachedNode* CachedRoot::moveFocus(Direction direction, const CachedFrame** framePtr, +const CachedNode* CachedRoot::moveCursor(Direction direction, const CachedFrame** framePtr, WebCore::IntPoint* scroll) { #ifndef NDEBUG @@ -977,7 +1049,6 @@ void CachedRoot::reset() mMaxXScroll = mMaxYScroll = 0; mSelectionStart = mSelectionEnd = -1; mScrollOnly = false; - mFocusBounds = WebCore::IntRect(0, 0, 0, 0); } bool CachedRoot::scrollDelta(WebCore::IntRect& newOutset, Direction direction, int* delta) @@ -986,13 +1057,13 @@ bool CachedRoot::scrollDelta(WebCore::IntRect& newOutset, Direction direction, i case LEFT: *delta = -mMaxXScroll; return newOutset.x() >= mViewBounds.x(); - case RIGHT: + case RIGHT: *delta = mMaxXScroll; return newOutset.right() <= mViewBounds.right(); case UP: *delta = -mMaxYScroll; return newOutset.y() >= mViewBounds.y(); - case DOWN: + case DOWN: *delta = mMaxYScroll; return newOutset.bottom() <= mViewBounds.bottom(); default: @@ -1004,46 +1075,62 @@ bool CachedRoot::scrollDelta(WebCore::IntRect& newOutset, Direction direction, i void CachedRoot::setCachedFocus(CachedFrame* frame, CachedNode* node) { -#if !defined NDEBUG - ASSERT(CachedFrame::mDebug.mInUse); -#endif -#if DEBUG_NAV_UI && !defined BROWSER_DEBUG - const CachedNode* focus = currentFocus(); - WebCore::IntRect bounds; - if (focus) - bounds = focus->bounds(); - LOGD("%s old focus %d (nodePointer=%p) bounds={%d,%d,%d,%d}\n", __FUNCTION__, - focus ? focus->index() : 0, - focus ? focus->nodePointer() : NULL, bounds.x(), bounds.y(), - bounds.width(), bounds.height()); -#endif - clearFocus(); + mFocusBounds = WebCore::IntRect(0, 0, 0, 0); if (node == NULL) return; node->setIsFocus(true); - ASSERT(node->isFrame() == false); + mFocusBounds = node->bounds(); frame->setFocusIndex(node - frame->document()); - ASSERT(frame->focusIndex() > 0 && frame->focusIndex() < (int) frame->size()); CachedFrame* parent; while ((parent = frame->parent()) != NULL) { parent->setFocusIndex(frame->indexInParent()); frame = parent; } #if DEBUG_NAV_UI && !defined BROWSER_DEBUG - focus = currentFocus(); - bounds = WebCore::IntRect(0, 0, 0, 0); + const CachedNode* focus = currentFocus(); + WebCore::IntRect bounds = WebCore::IntRect(0, 0, 0, 0); if (focus) bounds = focus->bounds(); LOGD("%s new focus %d (nodePointer=%p) bounds={%d,%d,%d,%d}\n", __FUNCTION__, focus ? focus->index() : 0, - focus ? focus->nodePointer() : NULL, bounds.x(), bounds.y(), + focus ? focus->nodePointer() : NULL, bounds.x(), bounds.y(), bounds.width(), bounds.height()); #endif } -void CachedRoot::setupScrolledBounds() const +void CachedRoot::setCursor(CachedFrame* frame, CachedNode* node) { - mScrolledBounds = mViewBounds; +#if DEBUG_NAV_UI && !defined BROWSER_DEBUG + const CachedNode* cursor = currentCursor(); + WebCore::IntRect bounds; + if (cursor) + bounds = cursor->bounds(); + LOGD("%s old cursor %d (nodePointer=%p) bounds={%d,%d,%d,%d}\n", __FUNCTION__, + cursor ? cursor->index() : 0, + cursor ? cursor->nodePointer() : NULL, bounds.x(), bounds.y(), + bounds.width(), bounds.height()); +#endif + clearCursor(); + if (node == NULL) + return; + node->setIsCursor(true); + node->show(); + frame->setCursorIndex(node - frame->document()); + CachedFrame* parent; + while ((parent = frame->parent()) != NULL) { + parent->setCursorIndex(frame->indexInParent()); + frame = parent; + } +#if DEBUG_NAV_UI && !defined BROWSER_DEBUG + cursor = currentCursor(); + bounds = WebCore::IntRect(0, 0, 0, 0); + if (cursor) + bounds = cursor->bounds(); + LOGD("%s new cursor %d (nodePointer=%p) bounds={%d,%d,%d,%d}\n", __FUNCTION__, + cursor ? cursor->index() : 0, + cursor ? cursor->nodePointer() : NULL, bounds.x(), bounds.y(), + bounds.width(), bounds.height()); +#endif } #if DUMP_NAV_CACHE @@ -1058,7 +1145,7 @@ void CachedRoot::setupScrolledBounds() const CachedRoot* CachedRoot::Debug::base() const { CachedRoot* nav = (CachedRoot*) ((char*) this - OFFSETOF(CachedRoot, mDebug)); - return nav; + return nav; } void CachedRoot::Debug::print() const @@ -1071,10 +1158,8 @@ void CachedRoot::Debug::print() const CachedRoot* b = base(); b->CachedFrame::mDebug.print(); b->mHistory->mDebug.print(b); - DEBUG_PRINT_RECT(mFocusBounds); - DUMP_NAV_LOGD("// int mMaxXScroll=%d, mMaxYScroll=%d;\n", + DUMP_NAV_LOGD("// int mMaxXScroll=%d, mMaxYScroll=%d;\n", b->mMaxXScroll, b->mMaxYScroll); - DEBUG_PRINT_BOOL(mFocusChild); #ifdef DUMP_NAV_CACHE_USING_PRINTF if (gNavCacheLogFile) fclose(gNavCacheLogFile); diff --git a/WebKit/android/nav/CachedRoot.h b/WebKit/android/nav/CachedRoot.h index ab1b823..38ab2d8 100644 --- a/WebKit/android/nav/CachedRoot.h +++ b/WebKit/android/nav/CachedRoot.h @@ -27,8 +27,9 @@ #define CachedRoot_H #include "CachedFrame.h" -#include "IntPoint.h" +#include "IntRect.h" #include "SkPicture.h" +#include "wtf/Vector.h" class SkRect; @@ -43,20 +44,19 @@ public: bool findClosest); int checkForCenter(int x, int y) const; void checkForJiggle(int* ) const; + bool checkRings(const WTF::Vector<WebCore::IntRect>& rings, + const WebCore::IntRect& bounds) const; + WebCore::IntPoint cursorLocation() const; int documentHeight() { return mContents.height(); } int documentWidth() { return mContents.width(); } const CachedNode* findAt(const WebCore::IntRect& , const CachedFrame** , - int* x, int* y) const; + int* x, int* y, bool checkForHidden) const; const WebCore::IntRect& focusBounds() const { return mFocusBounds; } - bool focusChild() const { return mFocusChild; } WebCore::IntPoint focusLocation() const; - int generation() const { return mGeneration; } SkPicture* getPicture() { return mPicture; } int getAndResetSelectionEnd(); int getAndResetSelectionStart(); -// const WebCore::IntRect& navClipBounds() const { return mClippedBounds; } - void getSimulatedMousePosition(WebCore::IntPoint* ); -// bool hasNavClipBounds() { return mClippedBounds.isEmpty() == false; } + void getSimulatedMousePosition(WebCore::IntPoint* ) const; void init(WebCore::Frame* , CachedHistory* ); bool innerDown(const CachedNode* , BestData* ) const; bool innerLeft(const CachedNode* , BestData* ) const; @@ -66,39 +66,34 @@ public: bool innerUp(const CachedNode* , BestData* ) const; WebCore::String imageURI(int x, int y) const; bool maskIfHidden(BestData* ) const; - const CachedNode* moveFocus(Direction , const CachedFrame** , WebCore::IntPoint* scroll); + const CachedNode* moveCursor(Direction , const CachedFrame** , WebCore::IntPoint* scroll); void reset(); -// void resetNavClipBounds() { mClippedBounds = WebCore::IntRect(-1, -1, 0, 0); } CachedHistory* rootHistory() const { return mHistory; } - bool scrollDelta(WebCore::IntRect& focusRingBounds, Direction , int* delta); + bool scrollDelta(WebCore::IntRect& cursorRingBounds, Direction , int* delta); const WebCore::IntRect& scrolledBounds() const { return mScrolledBounds; } + void setCursor(CachedFrame* , CachedNode* ); void setCachedFocus(CachedFrame* , CachedNode* ); void setFocusBounds(const WebCore::IntRect& r) { mFocusBounds = r; } - void setGeneration(int generation) { mGeneration = generation; } void setTextGeneration(int textGeneration) { mTextGeneration = textGeneration; } - void setFocusChild(bool state) const { mFocusChild = state; } void setMaxScroll(int x, int y) { mMaxXScroll = x; mMaxYScroll = y; } -// void setNavClipBounds(const WebCore::IntRect& r) { mClippedBounds = r; } void setPicture(SkPicture* picture) { mPicture = picture; } void setScrollOnly(bool state) { mScrollOnly = state; } void setSelection(int start, int end) { mSelectionStart = start; mSelectionEnd = end; } - void setupScrolledBounds() const; + void setupScrolledBounds() const { mScrolledBounds = mViewBounds; } void setVisibleRect(const WebCore::IntRect& r) { mViewBounds = r; } int textGeneration() const { return mTextGeneration; } int width() const { return mPicture ? mPicture->width() : 0; } private: CachedHistory* mHistory; SkPicture* mPicture; - WebCore::IntRect mFocusBounds; // chosen focus ring + WebCore::IntRect mFocusBounds; // dom text input focus node bounds mutable WebCore::IntRect mScrolledBounds; // view bounds + amount visible as result of scroll - int mGeneration; int mTextGeneration; int mMaxXScroll; int mMaxYScroll; // These two are ONLY used when the tree is rebuilt and the focus is a textfield/area int mSelectionStart; int mSelectionEnd; - mutable bool mFocusChild; // temporary state set if walked nodes are children of focus bool mScrollOnly; #if DUMP_NAV_CACHE public: diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index 0657a81..cf1e486 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -69,265 +69,8 @@ #include <JNIHelp.h> #include <jni.h> -#define REPLAY_BUFFER_SIZE 4096 - namespace android { -struct CommonParams { - enum Trigger { - NoData, - ClearFocusParams, - FirstMoveFocusParams, - MoveFocusParams, - MotionUpParams - } m_trigger; - int m_generation; -}; - -struct CacheParams { - void setFocus(const CachedNode* node, - const CachedFrame* frame, const CachedRoot* root, - const WebCore::IntPoint& focusLocation) - { - m_node = (WebCore::Node*) (node ? node->nodePointer() : 0); - m_frame = (WebCore::Frame*) (node ? frame->framePointer() : 0); - m_x = focusLocation.x(); - m_y = focusLocation.y(); - } - - WebCore::Node* m_node; - WebCore::Frame* m_frame; - int m_x; - int m_y; -}; - -struct ClearFocusParams { - CommonParams d; - CacheParams c; - int m_x; - int m_y; -}; - -struct MotionUpParams { - CommonParams d; - int m_x; - int m_y; - int m_slop; - bool m_isClick; -}; - -struct FirstMoveFocusParams { - CommonParams d; - int m_keyCode; - int m_count; - bool m_ignoreScroll; -}; - -struct MoveFocusParams { - FirstMoveFocusParams d; - CacheParams c; - void* m_sentFocus; - WebCore::IntRect m_sentBounds; - WebCore::IntRect m_visibleRect; - CachedHistory m_history; // FIXME: make this a subset - int m_xMax; - int m_yMax; -}; - -typedef MoveFocusParams LargestParams; - -#if DEBUG_NAV_UI -static const char* TriggerNames[] = { - "*** no data ! ***", - "clearFocus", - "firstMoveFocus", - "moveFocus", - "motionUp" -}; -#endif - -class FocusReplay { -public: -FocusReplay() : m_start(m_buffer), m_end(m_buffer), m_lastGeneration(0) -{ -} - -// find the most recent common data -void add(const CommonParams& data, size_t len) -{ - DBG_NAV_LOGD("m_start=%d m_end=%d trigger=%s moveGeneration=%d", m_start - m_buffer, - m_end - m_buffer, TriggerNames[data.m_trigger], data.m_generation); - m_lastGeneration = data.m_generation; - char* limit = m_buffer + sizeof(m_buffer); - int used = m_end - m_start; - if (used < 0) - used += sizeof(m_buffer); - int needed = (int) len - ((int) sizeof(m_buffer) - used); - if (needed >= 0) - reclaim(++needed); - if (m_end + len <= limit) { - memcpy(m_end, (void*) &data, len); - m_end += len; - DBG_NAV_LOGD("m_start=%d m_end=%d", m_start - m_buffer, m_end - m_buffer); - return; - } - size_t partial = limit - m_end; - memcpy(m_end, (void*) &data, partial); - const void* remainder = (const void*) ((const char*) &data + partial); - partial = len - partial; - memcpy(m_buffer, remainder, partial); - m_end = m_buffer + partial; - DBG_NAV_LOGD("wrap m_start=%d m_end=%d", - m_start - m_buffer, m_end - m_buffer); -} - -int count() -{ - DBG_NAV_LOGD("m_start=%d m_end=%d", - m_start - m_buffer, m_end - m_buffer); - if (m_start == m_end) - return 0; - char* limit = m_buffer + sizeof(m_buffer); - char* saveStart = m_start; - int result = 0; - while (true) { - ++result; - m_start += triggerSize(); - if (m_start == m_end) - break; - if (m_start < limit) - continue; - m_start -= sizeof(m_buffer); - if (m_start == m_end) - break; - } - m_start = saveStart; - DBG_NAV_LOGD("count=%d", result); - return result; -} - -void discard(int generation) -{ - DBG_NAV_LOGD("generation=%d", generation); - LargestParams storage; - const CommonParams& params = storage.d.d; - char* pos = position(); - retrieve(&storage.d.d); - if (params.m_generation > generation) { - DBG_NAV_LOGD("params.m_generation=%d > generation=%d", - params.m_generation, generation); - rewind(pos); - DBG_NAV_LOGD("m_start=%d m_end=%d", m_start - m_buffer, m_end - m_buffer); - return; - } - LOG_ASSERT(params.m_generation == generation, "params.m_generation != generation"); - DBG_NAV_LOGD("m_start=%d m_end=%d", m_start - m_buffer, m_end - m_buffer); -} - -int lastAdd() -{ - return m_lastGeneration; -} - -char* position() -{ - return m_start; -} - -int retrieve(CommonParams* data) -{ - if (m_end == m_start) { - // changed from LOGD to LOGV, as it always fires when I click to center - // text (mrr) - LOGV("%s *** no data to retrieve (error condition) ***", __FUNCTION__); - data->m_trigger = CommonParams::NoData; - return data->m_generation = INT_MAX; - } - DBG_NAV_LOGD("m_start=%d m_end=%d", - m_start - m_buffer, m_end - m_buffer); - char* limit = m_buffer + sizeof(m_buffer); - size_t size = triggerSize(); - if (m_start < m_end) { - LOG_ASSERT((size_t) (m_end - m_start) >= size, "m_end - m_start < size"); - memcpy(data, m_start, size); - m_start += size; - } else { - int partial = limit - m_start; - if (partial > (int) size) - partial = size; - memcpy(data, m_start, partial); - m_start += partial; - void* remainder = (void*) ((char*) data + partial); - partial = size - partial; - if (partial > 0) { - memcpy(remainder, m_buffer, partial); - m_start = m_buffer + partial; - LOG_ASSERT(m_start <= m_end, "m_start > m_end"); - } - } - if (m_start == limit) { - m_start = m_buffer; - if (m_end == limit) - m_end = m_buffer; - } - DBG_NAV_LOGD("m_start=%d m_end=%d trigger=%s moveGeneration=%d", - m_start - m_buffer, m_end - m_buffer, TriggerNames[data->m_trigger], - data->m_generation); - return data->m_generation; -} - -void rewind(char* pos) -{ - m_start = pos; -} - -private: -void reclaim(int needed) -{ - DBG_NAV_LOGD("needed=%d", needed); - char* limit = m_buffer + sizeof(m_buffer); - do { - size_t size = triggerSize(); - m_start += size; - needed -= size; - if (m_start >= limit) { - m_start = m_buffer + (m_start - limit); - if (m_end == limit) - m_end = m_buffer; - } - } while (needed > 0 && m_start != m_end); - DBG_NAV_LOGD("m_start=%d m_end=%d", - m_start - m_buffer, m_end - m_buffer); -} - -size_t triggerSize() -{ - LOG_ASSERT(m_start != m_end, "m_start == m_end"); - char* limit = m_buffer + sizeof(m_buffer); - LOG_ASSERT(m_start + sizeof(CommonParams::Trigger) <= limit, "trigger not in limit"); - CommonParams::Trigger trigger; - memcpy(&trigger, m_start, sizeof(trigger)); - switch (trigger) { - case CommonParams::ClearFocusParams: - return sizeof(ClearFocusParams); - case CommonParams::FirstMoveFocusParams: - return sizeof(FirstMoveFocusParams); - case CommonParams::MoveFocusParams: - return sizeof(MoveFocusParams); - case CommonParams::MotionUpParams: - return sizeof(MotionUpParams); - default: - LOG_ASSERT(0, "trigger undefined"); - } - return 0; -} - -char m_buffer[REPLAY_BUFFER_SIZE]; -char* m_start; -char* m_end; -int m_lastGeneration; -}; // end of helper class ReplayFocus - static jfieldID gWebViewField; //------------------------------------- @@ -351,25 +94,19 @@ enum FrameCachePermission { AllowNewest }; -enum OutOfFocusFix { - DoNothing, - ClearTextEntry, - UpdateTextEntry -}; - struct JavaGlue { jobject m_obj; jmethodID m_clearTextEntry; jmethodID m_overrideLoading; + jmethodID m_sendPluginState; jmethodID m_scrollBy; - jmethodID m_sendFinalFocus; - jmethodID m_sendKitFocus; + jmethodID m_sendMoveMouse; + jmethodID m_sendMoveMouseIfLatest; jmethodID m_sendMotionUp; - jmethodID m_setFocusData; jmethodID m_getScaledMaxXScroll; jmethodID m_getScaledMaxYScroll; jmethodID m_getVisibleRect; - jmethodID m_updateTextEntry; + jmethodID m_rebuildWebTextView; jmethodID m_displaySoftKeyboard; jmethodID m_viewInvalidate; jmethodID m_viewInvalidateRect; @@ -378,8 +115,6 @@ struct JavaGlue { jfieldID m_rectTop; jmethodID m_rectWidth; jmethodID m_rectHeight; - jfieldID m_focusNode; - jmethodID m_setAll; AutoJObject object(JNIEnv* env) { return getRealObject(env, m_obj); } @@ -393,15 +128,15 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) m_javaGlue.m_scrollBy = GetJMethod(env, clazz, "setContentScrollBy", "(IIZ)V"); m_javaGlue.m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "()V"); m_javaGlue.m_overrideLoading = GetJMethod(env, clazz, "overrideLoading", "(Ljava/lang/String;)V"); - m_javaGlue.m_sendFinalFocus = GetJMethod(env, clazz, "sendFinalFocus", "(IIII)V"); - m_javaGlue.m_sendKitFocus = GetJMethod(env, clazz, "sendKitFocus", "()V"); - m_javaGlue.m_sendMotionUp = GetJMethod(env, clazz, "sendMotionUp", "(IIIIIIIZZ)V"); - m_javaGlue.m_setFocusData = GetJMethod(env, clazz, "setFocusData", "(IIIIIIZ)V"); + m_javaGlue.m_sendPluginState = GetJMethod(env, clazz, "sendPluginState", "(I)V"); + m_javaGlue.m_sendMoveMouse = GetJMethod(env, clazz, "sendMoveMouse", "(IIII)V"); + m_javaGlue.m_sendMoveMouseIfLatest = GetJMethod(env, clazz, "sendMoveMouseIfLatest", "(Z)V"); + m_javaGlue.m_sendMotionUp = GetJMethod(env, clazz, "sendMotionUp", "(IIIIII)V"); m_javaGlue.m_getScaledMaxXScroll = GetJMethod(env, clazz, "getScaledMaxXScroll", "()I"); m_javaGlue.m_getScaledMaxYScroll = GetJMethod(env, clazz, "getScaledMaxYScroll", "()I"); m_javaGlue.m_getVisibleRect = GetJMethod(env, clazz, "sendOurVisibleRect", "()Landroid/graphics/Rect;"); - m_javaGlue.m_updateTextEntry = GetJMethod(env, clazz, "updateTextEntry", "()V"); - m_javaGlue.m_displaySoftKeyboard = GetJMethod(env, clazz, "displaySoftKeyboard", "()V"); + m_javaGlue.m_rebuildWebTextView = GetJMethod(env, clazz, "rebuildWebTextView", "()V"); + m_javaGlue.m_displaySoftKeyboard = GetJMethod(env, clazz, "displaySoftKeyboard", "(Z)V"); m_javaGlue.m_viewInvalidate = GetJMethod(env, clazz, "viewInvalidate", "()V"); m_javaGlue.m_viewInvalidateRect = GetJMethod(env, clazz, "viewInvalidate", "(IIII)V"); m_javaGlue.m_postInvalidateDelayed = GetJMethod(env, clazz, @@ -413,18 +148,10 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) m_javaGlue.m_rectWidth = GetJMethod(env, rectClass, "width", "()I"); m_javaGlue.m_rectHeight = GetJMethod(env, rectClass, "height", "()I"); - // Set up class for updateFocusNode - jclass focusnodeClass = env->FindClass("android/webkit/WebView$FocusNode"); - LOG_ASSERT(focusnodeClass, "Could not find FocusNode class!"); - m_javaGlue.m_focusNode = env->GetFieldID(clazz, "mFocusNode", "Landroid/webkit/WebView$FocusNode;"); - m_javaGlue.m_setAll = GetJMethod(env, focusnodeClass, "setAll", "(ZZZZZIIIIIIIILjava/lang/String;Ljava/lang/String;I)V"); - env->DeleteLocalRef(focusnodeClass); - env->SetIntField(javaWebView, gWebViewField, (jint)this); m_viewImpl = (WebViewCore*) viewImpl; m_frameCacheUI = 0; m_navPictureUI = 0; - m_invalidNode = 0; m_generation = 0; m_heightCanMeasure = false; m_followedLink = false; @@ -436,6 +163,10 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) m_matches = 0; m_hasCurrentLocation = false; m_isFindPaintSetUp = false; + m_pluginReceivesEvents = false; // initialization is the only time this + // variable should be set directly, all + // other changes should be made through + // setPluginReceivesEvents(bool) } ~WebView() @@ -452,33 +183,32 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) delete m_matches; } -void clearFocus(int x, int y, bool inval) +WebViewCore* getWebViewCore() const { + return m_viewImpl; +} + +// removes the cursor altogether (e.g., when going to a new page) +void clearCursor() { - DBG_NAV_LOGD("x=%d y=%d inval=%s", x, y, - inval ? "true" : "false"); - clearTextEntry(); CachedRoot* root = getFrameCache(AllowNewer); if (!root) return; - const CachedFrame* oldFrame = 0; - const CachedNode* oldFocusNode = root->currentFocus(&oldFrame); - WebCore::IntPoint focusLocation = WebCore::IntPoint(0, 0); - setFocusData(root->generation(), 0, 0, x, y, !oldFocusNode); - sendKitFocus(); - if (oldFocusNode) { - DBG_NAV_LOG("oldFocusNode"); - focusLocation = root->focusLocation(); - root->setCachedFocus(0, 0); - if (inval) - viewInvalidate(); - } - ClearFocusParams params; - params.d.m_trigger = CommonParams::ClearFocusParams; - params.d.m_generation = m_generation; - params.c.setFocus(oldFocusNode, oldFrame, root, focusLocation); - params.m_x = x; - params.m_y = y; - m_replay.add(params.d, sizeof(params)); + DBG_NAV_LOG(""); + m_viewImpl->m_hasCursorBounds = false; + root->clearCursor(); + viewInvalidate(); +} + +// leaves the cursor where it is, but suppresses drawing it +void hideCursor() +{ + CachedRoot* root = getFrameCache(AllowNewer); + if (!root) + return; + DBG_NAV_LOG(""); + m_viewImpl->m_hasCursorBounds = false; + root->hideCursor(); + viewInvalidate(); } void clearTextEntry() @@ -499,40 +229,38 @@ void debugDump() #endif // Traverse our stored array of buttons that are in our picture, and update -// their subpictures according to their current focus state. +// their subpictures according to their current state. // Called from the UI thread. This is the one place in the UI thread where we // access the buttons stored in the WebCore thread. // hasFocus keeps track of whether the WebView has focus && windowFocus. -// If not, we do not want to draw the button in a focused or pressed state +// If not, we do not want to draw the button in a selected or pressed state void nativeRecordButtons(bool hasFocus, bool pressed, bool invalidate) { - bool focusIsButton = false; - const CachedNode* cachedFocus = 0; + bool cursorIsOnButton = false; + const CachedNode* cachedCursor = 0; // Lock the mutex, since we now share with the WebCore thread. m_viewImpl->gButtonMutex.lock(); if (m_viewImpl->m_buttons.size()) { - // Find the focused node so we can determine which node has focus, and - // therefore which state to paint them in. - // FIXME: In a future change, we should keep track of whether the focus + // FIXME: In a future change, we should keep track of whether the selection // has changed to short circuit (note that we would still need to update // if we received new buttons from the WebCore thread). - WebCore::Node* focus = 0; + WebCore::Node* cursor = 0; CachedRoot* root = getFrameCache(DontAllowNewer); if (root) { - cachedFocus = root->currentFocus(); - if (cachedFocus) - focus = (WebCore::Node*) cachedFocus->nodePointer(); + cachedCursor = root->currentCursor(); + if (cachedCursor) + cursor = (WebCore::Node*) cachedCursor->nodePointer(); } // Traverse the array, and update each button, depending on whether it - // is focused. + // is selected. Container* end = m_viewImpl->m_buttons.end(); for (Container* ptr = m_viewImpl->m_buttons.begin(); ptr != end; ptr++) { WebCore::RenderSkinAndroid::State state; - if (ptr->matches(focus)) { - focusIsButton = true; + if (ptr->matches(cursor)) { + cursorIsOnButton = true; // If the WebView is out of focus/window focus, set the state to - // normal, but still keep track of the fact that the focus is a + // normal, but still keep track of the fact that the selected is a // button if (!hasFocus) { state = WebCore::RenderSkinAndroid::kNormal; @@ -548,8 +276,8 @@ void nativeRecordButtons(bool hasFocus, bool pressed, bool invalidate) } } m_viewImpl->gButtonMutex.unlock(); - if (invalidate && cachedFocus && focusIsButton) { - const WebCore::IntRect& b = cachedFocus->getBounds(); + if (invalidate && cachedCursor && cursorIsOnButton) { + const WebCore::IntRect& b = cachedCursor->getBounds(); viewInvalidateRect(b.x(), b.y(), b.right(), b.bottom()); } } @@ -577,7 +305,7 @@ void setUpFindPaint() m_isFindPaintSetUp = true; } -// Draw the match specified by region to the canvas. +// Draw the match specified by region to the canvas. void drawMatch(const SkRegion& region, SkCanvas* canvas, bool focused) { // For the match which has focus, use a filled paint. For the others, use @@ -666,8 +394,7 @@ void drawMatches(SkCanvas* canvas) unsigned numberOfMatches = m_matches->size(); if (numberOfMatches > 1 && numberOfMatches < MAX_NUMBER_OF_MATCHES_TO_DRAW) { - SkIRect visibleIRect; - android_setrect(&visibleIRect, visible); + SkIRect visibleIRect(visible); for(unsigned i = 0; i < numberOfMatches; i++) { // The current match has already been drawn if (i == m_findIndex) @@ -683,41 +410,50 @@ void drawMatches(SkCanvas* canvas) } } -void drawFocusRing(SkCanvas* canvas) +void resetCursorRing() +{ + m_followedLink = false; + setPluginReceivesEvents(false); + m_viewImpl->m_hasCursorBounds = false; +} + +void drawCursorRing(SkCanvas* canvas) { const CachedRoot* root = getFrameCache(AllowNewer); if (!root) { DBG_NAV_LOG("!root"); - m_followedLink = false; + resetCursorRing(); return; } - const CachedNode* node = root->currentFocus(); + const CachedFrame* frame; + const CachedNode* node = root->currentCursor(&frame); if (!node) { DBG_NAV_LOG("!node"); - m_followedLink = false; + resetCursorRing(); return; } - if (!node->hasFocusRing()) { - DBG_NAV_LOG("!node->hasFocusRing()"); + if (!node->hasCursorRing()) { + DBG_NAV_LOG("!node->hasCursorRing()"); + m_viewImpl->m_hasCursorBounds = false; return; } - const WTF::Vector<WebCore::IntRect>& rings = node->focusRings(); - if (!rings.size()) { - DBG_NAV_LOG("!rings.size()"); + const WTF::Vector<WebCore::IntRect>* rings = &node->cursorRings(); + if (!rings->size()) { + DBG_NAV_LOG("!rings->size()"); + m_viewImpl->m_hasCursorBounds = false; return; } - bool isButton = false; m_viewImpl->gButtonMutex.lock(); // If this is a button drawn by us (rather than webkit) do not draw the - // focus ring, since its focus will be shown by a change in what we draw. + // cursor ring, since its cursor will be shown by a change in what we draw. // Should be in sync with recordButtons, since that will be called // before this. if (m_viewImpl->m_buttons.size() > 0) { - WebCore::Node* focusPointer = (WebCore::Node*) node->nodePointer(); + WebCore::Node* cursorPointer = (WebCore::Node*) node->nodePointer(); Container* end = m_viewImpl->m_buttons.end(); for (Container* ptr = m_viewImpl->m_buttons.begin(); ptr != end; ptr++) { - if (ptr->matches(focusPointer)) { + if (ptr->matches(cursorPointer)) { isButton = true; break; } @@ -725,153 +461,93 @@ void drawFocusRing(SkCanvas* canvas) } m_viewImpl->gButtonMutex.unlock(); WebCore::IntRect bounds = node->bounds(); - bounds.inflate(SkScalarCeil(FOCUS_RING_OUTER_DIAMETER)); - SkRect sbounds; - android_setrect(&sbounds, bounds); - if (canvas->quickReject(sbounds, SkCanvas::kAA_EdgeType)) { - DBG_NAV_LOG("canvas->quickReject"); + updateCursorBounds(root, frame, node); + + WTF::Vector<WebCore::IntRect> oneRing; + bool useHitBounds = node->useHitBounds(); + if (useHitBounds) { + bounds = node->hitBounds(); + } + if (useHitBounds || node->useBounds()) { + oneRing.append(bounds); + rings = &oneRing; + } + bounds.inflate(SkScalarCeil(CURSOR_RING_OUTER_DIAMETER)); + if (canvas->quickReject(bounds, SkCanvas::kAA_EdgeType)) { + DBG_NAV_LOGD("canvas->quickReject cursorNode=%d (nodePointer=%p)" + " bounds=(%d,%d,w=%d,h=%d)", node->index(), node->nodePointer(), + bounds.x(), bounds.y(), bounds.width(), bounds.height()); m_followedLink = false; + setPluginReceivesEvents(false); return; } - FocusRing::Flavor flavor = FocusRing::NORMAL_FLAVOR; + CursorRing::Flavor flavor = CursorRing::NORMAL_FLAVOR; if (!isButton) { flavor = node->type() != NORMAL_CACHEDNODETYPE ? - FocusRing::FAKE_FLAVOR : node->nodePointer() == m_invalidNode ? - FocusRing::INVALID_FLAVOR : FocusRing::NORMAL_FLAVOR; - if (flavor != FocusRing::INVALID_FLAVOR && m_followedLink) { - flavor = (FocusRing::Flavor) (flavor + FocusRing::NORMAL_ANIMATING); + CursorRing::FAKE_FLAVOR : CursorRing::NORMAL_FLAVOR; + if (m_pluginReceivesEvents && node->isPlugin()) { + return; + } + if (m_followedLink) { + flavor = static_cast<CursorRing::Flavor> + (flavor + CursorRing::NORMAL_ANIMATING); } #if DEBUG_NAV_UI - const WebCore::IntRect& ring = rings[0]; - DBG_NAV_LOGD("cachedFocusNode=%d (nodePointer=%p) flavor=%s rings=%d" - " (%d, %d, %d, %d)", node->index(), node->nodePointer(), - flavor == FocusRing::FAKE_FLAVOR ? "FAKE_FLAVOR" : - flavor == FocusRing::INVALID_FLAVOR ? "INVALID_FLAVOR" : - flavor == FocusRing::NORMAL_ANIMATING ? "NORMAL_ANIMATING" : - flavor == FocusRing::FAKE_ANIMATING ? "FAKE_ANIMATING" : "NORMAL_FLAVOR", - rings.size(), ring.x(), ring.y(), ring.width(), ring.height()); + const WebCore::IntRect& ring = (*rings)[0]; + DBG_NAV_LOGD("cursorNode=%d (nodePointer=%p) flavor=%s rings=%d" + " (%d, %d, %d, %d) pluginReceivesEvents=%s isPlugin=%s", + node->index(), node->nodePointer(), + flavor == CursorRing::FAKE_FLAVOR ? "FAKE_FLAVOR" : + flavor == CursorRing::NORMAL_ANIMATING ? "NORMAL_ANIMATING" : + flavor == CursorRing::FAKE_ANIMATING ? "FAKE_ANIMATING" : "NORMAL_FLAVOR", + rings->size(), ring.x(), ring.y(), ring.width(), ring.height(), + m_pluginReceivesEvents ? "true" : "false", + node->isPlugin() ? "true" : "false"); #endif } - if (isButton || flavor >= FocusRing::NORMAL_ANIMATING) { + if (isButton || flavor >= CursorRing::NORMAL_ANIMATING) { SkMSec time = SkTime::GetMSecs(); if (time < m_ringAnimationEnd) { // views assume that inval bounds coordinates are non-negative bounds.intersect(WebCore::IntRect(0, 0, INT_MAX, INT_MAX)); postInvalidateDelayed(m_ringAnimationEnd - time, bounds); } else { + if (m_followedLink) + hideCursor(); m_followedLink = false; - flavor = (FocusRing::Flavor) (flavor - FocusRing::NORMAL_ANIMATING); + flavor = static_cast<CursorRing::Flavor> + (flavor - CursorRing::NORMAL_ANIMATING); } } if (!isButton) - FocusRing::DrawRing(canvas, rings, flavor); -} - -OutOfFocusFix fixOutOfDateFocus(bool useReplay) -{ - if (!m_frameCacheUI) { - DBG_NAV_LOG("!m_frameCacheUI"); - return DoNothing; - } - const CachedFrame* cachedFrame = 0; - const CachedNode* cachedFocusNode = m_frameCacheUI->currentFocus(&cachedFrame); - if (!cachedFocusNode) { - DBG_NAV_LOG("!cachedFocusNode"); - return DoNothing; - } - CachedRoot* webRoot = m_viewImpl->m_frameCacheKit; - if (!webRoot) { - DBG_NAV_LOG("!webRoot"); - return DoNothing; - } - int uiWidth = m_frameCacheUI->width(); - int webWidth = webRoot->width(); - if (uiWidth != webWidth) { - DBG_NAV_LOGD("uiWidth=%d webWidth=%d", uiWidth, webWidth); - return DoNothing; // allow text inputs to preserve their state - } else { - const WebCore::IntRect& cachedBounds = m_frameCacheUI->focusBounds(); - const CachedFrame* webFrame = 0; - const CachedNode* webFocusNode = webRoot->currentFocus(&webFrame); - DBG_NAV_LOGD("cachedBounds=(%d,%d,w=%d,h=%d) cachedFrame=%p (%d)" - " webFocusNode=%p (%d) webFrame=%p (%d)", - cachedBounds.x(), cachedBounds.y(), - cachedBounds.width(), cachedBounds.height(), - cachedFrame, cachedFrame ? cachedFrame->indexInParent() : -1, - webFocusNode, webFocusNode ? webFocusNode->index() : -1, - webFrame, webFrame ? webFrame->indexInParent() : -1); - if (webFocusNode && webFrame && webFrame->sameFrame(cachedFrame)) { - if (useReplay && !m_replay.count()) { - DBG_NAV_LOG("!m_replay.count()"); - return DoNothing; - } - if (webFocusNode->index() == cachedFocusNode->index()) { - DBG_NAV_LOG("index =="); - return DoNothing; - } - const WebCore::IntRect& webBounds = webRoot->focusBounds(); - DBG_NAV_LOGD("webBounds=(%d,%d,w=%d,h=%d)", - webBounds.x(), webBounds.y(), - webBounds.width(), webBounds.height()); - if (cachedBounds.contains(webBounds)) { - DBG_NAV_LOG("contains"); - return DoNothing; - } - if (webBounds.contains(cachedBounds)) { - DBG_NAV_LOG("webBounds contains"); - return DoNothing; - } - } - const CachedFrame* foundFrame = 0; - int x, y; - const CachedNode* found = findAt(webRoot, cachedBounds, &foundFrame, &x, &y); -#if DEBUG_NAV_UI - DBG_NAV_LOGD("found=%p (%d) frame=%p (%d)", - found, found ? found->index() : -1, - foundFrame, foundFrame ? foundFrame->indexInParent() : -1); - if (found) { - WebCore::IntRect newBounds = found->bounds(); - DBG_NAV_LOGD("found=(%d,%d,w=%d,h=%d) x=%d y=%d", - newBounds.x(), newBounds.y(), newBounds.width(), - newBounds.height(), x, y); - } -#endif - webRoot->setCachedFocus(const_cast<CachedFrame*>(foundFrame), - const_cast<CachedNode*>(found)); - if (found) - webRoot->rootHistory()->setNavBounds(found->bounds()); - WebCore::Frame* framePointer = foundFrame ? (WebCore::Frame*) foundFrame->framePointer() : 0; - WebCore::Node* nodePointer = found ? (WebCore::Node*) found->nodePointer() : 0; - setFocusData(webRoot->generation(), framePointer, nodePointer, x, y, !found); - sendFinalFocus(framePointer, nodePointer, x, y); - if (found && (found->isTextArea() || found->isTextField())) - return UpdateTextEntry; - } -checkOldFocus: - return cachedFocusNode->isTextArea() || cachedFocusNode->isTextField() ? ClearTextEntry : DoNothing; + CursorRing::DrawRing(canvas, *rings, flavor); } -bool focusIsTextArea(FrameCachePermission allowNewer) +bool cursorIsTextInput(FrameCachePermission allowNewer) { CachedRoot* root = getFrameCache(allowNewer); if (!root) { DBG_NAV_LOG("!root"); return false; } - const CachedNode* focus = root->currentFocus(); - if (!focus) + const CachedNode* cursor = root->currentCursor(); + if (!cursor) { + DBG_NAV_LOG("!cursor"); return false; - return focus->isTextArea() || focus->isTextField(); + } + DBG_NAV_LOGD("%s", + cursor->isTextArea() || cursor->isTextField() ? "true" : "false"); + return cursor->isTextArea() || cursor->isTextField(); } -void focusRingBounds(WebCore::IntRect* bounds) +void cursorRingBounds(WebCore::IntRect* bounds) { DBG_NAV_LOGD("%s", ""); CachedRoot* root = getFrameCache(DontAllowNewer); if (root) { - const CachedNode* cachedNode = root->currentFocus(); + const CachedNode* cachedNode = root->currentCursor(); if (cachedNode) { - cachedNode->focusRingBounds(bounds); + cachedNode->cursorRingBounds(bounds); DBG_NAV_LOGD("bounds={%d,%d,%d,%d}", bounds->x(), bounds->y(), bounds->width(), bounds->height()); return; @@ -880,23 +556,64 @@ void focusRingBounds(WebCore::IntRect* bounds) *bounds = WebCore::IntRect(0, 0, 0, 0); } +void fixCursor() +{ + m_viewImpl->gCursorBoundsMutex.lock(); + bool hasCursorBounds = m_viewImpl->m_hasCursorBounds; + IntRect bounds = m_viewImpl->m_cursorBounds; + m_viewImpl->gCursorBoundsMutex.unlock(); + if (!hasCursorBounds) + return; + int x, y; + const CachedFrame* frame; + const CachedNode* node = m_frameCacheUI->findAt(bounds, &frame, &x, &y, false); + if (!node) + return; + // require that node have approximately the same bounds (+/- 4) and the same + // center (+/- 2) + IntPoint oldCenter = IntPoint(bounds.x() + (bounds.width() >> 1), + bounds.y() + (bounds.height() >> 1)); + IntRect newBounds = node->bounds(); + IntPoint newCenter = IntPoint(newBounds.x() + (newBounds.width() >> 1), + newBounds.y() + (newBounds.height() >> 1)); + DBG_NAV_LOGD("oldCenter=(%d,%d) newCenter=(%d,%d)" + " bounds=(%d,%d,w=%d,h=%d) newBounds=(%d,%d,w=%d,h=%d)", + oldCenter.x(), oldCenter.y(), newCenter.x(), newCenter.y(), + bounds.x(), bounds.y(), bounds.width(), bounds.height(), + newBounds.x(), newBounds.y(), newBounds.width(), newBounds.height()); + if (abs(oldCenter.x() - newCenter.x()) > 2) + return; + if (abs(oldCenter.y() - newCenter.y()) > 2) + return; + if (abs(bounds.x() - newBounds.x()) > 4) + return; + if (abs(bounds.y() - newBounds.y()) > 4) + return; + if (abs(bounds.right() - newBounds.right()) > 4) + return; + if (abs(bounds.bottom() - newBounds.bottom()) > 4) + return; + DBG_NAV_LOGD("node=%p frame=%p x=%d y=%d bounds=(%d,%d,w=%d,h=%d)", + node, frame, x, y, bounds.x(), bounds.y(), bounds.width(), + bounds.height()); + m_frameCacheUI->setCursor(const_cast<CachedFrame*>(frame), + const_cast<CachedNode*>(node)); +} + CachedRoot* getFrameCache(FrameCachePermission allowNewer) { - if (!m_viewImpl->m_updatedFrameCache) - return m_frameCacheUI; - m_viewImpl->gRecomputeFocusMutex.lock(); - bool recomputeInProgress = m_viewImpl->m_recomputeEvents.size() > 0; - m_viewImpl->gRecomputeFocusMutex.unlock(); - if (allowNewer != AllowNewest && recomputeInProgress) + if (!m_viewImpl->m_updatedFrameCache) { + DBG_NAV_LOG("!m_viewImpl->m_updatedFrameCache"); return m_frameCacheUI; - if (allowNewer == DontAllowNewer && m_viewImpl->m_lastGeneration < m_generation) + } + if (allowNewer == DontAllowNewer && m_viewImpl->m_lastGeneration < m_generation) { + DBG_NAV_LOGD("allowNewer==DontAllowNewer m_viewImpl->m_lastGeneration=%d" + " < m_generation=%d", m_viewImpl->m_lastGeneration, m_generation); return m_frameCacheUI; + } DBG_NAV_LOGD("%s", "m_viewImpl->m_updatedFrameCache == true"); - bool hadFocus = m_frameCacheUI && m_frameCacheUI->currentFocus(); + bool hadCursor = m_frameCacheUI && m_frameCacheUI->currentCursor(); m_viewImpl->gFrameCacheMutex.lock(); - OutOfFocusFix fix = DoNothing; - if (allowNewer != DontAllowNewer) - fix = fixOutOfDateFocus(m_viewImpl->m_useReplay); delete m_frameCacheUI; delete m_navPictureUI; m_viewImpl->m_updatedFrameCache = false; @@ -905,12 +622,9 @@ CachedRoot* getFrameCache(FrameCachePermission allowNewer) m_viewImpl->m_frameCacheKit = 0; m_viewImpl->m_navPictureKit = 0; m_viewImpl->gFrameCacheMutex.unlock(); - if (hadFocus && (!m_frameCacheUI || !m_frameCacheUI->currentFocus())) - viewInvalidate(); // redraw in case focus ring is still visible - if (fix == UpdateTextEntry) - updateTextEntry(); - else if (fix == ClearTextEntry) - clearTextEntry(); + fixCursor(); + if (hadCursor && (!m_frameCacheUI || !m_frameCacheUI->currentCursor())) + viewInvalidate(); // redraw in case cursor ring is still visible return m_frameCacheUI; } @@ -970,64 +684,74 @@ static CachedFrame::Direction KeyToDirection(KeyCode keyCode) DBG_NAV_LOGD("keyCode=%s", "up"); return CachedFrame::UP; default: - LOGD("------- bad key sent to WebView::moveFocus"); + DBG_NAV_LOGD("bad key %d sent", keyCode); return CachedFrame::UNINITIALIZED; } } -bool invalidFrame(WebCore::Frame* frame, const CachedRoot* root) -{ - if (!frame) - return false; - int frameBuild = m_viewImpl->retrieveFrameGeneration(frame); - int rootBuild = root->generation(); - return frameBuild > rootBuild; -} - WebCore::String imageURI(int x, int y) { const CachedRoot* root = getFrameCache(DontAllowNewer); return root ? root->imageURI(x, y) : WebCore::String(); } -bool focusNodeWantsKeyEvents() +bool cursorWantsKeyEvents() { const CachedRoot* root = getFrameCache(DontAllowNewer); if (root) { - const CachedNode* focus = root->currentFocus(); - if (focus) { - return focus->isWantsKeyEvents(); - } + const CachedNode* focus = root->currentCursor(); + if (focus) + return focus->wantsKeyEvents(); } return false; } -/* returns true if the key had no effect (neither scrolled nor changed focus) */ -bool moveFocus(int keyCode, int count, bool ignoreScroll, bool inval, - void* lastSentFocus, const WebCore::IntRect* lastSentBounds) -{ +// This needs to be called each time we call CachedRoot::setCursor() with +// non-null CachedNode/CachedFrame, since otherwise the WebViewCore's data +// about the cursor is incorrect. When we call setCursor(0,0), we need +// to set m_viewImpl->hasCursorBounds to false. +void updateCursorBounds(const CachedRoot* root, const CachedFrame* cachedFrame, + const CachedNode* cachedNode) +{ + LOG_ASSERT(root, "updateCursorBounds: root cannot be null"); + LOG_ASSERT(cachedNode, "updateCursorBounds: cachedNode cannot be null"); + LOG_ASSERT(cachedFrame, "updateCursorBounds: cachedFrame cannot be null"); + m_viewImpl->gCursorBoundsMutex.lock(); + m_viewImpl->m_hasCursorBounds = cachedNode->hasCursorRing(); + // If m_viewImpl->m_hasCursorBounds is false, we never look at the other + // values, so do not bother setting them. + if (m_viewImpl->m_hasCursorBounds) { + WebCore::IntRect bounds = cachedNode->bounds(); + if (m_viewImpl->m_cursorBounds != bounds) + DBG_NAV_LOGD("new cursor bounds=(%d,%d,w=%d,h=%d)", + bounds.x(), bounds.y(), bounds.width(), bounds.height()); + m_viewImpl->m_cursorBounds = cachedNode->bounds(); + m_viewImpl->m_cursorHitBounds = cachedNode->hitBounds(); + m_viewImpl->m_cursorFrame = cachedFrame->framePointer(); + root->getSimulatedMousePosition(&m_viewImpl->m_cursorLocation); + m_viewImpl->m_cursorNode = cachedNode->nodePointer(); + } + m_viewImpl->gCursorBoundsMutex.unlock(); +} + +/* returns true if the key had no effect (neither scrolled nor changed cursor) */ +bool moveCursor(int keyCode, int count, bool ignoreScroll) +{ + setPluginReceivesEvents(false); CachedRoot* root = getFrameCache(AllowNewer); if (!root) { DBG_NAV_LOG("!root"); - setFocusData(0, 0, 0, 0, 0, true); - sendKitFocus(); // will build cache and retry - FirstMoveFocusParams params; - params.d.m_trigger = CommonParams::FirstMoveFocusParams; - params.d.m_generation = m_generation; - params.m_keyCode = keyCode; - params.m_count = count; - params.m_ignoreScroll = ignoreScroll; - m_replay.add(params.d, sizeof(params)); return true; } + m_viewImpl->m_moveGeneration++; CachedFrame::Direction direction = KeyToDirection((KeyCode) keyCode); const CachedFrame* cachedFrame, * oldFrame = 0; - const CachedNode* focus = root->currentFocus(&oldFrame); - WebCore::IntPoint focusLocation = root->focusLocation(); - DBG_NAV_LOGD("old focus %d (nativeNode=%p) focusLocation={%d, %d}", - focus ? focus->index() : 0, - focus ? focus->nodePointer() : 0, focusLocation.x(), focusLocation.y()); + const CachedNode* cursor = root->currentCursor(&oldFrame); + WebCore::IntPoint cursorLocation = root->cursorLocation(); + DBG_NAV_LOGD("old cursor %d (nativeNode=%p) cursorLocation={%d, %d}", + cursor ? cursor->index() : 0, + cursor ? cursor->nodePointer() : 0, cursorLocation.x(), cursorLocation.y()); WebCore::IntRect visibleRect; getVisibleRect(&visibleRect); DBG_NAV_LOGD("getVisibleRect %d,%d,%d,%d", @@ -1036,29 +760,31 @@ bool moveFocus(int keyCode, int count, bool ignoreScroll, bool inval, int xMax = getScaledMaxXScroll(); int yMax = getScaledMaxYScroll(); root->setMaxScroll(xMax, yMax); - CachedHistory savedHistory = *root->rootHistory(); - bool oldNodeIsTextArea = focusIsTextArea(DontAllowNewer); const CachedNode* cachedNode = 0; int dx = 0; int dy = 0; int counter = count; - if (!focus || !focus->isInput() || !m_followedLink) + if (!cursor || !m_followedLink) root->setScrollOnly(m_followedLink); while (--counter >= 0) { WebCore::IntPoint scroll = WebCore::IntPoint(0, 0); - cachedNode = root->moveFocus(direction, &cachedFrame, &scroll); + cachedNode = root->moveCursor(direction, &cachedFrame, &scroll); dx += scroll.x(); dy += scroll.y(); } - DBG_NAV_LOGD("new focus %d (nativeNode=%p) focusLocation={%d, %d}", - cachedNode ? cachedNode->index() : 0, - cachedNode ? cachedNode->nodePointer() : 0, root->focusLocation().x(), - root->focusLocation().y()); + DBG_NAV_LOGD("new cursor %d (nativeNode=%p) cursorLocation={%d, %d}" + "bounds={%d,%d,w=%d,h=%d}", cachedNode ? cachedNode->index() : 0, + cachedNode ? cachedNode->nodePointer() : 0, + root->cursorLocation().x(), root->cursorLocation().y(), + cachedNode ? cachedNode->bounds().x() : 0, + cachedNode ? cachedNode->bounds().y() : 0, + cachedNode ? cachedNode->bounds().width() : 0, + cachedNode ? cachedNode->bounds().height() : 0); // If !m_heightCanMeasure (such as in the browser), we want to scroll no // matter what if (!ignoreScroll && (!m_heightCanMeasure || !cachedNode || - (focus && focus->nodePointer() == cachedNode->nodePointer()))) + (cursor && cursor->nodePointer() == cachedNode->nodePointer()))) { if (count == 1 && dx != 0 && dy == 0 && -m_lastDx == dx && SkTime::GetMSecs() - m_lastDxTime < 1000) @@ -1068,55 +794,17 @@ bool moveFocus(int keyCode, int count, bool ignoreScroll, bool inval, this->scrollBy(dx, dy); m_lastDx = dx; m_lastDxTime = SkTime::GetMSecs(); - ignoreScroll = true; // if move re-executes, don't scroll the second time } bool result = false; if (cachedNode) { - WebCore::IntPoint pos; - root->setCachedFocus((CachedFrame*) cachedFrame, (CachedNode*) cachedNode); - root->getSimulatedMousePosition(&pos); - if (lastSentFocus == cachedNode->nodePointer() && lastSentBounds && - *lastSentBounds == cachedNode->bounds()) - { - sendFinalFocus((WebCore::Frame*) cachedFrame->framePointer(), - (WebCore::Node*) cachedNode->nodePointer(), pos.x(), pos.y()); - } else { - setFocusData(root->generation(), - (WebCore::Frame*) cachedFrame->framePointer(), - (WebCore::Node*) cachedNode->nodePointer(), pos.x(), pos.y(), - true); - sendKitFocus(); - if (inval) - viewInvalidate(); - MoveFocusParams params; - params.d.d.m_trigger = CommonParams::MoveFocusParams; - params.d.d.m_generation = m_generation; - params.c.setFocus(focus, oldFrame, root, focusLocation); - params.m_sentFocus = cachedNode->nodePointer(); - params.m_sentBounds = cachedNode->bounds(); - params.m_visibleRect = visibleRect; - params.m_history = savedHistory; - DBG_NAV_LOGD("history.mDidFirstLayout=%s", - params.m_history.didFirstLayout() ? "true" : "false"); - params.m_xMax = xMax; - params.m_yMax = yMax; - params.d.m_keyCode = keyCode; - params.d.m_count = count; - params.d.m_ignoreScroll = ignoreScroll; - m_replay.add(params.d.d, sizeof(params)); - } + updateCursorBounds(root, cachedFrame, cachedNode); + root->setCursor(const_cast<CachedFrame*>(cachedFrame), + const_cast<CachedNode*>(cachedNode)); + bool disableFocusController = cachedNode != root->currentFocus() + && cachedNode->wantsKeyEvents(); + sendMoveMouseIfLatest(disableFocusController); + viewInvalidate(); } else { - if (visibleRect.intersects(root->focusBounds()) == false) { - setFocusData(root->generation(), 0, 0, 0, 0, true); - sendKitFocus(); // will build cache and retry - } - FirstMoveFocusParams params; - params.d.m_trigger = CommonParams::FirstMoveFocusParams; - params.d.m_generation = m_generation; - params.m_keyCode = keyCode; - params.m_count = count; - params.m_ignoreScroll = ignoreScroll; - m_replay.add(params.d, sizeof(params)); int docHeight = root->documentHeight(); int docWidth = root->documentWidth(); if (visibleRect.bottom() + dy > docHeight) @@ -1131,45 +819,28 @@ bool moveFocus(int keyCode, int count, bool ignoreScroll, bool inval, direction == CachedFrame::RIGHT ? dx <= 0 : direction == CachedFrame::UP ? dy >= 0 : dy <= 0; } - if (focusIsTextArea(DontAllowNewer)) - updateTextEntry(); - else if (oldNodeIsTextArea) - clearTextEntry(); return result; } -void notifyFocusSet(FrameCachePermission inEditingMode) +bool pluginEatsNavKey() { CachedRoot* root = getFrameCache(DontAllowNewer); - if (root) { - // make sure the mFocusData in WebView.java is in sync with WebView.cpp - const CachedFrame* frame = 0; - const CachedNode* node = root->currentFocus(&frame); - const WebCore::IntPoint& focusLocation = root->focusLocation(); - setFocusData(root->generation(), - frame ? (WebCore::Frame*) frame->framePointer() : 0, - node ? (WebCore::Node*) node->nodePointer() : 0, - focusLocation.x(), focusLocation.y(), false); - } - - if (focusIsTextArea(inEditingMode)) - updateTextEntry(); - else if (inEditingMode) - clearTextEntry(); -#if DEBUG_NAV_UI - if (m_frameCacheUI) { - const CachedNode* focus = m_frameCacheUI->currentFocus(); - DBG_NAV_LOGD("focus %d (nativeNode=%p)", - focus ? focus->index() : 0, - focus ? focus->nodePointer() : 0); + if (!root) { + DBG_NAV_LOG("!root"); + return false; } -#endif + const CachedNode* cursor = root->currentCursor(); + DBG_NAV_LOGD("cursor=%p isPlugin=%s pluginReceivesEvents=%s", + cursor, cursor && cursor->isPlugin() ? "true" : "false", + m_pluginReceivesEvents ? "true" : "false"); + // FIXME: check to see if plugin wants keys + return cursor && cursor->isPlugin() && m_pluginReceivesEvents; } void notifyProgressFinished() { - DBG_NAV_LOGD("focusIsTextArea=%d", focusIsTextArea(DontAllowNewer)); - updateTextEntry(); + DBG_NAV_LOGD("cursorIsTextInput=%d", cursorIsTextInput(DontAllowNewer)); + rebuildWebTextView(); #if DEBUG_NAV_UI if (m_frameCacheUI) { const CachedNode* focus = m_frameCacheUI->currentFocus(); @@ -1180,121 +851,6 @@ void notifyProgressFinished() #endif } -void recomputeFocus() -{ - int generation; - do { - m_viewImpl->gRecomputeFocusMutex.lock(); - if (!m_viewImpl->m_recomputeEvents.size()) { - m_viewImpl->gRecomputeFocusMutex.unlock(); - return; - } - generation = m_viewImpl->m_recomputeEvents.first(); - m_viewImpl->m_recomputeEvents.remove(0); - m_viewImpl->gRecomputeFocusMutex.unlock(); - DBG_NAV_LOGD("generation=%d", generation); - CachedRoot* root = getFrameCache(AllowNewest); - if (!root) { - DBG_NAV_LOG("!root"); - return; - } - LargestParams storage; - const CommonParams& params = storage.d.d; - char* pos = m_replay.position(); - while (m_replay.retrieve(&storage.d.d) < generation) - DBG_NAV_LOGD("dropped ", params.m_generation); - if (params.m_generation > generation) { - DBG_NAV_LOGD("params.m_generation=%d > generation=%d", - params.m_generation, generation); - m_replay.rewind(pos); - return; - } - int lastAdd = m_replay.lastAdd(); - do { - LOG_ASSERT(params.m_trigger != CommonParams::NoData, "expected data"); - bool inval = generation == m_generation; - switch (params.m_trigger) { - case CommonParams::ClearFocusParams: { - const ClearFocusParams& sParams = *(ClearFocusParams*) &storage; - const CacheParams& cParams = sParams.c; - if (invalidFrame(cParams.m_frame, root)) { - DBG_NAV_LOGD("dropped %s generation=%d", - TriggerNames[params.m_trigger], generation); - return; - } - root->setFocus(cParams.m_frame, cParams.m_node, cParams.m_x, cParams.m_y); - clearFocus(sParams.m_x, sParams.m_y, inval); - DBG_NAV_LOGD("clearFocus(x,y)={%d,%d}", sParams.m_x, sParams.m_y); - } break; - case CommonParams::MotionUpParams: { - const MotionUpParams& mParams = *(MotionUpParams*) &storage; - // const CacheParams& cParams = mParams.c; - // if (invalidFrame(cParams.m_frame, root) == false) - // root->setFocus(cParams.m_frame, cParams.m_node, - // cParams.m_x, cParams.m_y); - motionUp(mParams.m_x, mParams.m_y, mParams.m_slop, mParams.m_isClick, inval, true); - DBG_NAV_LOGD("motionUp m_x=%d m_y=%d", mParams.m_x, mParams.m_y); - } break; - case CommonParams::FirstMoveFocusParams: { - if (invalidFrame((WebCore::Frame*) root->framePointer(), root)) { - DBG_NAV_LOGD("dropped %s generation=%d", - TriggerNames[params.m_trigger], generation); - return; - } - const FirstMoveFocusParams& fParams = *(FirstMoveFocusParams*) &storage; - DBG_NAV_LOGD("first moveFocus keyCode=%d count=%d" - " ignoreScroll=%s", fParams.m_keyCode, fParams.m_count, - fParams.m_ignoreScroll ? "true" : "false"); - moveFocus(fParams.m_keyCode, fParams.m_count, - fParams.m_ignoreScroll, inval, 0, 0); - } break; - case CommonParams::MoveFocusParams: { - const MoveFocusParams& mParams = *(MoveFocusParams*) &storage; - const CacheParams& cParams = mParams.c; - if (invalidFrame(cParams.m_frame, root)) { - DBG_NAV_LOGD("dropped %s generation=%d", - TriggerNames[params.m_trigger], generation); - return; - } - DBG_NAV_LOGD("moveFocus keyCode=%d count=%d ignoreScroll=%s " - "history.mDidFirstLayout=%s", mParams.d.m_keyCode, - mParams.d.m_count, mParams.d.m_ignoreScroll ? "true" : "false", - mParams.m_history.didFirstLayout() ? "true" : "false"); - if (!root->setFocus(cParams.m_frame, cParams.m_node, - cParams.m_x, cParams.m_y)) { - DBG_NAV_LOGD("can't restore focus frame=%p node=%p", - "x=%d y=%d %s", cParams.m_frame, cParams.m_node, - cParams.m_x, cParams.m_y, TriggerNames[params.m_trigger]); - return; - } - root->setVisibleRect(mParams.m_visibleRect); - root->setMaxScroll(mParams.m_xMax, mParams.m_yMax); - *root->rootHistory() = mParams.m_history; - moveFocus(mParams.d.m_keyCode, mParams.d.m_count, - mParams.d.m_ignoreScroll, inval, - mParams.m_sentFocus, &mParams.m_sentBounds); - } break; - default: - LOG_ASSERT(0, "unknown trigger"); - } - if (params.m_generation >= lastAdd) - break; - root = getFrameCache(DontAllowNewer); // re-execution may have retrieved newer cache - m_replay.retrieve(&storage.d.d); - DBG_NAV_LOGD("continuation m_generation %d", params.m_generation); - } while (true); - } while (true); -} - -void resetFocus() -{ - DEBUG_NAV_UI_LOGD("%s", __FUNCTION__); - CachedRoot* root = getFrameCache(AllowNewer); - if (!root) - return; - root->setCachedFocus(0, 0); -} - const CachedNode* findAt(CachedRoot* root, const WebCore::IntRect& rect, const CachedFrame** framePtr, int* rxPtr, int* ryPtr) { @@ -1306,49 +862,42 @@ const CachedNode* findAt(CachedRoot* root, const WebCore::IntRect& rect, WebCore::IntRect visibleRect; getVisibleRect(&visibleRect); root->setVisibleRect(visibleRect); - return root->findAt(rect, framePtr, rxPtr, ryPtr); + return root->findAt(rect, framePtr, rxPtr, ryPtr, true); } void selectBestAt(const WebCore::IntRect& rect) { const CachedFrame* frame; int rx, ry; + bool disableFocusController = false; CachedRoot* root = getFrameCache(DontAllowNewer); const CachedNode* node = findAt(root, rect, &frame, &rx, &ry); - int rootGeneration = root ? root->generation() : 0; - setFocusData(rootGeneration, - frame ? (WebCore::Frame*) frame->framePointer() : 0, - node ? (WebCore::Node*) node->nodePointer() : 0, rx, ry, false); + if (!node) { DBG_NAV_LOGD("no nodes found root=%p", root); - if (root) { - root->clearFocus(); - root->setCachedFocus(0, 0); + disableFocusController = true; + m_viewImpl->m_hasCursorBounds = false; + if (root) + root->setCursor(0, 0); + } else { + DBG_NAV_LOGD("CachedNode:%p (%d)", node, node->index()); + root->rootHistory()->setMouseBounds(node->bounds()); + updateCursorBounds(root, frame, node); + root->setCursor(const_cast<CachedFrame*>(frame), + const_cast<CachedNode*>(node)); + if (!node->wantsKeyEvents()) { + disableFocusController = true; } - sendKitFocus(); - viewInvalidate(); - clearTextEntry(); - return; } - DBG_NAV_LOGD("CachedNode:%p (%d)", node, node->index()); - const CachedFrame* oldFrame = 0; - const CachedNode* oldFocusNode = root->currentFocus(&oldFrame); - bool oldNodeIsTextArea = focusIsTextArea(DontAllowNewer); - root->setCachedFocus(const_cast<CachedFrame*>(frame), - const_cast<CachedNode*>(node)); + sendMoveMouseIfLatest(disableFocusController); viewInvalidate(); - if (focusIsTextArea(DontAllowNewer)) - updateTextEntry(); - else if (oldNodeIsTextArea) - clearTextEntry(); } WebCore::IntRect getNavBounds() { CachedRoot* root = getFrameCache(DontAllowNewer); - if (!root) - return WebCore::IntRect(0, 0, 0, 0); - return root->rootHistory()->navBounds(); + return root ? root->rootHistory()->navBounds() : + WebCore::IntRect(0, 0, 0, 0); } void setNavBounds(const WebCore::IntRect& rect) @@ -1359,14 +908,7 @@ void setNavBounds(const WebCore::IntRect& rect) root->rootHistory()->setNavBounds(rect); } -void markNodeInvalid(WebCore::Node* node) -{ - DBG_NAV_LOGD("node=%p", node); - m_invalidNode = node; - viewInvalidate(); -} - -bool motionUp(int x, int y, int slop, bool isClick, bool inval, bool retry) +bool motionUp(int x, int y, int slop) { bool pageScrolled = false; m_followedLink = false; @@ -1374,82 +916,48 @@ bool motionUp(int x, int y, int slop, bool isClick, bool inval, bool retry) WebCore::IntRect rect = WebCore::IntRect(x - slop, y - slop, slop * 2, slop * 2); int rx, ry; CachedRoot* root = getFrameCache(AllowNewer); + if (!root) + return false; const CachedNode* result = findAt(root, rect, &frame, &rx, &ry); if (!result) { DBG_NAV_LOGD("no nodes found root=%p", root); - int rootGeneration = 0; - if (root) { - root->clearFocus(); - rootGeneration = root->generation(); - if (!retry) { // scroll first time only - int dx = root->checkForCenter(x, y); - if (dx) { - scrollBy(dx, 0); - retry = true; // don't recompute later since we scrolled - pageScrolled = true; - } - } - } - sendMotionUp(rootGeneration, frame ? - (WebCore::Frame*) frame->framePointer() : 0, - 0, x, y, slop, isClick, retry); - if (inval) - viewInvalidate(); - if (!retry) { - MotionUpParams params; - params.d.m_trigger = CommonParams::MotionUpParams; - params.d.m_generation = m_generation; - params.m_x = x; - params.m_y = y; - params.m_slop = slop; - params.m_isClick = isClick; - m_replay.add(params.d, sizeof(params)); + setNavBounds(rect); + m_viewImpl->m_hasCursorBounds = false; + root->hideCursor(); + int dx = root->checkForCenter(x, y); + if (dx) { + scrollBy(dx, 0); + pageScrolled = true; } + sendMotionUp(frame ? (WebCore::Frame*) frame->framePointer() : 0, + 0, x, y, slop); + viewInvalidate(); clearTextEntry(); + setPluginReceivesEvents(false); return pageScrolled; } DBG_NAV_LOGD("CachedNode:%p (%d) x=%d y=%d rx=%d ry=%d", result, result->index(), x, y, rx, ry); - // const CachedFrame* oldFrame = 0; - // const CachedNode* oldFocusNode = root->currentFocus(&oldFrame); - // WebCore::IntPoint focusLocation = root->focusLocation(); - bool oldNodeIsTextArea = !retry && focusIsTextArea(DontAllowNewer); - root->setCachedFocus(const_cast<CachedFrame*>(frame), + setNavBounds(WebCore::IntRect(rx, ry, 1, 1)); + updateCursorBounds(root, frame, result); + root->setCursor(const_cast<CachedFrame*>(frame), const_cast<CachedNode*>(result)); - bool newNodeIsTextArea = focusIsTextArea(DontAllowNewer); + updatePluginReceivesEvents(); CachedNodeType type = result->type(); - if (type == NORMAL_CACHEDNODETYPE || newNodeIsTextArea) { - sendMotionUp(root->generation(), + if (type == NORMAL_CACHEDNODETYPE) { + sendMotionUp( frame ? (WebCore::Frame*) frame->framePointer() : 0, result ? (WebCore::Node*) result->nodePointer() : 0, rx, ry, - slop, isClick, retry); - if (inval) - viewInvalidate(); - if (!retry) { - MotionUpParams params; - params.d.m_trigger = CommonParams::MotionUpParams; - params.d.m_generation = m_generation; - params.m_x = x; - params.m_y = y; - params.m_slop = slop; - params.m_isClick = isClick; - // params.c.setFocus(oldFocusNode, oldFrame, root, focusLocation); - m_replay.add(params.d, sizeof(params)); - } - } else if (inval) - viewInvalidate(); - if (newNodeIsTextArea) { - updateTextEntry(); - displaySoftKeyboard(); + slop); + } + viewInvalidate(); + if (result->isTextField() || result->isTextArea()) { + rebuildWebTextView(); + displaySoftKeyboard(true); } else { - if (isClick) { - setFollowedLink(true); - if (type != NORMAL_CACHEDNODETYPE) { - overrideUrlLoading(result->getExport()); - } - } - if (oldNodeIsTextArea) - clearTextEntry(); + setFollowedLink(true); + if (type != NORMAL_CACHEDNODETYPE) + overrideUrlLoading(result->getExport()); } return pageScrolled; } @@ -1470,6 +978,32 @@ void setFindIsUp(bool up) m_hasCurrentLocation = false; } +void setPluginReceivesEvents(bool value) +{ + if (value == m_pluginReceivesEvents) + return; + + //send message to plugin in webkit + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->CallVoidMethod(m_javaGlue.object(env).get(), + m_javaGlue.m_sendPluginState, + value ? kGainFocus_PluginState : kLoseFocus_PluginState); + checkException(env); + + m_pluginReceivesEvents = value; +} + +void updatePluginReceivesEvents() +{ + CachedRoot* root = getFrameCache(DontAllowNewer); + if (!root) + return; + const CachedNode* cursor = root->currentCursor(); + setPluginReceivesEvents(cursor && cursor->isPlugin()); + DBG_NAV_LOGD("m_pluginReceivesEvents=%s cursor=%p", m_pluginReceivesEvents + ? "true" : "false", cursor); +} + void setFollowedLink(bool followed) { if ((m_followedLink = followed) != false) { @@ -1614,49 +1148,34 @@ void getSelectionCaret(SkPath* path) path->lineTo(0, height); } -void sendFinalFocus(WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y) +void sendMoveMouse(WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y) { DBG_NAV_LOGD("framePtr=%p nodePtr=%p x=%d y=%d", framePtr, nodePtr, x, y); - LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_sendFinalFocus, + env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_sendMoveMouse, (jint) framePtr, (jint) nodePtr, x, y); checkException(env); } -void sendKitFocus() +void sendMoveMouseIfLatest(bool disableFocusController) { LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_sendKitFocus); + env->CallVoidMethod(m_javaGlue.object(env).get(), + m_javaGlue.m_sendMoveMouseIfLatest, disableFocusController); checkException(env); } -void sendMotionUp(int buildGeneration, - WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y, int slop, - bool isClick, bool retry) +void sendMotionUp( + WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y, int slop) { m_viewImpl->m_touchGeneration = m_viewImpl->m_generation = ++m_generation; - DBG_NAV_LOGD("buildGeneration=%d m_generation=%d framePtr=%p nodePtr=%p" - " x=%d y=%d slop=%d", buildGeneration, + DBG_NAV_LOGD("m_generation=%d framePtr=%p nodePtr=%p x=%d y=%d slop=%d", m_generation, framePtr, nodePtr, x, y, slop); LOG_ASSERT(m_javaGlue.m_obj, "A WebView was not associated with this WebViewNative!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_sendMotionUp, m_generation, - buildGeneration, (jint) framePtr, (jint) nodePtr, x, y, slop, isClick, retry); - checkException(env); -} - -void setFocusData(int buildGeneration, WebCore::Frame* framePtr, - WebCore::Node* nodePtr, int x, int y, bool ignoreNullFocus) -{ - m_viewImpl->m_moveGeneration = m_viewImpl->m_generation = ++m_generation; - DBG_NAV_LOGD("moveGeneration=%d buildGeneration=%d framePtr=%p nodePtr=%p" - " x=%d y=%d", m_generation, buildGeneration, framePtr, nodePtr, x, y); - LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); - JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_setFocusData, m_generation, - buildGeneration, (jint) framePtr, (jint) nodePtr, x, y, ignoreNullFocus); + env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_sendMotionUp, + m_generation, (jint) framePtr, (jint) nodePtr, x, y, slop); checkException(env); } @@ -1724,68 +1243,52 @@ void scrollBy(int dx, int dy) LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_scrollBy, + env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_scrollBy, dx, dy, true); checkException(env); } -bool updateFocusNode(JNIEnv* env) +bool hasCursorNode() { CachedRoot* root = getFrameCache(DontAllowNewer); if (!root) { DBG_NAV_LOG("!root"); return false; } - const CachedFrame* cachedFrame = 0; - const CachedNode* cachedFocusNode = root->currentFocus(&cachedFrame); - if (!cachedFocusNode) { - DBG_NAV_LOG("!cachedFocusNode"); + const CachedNode* cursorNode = root->currentCursor(); + DBG_NAV_LOGD("cursorNode=%d (nodePointer=%p)", + cursorNode ? cursorNode->index() : -1, + cursorNode ? cursorNode->nodePointer() : 0); + return cursorNode; +} + +bool hasFocusNode() +{ + CachedRoot* root = getFrameCache(DontAllowNewer); + if (!root) { + DBG_NAV_LOG("!root"); return false; } - DBG_NAV_LOGD("cachedFocusNode=%d (nodePointer=%p)", - cachedFocusNode->index(), - cachedFocusNode->nodePointer()); - jobject focusnode = env->GetObjectField(m_javaGlue.object(env).get(), m_javaGlue.m_focusNode); - LOG_ASSERT(focusnode, "Could not find WebView's FocusNode"); - - bool isTextArea = cachedFocusNode->isTextArea(); - bool isTextField = cachedFocusNode->isTextField(); - int maxLength; - jstring jName; - if (isTextField) { - maxLength = cachedFocusNode->maxLength(); - const WebCore::String& name = cachedFocusNode->name(); - jName = env->NewString((jchar*)name.characters(), name.length()); - } else { - maxLength = -1; - jName = 0; - } - WebCore::IntRect bounds = cachedFocusNode->bounds(); - WebCore::String value = cachedFocusNode->getExport(); - jstring val = !value.isEmpty() ? env->NewString((jchar *)value.characters(), value.length()) : 0; - env->CallVoidMethod(focusnode, m_javaGlue.m_setAll, isTextField, isTextArea, cachedFocusNode->isPassword(), - cachedFocusNode->isAnchor(), cachedFocusNode->isRtlText(), maxLength, cachedFocusNode->textSize(), - bounds.x(), bounds.y(), bounds.right(), bounds.bottom(), (int)(cachedFocusNode->nodePointer()), - (int)(cachedFrame->framePointer()), val, jName, root->textGeneration()); - env->DeleteLocalRef(val); - env->DeleteLocalRef(focusnode); - if (isTextField) - env->DeleteLocalRef(jName); - return true; -} - -void updateTextEntry() + const CachedNode* focusNode = root->currentFocus(); + DBG_NAV_LOGD("focusNode=%d (nodePointer=%p)", + focusNode ? focusNode->index() : -1, + focusNode ? focusNode->nodePointer() : 0); + return focusNode; +} + +void rebuildWebTextView() { JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_updateTextEntry); + env->CallVoidMethod(m_javaGlue.object(env).get(), + m_javaGlue.m_rebuildWebTextView); checkException(env); } -void displaySoftKeyboard() +void displaySoftKeyboard(bool isTextView) { JNIEnv* env = JSC::Bindings::getJNIEnv(); env->CallVoidMethod(m_javaGlue.object(env).get(), - m_javaGlue.m_displaySoftKeyboard); + m_javaGlue.m_displaySoftKeyboard, isTextView); checkException(env); } @@ -1811,15 +1314,19 @@ void postInvalidateDelayed(int64_t delay, const WebCore::IntRect& bounds) checkException(env); } +int moveGeneration() +{ + return m_viewImpl->m_moveGeneration; +} + private: // local state for WebView // private to getFrameCache(); other functions operate in a different thread CachedRoot* m_frameCacheUI; // navigation data ready for use - FocusReplay m_replay; WebViewCore* m_viewImpl; - WebCore::Node* m_invalidNode; int m_generation; // associate unique ID with sent kit focus to match with ui SkPicture* m_navPictureUI; bool m_followedLink; + bool m_pluginReceivesEvents; SkMSec m_ringAnimationEnd; // Corresponds to the same-named boolean on the java side. bool m_heightCanMeasure; @@ -1852,11 +1359,11 @@ static jstring WebCoreStringToJString(JNIEnv *env, WebCore::String string) return ret; } -static void nativeClearFocus(JNIEnv *env, jobject obj, int x, int y) +static void nativeClearCursor(JNIEnv *env, jobject obj) { WebView* view = GET_NATIVE_VIEW(env, obj); LOG_ASSERT(view, "view not set in %s", __FUNCTION__); - view->clearFocus(x, y, true); + view->clearCursor(); } static void nativeCreate(JNIEnv *env, jobject obj, int viewImpl) @@ -1866,6 +1373,123 @@ static void nativeCreate(JNIEnv *env, jobject obj, int viewImpl) //Release(obj); } +static jint nativeCursorFramePointer(JNIEnv *env, jobject obj) +{ + WebView* view = GET_NATIVE_VIEW(env, obj); + CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer); + if (!root) + return 0; + const CachedFrame* frame = 0; + (void) root->currentCursor(&frame); + return reinterpret_cast<int>(frame ? frame->framePointer() : 0); +} + +static const CachedNode* getCursorNode(JNIEnv *env, jobject obj) +{ + WebView* view = GET_NATIVE_VIEW(env, obj); + CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer); + return root ? root->currentCursor() : 0; +} + +static const CachedNode* getFocusCandidate(JNIEnv *env, jobject obj) +{ + WebView* view = GET_NATIVE_VIEW(env, obj); + CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer); + if (!root) + return 0; + const CachedNode* cursor = root->currentCursor(); + if (cursor && cursor->wantsKeyEvents()) + return cursor; + return root->currentFocus(); +} + +static const CachedNode* getFocusNode(JNIEnv *env, jobject obj) +{ + WebView* view = GET_NATIVE_VIEW(env, obj); + CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer); + return root ? root->currentFocus() : 0; +} + +static jboolean nativeCursorMatchesFocus(JNIEnv *env, jobject obj) +{ + const CachedNode* cursor = getCursorNode(env, obj); + const CachedNode* focus = getFocusNode(env, obj); + return cursor && focus && cursor->nodePointer() == focus->nodePointer(); +} + +static jobject nativeCursorNodeBounds(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getCursorNode(env, obj); + WebCore::IntRect bounds = node ? node->getBounds() + : WebCore::IntRect(0, 0, 0, 0); + jclass rectClass = env->FindClass("android/graphics/Rect"); + jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V"); + jobject rect = env->NewObject(rectClass, init, bounds.x(), + bounds.y(), bounds.right(), bounds.bottom()); + return rect; +} + +static jint nativeCursorNodePointer(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getCursorNode(env, obj); + return reinterpret_cast<int>(node ? node->nodePointer() : 0); +} + +static jobject nativeCursorPosition(JNIEnv *env, jobject obj) +{ + WebView* view = GET_NATIVE_VIEW(env, obj); + const CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer); + WebCore::IntPoint pos = WebCore::IntPoint(0, 0); + if (root) + root->getSimulatedMousePosition(&pos); + jclass pointClass = env->FindClass("android/graphics/Point"); + jmethodID init = env->GetMethodID(pointClass, "<init>", "(II)V"); + jobject point = env->NewObject(pointClass, init, pos.x(), pos.y()); + return point; +} + +static WebCore::IntRect jrect_to_webrect(JNIEnv* env, jobject obj) +{ + int L, T, R, B; + GraphicsJNI::get_jrect(env, obj, &L, &T, &R, &B); + return WebCore::IntRect(L, T, R - L, B - T); +} + +static bool nativeCursorIntersects(JNIEnv *env, jobject obj, jobject visRect) +{ + const CachedNode* node = getCursorNode(env, obj); + return node ? node->getBounds().intersects(jrect_to_webrect(env, visRect)) + : false; +} + +static bool nativeCursorIsAnchor(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getCursorNode(env, obj); + return node ? node->isAnchor() : false; +} + +static bool nativeCursorIsPlugin(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getCursorNode(env, obj); + return node ? node->isPlugin() : false; +} + +static bool nativeCursorIsTextInput(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getCursorNode(env, obj); + return node ? node->isTextField() || node->isTextArea() : false; +} + +static jobject nativeCursorText(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getCursorNode(env, obj); + if (!node) + return 0; + WebCore::String value = node->getExport(); + return !value.isEmpty() ? env->NewString((jchar *)value.characters(), + value.length()) : 0; +} + static void nativeDebugDump(JNIEnv *env, jobject obj) { #if DUMP_NAV_CACHE @@ -1890,8 +1514,7 @@ static void nativeDrawMatches(JNIEnv *env, jobject obj, jobject canv) view->drawMatches(canvas); } -static void nativeDrawFocusRing(JNIEnv *env, jobject obj, - jobject canv) +static void nativeDrawCursorRing(JNIEnv *env, jobject obj, jobject canv) { SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv); if (!canv) { @@ -1903,7 +1526,7 @@ static void nativeDrawFocusRing(JNIEnv *env, jobject obj, DBG_NAV_LOG("!view"); return; } - view->drawFocusRing(canvas); + view->drawCursorRing(canvas); } static void nativeDrawSelection(JNIEnv *env, jobject obj, @@ -1951,10 +1574,96 @@ static jobject nativeImageURI(JNIEnv *env, jobject obj, jint x, jint y) return ret; } -static bool nativeFocusNodeWantsKeyEvents(JNIEnv* env, jobject jwebview) { +static bool nativeFocusCandidateIsPassword(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getFocusCandidate(env, obj); + return node ? node->isPassword() : false; +} + +static bool nativeFocusCandidateIsRtlText(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getFocusCandidate(env, obj); + return node ? node->isRtlText() : false; +} + +static bool nativeFocusCandidateIsTextField(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getFocusCandidate(env, obj); + return node ? node->isTextField() : false; +} + +static bool nativeFocusCandidateIsTextInput(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getFocusCandidate(env, obj); + return node ? node->isTextField() || node->isTextArea() : false; +} + +static jint nativeFocusCandidateMaxLength(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getFocusCandidate(env, obj); + return node ? node->maxLength() : false; +} + +static jobject nativeFocusCandidateName(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getFocusCandidate(env, obj); + if (!node) + return 0; + const WebCore::String& name = node->name(); + return env->NewString((jchar*)name.characters(), name.length()); +} + +static jobject nativeFocusCandidateNodeBounds(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getFocusCandidate(env, obj); + WebCore::IntRect bounds = node ? node->getBounds() + : WebCore::IntRect(0, 0, 0, 0); + jclass rectClass = env->FindClass("android/graphics/Rect"); + jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V"); + jobject rect = env->NewObject(rectClass, init, bounds.x(), + bounds.y(), bounds.right(), bounds.bottom()); + return rect; +} + +static jint nativeFocusCandidatePointer(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getFocusCandidate(env, obj); + return reinterpret_cast<int>(node ? node->nodePointer() : 0); +} + +static jobject nativeFocusCandidateText(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getFocusCandidate(env, obj); + if (!node) + return 0; + WebCore::String value = node->getExport(); + return !value.isEmpty() ? env->NewString((jchar *)value.characters(), + value.length()) : 0; +} + +static jint nativeFocusCandidateTextSize(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getFocusCandidate(env, obj); + return node ? node->textSize() : 0; +} + +static jint nativeFocusNodePointer(JNIEnv *env, jobject obj) +{ + const CachedNode* node = getFocusNode(env, obj); + return node ? reinterpret_cast<int>(node->nodePointer()) : 0; +} + +static bool nativeCursorWantsKeyEvents(JNIEnv* env, jobject jwebview) { WebView* view = GET_NATIVE_VIEW(env, jwebview); LOG_ASSERT(view, "view not set in %s", __FUNCTION__); - return view->focusNodeWantsKeyEvents(); + return view->cursorWantsKeyEvents(); +} + +static void nativeHideCursor(JNIEnv *env, jobject obj) +{ + WebView* view = GET_NATIVE_VIEW(env, obj); + LOG_ASSERT(view, "view not set in %s", __FUNCTION__); + view->hideCursor(); } static void nativeInstrumentReport(JNIEnv *env, jobject obj) @@ -1964,13 +1673,6 @@ static void nativeInstrumentReport(JNIEnv *env, jobject obj) #endif } -static WebCore::IntRect jrect_to_webrect(JNIEnv* env, jobject obj) -{ - int L, T, R, B; - GraphicsJNI::get_jrect(env, obj, &L, &T, &R, &B); - return WebCore::IntRect(L, T, R - L, B - T); -} - static void nativeSelectBestAt(JNIEnv *env, jobject obj, jobject jrect) { WebView* view = GET_NATIVE_VIEW(env, obj); @@ -1979,49 +1681,38 @@ static void nativeSelectBestAt(JNIEnv *env, jobject obj, jobject jrect) view->selectBestAt(rect); } -static void nativeMarkNodeInvalid(JNIEnv *env, jobject obj, int node) +static jint nativeTextGeneration(JNIEnv *env, jobject obj) { WebView* view = GET_NATIVE_VIEW(env, obj); - LOG_ASSERT(view, "view not set in %s", __FUNCTION__); - view->markNodeInvalid((WebCore::Node*) node); + CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer); + return root ? root->textGeneration() : 0; } static bool nativeMotionUp(JNIEnv *env, jobject obj, - int x, int y, int slop, bool isClick) + int x, int y, int slop) { WebView* view = GET_NATIVE_VIEW(env, obj); LOG_ASSERT(view, "view not set in %s", __FUNCTION__); - return view->motionUp(x, y, slop, isClick, true, false); + return view->motionUp(x, y, slop); } -static bool nativeUpdateFocusNode(JNIEnv *env, jobject obj) -{ - WebView* view = GET_NATIVE_VIEW(env, obj); - LOG_ASSERT(view, "view not set in %s", __FUNCTION__); - return view->updateFocusNode(env); -} - -static bool nativeMoveFocus(JNIEnv *env, jobject obj, - int key, int count, bool ignoreScroll) +static bool nativeHasCursorNode(JNIEnv *env, jobject obj) { - WebView* view = GET_NATIVE_VIEW(env, obj); - DBG_NAV_LOGD("env=%p obj=%p view=%p", env, obj, view); - LOG_ASSERT(view, "view not set in %s", __FUNCTION__); - return view->moveFocus(key, count, ignoreScroll, true, 0, 0); + return GET_NATIVE_VIEW(env, obj)->hasCursorNode(); } -static void nativeNotifyFocusSet(JNIEnv *env, jobject obj, bool inEditingMode) +static bool nativeHasFocusNode(JNIEnv *env, jobject obj) { - WebView* view = GET_NATIVE_VIEW(env, obj); - LOG_ASSERT(view, "view not set in %s", __FUNCTION__); - view->notifyFocusSet((WebView::FrameCachePermission) inEditingMode); + return GET_NATIVE_VIEW(env, obj)->hasFocusNode(); } -static void nativeRecomputeFocus(JNIEnv *env, jobject obj) +static bool nativeMoveCursor(JNIEnv *env, jobject obj, + int key, int count, bool ignoreScroll) { WebView* view = GET_NATIVE_VIEW(env, obj); + DBG_NAV_LOGD("env=%p obj=%p view=%p", env, obj, view); LOG_ASSERT(view, "view not set in %s", __FUNCTION__); - view->recomputeFocus(); + return view->moveCursor(key, count, ignoreScroll); } static void nativeRecordButtons(JNIEnv* env, jobject obj, bool hasFocus, @@ -2032,18 +1723,16 @@ static void nativeRecordButtons(JNIEnv* env, jobject obj, bool hasFocus, view->nativeRecordButtons(hasFocus, pressed, invalidate); } -static void nativeResetFocus(JNIEnv *env, jobject obj) +static void nativeSetFindIsDown(JNIEnv *env, jobject obj) { WebView* view = GET_NATIVE_VIEW(env, obj); LOG_ASSERT(view, "view not set in %s", __FUNCTION__); - view->resetFocus(); + view->setFindIsUp(false); } -static void nativeSetFindIsDown(JNIEnv *env, jobject obj) +static void nativeUpdatePluginReceivesEvents(JNIEnv *env, jobject obj) { - WebView* view = GET_NATIVE_VIEW(env, obj); - LOG_ASSERT(view, "view not set in %s", __FUNCTION__); - view->setFindIsUp(false); + GET_NATIVE_VIEW(env, obj)->updatePluginReceivesEvents(); } static void nativeSetFollowedLink(JNIEnv *env, jobject obj, bool followed) @@ -2060,7 +1749,7 @@ static void nativeSetHeightCanMeasure(JNIEnv *env, jobject obj, bool measure) view->setHeightCanMeasure(measure); } -static jobject nativeGetFocusRingBounds(JNIEnv *env, jobject obj) +static jobject nativeGetCursorRingBounds(JNIEnv *env, jobject obj) { WebView* view = GET_NATIVE_VIEW(env, obj); LOG_ASSERT(view, "view not set in %s", __FUNCTION__); @@ -2069,34 +1758,12 @@ static jobject nativeGetFocusRingBounds(JNIEnv *env, jobject obj) jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V"); LOG_ASSERT(init, "Could not find constructor for Rect"); WebCore::IntRect webRect; - view->focusRingBounds(&webRect); + view->cursorRingBounds(&webRect); jobject rect = env->NewObject(rectClass, init, webRect.x(), webRect.y(), webRect.right(), webRect.bottom()); return rect; } -static jobject nativeGetNavBounds(JNIEnv *env, jobject obj) -{ - WebView* view = GET_NATIVE_VIEW(env, obj); - LOG_ASSERT(view, "view not set in %s", __FUNCTION__); - jclass rectClass = env->FindClass("android/graphics/Rect"); - LOG_ASSERT(rectClass, "Could not find Rect class!"); - jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V"); - LOG_ASSERT(init, "Could not find constructor for Rect"); - WebCore::IntRect webRect = view->getNavBounds(); - jobject rect = env->NewObject(rectClass, init, webRect.x(), - webRect.y(), webRect.right(), webRect.bottom()); - return rect; -} - -static void nativeSetNavBounds(JNIEnv *env, jobject obj, jobject jrect) -{ - WebView* view = GET_NATIVE_VIEW(env, obj); - LOG_ASSERT(view, "view not set in %s", __FUNCTION__); - WebCore::IntRect rect = jrect_to_webrect(env, jrect); - view->setNavBounds(rect); -} - static int nativeFindAll(JNIEnv *env, jobject obj, jstring findLower, jstring findUpper) { @@ -2135,11 +1802,8 @@ static int nativeFindAll(JNIEnv *env, jobject obj, jstring findLower, checkException(env); return 0; } - static const int MAX_16_BIT_INT = 65535; int width = root->documentWidth(); - if (width > MAX_16_BIT_INT) width = MAX_16_BIT_INT; int height = root->documentHeight(); - if (height > MAX_16_BIT_INT) height = MAX_16_BIT_INT; // Create a FindCanvas, which allows us to fake draw into it so we can // figure out where our search string is rendered (and how many times). FindCanvas canvas(width, height, (const UChar*) findLowerChars, @@ -2189,6 +1853,14 @@ static void nativeDestroy(JNIEnv *env, jobject obj) delete view; } +static int nativeMoveGeneration(JNIEnv *env, jobject obj) +{ + WebView* view = GET_NATIVE_VIEW(env, obj); + if (!view) + return 0; + return view->moveGeneration(); +} + static void nativeMoveSelection(JNIEnv *env, jobject obj, int x, int y, bool ex) { WebView* view = GET_NATIVE_VIEW(env, obj); @@ -2196,6 +1868,11 @@ static void nativeMoveSelection(JNIEnv *env, jobject obj, int x, int y, bool ex) view->moveSelection(x, y, ex); } +static bool nativePluginEatsNavKey(JNIEnv *env, jobject obj) +{ + return GET_NATIVE_VIEW(env, obj)->pluginEatsNavKey(); +} + static jobject nativeGetSelection(JNIEnv *env, jobject obj) { WebView* view = GET_NATIVE_VIEW(env, obj); @@ -2216,29 +1893,25 @@ static void nativeDumpDisplayTree(JNIEnv* env, jobject jwebview, jstring jurl) WebView* view = GET_NATIVE_VIEW(env, jwebview); LOG_ASSERT(view, "view not set in %s", __FUNCTION__); - CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer); - if (root) { - SkPicture* picture = root->getPicture(); - if (picture) { - FILE* file = fopen(DISPLAY_TREE_LOG_FILE, "w"); - if (file) { - SkFormatDumper dumper(dumpToFile, file); - // dump the URL - if (jurl) { - const char* str = env->GetStringUTFChars(jurl, 0); - SkDebugf("Dumping %s to %s\n", str, DISPLAY_TREE_LOG_FILE); - dumpToFile(str, file); - env->ReleaseStringUTFChars(jurl, str); - } - // now dump the display tree - SkDumpCanvas canvas(&dumper); - // this will playback the picture into the canvas, which will - // spew its contents to the dumper - picture->draw(&canvas); - // we're done with the file now - fwrite("\n", 1, 1, file); - fclose(file); + if (view && view->getWebViewCore()) { + FILE* file = fopen(DISPLAY_TREE_LOG_FILE, "w"); + if (file) { + SkFormatDumper dumper(dumpToFile, file); + // dump the URL + if (jurl) { + const char* str = env->GetStringUTFChars(jurl, 0); + SkDebugf("Dumping %s to %s\n", str, DISPLAY_TREE_LOG_FILE); + dumpToFile(str, file); + env->ReleaseStringUTFChars(jurl, str); } + // now dump the display tree + SkDumpCanvas canvas(&dumper); + // this will playback the picture into the canvas, which will + // spew its contents to the dumper + view->getWebViewCore()->drawContent(&canvas, 0); + // we're done with the file now + fwrite("\n", 1, 1, file); + fclose(file); } } #endif @@ -2248,48 +1921,98 @@ static void nativeDumpDisplayTree(JNIEnv* env, jobject jwebview, jstring jurl) * JNI registration */ static JNINativeMethod gJavaWebViewMethods[] = { - { "nativeFindAll", "(Ljava/lang/String;Ljava/lang/String;)I", - (void*) nativeFindAll }, - { "nativeFindNext", "(Z)V", - (void*) nativeFindNext }, - { "nativeClearFocus", "(II)V", - (void*) nativeClearFocus }, + { "nativeClearCursor", "()V", + (void*) nativeClearCursor }, { "nativeCreate", "(I)V", (void*) nativeCreate }, + { "nativeCursorFramePointer", "()I", + (void*) nativeCursorFramePointer }, + { "nativeCursorMatchesFocus", "()Z", + (void*) nativeCursorMatchesFocus }, + { "nativeCursorNodeBounds", "()Landroid/graphics/Rect;", + (void*) nativeCursorNodeBounds }, + { "nativeCursorNodePointer", "()I", + (void*) nativeCursorNodePointer }, + { "nativeCursorIntersects", "(Landroid/graphics/Rect;)Z", + (void*) nativeCursorIntersects }, + { "nativeCursorIsAnchor", "()Z", + (void*) nativeCursorIsAnchor }, + { "nativeCursorIsPlugin", "()Z", + (void*) nativeCursorIsPlugin }, + { "nativeCursorIsTextInput", "()Z", + (void*) nativeCursorIsTextInput }, + { "nativeCursorPosition", "()Landroid/graphics/Point;", + (void*) nativeCursorPosition }, + { "nativeCursorText", "()Ljava/lang/String;", + (void*) nativeCursorText }, + { "nativeCursorWantsKeyEvents", "()Z", + (void*)nativeCursorWantsKeyEvents }, { "nativeDebugDump", "()V", (void*) nativeDebugDump }, { "nativeDestroy", "()V", (void*) nativeDestroy }, + { "nativeDrawCursorRing", "(Landroid/graphics/Canvas;)V", + (void*) nativeDrawCursorRing }, { "nativeDrawMatches", "(Landroid/graphics/Canvas;)V", (void*) nativeDrawMatches }, - { "nativeDrawFocusRing", "(Landroid/graphics/Canvas;)V", - (void*) nativeDrawFocusRing }, { "nativeDrawSelection", "(Landroid/graphics/Canvas;IIZ)V", (void*) nativeDrawSelection }, { "nativeDrawSelectionRegion", "(Landroid/graphics/Canvas;)V", (void*) nativeDrawSelectionRegion }, - { "nativeUpdateFocusNode", "()Z", - (void*) nativeUpdateFocusNode }, - { "nativeGetFocusRingBounds", "()Landroid/graphics/Rect;", - (void*) nativeGetFocusRingBounds }, - { "nativeGetNavBounds", "()Landroid/graphics/Rect;", - (void*) nativeGetNavBounds }, + { "nativeDumpDisplayTree", "(Ljava/lang/String;)V", + (void*) nativeDumpDisplayTree }, + { "nativeFindAll", "(Ljava/lang/String;Ljava/lang/String;)I", + (void*) nativeFindAll }, + { "nativeFindNext", "(Z)V", + (void*) nativeFindNext }, + { "nativeFocusCandidateIsPassword", "()Z", + (void*) nativeFocusCandidateIsPassword }, + { "nativeFocusCandidateIsRtlText", "()Z", + (void*) nativeFocusCandidateIsRtlText }, + { "nativeFocusCandidateIsTextField", "()Z", + (void*) nativeFocusCandidateIsTextField }, + { "nativeFocusCandidateIsTextInput", "()Z", + (void*) nativeFocusCandidateIsTextInput }, + { "nativeFocusCandidateMaxLength", "()I", + (void*) nativeFocusCandidateMaxLength }, + { "nativeFocusCandidateName", "()Ljava/lang/String;", + (void*) nativeFocusCandidateName }, + { "nativeFocusCandidateNodeBounds", "()Landroid/graphics/Rect;", + (void*) nativeFocusCandidateNodeBounds }, + { "nativeFocusCandidatePointer", "()I", + (void*) nativeFocusCandidatePointer }, + { "nativeFocusCandidateText", "()Ljava/lang/String;", + (void*) nativeFocusCandidateText }, + { "nativeFocusCandidateTextSize", "()I", + (void*) nativeFocusCandidateTextSize }, + { "nativeFocusNodePointer", "()I", + (void*) nativeFocusNodePointer }, + { "nativeGetCursorRingBounds", "()Landroid/graphics/Rect;", + (void*) nativeGetCursorRingBounds }, + { "nativeGetSelection", "()Landroid/graphics/Region;", + (void*) nativeGetSelection }, + { "nativeHasCursorNode", "()Z", + (void*) nativeHasCursorNode }, + { "nativeHasFocusNode", "()Z", + (void*) nativeHasFocusNode }, + { "nativeHideCursor", "()V", + (void*) nativeHideCursor }, + { "nativeImageURI", "(II)Ljava/lang/String;", + (void*) nativeImageURI }, { "nativeInstrumentReport", "()V", (void*) nativeInstrumentReport }, - { "nativeMarkNodeInvalid", "(I)V", - (void*) nativeMarkNodeInvalid }, - { "nativeMotionUp", "(IIIZ)Z", + { "nativeMotionUp", "(III)Z", (void*) nativeMotionUp }, - { "nativeMoveFocus", "(IIZ)Z", - (void*) nativeMoveFocus }, - { "nativeNotifyFocusSet", "(Z)V", - (void*) nativeNotifyFocusSet }, - { "nativeRecomputeFocus", "()V", - (void*) nativeRecomputeFocus }, + { "nativeMoveCursor", "(IIZ)Z", + (void*) nativeMoveCursor }, + { "nativeMoveGeneration", "()I", + (void*) nativeMoveGeneration }, + { "nativeMoveSelection", "(IIZ)V", + (void*) nativeMoveSelection }, + { "nativePluginEatsNavKey", "()Z", + (void*) nativePluginEatsNavKey }, { "nativeRecordButtons", "(ZZZ)V", (void*) nativeRecordButtons }, - { "nativeResetFocus", "()V", - (void*) nativeResetFocus }, { "nativeSelectBestAt", "(Landroid/graphics/Rect;)V", (void*) nativeSelectBestAt }, { "nativeSetFindIsDown", "()V", @@ -2298,20 +2021,12 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeSetFollowedLink }, { "nativeSetHeightCanMeasure", "(Z)V", (void*) nativeSetHeightCanMeasure }, - { "nativeSetNavBounds", "(Landroid/graphics/Rect;)V", - (void*) nativeSetNavBounds }, - { "nativeImageURI", "(II)Ljava/lang/String;", - (void*) nativeImageURI }, - { "nativeFocusNodeWantsKeyEvents", "()Z", - (void*)nativeFocusNodeWantsKeyEvents }, + { "nativeTextGeneration", "()I", + (void*) nativeTextGeneration }, { "nativeUpdateCachedTextfield", "(Ljava/lang/String;I)V", (void*) nativeUpdateCachedTextfield }, - { "nativeMoveSelection", "(IIZ)V", - (void*) nativeMoveSelection }, - { "nativeGetSelection", "()Landroid/graphics/Region;", - (void*) nativeGetSelection }, - { "nativeDumpDisplayTree", "(Ljava/lang/String;)V", - (void*) nativeDumpDisplayTree } + { "nativeUpdatePluginReceivesEvents", "()V", + (void*) nativeUpdatePluginReceivesEvents } }; int register_webview(JNIEnv* env) diff --git a/WebKit/android/plugins/ANPBitmapInterface.cpp b/WebKit/android/plugins/ANPBitmapInterface.cpp new file mode 100644 index 0000000..25d1e97 --- /dev/null +++ b/WebKit/android/plugins/ANPBitmapInterface.cpp @@ -0,0 +1,72 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// must include config.h first for webkit to fiddle with new/delete +#include "config.h" +#include "SkANP.h" +#include "SkColorPriv.h" + +static bool anp_getPixelPacking(ANPBitmapFormat fmt, ANPPixelPacking* packing) { + switch (fmt) { + case kRGBA_8888_ANPBitmapFormat: + if (packing) { + packing->AShift = SK_A32_SHIFT; + packing->ABits = SK_A32_BITS; + packing->RShift = SK_R32_SHIFT; + packing->RBits = SK_R32_BITS; + packing->GShift = SK_G32_SHIFT; + packing->GBits = SK_G32_BITS; + packing->BShift = SK_B32_SHIFT; + packing->BBits = SK_B32_BITS; + } + return true; + case kRGB_565_ANPBitmapFormat: + if (packing) { + packing->AShift = 0; + packing->ABits = 0; + packing->RShift = SK_R16_SHIFT; + packing->RBits = SK_R16_BITS; + packing->GShift = SK_G16_SHIFT; + packing->GBits = SK_G16_BITS; + packing->BShift = SK_B16_SHIFT; + packing->BBits = SK_B16_BITS; + } + return true; + default: + break; + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////// + +#define ASSIGN(obj, name) (obj)->name = anp_##name + +void ANPBitmapInterfaceV0_Init(ANPInterface* value) { + ANPBitmapInterfaceV0* i = reinterpret_cast<ANPBitmapInterfaceV0*>(value); + + ASSIGN(i, getPixelPacking); +} + diff --git a/WebKit/android/plugins/ANPCanvasInterface.cpp b/WebKit/android/plugins/ANPCanvasInterface.cpp index ba79691..c985f64 100644 --- a/WebKit/android/plugins/ANPCanvasInterface.cpp +++ b/WebKit/android/plugins/ANPCanvasInterface.cpp @@ -68,6 +68,9 @@ static void anp_clipRect(ANPCanvas* canvas, const ANPRectF* rect) { static void anp_clipPath(ANPCanvas* canvas, const ANPPath* path) { canvas->skcanvas->clipPath(*path); } +static void anp_concat(ANPCanvas* canvas, const ANPMatrix* matrix) { + canvas->skcanvas->concat(*matrix); +} static void anp_getTotalMatrix(ANPCanvas* canvas, ANPMatrix* matrix) { const SkMatrix& src = canvas->skcanvas->getTotalMatrix(); @@ -102,6 +105,12 @@ static void anp_drawPaint(ANPCanvas* canvas, const ANPPaint* paint) { canvas->skcanvas->drawPaint(*paint); } +static void anp_drawLine(ANPCanvas* canvas, float x0, float y0, + float x1, float y1, const ANPPaint* paint) { + canvas->skcanvas->drawLine(SkFloatToScalar(x0), SkFloatToScalar(y0), + SkFloatToScalar(x1), SkFloatToScalar(y1), *paint); +} + static void anp_drawRect(ANPCanvas* canvas, const ANPRectF* rect, const ANPPaint* paint) { SkRect r; @@ -146,7 +155,7 @@ static void anp_drawBitmapRect(ANPCanvas* canvas, const ANPBitmap* bitmap, SkBitmap bm; SkRect dstR; SkIRect srcR, *srcPtr = NULL; - + if (src) { srcPtr = SkANP::SetRect(&srcR, *src); } @@ -160,7 +169,7 @@ static void anp_drawBitmapRect(ANPCanvas* canvas, const ANPBitmap* bitmap, void ANPCanvasInterfaceV0_Init(ANPInterface* value) { ANPCanvasInterfaceV0* i = reinterpret_cast<ANPCanvasInterfaceV0*>(value); - + ASSIGN(i, newCanvas); ASSIGN(i, deleteCanvas); ASSIGN(i, save); @@ -171,11 +180,13 @@ void ANPCanvasInterfaceV0_Init(ANPInterface* value) { ASSIGN(i, skew); ASSIGN(i, clipRect); ASSIGN(i, clipPath); + ASSIGN(i, concat); ASSIGN(i, getTotalMatrix); ASSIGN(i, getLocalClipBounds); ASSIGN(i, getDeviceClipBounds); ASSIGN(i, drawColor); ASSIGN(i, drawPaint); + ASSIGN(i, drawLine); ASSIGN(i, drawRect); ASSIGN(i, drawOval); ASSIGN(i, drawPath); diff --git a/WebKit/android/plugins/ANPPathInterface.cpp b/WebKit/android/plugins/ANPPathInterface.cpp new file mode 100644 index 0000000..468d866 --- /dev/null +++ b/WebKit/android/plugins/ANPPathInterface.cpp @@ -0,0 +1,113 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// must include config.h first for webkit to fiddle with new/delete +#include "config.h" +#include "SkANP.h" + +static ANPPath* anp_newPath() { + return new ANPPath; +} + +static void anp_deletePath(ANPPath* path) { + delete path; +} + +static void anp_copy(ANPPath* dst, const ANPPath* src) { + *dst = *src; +} + +static bool anp_equal(const ANPPath* p0, const ANPPath* p1) { + return *p0 == *p1; +} + +static void anp_reset(ANPPath* path) { + path->reset(); +} + +static bool anp_isEmpty(const ANPPath* path) { + return path->isEmpty(); +} + +static void anp_getBounds(const ANPPath* path, ANPRectF* bounds) { + SkANP::SetRect(bounds, path->getBounds()); +} + +static void anp_moveTo(ANPPath* path, float x, float y) { + path->moveTo(SkFloatToScalar(x), SkFloatToScalar(y)); +} + +static void anp_lineTo(ANPPath* path, float x, float y) { + path->lineTo(SkFloatToScalar(x), SkFloatToScalar(y)); +} + +static void anp_quadTo(ANPPath* path, float x0, float y0, float x1, float y1) { + path->quadTo(SkFloatToScalar(x0), SkFloatToScalar(y0), + SkFloatToScalar(x1), SkFloatToScalar(y1)); +} + +static void anp_cubicTo(ANPPath* path, float x0, float y0, + float x1, float y1, float x2, float y2) { + path->cubicTo(SkFloatToScalar(x0), SkFloatToScalar(y0), + SkFloatToScalar(x1), SkFloatToScalar(y1), + SkFloatToScalar(x2), SkFloatToScalar(y2)); +} + +static void anp_close(ANPPath* path) { + path->close(); +} + +static void anp_offset(ANPPath* path, float dx, float dy, ANPPath* dst) { + path->offset(SkFloatToScalar(dx), SkFloatToScalar(dy), dst); +} + +static void anp_transform(ANPPath* src, const ANPMatrix* matrix, + ANPPath* dst) { + src->transform(*matrix, dst); +} + +/////////////////////////////////////////////////////////////////////////////// + +#define ASSIGN(obj, name) (obj)->name = anp_##name + +void ANPPathInterfaceV0_Init(ANPInterface* value) { + ANPPathInterfaceV0* i = reinterpret_cast<ANPPathInterfaceV0*>(value); + + ASSIGN(i, newPath); + ASSIGN(i, deletePath); + ASSIGN(i, copy); + ASSIGN(i, equal); + ASSIGN(i, reset); + ASSIGN(i, isEmpty); + ASSIGN(i, getBounds); + ASSIGN(i, moveTo); + ASSIGN(i, lineTo); + ASSIGN(i, quadTo); + ASSIGN(i, cubicTo); + ASSIGN(i, close); + ASSIGN(i, offset); + ASSIGN(i, transform); +} + diff --git a/WebKit/android/plugins/ANPSurfaceInterface.cpp b/WebKit/android/plugins/ANPSurfaceInterface.cpp new file mode 100644 index 0000000..835f45a --- /dev/null +++ b/WebKit/android/plugins/ANPSurfaceInterface.cpp @@ -0,0 +1,97 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// must include config.h first for webkit to fiddle with new/delete +#include "config.h" + +#include "PluginSurface.h" +#include "PluginView.h" +#include "PluginWidgetAndroid.h" +#include "SkANP.h" + +using namespace WebCore; + +static ANPSurface* anp_newSurface(NPP instance, ANPSurfaceType type) { + if (instance && instance->ndata) { + PluginView* view = static_cast<PluginView*>(instance->ndata); + PluginWidgetAndroid* widget = view->platformPluginWidget(); + return widget->createSurface(type); + } + return NULL; +} + +static void anp_deleteSurface(ANPSurface* surface) { + if (surface) { + if (surface->data) { + android::PluginSurface* s = + static_cast<android::PluginSurface*>(surface->data); + s->destroy(); + } + delete surface; + } +} + +static bool anp_lock(ANPSurface* surface, ANPBitmap* bitmap, + ANPRectI* dirtyRect) { + if (bitmap && surface && surface->data) { + android::PluginSurface* s = + static_cast<android::PluginSurface*>(surface->data); + SkBitmap src; + bool res = false; + if (dirtyRect) { + SkIRect rect; + res = s->lock(SkANP::SetRect(&rect, *dirtyRect), &src); + } else { + res = s->lock(NULL, &src); + } + if (res) { + res &= SkANP::SetBitmap(bitmap, src); + } + return res; + } + return false; +} + +static void anp_unlock(ANPSurface* surface) { + if (surface && surface->data) { + android::PluginSurface* s = + static_cast<android::PluginSurface*>(surface->data); + s->unlock(); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +#define ASSIGN(obj, name) (obj)->name = anp_##name + +void ANPSurfaceInterfaceV0_Init(ANPInterface* value) { + ANPSurfaceInterfaceV0* i = reinterpret_cast<ANPSurfaceInterfaceV0*>(value); + + ASSIGN(i, newSurface); + ASSIGN(i, deleteSurface); + ASSIGN(i, lock); + ASSIGN(i, unlock); +} + diff --git a/WebKit/android/plugins/ANPTypefaceInterface.cpp b/WebKit/android/plugins/ANPTypefaceInterface.cpp index 17b3067..d560d3e 100644 --- a/WebKit/android/plugins/ANPTypefaceInterface.cpp +++ b/WebKit/android/plugins/ANPTypefaceInterface.cpp @@ -26,6 +26,7 @@ // must include config.h first for webkit to fiddle with new/delete #include "config.h" #include "SkANP.h" +#include "SkFontHost.h" static ANPTypeface* anp_createFromName(const char name[], ANPTypefaceStyle s) { SkTypeface* tf = SkTypeface::CreateFromName(name, @@ -57,6 +58,27 @@ static ANPTypefaceStyle anp_getStyle(const ANPTypeface* tf) { return static_cast<ANPTypefaceStyle>(s); } +static const char* gFontDir; +#define FONT_DIR_SUFFIX "/fonts/" + +static const char* anp_getFontDirectoryPath() { + if (NULL == gFontDir) { + const char* root = getenv("ANDROID_ROOT"); + size_t len = strlen(root); + char* storage = (char*)malloc(len + sizeof(FONT_DIR_SUFFIX)); + if (NULL == storage) { + return NULL; + } + memcpy(storage, root, len); + memcpy(storage + len, FONT_DIR_SUFFIX, sizeof(FONT_DIR_SUFFIX)); + // save this assignment for last, so that if multiple threads call us + // (which should never happen), we never return an incomplete global. + // At worst, we would allocate storage for the path twice. + gFontDir = storage; + } + return gFontDir; +} + /////////////////////////////////////////////////////////////////////////////// #define ASSIGN(obj, name) (obj)->name = anp_##name @@ -70,5 +92,6 @@ void ANPTypefaceInterfaceV0_Init(ANPInterface* v) { ASSIGN(i, ref); ASSIGN(i, unref); ASSIGN(i, getStyle); + ASSIGN(i, getFontDirectoryPath); } diff --git a/WebKit/android/plugins/ANPWindowInterface.cpp b/WebKit/android/plugins/ANPWindowInterface.cpp index 4aa862b..41e00e9 100644 --- a/WebKit/android/plugins/ANPWindowInterface.cpp +++ b/WebKit/android/plugins/ANPWindowInterface.cpp @@ -26,6 +26,9 @@ // must include config.h first for webkit to fiddle with new/delete #include "config.h" #include "SkANP.h" +#include "WebViewCore.h" +#include "PluginView.h" +#include "PluginWidgetAndroid.h" static bool anp_lockRect(void* window, const ANPRectI* inval, ANPBitmap* bitmap) { @@ -48,15 +51,40 @@ static bool anp_lockRegion(void* window, const ANPRegion* inval, static void anp_unlock(void* window) { } +static PluginView* pluginViewForInstance(NPP instance) { + if (instance && instance->ndata) + return static_cast<PluginView*>(instance->ndata); + return PluginView::currentPluginView(); +} + +static void anp_setVisibleRects(NPP instance, const ANPRectI rects[], int32_t count) { + PluginView* pluginView = pluginViewForInstance(instance); + PluginWidgetAndroid* pluginWidget = pluginView->platformPluginWidget(); + pluginWidget->setVisibleRects(rects, count); +} + +static void anp_clearVisibleRects(NPP instance) { + anp_setVisibleRects(instance, NULL, 0); +} + +static void anp_showKeyboard(NPP instance, bool value) { + ScrollView* scrollView = pluginViewForInstance(instance)->parent(); + android::WebViewCore* core = android::WebViewCore::getWebViewCore(scrollView); + core->requestKeyboard(value); +} + /////////////////////////////////////////////////////////////////////////////// #define ASSIGN(obj, name) (obj)->name = anp_##name void ANPWindowInterfaceV0_Init(ANPInterface* value) { ANPWindowInterfaceV0* i = reinterpret_cast<ANPWindowInterfaceV0*>(value); - + ASSIGN(i, lockRect); ASSIGN(i, lockRegion); + ASSIGN(i, setVisibleRects); + ASSIGN(i, clearVisibleRects); + ASSIGN(i, showKeyboard); ASSIGN(i, unlock); } diff --git a/WebKit/android/plugins/PluginSurface.cpp b/WebKit/android/plugins/PluginSurface.cpp new file mode 100644 index 0000000..aba0263 --- /dev/null +++ b/WebKit/android/plugins/PluginSurface.cpp @@ -0,0 +1,186 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "PluginSurface.h" + +#include "android_graphics.h" +#include "PluginWidgetAndroid.h" +#include "WebViewCore.h" +#include "jni_utility.h" + +#include <ui/Rect.h> +#include <ui/Region.h> +#include <ui/Surface.h> + +namespace android { + +// jni field offset for the native surface pointer. +static jfieldID gSurfaceField; +static jmethodID gGetHolder; +static jmethodID gGetSurface; + +static void initFields(JNIEnv* env) { + if (gSurfaceField) + return; + + jclass clazz = env->FindClass("android/view/Surface"); + gSurfaceField = env->GetFieldID(clazz, "mSurface", "I"); + + clazz = env->FindClass("android/view/SurfaceView"); + gGetHolder = env->GetMethodID(clazz, "getHolder", "()Landroid/view/SurfaceHolder;"); + + clazz = env->FindClass("android/view/SurfaceHolder"); + gGetSurface = env->GetMethodID(clazz, "getSurface", "()Landroid/view/Surface;"); +} + +static inline sp<Surface> getSurface(jobject view) { + if (!view) { + return NULL; + } + JNIEnv* env = JSC::Bindings::getJNIEnv(); + initFields(env); + jobject holder = env->CallObjectMethod(view, gGetHolder); + jobject surface = env->CallObjectMethod(holder, gGetSurface); + return sp<Surface>((Surface*) env->GetIntField(surface, gSurfaceField)); +} + +static inline SkBitmap::Config convertPixelFormat(PixelFormat format) { + switch (format) { + case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config; + case PIXEL_FORMAT_RGBA_4444: return SkBitmap::kARGB_4444_Config; + case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config; + case PIXEL_FORMAT_A_8: return SkBitmap::kA8_Config; + default: return SkBitmap::kNo_Config; + } +} + +PluginSurface::PluginSurface(PluginWidgetAndroid* widget) + : m_jSurfaceView(0) + , m_widget(widget) { + // Create our java SurfaceView. + jobject obj = widget->webViewCore()->createSurface(this); + if (obj) { + JNIEnv* env = JSC::Bindings::getJNIEnv(); + m_jSurfaceView = env->NewGlobalRef(obj); + env->DeleteLocalRef(obj); + } +} + +void PluginSurface::attach(int x, int y, int width, int height) { + if (m_jSurfaceView) { + m_widget->webViewCore()->attachSurface(m_jSurfaceView, x, y, width, + height); + } +} + +void PluginSurface::destroy() { + m_surface.clear(); + if (m_jSurfaceView) { + m_widget->webViewCore()->destroySurface(m_jSurfaceView); + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->DeleteGlobalRef(m_jSurfaceView); + m_jSurfaceView = 0; + } +} + +bool PluginSurface::lock(SkIRect* dirty, SkBitmap* bitmap) { + if (!bitmap || !Surface::isValid(m_surface)) { + return false; + } + + Region dirtyRegion; + if (dirty) { + Rect rect(dirty->fLeft, dirty->fTop, dirty->fRight, dirty->fBottom); + if (!rect.isEmpty()) { + dirtyRegion.set(rect); + } + } else { + dirtyRegion.set(Rect(0x3FFF, 0x3FFF)); + } + + Surface::SurfaceInfo info; + status_t err = m_surface->lock(&info, &dirtyRegion); + if (err < 0) { + return false; + } + + ssize_t bpr = info.s * bytesPerPixel(info.format); + bitmap->setConfig(convertPixelFormat(info.format), info.w, info.h, bpr); + if (info.w > 0 && info.h > 0) { + bitmap->setPixels(info.bits); + } else { + bitmap->setPixels(NULL); + } + + return true; +} + +void PluginSurface::unlock() { + if (!Surface::isValid(m_surface)) { + return; + } + + m_surface->unlockAndPost(); +} + +static void sendSurfaceEvent(PluginWidgetAndroid* widget, + ANPSurfaceAction action, int format = 0, int width = 0, + int height = 0) { + // format is currently not reported to the plugin. The plumbing from Java + // to C is still provided in case we add the format back to the event. + ANPEvent event; + SkANP::InitEvent(&event, kSurface_ANPEventType); + + event.data.surface.action = action; + if (action == kChanged_ANPSurfaceAction) { + event.data.surface.data.changed.width = width; + event.data.surface.data.changed.height = height; + } + + widget->sendEvent(event); +} + +// SurfaceCallback methods +void PluginSurface::surfaceCreated() { + m_surface = getSurface(m_jSurfaceView); + // Not sure what values for format, width, and height should be here. + sendSurfaceEvent(m_widget, kCreated_ANPSurfaceAction); +} + +void PluginSurface::surfaceChanged(int format, int width, int height) { + m_surface = getSurface(m_jSurfaceView); + sendSurfaceEvent(m_widget, kChanged_ANPSurfaceAction, format, width, + height); +} + +void PluginSurface::surfaceDestroyed() { + m_surface = getSurface(m_jSurfaceView); + // Not sure what values for format, width, and height should be here. + sendSurfaceEvent(m_widget, kDestroyed_ANPSurfaceAction); +} + +} // namespace android diff --git a/WebKit/android/plugins/PluginSurface.h b/WebKit/android/plugins/PluginSurface.h new file mode 100644 index 0000000..b8cbac9 --- /dev/null +++ b/WebKit/android/plugins/PluginSurface.h @@ -0,0 +1,75 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2008 Google 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 COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PluginSurface_H +#define PluginSurface_H + +#include "android_npapi.h" +#include "SkANP.h" +#include "SurfaceCallback.h" + +#include <jni.h> +#include <ui/Surface.h> +#include <utils/RefBase.h> + +struct PluginWidgetAndroid; +class SkBitmap; +struct SkIRect; + +struct ANPSurface { + void* data; + ANPSurfaceType type; +}; + +namespace android { + +class Surface; + +class PluginSurface : public SurfaceCallback { +public: + PluginSurface(PluginWidgetAndroid* widget); + virtual ~PluginSurface() { + destroy(); + } + + void attach(int x, int y, int width, int height); + void destroy(); + bool lock(SkIRect* dirty, SkBitmap* bitmap); + void unlock(); + + virtual void surfaceCreated(); + virtual void surfaceChanged(int format, int width, int height); + virtual void surfaceDestroyed(); + +private: + jobject m_jSurfaceView; + sp<Surface> m_surface; + PluginWidgetAndroid* m_widget; +}; + +} // namespace android + +#endif diff --git a/WebKit/android/plugins/PluginWidgetAndroid.cpp b/WebKit/android/plugins/PluginWidgetAndroid.cpp index ea13a0c..30a55cb 100644 --- a/WebKit/android/plugins/PluginWidgetAndroid.cpp +++ b/WebKit/android/plugins/PluginWidgetAndroid.cpp @@ -25,9 +25,14 @@ #include "config.h" #include "android_graphics.h" +#include "Document.h" +#include "Element.h" +#include "Frame.h" #include "PluginPackage.h" +#include "PluginSurface.h" #include "PluginView.h" #include "PluginWidgetAndroid.h" +#include "ScrollView.h" #include "SkANP.h" #include "SkFlipPixelRef.h" #include "WebViewCore.h" @@ -37,7 +42,11 @@ PluginWidgetAndroid::PluginWidgetAndroid(WebCore::PluginView* view) m_flipPixelRef = NULL; m_core = NULL; m_drawingModel = kBitmap_ANPDrawingModel; - m_x = m_y = 0; + m_eventFlags = 0; + m_pluginWindow = NULL; + m_requestedVisibleRectCount = 0; + m_requestedFrameRect.setEmpty(); + m_visibleDocRect.setEmpty(); } PluginWidgetAndroid::~PluginWidgetAndroid() { @@ -57,21 +66,28 @@ static SkBitmap::Config computeConfig(bool isTransparent) { : SkBitmap::kRGB_565_Config; } -void PluginWidgetAndroid::setWindow(int x, int y, int width, int height, - bool isTransparent) { - m_x = x; - m_y = y; - m_flipPixelRef->safeUnref(); - m_flipPixelRef = new SkFlipPixelRef(computeConfig(isTransparent), - width, height); +void PluginWidgetAndroid::setWindow(NPWindow* window, bool isTransparent) { + m_pluginWindow = window; + + if (m_drawingModel == kSurface_ANPDrawingModel) { + if (m_surface) { + m_surface->attach(window->x, window->y, window->width, window->height); + } + } else { + m_flipPixelRef->safeUnref(); + m_flipPixelRef = new SkFlipPixelRef(computeConfig(isTransparent), + window->width, window->height); + } } -void PluginWidgetAndroid::setDrawingModel(ANPDrawingModel model) { +bool PluginWidgetAndroid::setDrawingModel(ANPDrawingModel model) { m_drawingModel = model; + return true; } void PluginWidgetAndroid::localToPageCoords(SkIRect* rect) const { - rect->offset(m_x, m_y); + if (m_pluginWindow) + rect->offset(m_pluginWindow->x, m_pluginWindow->y); } bool PluginWidgetAndroid::isDirty(SkIRect* rect) const { @@ -93,14 +109,14 @@ bool PluginWidgetAndroid::isDirty(SkIRect* rect) const { void PluginWidgetAndroid::inval(const WebCore::IntRect& rect, bool signalRedraw) { - // nothing to do if we haven't had setWindow() called yet + // nothing to do if we haven't had setWindow() called yet. m_flipPixelRef + // will also be null if this is a Surface model. if (NULL == m_flipPixelRef) { return; } - SkIRect r; - m_flipPixelRef->inval(*android_setrect(&r, rect)); - + m_flipPixelRef->inval(rect); + if (signalRedraw && m_flipPixelRef->isDirty()) { m_core->invalPlugin(this); } @@ -110,7 +126,7 @@ void PluginWidgetAndroid::draw(SkCanvas* canvas) { if (NULL == m_flipPixelRef || !m_flipPixelRef->isDirty()) { return; } - + SkAutoFlipUpdate update(m_flipPixelRef); const SkBitmap& bitmap = update.bitmap(); const SkRegion& dirty = update.dirty(); @@ -118,23 +134,23 @@ void PluginWidgetAndroid::draw(SkCanvas* canvas) { ANPEvent event; SkANP::InitEvent(&event, kDraw_ANPEventType); - event.data.drawContext.model = m_drawingModel; - SkANP::SetRect(&event.data.drawContext.clip, dirty.getBounds()); - + event.data.draw.model = m_drawingModel; + SkANP::SetRect(&event.data.draw.clip, dirty.getBounds()); + switch (m_drawingModel) { case kBitmap_ANPDrawingModel: { WebCore::PluginPackage* pkg = m_pluginView->plugin(); NPP instance = m_pluginView->instance(); - - if (SkANP::SetBitmap(&event.data.drawContext.data.bitmap, + + if (SkANP::SetBitmap(&event.data.draw.data.bitmap, bitmap) && pkg->pluginFuncs()->event(instance, &event)) { - - if (canvas) { + + if (canvas && m_pluginWindow) { SkBitmap bm(bitmap); bm.setPixelRef(m_flipPixelRef); - canvas->drawBitmap(bm, SkIntToScalar(m_x), - SkIntToScalar(m_y), NULL); + canvas->drawBitmap(bm, SkIntToScalar(m_pluginWindow->x), + SkIntToScalar(m_pluginWindow->y), NULL); } } break; @@ -144,3 +160,152 @@ void PluginWidgetAndroid::draw(SkCanvas* canvas) { } } +bool PluginWidgetAndroid::sendEvent(const ANPEvent& evt) { + WebCore::PluginPackage* pkg = m_pluginView->plugin(); + NPP instance = m_pluginView->instance(); + // "missing" plugins won't have these + if (pkg && instance) { + // make a localCopy since the actual plugin may not respect its constness, + // and so we don't want our caller to have its param modified + ANPEvent localCopy = evt; + return pkg->pluginFuncs()->event(instance, &localCopy); + } + return false; +} + +void PluginWidgetAndroid::updateEventFlags(ANPEventFlags flags) { + + // if there are no differences then immediately return + if (m_eventFlags == flags) { + return; + } + + Document* doc = m_pluginView->getParentFrame()->document(); + if((m_eventFlags ^ flags) & kTouch_ANPEventFlag) { + if(flags & kTouch_ANPEventFlag) + doc->addTouchEventListener(m_pluginView->getElement()); + else + doc->removeTouchEventListener(m_pluginView->getElement()); + } + + m_eventFlags = flags; +} + +bool PluginWidgetAndroid::isAcceptingEvent(ANPEventFlag flag) { + return m_eventFlags & flag; +} + +ANPSurface* PluginWidgetAndroid::createSurface(ANPSurfaceType ignored) { + if (m_drawingModel != kSurface_ANPDrawingModel) { + return NULL; + } + m_surface.set(new android::PluginSurface(this)); + ANPSurface* surface = new ANPSurface; + surface->data = m_surface.get(); + surface->type = ignored; + return surface; +} + +void PluginWidgetAndroid::setVisibleScreen(const ANPRectI& visibleDocRect, float zoom) { + + //TODO send an event to the plugin that communicates the zoom + + int oldScreenW = m_visibleDocRect.width(); + int oldScreenH = m_visibleDocRect.height(); + + m_visibleDocRect.set(visibleDocRect.left, visibleDocRect.top, + visibleDocRect.right, visibleDocRect.bottom); + + int newScreenW = m_visibleDocRect.width(); + int newScreenH = m_visibleDocRect.height(); + + if (oldScreenW != newScreenW || oldScreenH != newScreenH) + computeVisibleFrameRect(); +} + +void PluginWidgetAndroid::setVisibleRects(const ANPRectI rects[], int32_t count) { + + // ensure the count does not exceed our allocated space + if (count > MAX_REQUESTED_RECTS) + count = MAX_REQUESTED_RECTS; + + // store the values in member variables + m_requestedVisibleRectCount = count; + memcpy(m_requestedVisibleRect, rects, count * sizeof(rects[0])); + + computeVisibleFrameRect(); +} + +void PluginWidgetAndroid::computeVisibleFrameRect() { + + // ensure the visibleDocRect has been set (i.e. not equal to zero) + if (m_visibleDocRect.isEmpty() || !m_pluginWindow) + return; + + // create a rect that represents the plugin's bounds + SkIRect pluginBounds; + pluginBounds.set(m_pluginWindow->x, m_pluginWindow->y, + m_pluginWindow->x + m_pluginWindow->width, + m_pluginWindow->y + m_pluginWindow->height); + + // create a rect that will contain as many of the rects that will fit on screen + SkIRect visibleRect; + visibleRect.setEmpty(); + + for (int counter = 0; counter < m_requestedVisibleRectCount; counter++) { + + ANPRectI* rect = &m_requestedVisibleRect[counter]; + + // create skia rect for easier manipulation and convert it to frame coordinates + SkIRect pluginRect; + pluginRect.set(rect->left, rect->top, rect->right, rect->bottom); + pluginRect.offset(m_pluginWindow->x, m_pluginWindow->y); + + // ensure the rect falls within the plugin's bounds + if (!pluginBounds.contains(pluginRect)) + continue; + + // combine this new rect with the higher priority rects + pluginRect.join(visibleRect); + + // check to see if the new rect fits within the screen bounds. If this + // is the highest priority rect then attempt to center even if it doesn't + // fit on the screen. + if (counter > 0 && (m_visibleDocRect.width() < pluginRect.width() || + m_visibleDocRect.height() < pluginRect.height())) + break; + + // set the new visible rect + visibleRect = pluginRect; + } + + m_requestedFrameRect = visibleRect; + scrollToVisibleFrameRect(); +} + +void PluginWidgetAndroid::scrollToVisibleFrameRect() { + + if (m_requestedFrameRect.isEmpty() || m_visibleDocRect.isEmpty()) + return; + + // TODO if the entire rect is already visible then we don't need to scroll, + // this requires converting the m_requestedFrameRect from frame to doc coordinates + + // find the center of the visibleRect in document coordinates + ScrollView* scrollView = m_pluginView->parent(); + IntPoint pluginFramePoint = IntPoint(m_requestedFrameRect.fLeft, m_requestedFrameRect.fTop); + IntPoint pluginDocPoint = scrollView->convertToContainingWindow(pluginFramePoint); + int rectCenterX = pluginDocPoint.x() + m_requestedFrameRect.width()/2; + int rectCenterY = pluginDocPoint.y() + m_requestedFrameRect.height()/2; + + // find document coordinates for center of the visible screen + int screenCenterX = m_visibleDocRect.fLeft + m_visibleDocRect.width()/2; + int screenCenterY = m_visibleDocRect.fTop + m_visibleDocRect.height()/2; + + //compute the delta of the two points + int deltaX = rectCenterX - screenCenterX; + int deltaY = rectCenterY - screenCenterY; + + android::WebViewCore* core = android::WebViewCore::getWebViewCore(scrollView); + core->scrollBy(deltaX, deltaY, true); +} diff --git a/WebKit/android/plugins/PluginWidgetAndroid.h b/WebKit/android/plugins/PluginWidgetAndroid.h index f5e9363..1da618f 100644 --- a/WebKit/android/plugins/PluginWidgetAndroid.h +++ b/WebKit/android/plugins/PluginWidgetAndroid.h @@ -27,12 +27,16 @@ #define PluginWidgetAndroid_H #include "android_npapi.h" +#include "SkRect.h" + +#include <wtf/OwnPtr.h> namespace WebCore { class PluginView; } namespace android { + class PluginSurface; class WebViewCore; } @@ -49,18 +53,26 @@ struct PluginWidgetAndroid { // destroyed. PluginWidgetAndroid(WebCore::PluginView* view); ~PluginWidgetAndroid(); - + + WebCore::PluginView* pluginView() const { return m_pluginView; } + + // Needed by PluginSurface to manage the java SurfaceView. + android::WebViewCore* webViewCore() const { return m_core; } + /* Can't determine our core at construction time, so PluginView calls this as soon as it has a parent. */ void init(android::WebViewCore*); /* Called each time the PluginView gets a new size or position. */ - void setWindow(int x, int y, int width, int height, bool isTransparent); - /* Called whenever the plugin itself requests a new drawing model + void setWindow(NPWindow* window, bool isTransparent); + + /* Called whenever the plugin itself requests a new drawing model. If the + hardware does not support the requested model then false is returned, + otherwise true is returned. */ - void setDrawingModel(ANPDrawingModel); - + bool setDrawingModel(ANPDrawingModel); + /* Utility method to convert from local (plugin) coordinates to docuemnt coordinates. Needed (for instance) to convert the dirty rectangle into document coordinates to inturn inval the screen. @@ -76,19 +88,72 @@ struct PluginWidgetAndroid { a subsequent call to draw(NULL). */ void inval(const WebCore::IntRect&, bool signalRedraw); - + /* Called to draw into the plugin's bitmap. If canvas is non-null, the bitmap itself is then drawn into the canvas. */ void draw(SkCanvas* canvas = NULL); - + + /* Send this event to the plugin instance, and return true if the plugin + handled it. + */ + bool sendEvent(const ANPEvent&); + + /* Update the plugins event flags. If a flag is set to true then the plugin + wants to be notified of events of this type. + */ + void updateEventFlags(ANPEventFlags); + + /* Called to check if a plugin wants to accept a given event type. It + returns true if the plugin wants the events and false otherwise. + */ + bool isAcceptingEvent(ANPEventFlag); + + /* Create an ANPSurface that the plugin may draw in to. The drawing model + must be kSurface_ANPDrawingModel for this call to succeed. The type + specifies what kind of pixel access will be available. + */ + ANPSurface* createSurface(ANPSurfaceType type); + + /* Notify the plugin of the currently visible screen coordinates (document + space) and the current zoom level. + */ + void setVisibleScreen(const ANPRectI& visibleScreenRect, float zoom); + + /** Registers a set of rectangles that the plugin would like to keep on + screen. The rectangles are listed in order of priority with the highest + priority rectangle in location rects[0]. The browser will attempt to keep + as many of the rectangles on screen as possible and will scroll them into + view in response to the invocation of this method and other various events. + The count specifies how many rectangles are in the array. If the count is + zero it signals the plugin that any existing rectangles should be cleared + and no rectangles will be tracked. + */ + void setVisibleRects(const ANPRectI rects[], int32_t count); + private: + void computeVisibleFrameRect(); + void scrollToVisibleFrameRect(); + WebCore::PluginView* m_pluginView; android::WebViewCore* m_core; SkFlipPixelRef* m_flipPixelRef; ANPDrawingModel m_drawingModel; - int m_x; - int m_y; + ANPEventFlags m_eventFlags; + NPWindow* m_pluginWindow; + SkIRect m_visibleDocRect; + SkIRect m_requestedFrameRect; + OwnPtr<android::PluginSurface> m_surface; + + /* We limit the number of rectangles to minimize storage and ensure adequate + speed. + */ + enum { + MAX_REQUESTED_RECTS = 5, + }; + + ANPRectI m_requestedVisibleRect[MAX_REQUESTED_RECTS]; + int32_t m_requestedVisibleRectCount; }; #endif diff --git a/WebKit/android/plugins/sample/pluginGraphics.h b/WebKit/android/plugins/SurfaceCallback.h index 4dceb26..fb2e015 100644 --- a/WebKit/android/plugins/sample/pluginGraphics.h +++ b/WebKit/android/plugins/SurfaceCallback.h @@ -1,16 +1,17 @@ /* - * Copyright 2008, The Android Open Source Project + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2008 Google 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: - * * Redistributions of source code must retain the above copyright + * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright + * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR @@ -22,19 +23,20 @@ * (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 "main.h" // for NPAPI definitions -#include "PluginObject.h" -#ifndef pluginGraphics__DEFINED -#define pluginGraphics__DEFINED +#ifndef SurfaceCallback_H +#define SurfaceCallback_H -struct ANPBitmap; -struct ANPCanvas; -struct ANPRectI; +namespace android { -void drawPlugin(NPP instance, const ANPBitmap& bitmap, const ANPRectI& clip); -void drawPlugin(NPP instance, ANPCanvas*); -uint32_t getMSecs(); + class SurfaceCallback { + public: + virtual ~SurfaceCallback() {} + virtual void surfaceCreated() = 0; + virtual void surfaceChanged(int format, int width, int height) = 0; + virtual void surfaceDestroyed() = 0; + }; -#endif // pluginGraphics__DEFINED +} // namespace android + +#endif diff --git a/WebKit/android/plugins/android_npapi.h b/WebKit/android/plugins/android_npapi.h index f64c8ce..e50f031 100644 --- a/WebKit/android/plugins/android_npapi.h +++ b/WebKit/android/plugins/android_npapi.h @@ -24,10 +24,10 @@ */ /* Defines the android-specific types and functions as part of npapi - + In particular, defines the window and event types that are passed to NPN_GetValue, NPP_SetWindow and NPP_HandleEvent. - + To minimize what native libraries the plugin links against, some functionality is provided via function-ptrs (e.g. time, sound) */ @@ -49,6 +49,17 @@ enum ANPBitmapFormats { }; typedef int32_t ANPBitmapFormat; +struct ANPPixelPacking { + uint8_t AShift; + uint8_t ABits; + uint8_t RShift; + uint8_t RBits; + uint8_t GShift; + uint8_t GBits; + uint8_t BShift; + uint8_t BBits; +}; + struct ANPBitmap { void* baseAddr; ANPBitmapFormat format; @@ -91,9 +102,9 @@ typedef uint32_t ANPMatrixFlag; // NPN_GetValue /* queries for a specific ANPInterface. - + Maybe called with NULL for the NPP instance - + NPN_GetValue(inst, interface_enum, ANPInterface*) */ #define kLogInterfaceV0_ANPGetValue ((NPNVariable)1000) @@ -101,22 +112,25 @@ typedef uint32_t ANPMatrixFlag; #define kCanvasInterfaceV0_ANPGetValue ((NPNVariable)1002) #define kMatrixInterfaceV0_ANPGetValue ((NPNVariable)1003) #define kPaintInterfaceV0_ANPGetValue ((NPNVariable)1004) -#define kTypefaceInterfaceV0_ANPGetValue ((NPNVariable)1005) -#define kWindowInterfaceV0_ANPGetValue ((NPNVariable)1006) +#define kPathInterfaceV0_ANPGetValue ((NPNVariable)1005) +#define kTypefaceInterfaceV0_ANPGetValue ((NPNVariable)1006) +#define kWindowInterfaceV0_ANPGetValue ((NPNVariable)1007) +#define kBitmapInterfaceV0_ANPGetValue ((NPNVariable)1008) +#define kSurfaceInterfaceV0_ANPGetValue ((NPNVariable)1009) /* queries for which drawing model is desired (for the draw event) - + Should be called inside NPP_New(...) - + NPN_GetValue(inst, ANPSupportedDrawingModel_EnumValue, uint32_t* bits) */ #define kSupportedDrawingModel_ANPGetValue ((NPNVariable)2000) /////////////////////////////////////////////////////////////////////////////// -// NPN_GetValue +// NPN_SetValue + +/** Request to set the drawing model. -/** Reqeust to set the drawing model. - NPN_SetValue(inst, ANPRequestDrawingModel_EnumValue, (void*)foo_DrawingModel) */ #define kRequestDrawingModel_ANPSetValue ((NPPVariable)1000) @@ -130,14 +144,33 @@ enum ANPDrawingModels { /** Draw into a bitmap from the browser thread in response to a Draw event. NPWindow->window is reserved (ignore) */ - kBitmap_ANPDrawingModel = 0, + kBitmap_ANPDrawingModel = 0, + kSurface_ANPDrawingModel = 1, }; typedef int32_t ANPDrawingModel; +/** Request to receive/disable events. If the pointer is NULL then all input will + be disabled. Otherwise, the input type will be enabled iff its corresponding + bit in the EventFlags bit field is set. + + NPN_SetValue(inst, ANPAcceptEvents, (void*)EventFlags) + */ +#define kAcceptEvents_ANPSetValue ((NPPVariable)1001) + +/* The EventFlags are a set of bits used to determine which types of input the + plugin wishes to receive. For example, if the value is 0x03 then both key + and touch events will be provided to the plugin. + */ +enum ANPEventFlag { + kKey_ANPEventFlag = 0x01, + kTouch_ANPEventFlag = 0x02, +}; +typedef uint32_t ANPEventFlags; + /* Interfaces provide additional functionality to the plugin via function ptrs. Once an interface is retrived, it is valid for the lifetime of the plugin (just like browserfuncs). - + All ANPInterfaces begin with an inSize field, which must be set by the caller (plugin) with the number of bytes allocated for the interface. e.g. SomeInterface si; si.inSize = sizeof(si); browser->getvalue(..., &si); @@ -159,6 +192,50 @@ struct ANPLogInterfaceV0 : ANPInterface { void (*log)(NPP instance, ANPLogType, const char format[], ...); }; +struct ANPBitmapInterfaceV0 : ANPInterface { + /** Returns true if the specified bitmap format is supported, and if packing + is non-null, sets it to the packing info for that format. + */ + bool (*getPixelPacking)(ANPBitmapFormat, ANPPixelPacking* packing); +}; + +/** The surfaceType is the mechanism by which the plugin informs the native + libraries which type of surface view it wishes to use. + */ +enum ANPSurfaceTypes { + kRGBA_ANPSurfaceType = 0 +}; +typedef int32_t ANPSurfaceType; + +/** The ANPSurface acts as a handle between the plugin and the native libraries + that render the surface to the screen. + */ +struct ANPSurface; + +struct ANPSurfaceInterfaceV0 : ANPInterface { + /** Creates a new surface handle based on the given surface type. If the + given surface type is not supported then NULL is returned. + */ + ANPSurface* (*newSurface)(NPP instance, ANPSurfaceType); + /** Given a valid surface handle (i.e. one created by calling newSurface) + the underlying surface is removed and the pointer is set to NULL. + */ + void (*deleteSurface)(ANPSurface* surface); + /** Locks the surface from manipulation by other threads and provides a bitmap + to be written to. The dirtyRect param specifies which portion of the + bitmap will be written to. If the dirtyRect is NULL then the entire + surface will be considered dirty. If the lock was successful the function + will return true and the bitmap will be set to point to a valid bitmap. + If not the function will return false and the bitmap will be set to NULL. + */ + bool (*lock)(ANPSurface* surface, ANPBitmap* bitmap, ANPRectI* dirtyRect); + /** Given a locked surface handle (i.e. result of a successful call to lock) + the surface is unlocked and the contents of the bitmap, specifically + those inside the dirtyRect are written to the screen. + */ + void (*unlock)(ANPSurface* surface); +}; + struct ANPMatrixInterfaceV0 : ANPInterface { /* Return a new identity matrix */ @@ -212,9 +289,70 @@ struct ANPMatrixInterfaceV0 : ANPInterface { int32_t count); }; +struct ANPPathInterfaceV0 : ANPInterface { + /* Return a new path */ + ANPPath* (*newPath)(); + + /* Delete a path previously allocated by ANPPath() */ + void (*deletePath)(ANPPath*); + + /* Make a deep copy of the src path, into the dst path (already allocated + by the caller). + */ + void (*copy)(ANPPath* dst, const ANPPath* src); + + /* Returns true if the two paths are the same (i.e. have the same points) + */ + bool (*equal)(const ANPPath* path0, const ANPPath* path1); + + /* Remove any previous points, initializing the path back to empty. */ + void (*reset)(ANPPath*); + + /* Return true if the path is empty (has no lines, quads or cubics). */ + bool (*isEmpty)(const ANPPath*); + + /* Return the path's bounds in bounds. */ + void (*getBounds)(const ANPPath*, ANPRectF* bounds); + + void (*moveTo)(ANPPath*, float x, float y); + void (*lineTo)(ANPPath*, float x, float y); + void (*quadTo)(ANPPath*, float x0, float y0, float x1, float y1); + void (*cubicTo)(ANPPath*, float x0, float y0, float x1, float y1, + float x2, float y2); + void (*close)(ANPPath*); + + /* Offset the src path by [dx, dy]. If dst is null, apply the + change directly to the src path. If dst is not null, write the + changed path into dst, and leave the src path unchanged. In that case + dst must have been previously allocated by the caller. + */ + void (*offset)(ANPPath* src, float dx, float dy, ANPPath* dst); + + /* Transform the path by the matrix. If dst is null, apply the + change directly to the src path. If dst is not null, write the + changed path into dst, and leave the src path unchanged. In that case + dst must have been previously allocated by the caller. + */ + void (*transform)(ANPPath* src, const ANPMatrix*, ANPPath* dst); +}; + +/** ANPColor is always defined to have the same packing on all platforms, and + it is always unpremultiplied. + + This is in contrast to 32bit format(s) in bitmaps, which are premultiplied, + and their packing may vary depending on the platform, hence the need for + ANPBitmapInterface::getPixelPacking() + */ typedef uint32_t ANPColor; +#define ANPColor_ASHIFT 24 +#define ANPColor_RSHIFT 16 +#define ANPColor_GSHIFT 8 +#define ANPColor_BSHIFT 0 #define ANP_MAKE_COLOR(a, r, g, b) \ - (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) + (((a) << ANPColor_ASHIFT) | \ + ((r) << ANPColor_RSHIFT) | \ + ((g) << ANPColor_GSHIFT) | \ + ((b) << ANPColor_BSHIFT)) enum ANPPaintFlag { kAntiAlias_ANPPaintFlag = 1 << 0, @@ -266,6 +404,8 @@ enum ANPTypefaceStyles { }; typedef uint32_t ANPTypefaceStyle; +typedef uint32_t ANPFontTableTag; + struct ANPFontMetrics { //! The greatest distance above the baseline for any glyph (will be <= 0) float fTop; @@ -303,7 +443,7 @@ struct ANPTypefaceInterfaceV0 : ANPInterface { */ ANPTypeface* (*createFromTypeface)(const ANPTypeface* family, ANPTypefaceStyle); - + /** Return the owner count of the typeface. A newly created typeface has an owner count of 1. When the owner count is reaches 0, the typeface is deleted. @@ -318,29 +458,33 @@ struct ANPTypefaceInterfaceV0 : ANPInterface { the typeface is deleted. */ void (*unref)(ANPTypeface*); - + /** Return the style bits for the specified typeface */ ANPTypefaceStyle (*getStyle)(const ANPTypeface*); + + /** Return the path name for the font directory, or NULL if not supported + */ + const char* (*getFontDirectoryPath)(); }; struct ANPPaintInterfaceV0 : ANPInterface { /* Return a new paint object, which holds all of the color and style attributes that affect how things (geometry, text, bitmaps) are drawn in a ANPCanvas. - + The paint that is returned is not tied to any particular plugin instance, but it must only be accessed from one thread at a time. */ ANPPaint* (*newPaint)(); void (*deletePaint)(ANPPaint*); - + ANPPaintFlags (*getFlags)(const ANPPaint*); void (*setFlags)(ANPPaint*, ANPPaintFlags); - + ANPColor (*getColor)(const ANPPaint*); void (*setColor)(ANPPaint*, ANPColor); - + ANPPaintStyle (*getStyle)(const ANPPaint*); void (*setStyle)(ANPPaint*, ANPPaintStyle); @@ -352,7 +496,7 @@ struct ANPPaintInterfaceV0 : ANPInterface { void (*setStrokeMiter)(ANPPaint*, float); void (*setStrokeCap)(ANPPaint*, ANPPaintCap); void (*setStrokeJoin)(ANPPaint*, ANPPaintJoin); - + ANPTextEncoding (*getTextEncoding)(const ANPPaint*); ANPPaintAlign (*getTextAlign)(const ANPPaint*); float (*getTextSize)(const ANPPaint*); @@ -380,7 +524,7 @@ struct ANPPaintInterfaceV0 : ANPInterface { */ float (*measureText)(ANPPaint*, const void* text, uint32_t byteLength, ANPRectF* bounds); - + /** Return the number of unichars specifed by the text. If widths is not null, returns the array of advance widths for each unichar. @@ -388,7 +532,7 @@ struct ANPPaintInterfaceV0 : ANPInterface { */ int (*getTextWidths)(ANPPaint*, const void* text, uint32_t byteLength, float widths[], ANPRectF bounds[]); - + /** Return in metrics the spacing values for text, respecting the paint's typeface and pointsize, and return the spacing between lines (descent - ascent + leading). If metrics is NULL, it will be ignored. @@ -404,7 +548,7 @@ struct ANPCanvasInterfaceV0 : ANPInterface { goes out of scope. In the case of creating a canvas to draw into the pixels provided by kDraw_ANPEventType, those pixels are only while handling that event. - + The canvas that is returned is not tied to any particular plugin instance, but it must only be accessed from one thread at a time. */ @@ -433,9 +577,11 @@ struct ANPCanvasInterfaceV0 : ANPInterface { current clip is empty, return false and ignore the bounds argument. */ bool (*getDeviceClipBounds)(ANPCanvas*, ANPRectI* bounds); - + void (*drawColor)(ANPCanvas*, ANPColor); void (*drawPaint)(ANPCanvas*, const ANPPaint*); + void (*drawLine)(ANPCanvas*, float x0, float y0, float x1, float y1, + const ANPPaint*); void (*drawRect)(ANPCanvas*, const ANPRectF*, const ANPPaint*); void (*drawOval)(ANPCanvas*, const ANPRectF*, const ANPPaint*); void (*drawPath)(ANPCanvas*, const ANPPath*, const ANPPaint*); @@ -455,7 +601,7 @@ struct ANPWindowInterfaceV0 : ANPInterface { describing the subset of the window that will be drawn to (may be null) return true if the bitmap for that window can be accessed, and if so, fill out the specified ANPBitmap to point to the window's pixels. - + When drawing is complete, call unlock(window) */ bool (*lockRect)(void* window, const ANPRectI* inval, ANPBitmap*); @@ -468,6 +614,26 @@ struct ANPWindowInterfaceV0 : ANPInterface { results. If lock returned false, unlock should not be called. */ void (*unlock)(void* window); + /** Registers a set of rectangles that the plugin would like to keep on + screen. The rectangles are listed in order of priority with the highest + priority rectangle in location rects[0]. The browser will attempt to keep + as many of the rectangles on screen as possible and will scroll them into + view in response to the invocation of this method and other various events. + The count specifies how many rectangles are in the array. If the count is + zero it signals the browser that any existing rectangles should be cleared + and no rectangles will be tracked. + */ + void (*setVisibleRects)(NPP instance, const ANPRectI rects[], int32_t count); + /** Clears any rectangles that are being tracked as a result of a call to + setVisibleRects. This call is equivalent to setVisibleRect(inst, NULL, 0). + */ + void (*clearVisibleRects)(NPP instance); + /** Given a boolean value of true the device will be requested to provide + a keyboard. A value of false will result in a request to hide the + keyboard. Further, the on-screen keyboard will not be displayed if a + physical keyboard is active. + */ + void (*showKeyboard)(NPP instance, bool value); }; /////////////////////////////////////////////////////////////////////////////// @@ -517,11 +683,11 @@ typedef int32_t ANPAudioEvent; /** Called to feed sample data to the track. This will be called in a separate thread. However, you may call trackStop() from the callback (but you cannot delete the track). - + For example, when you have written the last chunk of sample data, you can immediately call trackStop(). This will take effect after the current buffer has been played. - + The "user" parameter is the same value that was passed to newTrack() */ typedef void (*ANPAudioCallbackProc)(ANPAudioEvent event, void* user, @@ -552,10 +718,13 @@ struct ANPAudioTrackInterfaceV0 : ANPInterface { // HandleEvent enum ANPEventTypes { - kNull_ANPEventType = 0, - kKey_ANPEventType = 1, - kTouch_ANPEventType = 2, - kDraw_ANPEventType = 3, + kNull_ANPEventType = 0, + kKey_ANPEventType = 1, + kMouse_ANPEventType = 2, + kTouch_ANPEventType = 3, + kDraw_ANPEventType = 4, + kLifecycle_ANPEventType = 5, + kSurface_ANPEventType = 6, }; typedef int32_t ANPEventType; @@ -575,21 +744,45 @@ enum ANPKeyModifiers { // bit-field containing some number of ANPKeyModifier bits typedef uint32_t ANPKeyModifier; +enum ANPMouseActions { + kDown_ANPMouseAction = 0, + kUp_ANPMouseAction = 1, +}; +typedef int32_t ANPMouseAction; + enum ANPTouchActions { - kDown_ANPTouchAction = 0, - kUp_ANPTouchAction = 1, + kDown_ANPTouchAction = 0, + kUp_ANPTouchAction = 1, + kMove_ANPTouchAction = 2, + kCancel_ANPTouchAction = 3, }; typedef int32_t ANPTouchAction; -struct ANPDrawContext { - ANPDrawingModel model; - // relative to (0,0) in top-left of your plugin - ANPRectI clip; - // use based on the value in model - union { - ANPBitmap bitmap; - } data; +enum ANPLifecycleActions { + kPause_ANPLifecycleAction = 0, + kResume_ANPLifecycleAction = 1, + kGainFocus_ANPLifecycleAction = 2, + kLoseFocus_ANPLifecycleAction = 3, + kFreeMemory_ANPLifecycleAction = 4, +}; +typedef uint32_t ANPLifecycleAction; + +enum ANPSurfaceActions { + /** The surface has been created and is ready to be used. Any calls to + lock/unlock before this action will fail. + */ + kCreated_ANPSurfaceAction = 0, + /** The surface's dimension has changed. + */ + kChanged_ANPSurfaceAction = 1, + /** The surface has been destroyed. This happens when the view system has + remove the surface (possibly due to the plugin being offscreen). Calls + to lock/unlock will fail after this action and before + kCreate_ANPSurfaceAction. + */ + kDestroyed_ANPSurfaceAction = 2, }; +typedef uint32_t ANPSurfaceAction; /* This is what is passed to NPP_HandleEvent() */ struct ANPEvent { @@ -606,12 +799,44 @@ struct ANPEvent { int32_t unichar; // 0 if there is no value } key; struct { + ANPMouseAction action; + int32_t x; // relative to your "window" (0...width) + int32_t y; // relative to your "window" (0...height) + } mouse; + struct { ANPTouchAction action; ANPKeyModifier modifiers; int32_t x; // relative to your "window" (0...width) int32_t y; // relative to your "window" (0...height) } touch; - ANPDrawContext drawContext; + struct { + ANPLifecycleAction action; + } lifecycle; + struct { + ANPDrawingModel model; + // relative to (0,0) in top-left of your plugin + ANPRectI clip; + // use based on the value in model + union { + ANPBitmap bitmap; + } data; + } draw; + struct { + ANPSurfaceAction action; + /** This union is based on the value of action and contains data + specific to the given action. + */ + union { + /** This struct is filled in only during the + kChanged_ANPSurfaceAction action. For all other actions, + this struct is undefined. + */ + struct { + int32_t width; + int32_t height; + } changed; + } data; + } surface; int32_t other[8]; } data; }; diff --git a/WebKit/android/plugins/sample/Android.mk b/WebKit/android/plugins/sample/Android.mk deleted file mode 100644 index 328ddc5..0000000 --- a/WebKit/android/plugins/sample/Android.mk +++ /dev/null @@ -1,50 +0,0 @@ -## -## -## Copyright 2008, The Android Open Source Project -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted provided that the following conditions -## are met: -## * Redistributions of source code must retain the above copyright -## notice, this list of conditions and the following disclaimer. -## * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR -## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -## - -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - main.cpp \ - PluginObject.cpp \ - pluginGraphics.cpp - -LOCAL_C_INCLUDES += \ - $(LOCAL_PATH) \ - external/webkit/WebCore/bridge \ - external/webkit/WebCore/plugins \ - external/webkit/WebCore/platform/android/JavaVM \ - external/webkit/WebKit/android/plugins - -LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) -LOCAL_CFLAGS += -fvisibility=hidden -LOCAL_PRELINK_MODULE:=false -LOCAL_MODULE_CLASS := SHARED_LIBRARIES - -LOCAL_MODULE:= browsertestplugin - -include $(BUILD_SHARED_LIBRARY) - diff --git a/WebKit/android/plugins/sample/PluginObject.cpp b/WebKit/android/plugins/sample/PluginObject.cpp deleted file mode 100644 index 5499072..0000000 --- a/WebKit/android/plugins/sample/PluginObject.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in - consideration of your agreement to the following terms, and your use, installation, - modification or redistribution of this Apple software constitutes acceptance of these - terms. If you do not agree with these terms, please do not use, install, modify or - redistribute this Apple software. - - In consideration of your agreement to abide by the following terms, and subject to these - terms, Apple grants you a personal, non-exclusive license, under AppleÕs copyrights in - this original Apple software (the "Apple Software"), to use, reproduce, modify and - redistribute the Apple Software, with or without modifications, in source and/or binary - forms; provided that if you redistribute the Apple Software in its entirety and without - modifications, you must retain this notice and the following text and disclaimers in all - such redistributions of the Apple Software. Neither the name, trademarks, service marks - or logos of Apple Computer, Inc. may be used to endorse or promote products derived from - the Apple Software without specific prior written permission from Apple. Except as expressly - stated in this notice, no other rights or licenses, express or implied, are granted by Apple - herein, including but not limited to any patent rights that may be infringed by your - derivative works or by other works in which the Apple Software may be incorporated. - - The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, - EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS - USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. - - IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, - REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND - WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR - OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stdlib.h> -#include "main.h" -#include "PluginObject.h" - -static void pluginInvalidate(NPObject *obj); -static bool pluginHasProperty(NPObject *obj, NPIdentifier name); -static bool pluginHasMethod(NPObject *obj, NPIdentifier name); -static bool pluginGetProperty(NPObject *obj, NPIdentifier name, NPVariant *variant); -static bool pluginSetProperty(NPObject *obj, NPIdentifier name, const NPVariant *variant); -static bool pluginInvoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result); -static bool pluginInvokeDefault(NPObject *obj, const NPVariant *args, uint32_t argCount, NPVariant *result); -static NPObject *pluginAllocate(NPP npp, NPClass *theClass); -static void pluginDeallocate(NPObject *obj); -static bool pluginRemoveProperty(NPObject *npobj, NPIdentifier name); -static bool pluginEnumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count); - - - -static NPClass pluginClass = { - NP_CLASS_STRUCT_VERSION, - pluginAllocate, - pluginDeallocate, - pluginInvalidate, - pluginHasMethod, - pluginInvoke, - pluginInvokeDefault, - pluginHasProperty, - pluginGetProperty, - pluginSetProperty, - pluginRemoveProperty, - pluginEnumerate -}; - -NPClass *getPluginClass(void) -{ - return &pluginClass; -} - -static bool identifiersInitialized = false; - -#define ID_TESTFILE_PROPERTY 0 -#define NUM_PROPERTY_IDENTIFIERS 1 - -static NPIdentifier pluginPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS]; -static const NPUTF8 *pluginPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = { - "testfile" -}; - -#define ID_GETTESTFILE_METHOD 0 -#define NUM_METHOD_IDENTIFIERS 1 - -static NPIdentifier pluginMethodIdentifiers[NUM_METHOD_IDENTIFIERS]; -static const NPUTF8 *pluginMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = { - "getTestFile" -}; - -static void initializeIdentifiers(void) -{ - browser->getstringidentifiers(pluginPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, pluginPropertyIdentifiers); - browser->getstringidentifiers(pluginMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, pluginMethodIdentifiers); -} - -static bool pluginHasProperty(NPObject *obj, NPIdentifier name) -{ - int i; - for (i = 0; i < NUM_PROPERTY_IDENTIFIERS; i++) - if (name == pluginPropertyIdentifiers[i]) - return true; - return false; -} - -static bool pluginHasMethod(NPObject *obj, NPIdentifier name) -{ - int i; - for (i = 0; i < NUM_METHOD_IDENTIFIERS; i++) - if (name == pluginMethodIdentifiers[i]) - return true; - return false; -} - -static bool pluginGetProperty(NPObject *obj, NPIdentifier name, NPVariant *variant) -{ - PluginObject *plugin = (PluginObject *)obj; - if (name == pluginPropertyIdentifiers[ID_TESTFILE_PROPERTY]) { - BOOLEAN_TO_NPVARIANT(true, *variant); - return true; - } - return false; -} - -static bool pluginSetProperty(NPObject *obj, NPIdentifier name, const NPVariant *variant) -{ - return false; -} - -static bool pluginInvoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result) -{ - PluginObject *plugin = (PluginObject *)obj; - if (name == pluginMethodIdentifiers[ID_GETTESTFILE_METHOD]) { - return true; - } - return false; -} - -static bool pluginInvokeDefault(NPObject *obj, const NPVariant *args, uint32_t argCount, NPVariant *result) -{ - return false; -} - -static void pluginInvalidate(NPObject *obj) -{ - // Release any remaining references to JavaScript objects. -} - -static NPObject *pluginAllocate(NPP npp, NPClass *theClass) -{ - PluginObject *newInstance = (PluginObject*) malloc(sizeof(PluginObject)); - newInstance->header._class = theClass; - newInstance->header.referenceCount = 1; - - if (!identifiersInitialized) { - identifiersInitialized = true; - initializeIdentifiers(); - } - - newInstance->npp = npp; - - return &newInstance->header; -} - -static void pluginDeallocate(NPObject *obj) -{ - free(obj); -} - -static bool pluginRemoveProperty(NPObject *npobj, NPIdentifier name) -{ - return false; -} - -static bool pluginEnumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count) -{ - return false; -} - diff --git a/WebKit/android/plugins/sample/PluginObject.h b/WebKit/android/plugins/sample/PluginObject.h deleted file mode 100644 index ae8963d..0000000 --- a/WebKit/android/plugins/sample/PluginObject.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in - consideration of your agreement to the following terms, and your use, installation, - modification or redistribution of this Apple software constitutes acceptance of these - terms. If you do not agree with these terms, please do not use, install, modify or - redistribute this Apple software. - - In consideration of your agreement to abide by the following terms, and subject to these - terms, Apple grants you a personal, non-exclusive license, under AppleÕs copyrights in - this original Apple software (the "Apple Software"), to use, reproduce, modify and - redistribute the Apple Software, with or without modifications, in source and/or binary - forms; provided that if you redistribute the Apple Software in its entirety and without - modifications, you must retain this notice and the following text and disclaimers in all - such redistributions of the Apple Software. Neither the name, trademarks, service marks - or logos of Apple Computer, Inc. may be used to endorse or promote products derived from - the Apple Software without specific prior written permission from Apple. Except as expressly - stated in this notice, no other rights or licenses, express or implied, are granted by Apple - herein, including but not limited to any patent rights that may be infringed by your - derivative works or by other works in which the Apple Software may be incorporated. - - The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, - EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS - USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. - - IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, - REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND - WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR - OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef PluginObject__DEFINED -#define PluginObject__DEFINED - -#include "npapi.h" - -struct ANPCanvas; -struct ANPAudioTrack; - -class Animation { -public: - Animation(NPP inst) : m_inst(inst) {} - virtual ~Animation() {} - virtual void draw(ANPCanvas*) = 0; - - NPP inst() const { return m_inst; } - -private: - NPP m_inst; -}; - -typedef struct PluginObject { - NPObject header; - NPP npp; - NPWindow* window; - Animation* anim; - ANPAudioTrack* track; - int32_t mUnichar; - - bool mTestTimers; - uint32_t mStartTime; - uint32_t mPrevTime; - int mTimerCount; -} PluginObject; - -NPClass *getPluginClass(void); - -#endif // PluginObject__DEFINED diff --git a/WebKit/android/plugins/sample/main.cpp b/WebKit/android/plugins/sample/main.cpp deleted file mode 100644 index e34cee6..0000000 --- a/WebKit/android/plugins/sample/main.cpp +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include "main.h" -#include "PluginObject.h" -#include "pluginGraphics.h" -#include "android_npapi.h" - -NPNetscapeFuncs* browser; -#define EXPORT __attribute__((visibility("default"))) - -NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, - char* argn[], char* argv[], NPSavedData* saved); -NPError NPP_Destroy(NPP instance, NPSavedData** save); -NPError NPP_SetWindow(NPP instance, NPWindow* window); -NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, - NPBool seekable, uint16* stype); -NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason); -int32 NPP_WriteReady(NPP instance, NPStream* stream); -int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, - void* buffer); -void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname); -void NPP_Print(NPP instance, NPPrint* platformPrint); -int16 NPP_HandleEvent(NPP instance, void* event); -void NPP_URLNotify(NPP instance, const char* URL, NPReason reason, - void* notifyData); -NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value); -NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value); - -extern "C" { -EXPORT NPError NP_Initialize(NPNetscapeFuncs* browserFuncs, NPPluginFuncs* pluginFuncs, void *java_env, void *application_context); -EXPORT NPError NP_GetValue(NPP instance, NPPVariable variable, void *value); -EXPORT const char* NP_GetMIMEDescription(void); -EXPORT void NP_Shutdown(void); -}; - -ANPAudioTrackInterfaceV0 gSoundI; -ANPCanvasInterfaceV0 gCanvasI; -ANPLogInterfaceV0 gLogI; -ANPPaintInterfaceV0 gPaintI; -ANPTypefaceInterfaceV0 gTypefaceI; - -#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0])) - -NPError NP_Initialize(NPNetscapeFuncs* browserFuncs, NPPluginFuncs* pluginFuncs, void *java_env, void *application_context) -{ - // Make sure we have a function table equal or larger than we are built against. - if (browserFuncs->size < sizeof(NPNetscapeFuncs)) { - return NPERR_GENERIC_ERROR; - } - - // Copy the function table (structure) - browser = (NPNetscapeFuncs*) malloc(sizeof(NPNetscapeFuncs)); - memcpy(browser, browserFuncs, sizeof(NPNetscapeFuncs)); - - // Build the plugin function table - pluginFuncs->version = 11; - pluginFuncs->size = sizeof(pluginFuncs); - pluginFuncs->newp = NPP_New; - pluginFuncs->destroy = NPP_Destroy; - pluginFuncs->setwindow = NPP_SetWindow; - pluginFuncs->newstream = NPP_NewStream; - pluginFuncs->destroystream = NPP_DestroyStream; - pluginFuncs->asfile = NPP_StreamAsFile; - pluginFuncs->writeready = NPP_WriteReady; - pluginFuncs->write = (NPP_WriteProcPtr)NPP_Write; - pluginFuncs->print = NPP_Print; - pluginFuncs->event = NPP_HandleEvent; - pluginFuncs->urlnotify = NPP_URLNotify; - pluginFuncs->getvalue = NPP_GetValue; - pluginFuncs->setvalue = NPP_SetValue; - - static const struct { - NPNVariable v; - uint32_t size; - ANPInterface* i; - } gPairs[] = { - { kLogInterfaceV0_ANPGetValue, sizeof(gLogI), &gLogI }, - { kCanvasInterfaceV0_ANPGetValue, sizeof(gCanvasI), &gCanvasI }, - { kPaintInterfaceV0_ANPGetValue, sizeof(gPaintI), &gPaintI }, - { kTypefaceInterfaceV0_ANPGetValue, sizeof(gPaintI), &gTypefaceI }, - { kAudioTrackInterfaceV0_ANPGetValue, sizeof(gSoundI), &gSoundI }, - }; - for (size_t i = 0; i < ARRAY_COUNT(gPairs); i++) { - gPairs[i].i->inSize = gPairs[i].size; - NPError err = browser->getvalue(NULL, gPairs[i].v, gPairs[i].i); - if (err) { - return err; - } - } - - return NPERR_NO_ERROR; -} - -void NP_Shutdown(void) -{ - -} - -const char *NP_GetMIMEDescription(void) -{ - return "application/x-testplugin:tst:Test plugin mimetype is application/x-testplugin"; -} - -NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, - char* argn[], char* argv[], NPSavedData* saved) -{ - PluginObject *obj = NULL; - - // Scripting functions appeared in NPAPI version 14 - if (browser->version >= 14) { - instance->pdata = browser->createobject (instance, getPluginClass()); - obj = static_cast<PluginObject*>(instance->pdata); - bzero(obj, sizeof(*obj)); - } - - uint32_t bits; - NPError err = browser->getvalue(instance, kSupportedDrawingModel_ANPGetValue, &bits); - if (err) { - gLogI.log(instance, kError_ANPLogType, "supported model err %d", err); - return err; - } - - ANPDrawingModel model = kBitmap_ANPDrawingModel; - - int count = argc; - for (int i = 0; i < count; i++) { - if (!strcmp(argn[i], "DrawingModel")) { - if (!strcmp(argv[i], "Bitmap")) { - model = kBitmap_ANPDrawingModel; - } - if (!strcmp(argv[i], "Canvas")) { - // obj->mTestTimers = true; - } - gLogI.log(instance, kDebug_ANPLogType, "------ %p DrawingModel is %d", instance, model); - break; - } - } - - // comment this out to draw via bitmaps (the default) - err = browser->setvalue(instance, kRequestDrawingModel_ANPSetValue, - reinterpret_cast<void*>(model)); - if (err) { - gLogI.log(instance, kError_ANPLogType, "request model %d err %d", model, err); - } - return err; -} - -NPError NPP_Destroy(NPP instance, NPSavedData** save) -{ - PluginObject *obj = (PluginObject*) instance->pdata; - delete obj->anim; - gSoundI.deleteTrack(obj->track); - - return NPERR_NO_ERROR; -} - -static void timer_oneshot(NPP instance, uint32 timerID) { - gLogI.log(instance, kDebug_ANPLogType, "-------- oneshot timer\n"); -} - -static int gTimerRepeatCount; -static void timer_repeat(NPP instance, uint32 timerID) { - - gLogI.log(instance, kDebug_ANPLogType, "-------- repeat timer %d\n", - gTimerRepeatCount); - if (--gTimerRepeatCount == 0) { - browser->unscheduletimer(instance, timerID); - } -} - -static void timer_neverfires(NPP instance, uint32 timerID) { - gLogI.log(instance, kError_ANPLogType, "-------- timer_neverfires!!!\n"); -} - -#define TIMER_INTERVAL 50 - -static void timer_latency(NPP instance, uint32 timerID) { - PluginObject *obj = (PluginObject*) instance->pdata; - - obj->mTimerCount += 1; - - uint32_t now = getMSecs(); - uint32_t interval = now - obj->mPrevTime; - - uint32_t dur = now - obj->mStartTime; - uint32_t expectedDur = obj->mTimerCount * TIMER_INTERVAL; - int32_t drift = dur - expectedDur; - int32_t aveDrift = drift / obj->mTimerCount; - - obj->mPrevTime = now; - - gLogI.log(instance, kDebug_ANPLogType, - "-------- latency test: [%3d] interval %d expected %d, total %d expected %d, drift %d ave %d\n", - obj->mTimerCount, interval, TIMER_INTERVAL, dur, expectedDur, - drift, aveDrift); -} - -NPError NPP_SetWindow(NPP instance, NPWindow* window) -{ - PluginObject *obj = (PluginObject*) instance->pdata; - - // Do nothing if browser didn't support NPN_CreateObject which would have created the PluginObject. - if (obj != NULL) { - obj->window = window; - } - - static bool gTestTimers; - if (!gTestTimers) { - gTestTimers = true; - // test for bogus timerID - browser->unscheduletimer(instance, 999999); - // test oneshot - browser->scheduletimer(instance, 100, false, timer_oneshot); - // test repeat - gTimerRepeatCount = 10; - browser->scheduletimer(instance, 50, true, timer_repeat); - // test unschedule immediately - uint32 id = browser->scheduletimer(instance, 100, false, timer_neverfires); - browser->unscheduletimer(instance, id); - // test double unschedlue (should be no-op) - browser->unscheduletimer(instance, id); - } - - if (obj->mTestTimers) { - browser->scheduletimer(instance, TIMER_INTERVAL, true, timer_latency); - obj->mStartTime = obj->mPrevTime = getMSecs(); - obj->mTestTimers = false; - } - - browser->invalidaterect(instance, NULL); - - return NPERR_NO_ERROR; -} - - -NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype) -{ - *stype = NP_ASFILEONLY; - return NPERR_NO_ERROR; -} - -NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) -{ - return NPERR_NO_ERROR; -} - -int32 NPP_WriteReady(NPP instance, NPStream* stream) -{ - return 0; -} - -int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer) -{ - return 0; -} - -void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) -{ -} - -void NPP_Print(NPP instance, NPPrint* platformPrint) -{ - -} - -struct SoundPlay { - NPP instance; - ANPAudioTrack* track; - FILE* file; -}; - -static void audioCallback(ANPAudioEvent evt, void* user, ANPAudioBuffer* buffer) { - switch (evt) { - case kMoreData_ANPAudioEvent: { - SoundPlay* play = reinterpret_cast<SoundPlay*>(user); - size_t amount = fread(buffer->bufferData, 1, buffer->size, play->file); - buffer->size = amount; - if (amount == 0) { - gSoundI.stop(play->track); - fclose(play->file); - play->file = NULL; - // need to notify our main thread to delete the track now - } - break; - } - default: - break; - } -} - -static ANPAudioTrack* createTrack(NPP instance, const char path[]) { - FILE* f = fopen(path, "r"); - gLogI.log(instance, kWarning_ANPLogType, "--- path %s FILE %p", path, f); - if (NULL == f) { - return NULL; - } - SoundPlay* play = new SoundPlay; - play->file = f; - play->track = gSoundI.newTrack(44100, kPCM16Bit_ANPSampleFormat, 2, audioCallback, play); - if (NULL == play->track) { - fclose(f); - delete play; - return NULL; - } - return play->track; -} - -int16 NPP_HandleEvent(NPP instance, void* event) -{ - PluginObject *obj = reinterpret_cast<PluginObject*>(instance->pdata); - const ANPEvent* evt = reinterpret_cast<const ANPEvent*>(event); - - switch (evt->eventType) { - case kDraw_ANPEventType: - switch (evt->data.drawContext.model) { - case kBitmap_ANPDrawingModel: - drawPlugin(instance, evt->data.drawContext.data.bitmap, - evt->data.drawContext.clip); - return 1; - default: - break; // unknown drawing model - } - - case kKey_ANPEventType: - gLogI.log(instance, kDebug_ANPLogType, "---- %p Key action=%d" - " code=%d vcode=%d unichar=%d repeat=%d mods=%x", instance, - evt->data.key.action, - evt->data.key.nativeCode, - evt->data.key.virtualCode, - evt->data.key.unichar, - evt->data.key.repeatCount, - evt->data.key.modifiers); - if (evt->data.key.action == kDown_ANPKeyAction) { - obj->mUnichar = evt->data.key.unichar; - browser->invalidaterect(instance, NULL); - } - return 1; - - case kTouch_ANPEventType: - gLogI.log(instance, kDebug_ANPLogType, "---- %p Touch action=%d [%d %d]", - instance, evt->data.touch.action, evt->data.touch.x, - evt->data.touch.y); - if (kUp_ANPTouchAction == evt->data.touch.action) { - if (obj->track) { - if (gSoundI.isStopped(obj->track)) { - gSoundI.start(obj->track); - } else { - gSoundI.pause(obj->track); - } - } else { - obj->track = createTrack(instance, "/sdcard/sample.snd"); - gLogI.log(instance, kDebug_ANPLogType, "track %p %d", - obj->track, gSoundI.isStopped(obj->track)); - gSoundI.start(obj->track); - gLogI.log(instance, kDebug_ANPLogType, "track %p %d", - obj->track, gSoundI.isStopped(obj->track)); - } - } - return 1; - - default: - break; - } - return 0; // unknown or unhandled event -} - -void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData) -{ - -} - -EXPORT NPError NP_GetValue(NPP instance, NPPVariable variable, void *value) { - - if (variable == NPPVpluginNameString) { - const char **str = (const char **)value; - *str = "Test Plugin"; - return NPERR_NO_ERROR; - } - - if (variable == NPPVpluginDescriptionString) { - const char **str = (const char **)value; - *str = "Description of Test Plugin"; - return NPERR_NO_ERROR; - } - - return NPERR_GENERIC_ERROR; -} - -NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) -{ - if (variable == NPPVpluginScriptableNPObject) { - void **v = (void **)value; - PluginObject *obj = (PluginObject*) instance->pdata; - - if (obj) - browser->retainobject((NPObject*)obj); - - *v = obj; - return NPERR_NO_ERROR; - } - - return NPERR_GENERIC_ERROR; -} - -NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) -{ - return NPERR_GENERIC_ERROR; -} - diff --git a/WebKit/android/plugins/sample/pluginGraphics.cpp b/WebKit/android/plugins/sample/pluginGraphics.cpp deleted file mode 100644 index ffa43e5..0000000 --- a/WebKit/android/plugins/sample/pluginGraphics.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "pluginGraphics.h" - -#include "android_npapi.h" -#include <stdio.h> -#include <sys/time.h> -#include <time.h> -#include <math.h> -#include <string.h> - -extern NPNetscapeFuncs* browser; -extern ANPLogInterfaceV0 gLogI; -extern ANPCanvasInterfaceV0 gCanvasI; -extern ANPPaintInterfaceV0 gPaintI; -extern ANPTypefaceInterfaceV0 gTypefaceI; - -static void inval(NPP instance) { - browser->invalidaterect(instance, NULL); -} - -static uint16 rnd16(float x, int inset) { - int ix = (int)roundf(x) + inset; - if (ix < 0) { - ix = 0; - } - return static_cast<uint16>(ix); -} - -static void inval(NPP instance, const ANPRectF& r, bool doAA) { - const int inset = doAA ? -1 : 0; - - PluginObject *obj = reinterpret_cast<PluginObject*>(instance->pdata); - NPRect inval; - inval.left = rnd16(r.left, inset); - inval.top = rnd16(r.top, inset); - inval.right = rnd16(r.right, -inset); - inval.bottom = rnd16(r.bottom, -inset); - browser->invalidaterect(instance, &inval); -} - -uint32_t getMSecs() { - struct timeval tv; - gettimeofday(&tv, NULL); - return (uint32_t) (tv.tv_sec * 1000 + tv.tv_usec / 1000 ); // microseconds to milliseconds -} - -/////////////////////////////////////////////////////////////////////////////// - -class BallAnimation : public Animation { -public: - BallAnimation(NPP inst); - virtual ~BallAnimation(); - virtual void draw(ANPCanvas*); -private: - float m_x; - float m_y; - float m_dx; - float m_dy; - - ANPRectF m_oval; - ANPPaint* m_paint; - - static const float SCALE = 0.1; -}; - -BallAnimation::BallAnimation(NPP inst) : Animation(inst) { - m_x = m_y = 0; - m_dx = 7 * SCALE; - m_dy = 5 * SCALE; - - memset(&m_oval, 0, sizeof(m_oval)); - - m_paint = gPaintI.newPaint(); - gPaintI.setFlags(m_paint, gPaintI.getFlags(m_paint) | kAntiAlias_ANPPaintFlag); - gPaintI.setColor(m_paint, 0xFFFF0000); - gPaintI.setTextSize(m_paint, 24); - - ANPTypeface* tf = gTypefaceI.createFromName("serif", kItalic_ANPTypefaceStyle); - gPaintI.setTypeface(m_paint, tf); - gTypefaceI.unref(tf); -} - -BallAnimation::~BallAnimation() { - gPaintI.deletePaint(m_paint); -} - -static void bounce(float* x, float* dx, const float max) { - *x += *dx; - if (*x < 0) { - *x = 0; - if (*dx < 0) { - *dx = -*dx; - } - } else if (*x > max) { - *x = max; - if (*dx > 0) { - *dx = -*dx; - } - } -} - -void BallAnimation::draw(ANPCanvas* canvas) { - NPP instance = this->inst(); - PluginObject *obj = (PluginObject*) instance->pdata; - const float OW = 20; - const float OH = 20; - - inval(instance, m_oval, true); // inval the old - m_oval.left = m_x; - m_oval.top = m_y; - m_oval.right = m_x + OW; - m_oval.bottom = m_y + OH; - inval(instance, m_oval, true); // inval the new - - gCanvasI.drawColor(canvas, 0xFFFFFFFF); - - gPaintI.setColor(m_paint, 0xFFFF0000); - gCanvasI.drawOval(canvas, &m_oval, m_paint); - - bounce(&m_x, &m_dx, obj->window->width - OW); - bounce(&m_y, &m_dy, obj->window->height - OH); - - if (obj->mUnichar) { - ANPFontMetrics fm; - gPaintI.getFontMetrics(m_paint, &fm); - - gPaintI.setColor(m_paint, 0xFF0000FF); - char c = static_cast<char>(obj->mUnichar); - gCanvasI.drawText(canvas, &c, 1, 10, -fm.fTop, m_paint); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -void drawPlugin(NPP instance, const ANPBitmap& bitmap, const ANPRectI& clip) { - ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap); - - ANPRectF clipR; - clipR.left = clip.left; - clipR.top = clip.top; - clipR.right = clip.right; - clipR.bottom = clip.bottom; - gCanvasI.clipRect(canvas, &clipR); - - drawPlugin(instance, canvas); - - gCanvasI.deleteCanvas(canvas); -} - -void drawPlugin(NPP instance, ANPCanvas* canvas) { - PluginObject *obj = (PluginObject*) instance->pdata; - if (obj->anim == NULL) { - obj->anim = new BallAnimation(instance); - } - obj->anim->draw(canvas); -} - diff --git a/WebKit/android/stl/algorithm b/WebKit/android/stl/algorithm index 33968ab..131fe0d 100644 --- a/WebKit/android/stl/algorithm +++ b/WebKit/android/stl/algorithm @@ -49,10 +49,6 @@ #include <SkScalar.h> // for SK_ScalarNaN #ifdef PREFIX_FOR_WEBCORE #include <SkTSearch.h> -namespace WebCore { - class InlineTextBox; - class RenderLayer; -} #endif #include <float.h> @@ -64,14 +60,6 @@ namespace WebCore { #define WCHAR_MAX 0xFFFF #endif -namespace JSC { - class ProfileNode; -} - -namespace WTF { - template <typename T> class RefPtr; -} - namespace std { template<typename _Tp> @@ -83,6 +71,24 @@ namespace std __b = __tmp; } + template<typename _Tp> + inline void + reverse(_Tp* __first, _Tp* __last) + { + while(true) + { + if (__first == __last || __first == --__last) + return; + else + { + _Tp __tmp = *__first; + *__first = *__last; + *__last = __tmp; + } + ++__first; + } + } + #undef min #undef max @@ -199,12 +205,17 @@ extern void sort(const void** start, const void** end, Comparator comp); } - inline void sort (WebCore::InlineTextBox** start, WebCore::InlineTextBox**end, - bool (* comp)(const WebCore::InlineTextBox*, const WebCore::InlineTextBox*)) + template<typename P> inline void sort (P** start, P**end, + bool (* comp)(const P*, const P*)) { sort((const void**) start, (const void**) end, (Comparator) comp); } + template<typename P> void sort(P* start, P* end, + bool (* comp)(const P&, const P&)) { + stable_sort(start, end, *comp); + } + template<typename P> inline void stable_sort(P** start, P** end, bool (* comp)(P*, P*)) { @@ -258,15 +269,6 @@ extern void sort(const void** start, const void** end, Comparator comp); }; #endif -typedef bool (* ProfileComparator)(const WTF::RefPtr<JSC::ProfileNode>&, - const WTF::RefPtr<JSC::ProfileNode>&); - -inline void sort(WTF::RefPtr<JSC::ProfileNode>* start, - WTF::RefPtr<JSC::ProfileNode>* end, ProfileComparator comp) -{ - sort((const void**) start, (const void**) end, (Comparator) comp); -} - } #endif diff --git a/WebKit/android/wds/DebugServer.h b/WebKit/android/wds/DebugServer.h index a0a2aa8..3ec158b 100644 --- a/WebKit/android/wds/DebugServer.h +++ b/WebKit/android/wds/DebugServer.h @@ -63,7 +63,7 @@ public: } private: DebugServer(); - Vector<Frame*> m_frames; + WTF::Vector<Frame*> m_frames; ThreadIdentifier m_threadId; friend DebugServer* server(); }; diff --git a/WebKit/android/wds/client/ClientUtils.h b/WebKit/android/wds/client/ClientUtils.h index 0aa068e..261af27 100644 --- a/WebKit/android/wds/client/ClientUtils.h +++ b/WebKit/android/wds/client/ClientUtils.h @@ -28,6 +28,14 @@ #include <arpa/inet.h> +/* + * included for sockaddr_in structure, AF_INET definiton and etc. + */ +#ifdef __FreeBSD__ +#include <netinet/in.h> +#include <sys/socket.h> +#endif + // Callers need to include Log.h and errno.h to use this macro #define log_errno(str) LOGE("%s: %s", str, strerror(errno)) diff --git a/WebKit/gtk/ChangeLog b/WebKit/gtk/ChangeLog index e6dc216..3691b4b 100644 --- a/WebKit/gtk/ChangeLog +++ b/WebKit/gtk/ChangeLog @@ -1,11 +1,810 @@ -2009-02-03 Mark Rowe <mrowe@apple.com> +2009-03-25 Gustavo Noronha Silva <gns@gnome.org> - Merge r40508. + Reviewed by Holger Freyther. + + https://bugs.webkit.org/show_bug.cgi?id=15793 + [GTK] tooltip position doesn't update when hovering consecutive links + + Work-around tooltips not updating their location when the elements + are consecutive, by clearing the tooltip when handling + mouseDidMoveOverElement. + + * WebCoreSupport/ChromeClientGtk.cpp: + (WebKit::ChromeClient::mouseDidMoveOverElement): + +2009-03-23 Alejandro Garcia Castro <alex@igalia.com> + + Reviewed by Holger Freyther. + + [Gtk] Current API does not allow us to open target="_blank" links + in new tabs instead of windows + https://bugs.webkit.org/show_bug.cgi?id=23932 + + Added a signal to the API (new-window-policy-decision-requested) + that allows the browser to decide the policy for the new window + request, if the signal is not handled we open the new window as + usual. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::getNavigationAction): + (WebKit::FrameLoaderClient::dispatchDecidePolicyForNewWindowAction): + (WebKit::FrameLoaderClient::dispatchDecidePolicyForNavigationAction): + * webkit/webkitwebview.cpp: + +2009-03-20 Jan Michael Alonzo <jmalonzo@gmail.com> + + Not reviewed. Fix style issues with my previous commit (r41866) as + suggested by Holger in https://bugs.webkit.org/show_bug.cgi?id=24493 + + * tests/testwebhistoryitem.c: + (test_webkit_web_history_item_get_data): + (test_webkit_web_history_item_alternate_title): + +2009-03-20 Jan Michael Alonzo <jmalonzo@gmail.com> + + Reviewed by Holger Freyther. + + [GTK] Misc patches for WebKitWebHistoryItem + https://bugs.webkit.org/show_bug.cgi?id=24493 + + Add unit test for WebKitWebHistoryItem + + * tests/testwebhistoryitem.c: Added. + (web_history_item_fixture_setup): + (web_history_item_fixture_teardown): + (test_webkit_web_history_item_get_data): + (test_webkit_web_history_item_alternate_title): + (main): + +2009-03-20 Jan Michael Alonzo <jmalonzo@gmail.com> + + Reviewed by Holger Freyther. + + Separate gtk unit tests + https://bugs.webkit.org/show_bug.cgi?id=24039 + + Split the current single-file unit test to make it more + modularized and manageable in the future as more unit tests are + written. + + * tests/main.c: Removed. + * tests/testwebbackforwardlist.c: Copied from WebKit/gtk/tests/main.c. + (main): + * tests/testwebframe.c: Copied from WebKit/gtk/tests/main.c. + (main): + +2009-03-16 Christian Dywan <christian@twotoasts.de> + + Reviewed by Adam Roben. + + [gtk] API implementation: url and title + http://bugs.webkit.org/show_bug.cgi?id=14807 + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::dispatchDidChangeLocationWithinPage): + (WebKit::FrameLoaderClient::dispatchDidReceiveTitle): + (WebKit::FrameLoaderClient::dispatchDidCommitLoad): + * webkit/webkitwebview.cpp: + * webkit/webkitwebview.h: Implement "title" and "uri" properties as well + as according functions. "uri" always reflects the current location + including navigation inside the same page. title-changed is deprecated. + +2009-03-15 Gustavo Noronha Silva <gns@gnome.org> + + Reviewed by Anders Carlsson. + + Fix default policy decision to be ignore, on MIME checks, if + WebKit doesn't know how to handle the MIME type. The documentation + is already correct, and this was an oversight when the policy + decision code was first committed. Since 1.1.2 will be the first + release to support download, there is no practical change in + behavior. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::dispatchDecidePolicyForMIMEType): + +2009-03-15 Xan Lopez <xlopez@igalia.com> + + * NEWS: update for 1.1.2. + +2009-03-14 Jan Michael Alonzo <jmalonzo@webkit.org> + + Reviewed by Holger Freyther. + + [GTK] use of confirm dialog (yes/no) causes segfault + https://bugs.webkit.org/show_bug.cgi?id=20940 + + Change the script-confirm marshaller from OBJECT,STRING,BOOLEAN to + OBJECT,STRING,POINTER + + * webkit/webkitwebview.cpp: + * webkitmarshal.list: + +2009-03-12 Gustavo Noronha Silva <gns@gnome.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=24553 + [GTK] Improvements to WebKitDownload + + Rename 'state' to 'status' to match the naming in the frame + loader rework that we plan to land soonish, and make it a + property, for the same reason. + + * webkit/webkitdownload.cpp: + (_WebKitDownloadPrivate::): + (_WebKitDownloadPrivate::webkit_download_finalize): + (_WebKitDownloadPrivate::webkit_download_get_property): + (_WebKitDownloadPrivate::webkit_download_set_property): + (_WebKitDownloadPrivate::webkit_download_class_init): + (_WebKitDownloadPrivate::webkit_download_init): + (_WebKitDownloadPrivate::webkit_download_start): + (_WebKitDownloadPrivate::webkit_download_cancel): + (_WebKitDownloadPrivate::webkit_download_set_destination_uri): + (_WebKitDownloadPrivate::webkit_download_get_status): + (_WebKitDownloadPrivate::webkit_download_set_status): + (_WebKitDownloadPrivate::webkit_download_received_data): + (_WebKitDownloadPrivate::webkit_download_finished_loading): + (_WebKitDownloadPrivate::webkit_download_error): + * webkit/webkitdownload.h: + +2009-03-12 Gustavo Noronha Silva <gns@gnome.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=24553 + [GTK] Improvements to WebKitDownload + + Improved documentation for the download-requested signal, to make + its usage clear. + + * webkit/webkitwebview.cpp: + +2009-03-12 Gustavo Noronha Silva <gns@gnome.org> + + Reviewed by Alp Toker. + + https://bugs.webkit.org/show_bug.cgi?id=24541 + Scrolling with home and end keys not always works + + Also make page up and page down keys be handled by the webview key + event code, so that they also work in cases where the GTK+ + scrollbars don't handle them directly, like in the bugzill's patch + review page. + + * webkit/webkitwebview.cpp: + +2009-03-12 Gustavo Noronha Silva <gns@gnome.org> + + Reviewed by Alp Toker. + + https://bugs.webkit.org/show_bug.cgi?id=24541 + Scrolling with home and end keys not always works + + Make home and end keys behave more consistently for scrolling the + view. + + * webkit/webkitwebview.cpp: + +2009-03-12 Gustavo Noronha Silva <gns@gnome.org> + + Reviewed by Alp Toker. + + https://bugs.webkit.org/show_bug.cgi?id=24254 + [GTK] spacebar doesn't scroll down + + Make spacebar and shift+spacebar scroll like page up and down + respectively would. + + * webkit/webkitwebview.cpp: + +2009-03-10 Xan Lopez <xlopez@igalia.com> + + Reviewed by Holger Freyther. + + https://bugs.webkit.org/show_bug.cgi?id=24493 + [GTK] Misc patches for WebKitWebHistoryItem + + Only run code in dispose once per instance. + + * webkit/webkitwebhistoryitem.cpp: + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_dispose): + +2009-03-10 Xan Lopez <xlopez@igalia.com> + + Reviewed by Holger Freyther. + + https://bugs.webkit.org/show_bug.cgi?id=24493 + [GTK] Misc patches for WebKitWebHistoryItem + + Call deref() on our internal HistoryItem on dispose, as we always + acquire it with a releaseRef() call to a PassRefPtr, which passes + ownership. + + * webkit/webkitwebhistoryitem.cpp: + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_dispose): + +2009-03-10 Xan Lopez <xlopez@igalia.com> + + Reviewed by Holger Freyther. + + https://bugs.webkit.org/show_bug.cgi?id=24493 + [GTK] Misc patches for WebKitWebHistoryItem + + return foo? foo : NULL == return foo + + * webkit/webkitwebhistoryitem.cpp: + (WebKit::core): + +2009-03-11 Jan Michael Alonzo <jmalonzo@webkit.org> + + Reviewed by Holger Freyther. + + Gtk] Implement LayoutTestControllerGtk::setPrivateBrowsingEnabled + https://bugs.webkit.org/show_bug.cgi?id=24487 + + Add private browsing option "enable-private-browsing" to WebKitWebSettings. + + * webkit/webkitwebsettings.cpp: + (_WebKitWebSettingsPrivate::): + (_WebKitWebSettingsPrivate::webkit_web_settings_class_init): + (_WebKitWebSettingsPrivate::webkit_web_settings_set_property): + (_WebKitWebSettingsPrivate::webkit_web_settings_get_property): + (_WebKitWebSettingsPrivate::webkit_web_settings_copy): + * webkit/webkitwebview.cpp: + +2009-03-11 Jan Michael Alonzo <jmalonzo@webkit.org> + + Reviewed by Holger Freyther. + + [GTK] BackForward history leak? + https://bugs.webkit.org/show_bug.cgi?id=19528 + + Don't ref the history items when returning the back/forward list + Added test_webkit_web_history_item_lifetime test case for this. + + * tests/main.c: + (test_webkit_web_history_item_lifetime): + (test_webkit_web_back_forward_list_order): Style fix. + (test_webkit_web_back_forward_list_add_item): Style fix. + (main): + * webkit/webkitwebbackforwardlist.cpp: + (_WebKitWebBackForwardListPrivate::webkit_web_back_forward_list_get_forward_list_with_limit): + (_WebKitWebBackForwardListPrivate::webkit_web_back_forward_list_get_back_list_with_limit): + +2009-03-10 Xan Lopez <xlopez@igalia.com> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=24493 + [GTK] Misc patches for WebKitWebHistoryItem + + Use g_hash_table_new_full so we can save the manual unref on the + values when removing them from the table. + + * webkit/webkitwebhistoryitem.cpp: + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_dispose): + +2009-03-10 Xan Lopez <xan@gnome.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=24493 + [GTK] Misc patches for WebKitWebHistoryItem + + Use 'if (foo)' instead of 'if (foo != NULL)', per coding style + guidelines. + + * webkit/webkitwebhistoryitem.cpp: + (_WebKitWebHistoryItemPrivate::webkit_history_item_remove): + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_get_title): + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_get_alternate_title): + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_get_uri): + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_get_original_uri): + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_get_last_visited_time): + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_get_target): + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_is_target_item): + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_get_children): + +2009-03-10 Xan Lopez <xlopez@igalia.com> + + Reviewed by Alexey Proskuryakov. + + Correct return value to false instead of NULL. + + * webkit/webkitwebhistoryitem.cpp: + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_is_target_item): + +2009-03-08 Holger Hans Peter Freyther <zecke@selfish.org> + + Reviewed by Mark Rowe. + + Add javascript-profiling-enabled property and implement it. This + will enable/disable the profiler on the InstpectorController. + + * webkit/webkitprivate.h: + * webkit/webkitwebinspector.cpp: + (_WebKitWebInspectorPrivate::webkit_web_inspector_class_init): + (_WebKitWebInspectorPrivate::webkit_web_inspector_set_property): + (_WebKitWebInspectorPrivate::webkit_web_inspector_get_property): + (_WebKitWebInspectorPrivate::webkit_web_inspector_set_inspector_client): + * webkit/webkitwebview.cpp: + +2009-03-05 Gustavo Noronha Silva <gns@gnome.org> + + Reviewed by Olliej. + + https://bugs.webkit.org/show_bug.cgi?id=24295 + webkit_web_back_forward_list_add_item needs a Since tag + + Add missing Since tag to webkit_web_back_forward_list_add_item + documentation. + + * webkit/webkitwebbackforwardlist.cpp: + +2009-03-05 Gustavo Noronha Silva <gns@gnome.org> + + Reviewed by Mark Rowe. + + https://bugs.webkit.org/show_bug.cgi?id=24417 + [GTK] WebKitDownload's _cancel and _dispose methods may emit warnings + + NULL-check for timer on _cancel and _dispose, to avoid bad + warnings. + + * webkit/webkitdownload.cpp: + (_WebKitDownloadPrivate::webkit_download_finalize): + (_WebKitDownloadPrivate::webkit_download_cancel): + +2009-03-02 Xan Lopez <xan@gnome.org> + + Reviewed by Mark Rowe. + + https://bugs.webkit.org/show_bug.cgi?id=24287 + [GTK] Move auth dialog feature to WebKit/ + + Add WebKitSoupAuthDialog and add it to the session in webkit_init. + + * webkit/webkitprivate.cpp: + (currentToplevelCallback): + (webkit_init): + * webkit/webkitsoupauthdialog.c: Added. + (webkit_soup_auth_dialog_class_init): + (webkit_soup_auth_dialog_init): + (webkit_soup_auth_dialog_session_feature_init): + (free_authData): + (set_password_callback): + (response_callback): + (table_add_entry): + (show_auth_dialog): + (find_password_callback): + (session_authenticate): + (attach): + * webkit/webkitsoupauthdialog.h: Added. + +2009-03-03 Gustavo Noronha Silva <gns@gnome.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=16826 + [Gtk] Implement WebKitDownload + + Implement download, and provide a nice object wrapping the + download process. Initial work done by Marco Barisione and + Pierre-Luc Beaudoin for Collabora. + + * WebCoreSupport/ContextMenuClientGtk.cpp: + (WebKit::ContextMenuClient::downloadURL): + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::download): + (WebKit::FrameLoaderClient::startDownload): + * webkit/webkit.h: + * webkit/webkitdefines.h: + * webkit/webkitdownload.cpp: Added. + (_WebKitDownloadPrivate::): + (_WebKitDownloadPrivate::webkit_download_dispose): + (_WebKitDownloadPrivate::webkit_download_finalize): + (_WebKitDownloadPrivate::webkit_download_get_property): + (_WebKitDownloadPrivate::webkit_download_set_property): + (_WebKitDownloadPrivate::webkit_download_class_init): + (_WebKitDownloadPrivate::webkit_download_init): + (_WebKitDownloadPrivate::webkit_download_new): + (_WebKitDownloadPrivate::webkit_download_open_stream_for_uri): + (_WebKitDownloadPrivate::webkit_download_close_stream): + (_WebKitDownloadPrivate::webkit_download_start): + (_WebKitDownloadPrivate::webkit_download_cancel): + (_WebKitDownloadPrivate::webkit_download_get_uri): + (_WebKitDownloadPrivate::webkit_download_get_network_request): + (_WebKitDownloadPrivate::webkit_download_set_response): + (_WebKitDownloadPrivate::webkit_download_get_suggested_filename): + (_WebKitDownloadPrivate::webkit_download_get_destination_uri): + (_WebKitDownloadPrivate::webkit_download_set_destination_uri): + (_WebKitDownloadPrivate::webkit_download_get_state): + (_WebKitDownloadPrivate::webkit_download_get_total_size): + (_WebKitDownloadPrivate::webkit_download_get_current_size): + (_WebKitDownloadPrivate::webkit_download_get_progress): + (_WebKitDownloadPrivate::webkit_download_get_elapsed_time): + (_WebKitDownloadPrivate::webkit_download_received_data): + (_WebKitDownloadPrivate::webkit_download_finished_loading): + (_WebKitDownloadPrivate::webkit_download_error): + (_WebKitDownloadPrivate::DownloadClient::DownloadClient): + (_WebKitDownloadPrivate::DownloadClient::didReceiveResponse): + (_WebKitDownloadPrivate::DownloadClient::didReceiveData): + (_WebKitDownloadPrivate::DownloadClient::didFinishLoading): + (_WebKitDownloadPrivate::DownloadClient::didFail): + (_WebKitDownloadPrivate::DownloadClient::wasBlocked): + (_WebKitDownloadPrivate::DownloadClient::cannotShowURL): + * webkit/webkitdownload.h: Added. + * webkit/webkitprivate.h: + * webkit/webkitwebview.cpp: + * webkitmarshal.list: + +2009-03-01 Jan Michael Alonzo <jmalonzo@webkit.org> + + Reviewed by Holger Freyther. + + [Gtk] get the HTTP layout tests going + https://bugs.webkit.org/show_bug.cgi?id=24259 + + Added API to get the response mime type from a frame. We need this + so we can decide if we need to dump the frame as text or its + render tree + + * webkit/webkitprivate.h: + * webkit/webkitwebframe.cpp: + +2009-03-01 Jan Michael Alonzo <jmalonzo@webkit.org> + + Reviewed by Holger Freyther. + + [Gtk] get the HTTP layout tests going + https://bugs.webkit.org/show_bug.cgi?id=24259 + + Create a WebKitWebHistoryItem for each WebCore::HistoryItem when + necessary. + Add necessary API additions for us to be able to dump a WebKitWebHistoryItem + + * webkit/webkitprivate.h: + * webkit/webkitwebbackforwardlist.cpp: + (_WebKitWebBackForwardListPrivate::webkit_web_back_forward_list_get_forward_list_with_limit): + (_WebKitWebBackForwardListPrivate::webkit_web_back_forward_list_get_back_list_with_limit): + * webkit/webkitwebhistoryitem.cpp: + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_new_with_core_item): + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_new): + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_new_with_data): + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_get_target): + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_is_target_item): + (_WebKitWebHistoryItemPrivate::webkit_web_history_item_get_children): + (WebKit::core): + (WebKit::kit): + +2009-03-01 Christian Dywan <christian@twotoasts.de> + + Reviewed by Holger Freyther. + + * webkit/webkitprivate.h: + * webkit/webkitwebview.cpp: + (webkit_web_view_get_encoding): + * webkit/webkitwebview.h: Implement 'encoding' and 'custom-encoding' + properties as well as webkit_web_view_get_encoding. + +2009-03-01 Gustavo Noronha Silva <gns@gnome.org> + + Unreviewed simple wording fix for the NEWS file. + + * NEWS: - 2009-02-02 Geoffrey Garen <ggaren@apple.com> +2009-03-01 Xan Lopez <xan@gnome.org> + + Add NEWS file to track progress between releases. + + * NEWS: Added. + +2009-02-28 Christian Dywan <christian@twotoasts.de> + + Reviewed by Holger Freyther. + + * webkit/webkitwebview.cpp: Let webkit_web_view_open add file:// if a + locale path is passed for compatibility, since we used to support that. + +2009-02-27 Gustavo Noronha Silva <gns@gnome.org> + + Reviewed by David Hyatt. + + Automatically ignore empty requests to avoid crashing. This fixes + the crash in fast/loader/empty-embed-src-attribute.html. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::dispatchDecidePolicyForMIMEType): + (WebKit::FrameLoaderClient::dispatchDecidePolicyForNewWindowAction): + (WebKit::FrameLoaderClient::dispatchDecidePolicyForNavigationAction): + +2009-02-27 Xan Lopez <xan@gnome.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=24221 + [GTK] Do not emit load-finished when being disposed + + webkit_web_view_stop_load() is called from dispose() on + WebKitWebView. This eventually calls postProgressFinishedNotification + in FrameLoaderClientGtk, which emits load-finished. Add + a 'disposing' flag to WebView that we can check here, so + we avoid emitting signals on objects on their way to be + destroyed. This fixes a bunch of critical warnings when + closing a loading WebView. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::postProgressFinishedNotification): + * webkit/webkitprivate.h: + * webkit/webkitwebview.cpp: + +2009-02-27 Xan Lopez <xan@gnome.org> + + Rubber-stamped by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=24222 + [GTK] Remove checks for old glib versions + + libsoup, which is a hard dependency, needs at least glib 2.15.3, + so remove all glib checks for versions older than that. + + * webkit/webkitwebview.cpp: + +2009-02-26 Xan Lopez <xan@gnome.org> + + Reviewed by Holger Freyther. + + https://bugs.webkit.org/show_bug.cgi?id=16947 + [GTK] Missing HTTP Auth challenge + + Add new marshalers list. + + * webkitmarshal.list: Added. + +2009-02-26 Xan Lopez <xan@gnome.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=24193 + [GTK] Checkbuttons not activated with space + + Do not swallow key events with GtkIMContext for non-editable + content. + + * WebCoreSupport/EditorClientGtk.cpp: + (WebKit::EditorClient::handleInputMethodKeydown): + +2009-02-26 Xan Lopez <xan@gnome.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=24103 + [GTK] Use correct return value for WebView button-release handler + + We are returning whatever the core code tells us it did, but this + does not play well with the GTK+ model. GTK+ in general expects it + will see a button-release if it saw a button-press and no + motion/leave/etc events in between. EventHandler.cpp will, in some + cases, not handle press but handle release, confusing the parent + container of the WebView. + + As a workaround return always FALSE for button-release (this is + the same than the Windows port does). + + * webkit/webkitwebview.cpp: + +2009-02-26 Xan Lopez <xan@gnome.org> + + Reviewed by Holger Freyther. + + https://bugs.webkit.org/show_bug.cgi?id=17585 + [gtk] get|set encoding api + + Add functions to get and set a custom encoding an a view. + + * webkit/webkitprivate.h: + * webkit/webkitwebview.cpp: + (webkit_web_view_set_custom_encoding): + (webkit_web_view_get_custom_encoding): + * webkit/webkitwebview.h: + +2009-02-23 Xan Lopez <xan@gnome.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=22624 + [SOUP][GTK] Need API to get SoupSession from WebKit. + + Add API to get the default soup session. + + * webkit/webkitwebview.cpp: + * webkit/webkitwebview.h: + +2009-02-23 Xan Lopez <xan@gnome.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=22624 + [SOUP][GTK] Need API to get SoupSession from WebKit. + + Add soup dependency to pc file. + + * webkit.pc.in: + +2009-02-23 Jan Michael Alonzo <jmalonzo@webkit.org> + + Reviewed by Mark Rowe. + + [GTK] Back / Forward history menus are flipped + https://bugs.webkit.org/show_bug.cgi?id=22694 + + Don't call g_list_reverse when returning the back or forward list. + + * tests/main.c: + (test_webkit_web_back_forward_list_order): + (main): + * webkit/webkitwebbackforwardlist.cpp: + (_WebKitWebBackForwardListPrivate::webkit_web_back_forward_list_get_forward_list_with_limit): + (_WebKitWebBackForwardListPrivate::webkit_web_back_forward_list_get_back_list_with_limit): + +2009-02-17 Xan Lopez <xan@gnome.org> + + Rubber-stamped by Alexey Proskuryakov. + + Restoring change landed in r40715, which was accidentally undone + by r40918. + + * webkit/webkitwebframe.cpp: + +2009-02-12 Christian Dywan <christian@twotoasts.de> + + Reviewed by Holger Freyther. + + http://bugs.webkit.org/show_bug.cgi?id=17176 + [GTK] API: hovering-over-link and webkit_web_view_open /_load_foo + + * webkit/webkitwebframe.cpp: + * webkit/webkitwebframe.h: + * webkit/webkitwebview.cpp: + * webkit/webkitwebview.h: Introduce webkit_web_frame_load_uri, + webkit_web_frame_load_string, webkit_web_view_load_uri and + webkit_web_view_load_request and unify implementations. + +2009-02-11 Dimitri Dupuis-latour <dupuislatour@apple.com> + + Stub out InspectorClient::hiddenPanels. + + Reviewed by Timothy Hatcher. + + * WebCoreSupport/InspectorClientGtk.cpp: + (WebKit::InspectorClient::hiddenPanels): + * WebCoreSupport/InspectorClientGtk.h: + +2009-02-07 Holger Hans Peter Freyther <zecke@selfish.org> + + Unreviewed build fix Use toNormalizedRange(). + + * WebCoreSupport/EditorClientGtk.cpp: + (WebKit::clipboard_get_contents_cb): + +2009-02-06 Geoffrey Garen <ggaren@apple.com> + + Build fix. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::updateGlobalHistoryRedirectLinks): + * WebCoreSupport/FrameLoaderClientGtk.h: + +2009-02-06 Xan Lopez <xan@gnome.org> + + Reviewed by Holger Freyther. + + Reported by Daniel Macks. + + https://bugs.webkit.org/show_bug.cgi?id=20412 + + Use positive numbers for the target info IDs, gtk_target_list_add + casts them to 'guint'. Also just start them from 0, since the + values are not relevant or magic in any way, they are just used as + tokens for the user of the API. + + * webkit/webkitwebview.h: + +2009-02-06 Xan Lopez <xan@gnome.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=23769 + + Do not use empty ResourceError errors. + + Rather create bogus but non-null errors, since some codepaths + expect these. For example, see DocumentLoader::mainReceivedError. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::cancelledError): + (WebKit::FrameLoaderClient::blockedError): + (WebKit::FrameLoaderClient::cannotShowURLError): + (WebKit::FrameLoaderClient::interruptForPolicyChangeError): + (WebKit::FrameLoaderClient::cannotShowMIMETypeError): + (WebKit::FrameLoaderClient::fileDoesNotExistError): + (WebKit::FrameLoaderClient::pluginWillHandleLoadError): + +2009-02-06 Xan Lopez <xan@gnome.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=23761 + + Use two-arg KURL ctor. + + We are using the one-arg ctor currently, but: + + - It assumes the strings are already encoded, which is not + necesarily the case for us. + + - The single-argument KURL ctors expect their input to already be + the output of a previous KURL::parse call, so for the general + case (ie, random user input) we need to use the two-arg ctor + anyway. + + * webkit/webkitwebframe.cpp: + * webkit/webkitwebview.cpp: + +2009-02-05 Aaron Boodman <aa@chromium.org> + + Reviewed by Dave Hyatt. + + https://bugs.webkit.org/show_bug.cgi?id=23708 + Adds documentElementAvailable() callback to FrameLoaderClient. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::documentElementAvailable): + Stub out documentElementAvailable() + * WebCoreSupport/FrameLoaderClientGtk.h: + Ditto. + +2009-02-03 Hiroyuki Ikezoe <poincare@ikezoe.net> + + Reviewed by Holger Freyther. + + https://bugs.webkit.org/show_bug.cgi?id=22988 + [GTK] Need a public method to add a WebKitWebHistoryItem to + WebKitWebBackForwardList. + + Wrap WebCore::BackForwardList::addItem. + + * tests/main.c: + (test_webkit_web_back_forward_list_add_item): + (main): + * webkit/webkitwebbackforwardlist.cpp: + (_WebKitWebBackForwardListPrivate::webkit_web_back_forward_list_add_item): + * webkit/webkitwebbackforwardlist.h: + +2009-02-02 Geoffrey Garen <ggaren@apple.com> + + Build fix. + + * webkit/webkitwebview.cpp: + +2009-02-02 Geoffrey Garen <ggaren@apple.com> + + Build fix. + + * webkit/webkitwebframe.cpp: + +2009-02-02 Geoffrey Garen <ggaren@apple.com> + + Build fix. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::createFrame): + +2009-02-02 Geoffrey Garen <ggaren@apple.com> Reviewed by Sam Weinig. - + Track redirects in global history. Keep GTK building. @@ -15,17 +814,62 @@ (WebKit::FrameLoaderClient::updateGlobalHistoryForRedirectWithoutHistoryItem): * WebCoreSupport/FrameLoaderClientGtk.h: -2009-02-03 Mark Rowe <mrowe@apple.com> +2009-02-02 Anders Carlsson <andersca@apple.com> + + Build fix. + + * WebCoreSupport/FrameLoaderClientGtk.h: + +2009-02-02 Anders Carlsson <andersca@apple.com> + + Reviewed by Dan Bernstein. + + Update for changes to WebCore. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::createPlugin): + (WebKit::FrameLoaderClient::createJavaAppletWidget): + * WebCoreSupport/FrameLoaderClientGtk.h: + +2009-02-02 Holger Hans Peter Freyther <zecke@selfish.org> - Merge r40436. + Reviewed by Darin Adler. - 2009-01-30 Geoffrey Garen <ggaren@apple.com> + Move Frame::forceLayout, Frame::adjustPageHeight and Frame::forceLayoutWithPageWidthRange to FrameView + + https://bugs.webkit.org/show_bug.cgi?id=23428 + + FrameView::forceLayout could be killed but the comment might + contain a value over the the plain FrameView::layout... + + Adjust the WebCore/WebKit consumers of these methods. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::forceLayout): + * webkit/webkitwebview.cpp: + +2009-01-30 Geoffrey Garen <ggaren@apple.com> Build fix. * WebCoreSupport/FrameLoaderClientGtk.cpp: (WebKit::FrameLoaderClient::createFrame): +2009-01-30 Holger Hans Peter Freyther <zecke@selfish.org> + + Reviewed by Simon Hausmann. + + https://bugs.webkit.org/show_bug.cgi?id=22056 + + Kill FrameLoaderClient.cpp, move the code over to Frame::createView + + FrameLoaderClient is supposed to be an interface, move the + to be shared code to Frame which is a controller and is + allowed to create a FrameView. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::transitionToCommittedForNewPage): + 2009-01-27 Brady Eidson <beidson@apple.com> Reviewed by Dan Bernstein @@ -157,29 +1001,29 @@ Reviewed by Darin Adler. [GTK] Fix the reference counting of WebKitWebFrames - + The ownership is the following: WebKitWebView owns a WebCore::Page. WebKitWebView is creating one WebKitWebFrame which will be the mainFrame of the WebCore::Page (having the reference on the Frame). - + The FrameLoaderClient has the reference of the WebKitWebFrame for the main frame and also any other frame. This means when the WebCore::Frame goes away the FrameLoaderClient will go away which will normally remove the last reference of the WebKitWebFrame. Because an API user might have g_object_ref'ed the WebKitWebFrame null checks had to be added to WebKitWebFrame. - + For WebCore::Frames created by the FrameLoaderClient the ownership will be passed down to the FrameTree, the WebKitWebFrame is not holding a reference to the WebCore::Frame. - + Do not g_object_unref the mainFrame in the destructor of the WebKitWebFrame as this will happen from within the WebCore::Page destruction. Do not hold a reference to the WebCore::Frame (circle) in WebKitWebFrame, add null checks as the WebCore::Frame might have gone away. Do not keep track of the FrameLoaderClient in the private structures as it was mostly unusued. - + https://bugs.webkit.org/show_bug.cgi?id=21837 * WebCoreSupport/FrameLoaderClientGtk.cpp: @@ -415,7 +1259,7 @@ Renderer::caretRect() is now localCaretRect(), which needs converting to absolute coordinates (taking transforms into account). - + * webkit/webkitwebview.cpp: 2008-12-01 Xan Lopez <xan@gnome.org> @@ -930,7 +1774,7 @@ 2008-10-06 David Hyatt <hyatt@apple.com> Enable viewless Mac WebKit to paint some basic pages. - + Reviewed by Sam Weinig * WebCoreSupport/FrameLoaderClientGtk.cpp: @@ -946,11 +1790,11 @@ 2008-10-03 David Hyatt <hyatt@apple.com> https://bugs.webkit.org/show_bug.cgi?id=21340 - + Remove "containingWindow()/setContainingWindow()" from Widget. HostWindow covers this now. Reviewed by Dan Bernstein & Darin Adler - + * WebCoreSupport/FrameLoaderClientGtk.cpp: (WebKit::FrameLoaderClient::transitionToCommittedForNewPage): @@ -970,7 +1814,7 @@ 2008-10-03 David Hyatt <hyatt@apple.com> Remove addToDirtyRegion. - + Reviewed by Oliver Hunt * WebCoreSupport/ChromeClientGtk.cpp: @@ -978,7 +1822,7 @@ 2008-10-02 David Hyatt <hyatt@apple.com> https://bugs.webkit.org/show_bug.cgi?id=21314 - + Make scrollBackingStore cross-platform. Reviewed by Sam Weinig @@ -991,9 +1835,9 @@ 2008-10-01 David Hyatt <hyatt@apple.com> https://bugs.webkit.org/show_bug.cgi?id=21282 - + Make contentsToScreen/screenToContents cross-platform. Only implemented by Mac/Win right now. - + Reviewed by Adam Roben * WebCoreSupport/ChromeClientGtk.cpp: @@ -1004,7 +1848,7 @@ 2008-09-30 Dave Hyatt <hyatt@apple.com> http://bugs.webkit.org/show_bug.cgi?id=21250 - + Rename updateContents to repaintContentRectangle and make it cross-platform by always sending repaints up through the ChromeClient. @@ -2396,9 +3240,9 @@ http://bugs.webkit.org/show_bug.cgi?id=16802 [GTK] Missing gtk properties - + Add missing properties to WebKitViewFrame and WebKitWebView. - + * WebView/webkitprivate.h: add some useful defines for param specs * WebView/webkitwebframe.cpp: (webkit_web_frame_get_property): added @@ -2415,7 +3259,7 @@ http://bugs.webkit.org/show_bug.cgi?id=16654 [GTK] Signal "navigation-requested" does not react correctly on return TRUE from callbacks - + * WebView/webkitwebview.cpp: use our own accumulator for signals returning WebKitNavigationResponse. The emission will be stopped when any callback returns anything but @@ -2587,7 +3431,7 @@ * WebView/webkitwebview.cpp: * WebView/webkitwebview.h: -2007-12-19 Christian Dywan <christian@twotoasts.de> +2007-12-19 Christian Dywan <christian@twotoasts.de> Reviewed by Alp Toker. @@ -2602,7 +3446,7 @@ Reviewed by Holger Freyther. Delete when Destroy functions are called to avoid leaks - + This matches the Mac port. * WebCoreSupport/ChromeClientGtk.cpp: @@ -2849,7 +3693,7 @@ * WebView/webkitprivate.h: (getFrameFromView): removed - + * WebView/webkitwebview.cpp: (webkit_web_view_expose_event): (webkit_web_view_key_press_event): use focused frame @@ -3275,7 +4119,7 @@ http://bugs.webkit.org/show_bug.cgi?id=15745 [GTK] Arrow keys do not Scroll - + * Api/webkitgtkpage.cpp: Support Up/Down/Right/Left keys to scroll. Slight hack, see FIXME for @@ -3848,12 +4692,12 @@ 2007-09-05 Geoffrey Garen <ggaren@apple.com> Reviewed by Darin Adler, Maciej Stachowiak, Mark Rowe, Tim Hatcher. - - Fixed <rdar://problem/5326009> Make non-browser WebKit clients have no + + Fixed <rdar://problem/5326009> Make non-browser WebKit clients have no memory cache, or a very tiny one - + Keep the GTK build working with an empty stub. - + * WebCoreSupport/FrameLoaderClientGtk.cpp: (WebKit::FrameLoaderClient::didPerformFirstNavigation): * WebCoreSupport/FrameLoaderClientGtk.h: @@ -3863,7 +4707,7 @@ Reviewed by Sam. <rdar://problem/5344848> IME is incorrectly used for key events when on non-editable regions - + EditorClient::setInputMethodState stub * WebCoreSupport/EditorClientGtk.cpp: @@ -3879,7 +4723,7 @@ 2007-08-17 Anders Carlsson <andersca@apple.com> Build fix. - + * WebCoreSupport/FrameLoaderClientGtk.cpp: (WebKit::FrameLoaderClient::createPlugin): * WebCoreSupport/FrameLoaderClientGtk.h: @@ -3931,7 +4775,7 @@ Minor changes to the WebKit::EditorClient to allow removing of text from TextFields. Remove the selectWordBeforeMenuEvent method - which is not used and not within WebCore::EditorClient. + which is not used and not within WebCore::EditorClient. * WebCoreSupport/EditorClientGtk.cpp: (WebKit::EditorClient::shouldDeleteRange): @@ -3949,7 +4793,7 @@ classes into the WebKit namespace. Change the class names to not contain Gtk. The file names have to contain the Gtk suffix to not clash with files in WebCore (e.g. bridge/EditorClient.h). - + * Api/webkitgtkframe.cpp: * Api/webkitgtkpage.cpp: @@ -4424,7 +5268,7 @@ GtkAdjustment of the GtkLayout and reimplement the set_scroll_adjustments method and pass the GtkAdjustments to ScrollView. This makes having one GdkWindow for the complete FrameTree possible. - + * gtk/Api/webkitgtkframe.cpp: * gtk/Api/webkitgtkpage.cpp: @@ -4515,7 +5359,7 @@ * gtk/Api/webkitgtkpage.cpp: Implement webkit_gtk_page_can_go_backward() and webkit_gtk_page_can_go_forward() functions. -2007-07-30 Diego Escalante Urrelo <diegoe@gnome.org> +2007-07-30 Diego Escalante Urrelo <diegoe@gnome.org> Reviewed by Alp Toker. diff --git a/WebKit/gtk/NEWS b/WebKit/gtk/NEWS new file mode 100644 index 0000000..c8f656c --- /dev/null +++ b/WebKit/gtk/NEWS @@ -0,0 +1,54 @@ +================ +WebKitGTK+ 1.1.2 +================ + +What's new in WebKitGTK+ 1.1.2? + + - Added support for downloads: a new signal, 'download-requested', + will be emitted by WebKit when a dowload is requested. On top of + that, the download process has been encapsulated in a new object, + WebKitDownload, which allows the user to control it or to start + new downloads from the client side. + - Added webkit_web_view_get_encoding to get the automatic encoding + of the current page. + - Added GObject properties for 'encoding' and 'custom-encoding'. + - Added 'javascript-profiling-enabled' property to the WebInspector, + which allows to enable and disable the profiling functionality. + - Added API to create and add history items to WebKit's history. + - Improved debugging support with WEBKIT_DEBUG environment + variable. Most of the settings will only give useful output for + debug builds, but WEBKIT_DEBUG=Network will log all HTTP traffic + form libsoup to console. See WebCore/platform/gtk/LoggingGtk.cpp + for all the options available. + - Lots of bugfixes. + +================ +WebKitGTK+ 1.1.1 +================ + +What's new in WebKitGTK+ 1.1.1? + + - ABI compatibility with 1.0.3 was broken, so you will need to + recompile your application against 1.1.1 + - Support for the CURL backend was dropped, libsoup is the only HTTP + backend now. + - webkit_get_default_session, to get the SoupSession used internally + by WebKit. + - 'create-web-view' signal, emitted when the creation of a new + window is requested. + - 'navigation-policy-decision-requested' signal, emitted when a + navigation to another page is requested. + - 'mime-type-policy-decision-requested' signal, emitted each time + WebKit is about to show a URI with a given MIME type. + - Support for the Web Inspector + (see http://webkit.org/blog/197/web-inspector-redesign/) + - HTTP authentication support, with optional gnome-keyring storage. + - New load functions: webkit_web_view_open, webkit_web_view_load_uri + and webkit_web_view_load_request. The old + webkit_web_view_load_string and webkit_web_view_load_html_string + are now deprecated. + - webkit_web_view_reload_bypass_cache + - webkit_web_view_{get,set}_custom_encoding, to override the + encoding of the current page. + - Improved stability and lots of bugfixes. + diff --git a/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp b/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp index 3557a3f..7125305 100644 --- a/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp +++ b/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp @@ -358,6 +358,20 @@ void ChromeClient::contentsSizeChanged(Frame*, const IntSize&) const void ChromeClient::mouseDidMoveOverElement(const HitTestResult& hit, unsigned modifierFlags) { + // If a tooltip must be displayed it will be, afterwards, when + // setToolTip is called; this is just a work-around to make sure + // it updates its location correctly; see + // https://bugs.webkit.org/show_bug.cgi?id=15793. + g_object_set(m_webView, "has-tooltip", FALSE, NULL); + + GdkDisplay* gdkDisplay; + GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(m_webView)); + if (GTK_WIDGET_TOPLEVEL(window)) + gdkDisplay = gtk_widget_get_display(window); + else + gdkDisplay = gdk_display_get_default(); + gtk_tooltip_trigger_tooltip_query(gdkDisplay); + // check if the element is a link... bool isLink = hit.isLiveLink(); if (isLink) { @@ -393,16 +407,24 @@ void ChromeClient::print(Frame* frame) webkit_web_frame_print(kit(frame)); } +#if ENABLE(DATABASE) void ChromeClient::exceededDatabaseQuota(Frame* frame, const String&) { -#if ENABLE(DATABASE) // Set to 5M for testing // FIXME: Make this configurable notImplemented(); const unsigned long long defaultQuota = 5 * 1024 * 1024; DatabaseTracker::tracker().setQuota(frame->document()->securityOrigin(), defaultQuota); +} #endif + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +void ChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded) +{ + // FIXME: Free some space. + notImplemented(); } +#endif void ChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChooser) { diff --git a/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h b/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h index 299d023..bac9940 100644 --- a/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h +++ b/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h @@ -96,9 +96,12 @@ namespace WebKit { virtual void setToolTip(const WebCore::String&); virtual void print(WebCore::Frame*); - +#if ENABLE(DATABASE) virtual void exceededDatabaseQuota(WebCore::Frame*, const WebCore::String&); - +#endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); +#endif virtual void runOpenPanel(WebCore::Frame*, PassRefPtr<WebCore::FileChooser>); virtual void formStateDidChange(const WebCore::Node*) { } diff --git a/WebKit/gtk/WebCoreSupport/ContextMenuClientGtk.cpp b/WebKit/gtk/WebCoreSupport/ContextMenuClientGtk.cpp index 490370c..42d4813 100644 --- a/WebKit/gtk/WebCoreSupport/ContextMenuClientGtk.cpp +++ b/WebKit/gtk/WebCoreSupport/ContextMenuClientGtk.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 Nuanti Ltd. + * Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,6 +21,7 @@ #include "ContextMenu.h" #include "ContextMenuClientGtk.h" +#include "CString.h" #include "HitTestResult.h" #include "KURL.h" #include "NotImplemented.h" @@ -163,7 +165,20 @@ void ContextMenuClient::contextMenuItemSelected(ContextMenuItem*, const ContextM void ContextMenuClient::downloadURL(const KURL& url) { - notImplemented(); + WebKitNetworkRequest* network_request = webkit_network_request_new(url.string().utf8().data()); + WebKitDownload* download = webkit_download_new(network_request); + g_object_unref(network_request); + + gboolean handled; + g_signal_emit_by_name(m_webView, "download-requested", download, &handled); + + if (!handled) { + webkit_download_cancel(download); + g_object_unref(download); + return; + } + + webkit_download_start(download); } void ContextMenuClient::copyImageToClipboard(const HitTestResult&) diff --git a/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp b/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp index e09178e..a1f2509 100644 --- a/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp +++ b/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp @@ -169,7 +169,7 @@ static void clipboard_get_contents_cb(GtkClipboard* clipboard, GtkSelectionData* { WebKitWebView* webView = reinterpret_cast<WebKitWebView*>(data); Frame* frame = core(webView)->focusController()->focusedOrMainFrame(); - PassRefPtr<Range> selectedRange = frame->selection()->toRange(); + PassRefPtr<Range> selectedRange = frame->selection()->toNormalizedRange(); if (static_cast<gint>(info) == WEBKIT_WEB_VIEW_TARGET_INFO_HTML) { String markup = createMarkup(selectedRange.get(), 0, AnnotateForInterchange); @@ -457,8 +457,11 @@ void EditorClient::handleKeyboardEvent(KeyboardEvent* event) void EditorClient::handleInputMethodKeydown(KeyboardEvent* event) { - WebKitWebViewPrivate* priv = m_webView->priv; + Frame* targetFrame = core(m_webView)->focusController()->focusedOrMainFrame(); + if (!targetFrame || !targetFrame->editor()->canEdit()) + return; + WebKitWebViewPrivate* priv = m_webView->priv; // TODO: Dispatch IE-compatible text input events for IM events. if (gtk_im_context_filter_keypress(priv->imContext, event->keyEvent()->gdkEventKey())) event->setDefaultHandled(); diff --git a/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp b/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp index 55d5024..a54aecc 100644 --- a/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp +++ b/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp @@ -3,6 +3,7 @@ * Copyright (C) 2007, 2008 Holger Hans Peter Freyther * Copyright (C) 2007 Christian Dywan <christian@twotoasts.de> * Copyright (C) 2008 Collabora Ltd. All rights reserved. + * Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,10 +29,12 @@ #include "FrameLoader.h" #include "FrameView.h" #include "FrameTree.h" +#include "HTMLAppletElement.h" #include "HTMLFormElement.h" #include "HTMLFrameElement.h" #include "HTMLFrameOwnerElement.h" #include "HTMLNames.h" +#include "HTMLPlugInElement.h" #include "JSDOMWindow.h" #include "Language.h" #include "MIMETypeRegistry.h" @@ -40,6 +43,7 @@ #include "PlatformString.h" #include "PluginDatabase.h" #include "RenderPart.h" +#include "ResourceHandle.h" #include "ResourceRequest.h" #include "CString.h" #include "ProgressTracker.h" @@ -245,8 +249,12 @@ void FrameLoaderClient::postProgressEstimateChangedNotification() void FrameLoaderClient::postProgressFinishedNotification() { WebKitWebView* webView = getViewFromFrame(m_frame); + WebKitWebViewPrivate* privateData = WEBKIT_WEB_VIEW_GET_PRIVATE(webView); - g_signal_emit_by_name(webView, "load-finished", m_frame); + // We can get a stopLoad() from dispose when the object is being + // destroyed, don't emit the signal in that case. + if (!privateData->disposing) + g_signal_emit_by_name(webView, "load-finished", m_frame); } void FrameLoaderClient::frameLoaderDestroyed() @@ -268,6 +276,11 @@ void FrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction poli if (!policyFunction) return; + if (resourceRequest.isNull()) { + (core(m_frame)->loader()->*policyFunction)(PolicyIgnore); + return; + } + WebKitWebView* page = getViewFromFrame(m_frame); WebKitNetworkRequest* request = webkit_network_request_new(resourceRequest.url().string().utf8().data()); @@ -287,7 +300,40 @@ void FrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction poli if (canShowMIMEType(mimeType)) webkit_web_policy_decision_use (policyDecision); else - webkit_web_policy_decision_download (policyDecision); + webkit_web_policy_decision_ignore (policyDecision); +} + +static WebKitWebNavigationAction* getNavigationAction(const NavigationAction& action) +{ + gint button = -1; + + const Event* event = action.event(); + if (event && event->isMouseEvent()) { + const MouseEvent* mouseEvent = static_cast<const MouseEvent*>(event); + // DOM button values are 0, 1 and 2 for left, middle and right buttons. + // GTK+ uses 1, 2 and 3, so let's add 1 to remain consistent. + button = mouseEvent->button() + 1; + } + + gint modifierFlags = 0; + UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event)); + if (keyStateEvent) { + if (keyStateEvent->shiftKey()) + modifierFlags |= GDK_SHIFT_MASK; + if (keyStateEvent->ctrlKey()) + modifierFlags |= GDK_CONTROL_MASK; + if (keyStateEvent->altKey()) + modifierFlags |= GDK_MOD1_MASK; + if (keyStateEvent->metaKey()) + modifierFlags |= GDK_MOD2_MASK; + } + + return WEBKIT_WEB_NAVIGATION_ACTION(g_object_new(WEBKIT_TYPE_WEB_NAVIGATION_ACTION, + "reason", kit(action.type()), + "original-uri", action.url().string().utf8().data(), + "button", button, + "modifier-state", modifierFlags, + NULL)); } void FrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>, const String& s) @@ -295,9 +341,32 @@ void FrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFuncti ASSERT(policyFunction); if (!policyFunction) return; + + if (resourceRequest.isNull()) { + (core(m_frame)->loader()->*policyFunction)(PolicyIgnore); + return; + } + + WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction); + + if (m_policyDecision) + g_object_unref(m_policyDecision); + m_policyDecision = policyDecision; + + WebKitWebView* webView = getViewFromFrame(m_frame); + WebKitNetworkRequest* request = webkit_network_request_new(resourceRequest.url().string().utf8().data()); + WebKitWebNavigationAction* navigationAction = getNavigationAction(action); + gboolean isHandled = false; + + g_signal_emit_by_name(webView, "new-window-policy-decision-requested", m_frame, request, navigationAction, policyDecision, &isHandled); + + g_object_unref(navigationAction); + g_object_unref(request); + // FIXME: I think Qt version marshals this to another thread so when we // have multi-threaded download, we might need to do the same - (core(m_frame)->loader()->*policyFunction)(PolicyUse); + if (!isHandled) + (core(m_frame)->loader()->*policyFunction)(PolicyUse); } void FrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>) @@ -306,6 +375,11 @@ void FrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunct if (!policyFunction) return; + if (resourceRequest.isNull()) { + (core(m_frame)->loader()->*policyFunction)(PolicyIgnore); + return; + } + WebKitWebView* webView = getViewFromFrame(m_frame); WebKitNetworkRequest* request = webkit_network_request_new(resourceRequest.url().string().utf8().data()); WebKitNavigationResponse response; @@ -329,36 +403,7 @@ void FrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunct g_object_unref(m_policyDecision); m_policyDecision = policyDecision; - gint button = -1; - gint modifierFlags = 0; - - const Event* event = action.event(); - if (event && event->isMouseEvent()) { - const MouseEvent* mouseEvent = static_cast<const MouseEvent*>(event); - // DOM button values are 0, 1 and 2 for left, middle and right buttons. - // GTK+ uses 1, 2 and 3, so let's add 1 to remain consistent. - button = mouseEvent->button() + 1; - } - - UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event)); - if (keyStateEvent) { - if (keyStateEvent->shiftKey()) - modifierFlags |= GDK_SHIFT_MASK; - if (keyStateEvent->ctrlKey()) - modifierFlags |= GDK_CONTROL_MASK; - if (keyStateEvent->altKey()) - modifierFlags |= GDK_MOD1_MASK; - if (keyStateEvent->metaKey()) - modifierFlags |= GDK_MOD2_MASK; - } - - GObject* navigationAction = G_OBJECT(g_object_new(WEBKIT_TYPE_WEB_NAVIGATION_ACTION, - "reason", kit(action.type()), - "original-uri", action.url().string().utf8().data(), - "button", button, - "modifier-state", modifierFlags, - NULL)); - + WebKitWebNavigationAction* navigationAction = getNavigationAction(action); gboolean isHandled = false; g_signal_emit_by_name(webView, "navigation-policy-decision-requested", m_frame, request, navigationAction, policyDecision, &isHandled); @@ -370,7 +415,7 @@ void FrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunct webkit_web_policy_decision_use(m_policyDecision); } -Widget* FrameLoaderClient::createPlugin(const IntSize& pluginSize, Element* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually) +Widget* FrameLoaderClient::createPlugin(const IntSize& pluginSize, HTMLPlugInElement* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually) { PluginView* pluginView = PluginView::create(core(m_frame), pluginSize, element, url, paramNames, paramValues, mimeType, loadManually); @@ -393,7 +438,7 @@ PassRefPtr<Frame> FrameLoaderClient::createFrame(const KURL& url, const String& childFrame->tree()->setName(name); childFrame->init(); - childFrame->loader()->loadURL(url, referrer, String(), FrameLoadTypeRedirectWithLockedBackForwardList, 0, 0); + childFrame->loader()->loadURL(url, referrer, String(), false, FrameLoadTypeRedirectWithLockedBackForwardList, 0, 0); // The frame's onload handler may have removed it from the document. if (!childFrame->tree()->parent()) @@ -409,7 +454,7 @@ void FrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget) m_hasSentResponseToPlugin = false; } -Widget* FrameLoaderClient::createJavaAppletWidget(const IntSize&, Element*, const KURL& baseURL, +Widget* FrameLoaderClient::createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues) { notImplemented(); @@ -469,6 +514,10 @@ void FrameLoaderClient::windowObjectCleared() // The Win port has an example of how we might do this. } +void FrameLoaderClient::documentElementAvailable() +{ +} + void FrameLoaderClient::didPerformFirstNavigation() const { } @@ -524,7 +573,9 @@ void FrameLoaderClient::makeRepresentation(DocumentLoader*) void FrameLoaderClient::forceLayout() { - core(m_frame)->forceLayout(true); + FrameView* view = core(m_frame)->view(); + if (view) + view->forceLayout(true); } void FrameLoaderClient::forceLayoutForNonHTML() @@ -569,7 +620,10 @@ void FrameLoaderClient::dispatchWillPerformClientRedirect(const KURL&, double, d void FrameLoaderClient::dispatchDidChangeLocationWithinPage() { - notImplemented(); + WebKitWebFramePrivate* priv = m_frame->priv; + g_free(priv->uri); + priv->uri = g_strdup(core(m_frame)->loader()->url().prettyURL().utf8().data()); + g_object_notify(G_OBJECT(m_frame), "uri"); } void FrameLoaderClient::dispatchWillClose() @@ -590,11 +644,18 @@ void FrameLoaderClient::dispatchDidStartProvisionalLoad() void FrameLoaderClient::dispatchDidReceiveTitle(const String& title) { - g_signal_emit_by_name(m_frame, "title-changed", title.utf8().data()); + WebKitWebFramePrivate* priv = m_frame->priv; + g_free(priv->title); + priv->title = g_strdup(title.utf8().data()); + + g_signal_emit_by_name(m_frame, "title-changed", priv->title); + g_object_notify(G_OBJECT(m_frame), "title"); WebKitWebView* webView = getViewFromFrame(m_frame); - if (m_frame == webkit_web_view_get_main_frame(webView)) + if (m_frame == webkit_web_view_get_main_frame(webView)) { g_signal_emit_by_name(webView, "title-changed", m_frame, title.utf8().data()); + g_object_notify(G_OBJECT(webView), "title"); + } } void FrameLoaderClient::dispatchDidCommitLoad() @@ -602,15 +663,28 @@ void FrameLoaderClient::dispatchDidCommitLoad() /* Update the URI once first data has been received. * This means the URI is valid and successfully identify the page that's going to be loaded. */ - WebKitWebFramePrivate* frameData = WEBKIT_WEB_FRAME_GET_PRIVATE(m_frame); - g_free(frameData->uri); - frameData->uri = g_strdup(core(m_frame)->loader()->url().prettyURL().utf8().data()); + g_object_freeze_notify(G_OBJECT(m_frame)); + + WebKitWebFramePrivate* priv = m_frame->priv; + g_free(priv->uri); + priv->uri = g_strdup(core(m_frame)->loader()->url().prettyURL().utf8().data()); + g_free(priv->title); + priv->title = NULL; + g_object_notify(G_OBJECT(m_frame), "uri"); + g_object_notify(G_OBJECT(m_frame), "title"); g_signal_emit_by_name(m_frame, "load-committed"); WebKitWebView* webView = getViewFromFrame(m_frame); - if (m_frame == webkit_web_view_get_main_frame(webView)) + if (m_frame == webkit_web_view_get_main_frame(webView)) { + g_object_freeze_notify(G_OBJECT(webView)); + g_object_notify(G_OBJECT(webView), "uri"); + g_object_notify(G_OBJECT(webView), "title"); + g_object_thaw_notify(G_OBJECT(webView)); g_signal_emit_by_name(webView, "load-committed", m_frame); + } + + g_object_thaw_notify(G_OBJECT(m_frame)); } void FrameLoaderClient::dispatchDidFinishDocumentLoad() @@ -746,51 +820,57 @@ void FrameLoaderClient::dispatchDidFailLoad(const ResourceError&) g_signal_emit_by_name(m_frame, "load-done", false); } -void FrameLoaderClient::download(ResourceHandle*, const ResourceRequest&, const ResourceRequest&, const ResourceResponse&) +void FrameLoaderClient::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest&, const ResourceResponse&) { - notImplemented(); + // FIXME: We could reuse the same handle here, but when I tried + // implementing that the main load would fail and stop, so I have + // simplified this case for now. + handle->cancel(); + startDownload(request); } ResourceError FrameLoaderClient::cancelledError(const ResourceRequest&) { notImplemented(); - return ResourceError(); + ResourceError error("", 0, "", ""); + error.setIsCancellation(true); + return error; } ResourceError FrameLoaderClient::blockedError(const ResourceRequest&) { notImplemented(); - return ResourceError(); + return ResourceError("", 0, "", ""); } ResourceError FrameLoaderClient::cannotShowURLError(const ResourceRequest&) { notImplemented(); - return ResourceError(); + return ResourceError("", 0, "", ""); } ResourceError FrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest&) { notImplemented(); - return ResourceError(); + return ResourceError("", 0, "", ""); } ResourceError FrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse&) { notImplemented(); - return ResourceError(); + return ResourceError("", 0, "", ""); } ResourceError FrameLoaderClient::fileDoesNotExistError(const ResourceResponse&) { notImplemented(); - return ResourceError(); + return ResourceError("", 0, "", ""); } ResourceError FrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse&) { notImplemented(); - return ResourceError(); + return ResourceError("", 0, "", ""); } bool FrameLoaderClient::shouldFallBack(const ResourceError&) @@ -832,9 +912,23 @@ void FrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceErro } } -void FrameLoaderClient::startDownload(const ResourceRequest&) +void FrameLoaderClient::startDownload(const ResourceRequest& request) { - notImplemented(); + WebKitNetworkRequest* networkRequest = webkit_network_request_new(request.url().string().utf8().data()); + WebKitDownload* download = webkit_download_new(networkRequest); + g_object_unref(networkRequest); + + WebKitWebView* view = getViewFromFrame(m_frame); + gboolean handled; + g_signal_emit_by_name(view, "download-requested", download, &handled); + + if (!handled) { + webkit_download_cancel(download); + g_object_unref(download); + return; + } + + webkit_download_start(download); } void FrameLoaderClient::updateGlobalHistory() @@ -842,7 +936,7 @@ void FrameLoaderClient::updateGlobalHistory() notImplemented(); } -void FrameLoaderClient::updateGlobalHistoryForRedirectWithoutHistoryItem() +void FrameLoaderClient::updateGlobalHistoryRedirectLinks() { notImplemented(); } @@ -865,7 +959,7 @@ void FrameLoaderClient::transitionToCommittedForNewPage() Frame* frame = core(m_frame); ASSERT(frame); - WebCore::FrameLoaderClient::transitionToCommittedForNewPage(frame, size, backgroundColor, transparent, IntSize(), false); + frame->createView(size, backgroundColor, transparent, IntSize(), false); // We need to do further manipulation on the FrameView if it was the mainFrame if (frame != frame->page()->mainFrame()) diff --git a/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h b/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h index 82286e8..cb4786d 100644 --- a/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h +++ b/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h @@ -109,11 +109,12 @@ namespace WebKit { virtual PassRefPtr<WebCore::Frame> createFrame(const WebCore::KURL& url, const WebCore::String& name, WebCore::HTMLFrameOwnerElement* ownerElement, const WebCore::String& referrer, bool allowsScrolling, int marginWidth, int marginHeight); - virtual WebCore::Widget* createPlugin(const WebCore::IntSize&, WebCore::Element*, const WebCore::KURL&, const WTF::Vector<WebCore::String>&, const WTF::Vector<WebCore::String>&, const WebCore::String&, bool); + virtual WebCore::Widget* createPlugin(const WebCore::IntSize&, WebCore::HTMLPlugInElement*, const WebCore::KURL&, const WTF::Vector<WebCore::String>&, const WTF::Vector<WebCore::String>&, const WebCore::String&, bool); virtual void redirectDataToPlugin(WebCore::Widget* pluginWidget); - virtual WebCore::Widget* createJavaAppletWidget(const WebCore::IntSize&, WebCore::Element*, const WebCore::KURL& baseURL, const WTF::Vector<WebCore::String>& paramNames, const WTF::Vector<WebCore::String>& paramValues); + virtual WebCore::Widget* createJavaAppletWidget(const WebCore::IntSize&, WebCore::HTMLAppletElement*, const WebCore::KURL& baseURL, const WTF::Vector<WebCore::String>& paramNames, const WTF::Vector<WebCore::String>& paramValues); virtual WebCore::String overrideMediaType() const; virtual void windowObjectCleared(); + virtual void documentElementAvailable(); virtual void didPerformFirstNavigation() const; virtual void registerForIconNotification(bool); @@ -131,7 +132,7 @@ namespace WebKit { virtual void finishedLoading(WebCore::DocumentLoader*); virtual void updateGlobalHistory(); - virtual void updateGlobalHistoryForRedirectWithoutHistoryItem(); + virtual void updateGlobalHistoryRedirectLinks(); virtual bool shouldGoToHistoryItem(WebCore::HistoryItem*) const; virtual WebCore::ResourceError cancelledError(const WebCore::ResourceRequest&); diff --git a/WebKit/gtk/WebCoreSupport/InspectorClientGtk.cpp b/WebKit/gtk/WebCoreSupport/InspectorClientGtk.cpp index ba3721a..faa3e28 100644 --- a/WebKit/gtk/WebCoreSupport/InspectorClientGtk.cpp +++ b/WebKit/gtk/WebCoreSupport/InspectorClientGtk.cpp @@ -104,6 +104,12 @@ String InspectorClient::localizedStringsURL() return String(); } +String InspectorClient::hiddenPanels() +{ + notImplemented(); + return String(); +} + void InspectorClient::showWindow() { if (!m_webView) diff --git a/WebKit/gtk/WebCoreSupport/InspectorClientGtk.h b/WebKit/gtk/WebCoreSupport/InspectorClientGtk.h index 4fba55d..43894b3 100644 --- a/WebKit/gtk/WebCoreSupport/InspectorClientGtk.h +++ b/WebKit/gtk/WebCoreSupport/InspectorClientGtk.h @@ -52,6 +52,8 @@ namespace WebKit { virtual WebCore::String localizedStringsURL(); + virtual WebCore::String hiddenPanels(); + virtual void showWindow(); virtual void closeWindow(); diff --git a/WebKit/gtk/docs/webkitgtk-docs.sgml b/WebKit/gtk/docs/webkitgtk-docs.sgml new file mode 100644 index 0000000..655a991 --- /dev/null +++ b/WebKit/gtk/docs/webkitgtk-docs.sgml @@ -0,0 +1,41 @@ +<?xml version="1.0"?> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"> +<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude"> + <bookinfo> + <title>webkitgtk Reference Manual</title> + <releaseinfo> + for webkitgtk [VERSION] + The latest version of this documentation can be found on-line at + <ulink role="online-location" url="http://[SERVER]/webkitgtk/index.html">http://[SERVER]/webkitgtk/</ulink>. + </releaseinfo> + </bookinfo> + + <chapter> + <title>Class Overview</title> + <xi:include href="xml/webkitwebview.xml"/> + <xi:include href="xml/webkitwebframe.xml"/> + <xi:include href="xml/webkitwebsettings.xml"/> + <xi:include href="xml/webkitwebbackforwardlist.xml"/> + <xi:include href="xml/webkitwebhistoryitem.xml"/> + <xi:include href="xml/webkitnetworkrequest.xml"/> + <xi:include href="xml/webkitwebinspector.xml"/> + <xi:include href="xml/webkitwebwindowfeatures.xml"/> + </chapter> + + <index id="index-all"> + <title>Index</title> + </index> + <index id="index-deprecated" role="deprecated"> + <title>Index of deprectaed symbols</title> + </index> + <index id="index-1.0.1" role="1.0.1"> + <title>Index of new symbols in 1.0.1</title> + </index> + <index id="index-1.0.2" role="1.0.2"> + <title>Index of new symbols in 1.0.2</title> + </index> + <index id="index-1.0.3" role="1.0.3"> + <title>Index of new symbols in 1.0.3</title> + </index> +</book> diff --git a/WebKit/gtk/docs/webkitgtk-overrides.txt b/WebKit/gtk/docs/webkitgtk-overrides.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/WebKit/gtk/docs/webkitgtk-overrides.txt diff --git a/WebKit/gtk/docs/webkitgtk-sections.txt b/WebKit/gtk/docs/webkitgtk-sections.txt new file mode 100644 index 0000000..d20bc7a --- /dev/null +++ b/WebKit/gtk/docs/webkitgtk-sections.txt @@ -0,0 +1,275 @@ +<SECTION> +<FILE>webkitwebsettings</FILE> +<TITLE>WebKitWebSettings</TITLE> +WebKitWebSettings +webkit_web_settings_copy +webkit_web_settings_new +<SUBSECTION Standard> +WEBKIT_WEB_SETTINGS +WEBKIT_IS_WEB_SETTINGS +WEBKIT_TYPE_WEB_SETTINGS +WEBKIT_WEB_SETTINGS_CLASS +WEBKIT_IS_WEB_SETTINGS_CLASS +WEBKIT_WEB_SETTINGS_GET_CLASS +<SUBSECTION Private> +webkit_web_settings_get_type +WebKitWebSettingsPrivate +WebKitWebSettings +WebKitWebSettingsClass +</SECTION> + +<SECTION> +<FILE>webkitwebbackforwardlist</FILE> +<TITLE>WebKitWebBackForwardList</TITLE> +WebKitWebBackForwardList +webkit_web_back_forward_list_contains_item +webkit_web_back_forward_list_get_back_item +webkit_web_back_forward_list_get_back_length +webkit_web_back_forward_list_get_back_list_with_limit +webkit_web_back_forward_list_get_current_item +webkit_web_back_forward_list_get_forward_item +webkit_web_back_forward_list_get_forward_length +webkit_web_back_forward_list_get_forward_list_with_limit +webkit_web_back_forward_list_get_limit +webkit_web_back_forward_list_get_nth_item +webkit_web_back_forward_list_go_back +webkit_web_back_forward_list_go_forward +webkit_web_back_forward_list_go_to_item +webkit_web_back_forward_list_new_with_web_view +webkit_web_back_forward_list_set_limit +<SUBSECTION Standard> +WEBKIT_WEB_BACK_FORWARD_LIST +WEBKIT_IS_WEB_BACK_FORWARD_LIST +WEBKIT_TYPE_WEB_BACK_FORWARD_LIST +WEBKIT_WEB_BACK_FORWARD_LIST_CLASS +WEBKIT_IS_WEB_BACK_FORWARD_LIST_CLASS +WEBKIT_WEB_BACK_FORWARD_LIST_GET_CLASS +<SUBSECTION Private> +WebKitWebBackForwardListPrivate +webkit_web_back_forward_list_get_type +WebKitWebBackForwardList +WebKitWebBackForwardListClass +</SECTION> + +<SECTION> +<FILE>webkitwebhistoryitem</FILE> +<TITLE>WebKitWebHistoryItem</TITLE> +WebKitWebHistoryItem +webkit_web_history_item_get_alternate_title +webkit_web_history_item_get_last_visited_time +webkit_web_history_item_get_original_uri +webkit_web_history_item_get_title +webkit_web_history_item_get_uri +webkit_web_history_item_new +webkit_web_history_item_new_with_data +webkit_web_history_item_set_alternate_title +<SUBSECTION Standard> +WEBKIT_WEB_HISTORY_ITEM +WEBKIT_IS_WEB_HISTORY_ITEM +WEBKIT_TYPE_WEB_HISTORY_ITEM +WEBKIT_WEB_HISTORY_ITEM_CLASS +WEBKIT_IS_WEB_HISTORY_ITEM_CLASS +WEBKIT_WEB_HISTORY_ITEM_GET_CLASS +<SUBSECTION Private> +webkit_web_history_item_get_type +WebKitWebHistoryItemPrivate +WebKitWebHistoryItem +WebKitWebHistoryItemClass +</SECTION> + +<SECTION> +<FILE>webkitwebframe</FILE> +<TITLE>WebKitWebFrame</TITLE> +WebKitWebFrame +webkit_web_frame_find_frame +webkit_web_frame_get_global_context +webkit_web_frame_get_name +webkit_web_frame_get_parent +webkit_web_frame_get_title +webkit_web_frame_get_uri +webkit_web_frame_get_web_view +webkit_web_frame_load_request +webkit_web_frame_new +webkit_web_frame_reload +webkit_web_frame_stop_loading +<SUBSECTION Standard> +WEBKIT_WEB_FRAME +WEBKIT_IS_WEB_FRAME +WEBKIT_TYPE_WEB_FRAME +WEBKIT_WEB_FRAME_CLASS +WEBKIT_IS_WEB_FRAME_CLASS +WEBKIT_WEB_FRAME_GET_CLASS +<SUBSECTION Private> +WEBKIT_WEB_FRAME_GET_PRIVATE +WebKitWebFramePrivate +webkit_web_frame_get_type +WebKitWebFrame +WebKitWebFrameClass +</SECTION> + +<SECTION> +<FILE>webkitwebinspector</FILE> +<TITLE>WebKitWebInspector</TITLE> +WebKitWebInspector +webkit_web_inspector_get_inspected_uri +webkit_web_inspector_get_web_view +<SUBSECTION Standard> +WEBKIT_WEB_INSPECTOR +WEBKIT_IS_WEB_INSPECTOR +WEBKIT_TYPE_WEB_INSPECTOR +WEBKIT_WEB_INSPECTOR_CLASS +WEBKIT_IS_WEB_INSPECTOR_CLASS +WEBKIT_WEB_INSPECTOR_GET_CLASS +<SUBSECTION Private> +webkit_web_inspector_get_type +WebKitWebInspectorPrivate +WebKitWebInspector +WebKitWebInspectorClass +</SECTION> + +<SECTION> +<FILE>webkitnetworkrequest</FILE> +<TITLE>WebKitNetworkRequest</TITLE> +WebKitNetworkRequest +webkit_network_request_get_uri +<SUBSECTION Standard> +WEBKIT_NETWORK_REQUEST +WEBKIT_IS_NETWORK_REQUEST +WEBKIT_TYPE_NETWORK_REQUEST +WEBKIT_NETWORK_REQUEST_CLASS +WEBKIT_IS_NETWORK_REQUEST_CLASS +WEBKIT_NETWORK_REQUEST_GET_CLASS +<SUBSECTION Private> +webkit_network_request_get_type +webkit_network_request_new +webkit_network_request_set_uri +WebKitNetworkRequestPrivate +WebKitNetworkRequest +WebKitNetworkRequestClass +</SECTION> + +<SECTION> +<FILE>webkitwebview</FILE> +WebKitNavigationResponse +WebKitWebViewTargetInfo +<TITLE>WebKitWebView</TITLE> +WebKitWebView +webkit_web_view_can_copy_clipboard +webkit_web_view_can_cut_clipboard +webkit_web_view_can_go_back +webkit_web_view_can_go_back_or_forward +webkit_web_view_can_go_forward +webkit_web_view_can_paste_clipboard +webkit_web_view_copy_clipboard +webkit_web_view_cut_clipboard +webkit_web_view_delete_selection +webkit_web_view_execute_script +webkit_web_view_get_back_forward_list +webkit_web_view_get_copy_target_list +webkit_web_view_get_editable +webkit_web_view_get_focused_frame +webkit_web_view_get_full_content_zoom +webkit_web_view_get_inspector +webkit_web_view_get_main_frame +webkit_web_view_get_paste_target_list +webkit_web_view_get_settings +webkit_web_view_get_transparent +webkit_web_view_get_zoom_level +webkit_web_view_go_back +webkit_web_view_go_back_or_forward +webkit_web_view_go_forward +webkit_web_view_go_to_back_forward_item +webkit_web_view_has_selection +webkit_web_view_load_html_string +webkit_web_view_load_string +webkit_web_view_mark_text_matches +webkit_web_view_new +webkit_web_view_open +webkit_web_view_paste_clipboard +webkit_web_view_reload +webkit_web_view_search_text +webkit_web_view_select_all +webkit_web_view_set_editable +webkit_web_view_set_full_content_zoom +webkit_web_view_set_highlight_text_matches +webkit_web_view_set_maintains_back_forward_list +webkit_web_view_set_settings +webkit_web_view_set_transparent +webkit_web_view_set_zoom_level +webkit_web_view_stop_loading +webkit_web_view_target_info_get_type +webkit_web_view_unmark_text_matches +webkit_web_view_zoom_in +webkit_web_view_zoom_out +webkit_web_view_get_window_features +<SUBSECTION Standard> +WEBKIT_WEB_VIEW +WEBKIT_IS_WEB_VIEW +WEBKIT_TYPE_WEB_VIEW +WEBKIT_WEB_VIEW_CLASS +WEBKIT_IS_WEB_VIEW_CLASS +WEBKIT_WEB_VIEW_GET_CLASS +<SUBSECTION Private> +webkit_web_view_set_window_features +webkit_web_view_get_type +WebKitWebViewPrivate +WebKitWebView +WebKitWebViewClass +WEBKIT_WEB_VIEW_GET_PRIVATE +</SECTION> + +<SECTION> +<FILE>webkitwebwindowfeatures</FILE> +<TITLE>WebKitWebWindowFeatures</TITLE> +WebKitWebWindowFeatures +webkit_web_window_features_equal +webkit_web_window_features_new +<SUBSECTION Standard> +WEBKIT_IS_WEB_WINDOW_FEATURES +WEBKIT_IS_WEB_WINDOW_FEATURES_CLASS +WEBKIT_TYPE_WEB_WINDOW_FEATURES +WEBKIT_WEB_WINDOW_FEATURES +WEBKIT_WEB_WINDOW_FEATURES_CLASS +WEBKIT_WEB_WINDOW_FEATURES_GET_CLASS +<SUBSECTION Private> +webkit_web_window_features_get_type +WebKitWebWindowFeatures +WebKitWebWindowFeaturesClass +WebKitWebWindowFeaturesPrivate +</SECTION> + +<SECTION> +<FILE>webkit</FILE> +webkit_init +</SECTION> + +<SECTION> +<FILE>webkitprivate</FILE> +getViewFromFrame +kit +WEBKIT_PARAM_READABLE +WEBKIT_PARAM_READWRITE +webkit_web_frame_init_with_web_view +webkit_web_history_item_new_with_core_item +webkit_web_inspector_set_inspector_client +webkit_web_inspector_set_web_view +webkit_web_inspector_set_inspected_uri +</SECTION> + +<SECTION> +<FILE>webkitdefines</FILE> +WEBKIT_API +webkit_navigation_response_get_type +WEBKIT_OBSOLETE_API +WEBKIT_CHECK_VERSION +WEBKIT_MAJOR_VERSION +WEBKIT_MICRO_VERSION +WEBKIT_MINOR_VERSION +WEBKIT_TYPE_NAVIGATION_RESPONSE +WEBKIT_TYPE_WEB_VIEW_TARGET_INFO +webkit_check_version +webkit_major_version +webkit_micro_version +webkit_minor_version +</SECTION> + diff --git a/WebKit/gtk/docs/webkitgtk.types b/WebKit/gtk/docs/webkitgtk.types new file mode 100644 index 0000000..b8ed5be --- /dev/null +++ b/WebKit/gtk/docs/webkitgtk.types @@ -0,0 +1,12 @@ +#include <webkit/webkit.h> + +webkit_network_request_get_type +webkit_web_back_forward_list_get_type +webkit_web_history_item_get_type +webkit_web_inspector_get_type +webkit_web_settings_get_type +webkit_web_view_get_type +webkit_navigation_response_get_type +webkit_web_view_target_info_get_type +webkit_web_window_features_get_type + diff --git a/WebKit/gtk/tests/testwebbackforwardlist.c b/WebKit/gtk/tests/testwebbackforwardlist.c new file mode 100644 index 0000000..8d53c3e --- /dev/null +++ b/WebKit/gtk/tests/testwebbackforwardlist.c @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2008 Holger Hans Peter Freyther + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <glib.h> +#include <gtk/gtk.h> +#include <webkit/webkit.h> + +#if GLIB_CHECK_VERSION(2, 16, 0) && GTK_CHECK_VERSION(2, 14, 0) + +static void test_webkit_web_history_item_lifetime(void) +{ + WebKitWebView* webView; + WebKitWebBackForwardList* backForwardList; + WebKitWebHistoryItem* currentItem; + WebKitWebHistoryItem* forwardItem; + WebKitWebHistoryItem* backItem; + WebKitWebHistoryItem* nthItem; + WebKitWebHistoryItem* item1; + WebKitWebHistoryItem* item2; + WebKitWebHistoryItem* item3; + WebKitWebHistoryItem* item4; + GList* backList = NULL; + GList* forwardList = NULL; + g_test_bug("19898"); + + webView = WEBKIT_WEB_VIEW(webkit_web_view_new()); + g_object_ref_sink(webView); + backForwardList = webkit_web_view_get_back_forward_list(webView); + g_assert_cmpint(G_OBJECT(backForwardList)->ref_count, ==, 1); + + /* add test items */ + item1 = webkit_web_history_item_new_with_data("http://example.com/1/", "Site 1"); + webkit_web_back_forward_list_add_item(backForwardList, item1); + + item2 = webkit_web_history_item_new_with_data("http://example.com/2/", "Site 2"); + webkit_web_back_forward_list_add_item(backForwardList, item2); + + item3 = webkit_web_history_item_new_with_data("http://example.com/3/", "Site 3"); + webkit_web_back_forward_list_add_item(backForwardList, item3); + + item4 = webkit_web_history_item_new_with_data("http://example.com/4/", "Site 4"); + webkit_web_back_forward_list_add_item(backForwardList, item4); + + /* make sure these functions don't add unnecessary ref to the history item */ + backItem = webkit_web_back_forward_list_get_back_item(backForwardList); + g_object_ref(backItem); + g_assert_cmpint(G_OBJECT(backItem)->ref_count, ==, 2); + g_object_unref(backItem); + g_assert_cmpint(G_OBJECT(backItem)->ref_count, ==, 1); + + currentItem = webkit_web_back_forward_list_get_current_item(backForwardList); + g_object_ref(currentItem); + g_assert_cmpint(G_OBJECT(currentItem)->ref_count, ==, 2); + g_object_unref(currentItem); + g_assert_cmpint(G_OBJECT(currentItem)->ref_count, ==, 1); + + webkit_web_back_forward_list_go_to_item(backForwardList, item2); + forwardItem = webkit_web_back_forward_list_get_forward_item(backForwardList); + g_object_ref(forwardItem); + g_assert_cmpint(G_OBJECT(forwardItem)->ref_count, ==, 2); + g_object_unref(forwardItem); + g_assert_cmpint(G_OBJECT(forwardItem)->ref_count, ==, 1); + + nthItem = webkit_web_back_forward_list_get_nth_item(backForwardList, 1); + g_object_ref(nthItem); + g_assert_cmpint(G_OBJECT(nthItem)->ref_count, ==, 2); + g_object_unref(nthItem); + g_assert_cmpint(G_OBJECT(nthItem)->ref_count, ==, 1); + + backList = webkit_web_back_forward_list_get_back_list_with_limit(backForwardList, 5); + for (; backList; backList = backList->next) + g_assert_cmpint(G_OBJECT(backList->data)->ref_count, ==, 1); + + forwardList = webkit_web_back_forward_list_get_forward_list_with_limit(backForwardList, 5); + for (; forwardList; forwardList = forwardList->next) + g_assert_cmpint(G_OBJECT(forwardList->data)->ref_count, ==, 1); + + g_list_free(forwardList); + g_list_free(backList); + g_object_unref(item1); + g_object_unref(item2); + g_object_unref(item3); + g_object_unref(item4); + + g_object_ref(backForwardList); + g_object_unref(webView); + + g_assert_cmpint(G_OBJECT(backForwardList)->ref_count, ==, 1); + g_object_unref(backForwardList); +} + +static void test_webkit_web_back_forward_list_order(void) +{ + WebKitWebView* webView; + WebKitWebBackForwardList* webBackForwardList; + WebKitWebHistoryItem* item1; + WebKitWebHistoryItem* item2; + WebKitWebHistoryItem* item3; + WebKitWebHistoryItem* item4; + WebKitWebHistoryItem* currentItem; + GList* backList = NULL; + GList* forwardList = NULL; + g_test_bug("22694"); + + webView = WEBKIT_WEB_VIEW(webkit_web_view_new()); + g_object_ref_sink(webView); + + webkit_web_view_set_maintains_back_forward_list(webView, TRUE); + webBackForwardList = webkit_web_view_get_back_forward_list(webView); + g_assert(webBackForwardList); + + // Check that there is no item. + g_assert(!webkit_web_back_forward_list_get_current_item(webBackForwardList)); + g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0); + g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0); + g_assert(!webkit_web_view_can_go_forward(webView)); + g_assert(!webkit_web_view_can_go_back(webView)); + + // Add a new items + item1 = webkit_web_history_item_new_with_data("http://example.com/1/", "Site 1"); + webkit_web_back_forward_list_add_item(webBackForwardList, item1); + g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, item1)); + + item2 = webkit_web_history_item_new_with_data("http://example.com/2/", "Site 2"); + webkit_web_back_forward_list_add_item(webBackForwardList, item2); + g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, item2)); + + item3 = webkit_web_history_item_new_with_data("http://example.com/3/", "Site 3"); + webkit_web_back_forward_list_add_item(webBackForwardList, item3); + g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, item3)); + + item4 = webkit_web_history_item_new_with_data("http://example.com/4/", "Site 4"); + webkit_web_back_forward_list_add_item(webBackForwardList, item4); + g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, item4)); + + // check the back list order + backList = webkit_web_back_forward_list_get_back_list_with_limit(webBackForwardList, 5); + g_assert(backList); + + currentItem = WEBKIT_WEB_HISTORY_ITEM(backList->data); + g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/3/"); + g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 3"); + backList = backList->next; + + currentItem = WEBKIT_WEB_HISTORY_ITEM(backList->data); + g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/2/"); + g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 2"); + backList = backList->next; + + currentItem = WEBKIT_WEB_HISTORY_ITEM(backList->data); + g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/1/"); + g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 1"); + g_list_free(backList); + + // check the forward list order + g_assert(webkit_web_view_go_to_back_forward_item(webView, item1)); + forwardList = webkit_web_back_forward_list_get_forward_list_with_limit(webBackForwardList,5); + g_assert(forwardList); + + currentItem = WEBKIT_WEB_HISTORY_ITEM(forwardList->data); + g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/4/"); + g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 4"); + forwardList = forwardList->next; + + currentItem = WEBKIT_WEB_HISTORY_ITEM(forwardList->data); + g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/3/"); + g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 3"); + forwardList = forwardList->next; + + currentItem = WEBKIT_WEB_HISTORY_ITEM(forwardList->data); + g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/2/"); + g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 2"); + + g_object_unref(item1); + g_object_unref(item2); + g_object_unref(item3); + g_object_unref(item4); + g_list_free(forwardList); + g_object_unref(webView); +} + +static void test_webkit_web_back_forward_list_add_item(void) +{ + WebKitWebView* webView; + WebKitWebBackForwardList* webBackForwardList; + WebKitWebHistoryItem* addItem1; + WebKitWebHistoryItem* addItem2; + WebKitWebHistoryItem* backItem; + WebKitWebHistoryItem* currentItem; + g_test_bug("22988"); + + webView = WEBKIT_WEB_VIEW(webkit_web_view_new()); + g_object_ref_sink(webView); + + webkit_web_view_set_maintains_back_forward_list(webView, TRUE); + webBackForwardList = webkit_web_view_get_back_forward_list(webView); + g_assert(webBackForwardList); + + // Check that there is no item. + g_assert(!webkit_web_back_forward_list_get_current_item(webBackForwardList)); + g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0); + g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0); + g_assert(!webkit_web_view_can_go_forward(webView)); + g_assert(!webkit_web_view_can_go_back(webView)); + + // Add a new item + addItem1 = webkit_web_history_item_new_with_data("http://example.com/", "Added site"); + webkit_web_back_forward_list_add_item(webBackForwardList, addItem1); + g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, addItem1)); + + // Check that the added item is the current item. + currentItem = webkit_web_back_forward_list_get_current_item(webBackForwardList); + g_assert(currentItem); + g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0); + g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0); + g_assert(!webkit_web_view_can_go_forward(webView)); + g_assert(!webkit_web_view_can_go_back(webView)); + g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/"); + g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Added site"); + + // Add another item. + addItem2 = webkit_web_history_item_new_with_data("http://example.com/2/", "Added site 2"); + webkit_web_back_forward_list_add_item(webBackForwardList, addItem2); + g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, addItem2)); + g_object_unref(addItem2); + + // Check that the added item is new current item. + currentItem = webkit_web_back_forward_list_get_current_item(webBackForwardList); + g_assert(currentItem); + g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0); + g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 1); + g_assert(!webkit_web_view_can_go_forward(webView)); + g_assert(webkit_web_view_can_go_back(webView)); + g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/2/"); + g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Added site 2"); + + backItem = webkit_web_back_forward_list_get_back_item(webBackForwardList); + g_assert(backItem); + g_assert_cmpstr(webkit_web_history_item_get_uri(backItem), ==, "http://example.com/"); + g_assert_cmpstr(webkit_web_history_item_get_title(backItem), ==, "Added site"); + + // Go to the first added item. + g_assert(webkit_web_view_go_to_back_forward_item(webView, addItem1)); + g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 1); + g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0); + g_assert(webkit_web_view_can_go_forward(webView)); + g_assert(!webkit_web_view_can_go_back(webView)); + + g_object_unref(addItem1); + g_object_unref(webView); +} + +int main(int argc, char** argv) +{ + g_thread_init(NULL); + gtk_test_init(&argc, &argv, NULL); + + g_test_bug_base("https://bugs.webkit.org/"); + g_test_add_func("/webkit/webbackforwardlist/add_item", test_webkit_web_back_forward_list_add_item); + g_test_add_func("/webkit/webbackforwardlist/list_order", test_webkit_web_back_forward_list_order); + g_test_add_func("/webkit/webhistoryitem/lifetime", test_webkit_web_history_item_lifetime); + return g_test_run (); +} + +#else +int main(int argc, char** argv) +{ + g_critical("You will need at least glib-2.16.0 and gtk-2.14.0 to run the unit tests. Doing nothing now."); + return 0; +} + +#endif diff --git a/WebKit/gtk/tests/testwebframe.c b/WebKit/gtk/tests/testwebframe.c new file mode 100644 index 0000000..e2da29c --- /dev/null +++ b/WebKit/gtk/tests/testwebframe.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2008 Holger Hans Peter Freyther + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <glib.h> +#include <gtk/gtk.h> +#include <webkit/webkit.h> + +#if GLIB_CHECK_VERSION(2, 16, 0) && GTK_CHECK_VERSION(2, 14, 0) + +static void test_webkit_web_frame_create_destroy(void) +{ + WebKitWebView* webView; + g_test_bug("21837"); + + webView = WEBKIT_WEB_VIEW(webkit_web_view_new()); + g_object_ref_sink(webView); + g_assert_cmpint(G_OBJECT(webView)->ref_count, ==, 1); + + // This crashed with the original version + g_object_unref(webView); +} + +static void test_webkit_web_frame_lifetime(void) +{ + WebKitWebView* webView; + WebKitWebFrame* webFrame; + g_test_bug("21837"); + + webView = WEBKIT_WEB_VIEW(webkit_web_view_new()); + g_object_ref_sink(webView); + g_assert_cmpint(G_OBJECT(webView)->ref_count, ==, 1); + webFrame = webkit_web_view_get_main_frame(webView); + g_assert_cmpint(G_OBJECT(webFrame)->ref_count, ==, 1); + + // Add dummy reference on the WebKitWebFrame to keep it alive + g_object_ref(webFrame); + g_assert_cmpint(G_OBJECT(webFrame)->ref_count, ==, 2); + + // This crashed with the original version + g_object_unref(webView); + + // Make sure that the frame got deleted as well. We did this + // by adding an extra ref on the WebKitWebFrame and we should + // be the one holding the last reference. + g_assert_cmpint(G_OBJECT(webFrame)->ref_count, ==, 1); + g_object_unref(webFrame); +} + +int main(int argc, char** argv) +{ + g_thread_init(NULL); + gtk_test_init(&argc, &argv, NULL); + + g_test_bug_base("https://bugs.webkit.org/"); + g_test_add_func("/webkit/webview/create_destroy", test_webkit_web_frame_create_destroy); + g_test_add_func("/webkit/webframe/lifetime", test_webkit_web_frame_lifetime); + return g_test_run (); +} + +#else +int main(int argc, char** argv) +{ + g_critical("You will need at least glib-2.16.0 and gtk-2.14.0 to run the unit tests. Doing nothing now."); + return 0; +} + +#endif diff --git a/WebKit/gtk/tests/testwebhistoryitem.c b/WebKit/gtk/tests/testwebhistoryitem.c new file mode 100644 index 0000000..6038c647 --- /dev/null +++ b/WebKit/gtk/tests/testwebhistoryitem.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2009 Jan Michael Alonzo + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <glib.h> +#include <gtk/gtk.h> +#include <webkit/webkit.h> + +#if GLIB_CHECK_VERSION(2, 16, 0) && GTK_CHECK_VERSION(2, 14, 0) + +typedef struct { + WebKitWebHistoryItem* item; +} WebHistoryItemFixture; + +static void web_history_item_fixture_setup(WebHistoryItemFixture* fixture, + gconstpointer data) +{ + fixture->item = webkit_web_history_item_new_with_data("http://example.com/", "Example1"); + g_assert_cmpint(G_OBJECT(fixture->item)->ref_count, == , 2); + g_assert(fixture->item != NULL); +} + +static void web_history_item_fixture_teardown(WebHistoryItemFixture* fixture, + gconstpointer data) +{ + g_assert(fixture->item != NULL); + g_assert_cmpint(G_OBJECT(fixture->item)->ref_count, ==, 2); + g_object_unref(fixture->item); + g_assert_cmpint(G_OBJECT(fixture->item)->ref_count, ==, 1); +} + +static void test_webkit_web_history_item_get_data(WebHistoryItemFixture* fixture, + gconstpointer data) +{ + g_assert_cmpstr(webkit_web_history_item_get_title(fixture->item), ==, "Example1"); + g_assert_cmpstr(webkit_web_history_item_get_uri(fixture->item), ==, "http://example.com/"); +} + +static void test_webkit_web_history_item_alternate_title(WebHistoryItemFixture* fixture, + gconstpointer data) +{ + webkit_web_history_item_set_alternate_title(fixture->item, "Alternate title"); + g_assert_cmpstr(webkit_web_history_item_get_alternate_title(fixture->item), ==, "Alternate title"); +} + +int main(int argc, char** argv) +{ + g_thread_init(NULL); + gtk_test_init(&argc, &argv, NULL); + + g_test_bug_base("https://bugs.webkit.org/"); + g_test_add("/webkit/webhistoryitem/get_data", + WebHistoryItemFixture, 0, web_history_item_fixture_setup, + test_webkit_web_history_item_get_data, web_history_item_fixture_teardown); + g_test_add("/webkit/webhistoryitem/alternate_title", + WebHistoryItemFixture, 0, web_history_item_fixture_setup, + test_webkit_web_history_item_alternate_title, web_history_item_fixture_teardown); + return g_test_run (); +} + +#else +int main(int argc, char** argv) +{ + g_critical("You will need at least glib-2.16.0 and gtk-2.14.0 to run the unit tests. Doing nothing now."); + return 0; +} + +#endif diff --git a/WebKit/gtk/webkit.pc.in b/WebKit/gtk/webkit.pc.in index 0ce6f71..84d6115 100644 --- a/WebKit/gtk/webkit.pc.in +++ b/WebKit/gtk/webkit.pc.in @@ -6,6 +6,6 @@ includedir=@includedir@ Name: WebKit Description: Web content engine for GTK+ Version: @VERSION@ -Requires: gtk+-2.0 +Requires: gtk+-2.0 libsoup-2.4 Libs: -L${libdir} -lwebkit-1.0 Cflags: -I${includedir}/webkit-1.0 diff --git a/WebKit/gtk/webkit/webkit.h b/WebKit/gtk/webkit/webkit.h index 8c868a2..c22165e 100644 --- a/WebKit/gtk/webkit/webkit.h +++ b/WebKit/gtk/webkit/webkit.h @@ -23,7 +23,9 @@ #include <webkit/webkitversion.h> #include <webkit/webkitdefines.h> +#include <webkit/webkitdownload.h> #include <webkit/webkitnetworkrequest.h> +#include <webkit/webkitsoupauthdialog.h> #include <webkit/webkitwebframe.h> #include <webkit/webkitwebsettings.h> #include <webkit/webkitwebinspector.h> diff --git a/WebKit/gtk/webkit/webkitdefines.h b/WebKit/gtk/webkit/webkitdefines.h index f94e710..b0ab5e9 100644 --- a/WebKit/gtk/webkit/webkitdefines.h +++ b/WebKit/gtk/webkit/webkitdefines.h @@ -68,6 +68,9 @@ typedef struct _WebKitWebWindowFeaturesClass WebKitWebWindowFeaturesClass; typedef struct _WebKitWebView WebKitWebView; typedef struct _WebKitWebViewClass WebKitWebViewClass; +typedef struct _WebKitDownload WebKitDownload; +typedef struct _WebKitDownloadClass WebKitDownloadClass; + G_END_DECLS #endif diff --git a/WebKit/gtk/webkit/webkitdownload.cpp b/WebKit/gtk/webkit/webkitdownload.cpp new file mode 100644 index 0000000..4488304 --- /dev/null +++ b/WebKit/gtk/webkit/webkitdownload.cpp @@ -0,0 +1,818 @@ +/* + * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#include "CString.h" +#include "Noncopyable.h" +#include "NotImplemented.h" +#include "ResourceHandleClient.h" +#include "ResourceRequest.h" +#include "ResourceResponse.h" +#include "webkitdownload.h" +#include "webkitenumtypes.h" +#include "webkitmarshal.h" +#include "webkitprivate.h" + +#include <glib/gstdio.h> + +using namespace WebKit; +using namespace WebCore; + +class DownloadClient : Noncopyable, public ResourceHandleClient { + public: + DownloadClient(WebKitDownload*); + + virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&); + virtual void didReceiveData(ResourceHandle*, const char*, int, int); + virtual void didFinishLoading(ResourceHandle*); + virtual void didFail(ResourceHandle*, const ResourceError&); + virtual void wasBlocked(ResourceHandle*); + virtual void cannotShowURL(ResourceHandle*); + + private: + WebKitDownload* m_download; +}; + +extern "C" { + +#define WEBKIT_DOWNLOAD_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_DOWNLOAD, WebKitDownloadPrivate)) + +struct _WebKitDownloadPrivate { + gchar* destinationURI; + gchar* suggestedFilename; + guint currentSize; + GTimer* timer; + WebKitDownloadStatus status; + GFileOutputStream* outputStream; + DownloadClient* downloadClient; + WebKitNetworkRequest* networkRequest; + ResourceResponse* networkResponse; + RefPtr<ResourceHandle> resourceHandle; +}; + +enum { + // Normal signals. + ERROR, + LAST_SIGNAL +}; + +static guint webkit_download_signals[LAST_SIGNAL] = { 0 }; + +enum { + PROP_0, + + PROP_NETWORK_REQUEST, + PROP_DESTINATION_URI, + PROP_SUGGESTED_FILENAME, + PROP_PROGRESS, + PROP_STATUS, + PROP_CURRENT_SIZE, + PROP_TOTAL_SIZE +}; + +G_DEFINE_TYPE(WebKitDownload, webkit_download, G_TYPE_OBJECT); + + +static void webkit_download_set_status(WebKitDownload* download, WebKitDownloadStatus status); + +static void webkit_download_dispose(GObject* object) +{ + WebKitDownload* download = WEBKIT_DOWNLOAD(object); + WebKitDownloadPrivate* priv = download->priv; + + if (priv->outputStream) { + g_object_unref(priv->outputStream); + priv->outputStream = NULL; + } + + if (priv->networkRequest) { + g_object_unref(priv->networkRequest); + priv->networkRequest = NULL; + } + + G_OBJECT_CLASS(webkit_download_parent_class)->dispose(object); +} + +static void webkit_download_finalize(GObject* object) +{ + WebKitDownload* download = WEBKIT_DOWNLOAD(object); + WebKitDownloadPrivate* priv = download->priv; + + // We don't call webkit_download_cancel() because we don't want to emit + // signals when finalizing an object. + if (priv->resourceHandle) { + if (priv->status == WEBKIT_DOWNLOAD_STATUS_STARTED) { + priv->resourceHandle->setClient(0); + priv->resourceHandle->cancel(); + } + priv->resourceHandle.release(); + } + + delete priv->downloadClient; + delete priv->networkResponse; + + // The download object may never have _start called on it, so we + // need to make sure timer is non-NULL. + if (priv->timer) + g_timer_destroy(priv->timer); + + g_free(priv->destinationURI); + g_free(priv->suggestedFilename); + + G_OBJECT_CLASS(webkit_download_parent_class)->finalize(object); +} + +static void webkit_download_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) +{ + WebKitDownload* download = WEBKIT_DOWNLOAD(object); + + switch(prop_id) { + case PROP_NETWORK_REQUEST: + g_value_set_object(value, webkit_download_get_network_request(download)); + break; + case PROP_DESTINATION_URI: + g_value_set_string(value, webkit_download_get_destination_uri(download)); + break; + case PROP_SUGGESTED_FILENAME: + g_value_set_string(value, webkit_download_get_suggested_filename(download)); + break; + case PROP_PROGRESS: + g_value_set_double(value, webkit_download_get_progress(download)); + break; + case PROP_STATUS: + g_value_set_enum(value, webkit_download_get_status(download)); + break; + case PROP_CURRENT_SIZE: + g_value_set_uint64(value, webkit_download_get_current_size(download)); + break; + case PROP_TOTAL_SIZE: + g_value_set_uint64(value, webkit_download_get_total_size(download)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + } +} + +static void webkit_download_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec *pspec) +{ + WebKitDownload* download = WEBKIT_DOWNLOAD(object); + WebKitDownloadPrivate* priv = download->priv; + + switch(prop_id) { + case PROP_NETWORK_REQUEST: + priv->networkRequest = WEBKIT_NETWORK_REQUEST(g_value_dup_object(value)); + // This is safe as network-request is a construct only property and + // suggestedFilename is initially null. + priv->suggestedFilename = g_path_get_basename(webkit_network_request_get_uri(priv->networkRequest)); + break; + case PROP_DESTINATION_URI: + webkit_download_set_destination_uri(download, g_value_get_string(value)); + break; + case PROP_STATUS: + webkit_download_set_status(download, static_cast<WebKitDownloadStatus>(g_value_get_enum(value))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + } +} + +static void webkit_download_class_init(WebKitDownloadClass* downloadClass) +{ + GObjectClass* objectClass = G_OBJECT_CLASS(downloadClass); + objectClass->dispose = webkit_download_dispose; + objectClass->finalize = webkit_download_finalize; + objectClass->get_property = webkit_download_get_property; + objectClass->set_property = webkit_download_set_property; + + /** + * WebKitDownload::error: + * @download: the object on which the signal is emitted + * @current_bytes: the current count of bytes downloaded + * @total_bytes: the total bytes count in the downloaded file, aka file size. + * + * Indicates an error in the download. + * + * Since: 1.1.2 + */ + webkit_download_signals[ERROR] = g_signal_new("error", + G_TYPE_FROM_CLASS(downloadClass), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + 0, + g_signal_accumulator_true_handled, + NULL, + webkit_marshal_BOOLEAN__INT_INT_STRING, + G_TYPE_BOOLEAN, 3, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_STRING); + + // Properties. + + /** + * WebKitDownload:network-request + * + * The #WebKitNetworkRequest instance associated with the download. + * + * Since: 1.1.2 + */ + g_object_class_install_property(objectClass, + PROP_NETWORK_REQUEST, + g_param_spec_object("network-request", + "Network Request", + "The network request for the URI that should be downloaded", + WEBKIT_TYPE_NETWORK_REQUEST, + (GParamFlags)(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY))); + + /** + * WebKitDownload:destination-uri + * + * The URI of the save location for this download. + * + * Since: 1.1.2 + */ + g_object_class_install_property(objectClass, + PROP_DESTINATION_URI, + g_param_spec_string("destination-uri", + "Destination URI", + "The destination URI where to save the file", + "", + WEBKIT_PARAM_READWRITE)); + + /** + * WebKitDownload:suggested-filename + * + * The file name suggested as default when saving + * + * Since: 1.1.2 + */ + g_object_class_install_property(objectClass, + PROP_SUGGESTED_FILENAME, + g_param_spec_string("suggested-filename", + "Suggested Filename", + "The filename suggested as default when saving", + "", + WEBKIT_PARAM_READABLE)); + + /** + * WebKitDownload:progress: + * + * Determines the current progress of the download. + * + * Since: 1.1.2 + */ + g_object_class_install_property(objectClass, PROP_PROGRESS, + g_param_spec_double("progress", + "Progress", + "Determines the current progress of the download", + 0.0, 1.0, 1.0, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitDownload:status: + * + * Determines the current status of the download. + * + * Since: 1.1.2 + */ + g_object_class_install_property(objectClass, PROP_STATUS, + g_param_spec_enum("status", + "Status", + "Determines the current status of the download", + WEBKIT_TYPE_DOWNLOAD_STATUS, + WEBKIT_DOWNLOAD_STATUS_CREATED, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitDownload:current-size + * + * The length of the data already downloaded + * + * Since: 1.1.2 + */ + g_object_class_install_property(objectClass, + PROP_CURRENT_SIZE, + g_param_spec_uint64("current-size", + "Current Size", + "The length of the data already downloaded", + 0, G_MAXUINT64, 0, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitDownload:total-size + * + * The total size of the file + * + * Since: 1.1.2 + */ + g_object_class_install_property(objectClass, + PROP_CURRENT_SIZE, + g_param_spec_uint64("total-size", + "Total Size", + "The total size of the file", + 0, G_MAXUINT64, 0, + WEBKIT_PARAM_READABLE)); + + g_type_class_add_private(downloadClass, sizeof(WebKitDownloadPrivate)); +} + +static void webkit_download_init(WebKitDownload* download) +{ + WebKitDownloadPrivate* priv = WEBKIT_DOWNLOAD_GET_PRIVATE(download); + download->priv = priv; + + priv->downloadClient = new DownloadClient(download); + priv->currentSize = 0; + priv->status = WEBKIT_DOWNLOAD_STATUS_CREATED; +} + +/** + * webkit_download_new: + * @request: a #WebKitNetworkRequest + * + * Creates a new #WebKitDownload object for the given + * #WebKitNetworkRequest object. + * + * Returns: the new #WebKitDownload + * + * Since: 1.1.2 + */ +WebKitDownload* webkit_download_new(WebKitNetworkRequest* request) +{ + g_return_val_if_fail(request, NULL); + + return WEBKIT_DOWNLOAD(g_object_new(WEBKIT_TYPE_DOWNLOAD, "network-request", request, NULL)); +} + +static gboolean webkit_download_open_stream_for_uri(WebKitDownload* download, const gchar* uri, gboolean append=FALSE) +{ + g_return_val_if_fail(uri, FALSE); + + WebKitDownloadPrivate* priv = download->priv; + GFile* file = g_file_new_for_uri(uri); + GError* error = NULL; + + if (append) + priv->outputStream = g_file_append_to(file, G_FILE_CREATE_NONE, NULL, &error); + else + priv->outputStream = g_file_replace(file, NULL, TRUE, G_FILE_CREATE_NONE, NULL, &error); + + g_object_unref(file); + + if (error) { + gboolean handled; + g_signal_emit_by_name(download, "error", 0, WEBKIT_DOWNLOAD_ERROR_DESTINATION, error->message, &handled); + g_error_free(error); + return FALSE; + } + + return TRUE; +} + +static void webkit_download_close_stream(WebKitDownload* download) +{ + WebKitDownloadPrivate* priv = download->priv; + if (priv->outputStream) { + g_object_unref(priv->outputStream); + priv->outputStream = NULL; + } +} + +/** + * webkit_download_start: + * @download: the #WebKitDownload + * + * Initiates the download. Notice that you must have set the + * destination-uri property before calling this method. + * + * Since: 1.1.2 + */ +void webkit_download_start(WebKitDownload* download) +{ + g_return_if_fail(WEBKIT_IS_DOWNLOAD(download)); + + WebKitDownloadPrivate* priv = download->priv; + g_return_if_fail(priv->destinationURI); + g_return_if_fail(priv->status == WEBKIT_DOWNLOAD_STATUS_CREATED); + g_return_if_fail(priv->timer == NULL); + + if (priv->resourceHandle) + priv->resourceHandle->setClient(priv->downloadClient); + else { + // FIXME: Use the actual request object when WebKitNetworkRequest is finished. + ResourceRequest request(webkit_network_request_get_uri(priv->networkRequest)); + priv->resourceHandle = ResourceHandle::create(request, priv->downloadClient, 0, false, false, false); + } + + priv->timer = g_timer_new(); + webkit_download_open_stream_for_uri(download, priv->destinationURI); +} + +/** + * webkit_download_cancel: + * @download: the #WebKitDownload + * + * Cancels the download. Calling this will not free the + * #WebKitDownload object, so you still need to call + * g_object_unref() on it, if you are the owner of a reference. Notice + * that cancelling the download provokes the emission of the + * WebKitDownload::error signal, reporting that the download was + * cancelled. + * + * Since: 1.1.2 + */ +void webkit_download_cancel(WebKitDownload* download) +{ + g_return_if_fail(WEBKIT_IS_DOWNLOAD(download)); + + WebKitDownloadPrivate* priv = download->priv; + + // Cancel may be called even if start was not called, so we need + // to make sure timer is non-NULL. + if (priv->timer) + g_timer_stop(priv->timer); + + if (priv->resourceHandle) + priv->resourceHandle->cancel(); + + webkit_download_set_status(download, WEBKIT_DOWNLOAD_STATUS_CANCELLED); + + gboolean handled; + g_signal_emit_by_name(download, "error", 0, WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER, "User cancelled the download", &handled); +} + +/** + * webkit_download_get_uri: + * @download: the #WebKitDownload + * + * Convenience method to retrieve the URI from the + * #WebKitNetworkRequest which is being downloaded. + * + * Returns: the uri + * + * Since: 1.1.2 + */ +const gchar* webkit_download_get_uri(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), NULL); + + WebKitDownloadPrivate* priv = download->priv; + return webkit_network_request_get_uri(priv->networkRequest); +} + +/** + * webkit_download_get_network_request: + * @download: the #WebKitDownload + * + * Retrieves the #WebKitNetworkRequest object that backs the download + * process. + * + * Returns: the #WebKitNetworkRequest instance + * + * Since: 1.1.2 + */ +WebKitNetworkRequest* webkit_download_get_network_request(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), NULL); + + WebKitDownloadPrivate* priv = download->priv; + return priv->networkRequest; +} + +static void webkit_download_set_response(WebKitDownload* download, const ResourceResponse& response) +{ + // FIXME Use WebKitNetworkResponse when it's merged. + WebKitDownloadPrivate* priv = download->priv; + priv->networkResponse = new ResourceResponse(response); +} + +/** + * webkit_download_get_suggested_filename: + * @download: the #WebKitDownload + * + * Retrieves the filename that was suggested by the server, or the one + * derived by WebKit from the URI. + * + * Returns: the suggested filename + * + * Since: 1.1.2 + */ +const gchar* webkit_download_get_suggested_filename(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), NULL); + + WebKitDownloadPrivate* priv = download->priv; + return priv->suggestedFilename; +} + +/** + * webkit_download_get_destination_uri: + * @download: the #WebKitDownload + * + * Obtains the URI to which the downloaded file will be written. This + * must have been set by the application before calling + * webkit_download_start(), and may be %NULL. + * + * Returns: the destination URI or %NULL + * + * Since: 1.1.2 + */ +const gchar* webkit_download_get_destination_uri(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), NULL); + + WebKitDownloadPrivate* priv = download->priv; + return priv->destinationURI; +} + +/** + * webkit_download_set_destination_uri: + * @download: the #WebKitDownload + * @destination_uri: the destination URI + * + * Defines the URI that should be used to save the downloaded file to. + * + * Since: 1.1.2 + */ +void webkit_download_set_destination_uri(WebKitDownload* download, const gchar* destination_uri) +{ + g_return_if_fail(WEBKIT_IS_DOWNLOAD(download)); + g_return_if_fail(destination_uri); + + WebKitDownloadPrivate* priv = download->priv; + if (priv->destinationURI && !strcmp(priv->destinationURI, destination_uri)) + return; + + if (priv->status != WEBKIT_DOWNLOAD_STATUS_CREATED && priv->status != WEBKIT_DOWNLOAD_STATUS_CANCELLED) { + ASSERT(priv->destinationURI); + + gboolean downloading = priv->outputStream != NULL; + if (downloading) + webkit_download_close_stream(download); + + GFile* src = g_file_new_for_uri(priv->destinationURI); + GFile* dest = g_file_new_for_uri(destination_uri); + GError* error = NULL; + + g_file_move(src, dest, G_FILE_COPY_BACKUP, NULL, NULL, NULL, &error); + + g_object_unref(src); + g_object_unref(dest); + + g_free(priv->destinationURI); + priv->destinationURI = g_strdup(destination_uri); + + if (error) { + gboolean handled; + g_signal_emit_by_name(download, "error", 0, WEBKIT_DOWNLOAD_ERROR_DESTINATION, error->message, &handled); + g_error_free(error); + return; + } + + if (downloading) { + if (!webkit_download_open_stream_for_uri(download, destination_uri, TRUE)) { + webkit_download_cancel(download); + return; + } + } + } else { + g_free(priv->destinationURI); + priv->destinationURI = g_strdup(destination_uri); + } + + // Only notify change if everything went fine. + g_object_notify(G_OBJECT(download), "destination-uri"); +} + +/** + * webkit_download_get_status: + * @download: the #WebKitDownload + * + * Obtains the current status of the download, as a + * #WebKitDownloadStatus. + * + * Returns: the current #WebKitDownloadStatus + * + * Since: 1.1.2 + */ +WebKitDownloadStatus webkit_download_get_status(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), WEBKIT_DOWNLOAD_STATUS_ERROR); + + WebKitDownloadPrivate* priv = download->priv; + return priv->status; +} + +static void webkit_download_set_status(WebKitDownload* download, WebKitDownloadStatus status) +{ + g_return_if_fail(WEBKIT_IS_DOWNLOAD(download)); + + WebKitDownloadPrivate* priv = download->priv; + priv->status = status; + + g_object_notify(G_OBJECT(download), "status"); +} + +/** + * webkit_download_get_total_size: + * @download: the #WebKitDownload + * + * Returns the expected total size of the download. This is expected + * because the server may provide incorrect or missing + * Content-Length. Notice that this may grow over time, as it will be + * always the same as current_size in the cases where current size + * surpasses it. + * + * Returns: the expected total size of the downloaded file + * + * Since: 1.1.2 + */ +guint64 webkit_download_get_total_size(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), 0); + + WebKitDownloadPrivate* priv = download->priv; + if (!priv->networkResponse) + return 0; + + return MAX(priv->currentSize, priv->networkResponse->expectedContentLength()); +} + +/** + * webkit_download_get_current_size: + * @download: the #WebKitDownload + * + * Current already downloaded size. + * + * Returns: the already downloaded size + * + * Since: 1.1.2 + */ +guint64 webkit_download_get_current_size(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), 0); + + WebKitDownloadPrivate* priv = download->priv; + return priv->currentSize; +} + +/** + * webkit_download_get_progress: + * @download: a #WebKitDownload + * + * Determines the current progress of the download. + * + * Returns: a #gdouble ranging from 0.0 to 1.0. + * + * Since: 1.1.2 + */ +gdouble webkit_download_get_progress(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), 1.0); + + WebKitDownloadPrivate* priv = download->priv; + gdouble total_size = (gdouble)priv->networkResponse->expectedContentLength(); + + if (total_size == 0) + return 1.0; + + return ((gdouble)priv->currentSize) / total_size; +} + +/** + * webkit_download_get_elapsed_time: + * @download: a #WebKitDownload + * + * Elapsed time for the download in seconds, including any fractional + * part. If the download is finished, had an error or was cancelled + * this is the time between its start and the event. + * + * Returns: seconds since the download was started, as a #gdouble + * + * Since: 1.1.2 + */ +gdouble webkit_download_get_elapsed_time(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), 0.0); + + WebKitDownloadPrivate* priv = download->priv; + return g_timer_elapsed(priv->timer, NULL); +} + +static void webkit_download_received_data(WebKitDownload* download, const gchar* data, int length) +{ + WebKitDownloadPrivate* priv = download->priv; + + if (priv->currentSize == 0) + webkit_download_set_status(download, WEBKIT_DOWNLOAD_STATUS_STARTED); + + ASSERT(priv->outputStream); + + gsize bytes_written; + GError* error = NULL; + + g_output_stream_write_all(G_OUTPUT_STREAM(priv->outputStream), + data, length, &bytes_written, NULL, &error); + + if (error) { + gboolean handled; + g_signal_emit_by_name(download, "error", 0, WEBKIT_DOWNLOAD_ERROR_DESTINATION, error->message, &handled); + g_error_free(error); + return; + } + + priv->currentSize += length; + g_object_notify(G_OBJECT(download), "current-size"); + + ASSERT(priv->networkResponse); + if (priv->currentSize > priv->networkResponse->expectedContentLength()) + g_object_notify(G_OBJECT(download), "total-size"); + + // FIXME: Throttle the number of updates? Should we remove the + // previous g_object_notify()s if we are going to throttle the + // progress updates? + g_object_notify(G_OBJECT(download), "progress"); +} + +static void webkit_download_finished_loading(WebKitDownload* download) +{ + webkit_download_close_stream(download); + + WebKitDownloadPrivate* priv = download->priv; + + g_timer_stop(priv->timer); + + g_object_notify(G_OBJECT(download), "progress"); + webkit_download_set_status(download, WEBKIT_DOWNLOAD_STATUS_FINISHED); +} + +static void webkit_download_error(WebKitDownload* download, const ResourceError& error) +{ + webkit_download_close_stream(download); + + WebKitDownloadPrivate* priv = download->priv; + + g_timer_stop(priv->timer); + webkit_download_set_status(download, WEBKIT_DOWNLOAD_STATUS_ERROR); + + gboolean handled; + g_signal_emit_by_name(download, "error", 0, WEBKIT_DOWNLOAD_ERROR_NETWORK, error.localizedDescription().utf8().data(), &handled); +} + +DownloadClient::DownloadClient(WebKitDownload* download) + : m_download(download) +{ +} + +void DownloadClient::didReceiveResponse(ResourceHandle*, const ResourceResponse& response) +{ + webkit_download_set_response(m_download, response); +} + +void DownloadClient::didReceiveData(ResourceHandle*, const char* data, int length, int lengthReceived) +{ + webkit_download_received_data(m_download, data, length); +} + +void DownloadClient::didFinishLoading(ResourceHandle*) +{ + webkit_download_finished_loading(m_download); +} + +void DownloadClient::didFail(ResourceHandle*, const ResourceError& error) +{ + webkit_download_error(m_download, error); +} + +void DownloadClient::wasBlocked(ResourceHandle*) +{ + // FIXME: Implement this when we have the new frame loader signals + // and error handling. + notImplemented(); +} + +void DownloadClient::cannotShowURL(ResourceHandle*) +{ + // FIXME: Implement this when we have the new frame loader signals + // and error handling. + notImplemented(); +} + +} diff --git a/WebKit/gtk/webkit/webkitdownload.h b/WebKit/gtk/webkit/webkitdownload.h new file mode 100644 index 0000000..7c86c65 --- /dev/null +++ b/WebKit/gtk/webkit/webkitdownload.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WEBKIT_DOWNLOAD_H +#define WEBKIT_DOWNLOAD_H + +#include <webkit/webkitdefines.h> + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_DOWNLOAD (webkit_download_get_type()) +#define WEBKIT_DOWNLOAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_DOWNLOAD, WebKitDownload)) +#define WEBKIT_DOWNLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_DOWNLOAD, WebKitDownloadClass)) +#define WEBKIT_IS_DOWNLOAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_DOWNLOAD)) +#define WEBKIT_IS_DOWNLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_DOWNLOAD)) +#define WEBKIT_DOWNLOAD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_DOWNLOAD, WebKitDownloadClass)) + +typedef enum { + WEBKIT_DOWNLOAD_STATUS_ERROR = -1, + WEBKIT_DOWNLOAD_STATUS_CREATED = 0, + WEBKIT_DOWNLOAD_STATUS_STARTED, + WEBKIT_DOWNLOAD_STATUS_CANCELLED, + WEBKIT_DOWNLOAD_STATUS_FINISHED +} WebKitDownloadStatus; + +typedef enum { + WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER, + WEBKIT_DOWNLOAD_ERROR_DESTINATION, + WEBKIT_DOWNLOAD_ERROR_NETWORK +} WebKitDownloadError; + +typedef struct _WebKitDownloadPrivate WebKitDownloadPrivate; + +struct _WebKitDownload { + GObject parent_instance; + + WebKitDownloadPrivate *priv; +}; + +struct _WebKitDownloadClass { + GObjectClass parent_class; + + /* Padding for future expansion */ + void (*_webkit_reserved0) (void); + void (*_webkit_reserved1) (void); + void (*_webkit_reserved2) (void); + void (*_webkit_reserved3) (void); +}; + +WEBKIT_API GType +webkit_download_get_type (void); + +WEBKIT_API WebKitDownload* +webkit_download_new (WebKitNetworkRequest *request); + +WEBKIT_API void +webkit_download_start (WebKitDownload *download); + +WEBKIT_API void +webkit_download_cancel (WebKitDownload *download); + +WEBKIT_API const gchar* +webkit_download_get_uri (WebKitDownload *download); + +WEBKIT_API WebKitNetworkRequest* +webkit_download_get_network_request (WebKitDownload *download); + +WEBKIT_API const gchar* +webkit_download_get_suggested_filename (WebKitDownload *download); + +WEBKIT_API const gchar* +webkit_download_get_destination_uri (WebKitDownload *download); + +WEBKIT_API void +webkit_download_set_destination_uri (WebKitDownload *download, + const gchar *destination_uri); + +WEBKIT_API gdouble +webkit_download_get_progress (WebKitDownload *download); + +WEBKIT_API gdouble +webkit_download_get_elapsed_time (WebKitDownload *download); + +WEBKIT_API guint64 +webkit_download_get_total_size (WebKitDownload *download); + +WEBKIT_API guint64 +webkit_download_get_current_size (WebKitDownload *download); + +WEBKIT_API WebKitDownloadStatus +webkit_download_get_status (WebKitDownload *download); + +G_END_DECLS + +#endif diff --git a/WebKit/gtk/webkit/webkitprivate.cpp b/WebKit/gtk/webkit/webkitprivate.cpp index e801981..c4264c9 100644 --- a/WebKit/gtk/webkit/webkitprivate.cpp +++ b/WebKit/gtk/webkit/webkitprivate.cpp @@ -20,8 +20,10 @@ #include "config.h" +#include "webkitsoupauthdialog.h" #include "webkitprivate.h" #include "ChromeClientGtk.h" +#include "Frame.h" #include "FrameLoader.h" #include "FrameLoaderClientGtk.h" #include "Logging.h" @@ -30,6 +32,9 @@ #include "PageGroup.h" #include "Pasteboard.h" #include "PasteboardHelperGtk.h" +#include "ResourceHandle.h" +#include "ResourceHandleClient.h" +#include "ResourceHandleInternal.h" #include <runtime/InitializeThreading.h> #if ENABLE(DATABASE) @@ -96,6 +101,31 @@ WebCore::NavigationType core(WebKitWebNavigationReason type) } /** end namespace WebKit */ +static GtkWidget* currentToplevelCallback(WebKitSoupAuthDialog* feature, SoupMessage* message, gpointer userData) +{ + gpointer messageData = g_object_get_data(G_OBJECT(message), "resourceHandle"); + if (!messageData) + return NULL; + + ResourceHandle* handle = static_cast<ResourceHandle*>(messageData); + if (!handle) + return NULL; + + ResourceHandleInternal* d = handle->getInternal(); + if (!d) + return NULL; + + WebCore::Frame* frame = d->m_frame; + if (!frame) + return NULL; + + GtkWidget* toplevel = gtk_widget_get_toplevel(GTK_WIDGET(frame->page()->chrome()->platformWindow())); + if (GTK_WIDGET_TOPLEVEL(toplevel)) + return toplevel; + else + return NULL; +} + void webkit_init() { static bool isInitialized = false; @@ -121,4 +151,10 @@ void webkit_init() PageGroup::setShouldTrackVisitedLinks(true); Pasteboard::generalPasteboard()->setHelper(new WebKit::PasteboardHelperGtk()); + + SoupSession* session = webkit_get_default_session(); + SoupSessionFeature* authDialog = static_cast<SoupSessionFeature*>(g_object_new(WEBKIT_TYPE_SOUP_AUTH_DIALOG, NULL)); + g_signal_connect(authDialog, "current-toplevel", G_CALLBACK(currentToplevelCallback), NULL); + soup_session_add_feature(session, authDialog); + g_object_unref(authDialog); } diff --git a/WebKit/gtk/webkit/webkitprivate.h b/WebKit/gtk/webkit/webkitprivate.h index ace996d..0b83a11 100644 --- a/WebKit/gtk/webkit/webkitprivate.h +++ b/WebKit/gtk/webkit/webkitprivate.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Holger Hans Peter Freyther + * Copyright (C) 2007, 2008, 2009 Holger Hans Peter Freyther * Copyright (C) 2008 Jan Michael C. Alonzo * Copyright (C) 2008 Collabora Ltd. * @@ -28,6 +28,7 @@ */ #include <webkit/webkitdefines.h> +#include <webkit/webkitdownload.h> #include <webkit/webkitwebview.h> #include <webkit/webkitwebframe.h> #include <webkit/webkitwebpolicydecision.h> @@ -43,10 +44,14 @@ #include "Frame.h" #include "InspectorClientGtk.h" #include "FrameLoaderClient.h" +#include "ResourceHandle.h" +#include "ResourceResponse.h" #include "WindowFeatures.h" #include <glib.h> +class DownloadClient; + namespace WebKit { WebKitWebView* getViewFromFrame(WebKitWebFrame*); @@ -57,7 +62,7 @@ namespace WebKit { WebKitWebView* kit(WebCore::Page*); WebCore::HistoryItem* core(WebKitWebHistoryItem*); - WebKitWebHistoryItem* kit(WebCore::HistoryItem*); + WebKitWebHistoryItem* kit(PassRefPtr<WebCore::HistoryItem>); WebCore::BackForwardList* core(WebKitWebBackForwardList*); @@ -101,6 +106,10 @@ extern "C" { GtkAdjustment* verticalAdjustment; gboolean zoomFullContent; + char* encoding; + char* customEncoding; + + gboolean disposing; }; #define WEBKIT_WEB_FRAME_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_WEB_FRAME, WebKitWebFramePrivate)) @@ -120,11 +129,22 @@ extern "C" { void webkit_web_frame_core_frame_gone(WebKitWebFrame*); + // WebKitWebHistoryItem private WebKitWebHistoryItem* - webkit_web_history_item_new_with_core_item(WebCore::HistoryItem*); + webkit_web_history_item_new_with_core_item(PassRefPtr<WebCore::HistoryItem> historyItem); + + WEBKIT_API G_CONST_RETURN gchar* + webkit_web_history_item_get_target(WebKitWebHistoryItem*); + + WEBKIT_API gboolean + webkit_web_history_item_is_target_item(WebKitWebHistoryItem*); + + WEBKIT_API GList* + webkit_web_history_item_get_children(WebKitWebHistoryItem*); + // end WebKitWebHistoryItem private void - webkit_web_inspector_set_inspector_client(WebKitWebInspector*, WebKit::InspectorClient*); + webkit_web_inspector_set_inspector_client(WebKitWebInspector*, WebCore::Page*); void webkit_web_inspector_set_web_view(WebKitWebInspector *web_inspector, WebKitWebView *web_view); @@ -144,6 +164,10 @@ extern "C" { void webkit_web_policy_decision_cancel (WebKitWebPolicyDecision* decision); + // FIXME: move this functionality into a 'WebKitWebDataSource' once implemented + WEBKIT_API gchar* + webkit_web_frame_get_response_mime_type(WebKitWebFrame* frame); + // FIXME: Move these to webkitwebframe.h once their API has been discussed. WEBKIT_API GSList* diff --git a/WebKit/gtk/webkit/webkitsoupauthdialog.c b/WebKit/gtk/webkit/webkitsoupauthdialog.c new file mode 100644 index 0000000..139000b --- /dev/null +++ b/WebKit/gtk/webkit/webkitsoupauthdialog.c @@ -0,0 +1,347 @@ +/* + * Copyright (C) 2009 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#include <gtk/gtk.h> +#include <libsoup/soup.h> +#if USE(GNOMEKEYRING) +#include <gnome-keyring.h> +#endif + +#include "webkitmarshal.h" +#include "webkitsoupauthdialog.h" + +static void webkit_soup_auth_dialog_session_feature_init(SoupSessionFeatureInterface* feature_interface, gpointer interface_data); +static void attach(SoupSessionFeature* manager, SoupSession* session); +static void detach(SoupSessionFeature* manager, SoupSession* session); + +enum { + CURRENT_TOPLEVEL, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE_WITH_CODE(WebKitSoupAuthDialog, webkit_soup_auth_dialog, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(SOUP_TYPE_SESSION_FEATURE, + webkit_soup_auth_dialog_session_feature_init)) + +static void webkit_soup_auth_dialog_class_init(WebKitSoupAuthDialogClass* klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS(klass); + + signals[CURRENT_TOPLEVEL] = + g_signal_new("current-toplevel", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitSoupAuthDialogClass, current_toplevel), + NULL, NULL, + webkit_marshal_OBJECT__OBJECT, + GTK_TYPE_WIDGET, 1, + SOUP_TYPE_MESSAGE); +} + +static void webkit_soup_auth_dialog_init(WebKitSoupAuthDialog* instance) +{ +} + +static void webkit_soup_auth_dialog_session_feature_init(SoupSessionFeatureInterface *feature_interface, + gpointer interface_data) +{ + feature_interface->attach = attach; + feature_interface->detach = detach; +} + +typedef struct _WebKitAuthData { + SoupMessage* msg; + SoupAuth* auth; + SoupSession* session; + SoupSessionFeature* manager; + GtkWidget* loginEntry; + GtkWidget* passwordEntry; +#if USE(GNOMEKEYRING) + GtkWidget* checkButton; +#endif +} WebKitAuthData; + +static void free_authData(WebKitAuthData* authData) +{ + g_object_unref(authData->msg); + g_slice_free(WebKitAuthData, authData); +} + +#if USE(GNOMEKEYRING) +static void set_password_callback(GnomeKeyringResult result, guint32 val, gpointer user_data) +{ + /* Dummy callback, gnome_keyring_set_network_password does not accept a NULL one */ +} +#endif + +static void response_callback(GtkDialog* dialog, gint response_id, WebKitAuthData* authData) +{ + const char* login; + const char* password; +#if USE(GNOMEKEYRING) + SoupURI* uri; + gboolean storePassword; +#endif + + switch(response_id) { + case GTK_RESPONSE_OK: + login = gtk_entry_get_text(GTK_ENTRY(authData->loginEntry)); + password = gtk_entry_get_text(GTK_ENTRY(authData->passwordEntry)); + soup_auth_authenticate(authData->auth, login, password); + +#if USE(GNOMEKEYRING) + storePassword = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(authData->checkButton)); + if (storePassword) { + uri = soup_message_get_uri(authData->msg); + gnome_keyring_set_network_password(NULL, + login, + soup_auth_get_realm(authData->auth), + uri->host, + NULL, + uri->scheme, + soup_auth_get_scheme_name(authData->auth), + uri->port, + password, + (GnomeKeyringOperationGetIntCallback)set_password_callback, + NULL, + NULL); + } +#endif + default: + break; + } + + soup_session_unpause_message(authData->session, authData->msg); + free_authData(authData); + gtk_widget_destroy(GTK_WIDGET(dialog)); +} + +static GtkWidget * +table_add_entry (GtkWidget* table, + int row, + const char* label_text, + const char* value, + gpointer user_data) +{ + GtkWidget* entry; + GtkWidget* label; + + label = gtk_label_new(label_text); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + + entry = gtk_entry_new(); + gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); + + if (value) + gtk_entry_set_text(GTK_ENTRY(entry), value); + + gtk_table_attach(GTK_TABLE(table), label, + 0, 1, row, row + 1, + GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + gtk_table_attach_defaults(GTK_TABLE(table), entry, + 1, 2, row, row + 1); + + return entry; +} + +static void show_auth_dialog(WebKitAuthData* authData, const char* login, const char* password) +{ + GtkWidget* toplevel; + GtkWidget* widget; + GtkDialog* dialog; + GtkWindow* window; + GtkWidget* entryContainer; + GtkWidget* hbox; + GtkWidget* mainVBox; + GtkWidget* vbox; + GtkWidget* icon; + GtkWidget* table; + GtkWidget* messageLabel; + char* message; + SoupURI* uri; +#if USE(GNOMEKEYRING) + GtkWidget* rememberBox; + GtkWidget* checkButton; +#endif + + /* From GTK+ gtkmountoperation.c, modified and simplified. LGPL 2 license */ + + widget = gtk_dialog_new(); + window = GTK_WINDOW(widget); + dialog = GTK_DIALOG(widget); + + gtk_dialog_add_buttons(dialog, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_OK, + NULL); + + /* Set the dialog up with HIG properties */ + gtk_dialog_set_has_separator(dialog, FALSE); + gtk_container_set_border_width(GTK_CONTAINER (dialog), 5); + gtk_box_set_spacing(GTK_BOX(dialog->vbox), 2); /* 2 * 5 + 2 = 12 */ + gtk_container_set_border_width(GTK_CONTAINER (dialog->action_area), 5); + gtk_box_set_spacing(GTK_BOX(dialog->action_area), 6); + + gtk_window_set_resizable(window, FALSE); + gtk_window_set_title(window, ""); + gtk_window_set_icon_name(window, GTK_STOCK_DIALOG_AUTHENTICATION); + + gtk_dialog_set_default_response(dialog, GTK_RESPONSE_OK); + + /* Get the current toplevel */ + g_signal_emit(authData->manager, signals[CURRENT_TOPLEVEL], 0, authData->msg, &toplevel); + + if (toplevel) + gtk_window_set_transient_for(window, GTK_WINDOW(toplevel)); + + /* Build contents */ + hbox = gtk_hbox_new(FALSE, 12); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); + gtk_box_pack_start(GTK_BOX(dialog->vbox), hbox, TRUE, TRUE, 0); + + icon = gtk_image_new_from_stock(GTK_STOCK_DIALOG_AUTHENTICATION, + GTK_ICON_SIZE_DIALOG); + + gtk_misc_set_alignment(GTK_MISC(icon), 0.5, 0.0); + gtk_box_pack_start(GTK_BOX(hbox), icon, FALSE, FALSE, 0); + + mainVBox = gtk_vbox_new(FALSE, 18); + gtk_box_pack_start(GTK_BOX(hbox), mainVBox, TRUE, TRUE, 0); + + uri = soup_message_get_uri(authData->msg); + message = g_strdup_printf("A username and password are being requested by the site %s", uri->host); + messageLabel = gtk_label_new(message); + g_free(message); + gtk_misc_set_alignment(GTK_MISC(messageLabel), 0.0, 0.5); + gtk_label_set_line_wrap(GTK_LABEL(messageLabel), TRUE); + gtk_box_pack_start(GTK_BOX(mainVBox), GTK_WIDGET(messageLabel), + FALSE, FALSE, 0); + + vbox = gtk_vbox_new(FALSE, 6); + gtk_box_pack_start(GTK_BOX (mainVBox), vbox, FALSE, FALSE, 0); + + /* The table that holds the entries */ + entryContainer = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); + + gtk_alignment_set_padding(GTK_ALIGNMENT(entryContainer), + 0, 0, 0, 0); + + gtk_box_pack_start(GTK_BOX(vbox), entryContainer, + FALSE, FALSE, 0); + + table = gtk_table_new(2, 2, FALSE); + gtk_table_set_col_spacings(GTK_TABLE (table), 12); + gtk_table_set_row_spacings(GTK_TABLE (table), 6); + gtk_container_add(GTK_CONTAINER(entryContainer), table); + + authData->loginEntry = table_add_entry(table, 0, "Username:", + login, NULL); + authData->passwordEntry = table_add_entry(table, 1, "Password:", + password, NULL); + + gtk_entry_set_visibility(GTK_ENTRY(authData->passwordEntry), FALSE); + +#if USE(GNOMEKEYRING) + rememberBox = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (vbox), rememberBox, + FALSE, FALSE, 0); + + checkButton = gtk_check_button_new_with_label("Remember password"); + if (login && password) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkButton), TRUE); + gtk_label_set_line_wrap(GTK_LABEL(gtk_bin_get_child(GTK_BIN(checkButton))), TRUE); + gtk_box_pack_start (GTK_BOX (rememberBox), checkButton, FALSE, FALSE, 0); + authData->checkButton = checkButton; +#endif + + g_signal_connect(dialog, "response", G_CALLBACK(response_callback), authData); + gtk_widget_show_all(widget); +} + +#if USE(GNOMEKEYRING) +static void find_password_callback(GnomeKeyringResult result, GList* list, WebKitAuthData* authData) +{ + GList* p; + const char* login = NULL; + const char* password = NULL; + + for (p = list; p; p = p->next) { + /* FIXME: support multiple logins/passwords ? */ + GnomeKeyringNetworkPasswordData* data = (GnomeKeyringNetworkPasswordData*)p->data; + login = data->user; + password = data->password; + break; + } + + show_auth_dialog(authData, login, password); +} +#endif + +static void session_authenticate(SoupSession* session, SoupMessage* msg, SoupAuth* auth, gboolean retrying, gpointer user_data) +{ + SoupURI* uri; + WebKitAuthData* authData; + SoupSessionFeature* manager = (SoupSessionFeature*)user_data; + + soup_session_pause_message(session, msg); + /* We need to make sure the message sticks around when pausing it */ + g_object_ref(msg); + + uri = soup_message_get_uri(msg); + authData = g_slice_new(WebKitAuthData); + authData->msg = msg; + authData->auth = auth; + authData->session = session; + authData->manager = manager; + + /* + * If we have gnome-keyring let's try to find the password first in the ring. + * Otherwise just show the dialog straight away + */ +#if USE(GNOMEKEYRING) + gnome_keyring_find_network_password(NULL, + soup_auth_get_realm(auth), + uri->host, + NULL, + uri->scheme, + soup_auth_get_scheme_name(auth), + uri->port, + (GnomeKeyringOperationGetListCallback)find_password_callback, + authData, + NULL); +#else + show_auth_dialog(authData, NULL, NULL); +#endif +} + +static void attach(SoupSessionFeature* manager, SoupSession* session) +{ + g_signal_connect(session, "authenticate", G_CALLBACK(session_authenticate), manager); +} + +static void detach(SoupSessionFeature* manager, SoupSession* session) +{ + g_signal_handlers_disconnect_by_func(session, session_authenticate, manager); +} + + diff --git a/WebKit/gtk/webkit/webkitsoupauthdialog.h b/WebKit/gtk/webkit/webkitsoupauthdialog.h new file mode 100644 index 0000000..2c030b4 --- /dev/null +++ b/WebKit/gtk/webkit/webkitsoupauthdialog.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <gtk/gtk.h> +#include <libsoup/soup.h> + +#ifndef WEBKIT_SOUP_AUTH_DIALOG_H +#define WEBKIT_SOUP_AUTH_DIALOG_H 1 + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_SOUP_AUTH_DIALOG (webkit_soup_auth_dialog_get_type ()) +#define WEBKIT_SOUP_AUTH_DIALOG(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), WEBKIT_TYPE_SOUP_AUTH_DIALOG, WebKitSoupAuthDialog)) +#define WEBKIT_SOUP_AUTH_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_SOUP_AUTH_DIALOG, WebKitSoupAuthDialog)) +#define WEBKIT_IS_SOUP_AUTH_DIALOG(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), WEBKIT_TYPE_SOUP_AUTH_DIALOG)) +#define WEBKIT_IS_SOUP_AUTH_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEBKIT_TYPE_SOUP_AUTH_DIALOG)) +#define WEBKIT_SOUP_AUTH_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WEBKIT_TYPE_SOUP_AUTH_DIALOG, WebKitSoupAuthDialog)) + +typedef struct { + GObject parent_instance; +} WebKitSoupAuthDialog; + +typedef struct { + GObjectClass parent_class; + + GtkWidget* (*current_toplevel) (WebKitSoupAuthDialog* feature, SoupMessage* message); +} WebKitSoupAuthDialogClass; + +GType webkit_soup_auth_dialog_get_type (void); + +G_END_DECLS + +#endif /* WEBKIT_SOUP_AUTH_DIALOG_H */ diff --git a/WebKit/gtk/webkit/webkitwebbackforwardlist.cpp b/WebKit/gtk/webkit/webkitwebbackforwardlist.cpp index 3899f4b..5c93df0 100644 --- a/WebKit/gtk/webkit/webkitwebbackforwardlist.cpp +++ b/WebKit/gtk/webkit/webkitwebbackforwardlist.cpp @@ -189,11 +189,11 @@ GList* webkit_web_back_forward_list_get_forward_list_with_limit(WebKitWebBackFor backForwardList->forwardListWithLimit(limit, items); for (unsigned i = 0; i < items.size(); i++) { - WebKitWebHistoryItem* webHistoryItem = webkit_web_history_item_new_with_core_item(items[i].get()); - forwardItems = g_list_prepend(forwardItems, g_object_ref(webHistoryItem)); + WebKitWebHistoryItem* webHistoryItem = kit(items[i]); + forwardItems = g_list_prepend(forwardItems, webHistoryItem); } - return g_list_reverse(forwardItems); + return forwardItems; } /** @@ -219,12 +219,13 @@ GList* webkit_web_back_forward_list_get_back_list_with_limit(WebKitWebBackForwar backForwardList->backListWithLimit(limit, items); for (unsigned i = 0; i < items.size(); i++) { - WebKitWebHistoryItem* webHistoryItem = webkit_web_history_item_new_with_core_item(items[i].get()); - backItems = g_list_prepend(backItems, g_object_ref(webHistoryItem)); + WebKitWebHistoryItem* webHistoryItem = kit(items[i]); + backItems = g_list_prepend(backItems, webHistoryItem); } - return g_list_reverse(backItems); + return backItems; } + /** * webkit_web_back_forward_list_get_back_item: * @web_back_forward_list: a #WebBackForwardList @@ -389,6 +390,25 @@ void webkit_web_back_forward_list_set_limit(WebKitWebBackForwardList* webBackFor backForwardList->setCapacity(limit); } +/** + * webkit_web_back_forward_list_add_item: + * @web_back_forward_list: a #WebKitWebBackForwardList + * @history_item: the #WebKitWebHistoryItem to add + * + * Adds the item to the #WebKitWebBackForwardList. + * + * Since: 1.1.1 + */ +void webkit_web_back_forward_list_add_item(WebKitWebBackForwardList *webBackForwardList, WebKitWebHistoryItem *webHistoryItem) +{ + g_return_if_fail(WEBKIT_IS_WEB_BACK_FORWARD_LIST(webBackForwardList)); + + WebCore::BackForwardList* backForwardList = core(webBackForwardList); + WebCore::HistoryItem* historyItem = core(webHistoryItem); + + backForwardList->addItem(historyItem); +} + } /* end extern "C" */ WebCore::BackForwardList* WebKit::core(WebKitWebBackForwardList* webBackForwardList) diff --git a/WebKit/gtk/webkit/webkitwebbackforwardlist.h b/WebKit/gtk/webkit/webkitwebbackforwardlist.h index fb641f0..a44cbcd 100644 --- a/WebKit/gtk/webkit/webkitwebbackforwardlist.h +++ b/WebKit/gtk/webkit/webkitwebbackforwardlist.h @@ -107,6 +107,9 @@ webkit_web_back_forward_list_get_limit (WebKitWebBackForwardLi WEBKIT_API void webkit_web_back_forward_list_set_limit (WebKitWebBackForwardList *web_back_forward_list, gint limit); +WEBKIT_API void +webkit_web_back_forward_list_add_item (WebKitWebBackForwardList *web_back_forward_list, + WebKitWebHistoryItem *history_item); G_END_DECLS diff --git a/WebKit/gtk/webkit/webkitwebframe.cpp b/WebKit/gtk/webkit/webkitwebframe.cpp index 38e23a4..e2b10b6 100644 --- a/WebKit/gtk/webkit/webkitwebframe.cpp +++ b/WebKit/gtk/webkit/webkitwebframe.cpp @@ -5,6 +5,7 @@ * Copyright (C) 2008 Christian Dywan <christian@imendio.com> * Copyright (C) 2008 Collabora Ltd. * Copyright (C) 2008 Nuanti Ltd. + * Copyright (C) 2009 Jan Alonzo <jmalonzo@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -31,6 +32,7 @@ #include "AnimationController.h" #include "CString.h" +#include "DocumentLoader.h" #include "FrameLoader.h" #include "FrameLoaderClientGtk.h" #include "FrameTree.h" @@ -43,6 +45,7 @@ #include "RenderTreeAsText.h" #include "JSDOMBinding.h" #include "ScriptController.h" +#include "SubstituteData.h" #include <JavaScriptCore/APICast.h> @@ -373,6 +376,60 @@ WebKitWebFrame* webkit_web_frame_get_parent(WebKitWebFrame* frame) } /** + * webkit_web_frame_load_uri: + * @frame: a #WebKitWebFrame + * @uri: an URI string + * + * Requests loading of the specified URI string. + * + * Since: 1.1.1 + */ +void webkit_web_frame_load_uri(WebKitWebFrame* frame, const gchar* uri) +{ + g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame)); + g_return_if_fail(uri); + + Frame* coreFrame = core(frame); + if (!coreFrame) + return; + + coreFrame->loader()->load(ResourceRequest(KURL(KURL(), String::fromUTF8(uri))), false); +} + +/** + * webkit_web_frame_load_string: + * @frame: a #WebKitWebFrame + * @content: an URI string + * @mime_type: the MIME type, or %NULL + * @encoding: the encoding, or %NULL + * @base_uri: the base URI for relative locations + * + * Requests loading of the given @content with the specified @mime_type, + * @encoding and @base_uri. + * + * If @mime_type is %NULL, "text/html" is assumed. + * + * If @encoding is %NULL, "UTF-8" is assumed. + * + * Since: 1.1.1 + */ +void webkit_web_frame_load_string(WebKitWebFrame* frame, const gchar* content, const gchar* contentMimeType, const gchar* contentEncoding, const gchar* baseUri) +{ + g_return_if_fail(WEBKIT_IS_WEB_FRAME(frame)); + g_return_if_fail(content); + + Frame* coreFrame = core(frame); + if (!coreFrame) + return; + + KURL url(KURL(), baseUri ? String::fromUTF8(baseUri) : ""); + RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(content, strlen(content)); + SubstituteData substituteData(sharedBuffer.release(), contentMimeType ? String(contentMimeType) : "text/html", contentEncoding ? String(contentEncoding) : "UTF-8", blankURL(), url); + + coreFrame->loader()->load(ResourceRequest(url), substituteData, false); +} + +/** * webkit_web_frame_load_request: * @frame: a #WebKitWebFrame * @request: a #WebKitNetworkRequest @@ -394,7 +451,7 @@ void webkit_web_frame_load_request(WebKitWebFrame* frame, WebKitNetworkRequest* // TODO: Use the ResourceRequest carried by WebKitNetworkRequest when it is implemented. String string = String::fromUTF8(webkit_network_request_get_uri(request)); - coreFrame->loader()->load(ResourceRequest(KURL(string))); + coreFrame->loader()->load(ResourceRequest(KURL(KURL(), string)), false); } /** @@ -662,4 +719,12 @@ unsigned int webkit_web_frame_number_of_active_animations(WebKitWebFrame* frame) return controller->numberOfActiveAnimations(); } +gchar* webkit_web_frame_get_response_mime_type(WebKitWebFrame* frame) +{ + Frame* coreFrame = core(frame); + DocumentLoader* docLoader = coreFrame->loader()->documentLoader(); + String mimeType = docLoader->responseMIMEType(); + return g_strdup(mimeType.utf8().data()); +} + } diff --git a/WebKit/gtk/webkit/webkitwebframe.h b/WebKit/gtk/webkit/webkitwebframe.h index fcdace6..7e24565 100644 --- a/WebKit/gtk/webkit/webkitwebframe.h +++ b/WebKit/gtk/webkit/webkitwebframe.h @@ -81,6 +81,17 @@ WEBKIT_API WebKitWebFrame* webkit_web_frame_get_parent (WebKitWebFrame *frame); WEBKIT_API void +webkit_web_frame_load_uri (WebKitWebFrame *frame, + const gchar *uri); + +WEBKIT_API void +webkit_web_frame_load_string (WebKitWebFrame *frame, + const gchar *content, + const gchar *mime_type, + const gchar *encoding, + const gchar *base_uri); + +WEBKIT_API void webkit_web_frame_load_request (WebKitWebFrame *frame, WebKitNetworkRequest *request); diff --git a/WebKit/gtk/webkit/webkitwebhistoryitem.cpp b/WebKit/gtk/webkit/webkitwebhistoryitem.cpp index 8cdaa90..42e6a9b 100644 --- a/WebKit/gtk/webkit/webkitwebhistoryitem.cpp +++ b/WebKit/gtk/webkit/webkitwebhistoryitem.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Jan Michael C. Alonzo + * Copyright (C) 2008, 2009 Jan Michael C. Alonzo * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -17,7 +17,6 @@ * Boston, MA 02110-1301, USA. */ - #include "config.h" #include "webkitwebhistoryitem.h" @@ -53,12 +52,14 @@ using namespace WebKit; extern "C" { struct _WebKitWebHistoryItemPrivate { - WTF::RefPtr<WebCore::HistoryItem> historyItem; + WebCore::HistoryItem* historyItem; WebCore::CString title; WebCore::CString alternateTitle; WebCore::CString uri; WebCore::CString originalUri; + + gboolean disposed; }; #define WEBKIT_WEB_HISTORY_ITEM_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_WEB_HISTORY_ITEM, WebKitWebHistoryItemPrivate)) @@ -81,7 +82,7 @@ static void webkit_web_history_item_get_property(GObject* object, guint prop_id, static GHashTable* webkit_history_items() { - static GHashTable* historyItems = g_hash_table_new(g_direct_hash, g_direct_equal); + static GHashTable* historyItems = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref); return historyItems; } @@ -94,27 +95,24 @@ static void webkit_history_item_add(WebKitWebHistoryItem* webHistoryItem, WebCor g_hash_table_insert(table, historyItem, g_object_ref(webHistoryItem)); } -static void webkit_history_item_remove(WebCore::HistoryItem* historyItem) -{ - GHashTable* table = webkit_history_items(); - WebKitWebHistoryItem* webHistoryItem = (WebKitWebHistoryItem*) g_hash_table_lookup(table, historyItem); - - g_return_if_fail(webHistoryItem != NULL); - - g_hash_table_remove(table, historyItem); - g_object_unref(webHistoryItem); -} - static void webkit_web_history_item_dispose(GObject* object) { WebKitWebHistoryItem* webHistoryItem = WEBKIT_WEB_HISTORY_ITEM(object); + WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; + WebCore::HistoryItem* item = core(webHistoryItem); - webkit_history_item_remove(core(webHistoryItem)); + if (!priv->disposed) { + GHashTable* table = webkit_history_items(); - /* destroy table if empty */ - GHashTable* table = webkit_history_items(); - if (!g_hash_table_size(table)) - g_hash_table_destroy(table); + g_hash_table_remove(table, item); + item->deref(); + + /* destroy table if empty */ + if (!g_hash_table_size(table)) + g_hash_table_destroy(table); + + priv->disposed = true; + } G_OBJECT_CLASS(webkit_web_history_item_parent_class)->dispose(object); } @@ -270,21 +268,9 @@ static void webkit_web_history_item_get_property(GObject* object, guint prop_id, } /* Helper function to create a new WebHistoryItem instance when needed */ -WebKitWebHistoryItem* webkit_web_history_item_new_with_core_item(WebCore::HistoryItem* item) +WebKitWebHistoryItem* webkit_web_history_item_new_with_core_item(PassRefPtr<WebCore::HistoryItem> historyItem) { - WebKitWebHistoryItem* webHistoryItem = kit(item); - - if (webHistoryItem) - g_object_ref(webHistoryItem); - else { - webHistoryItem = WEBKIT_WEB_HISTORY_ITEM(g_object_new(WEBKIT_TYPE_WEB_HISTORY_ITEM, NULL)); - WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; - - priv->historyItem = item; - webkit_history_item_add(webHistoryItem, priv->historyItem.get()); - } - - return webHistoryItem; + return kit(historyItem); } @@ -300,8 +286,9 @@ WebKitWebHistoryItem* webkit_web_history_item_new() WebKitWebHistoryItem* webHistoryItem = WEBKIT_WEB_HISTORY_ITEM(g_object_new(WEBKIT_TYPE_WEB_HISTORY_ITEM, NULL)); WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; - priv->historyItem = WebCore::HistoryItem::create(); - webkit_history_item_add(webHistoryItem, priv->historyItem.get()); + RefPtr<WebCore::HistoryItem> item = WebCore::HistoryItem::create(); + priv->historyItem = item.release().releaseRef(); + webkit_history_item_add(webHistoryItem, priv->historyItem); return webHistoryItem; } @@ -323,8 +310,9 @@ WebKitWebHistoryItem* webkit_web_history_item_new_with_data(const gchar* uri, co WebKitWebHistoryItem* webHistoryItem = WEBKIT_WEB_HISTORY_ITEM(g_object_new(WEBKIT_TYPE_WEB_HISTORY_ITEM, NULL)); WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; - priv->historyItem = WebCore::HistoryItem::create(historyUri, historyTitle, 0); - webkit_history_item_add(webHistoryItem, priv->historyItem.get()); + RefPtr<WebCore::HistoryItem> item = WebCore::HistoryItem::create(historyUri, historyTitle, 0); + priv->historyItem = item.release().releaseRef(); + webkit_history_item_add(webHistoryItem, priv->historyItem); return webHistoryItem; } @@ -341,7 +329,7 @@ G_CONST_RETURN gchar* webkit_web_history_item_get_title(WebKitWebHistoryItem* we WebCore::HistoryItem* item = core(webHistoryItem); - g_return_val_if_fail(item != NULL, NULL); + g_return_val_if_fail(item, NULL); WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; priv->title = item->title().utf8(); @@ -363,7 +351,7 @@ G_CONST_RETURN gchar* webkit_web_history_item_get_alternate_title(WebKitWebHisto WebCore::HistoryItem* item = core(webHistoryItem); - g_return_val_if_fail(item != NULL, NULL); + g_return_val_if_fail(item, NULL); WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; priv->alternateTitle = item->alternateTitle().utf8(); @@ -403,7 +391,7 @@ G_CONST_RETURN gchar* webkit_web_history_item_get_uri(WebKitWebHistoryItem* webH WebCore::HistoryItem* item = core(WEBKIT_WEB_HISTORY_ITEM(webHistoryItem)); - g_return_val_if_fail(item != NULL, NULL); + g_return_val_if_fail(item, NULL); WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; priv->uri = item->urlString().utf8(); @@ -425,7 +413,7 @@ G_CONST_RETURN gchar* webkit_web_history_item_get_original_uri(WebKitWebHistoryI WebCore::HistoryItem* item = core(WEBKIT_WEB_HISTORY_ITEM(webHistoryItem)); - g_return_val_if_fail(item != NULL, NULL); + g_return_val_if_fail(item, NULL); WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; priv->originalUri = item->originalURLString().utf8(); @@ -447,31 +435,84 @@ gdouble webkit_web_history_item_get_last_visited_time(WebKitWebHistoryItem* webH WebCore::HistoryItem* item = core(WEBKIT_WEB_HISTORY_ITEM(webHistoryItem)); - g_return_val_if_fail(item != NULL, 0); + g_return_val_if_fail(item, 0); return item->lastVisitedTime(); } +/* private methods */ + +G_CONST_RETURN gchar* webkit_web_history_item_get_target(WebKitWebHistoryItem* webHistoryItem) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL); + + WebCore::HistoryItem* item = core(webHistoryItem); + + g_return_val_if_fail(item, NULL); + + WebCore::CString t = item->target().utf8(); + return g_strdup(t.data()); +} + +gboolean webkit_web_history_item_is_target_item(WebKitWebHistoryItem* webHistoryItem) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), false); + + WebCore::HistoryItem* item = core(webHistoryItem); + + g_return_val_if_fail(item, false); + + return item->isTargetItem(); +} + +GList* webkit_web_history_item_get_children(WebKitWebHistoryItem* webHistoryItem) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL); + + WebCore::HistoryItem* item = core(webHistoryItem); + + g_return_val_if_fail(item, NULL); + + const WebCore::HistoryItemVector& children = item->children(); + if (!children.size()) + return NULL; + + unsigned size = children.size(); + GList* kids = NULL; + for (unsigned i = 0; i < size; ++i) + kids = g_list_prepend(kids, kit(children[i].get())); + + return g_list_reverse(kids); +} + } /* end extern "C" */ WebCore::HistoryItem* WebKit::core(WebKitWebHistoryItem* webHistoryItem) { g_return_val_if_fail(WEBKIT_IS_WEB_HISTORY_ITEM(webHistoryItem), NULL); - WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; - WTF::RefPtr<WebCore::HistoryItem> historyItem = priv->historyItem; - - return historyItem ? historyItem.get() : 0; + return webHistoryItem->priv->historyItem; } -WebKitWebHistoryItem* WebKit::kit(WebCore::HistoryItem* historyItem) +WebKitWebHistoryItem* WebKit::kit(PassRefPtr<WebCore::HistoryItem> historyItem) { - g_return_val_if_fail(historyItem != NULL, NULL); + g_return_val_if_fail(historyItem, NULL); + + RefPtr<WebCore::HistoryItem> item = historyItem; WebKitWebHistoryItem* webHistoryItem; GHashTable* table = webkit_history_items(); - webHistoryItem = (WebKitWebHistoryItem*) g_hash_table_lookup(table, historyItem); + webHistoryItem = (WebKitWebHistoryItem*) g_hash_table_lookup(table, item.get()); + + if (!webHistoryItem) { + webHistoryItem = WEBKIT_WEB_HISTORY_ITEM(g_object_new(WEBKIT_TYPE_WEB_HISTORY_ITEM, NULL)); + WebKitWebHistoryItemPrivate* priv = webHistoryItem->priv; + + priv->historyItem = item.release().releaseRef(); + webkit_history_item_add(webHistoryItem, priv->historyItem); + } + return webHistoryItem; } diff --git a/WebKit/gtk/webkit/webkitwebinspector.cpp b/WebKit/gtk/webkit/webkitwebinspector.cpp index b8f8d9e..8e1c8c0 100644 --- a/WebKit/gtk/webkit/webkitwebinspector.cpp +++ b/WebKit/gtk/webkit/webkitwebinspector.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 Gustavo Noronha Silva - * Copyright (C) 2008 Holger Hans Peter Freyther + * Copyright (C) 2008, 2009 Holger Hans Peter Freyther * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -75,12 +75,13 @@ enum { PROP_WEB_VIEW, PROP_INSPECTED_URI, + PROP_JAVASCRIPT_PROFILING_ENABLED }; G_DEFINE_TYPE(WebKitWebInspector, webkit_web_inspector, G_TYPE_OBJECT) struct _WebKitWebInspectorPrivate { - InspectorClient* inspectorClient; + WebCore::Page* page; WebKitWebView* inspector_view; gchar* inspected_uri; }; @@ -274,6 +275,23 @@ static void webkit_web_inspector_class_init(WebKitWebInspectorClass* klass) NULL, WEBKIT_PARAM_READABLE)); + /** + * WebKitWebInspector:javascript-profiling-enabled + * + * This is enabling JavaScript profiling in the Inspector. This means + * that Console.profiles will return the profiles. + * + * Since: 1.1.1 + */ + g_object_class_install_property(gobject_class, + PROP_JAVASCRIPT_PROFILING_ENABLED, + g_param_spec_boolean( + "javascript-profiling-enabled", + "Enable JavaScript profiling", + "Profile the executed JavaScript.", + FALSE, + WEBKIT_PARAM_READWRITE)); + g_type_class_add_private(klass, sizeof(WebKitWebInspectorPrivate)); } @@ -298,7 +316,19 @@ static void webkit_web_inspector_finalize(GObject* object) static void webkit_web_inspector_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { + WebKitWebInspector* web_inspector = WEBKIT_WEB_INSPECTOR(object); + WebKitWebInspectorPrivate* priv = web_inspector->priv; + switch(prop_id) { + case PROP_JAVASCRIPT_PROFILING_ENABLED: { + bool enabled = g_value_get_boolean(value); + WebCore::InspectorController* controller = priv->page->inspectorController(); + if (enabled) + controller->enableProfiler(); + else + controller->disableProfiler(); + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -317,6 +347,9 @@ static void webkit_web_inspector_get_property(GObject* object, guint prop_id, GV case PROP_INSPECTED_URI: g_value_set_string(value, priv->inspected_uri); break; + case PROP_JAVASCRIPT_PROFILING_ENABLED: + g_value_set_boolean(value, priv->page->inspectorController()->profilerEnabled()); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -388,11 +421,11 @@ const gchar* webkit_web_inspector_get_inspected_uri(WebKitWebInspector *web_insp } void -webkit_web_inspector_set_inspector_client(WebKitWebInspector* web_inspector, WebKit::InspectorClient* inspectorClient) +webkit_web_inspector_set_inspector_client(WebKitWebInspector* web_inspector, WebCore::Page* page) { WebKitWebInspectorPrivate* priv = web_inspector->priv; - priv->inspectorClient = inspectorClient; + priv->page = page; } } diff --git a/WebKit/gtk/webkit/webkitwebsettings.cpp b/WebKit/gtk/webkit/webkitwebsettings.cpp index aa38c6c..d31ec2f 100644 --- a/WebKit/gtk/webkit/webkitwebsettings.cpp +++ b/WebKit/gtk/webkit/webkitwebsettings.cpp @@ -74,6 +74,7 @@ struct _WebKitWebSettingsPrivate { gchar* user_stylesheet_uri; gfloat zoom_step; gboolean enable_developer_extras; + gboolean enable_private_browsing; }; #define WEBKIT_WEB_SETTINGS_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_WEB_SETTINGS, WebKitWebSettingsPrivate)) @@ -101,7 +102,8 @@ enum { PROP_RESIZABLE_TEXT_AREAS, PROP_USER_STYLESHEET_URI, PROP_ZOOM_STEP, - PROP_ENABLE_DEVELOPER_EXTRAS + PROP_ENABLE_DEVELOPER_EXTRAS, + PROP_ENABLE_PRIVATE_BROWSING }; static void webkit_web_settings_finalize(GObject* object); @@ -335,6 +337,22 @@ static void webkit_web_settings_class_init(WebKitWebSettingsClass* klass) FALSE, flags)); + /** + * WebKitWebSettings:enable-private-browsing: + * + * Whether to enable private browsing mode. + * + * Since 1.1.2 + */ + g_object_class_install_property(gobject_class, + PROP_ENABLE_PRIVATE_BROWSING, + g_param_spec_boolean( + "enable-private-browsing", + "Enable Private Browsing", + "Enables private browsing mode", + FALSE, + flags)); + g_type_class_add_private(klass, sizeof(WebKitWebSettingsPrivate)); } @@ -437,6 +455,9 @@ static void webkit_web_settings_set_property(GObject* object, guint prop_id, con case PROP_ENABLE_DEVELOPER_EXTRAS: priv->enable_developer_extras = g_value_get_boolean(value); break; + case PROP_ENABLE_PRIVATE_BROWSING: + priv->enable_private_browsing = g_value_get_boolean(value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -512,6 +533,9 @@ static void webkit_web_settings_get_property(GObject* object, guint prop_id, GVa case PROP_ENABLE_DEVELOPER_EXTRAS: g_value_set_boolean(value, priv->enable_developer_extras); break; + case PROP_ENABLE_PRIVATE_BROWSING: + g_value_set_boolean(value, priv->enable_private_browsing); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -563,6 +587,7 @@ WebKitWebSettings* webkit_web_settings_copy(WebKitWebSettings* web_settings) "user-stylesheet-uri", priv->user_stylesheet_uri, "zoom-step", priv->zoom_step, "enable-developer-extras", priv->enable_developer_extras, + "enable-private-browsing", priv->enable_private_browsing, NULL)); return copy; diff --git a/WebKit/gtk/webkit/webkitwebview.cpp b/WebKit/gtk/webkit/webkitwebview.cpp index 0ea6ed5..d6a0d54 100644 --- a/WebKit/gtk/webkit/webkitwebview.cpp +++ b/WebKit/gtk/webkit/webkitwebview.cpp @@ -1,12 +1,13 @@ /* * Copyright (C) 2007, 2008 Holger Hans Peter Freyther - * Copyright (C) 2007, 2008 Christian Dywan <christian@imendio.com> + * Copyright (C) 2007, 2008, 2009 Christian Dywan <christian@imendio.com> * Copyright (C) 2007 Xan Lopez <xan@gnome.org> * Copyright (C) 2007, 2008 Alp Toker <alp@atoker.com> * Copyright (C) 2008 Jan Alonzo <jmalonzo@unpluggable.com> * Copyright (C) 2008 Gustavo Noronha Silva <gns@gnome.org> * Copyright (C) 2008 Nuanti Ltd. * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2009 Igalia S.L. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,6 +26,7 @@ #include "config.h" +#include "webkitdownload.h" #include "webkitwebview.h" #include "webkitenumtypes.h" #include "webkitmarshal.h" @@ -43,6 +45,7 @@ #include "ContextMenuController.h" #include "Cursor.h" #include "Document.h" +#include "DocumentLoader.h" #include "DragClientGtk.h" #include "Editor.h" #include "EditorClientGtk.h" @@ -56,13 +59,12 @@ #include "InspectorClientGtk.h" #include "FrameLoader.h" #include "FrameView.h" -#include "Editor.h" #include "PasteboardHelper.h" #include "PlatformKeyboardEvent.h" #include "PlatformWheelEvent.h" +#include "ResourceHandle.h" #include "ScriptValue.h" #include "Scrollbar.h" -#include "SubstituteData.h" #include <wtf/GOwnPtr.h> #include <gdk/gdkkeysyms.h> @@ -110,6 +112,7 @@ extern "C" { enum { /* normal signals */ NAVIGATION_REQUESTED, + NEW_WINDOW_POLICY_DECISION_REQUESTED, NAVIGATION_POLICY_DECISION_REQUESTED, MIME_TYPE_POLICY_DECISION_REQUESTED, CREATE_WEB_VIEW, @@ -133,12 +136,15 @@ enum { COPY_CLIPBOARD, PASTE_CLIPBOARD, CUT_CLIPBOARD, + DOWNLOAD_REQUESTED, LAST_SIGNAL }; enum { PROP_0, + PROP_TITLE, + PROP_URI, PROP_COPY_TARGET_LIST, PROP_PASTE_TARGET_LIST, PROP_EDITABLE, @@ -147,7 +153,9 @@ enum { PROP_WINDOW_FEATURES, PROP_TRANSPARENT, PROP_ZOOM_LEVEL, - PROP_FULL_CONTENT_ZOOM + PROP_FULL_CONTENT_ZOOM, + PROP_ENCODING, + PROP_CUSTOM_ENCODING }; static guint webkit_web_view_signals[LAST_SIGNAL] = { 0, }; @@ -276,6 +284,12 @@ static void webkit_web_view_get_property(GObject* object, guint prop_id, GValue* WebKitWebView* webView = WEBKIT_WEB_VIEW(object); switch(prop_id) { + case PROP_TITLE: + g_value_set_string(value, webkit_web_view_get_title(webView)); + break; + case PROP_URI: + g_value_set_string(value, webkit_web_view_get_uri(webView)); + break; #if GTK_CHECK_VERSION(2,10,0) case PROP_COPY_TARGET_LIST: g_value_set_boxed(value, webkit_web_view_get_copy_target_list(webView)); @@ -305,6 +319,12 @@ static void webkit_web_view_get_property(GObject* object, guint prop_id, GValue* case PROP_FULL_CONTENT_ZOOM: g_value_set_boolean(value, webkit_web_view_get_full_content_zoom(webView)); break; + case PROP_ENCODING: + g_value_set_string(value, webkit_web_view_get_encoding(webView)); + break; + case PROP_CUSTOM_ENCODING: + g_value_set_string(value, webkit_web_view_get_custom_encoding(webView)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); } @@ -333,6 +353,9 @@ static void webkit_web_view_set_property(GObject* object, guint prop_id, const G case PROP_FULL_CONTENT_ZOOM: webkit_web_view_set_full_content_zoom(webView, g_value_get_boolean(value)); break; + case PROP_CUSTOM_ENCODING: + webkit_web_view_set_custom_encoding(webView, g_value_get_string(value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); } @@ -436,11 +459,23 @@ static gboolean webkit_web_view_key_press_event(GtkWidget* widget, GdkEventKey* case GDK_Left: view->scrollBy(IntSize(-cScrollbarPixelsPerLineStep, 0)); return TRUE; + case GDK_space: + if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) + view->scrollBy(IntSize(0, -view->visibleHeight())); + else + view->scrollBy(IntSize(0, view->visibleHeight())); + return TRUE; + case GDK_Page_Up: + view->scrollBy(IntSize(0, -view->visibleHeight())); + return TRUE; + case GDK_Page_Down: + view->scrollBy(IntSize(0, view->visibleHeight())); + return TRUE; case GDK_Home: - frame->selection()->modify(alteration, SelectionController::BACKWARD, DocumentBoundary, true); + view->scrollBy(IntSize(0, -view->contentsHeight())); return TRUE; case GDK_End: - frame->selection()->modify(alteration, SelectionController::FORWARD, DocumentBoundary, true); + view->scrollBy(IntSize(0, view->contentsHeight())); return TRUE; } @@ -496,10 +531,17 @@ static gboolean webkit_web_view_button_release_event(GtkWidget* widget, GdkEvent } Frame* mainFrame = core(webView)->mainFrame(); - if (!mainFrame->view()) - return FALSE; + if (mainFrame->view()) + mainFrame->eventHandler()->handleMouseReleaseEvent(PlatformMouseEvent(event)); + + /* We always return FALSE here because WebKit can, for the same click, decide + * to not handle press-event but handle release-event, which can totally confuse + * some GTK+ containers when there are no other events in between. This way we + * guarantee that this case never happens, and that if press-event goes through + * release-event also goes through. + */ - return mainFrame->eventHandler()->handleMouseReleaseEvent(PlatformMouseEvent(event)); + return FALSE; } static gboolean webkit_web_view_motion_event(GtkWidget* widget, GdkEventMotion* event) @@ -536,7 +578,7 @@ static void webkit_web_view_size_allocate(GtkWidget* widget, GtkAllocation* allo return; frame->view()->resize(allocation->width, allocation->height); - frame->forceLayout(); + frame->view()->forceLayout(); frame->view()->adjustViewSize(); } @@ -816,6 +858,8 @@ static void webkit_web_view_dispose(GObject* object) WebKitWebView* webView = WEBKIT_WEB_VIEW(object); WebKitWebViewPrivate* priv = webView->priv; + priv->disposing = TRUE; + if (priv->corePage) { webkit_web_view_stop_loading(WEBKIT_WEB_VIEW(object)); @@ -864,6 +908,17 @@ static void webkit_web_view_dispose(GObject* object) G_OBJECT_CLASS(webkit_web_view_parent_class)->dispose(object); } +static void webkit_web_view_finalize(GObject* object) +{ + WebKitWebView* webView = WEBKIT_WEB_VIEW(object); + WebKitWebViewPrivate* priv = webView->priv; + + g_free(priv->encoding); + g_free(priv->customEncoding); + + G_OBJECT_CLASS(webkit_web_view_parent_class)->finalize(object); +} + static gboolean webkit_create_web_view_request_handled(GSignalInvocationHint* ihint, GValue* returnAccu, const GValue* handlerReturn, gpointer dummy) { gpointer newWebView = g_value_get_object(handlerReturn); @@ -998,6 +1053,45 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) WEBKIT_TYPE_NETWORK_REQUEST); /** + * WebKitWebView::new-window-policy-decision-requested: + * @web_view: the object on which the signal is emitted + * @frame: the #WebKitWebFrame that required the navigation + * @request: a #WebKitNetworkRequest + * @navigation_action: a #WebKitWebNavigation + * @policy_decision: a #WebKitWebPolicyDecision + * @return: TRUE if the signal will be handled, FALSE to have the + * default behavior apply + * + * Emitted when @frame requests opening a new window. With this + * signal the browser can use the context of the request to decide + * about the new window. If the request is not handled the default + * behavior is to allow opening the new window to load the url, + * which will cause a create-web-view signal emission where the + * browser handles the new window action but without information + * of the context that caused the navigation. The following + * navigation-policy-decision-requested emissions will load the + * page after the creation of the new window just with the + * information of this new navigation context, without any + * information about the action that made this new window to be + * opened. + * + * Since: 1.1.4 + */ + webkit_web_view_signals[NEW_WINDOW_POLICY_DECISION_REQUESTED] = + g_signal_new("new-window-policy-decision-requested", + G_TYPE_FROM_CLASS(webViewClass), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + 0, + g_signal_accumulator_true_handled, + NULL, + webkit_marshal_BOOLEAN__OBJECT_OBJECT_OBJECT_OBJECT, + G_TYPE_BOOLEAN, 4, + WEBKIT_TYPE_WEB_FRAME, + WEBKIT_TYPE_NETWORK_REQUEST, + WEBKIT_TYPE_WEB_NAVIGATION_ACTION, + WEBKIT_TYPE_WEB_POLICY_DECISION); + + /** * WebKitWebView::navigation-policy-decision-requested: * @web_view: the object on which the signal is emitted * @frame: the #WebKitWebFrame that required the navigation @@ -1085,6 +1179,34 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) G_TYPE_POINTER); /** + * WebKitWebView::download-requested: + * @web_view: the object on which the signal is emitted + * @download: a #WebKitDownload object that lets you control the + * download process + * @return: %TRUE if the download should be performed, %FALSE to cancel it. + * + * A new Download is being requested. By default, if the signal is + * not handled, the download is cancelled. Notice that while + * handling this signal you must set the target URI using + * webkit_download_set_target_uri(). + * + * If you intend to handle downloads yourself rather than using + * the #WebKitDownload helper object you must handle this signal, + * and return %FALSE. + * + * Since: 1.1.2 + */ + webkit_web_view_signals[DOWNLOAD_REQUESTED] = g_signal_new("download-requested", + G_TYPE_FROM_CLASS(webViewClass), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + 0, + g_signal_accumulator_true_handled, + NULL, + webkit_marshal_BOOLEAN__OBJECT, + G_TYPE_BOOLEAN, 1, + G_TYPE_OBJECT); + + /** * WebKitWebView::load-started: * @web_view: the object on which the signal is emitted * @frame: the frame going to do the load @@ -1151,6 +1273,8 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * @title: the new title * * When a #WebKitWebFrame changes the document title this signal is emitted. + * + * Deprecated: 1.1.4: Use "notify::title" instead. */ webkit_web_view_signals[TITLE_CHANGED] = g_signal_new("title-changed", G_TYPE_FROM_CLASS(webViewClass), @@ -1284,9 +1408,9 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) G_STRUCT_OFFSET(WebKitWebViewClass, script_confirm), g_signal_accumulator_true_handled, NULL, - webkit_marshal_BOOLEAN__OBJECT_STRING_BOOLEAN, + webkit_marshal_BOOLEAN__OBJECT_STRING_POINTER, G_TYPE_BOOLEAN, 3, - WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING, G_TYPE_BOOLEAN); + WEBKIT_TYPE_WEB_FRAME, G_TYPE_STRING, G_TYPE_POINTER); /** * WebKitWebView::script-prompt: @@ -1396,6 +1520,7 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) GObjectClass* objectClass = G_OBJECT_CLASS(webViewClass); objectClass->dispose = webkit_web_view_dispose; + objectClass->finalize = webkit_web_view_finalize; objectClass->get_property = webkit_web_view_get_property; objectClass->set_property = webkit_web_view_set_property; @@ -1461,6 +1586,34 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * properties */ + /** + * WebKitWebView:title: + * + * Returns the @web_view's document title. + * + * Since: 1.1.4 + */ + g_object_class_install_property(objectClass, PROP_TITLE, + g_param_spec_string("title", + "Title", + "Returns the @web_view's document title", + NULL, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitWebView:uri: + * + * Returns the current URI of the contents displayed by the @web_view. + * + * Since: 1.1.4 + */ + g_object_class_install_property(objectClass, PROP_URI, + g_param_spec_string("uri", + "URI", + "Returns the current URI of the contents displayed by the @web_view", + NULL, + WEBKIT_PARAM_READABLE)); + #if GTK_CHECK_VERSION(2,10,0) /** * WebKitWebView:copy-target-list: @@ -1570,6 +1723,34 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) FALSE, WEBKIT_PARAM_READWRITE)); + /** + * WebKitWebView:encoding: + * + * The default encoding of the web view. + * + * Since: 1.1.2 + */ + g_object_class_install_property(objectClass, PROP_ENCODING, + g_param_spec_string("encoding", + "Encoding", + "The default encoding of the web view", + NULL, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitWebView:custom-encoding: + * + * The custom encoding of the web view. + * + * Since: 1.1.2 + */ + g_object_class_install_property(objectClass, PROP_CUSTOM_ENCODING, + g_param_spec_string("custom-encoding", + "Custom Encoding", + "The custom encoding of the web view", + NULL, + WEBKIT_PARAM_READWRITE)); + g_type_class_add_private(webViewClass, sizeof(WebKitWebViewPrivate)); } @@ -1625,7 +1806,9 @@ static void webkit_web_view_update_settings(WebKitWebView* webView) Settings* settings = core(webView)->settings(); gchar* defaultEncoding, *cursiveFontFamily, *defaultFontFamily, *fantasyFontFamily, *monospaceFontFamily, *sansSerifFontFamily, *serifFontFamily, *userStylesheetUri; - gboolean autoLoadImages, autoShrinkImages, printBackgrounds, enableScripts, enablePlugins, enableDeveloperExtras, resizableTextAreas; + gboolean autoLoadImages, autoShrinkImages, printBackgrounds, + enableScripts, enablePlugins, enableDeveloperExtras, resizableTextAreas, + enablePrivateBrowsing; g_object_get(webSettings, "default-encoding", &defaultEncoding, @@ -1643,6 +1826,7 @@ static void webkit_web_view_update_settings(WebKitWebView* webView) "resizable-text-areas", &resizableTextAreas, "user-stylesheet-uri", &userStylesheetUri, "enable-developer-extras", &enableDeveloperExtras, + "enable-private-browsing", &enablePrivateBrowsing, NULL); settings->setDefaultTextEncodingName(defaultEncoding); @@ -1658,8 +1842,9 @@ static void webkit_web_view_update_settings(WebKitWebView* webView) settings->setJavaScriptEnabled(enableScripts); settings->setPluginsEnabled(enablePlugins); settings->setTextAreasAreResizable(resizableTextAreas); - settings->setUserStyleSheetLocation(KURL(userStylesheetUri)); + settings->setUserStyleSheetLocation(KURL(KURL(), userStylesheetUri)); settings->setDeveloperExtrasEnabled(enableDeveloperExtras); + settings->setPrivateBrowsingEnabled(enablePrivateBrowsing); g_free(defaultEncoding); g_free(cursiveFontFamily); @@ -1725,9 +1910,11 @@ static void webkit_web_view_settings_notify(WebKitWebSettings* webSettings, GPar else if (name == g_intern_string("resizable-text-areas")) settings->setTextAreasAreResizable(g_value_get_boolean(&value)); else if (name == g_intern_string("user-stylesheet-uri")) - settings->setUserStyleSheetLocation(KURL(g_value_get_string(&value))); + settings->setUserStyleSheetLocation(KURL(KURL(), g_value_get_string(&value))); else if (name == g_intern_string("enable-developer-extras")) settings->setDeveloperExtrasEnabled(g_value_get_boolean(&value)); + else if (name == g_intern_string("enable-private-browsing")) + settings->setPrivateBrowsingEnabled(g_value_get_boolean(&value)); else if (!g_object_class_find_property(G_OBJECT_GET_CLASS(webSettings), name)) g_warning("Unexpected setting '%s'", name); g_value_unset(&value); @@ -1746,20 +1933,13 @@ static void webkit_web_view_init(WebKitWebView* webView) // We also add a simple wrapper class to provide the public // interface for the Web Inspector. priv->webInspector = WEBKIT_WEB_INSPECTOR(g_object_new(WEBKIT_TYPE_WEB_INSPECTOR, NULL)); - webkit_web_inspector_set_inspector_client(priv->webInspector, inspectorClient); + webkit_web_inspector_set_inspector_client(priv->webInspector, priv->corePage); priv->horizontalAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); priv->verticalAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); -#if GLIB_CHECK_VERSION(2,10,0) g_object_ref_sink(priv->horizontalAdjustment); g_object_ref_sink(priv->verticalAdjustment); -#else - g_object_ref(priv->horizontalAdjustment); - gtk_object_sink(GTK_OBJECT(priv->horizontalAdjustment)); - g_object_ref(priv->verticalAdjustment); - gtk_object_sink(GTK_OBJECT(priv->verticalAdjustment)); -#endif GTK_WIDGET_SET_FLAGS(webView, GTK_CAN_FOCUS); priv->mainFrame = WEBKIT_WEB_FRAME(webkit_web_frame_new(webView)); @@ -1890,6 +2070,42 @@ WebKitWebWindowFeatures* webkit_web_view_get_window_features(WebKitWebView* webV } /** + * webkit_web_view_get_title: + * @web_view: a #WebKitWebView + * + * Returns the @web_view's document title + * + * Since: 1.1.4 + * + * Return value: the title of @web_view + */ +G_CONST_RETURN gchar* webkit_web_view_get_title(WebKitWebView* webView) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL); + + WebKitWebViewPrivate* priv = webView->priv; + return priv->mainFrame->priv->title; +} + +/** + * webkit_web_view_get_uri: + * @web_view: a #WebKitWebView + * + * Returns the current URI of the contents displayed by the @web_view + * + * Since: 1.1.4 + * + * Return value: the URI of @web_view + */ +G_CONST_RETURN gchar* webkit_web_view_get_uri(WebKitWebView* webView) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL); + + WebKitWebViewPrivate* priv = webView->priv; + return priv->mainFrame->priv->uri; +} + +/** * webkit_web_view_set_maintains_back_forward_list: * @web_view: a #WebKitWebView * @flag: to tell the view to maintain a back or forward list @@ -2048,13 +2264,29 @@ gboolean webkit_web_view_can_go_forward(WebKitWebView* webView) return TRUE; } +/** + * webkit_web_view_open: + * @web_view: a #WebKitWebView + * @uri: an URI + * + * Requests loading of the specified URI string. + * + * Deprecated: 1.1.1: Use webkit_web_view_load_uri() instead. + */ void webkit_web_view_open(WebKitWebView* webView, const gchar* uri) { g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); g_return_if_fail(uri); - Frame* frame = core(webView)->mainFrame(); - frame->loader()->load(ResourceRequest(KURL(String::fromUTF8(uri)))); + // We used to support local paths, unlike the newer + // function webkit_web_view_load_uri + if (g_path_is_absolute(uri)) { + gchar* fileUri = g_strdup_printf("file://%s", uri); + webkit_web_view_load_uri(webView, fileUri); + g_free(fileUri); + } + else + webkit_web_view_load_uri(webView, uri); } void webkit_web_view_reload(WebKitWebView* webView) @@ -2079,20 +2311,57 @@ void webkit_web_view_reload_bypass_cache(WebKitWebView* webView) core(webView)->mainFrame()->loader()->reload(true); } -void webkit_web_view_load_string(WebKitWebView* webView, const gchar* content, const gchar* contentMimeType, const gchar* contentEncoding, const gchar* baseUri) +/** + * webkit_web_view_load_uri: + * @web_view: a #WebKitWebView + * @uri: an URI string + * + * Requests loading of the specified URI string. + * + * Since: 1.1.1 + */ +void webkit_web_view_load_uri(WebKitWebView* webView, const gchar* uri) { g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); - g_return_if_fail(content); + g_return_if_fail(uri); - Frame* frame = core(webView)->mainFrame(); + WebKitWebFrame* frame = webView->priv->mainFrame; + webkit_web_frame_load_uri(frame, uri); +} - KURL url(baseUri ? String::fromUTF8(baseUri) : ""); - RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(content, strlen(content)); - SubstituteData substituteData(sharedBuffer.release(), contentMimeType ? String(contentMimeType) : "text/html", contentEncoding ? String(contentEncoding) : "UTF-8", KURL("about:blank"), url); +/** ++ * webkit_web_view_load_string: ++ * @web_view: a #WebKitWebView ++ * @content: an URI string ++ * @mime_type: the MIME type, or %NULL ++ * @encoding: the encoding, or %NULL ++ * @base_uri: the base URI for relative locations ++ * ++ * Requests loading of the given @content with the specified @mime_type, ++ * @encoding and @base_uri. ++ * ++ * If @mime_type is %NULL, "text/html" is assumed. ++ * ++ * If @encoding is %NULL, "UTF-8" is assumed. ++ */ +void webkit_web_view_load_string(WebKitWebView* webView, const gchar* content, const gchar* mimeType, const gchar* encoding, const gchar* baseUri) +{ + g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); + g_return_if_fail(content); - frame->loader()->load(ResourceRequest(url), substituteData); + WebKitWebFrame* frame = webView->priv->mainFrame; + webkit_web_frame_load_string(frame, content, mimeType, encoding, baseUri); } - +/** + * webkit_web_view_load_html_string: + * @web_view: a #WebKitWebView + * @content: an URI string + * @base_uri: the base URI for relative locations + * + * Requests loading of the given @content with the specified @base_uri. + * + * Deprecated: 1.1.1: Use webkit_web_view_load_string() instead. + */ void webkit_web_view_load_html_string(WebKitWebView* webView, const gchar* content, const gchar* baseUri) { g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); @@ -2101,6 +2370,28 @@ void webkit_web_view_load_html_string(WebKitWebView* webView, const gchar* conte webkit_web_view_load_string(webView, content, NULL, NULL, baseUri); } +/** + * webkit_web_view_load_request: + * @web_view: a #WebKitWebView + * @request: a #WebKitNetworkRequest + * + * Requests loading of the specified asynchronous client request. + * + * Creates a provisional data source that will transition to a committed data + * source once any data has been received. Use webkit_web_view_stop_loading() to + * stop the load. + * + * Since: 1.1.1 + */ +void webkit_web_view_load_request(WebKitWebView* webView, WebKitNetworkRequest* request) +{ + g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); + g_return_if_fail(WEBKIT_IS_NETWORK_REQUEST(request)); + + WebKitWebFrame* frame = webView->priv->mainFrame; + webkit_web_frame_load_request(frame, request); +} + void webkit_web_view_stop_loading(WebKitWebView* webView) { g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); @@ -2673,4 +2964,89 @@ void webkit_web_view_set_full_content_zoom(WebKitWebView* webView, gboolean zoom g_object_notify(G_OBJECT(webView), "full-content-zoom"); } +/** + * webkit_get_default_session: + * + * Retrieves the default #SoupSession used by all web views. + * Note that the session features are added by WebKit on demand, + * so if you insert your own #SoupCookieJar before any network + * traffic occurs, WebKit will use it instead of the default. + * + * Return value: the default #SoupSession + * + * Since: 1.1.1 + */ +SoupSession* webkit_get_default_session () +{ + return ResourceHandle::defaultSession(); +} + +} + +/** + * webkit_web_view_get_encoding: + * @web_view: a #WebKitWebView + * + * Returns the default encoding of the #WebKitWebView. + * + * Return value: the default encoding + * + * Since: 1.1.1 + */ +const gchar* webkit_web_view_get_encoding(WebKitWebView* webView) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL); + + String encoding = core(webView)->mainFrame()->loader()->encoding(); + + if (!encoding.isEmpty()) { + WebKitWebViewPrivate* priv = webView->priv; + g_free(priv->encoding); + priv->encoding = g_strdup(encoding.utf8().data()); + return priv->encoding; + } else + return NULL; +} + +/** + * webkit_web_view_set_custom_encoding: + * @web_view: a #WebKitWebView + * @encoding: the new encoding, or %NULL to restore the default encoding + * + * Sets the current #WebKitWebView encoding, without modifying the default one, + * and reloads the page. + * + * Since: 1.1.1 + */ +void webkit_web_view_set_custom_encoding(WebKitWebView* webView, const char* encoding) +{ + g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); + + core(webView)->mainFrame()->loader()->reloadWithOverrideEncoding(String::fromUTF8(encoding)); +} + +/** + * webkit_web_view_get_custom_encoding: + * @web_view: a #WebKitWebView + * + * Returns the current encoding of the #WebKitWebView, not the default-encoding + * of WebKitWebSettings. + * + * Return value: a string containing the current custom encoding for @web_view, or %NULL if there's none set. + * + * Since: 1.1.1 + */ +const char* webkit_web_view_get_custom_encoding(WebKitWebView* webView) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), NULL); + + String overrideEncoding = core(webView)->mainFrame()->loader()->documentLoader()->overrideEncoding(); + + if (!overrideEncoding.isEmpty()) { + WebKitWebViewPrivate* priv = webView->priv; + g_free (priv->customEncoding); + priv->customEncoding = g_strdup(overrideEncoding.utf8().data()); + return priv->customEncoding; + } else + return NULL; } diff --git a/WebKit/gtk/webkit/webkitwebview.h b/WebKit/gtk/webkit/webkitwebview.h index 2bb8c61..1455a79 100644 --- a/WebKit/gtk/webkit/webkitwebview.h +++ b/WebKit/gtk/webkit/webkitwebview.h @@ -23,6 +23,7 @@ #define WEBKIT_WEB_VIEW_H #include <gtk/gtk.h> +#include <libsoup/soup.h> #include <JavaScriptCore/JSBase.h> #include <webkit/webkitdefines.h> @@ -49,8 +50,8 @@ typedef enum { typedef enum { - WEBKIT_WEB_VIEW_TARGET_INFO_HTML = - 1, - WEBKIT_WEB_VIEW_TARGET_INFO_TEXT = - 2 + WEBKIT_WEB_VIEW_TARGET_INFO_HTML, + WEBKIT_WEB_VIEW_TARGET_INFO_TEXT } WebKitWebViewTargetInfo; struct _WebKitWebView { @@ -126,6 +127,12 @@ webkit_web_view_get_type (void); WEBKIT_API GtkWidget * webkit_web_view_new (void); +WEBKIT_API G_CONST_RETURN gchar * +webkit_web_view_get_title (WebKitWebView *web_view); + +WEBKIT_API G_CONST_RETURN gchar * +webkit_web_view_get_uri (WebKitWebView *web_view); + WEBKIT_API void webkit_web_view_set_maintains_back_forward_list (WebKitWebView *web_view, gboolean flag); @@ -171,10 +178,14 @@ WEBKIT_API void webkit_web_view_reload_bypass_cache (WebKitWebView *web_view); WEBKIT_API void +webkit_web_view_load_uri (WebKitWebView *web_view, + const gchar *uri); + +WEBKIT_API void webkit_web_view_load_string (WebKitWebView *web_view, const gchar *content, - const gchar *content_mime_type, - const gchar *content_encoding, + const gchar *mime_type, + const gchar *encoding, const gchar *base_uri); WEBKIT_API void @@ -182,6 +193,10 @@ webkit_web_view_load_html_string (WebKitWebView *web_view, const gchar *content, const gchar *base_uri); +WEBKIT_API void +webkit_web_view_load_request (WebKitWebView *web_view, + WebKitNetworkRequest *request); + WEBKIT_API gboolean webkit_web_view_search_text (WebKitWebView *web_view, const gchar *text, @@ -296,6 +311,19 @@ WEBKIT_API void webkit_web_view_set_full_content_zoom (WebKitWebView *web_view, gboolean full_content_zoom); +WEBKIT_API SoupSession* +webkit_get_default_session (void); + +WEBKIT_API const gchar* +webkit_web_view_get_encoding (WebKitWebView * webView); + +WEBKIT_API void +webkit_web_view_set_custom_encoding (WebKitWebView * webView, + const gchar * encoding); + +WEBKIT_API const char* +webkit_web_view_get_custom_encoding (WebKitWebView * webView); + G_END_DECLS #endif diff --git a/WebKit/gtk/webkitmarshal.list b/WebKit/gtk/webkitmarshal.list new file mode 100644 index 0000000..b714a7c --- /dev/null +++ b/WebKit/gtk/webkitmarshal.list @@ -0,0 +1,17 @@ +BOOLEAN:INT,INT,STRING +BOOLEAN:OBJECT +BOOLEAN:OBJECT,OBJECT,OBJECT,OBJECT +BOOLEAN:OBJECT,OBJECT,STRING,OBJECT +BOOLEAN:OBJECT,STRING +BOOLEAN:OBJECT,STRING,POINTER +BOOLEAN:OBJECT,STRING,STRING,STRING +BOOLEAN:STRING,INT,STRING +BOOLEAN:VOID +ENUM:OBJECT,OBJECT +OBJECT:OBJECT +OBJECT:VOID +VOID:OBJECT,OBJECT +VOID:OBJECT,POINTER,POINTER +VOID:OBJECT,STRING +VOID:STRING +VOID:STRING,STRING diff --git a/WebKit/mac/Carbon/CarbonUtils.h b/WebKit/mac/Carbon/CarbonUtils.h index f005286..166de7b 100644 --- a/WebKit/mac/Carbon/CarbonUtils.h +++ b/WebKit/mac/Carbon/CarbonUtils.h @@ -45,12 +45,12 @@ extern "C" { #endif extern void -WebInitForCarbon(void) AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1; +WebInitForCarbon(void) AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0; #ifdef __OBJC__ extern CGImageRef -WebConvertNSImageToCGImageRef(NSImage * inImage) AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1; +WebConvertNSImageToCGImageRef(NSImage * inImage) AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0; #endif diff --git a/WebKit/mac/Carbon/HIWebView.h b/WebKit/mac/Carbon/HIWebView.h index 5483472..bc67453 100644 --- a/WebKit/mac/Carbon/HIWebView.h +++ b/WebKit/mac/Carbon/HIWebView.h @@ -67,7 +67,7 @@ extern "C" { * Non-Carbon CFM: not available */ extern OSStatus -HIWebViewCreate(HIViewRef * outControl) AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1; +HIWebViewCreate(HIViewRef * outControl) AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0; #ifdef __OBJC__ @@ -91,7 +91,7 @@ HIWebViewCreate(HIViewRef * outControl) AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_B * Non-Carbon CFM: not available */ extern WebView * -HIWebViewGetWebView(HIViewRef inView) AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_3_1; +HIWebViewGetWebView(HIViewRef inView) AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0; #endif diff --git a/WebKit/mac/ChangeLog b/WebKit/mac/ChangeLog index 16a69b1..dbf2427 100644 --- a/WebKit/mac/ChangeLog +++ b/WebKit/mac/ChangeLog @@ -1,8 +1,1214 @@ -2009-02-18 Mark Rowe <mrowe@apple.com> +2009-03-26 Jungshik Shin <jshin@chromium.org> - Merge r41071. + Reviewed by Alexey Proskuryakov. + + Add WebPreferences for encoding autodetection on Mac. + + http://bugs.webkit.org/show_bug.cgi?id=16482 + + * WebView/WebPreferenceKeysPrivate.h: + * WebView/WebPreferences.mm: + (+[WebPreferences initialize]): + (-[WebPreferences usesEncodingDetector]): + (-[WebPreferences setUsesEncodingDetector:]): + * WebView/WebPreferencesPrivate.h: + * WebView/WebView.mm: + (-[WebView _preferencesChangedNotification:]): + +2009-03-26 Anders Carlsson <andersca@apple.com> + + Reviewed by Dan Bernstein. + + - Fix <rdar://problem/6687055> and <rdar://problem/6713639>. + + * Plugins/Hosted/NetscapePluginHostProxy.mm: + (WKPCInvalidateRect): + Call NetscapePluginInstanceProxy::invalidateRect. + + * Plugins/Hosted/NetscapePluginInstanceProxy.h: + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::cleanup): + Stop the request timer, set m_pluginView to nil. + + (WebKit::NetscapePluginInstanceProxy::pluginHostDied): + No need to set m_pluginView to nil here anymore, it's now done in cleanup(). + + (WebKit::NetscapePluginInstanceProxy::performRequest): + (WebKit::NetscapePluginInstanceProxy::requestTimerFired): + Assert that the plug-in view is not nil. + + (WebKit::NetscapePluginInstanceProxy::invalidateRect): + Call setNeedsDisplayInRect here. + +2009-03-25 Anders Carlsson <andersca@apple.com> + + Reviewed by Darin Adler. + + <rdar://problem/6714964> + CrashTracer: [REGRESSION] 51 crashes in Safari at com.apple.WebKit • WebNetscapePluginStream::deliverData + 775 + + Don't release m_deliveryData since it's a RetainPtr. Also, use adoptNS instead of releasing newDeliveryData manually. + + * Plugins/WebBaseNetscapePluginStream.mm: + (WebNetscapePluginStream::deliverData): + +2009-03-25 Mike Thole <mthole@apple.com> + + Reviewed by Kevin Decker. + + <rdar://problem/6453738> call SetWindow when user creates a new tab + + CoreGraphics plug-ins now receive an NPP_SetWindow call when moving to a background tab. + Flash is excluded from this change in behavior, as it has historical WebKit-specific code + that isn't compatible with this change. + + * Plugins/WebNetscapePluginView.h: + Added an _isFlash ivar. + * Plugins/WebNetscapePluginView.mm: + (-[WebNetscapePluginView _createPlugin]): + Set the new _isFlash ivar based on the bundle identifier. + (-[WebNetscapePluginView saveAndSetNewPortStateForUpdate:]): + When using the CG drawing model and in a non-drawable state, set the portState + to NULL and return early. + (-[WebNetscapePluginView updateAndSetWindow]): + When using the CG drawing model, call -setWindowIfNecessary even if the portState is NULL. + Flash is an exception to this, due to its historical behavior. + (-[WebNetscapePluginView setWindowIfNecessary]): + Removed an assertion that was no longer true. The [NSView focus] view + is no longer guaranteed to be 'self' at this point. + Also modified the debug logging for CG plug-ins to include the size of the + window's clipRect, which was useful in verifying the correct behavior of this patch. + +2009-03-24 Dan Bernstein <mitz@apple.com> + + Reviewed by Oliver Hunt. + + - speculative fix for <rdar://problem/6630134> Crash at + Editor::compositionRange() + + * WebView/WebHTMLView.mm: + (-[WebHTMLView markedRange]): Null-check the Frame like most other + methods in this class. + +2009-03-23 Sam Weinig <sam@webkit.org> + + Reviewed by Dan Bernstein. + + Fix for <rdar://problem/6140966> + Empty Caches does not clear the Cross-site XMLHttpRequest preflight cache + + * Misc/WebCache.mm: + (+[WebCache empty]): + +2009-03-23 Adele Peterson <adele@apple.com> + + Reviewed by Mark Rowe & Dave Hyatt. + + Merge some of the individual Mail quirks into two settings that we can check for future quirks. + + * WebView/WebView.mm: + (runningLeopardMail): + (runningTigerMail): + (-[WebView _preferencesChangedNotification:]): + +2009-03-23 Darin Adler <darin@apple.com> + + * WebView/WebTextIterator.h: Fixed a spelling error in a comment. + +2009-03-22 Dan Bernstein <mitz@apple.com> + + Reviewed by John Sullivan. + + - fix <rdar://problem/6640741> Messages not displaying after the + Safari 4 beta was installed + + Mail assumes that if -[WebArchive subresources] is not nil, then it + contains at least one object. + + * WebView/WebArchive.mm: + (-[WebArchive subresources]): Preserve the behavior of returning nil + if there are no subresources. + +2009-03-20 Adele Peterson <adele@apple.com> + + Build fix. + + Reviewed by Darin Adler. + + * WebView/WebFrameView.mm: (-[WebFrameView initWithFrame:]): + +2009-03-20 Timothy Hatcher <timothy@apple.com> + + Change how threading exceptions are checked so they are reported + by what round they were added. That way WebKit can decided the + behavior per-round based on linked-on-or-after checks. + + <rdar://problem/6626741&6648478&6635474&6674079> + + Reviewed by Darin Adler. + + * History/WebBackForwardList.mm: Use the new WebCoreThreadViolationCheckRoundOne macro. + * History/WebHistoryItem.mm: Ditto. + * Misc/WebIconDatabase.mm: Ditto. + + * WebView/WebArchive.mm: Use the new WebCoreThreadViolationCheckRoundTwo macro. + * WebView/WebResource.mm: Ditto. + (+[WebResource _needMailThreadWorkaroundIfCalledOffMainThread]): Check Mail's bundle version + to truly decide if it is an old Mail client. + * WebView/WebView.mm: Ditto. + + * Misc/WebKitVersionChecks.h: Add a new linked-on-or-after version define. + * WebView/WebFrameView.mm: + (-[WebFrameView initWithFrame:]): Set the default thread violation behavior per-round + based on difference version checks and the Mail workaround check. + +2009-03-20 Darin Adler <darin@apple.com> + + Reviewed by Timothy Hatcher. + + * WebView/WebTextIterator.h: Improved comments to point out some of the pitfalls + of this SPI. + +2009-03-20 Darin Adler <darin@apple.com> + + Reviewed by Adele Peterson. + + Use a better technique to handle finding out if something responds to a selector + in WebHTMLView's doCommandBySelector method. + + * WebView/WebHTMLView.mm: + (-[WebHTMLView doCommandBySelector:]): Removed unneeded check for 0 coreFrame; + this is already handled by coreCommandBySelector: so doesn't need to be checked + twice. Got rid of initial value for eventWasHandled boolean to make it more clear. + Use WebResponderChainSink to find out if a command is handled rather than walking + the responder chain explicitly. + (-[WebResponderChainSink initWithResponderChain:]): Added. + (-[WebResponderChainSink detach]): Added. + (-[WebResponderChainSink receivedUnhandledCommand]): Added. + (-[WebResponderChainSink noResponderFor:]): Added. + (-[WebResponderChainSink doCommandBySelector:]): Added. + +2009-03-19 Timothy Hatcher <timothy@apple.com> + + Remove #ifndef BUILDING_ON_TIGER around code that schedules runloop modes + for Page, so the new RunLoopTimer in WebCore always gets a default mode. + Fixes the layout test failures on the Tiger build bots. + + Reviewed by Mark Rowe. + + * WebView/WebView.mm: + (-[WebView _commonInitializationWithFrameName:groupName:usesDocumentViews:]): + (-[WebView scheduleInRunLoop:forMode:]): + (-[WebView unscheduleFromRunLoop:forMode:]): + +2009-03-18 Anders Carlsson <andersca@apple.com> + + Reviewed by Oliver Hunt. + + WebKit side of <rdar://problem/6688244>. + + Try reinitializing the vendor port if it's invalid. + + * Plugins/Hosted/NetscapePluginHostManager.mm: + (WebKit::NetscapePluginHostManager::spawnPluginHost): + +2009-03-18 Anders Carlsson <andersca@apple.com> + + Reviewed by Darin Adler. + + <rdar://problem/6504776> + CrashTracer: [USER] 188 crashes in Safari at com.apple.WebCore • WTF::HashTableIterator<WTF::RefPtr<WebCore::ResourceLoader>, ... + + If the m_pluginView member was zeroed out as a result of making a call into the plug-in, the pluginFunctionCallDepth would be off + causing the plug-in never to be stopped. Simplify the code by using a RAII object. + + * Plugins/WebBaseNetscapePluginStream.mm: + (PluginStopDeferrer::PluginStopDeferrer): + (PluginStopDeferrer::~PluginStopDeferrer): + (WebNetscapePluginStream::startStream): + (WebNetscapePluginStream::wantsAllStreams): + (WebNetscapePluginStream::destroyStream): + +2009-03-17 Darin Adler <darin@apple.com> + + Reviewed by Adele Peterson. + + <rdar://problem/6687005> Need support for new move-left/right selectors. + + * WebView/WebHTMLView.mm: Added the four new selectors to the command-forwarding list. + * WebView/WebView.mm: Ditto. + +2009-03-17 Darin Adler <darin@apple.com> + + Reviewed by Adele Peterson. + + Bug 24477: REGRESSION (r41467): Page Down key scrolls two pages + https://bugs.webkit.org/show_bug.cgi?id=24477 + rdar://problem/6674184 + + * WebView/WebHTMLView.mm: + (responderChainRespondsToSelector): Added. + (-[WebHTMLView doCommandBySelector:]): Set eventWasHandled based on whether we + can find a responder that responds to this selector rather than always assuming + the selector will not be handled. + +2009-03-17 Mark Rowe <mrowe@apple.com> + + Fix the build. + + * Plugins/Hosted/HostedNetscapePluginStream.mm: + +2009-03-17 David Kilzer <ddkilzer@apple.com> + + Use -[NSURLResponse(WebCoreURLResponse) _webcore_MIMEType] consistently + + Reviewed by Darin Adler. + + WebKit r30323 added -_webcore_MIMEType to fix issues with + incorrect MIME types in NS[HTTP]URLResponse objects. However, + uses of -[NSURLResponse MIMEType] still persist in WebKit that + should be switched to use -_webcore_MIMEType. Note that + -[WebDataSource _responseMIMEType] calls back into WebCore to + get the MIME type from the ResourceResponse object, which has + already retrieved it via -_webcore_MIMEType. + + * Plugins/Hosted/HostedNetscapePluginStream.mm: + (WebKit::HostedNetscapePluginStream::didReceiveResponse): Use + -_webcore_MIMEType. + * Plugins/WebBaseNetscapePluginStream.mm: + (WebNetscapePluginStream::didReceiveResponse): Ditto. + * Plugins/WebNetscapePluginView.mm: + (-[WebNetscapePluginView pluginView:receivedData:]): Ditto. + * Plugins/WebPluginController.mm: + (-[WebPluginController pluginView:receivedResponse:]): Ditto. + * WebView/WebHTMLRepresentation.mm: + (-[WebHTMLRepresentation _isDisplayingWebArchive]): Use + -[WebDataSource _responseMIMEType] instead. + * WebView/WebPDFRepresentation.m: + (-[WebPDFRepresentation finishedLoadingWithDataSource:]): Ditto. + * WebView/WebPDFView.mm: + (-[WebPDFView menuForEvent:]): Ditto. + +2009-03-17 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Darin Adler + + https://bugs.webkit.org/show_bug.cgi?id=24396 + + Add WTF_USE_ACCELERATED_COMPOSITING, defined to 0 for now. + + * WebKitPrefix.h: + +2009-03-17 Kevin Ollivier <kevino@theolliviers.com> + + Reviewed by Mark Rowe. + + Get BUILDING_ON_* defines from Platform.h. + + https://bugs.webkit.org/show_bug.cgi?id=24630 + + * WebKitPrefix.h: + +2009-03-16 Darin Adler <darin@apple.com> + + Reviewed by Dan Bernstein. + + <rdar://problem/6577174> Rename the text directionality submenus to “Paragraph Direction†and “Selection Direction†+ + * WebCoreSupport/WebViewFactory.mm: + (-[WebViewFactory contextMenuItemTagParagraphDirectionMenu]): Changed string here, but only + post-Leopard, since we want this to match the Mac OS X menu on Tiger and Leopard. + (-[WebViewFactory contextMenuItemTagSelectionDirectionMenu]): Changed string here. + +2009-03-16 Anders Carlsson <andersca@apple.com> + + Reviewed by Oliver Hunt. + + Don't mig_deallocate random data in case an instance proxy method returns false. + + * Plugins/Hosted/NetscapePluginHostProxy.mm: + (WKPCEvaluate): + (WKPCInvoke): + (WKPCInvokeDefault): + (WKPCGetProperty): + (WKPCEnumerate): + +2009-03-16 Anders Carlsson <andersca@apple.com> + + Reviewed by Oliver Hunt. + + <rdar://problem/6633944> + REGRESSION (Safari 4 PB): Many crashes in Flip4Mac involving loading the plugin + + Defer loading while calling webPlugInInitialize since it can end up spinning the run loop. + + * Plugins/WebPluginController.mm: + (-[WebPluginController addPlugin:]): + +2009-03-16 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. + + Fix <rdar://problem/6622601> + + Make sure to update both the window frame and the plug-in frame. + + * Plugins/Hosted/WebHostedNetscapePluginView.mm: + (-[WebHostedNetscapePluginView addWindowObservers]): + +2009-03-15 Dan Bernstein <mitz@apple.com> + + Reviewed by Adele Peterson. + + - fix <rdar://problem/6607773> WebKit should support the "Default" + paragraph writing direction -- or at least validate the menu item + appropriately + + Made WebHTMLView validate user interface items with the selector + -makeBaseWritingDirectionNatural: by returning NO and, if the item is + a menu item, setting its state to "off". + + Strictly speaking, since -makeBaseWritingDirectionNatural: is never + valid for WebViews, WebHTMLView should not need to respond to it and + validate it, however because other responders respond to all three + -makeBaseWritingDirection*: messages and set the menu item state, having + WebHTMLView do the same makes application developers' lives easier. + + * WebView/WebHTMLView.mm: + (-[WebHTMLView validateUserInterfaceItemWithoutDelegate:]): + (-[WebHTMLView makeBaseWritingDirectionNatural:]): + +2009-03-13 Mark Rowe <mrowe@apple.com> + + Rubber-stamped by Dan Bernstein. + + Take advantage of the ability of recent versions of Xcode to easily switch the active + architecture. + + * Configurations/DebugRelease.xcconfig: + +2009-03-13 Anders Carlsson <andersca@apple.com> + + Reviewed by Kevin Decker and Geoffrey Garen. + + <rdar://problem/6590384> + REGRESSION (Safari 3-4): Tiger-only Crash occurs at WebView hostWindow () after reloading a set of tabs then quitting + + When we're doing fast teardown, plug-in views can be destroyed from -[WebView dealloc]'s [super dealloc] call, + and thus calling -[WebView hostWindow] will crash since _private is nil. + + * WebView/WebView.mm: + (-[WebView hostWindow]): + +2009-03-13 Anders Carlsson <andersca@apple.com> + + And yet another attempt... + + * Plugins/WebNetscapePluginEventHandlerCocoa.h: + (WebNetscapePluginEventHandlerCocoa::installKeyEventHandler): + (WebNetscapePluginEventHandlerCocoa::removeKeyEventHandler): + * Plugins/WebNetscapePluginEventHandlerCocoa.mm: + +2009-03-13 Anders Carlsson <andersca@apple.com> + + Another attempt at fixing the build. + + * Plugins/WebNetscapePluginEventHandlerCocoa.mm: + (WebNetscapePluginEventHandlerCocoa::WebNetscapePluginEventHandlerCocoa): + +2009-03-13 Anders Carlsson <andersca@apple.com> + + Try to fix the SL build. + + * Plugins/WebNetscapePluginEventHandlerCocoa.h: + * Plugins/WebNetscapePluginEventHandlerCocoa.mm: + (WebNetscapePluginEventHandlerCocoa::keyDown): + +2009-03-13 Greg Bolsinga <bolsinga@apple.com> + + Reviewed by Simon Fraser. + + Update Geolocation perimission dialogs to be asynchronous. + https://bugs.webkit.org/show_bug.cgi?id=24505 + + WebGeolocation is a wrapper around WebCore::Geolocation. It mimics the + coding style set by WebSecurityOrigin. + + WebChromeClient now calls the private UI delegate method + -webView:frame:requestGeolocationPermission:securityOrigin: + + * WebCoreSupport/WebChromeClient.h: + * WebCoreSupport/WebChromeClient.mm: + (WebChromeClient::requestGeolocationPermissionForFrame): + * WebCoreSupport/WebGeolocation.mm: Added. + (WebCore::if): + (-[WebGeolocation shouldClearCache]): + (-[WebGeolocation setIsAllowed:]): + (-[WebGeolocation dealloc]): + * WebCoreSupport/WebGeolocationInternal.h: Added. + * WebCoreSupport/WebGeolocationPrivate.h: Added. + * WebView/WebUIDelegatePrivate.h: + +2009-03-13 Anders Carlsson <andersca@apple.com> + + Reviewed by Dan Bernstein. + + <rdar://problem/6610666> Revise the Cocoa event model text API + + Replace the text input API with a simpler API that uses a separate text input window. + + * Plugins/WebNetscapePluginEventHandlerCocoa.h: + * Plugins/WebNetscapePluginEventHandlerCocoa.mm: + (WebNetscapePluginEventHandlerCocoa::WebNetscapePluginEventHandlerCocoa): + Initialize m_keyEventHandler to 0. + + (WebNetscapePluginEventHandlerCocoa::keyDown): + If the plug-in returns 0 from NPP_HandleEvent, pass the event to the TSM machinery. + + (WebNetscapePluginEventHandlerCocoa::focusChanged): + Install/remove the key event handler as needed. + + (WebNetscapePluginEventHandlerCocoa::handleTSMEvent): + Get the text and send a TextInput event. + + * Plugins/WebNetscapePluginView.h: + * Plugins/WebNetscapePluginView.mm: + Remove the old text input API. + + (-[WebNetscapePluginView inputContext]): + Always return nil here. + + * Plugins/npapi.mm: + * Plugins/nptextinput.h: Removed. + +2009-03-12 Anders Carlsson <andersca@apple.com> + + Reviewed by Mike Thole and Mark Rowe. + + Fix <rdar://problem/6624105>. + + Make sure to process incoming messages for the NSEventTrackingRunLoopMode as well. + + * Plugins/Hosted/NetscapePluginHostProxy.mm: + (WebKit::NetscapePluginHostProxy::NetscapePluginHostProxy): + +2009-03-12 Anders Carlsson <andersca@apple.com> + + Reviewed by Geoffrey Garen. + + WebKit side of <rdar://problem/6607801> + + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::destroy): + Pass a requestID to _WKPCDestroyPluginInstance and wait until we get a reply back. + + * Plugins/Hosted/WebKitPluginHost.defs: + Add requestID parameter. + +2009-03-12 Kevin Decker <kdecker@apple.com> + + Reviewed by Anders Carlsson. + + * Plugins/WebNetscapePluginPackage.mm: + (-[WebNetscapePluginPackage _unloadWithShutdown:]): Simply a small SUPPORT_CFM code block. + +2009-03-12 Kevin Decker <kdecker@apple.com> + + Reviewed by Anders Carlsson. + + Fixed: <rdar://problem/5815862> Opening a subclassed NSWindow from a Safari plugin causes Safari to crash on Quit + + This fix addresses crashes in both Silverlight and ChemDraw. This type of crash would occur because AppKit still + had a reference to open windows that the plugin created (which no longer exist). + + * Plugins/WebNetscapePluginPackage.mm: + (-[WebNetscapePluginPackage _unloadWithShutdown:]): Do not unload the plug-in bundle on browser shutdown. + +2009-03-11 David Kilzer <ddkilzer@apple.com> + + Remove duplicate header include + + Rubber-stamped by Mark Rowe. + + * WebView/WebView.mm: Remove duplicate #include <runtime/InitializeThreading.h>. + Also realphabetized lowercase #include statements. + +2009-03-11 David Kilzer <ddkilzer@apple.com> + + Clarify comments regarding order of FEATURE_DEFINES + + Rubber-stamped by Mark Rowe. + + * Configurations/WebKit.xcconfig: Added warning about the + consequences when FEATURE_DEFINES are not kept in sync. + +2009-03-11 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. + + WebKit side of <rdar://problem/6656147>. + + * Plugins/Hosted/NetscapePluginHostManager.mm: + (WebKit::NetscapePluginHostManager::instantiatePlugin): + Pass the requestID to _WKPHInstantiatePlugin. + + * Plugins/Hosted/NetscapePluginHostProxy.mm: + Pass the requestID to setCurrentReply. + + * Plugins/Hosted/NetscapePluginInstanceProxy.h: + (WebKit::NetscapePluginInstanceProxy::setCurrentReply): + Store the reply in a map with the requestID as the key. + + (WebKit::NetscapePluginInstanceProxy::waitForReply): + Wait for a reply that matches the given requestID. + + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::NetscapePluginInstanceProxy): + Initialize member variables. + + (WebKit::NetscapePluginInstanceProxy::~NetscapePluginInstanceProxy): + Delete all requests. + + (WebKit::NetscapePluginInstanceProxy::print): + Pass the requestID to _WKPHPluginInstancePrint. + + (WebKit::NetscapePluginInstanceProxy::loadRequest): + Rename m_currentRequestID to m_currentURLRequestID. + + (WebKit::NetscapePluginInstanceProxy::processRequestsAndWaitForReply): + Process requests until we find a reply with the right requestID. + + (WebKit::NetscapePluginInstanceProxy::createBindingsInstance): + Pass a requestID to the _WKPH function. + + (WebKit::NetscapePluginInstanceProxy::nextRequestID): + Ditto. + + * Plugins/Hosted/ProxyInstance.mm: + Pass a requestID to the _WKPH functions. + + * Plugins/Hosted/WebKitPluginClient.defs: + * Plugins/Hosted/WebKitPluginHost.defs: + Add requestID parameters. + +2009-03-11 Anders Carlsson <andersca@apple.com> + + Reviewed by Darin Adler. + + Fix <rdar://problem/6620064>. + + * Plugins/WebPluginContainerPrivate.h: + +2009-03-10 Xan Lopez <xlopez@igalia.com> + + Build fix, no review. + + * WebView/WebFrame.mm: + (-[WebFrame _smartDeleteRangeForProposedRange:]): + +2009-03-09 Anders Carlsson <andersca@apple.com> + + Reviewed by Kevin Decker. + + WebKit side of <rdar://problem/6530007> + + * Plugins/Hosted/NetscapePluginHostProxy.mm: + (WKPCEnumerate): + Call NetscapePluginInstanceProxy::enumerate. + + * Plugins/Hosted/NetscapePluginInstanceProxy.h: + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::enumerate): + Enumerate the JS object and serialize its values. + + * Plugins/Hosted/ProxyInstance.h: + * Plugins/Hosted/ProxyInstance.mm: + (WebKit::ProxyInstance::getPropertyNames): + Ask the plug-in host to get the property names and deserialize them. + + * Plugins/Hosted/WebKitPluginClient.defs: + * Plugins/Hosted/WebKitPluginHost.defs: + +2009-03-09 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Oliver Hunt and Cameron Zwarich + + https://bugs.webkit.org/show_bug.cgi?id=24440 + + The sublayer added to WebHTMLView to host accelerated compositing layers needs to + be a subclass of NSView which allows context menu clicks through. + + * WebView/WebHTMLView.mm: + (-[WebLayerHostingView rightMouseDown:]): + (-[WebHTMLView attachRootLayer:]): + +2009-03-08 Mark Rowe <mrowe@apple.com> + + Reviewed by Oliver Hunt. + + Split ScrollAlignment and ScrollBehavior out of RenderLayer.h so that + Frame.h no longer needs to include it. This cuts the size of the symbols + for a debug build by around 3%. + + * Plugins/WebNetscapePluginView.mm: + * WebView/WebFrame.mm: + (-[WebFrame _scrollDOMRangeToVisible:]): + (-[WebFrame _insertParagraphSeparatorInQuotedContent]): + (-[WebFrame _replaceSelectionWithFragment:selectReplacement:smartReplace:matchStyle:]): + * WebView/WebHTMLView.mm: + (-[WebHTMLView jumpToSelection:]): + (-[WebHTMLView centerSelectionInVisibleArea:]): + +2009-03-07 Dan Bernstein <mitz@apple.com> + + Reviewed by Alexey Proskuryakov. + + - fix a bug where debug builds were clearing the HTML5 application cache + on application termination + + * WebView/WebView.mm: + (-[WebView _close]): Call -[WebCache setDisabled:YES] instead of + -[WebCache empty]. + +2009-03-06 Douglas R. Davidson <ddavidso@apple.com> + + Reviewed by Justin Garcia. + + https://bugs.webkit.org/show_bug.cgi?id=24108 + + Update spelling and grammar checking to use the new combined text + checking (with automatic language identification) on Snow Leopard. + + * WebCoreSupport/WebEditorClient.h: + * WebCoreSupport/WebEditorClient.mm: + (WebEditorClient::checkSpellingAndGrammarOfParagraph): + +2009-03-05 Adele Peterson <adele@apple.com> + + Reviewed by Darin Adler. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=24079 + <rdar://problem/6611233> REGRESSION (r39549): Page loads cannot be interrupted with Command-. or Escape + <rdar://problem/6636563> Ctrl-tab shortcut doesn't switch tabs when focus is in text field + + * WebView/WebHTMLView.mm: (-[WebHTMLView doCommandBySelector:]): + If WebKit does not support the command, we need to pass the selector to super. In this case, + we'll consider the event not to be handled. This is not perfect because in theory, [super doCommandBySelector:] + can do some action that would cause WebKit to need to consider the event handled. But in practice, I've found no + example of that happening and causing broken behavior. + +2009-03-04 Mark Rowe <mrowe@apple.com> + + Reviewed by Dan Bernstein. + + <rdar://problem/6206172> Adoption of new Cocoa API for dictionary contextual menu + + * WebView/WebHTMLView.mm: + (-[WebHTMLView _lookUpInDictionaryFromMenu:]): + +2009-03-04 Adam Barth <abath@webkit.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=24356 + + Fix WebKit style for allowUniversalAccessFromFileURLs. + + * WebView/WebPreferenceKeysPrivate.h: + * WebView/WebPreferences.mm: + (+[WebPreferences initialize]): + (-[WebPreferences allowUniversalAccessFromFileURLs]): + (-[WebPreferences setAllowUniversalAccessFromFileURLs:]): + * WebView/WebPreferencesPrivate.h: + * WebView/WebView.mm: + (-[WebView _preferencesChangedNotification:]): + +2009-03-03 David Kilzer <ddkilzer@apple.com> + + <rdar://problem/6581203> WebCore and WebKit should install the same set of headers during installhdrs phase as build phase + + Reviewed by Mark Rowe. + + The fix is to add INSTALLHDRS_COPY_PHASE = YES and + INSTALLHDRS_SCRIPT_PHASE = YES to WebKit.xcconfig, then to + make sure various build phase scripts work with the installhdrs + build phase. + + * Configurations/Base.xcconfig: Defined REAL_PLATFORM_NAME + based on PLATFORM_NAME to work around the missing definition on + Tiger. + * Configurations/WebKit.xcconfig: Added + WEBCORE_PRIVATE_HEADERS_DIR variable to remove definition of + UMBRELLA_FRAMEWORKS_DIR for Debug and Release builds in the + Xcode project file. Added INSTALLHDRS_COPY_PHASE = YES and + INSTALLHDRS_SCRIPT_PHASE = YES. + +2009-03-03 David Kilzer <ddkilzer@apple.com> + + Remove last vestiges of JAVASCRIPTCORE_PRIVATE_HEADERS_DIR from WebKit + + Reviewed by Adam Roben. + + Use of JAVASCRIPTCORE_PRIVATE_HEADERS_DIR was removed in r37465 + since NPAPI headers had migrated from JavaScriptCore to WebCore + before that. + + * Configurations/WebKit.xcconfig: Removed definition of + JAVASCRIPTCORE_PRIVATE_HEADERS_DIR used in Production builds. + +2009-03-03 Anders Carlsson <andersca@apple.com> + + Reviewed by Darin Adler. + + Fix <rdar://problem/6633834>. + + * Plugins/Hosted/NetscapePluginHostManager.mm: + (WebKit::NetscapePluginHostManager::instantiatePlugin): + Create a new plug-in instance if the plug-in host has crashed. + + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::invalidate): + Add a null check for the plug-in host proxy. + +2009-03-02 Sam Weinig <sam@webkit.org> + + Reviewed by Mark Rowe. + + Enable Geolocation (except on Tiger and Leopard). + + * Configurations/WebKit.xcconfig: + +2009-03-02 Anders Carlsson <andersca@apple.com> + + Reviewed by Dan Bernstein. + + WebKit part of <rdar://problem/6638658>. + + * Plugins/Hosted/NetscapePluginHostManager.h: + * Plugins/Hosted/NetscapePluginHostManager.mm: + (WebKit::NetscapePluginHostManager::createPropertyListFile): + Spawn the plug-in host and wait for it to create the property list. + + * Plugins/WebBasePluginPackage.mm: + (-[WebBasePluginPackage createPropertyListFile]): + Factor code out into a new method. + + (-[WebBasePluginPackage pListForPath:createFile:]): + Call the newly added createPropertyListFile method. + + * Plugins/WebNetscapePluginPackage.mm: + (-[WebNetscapePluginPackage createPropertyListFile]): + Tell the plug-in host manager to create a property list file for us. + +2009-03-02 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + Fix for <rdar://problem/6507404> Add Geolocation support. + + This is not yet turned on for any Mac platform. + + Add SPI to ask the embedding application whether to allow + Geolocation for an origin. + + * WebCoreSupport/WebChromeClient.h: + * WebCoreSupport/WebChromeClient.mm: + (WebChromeClient::shouldAllowGeolocationForFrame): + * WebView/WebUIDelegatePrivate.h: + +2009-03-02 Anders Carlsson <andersca@apple.com> + + Fix PowerPC build. + + * Plugins/WebNetscapePluginPackage.mm: + (-[WebNetscapePluginPackage _tryLoad]): + +2009-03-02 Anders Carlsson <andersca@apple.com> + + Reviewed by John Sullivan, Ada Chan. + + Factor loading code out into its own method and get rid of a bunch of gotos. + + * Plugins/WebNetscapePluginPackage.mm: + (-[WebNetscapePluginPackage _tryLoad]): + (-[WebNetscapePluginPackage load]): + +2009-03-02 Anders Carlsson <andersca@apple.com> + + Build fix. + + * Plugins/WebNetscapeDeprecatedFunctions.h: + +2009-03-02 Anders Carlsson <andersca@apple.com> + + Reviewed by John Sullivan. + + Rename WebNetscapePluginPackage.m to WebNetscapePluginPackage.mm + + * Plugins/WebNetscapePluginPackage.m: Removed. + * Plugins/WebNetscapePluginPackage.mm: Copied from mac/Plugins/WebNetscapePluginPackage.m. + +2009-03-01 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. + + WebKit side of <rdar://problem/6449689> + + Pass the visible name to the plug-in host. + + * Plugins/Hosted/NetscapePluginHostManager.mm: + (WebKit::NetscapePluginHostManager::spawnPluginHost): + +2009-02-27 Alice Liu <alice.liu@apple.com> + + Fix <rdar://problem/6531265> REGRESSION (r39185): adding ".jpeg" + extension to images that already have .jpg extension + + Reviewed by Oliver Hunt. + + * WebView/WebHTMLView.mm: + (-[NSString matchesExtensionEquivalent:]): + (-[WebHTMLView namesOfPromisedFilesDroppedAtDestination:]): + Relax the check for the proper extension to allow for known + equivalents, special-cased in matchesExtensionEquivalent function. + +2009-02-27 Anders Carlsson <andersca@apple.com> + + Reviewed by Geoffrey Garen. + + <rdar://problem/6631436> + CrashTracer: [USER] 1 crash in Safari at com.apple.WebKit • WebKit::NetscapePluginInstanceProxy::addValueToArray + 55 + + Port the NPN_Evaluate code over from WebCore instead of using the frame loader. + + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::evaluate): + +2009-02-27 Anders Carlsson <andersca@apple.com> + + Reviewed by Geoffrey Garen. + + WebKit side of <rdar://problem/6626814>. + + * Plugins/Hosted/NetscapePluginHostProxy.mm: + (WKPCInvokeDefault): + Make InvokeDefault async. + + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::addValueToArray): + Handle passing NPObjects back to the plug-in host. + + * Plugins/Hosted/ProxyInstance.h: + (WebKit::ProxyInstance::objectID): + Add objectID getter. + + * Plugins/Hosted/WebKitPluginClient.defs: + Make InvokeDefault a simpleroutine. + +2009-02-27 Timothy Hatcher <timothy@apple.com> + + Fixes an exception by null checking the WebResource before adding it to + the subresources array. + + <rdar://problem/5950769> Bug in [WebDataSource subresources] can throw an exception + + Reviewed by Geoff Garen and Anders Carlsson. + + * WebView/WebDataSource.mm: + (-[WebDataSource subresources]): Null check the WebResource before adding it. + +2009-02-27 Timothy Hatcher <timothy@apple.com> + + Adds a workaround for Automator creating a WebView from a secondary thread. + + <rdar://problem/6631951> REGRESSION (Safari 4 Beta): Automator crash on + secondary thread beneath -[WebView initWithFrame:frameName:groupName:] + + Reviewed by Geoff Garen. + + * WebView/WebView.mm: + (needsWebViewInitThreadWorkaround): Check for com.apple.Automator. + +2009-02-27 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Add a preference to reduce the power of file:// URLs. + + * WebView/WebPreferenceKeysPrivate.h: + * WebView/WebPreferences.mm: + (+[WebPreferences initialize]): + (-[WebPreferences allowUniversalAccessFromFileUrls]): + (-[WebPreferences setAllowUniversalAccessFromFileUrls:]): + * WebView/WebPreferencesPrivate.h: + * WebView/WebView.mm: + (-[WebView _preferencesChangedNotification:]): + +2009-02-27 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Anders Carlsson + + https://bugs.webkit.org/show_bug.cgi?id=24242 + + setCursor(), and resetCursorRects() on Tiger, were using global, not local + coordinates for elementAtPoint: + + * WebView/WebHTMLView.mm: + (resetCursorRects): + (setCursor): + +2009-02-27 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Add a preference to reduce the power of file:// URLs. + + * WebView/WebPreferenceKeysPrivate.h: + * WebView/WebPreferences.mm: + (+[WebPreferences initialize]): + (-[WebPreferences allowUniversalAccessFromFileUrls]): + (-[WebPreferences setAllowUniversalAccessFromFileUrls:]): + * WebView/WebPreferencesPrivate.h: + * WebView/WebView.mm: + (-[WebView _preferencesChangedNotification:]): + +2009-02-26 Adele Peterson <adele@apple.com> + + Reviewed by Geoff Garen. + + Fix for <rdar://problem/6618166> + https://bugs.webkit.org/show_bug.cgi?id=24216 + (REGRESSION r36919) Safari 4 Beta causes MSN Messenger's text entry field to lose focus after entering a message + + During a series of firstResponder changes, at some point while the WebHTMLView was losing first responder status, + we incorrectly marked the page as active, and then when the WebHTMLView became first responder again, setActive did nothing. + This change restores behavior from before r36919 to check if the WebHTMLView is in the middle of losing first responder when calling setActive. + + In addition to updating editing/selection/designmode-no-caret.html results, I also made sure the test cases that were + fixed in r36919 and r38570 are still fixed. + + * WebView/WebHTMLView.mm: + (-[WebHTMLView resignFirstResponder]): Keep track if we're in the process of resigning first responder. + (-[WebHTMLView _isResigningFirstResponder]): Added. + * WebView/WebHTMLViewInternal.h: + * WebView/WebView.mm: (-[WebView _updateFocusedAndActiveStateForFrame:]): Don't set the page to be active + if the document view is currently resigning first responder. + +2009-02-25 Anders Carlsson <andersca@apple.com> + + Reviewed by Kevin Decker. + + Fix <rdar://problem/6623697>. + + * Plugins/Hosted/NetscapePluginInstanceProxy.h: + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::print): + Ask the plug-in host to print, create a CGImage of the returned bytes and draw + the image into the passed in context. + + * Plugins/Hosted/WebHostedNetscapePluginView.mm: + (-[WebHostedNetscapePluginView drawRect:]): + When printing, call NetscapePluginInstanceProxy::print. + + * Plugins/Hosted/WebKitPluginHost.defs: + +2009-02-19 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=24024 + REGRESSION (r39845): Assertion failure in -[WebHistoryItem dictionaryRepresentation] when + archiving a submission to about:blank + + I don't know how to make an automated test for this bug. + + * History/WebHistory.mm: (-[WebHistory _visitedURL:withTitle:method:wasFailure:]): + Account for the fact that HTTP method may be non-empty for non-HTTP requests. + +2009-02-25 Chris Fleizach <cfleizach@apple.com> + + Reviewed by Beth Dakin. + + Naming change from + Bug 24143: Crash occurs at WebCore::AccessibilityTable::isTableExposableThroughAccessibility() when applying a link in GMail + https://bugs.webkit.org/show_bug.cgi?id=24143 + + * WebView/WebFrame.mm: + (-[WebFrame _accessibilityTree]): + +2009-02-25 Simon Fraser <simon.fraser@apple.com> + + Build fix with ACCELERATED_COMPOSITING turned on. + + I missed a spot in my last commit in renaming to + _stoppedAcceleratedCompositingForFrame: + + * WebView/WebHTMLView.mm: + (-[WebHTMLView close]): + +2009-02-25 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Dan Bernstein + + https://bugs.webkit.org/show_bug.cgi?id=23854 + + Make an observable property, _isUsingAcceleratedCompositing, on + WebView that DumpRenderTree can use to specialize behavior. + + This is implemented via a count of Frames that are using + accelerated compositing. + + * WebView/WebHTMLView.mm: + (-[WebHTMLViewPrivate clear]): + (-[WebHTMLView close]): + (-[WebHTMLView attachRootLayer:]): + (-[WebHTMLView detachRootLayer]): + * WebView/WebView.mm: + (+[WebView automaticallyNotifiesObserversForKey:]): + (-[WebView _startedAcceleratedCompositingForFrame:]): + (-[WebView _stoppedAcceleratedCompositingForFrame:]): + (-[WebView _isUsingAcceleratedCompositing]): + * WebView/WebViewInternal.h: + * WebView/WebViewPrivate.h: + +2009-02-24 Sam Weinig <sam@webkit.org> - 2009-02-18 Dan Bernstein <mitz@apple.com> + Reviewed by Geoffrey Garen. + + Related to <rdar://problem/6590295> + Allow disabling javascript: urls. + + * WebView/WebView.mm: + (-[WebView _setJavaScriptURLsAreAllowed:]): + * WebView/WebViewPrivate.h: + +2009-02-24 Mark Rowe <mrowe@apple.com> + + Reviewed by Oliver Hunt. + + <rdar://problem/6259220> Rename AVAILABLE_AFTER_WEBKIT_VERSION_3_1 (etc.) to match the other macros + + * Carbon/CarbonUtils.h: + * Carbon/HIWebView.h: + * Plugins/WebPlugin.h: + * Plugins/WebPluginViewFactory.h: + * WebView/WebUIDelegate.h: + +2009-02-24 Peter Ammon <pammon@apple.com> + + Reviewed by Mark Rowe. + + Fix <rdar://problem/6251410> Services can modify non-editable content in Safari + + * WebView/WebHTMLView.mm: + (-[WebHTMLView validRequestorForSendType:returnType:]): Return self only if we can handle + both the send and return type. We should also handle a nil send or return type by ignoring + the argument and returning whether we can handle the other type passed in. + +2009-02-23 Anders Carlsson <andersca@apple.com> + + Reviewed by Geoffrey Garen and Darin Adler. + + WebKit side of <rdar://problem/6613151>. + + Make sure to vm_deallocate all memory we get from MIG callbacks. + + * Plugins/Hosted/NetscapePluginHostProxy.mm: + (DataDeallocator::DataDeallocator): + (DataDeallocator::~DataDeallocator): + Add a simple deallocator class. + + (WKPCStatusText): + (WKPCLoadURL): + (WKPCBooleanAndDataReply): + (WKPCEvaluate): + (WKPCGetStringIdentifier): + (WKPCInvoke): + (WKPCInvokeDefault): + (WKPCConstruct): + (WKPCSetProperty): + Use the new deallocator class. + +2009-02-23 Anders Carlsson <andersca@apple.com> + + Reviewed by Darin Adler. + + Fix <rdar://problem/6450656>. + + * Plugins/Hosted/NetscapePluginInstanceProxy.h: + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::insertText): + Add insert text which just calls the new WKPH function. + + * Plugins/Hosted/WebHostedNetscapePluginView.mm: + (-[WebHostedNetscapePluginView inputContext]): + Get the input context from the shared input panel. + + (-[WebHostedNetscapePluginView keyDown:]): + Let the shared input panel have a go at the event first. + + * Plugins/Hosted/WebKitPluginHost.defs: + Add new InsertText function. + +2009-02-23 Mark Rowe <mrowe@apple.com> + + Fix the build after r41126. + + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::invoke): + (WebKit::NetscapePluginInstanceProxy::invokeDefault): + (WebKit::NetscapePluginInstanceProxy::construct): + +2009-02-22 Dan Bernstein <mitz@apple.com> + + Reviewed by Darin Adler. + + - fix <rdar://problem/5966123> REGRESSION (r30741): Generic Sun Applet loading logo appears half off screen + + * WebCoreSupport/WebFrameLoaderClient.mm: Correct a copy & paste error + in r30741, and assign the height value, rather than the width, to the + "height" parameter. + +2009-02-21 Anders Carlsson <andersca@apple.com> + + Fix build. + + * Plugins/Hosted/WebTextInputWindowController.m: + +2009-02-20 Anders Carlsson <andersca@apple.com> + + Reviewed by Dan Bernstein. + + Add a shared floating text input window implementation, to be used by the hosted plug-in view. + + * Plugins/Hosted/WebTextInputWindowController.h: Added. + * Plugins/Hosted/WebTextInputWindowController.m: Added. + +2009-02-20 Kevin Decker <kdecker@apple.com> + + Reviewed by andersca. + + <rdar://problem/6496140> Safari sometimes hangs in WKSetMetadataURL for several seconds after downloading a file + + Spawn a background thread for WKSetMetadataURL because this function will not return until mds has journaled the data + we are trying to set. Depending on what other I/O is going on, it can take some time. + + * Misc/WebNSFileManagerExtras.m: Import pthread.h and FoundationExtras.h + (setMetaData): Added. Calls WKSetMetadataURL(). + (-[NSFileManager _webkit_setMetadataURL:referrer:atPath:]): Call setMetaData on a background thread + +2009-02-19 Dan Bernstein <mitz@apple.com> + + Reviewed by Sam Weinig. + + - WebKit part of fixing https://bugs.webkit.org/show_bug.cgi?id=24027 + Do not send loader callbacks during CSS styling + + * WebView/WebView.mm: + (-[WebView _preferencesChangedNotification:]): Reverted the + iChat-specific quirk added in <http://trac.webkit.org/changeset/41071>. + +2009-02-18 Dan Bernstein <mitz@apple.com> Reviewed by Brady Eidson. @@ -12,30 +1218,154 @@ (-[WebView _preferencesChangedNotification:]): Activate the WebCore workaround for this crash in iChat. -2009-02-13 Mark Rowe <mrowe@apple.com> +2009-02-18 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. + + Fix for <rdar://problem/6542390> + + There's no need to call setDefersLoading here - we already defer anything a plug-in can do that + would cause a load to begin. + + * Plugins/WebNetscapePluginView.mm: + (-[WebNetscapePluginView sendEvent:isDrawRect:]): + +2009-02-18 Adam Roben <aroben@apple.com> + + Add SPI to get WebKit's custom pointing-hand cursor + + Reviewed by John Sullivan. + + * WebView/WebView.mm: + (+[WebView _pointingHandCursor]): Added. Returns the custom + pointing-hand cursor that WebKit uses. + * WebView/WebViewPrivate.h: Added +_pointingHandCursor. + +2009-02-17 Eric Carlson <eric.carlson@apple.com> + + Reviewed by Antti Koivisto. + + https://bugs.webkit.org/show_bug.cgi?id=23917 + Allow a WebKit plug-in to act as a proxy for the <audio> and <video> + element. - Merge r40940. + * Plugins/WebPluginContainerPrivate.h: + * Plugins/WebPluginController.mm: + (mediaProxyClient): New, cast to HTMLMediaElement if it is a video or audio element + (-[WebPluginController _setMediaPlayerProxy:forElement:]): New, pass proxy to HTMLMediaElement + (-[WebPluginController _postMediaPlayerNotification:forElement:]): New, deliver event to HTMLMediaElement + + * WebCoreSupport/WebFrameLoaderClient.mm: + (WebFrameLoaderClient::createPlugin): Don't allow a media player proxy plug-in to be chosen by + file extension, only want a match for the new MIME type proxy plug-ins should have. - 2009-02-12 Anders Carlsson <andersca@apple.com> +2009-02-13 Anders Carlsson <andersca@apple.com> Reviewed by Kevin Decker. - <rdar://problem/6579412> - REGRESSION (3.2.1-ToT): Crash in Silverlight viewing streaming lecture + <rdar://problem/6584834> ESPN radio live stream link hangs Safari + + When a plug-in invokes JavaScript code that will destroy the plug-in, we need to + defer destruction until we're done executing the script. + + * Plugins/Hosted/NetscapePluginHostProxy.mm: + (WebKit::PluginDestroyDeferrer::PluginDestroyDeferrer): + (WebKit::PluginDestroyDeferrer::~PluginDestroyDeferrer): + Add a simple RAII object for deferring destruction of the plug-in instance. + + (WKPCEvaluate): + (WKPCInvoke): + (WKPCInvokeDefault): + (WKPCConstruct): + (WKPCGetProperty): + (WKPCSetProperty): + (WKPCRemoveProperty): + (WKPCHasProperty): + (WKPCHasMethod): + Use the PluginDestroyDeferrer. + + * Plugins/Hosted/NetscapePluginInstanceProxy.h: + (WebKit::NetscapePluginInstanceProxy::pluginID): + Assert that the plug-in ID is not 0 here. + + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::NetscapePluginInstanceProxy): + Initialize the call depth. + + (WebKit::NetscapePluginInstanceProxy::~NetscapePluginInstanceProxy): + Set the plug-in ID to 0 to aid debugging. + + (WebKit::NetscapePluginInstanceProxy::willCallPluginFunction): + Increment the call depth. + + (WebKit::NetscapePluginInstanceProxy::didCallPluginFunction): + Decrement the call depth, if it's 0 and we should stop the plug-in, do so. + + (WebKit::NetscapePluginInstanceProxy::shouldStop): + If we're called this with a non-zero call depth, set shouldStopSoon to true. + + * Plugins/Hosted/WebHostedNetscapePluginView.mm: + (-[WebHostedNetscapePluginView shouldStop]): + Call the proxy. + +2009-02-12 Brady Eidson <beidson@apple.com> + + Reviewed by Kevin Decker + + <rdar://problem/6582180> - Wrong HTTP method applied to history item. + * WebCoreSupport/WebFrameLoaderClient.mm: + (WebFrameLoaderClient::updateGlobalHistory): Check the original request, not any + redirected request. + +2009-02-12 Anders Carlsson <andersca@apple.com> + + Reviewed by Kevin Decker. + + <rdar://problem/6579412> + REGRESSION (3.2.1-ToT): Crash in Silverlight viewing streaming lecture + * Plugins/WebNetscapePluginView.h: * Plugins/WebNetscapePluginView.mm: (-[WebNetscapePluginView userAgent]): Apply workaround for Silverlight workaround. - + (-[WebNetscapePluginView _createPlugin]): Check if the plug-in that we're creating is the silverlight plug-in. -2009-02-13 Mark Rowe <mrowe@apple.com> +2009-02-12 Brady Eidson <beidson@apple.com> - Merge r40920. + Reviewed by Darin Adler - 2009-02-12 Brady Eidson <beidson@apple.com> + Fix potential ref-count or null-deref problems with C++ objects as Obj-C members. + + * History/WebBackForwardList.mm: + (-[WebBackForwardList dealloc]): Null check before deref()'ing. + (-[WebBackForwardList finalize]): Ditto. + + * Misc/WebIconFetcher.mm: + (-[WebIconFetcher dealloc]): Null check before deref()'ing. + (-[WebIconFetcher finalize]): Ditto. + + * WebCoreSupport/WebEditorClient.mm: Change to use RefPtr<> instead of ref()/deref(). + (-[WebEditCommand initWithEditCommand:]): + (-[WebEditCommand dealloc]): + (-[WebEditCommand finalize]): + (-[WebEditCommand command]): + + * WebView/WebArchive.mm: Change to use RefPtr<> instead of ref()/deref(). + (-[WebArchivePrivate init]): + (-[WebArchivePrivate initWithCoreArchive:]): + (-[WebArchivePrivate coreArchive]): + (-[WebArchivePrivate setCoreArchive:]): + (-[WebArchivePrivate dealloc]): + (-[WebArchivePrivate finalize]): + + * WebView/WebDataSource.mm: + (-[WebDataSourcePrivate dealloc]): Null check before deref()'ing. + (-[WebDataSourcePrivate finalize]): Ditto. + +2009-02-12 Brady Eidson <beidson@apple.com> Reviewed by Kevin Decker @@ -51,22 +1381,14 @@ (-[WebArchivePrivate finalize]): Ditto (-[WebArchive initWithData:]): If the LegacyWebArchive cannot be created, return nil instead of an invalid object. -2009-02-12 Mark Rowe <mrowe@apple.com> - - Merge r40884. - - 2009-02-11 Mark Rowe <mrowe@apple.com> +2009-02-11 Mark Rowe <mrowe@apple.com> Fix the build. * History/WebHistory.mm: (-[WebHistoryPrivate visitedURL:withTitle:]): Use ASSERT_UNUSED in a manner that makes sense. -2009-02-12 Mark Rowe <mrowe@apple.com> - - Merge r40882. - - 2009-02-11 Brady Eidson <beidson@apple.com> +2009-02-11 Brady Eidson <beidson@apple.com> Reviewed by Mark Rowe @@ -84,17 +1406,41 @@ (-[WebHistoryPrivate addItems:]): (-[WebHistoryPrivate loadHistoryGutsFromURL:savedItemsCount:collectDiscardedItemsInto:error:]): -2009-02-11 Mark Rowe <mrowe@apple.com> +2009-02-11 Dimitri Dupuis-latour <dupuislatour@apple.com> - Merge r40851. + Added a preference to disable some Inspector's panels (rdar://6419624, rdar://6419645). + This is controlled via the 'WebKitInspectorHiddenPanels' key; if nothing is specified, all panels are shown. - 2009-02-10 John Sullivan <sullivan@apple.com> + Reviewed by Timothy Hatcher. - Reviewed by Dan Bernstein + * WebCoreSupport/WebInspectorClient.h: + * WebCoreSupport/WebInspectorClient.mm: + (WebInspectorClient::hiddenPanels): + +2009-02-11 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Darin Adler. + <rdar://problem/6562920> Pasted text should be normalized to NFC + + * Misc/WebNSURLExtras.mm: (-[NSURL _web_userVisibleString]): Route the URL string through + -[NSString precomposedStringWithCanonicalMapping]. + + * WebCoreSupport/WebPasteboardHelper.mm: + (WebPasteboardHelper::plainTextFromPasteboard): Ditto. + + * WebView/WebHTMLView.mm: + (-[WebHTMLView _documentFragmentFromPasteboard:forType:inContext:subresources:]): + Ditto. The affected cases are all plain text ones - RTF, RTFD and HTML are assumed to be + precomposed already, and the conversion is performed outside WebKit for those anyway. + +2009-02-10 John Sullivan <sullivan@apple.com> + + Reviewed by Dan Bernstein + <https://bugs.webkit.org/show_bug.cgi?id=23889>, <rdar://problem/6572300> Negative visit counts stored in History.plist aren't corrected. - + It's not clear how a huge negative visit count ended up in History.plist, but we can't trust data read from disk so we can at least reset this to something sane. WebCore has no guard against a visit count overflowing an int, but that seems very unlikely to have @@ -103,30 +1449,185 @@ * History/WebHistoryItem.mm: (-[WebHistoryItem initFromDictionaryRepresentation:]): If a negative visit count is in the dictionary, replace it with 1. If a negative daily or - weekly visit count is in the dictionary, replace it with 0. + weekly visit count is in the dictionary, replace it with 0. + +2009-02-10 John Sullivan <sullivan@apple.com> + + Reviewed by Dan Bernstein + + <https://bugs.webkit.org/show_bug.cgi?id=23891> + [WebHistoryItem _setVisitCount:] is unused and should be removed + + * History/WebHistoryItem.mm: + (-[WebHistoryItem _setVisitCount:]): + removed this unused method, which is a synonym for setVisitCount: that was introduced + recently and abandoned even more recently + + * History/WebHistoryItemInternal.h: + removed declaration of _setVisitCount: + +2009-02-10 Anders Carlsson <andersca@apple.com> + + Reviewed by Mark Rowe. + + <rdar://problem/6573916> + CrashTracer: [USER] 1 crash in Safari at com.apple.WebKit • WebKit::NetscapePluginInstanceProxy::pluginHostDied + 25. + + * Plugins/Hosted/NetscapePluginHostManager.mm: + (WebKit::NetscapePluginHostManager::instantiatePlugin): + If we failed to instantiate the plug-in, invalidate the instance proxy. + + * Plugins/Hosted/NetscapePluginInstanceProxy.h: + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::invalidate): + Remove the instance from the plug-in host's set. + + (WebKit::NetscapePluginInstanceProxy::destroy): + Call invalidate(). + +2009-02-09 Mark Rowe <mrowe@apple.com> + + Reviewed by Dan Bernstein. + + Fix <https://bugs.webkit.org/show_bug.cgi?id=23863> / <rdar://problem/6571390>. + Bug 23863: Reproducible crash in Mail with TOT WebKit when creating a new message + + * WebView/WebHTMLView.mm: + (-[WebHTMLView _removeMouseMovedObserverUnconditionally]): Nil-check _private as it may have not + yet been initialized if this WebHTMLView was loaded from a nib. + (-[WebHTMLView _removeSuperviewObservers]): Ditto. + +2009-02-09 Eric Seidel <eric@webkit.org> + + Reviewed by Dave Hyatt. + + Rename Selection to VisibleSelection to allow us to separate + the selections the user works with from the ones used by + the JS editing APIs. + https://bugs.webkit.org/show_bug.cgi?id=23852 + + * WebView/WebFrame.mm: + (-[WebFrame _selectNSRange:]): + * WebView/WebView.mm: + (-[WebView textIteratorForRect:]): + +2009-02-06 Anders Carlsson <andersca@apple.com> + + Reviewed by Kevin Decker. + + Fix crash when plug-in host dies. + + * Plugins/Hosted/HostedNetscapePluginStream.mm: + (WebKit::HostedNetscapePluginStream::didFail): + +2009-02-05 Eric Seidel <eric@webkit.org> + + Reviewed by Justin Garcia. + + DOMSelection.getRangeAt() returns a different range than the selection + https://bugs.webkit.org/show_bug.cgi?id=23601 + + Rename toRange to toNormalizedRange and add new firstRange which returns an unmodified range + + * WebView/WebFrame.mm: + (-[WebFrame _rangeByAlteringCurrentSelection:SelectionController::direction:SelectionController::granularity:]): + (-[WebFrame _markDOMRange]): + (-[WebFrame _replaceSelectionWithText:selectReplacement:smartReplace:]): + (-[WebFrame _selectedNSRange]): + * WebView/WebHTMLView.mm: + (-[WebHTMLView _selectedRange]): + (-[WebTextCompleteController doCompletion]): + (-[WebHTMLView selectedAttributedString]): + * WebView/WebView.mm: + (-[WebView textIteratorForRect:]): + (-[WebView selectedDOMRange]): + +2009-02-06 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Part III of <rdar://problem/6552272>. + + Refactored to use the redirect data WebCore makes available, instead of + tracking loading state in WebKit. + + * History/WebHistory.mm: + (-[WebHistoryPrivate dealloc]): + (-[WebHistory _visitedURL:withTitle:method:wasFailure:]): + (-[WebHistory _visitedURLForRedirectWithoutHistoryItem:]): + * History/WebHistoryInternal.h: + * WebCoreSupport/WebFrameLoaderClient.h: + * WebCoreSupport/WebFrameLoaderClient.mm: + (WebFrameLoaderClient::updateGlobalHistory): + (WebFrameLoaderClient::updateGlobalHistoryRedirectLinks): + +2009-02-06 Anders Carlsson <andersca@apple.com> -2009-02-06 Mark Rowe <mrowe@apple.com> + Reviewed by Sam Weinig. - Merge r40727. + <rdar://problem/6562220> + CrashTracer: [USER] 21 crashes in Safari at com.apple.WebKit • WebKit::NetscapePluginHostProxy::port + + Make the handling of crashes in the plug-in host more robust. + + * Plugins/Hosted/NetscapePluginHostProxy.h: + Add m_portSet. + + * Plugins/Hosted/NetscapePluginHostProxy.mm: + (WebKit::NetscapePluginHostProxy::NetscapePluginHostProxy): + Initialize m_portSet. + + (WebKit::NetscapePluginHostProxy::~NetscapePluginHostProxy): + Free m_portSet. + + (WebKit::NetscapePluginHostProxy::processRequests): + Listen for messages on the port set. If we get a message to the port death notification port, + then call pluginHostDied. Otherwise, process the message. + + * Plugins/Hosted/NetscapePluginInstanceProxy.h: + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::cleanup): + Factor code that should be shared between destroy() and pluginHostDied() into cleanup. + + (WebKit::NetscapePluginInstanceProxy::destroy): + Call cleanup(). + + (WebKit::NetscapePluginInstanceProxy::pluginHostDied): + Call cleanup(). + + (WebKit::NetscapePluginInstanceProxy::processRequestsAndWaitForReply): + Call NetscapePluginHostProxy::processRequests. + + * Plugins/Hosted/ProxyInstance.mm: + (WebKit::ProxyInstance::invalidate): + Add a null check for the host proxy. - 2009-02-06 Dan Bernstein <mitz@apple.com> +2009-02-06 Dan Bernstein <mitz@apple.com> - try to fix the Tiger build * Misc/WebNSArrayExtras.h: -2009-02-06 Mark Rowe <mrowe@apple.com> +2009-02-06 Anders Carlsson <andersca@apple.com> - Merge r40711. + Reviewed by Dan Bernstein. - 2009-02-05 Maciej Stachowiak <mjs@apple.com> and Brady Eidson <beidson@apple.com> + <rdar://problem/6563650> + Add Netscape plug-in API to tell the browser not to load streams (some plug-ins handle network loading manually) + + * Plugins/WebNetscapePluginView.mm: + (-[WebNetscapePluginView loadStream]): + (-[WebNetscapePluginView pluginView:receivedData:]): + (-[WebNetscapePluginView _shouldCancelSrcStream]): + +2009-02-05 Maciej Stachowiak <mjs@apple.com> and Brady Eidson <beidson@apple.com> Reviewed by Dan Bernstein and Geoff Garen. - WebKit code to track per-day and per-week visit counts in history For now this data is only exposed via SPI for performance reasons. - + * History/WebHistoryItem.mm: (-[WebHistoryItem initFromDictionaryRepresentation:]): Add parsing support for new data. @@ -145,41 +1646,190 @@ * Misc/WebNSArrayExtras.m: (-[NSArray _webkit_numberAtIndex:]): Helper to retrieve an NSNumber or nil from an NSArray (-[NSArray _webkit_stringAtIndex:]): Helper to retrieve an NSString of nil from an NSArray + +2009-02-05 Aaron Boodman <aa@chromium.org> + + Reviewed by Dave Hyatt. + + https://bugs.webkit.org/show_bug.cgi?id=23708 + Adds documentElementAvailable() callback to FrameLoaderClient. -2009-02-06 Mark Rowe <mrowe@apple.com> + * WebCoreSupport/WebFrameLoaderClient.h: + Stub out documentElementAvailable(). + * WebCoreSupport/WebFrameLoaderClient.mm: + Ditto. + +2009-02-05 Dan Bernstein <mitz@apple.com> + + - build fix - Merge r40680. + * WebView/WebScriptDebugger.mm: + (WebScriptDebugger::initGlobalCallFrame): - 2009-02-05 Beth Dakin <bdakin@apple.com> +2009-02-05 Beth Dakin <bdakin@apple.com> Reviewed by John Sullivan and Brady Eidson. - Fix for <rdar://problem/6557595> REGRESSION: In Mail, selecting a + Fix for <rdar://problem/6557595> REGRESSION: In Mail, selecting a mail note message doesn't display it in Mail's preview pane - This was failing because revision 36962 removed a version of - setVerticalScrollingMode that mail calls. This patch simply adds + This was failing because revision 36962 removed a version of + setVerticalScrollingMode that mail calls. This patch simply adds that method back. * WebView/WebDynamicScrollBarsView.m: (-[WebDynamicScrollBarsView setVerticalScrollingMode:]): -2009-02-03 Mark Rowe <mrowe@apple.com> +2009-02-04 Anders Carlsson <andersca@apple.com> + + Build fix fix. - Merge r40514. + * WebView/WebScriptDebugger.mm: + (WebScriptDebugger::initGlobalCallFrame): - 2009-02-02 Geoffrey Garen <ggaren@apple.com> +2009-02-04 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. + + Change PCHasProperty, PCHasMethod and PCGetProperty into simpleroutines. + + Rename PHEvaluateReply to PHBooleanAndDataReply and add PHBooleanReply. + + * Plugins/Hosted/NetscapePluginHostProxy.mm: + (WKPCEvaluate): + (WKPCInvoke): + (WKPCGetProperty): + (WKPCHasProperty): + (WKPCHasMethod): + * Plugins/Hosted/WebKitPluginClient.defs: + * Plugins/Hosted/WebKitPluginHost.defs: + +2009-02-04 Anders Carlsson <andersca@apple.com> + + Reviewed by Mark Rowe. + + Fix 64-bit build. + + * WebView/WebScriptDebugger.mm: + (WebScriptDebugger::initGlobalCallFrame): + +2009-02-04 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Mark Rowe. + + Part I of <rdar://problem/6552272>. + + Clear the redirectURLs entry when first visiting a site, so sites that + only redirect you the first time you visit them can later learn that + they don't redirect. + + * History/WebHistory.mm: + (-[WebHistory _visitedURL:withTitle:method:wasFailure:serverRedirectURL:isClientRedirect:]): + +2009-02-04 Timothy Hatcher <timothy@apple.com> + + Change the WebSourceId typedef from int to intptr_t now that <rdar://problem/6263297> is fixed. + + <rdar://problem/6263293> WebScriptDebugDelegate should use intptr_t for sourceId, not int + + Reviewed by Oliver Hunt. + + * WebView/WebScriptDebugDelegate.h: + +2009-02-04 Timothy Hatcher <timothy@apple.com> + + Switched over from using the WebSafeForwarder for the Script Debug + delegate and added high performance CallScriptDebugDelegate functions. + + <rdar://problem/6508457> Launching widget in Dashcode debugger is + super-slow due forwardInvocation: calling debug delegate + + Reviewed by Oliver Hunt. + + * DefaultDelegates/WebDefaultScriptDebugDelegate.h: Removed. + * DefaultDelegates/WebDefaultScriptDebugDelegate.m: Removed. + * WebView/WebScriptDebugger.mm: + (WebScriptDebugger::initGlobalCallFrame): Use CallScriptDebugDelegate. + (WebScriptDebugger::sourceParsed): Ditto. + (WebScriptDebugger::callEvent): Ditto. + (WebScriptDebugger::atStatement): Ditto. + (WebScriptDebugger::returnEvent): Ditto. + (WebScriptDebugger::exception): Ditto. + * WebView/WebView.mm: + (-[WebViewPrivate dealloc]): Removed scriptDebugDelegateForwarder. + (-[WebView _cacheScriptDebugDelegateImplementations]): Added. Gets the + method implementations for the script debug delegate. Also caches what + didParseSource method to use. + (WebViewGetScriptDebugDelegateImplementations): Added. Returns the + WebScriptDebugDelegateImplementations structure. + (-[WebView setScriptDebugDelegate:]): Call _cacheScriptDebugDelegateImplementations. + (CallDelegate): Added more overloaded versions that take different arguments. + (CallScriptDebugDelegate): Added overloaded versions that take different arguments. + * WebView/WebViewInternal.h: + +2009-02-03 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Dave Hyatt + + https://bugs.webkit.org/show_bug.cgi?id=23365 + + Hook up accelerated compositing layers the native + view system on Mac. + + * WebCoreSupport/WebChromeClient.h: + * WebCoreSupport/WebChromeClient.mm: + (WebChromeClient::attachRootGraphicsLayer): + (WebChromeClient::setNeedsOneShotDrawingSynchronization): + New methods to hook up the root GraphicsLayer to the native + view system, and to synchronize layer changes with view-based + drawing when layers come and go. + + * WebView/WebHTMLView.mm: + (-[WebHTMLViewPrivate clear]): + Clear the pointer to layerHostingView. + + (-[WebHTMLView _setAsideSubviews]): + (-[WebHTMLView willRemoveSubview:]): + Keep the special layer-hosting view in the subviews even + when the rest of the subviews are ripped out for + painting. + + (-[WebHTMLView _isUsingAcceleratedCompositing]): + New utility method for DumpRenderTree to know if we're + hosting layers. + + (-[WebHTMLView drawRect:]): + Call -disableScreenUpdatesUntilFlush if we have to + synchronize layer changes with painting. + + (-[WebHTMLView attachRootLayer:]): + (-[WebHTMLView detachRootLayer]): + Attach and detach the root GraphicsLayer. + + * WebView/WebViewInternal.h: + * WebView/WebHTMLViewInternal.h: + * WebView/WebHTMLViewPrivate.h: + New method declarations. + + * WebView/WebView.mm: + (-[WebView _needsOneShotDrawingSynchronization]): + (-[WebView _setNeedsOneShotDrawingSynchronization:]): + Set the flag to say if we need to synchronize layer + changes and painting on the next -drawRect: call. + + (-[WebView viewWillMoveToWindow:]): + (-[WebView viewDidMoveToWindow]): + Call new notifications that the view was added to or removed from + the window, which are required by the layer hosting mechanism. + +2009-02-02 Geoffrey Garen <ggaren@apple.com> Build fix. * Plugins/WebPluginController.mm: (-[WebPluginController webPlugInContainerLoadRequest:inFrame:]): -2009-02-03 Mark Rowe <mrowe@apple.com> - - Merge r40508. - - 2009-02-02 Geoffrey Garen <ggaren@apple.com> +2009-02-02 Geoffrey Garen <ggaren@apple.com> Reviewed by Sam Weinig. @@ -208,54 +1858,210 @@ (-[WebFrame _loadData:MIMEType:textEncodingName:baseURL:unreachableURL:]): * WebView/WebFramePrivate.h: Updated for rename and extra parameter. -2009-02-03 Mark Rowe <mrowe@apple.com> +2009-02-02 Anders Carlsson <andersca@apple.com> - Merge r40382. + Reviewed by Dan Bernstein. - 2009-01-29 Sam Weinig <sam@webkit.org> + Work around a limitation in MIG where two functions can't have the same name even if they're + not in the same subsystem. + + * Plugins/Hosted/NetscapePluginHostProxy.mm: + (WebKit::NetscapePluginHostProxy::NetscapePluginHostProxy): + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::processRequestsAndWaitForReply): + * Plugins/Hosted/WebKitPluginClient.defs: + * Plugins/Hosted/WebKitPluginHost.defs: - Reviewed by Anders Carlsson. +2009-02-02 Anders Carlsson <andersca@apple.com> - Second step in tracking the urls a HistoryItem was redirected through - Add SPI to access the array of redirect urls associated with a HistoryItem. + Reviewed by Sam Weinig. - * History/WebHistoryItem.mm: - (-[WebHistoryItem dictionaryRepresentation]): - (-[WebHistoryItem _redirectURLs]): - * History/WebHistoryItemPrivate.h: + Implement WKPCGetPluginElementObject. + + * Plugins/Hosted/NetscapePluginHostProxy.mm: + (WKPCGetPluginElementNPObject): + * Plugins/Hosted/NetscapePluginInstanceProxy.h: + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::getPluginElementNPObject): + * Plugins/Hosted/WebKitPluginClient.defs: + * Plugins/WebBaseNetscapePluginView.h: + * Plugins/WebBaseNetscapePluginView.mm: + (-[WebBaseNetscapePluginView WebCore::]): + +2009-02-02 Anders Carlsson <andersca@apple.com> + + Build fix. + + * WebView/WebHTMLView.mm: + +2009-02-02 Anders Carlsson <andersca@apple.com> + + Reviewed by Dan Bernstein. + + Make WebBaseNetscapePluginView hold a reference to a HTMLPlugInElement instead of a DOMElement. + + * Plugins/Hosted/WebHostedNetscapePluginView.h: + * Plugins/Hosted/WebHostedNetscapePluginView.mm: + (-[WebHostedNetscapePluginView initWithFrame:pluginPackage:URL:baseURL:MIMEType:attributeKeys:attributeValues:loadManually:element:WebCore::]): + * Plugins/WebBaseNetscapePluginView.h: + * Plugins/WebBaseNetscapePluginView.mm: + (-[WebBaseNetscapePluginView initWithFrame:pluginPackage:URL:baseURL:MIMEType:attributeKeys:attributeValues:loadManually:element:WebCore::]): + (-[WebBaseNetscapePluginView _windowClipRect]): + (-[WebBaseNetscapePluginView visibleRect]): + (-[WebBaseNetscapePluginView dataSource]): + * Plugins/WebKitPluginContainerView.h: Removed. + * Plugins/WebKitPluginContainerView.mm: Removed. + * Plugins/WebNetscapePluginView.h: + * Plugins/WebNetscapePluginView.mm: + (-[WebNetscapePluginView initWithFrame:pluginPackage:URL:baseURL:MIMEType:attributeKeys:attributeValues:loadManually:element:WebCore::]): + (-[WebNetscapePluginView getVariable:value:]): + * WebCoreSupport/WebFrameLoaderClient.mm: + (WebFrameLoaderClient::createPlugin): + +2009-02-02 Anders Carlsson <andersca@apple.com> + + Reviewed by Dan Bernstein. + + Update for changes to WebCore. + + * WebCoreSupport/WebFrameLoaderClient.h: + * WebCoreSupport/WebFrameLoaderClient.mm: + (WebFrameLoaderClient::createPlugin): + +2009-02-02 Anders Carlsson <andersca@apple.com> + + Reviewed by Oliver Hunt. -2009-02-03 Mark Rowe <mrowe@apple.com> + When a new Web View was not created, report back to the plug-in host. + + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::performRequest): + * Plugins/Hosted/WebKitPluginHost.defs: + +2009-02-02 Anders Carlsson <andersca@apple.com> + + Reviewed by Kevin Decker. + + Draw the regular missing plug-in icon instead of a red rect when a plug-in has crashed. + + * Plugins/Hosted/WebHostedNetscapePluginView.mm: + (-[WebHostedNetscapePluginView drawRect:]): + +2009-02-02 Holger Hans Peter Freyther <zecke@selfish.org> + + Reviewed by Darin Adler. + + Move Frame::forceLayout, Frame::adjustPageHeight and Frame::forceLayoutWithPageWidthRange to FrameView + + https://bugs.webkit.org/show_bug.cgi?id=23428 + + FrameView::forceLayout could be killed but the comment might + contain a value over the the plain FrameView::layout... + + Adjust the WebCore/WebKit consumers of these methods. + + * WebView/WebFrame.mm: + (-[WebFrame _computePageRectsWithPrintWidthScaleFactor:printHeight:]): + * WebView/WebHTMLView.mm: + (-[WebHTMLView layoutToMinimumPageWidth:maximumPageWidth:adjustingViewSize:]): + (-[WebHTMLView adjustPageHeightNew:top:bottom:limit:]): + +2009-01-31 John Sullivan <sullivan@apple.com> - Merge r40380. + https://bugs.webkit.org/show_bug.cgi?id=23665 - 2009-01-29 Sam Weinig <sam@webkit.org> + Cleaned up code to add/remove NSNotification observers, to avoid performance hit + of calling removeObserver with unspecified notifications, or calling removeObserver + multiple times for the same notification. + + Reviewed by Darin Adler + + * WebView/WebHTMLView.mm: + added observingMouseMovedNotifications, observingSuperviewNotifications, and + observingWindowNotifications as BOOL ivars of _private object + (-[WebHTMLView _removeMouseMovedObserverUnconditionally]): + moved to file-internal section of file, added leading underscore, now bails out + if we aren't observing the relevant notifications, now records that we are no longer + observing the relevant notifications + (-[WebHTMLView _removeSuperviewObservers]): + ditto, also stores [NSNoticationCenter defaultCenter] in local var to avoid objc dispatch + (-[WebHTMLView _removeWindowObservers]): + ditto + (-[WebHTMLView close]): + replace general removeObserver: call with three specific calls for all the notifications + that this class actually observes + (-[WebHTMLView addMouseMovedObserver]): + bail out if already observing relevant notifications, now records that we are observing + the relevant notifications + (-[WebHTMLView removeMouseMovedObserver]): + updated for name change + (-[WebHTMLView addSuperviewObservers]): + bail out if already observing relevant notifications, now records that we are observing + the relevant notifications; also stores [NSNoticationCenter defaultCenter] in local var + to avoid objc dispatch + (-[WebHTMLView addWindowObservers]): + ditto + (-[WebHTMLView viewWillMoveToSuperview:]): + updated for name change + (-[WebHTMLView viewWillMoveToWindow:]): + updated for name changes + +2009-01-31 Darin Adler <darin@apple.com> Reviewed by Mark Rowe. - First step in tracking the urls a HistoryItem was redirected through. + Fix code that assumes all command selectors end in colons. + rdar://problem/6545874 - * History/WebHistoryItem.mm: - (-[WebHistoryItem initFromDictionaryRepresentation:]): - (-[WebHistoryItem dictionaryRepresentation]): - * Misc/WebNSDictionaryExtras.h: - * Misc/WebNSDictionaryExtras.m: - (-[NSDictionary _webkit_arrayForKey:]): Add helper. + * WebView/WebHTMLView.mm: + (commandNameForSelector): Don't assert, just return a null string, when + the selector doesn't end in a colon. -2009-02-03 Mark Rowe <mrowe@apple.com> +2009-01-30 Adam Barth <abarth@webkit.org> - Merge r40436. + Reviewed by Sam Weinig. - 2009-01-30 Geoffrey Garen <ggaren@apple.com> + Add a pref to disable web security. - Build fix. + * WebView/WebPreferenceKeysPrivate.h: + * WebView/WebPreferencesPrivate.h: + * WebView/WebPreferences.mm: + (+[WebPreferences initialize]): + (-[WebPreferences isWebSecurityEnabled]): + (-[WebPreferences setWebSecurityEnabled:]): + * WebView/WebView.mm: + (-[WebView _preferencesChangedNotification:]): - * WebView/WebFramePrivate.h: +2009-01-30 Holger Hans Peter Freyther <zecke@selfish.org> + + Reviewed by Darin Adler. + + Move Frame::sendResizeEvent and Frame::sendScrollEvent to EventHandler + + Carry out the move and catch up in two call sites. + + * WebView/WebHTMLView.mm: + (-[WebHTMLView _frameOrBoundsChanged]): + +2009-01-30 Holger Hans Peter Freyther <zecke@selfish.org> + + Reviewed by Darin Adler. + + isFrameSet was moved from Frame to Document. Update the + WebKit usage. -2009-02-03 Mark Rowe <mrowe@apple.com> + * WebView/WebFrame.mm: + (-[WebFrame _isFrameSet]): + * WebView/WebHTMLView.mm: + (-[WebHTMLView knowsPageRange:]): - Merge r40432. +2009-01-30 Geoffrey Garen <ggaren@apple.com> - 2009-01-30 Geoffrey Garen <ggaren@apple.com> + Build fix. + + * WebView/WebFramePrivate.h: + +2009-01-30 Geoffrey Garen <ggaren@apple.com> Reviewed by Sam Weinig. @@ -265,24 +2071,59 @@ * WebView/WebPDFView.mm: (-[WebPDFView PDFViewWillClickOnLink:withURL:]): -2009-02-03 Mark Rowe <mrowe@apple.com> +2009-01-30 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. - Merge r40353. + Fix <rdar://problem/6544048> + + Have NetscapePluginInstanceProxy keep track of all the ProxyInstance objects associated. + + When the plug-in instance is destroyed, invalidate all proxy instances. + + * Plugins/Hosted/NetscapePluginInstanceProxy.h: + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::NetscapePluginInstanceProxy::destroy): + (WebKit::NetscapePluginInstanceProxy::addInstance): + (WebKit::NetscapePluginInstanceProxy::removeInstance): + * Plugins/Hosted/ProxyInstance.h: + * Plugins/Hosted/ProxyInstance.mm: + (WebKit::ProxyInstance::ProxyInstance): + (WebKit::ProxyInstance::~ProxyInstance): + (WebKit::ProxyInstance::invalidate): - 2009-01-28 Geoffrey Garen <ggaren@apple.com> +2009-01-30 Anders Carlsson <andersca@apple.com> Reviewed by Sam Weinig. - Updated for WebCore rename. + Fix <rdar://problem/6490778>. + + Change the NPRuntime related functions to use IdentifierRep directly, and make sure to always + validate IdentifierReps before dereferencing them. + + * Plugins/Hosted/NetscapePluginHostProxy.mm: + (WKPCEvaluate): + (WKPCGetStringIdentifier): + (WKPCGetIntIdentifier): + (identifierFromIdentifierRep): + (WKPCInvoke): + (WKPCGetProperty): + (WKPCSetProperty): + (WKPCRemoveProperty): + (WKPCHasProperty): + (WKPCHasMethod): + (WKPCIdentifierInfo): - * WebView/WebView.mm: - (-[WebView setCustomTextEncodingName:]): +2009-01-30 Brady Eidson <beidson@apple.com> -2009-02-03 Mark Rowe <mrowe@apple.com> + Reviewed by Sam Weinig + + Remove FrameLoaderClient code that is now handled by FrameLoader itself - Merge r40397. + * WebCoreSupport/WebFrameLoaderClient.mm: + (WebFrameLoaderClient::frameLoadCompleted): - 2009-01-29 Stephanie Lewis <slewis@apple.com> +2009-01-29 Stephanie Lewis <slewis@apple.com> RS by Oliver Hunt. @@ -290,11 +2131,147 @@ * WebKit.order: -2009-02-03 Mark Rowe <mrowe@apple.com> +2009-01-29 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + Second step in tracking the urls a HistoryItem was redirected through + Add SPI to access the array of redirect urls associated with a HistoryItem. + + * History/WebHistoryItem.mm: + (-[WebHistoryItem dictionaryRepresentation]): + (-[WebHistoryItem _redirectURLs]): + * History/WebHistoryItemPrivate.h: + +2009-01-29 Anders Carlsson <andersca@apple.com> + + Reviewed by Dan Bernstein. + + Always activate the plug-in host process if we're in "modal mode" and are being told to activate. + + * Plugins/Hosted/NetscapePluginHostProxy.h: + * Plugins/Hosted/NetscapePluginHostProxy.mm: + (WebKit::NetscapePluginHostProxy::pluginHostDied): + Call endModal here. + + (WebKit::NetscapePluginHostProxy::applicationDidBecomeActive): + If we're modal, we should always bring the plug-in host process to the front. + + (WebKit::NetscapePluginHostProxy::beginModal): + Add an observer for the NSApplicationWillBecomeActiveNotification callback. + + (WebKit::NetscapePluginHostProxy::endModal): + Remove the observer. + +2009-01-29 Sam Weinig <sam@webkit.org> + + Reviewed by Mark Rowe. + + First step in tracking the urls a HistoryItem was redirected through. + + * History/WebHistoryItem.mm: + (-[WebHistoryItem initFromDictionaryRepresentation:]): + (-[WebHistoryItem dictionaryRepresentation]): + * Misc/WebNSDictionaryExtras.h: + * Misc/WebNSDictionaryExtras.m: + (-[NSDictionary _webkit_arrayForKey:]): Add helper. + +2009-01-29 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. + + Pass the PSN of the client to the host, and get the PSN of the host back when checking in. + + * Plugins/Hosted/NetscapePluginHostManager.h: + * Plugins/Hosted/NetscapePluginHostManager.mm: + (WebKit::NetscapePluginHostManager::hostForPackage): + Get the current PSN and pass it to spawnPluginHost. + + (WebKit::NetscapePluginHostManager::spawnPluginHost): + Pass the PSN to the "check in" function. + + * Plugins/Hosted/NetscapePluginHostProxy.h: + * Plugins/Hosted/NetscapePluginHostProxy.mm: + (WebKit::NetscapePluginHostProxy::NetscapePluginHostProxy): + + (WebKit::NetscapePluginHostProxy::pluginHostDied): + Fix a bug noticed by Julien Chaffraix. Call endModal if necessary. + + (WebKit::NetscapePluginHostProxy::beginModal): + (WebKit::NetscapePluginHostProxy::endModal): + (WebKit::NetscapePluginHostProxy::setModal): + Split out the code that does all of the work into beginModal and endModal methods. + + * Plugins/Hosted/WebKitPluginHost.defs: + * Plugins/WebNetscapePluginView.mm: + (-[WebNetscapePluginView loadStream]): + +2009-01-29 David Kilzer <ddkilzer@apple.com> + + Remove semi-colons from the end of ObjC method implementations + + Rubber-stamped by Adam Roben. + + $ find WebKit -name \*.m -o -name \*.mm -exec perl -e 'undef $/; $s = <>; while ($s =~ m/[\n\r][-+].*;[\s\r\n]+\{/g) { print "$ARGV: $&\n"; }' {} \; + + * DefaultDelegates/WebDefaultUIDelegate.m: + (-[WebDefaultUIDelegate webView:setResizable:]): + (-[WebDefaultUIDelegate webView:dragDestinationActionMaskForDraggingInfo:]): + (-[WebDefaultUIDelegate webView:dragSourceActionMaskForPoint:]): + (-[WebDefaultUIDelegate webView:willPerformDragSourceAction:fromPoint:withPasteboard:]): + * History/WebBackForwardList.mm: + (-[WebBackForwardList addItem:]): + (-[WebBackForwardList backListWithLimit:]): + (-[WebBackForwardList forwardListWithLimit:]): + * History/WebHistoryItem.mm: + (-[WebHistoryItem alternateTitle]): + (-[WebHistoryItem setViewState:]): + * Misc/WebCoreStatistics.mm: + (+[WebCoreStatistics garbageCollectJavaScriptObjectsOnAlternateThreadForDebugging:]): + * Misc/WebKitNSStringExtras.m: + (-[NSString _web_drawAtPoint:font:textColor:]): + * Plugins/WebNetscapePluginView.mm: + (-[WebNetscapePluginView setAttributeKeys:andValues:]): + * WebCoreSupport/WebEditorClient.mm: + (-[WebEditCommand command]): + * WebView/WebFrame.mm: + (-[WebFrame _getVisibleRect:]): + * WebView/WebHTMLRepresentation.mm: + (-[WebHTMLRepresentation _redirectDataToManualLoader:forPluginView:]): + * WebView/WebHTMLView.mm: + (-[WebHTMLView elementAtPoint:allowShadowContent:]): + * WebView/WebPreferences.mm: + (-[WebPreferences setAllowsAnimatedImages:]): + (-[WebPreferences setAutosaves:]): + (-[WebPreferences PDFDisplayMode]): + * WebView/WebView.mm: + (+[WebView _viewClass:andRepresentationClass:forMIMEType:]): + (-[WebView _viewClass:andRepresentationClass:forMIMEType:]): + (+[WebView _unregisterViewClassAndRepresentationClassForMIMEType:]): + (+[WebView _registerViewClass:representationClass:forURLScheme:]): + (-[WebView _shouldChangeSelectedDOMRange:toDOMRange:affinity:stillSelecting:]): + (-[WebView _insertNewlineInQuotedContent]): + +2009-01-28 Geoffrey Garen <ggaren@apple.com> - Merge r40332. + Reviewed by Sam Weinig. + + Updated for WebCore rename. + + * WebView/WebView.mm: + (-[WebView setCustomTextEncodingName:]): + +2009-01-28 David Kilzer <ddkilzer@apple.com> + + Add missing declaration for -[NSURL(WebNSURLExtras) _webkit_isFileURL] + + Reviewed by Dan Bernstein. - 2009-01-28 Sam Weinig <sam@webkit.org> + * Misc/WebNSURLExtras.h: + (-[NSURL(WebNSURLExtras) _webkit_isFileURL]): Added missing + declaration after the implementation was added in r9258. + +2009-01-28 Sam Weinig <sam@webkit.org> Reviewed by Geoff Garen. @@ -304,6 +2281,19 @@ * WebView/WebScriptDebugDelegate.mm: (-[WebScriptCallFrame scopeChain]): Wrap JSActivations in DebuggerActivations. +2009-01-27 Anders Carlsson <andersca@apple.com> + + Reviewed by Oliver Hunt. + + Fix two bugs with Core Animation based plug-ins. + + 1. The plug-in view was marked as opaque even though it's not. + (This would leave garbage in the plug-in view). + 2. The plug-in layer needs to have autoresizing turned on. + + * Plugins/WebNetscapePluginView.mm: + (-[WebNetscapePluginView setLayer:]): + 2009-01-27 Brady Eidson <beidson@apple.com> Reviewed by Dan Bernstein diff --git a/WebKit/mac/Configurations/Base.xcconfig b/WebKit/mac/Configurations/Base.xcconfig index 2c83815..8ed667f 100644 --- a/WebKit/mac/Configurations/Base.xcconfig +++ b/WebKit/mac/Configurations/Base.xcconfig @@ -25,6 +25,11 @@ VALID_ARCHS = i386 ppc x86_64 ppc64; WARNING_CFLAGS = -Wall -Wextra -Wcast-align -Wchar-subscripts -Wextra-tokens -Wformat-security -Winit-self -Wmissing-format-attribute -Wmissing-noreturn -Wno-unused-parameter -Wpacked -Wpointer-arith -Wredundant-decls -Wundef -Wwrite-strings; +REAL_PLATFORM_NAME = $(REAL_PLATFORM_NAME_$(PLATFORM_NAME)); +REAL_PLATFORM_NAME_ = $(REAL_PLATFORM_NAME_macosx); +REAL_PLATFORM_NAME_macosx = macosx; + + // DEBUG_DEFINES, GCC_OPTIMIZATION_LEVEL, STRIP_INSTALLED_PRODUCT and DEAD_CODE_STRIPPING vary between the debug and normal variants. // We set up the values for each variant here, and have the Debug configuration in the Xcode project use the _debug variant. DEBUG_DEFINES_debug = DISABLE_THREAD_CHECK; diff --git a/WebKit/mac/Configurations/DebugRelease.xcconfig b/WebKit/mac/Configurations/DebugRelease.xcconfig index 10699fb..fab0906 100644 --- a/WebKit/mac/Configurations/DebugRelease.xcconfig +++ b/WebKit/mac/Configurations/DebugRelease.xcconfig @@ -1,5 +1,12 @@ #include "Base.xcconfig" -ARCHS = $(NATIVE_ARCH); + +ARCHS = $(ARCHS_$(MAC_OS_X_VERSION_MAJOR)); +ARCHS_ = $(ARCHS_1040); +ARCHS_1040 = $(NATIVE_ARCH); +ARCHS_1050 = $(NATIVE_ARCH); +ARCHS_1060 = $(ARCHS_STANDARD_32_64_BIT); + +ONLY_ACTIVE_ARCH = YES; MACOSX_DEPLOYMENT_TARGET = $(MACOSX_DEPLOYMENT_TARGET_$(MAC_OS_X_VERSION_MAJOR)); MACOSX_DEPLOYMENT_TARGET_ = 10.4; diff --git a/WebKit/mac/Configurations/Version.xcconfig b/WebKit/mac/Configurations/Version.xcconfig index bf339bf..ab0aa9b 100644 --- a/WebKit/mac/Configurations/Version.xcconfig +++ b/WebKit/mac/Configurations/Version.xcconfig @@ -1,5 +1,5 @@ -MAJOR_VERSION = 528; -MINOR_VERSION = 16; +MAJOR_VERSION = 530; +MINOR_VERSION = 5; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/WebKit/mac/Configurations/WebKit.xcconfig b/WebKit/mac/Configurations/WebKit.xcconfig index 0937fdb..12d47ea 100644 --- a/WebKit/mac/Configurations/WebKit.xcconfig +++ b/WebKit/mac/Configurations/WebKit.xcconfig @@ -11,11 +11,23 @@ GCC_PREPROCESSOR_DEFINITIONS = $(DEBUG_DEFINES) $(FEATURE_DEFINES) FRAMEWORK_NAM HEADER_SEARCH_PATHS = $(WEBCORE_PRIVATE_HEADERS_DIR)/ForwardingHeaders $(WEBCORE_PRIVATE_HEADERS_DIR)/icu "${BUILT_PRODUCTS_DIR}/usr/local/include" "${BUILT_PRODUCTS_DIR}/DerivedSources/WebKit" $(HEADER_SEARCH_PATHS); INFOPLIST_FILE = mac/Info.plist; INSTALL_PATH = $(SYSTEM_LIBRARY_DIR)/Frameworks; -JAVASCRIPTCORE_PRIVATE_HEADERS_DIR = $(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/JavaScriptCore.framework/PrivateHeaders; +INSTALLHDRS_COPY_PHASE = YES; +INSTALLHDRS_SCRIPT_PHASE = YES; PRODUCT_NAME = WebKit; UMBRELLA_FRAMEWORKS_DIR = $(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/WebKit.framework/Versions/A/Frameworks; -WEBCORE_PRIVATE_HEADERS_DIR = $(UMBRELLA_FRAMEWORKS_DIR)/WebCore.framework/PrivateHeaders; OTHER_LDFLAGS = -sub_umbrella WebCore $(OTHER_LDFLAGS); -// This needs to be kept sorted, and in sync with FEATURE_DEFINES in JavaScriptCore.xcconfig, WebCore.xcconfig and the default settings of build-webkit. -FEATURE_DEFINES = ENABLE_DATABASE ENABLE_DOM_STORAGE ENABLE_ICONDATABASE ENABLE_OFFLINE_WEB_APPLICATIONS ENABLE_SVG ENABLE_SVG_ANIMATION ENABLE_SVG_AS_IMAGE ENABLE_SVG_FONTS ENABLE_SVG_FOREIGN_OBJECT ENABLE_SVG_USE ENABLE_VIDEO ENABLE_WORKERS ENABLE_XPATH ENABLE_XSLT; +WEBCORE_PRIVATE_HEADERS_DIR = $(WEBCORE_PRIVATE_HEADERS_DIR_$(REAL_PLATFORM_NAME)_$(CONFIGURATION)); +WEBCORE_PRIVATE_HEADERS_DIR_macosx_Release = $(WEBCORE_PRIVATE_HEADERS_engineering); +WEBCORE_PRIVATE_HEADERS_DIR_macosx_Debug = $(WEBCORE_PRIVATE_HEADERS_engineering); +WEBCORE_PRIVATE_HEADERS_DIR_macosx_Production = $(UMBRELLA_FRAMEWORKS_DIR)/WebCore.framework/PrivateHeaders; +WEBCORE_PRIVATE_HEADERS_engineering = $(BUILT_PRODUCTS_DIR)/WebCore.framework/PrivateHeaders; + +// This needs to be kept sorted, and in sync with FEATURE_DEFINES in JavaScriptCore.xcconfig, WebCore.xcconfig and +// the default settings of build-webkit to prevent needless rebuilding when using both Xcode and build-webkit. +FEATURE_DEFINES = $(FEATURE_DEFINES_$(MAC_OS_X_VERSION_MAJOR)); +FEATURE_DEFINES_BASE = ENABLE_DATABASE ENABLE_DOM_STORAGE ENABLE_ICONDATABASE ENABLE_OFFLINE_WEB_APPLICATIONS ENABLE_SVG ENABLE_SVG_ANIMATION ENABLE_SVG_AS_IMAGE ENABLE_SVG_FONTS ENABLE_SVG_FOREIGN_OBJECT ENABLE_SVG_USE ENABLE_VIDEO ENABLE_WORKERS ENABLE_XPATH ENABLE_XSLT; +FEATURE_DEFINES_ = $(FEATURE_DEFINES_1040); +FEATURE_DEFINES_1040 = $(FEATURE_DEFINES_BASE); +FEATURE_DEFINES_1050 = $(FEATURE_DEFINES_BASE); +FEATURE_DEFINES_1060 = $(FEATURE_DEFINES_BASE) ENABLE_GEOLOCATION; diff --git a/WebKit/mac/DefaultDelegates/WebDefaultScriptDebugDelegate.h b/WebKit/mac/DefaultDelegates/WebDefaultScriptDebugDelegate.h deleted file mode 100644 index b548212..0000000 --- a/WebKit/mac/DefaultDelegates/WebDefaultScriptDebugDelegate.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2005 Apple Computer, 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. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. - */ - -#import <Foundation/Foundation.h> - -@interface WebDefaultScriptDebugDelegate : NSObject -+ (WebDefaultScriptDebugDelegate *)sharedScriptDebugDelegate; -@end - diff --git a/WebKit/mac/DefaultDelegates/WebDefaultScriptDebugDelegate.m b/WebKit/mac/DefaultDelegates/WebDefaultScriptDebugDelegate.m deleted file mode 100644 index 85cef90..0000000 --- a/WebKit/mac/DefaultDelegates/WebDefaultScriptDebugDelegate.m +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2005 Apple Computer, 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. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. - */ - -#import <WebKit/WebScriptDebugDelegate.h> -#import "WebDefaultScriptDebugDelegate.h" -#import "WebTypesInternal.h" - -@implementation WebDefaultScriptDebugDelegate - -static WebDefaultScriptDebugDelegate *sharedDelegate = nil; - -+ (WebDefaultScriptDebugDelegate *)sharedScriptDebugDelegate -{ - if (!sharedDelegate) { - sharedDelegate = [[WebDefaultScriptDebugDelegate alloc] init]; - } - return sharedDelegate; -} - -- (void)webView:(WebView *)webView didParseSource:(NSString *)source - fromURL:(NSString *)url - sourceId:(WebSourceId)sid - forWebFrame:(WebFrame *)webFrame -{ -} - -- (void)webView:(WebView *)webView didParseSource:(NSString *)source - baseLineNumber:(NSUInteger)lineNumber - fromURL:(NSURL *)url - sourceId:(WebSourceId)sid - forWebFrame:(WebFrame *)webFrame -{ -} - -- (void)webView:(WebView *)webView failedToParseSource:(NSString *)source - baseLineNumber:(NSUInteger)lineNumber - fromURL:(NSURL *)url - withError:(NSError *)error - forWebFrame:(WebFrame *)webFrame -{ -} - -- (void)webView:(WebView *)webView didEnterCallFrame:(WebScriptCallFrame *)frame - sourceId:(WebSourceId)sid - line:(int)lineno - forWebFrame:(WebFrame *)webFrame -{ -} - -- (void)webView:(WebView *)webView willExecuteStatement:(WebScriptCallFrame *)frame - sourceId:(WebSourceId)sid - line:(int)lineno - forWebFrame:(WebFrame *)webFrame -{ -} - -- (void)webView:(WebView *)webView willLeaveCallFrame:(WebScriptCallFrame *)frame - sourceId:(WebSourceId)sid - line:(int)lineno - forWebFrame:(WebFrame *)webFrame -{ -} - -- (void)webView:(WebView *)webView exceptionWasRaised:(WebScriptCallFrame *)frame - sourceId:(WebSourceId)sid - line:(int)lineno - forWebFrame:(WebFrame *)webFrame -{ -} - -@end diff --git a/WebKit/mac/DefaultDelegates/WebDefaultUIDelegate.m b/WebKit/mac/DefaultDelegates/WebDefaultUIDelegate.m index aa5df4a..68fa05e 100644 --- a/WebKit/mac/DefaultDelegates/WebDefaultUIDelegate.m +++ b/WebKit/mac/DefaultDelegates/WebDefaultUIDelegate.m @@ -134,7 +134,7 @@ static WebDefaultUIDelegate *sharedDelegate = nil; return [[wv window] showsResizeIndicator]; } -- (void)webView: (WebView *)wv setResizable:(BOOL)resizable; +- (void)webView: (WebView *)wv setResizable:(BOOL)resizable { // FIXME: This doesn't actually change the resizability of the window, // only visibility of the indicator. @@ -193,7 +193,7 @@ static WebDefaultUIDelegate *sharedDelegate = nil; return YES; } -- (NSUInteger)webView:(WebView *)webView dragDestinationActionMaskForDraggingInfo:(id <NSDraggingInfo>)draggingInfo; +- (NSUInteger)webView:(WebView *)webView dragDestinationActionMaskForDraggingInfo:(id <NSDraggingInfo>)draggingInfo { return WebDragDestinationActionAny; } @@ -202,12 +202,12 @@ static WebDefaultUIDelegate *sharedDelegate = nil; { } -- (NSUInteger)webView:(WebView *)webView dragSourceActionMaskForPoint:(NSPoint)point; +- (NSUInteger)webView:(WebView *)webView dragSourceActionMaskForPoint:(NSPoint)point { return WebDragSourceActionAny; } -- (void)webView:(WebView *)webView willPerformDragSourceAction:(WebDragSourceAction)action fromPoint:(NSPoint)point withPasteboard:(NSPasteboard *)pasteboard; +- (void)webView:(WebView *)webView willPerformDragSourceAction:(WebDragSourceAction)action fromPoint:(NSPoint)point withPasteboard:(NSPasteboard *)pasteboard { } diff --git a/WebKit/mac/ForwardingHeaders/kjs/SavedBuiltins.h b/WebKit/mac/ForwardingHeaders/kjs/SavedBuiltins.h deleted file mode 100644 index e380807..0000000 --- a/WebKit/mac/ForwardingHeaders/kjs/SavedBuiltins.h +++ /dev/null @@ -1 +0,0 @@ -#import <JavaScriptCore/SavedBuiltins.h> diff --git a/WebKit/mac/ForwardingHeaders/kjs/collector.h b/WebKit/mac/ForwardingHeaders/kjs/collector.h deleted file mode 100644 index b8ef5a1..0000000 --- a/WebKit/mac/ForwardingHeaders/kjs/collector.h +++ /dev/null @@ -1 +0,0 @@ -#import <JavaScriptCore/collector.h> diff --git a/WebKit/mac/ForwardingHeaders/kjs/dtoa.h b/WebKit/mac/ForwardingHeaders/kjs/dtoa.h deleted file mode 100644 index 4646cf1..0000000 --- a/WebKit/mac/ForwardingHeaders/kjs/dtoa.h +++ /dev/null @@ -1 +0,0 @@ -#import <JavaScriptCore/dtoa.h> diff --git a/WebKit/mac/ForwardingHeaders/kjs/identifier.h b/WebKit/mac/ForwardingHeaders/kjs/identifier.h deleted file mode 100644 index 2471c99..0000000 --- a/WebKit/mac/ForwardingHeaders/kjs/identifier.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/identifier.h> diff --git a/WebKit/mac/ForwardingHeaders/kjs/interpreter.h b/WebKit/mac/ForwardingHeaders/kjs/interpreter.h deleted file mode 100644 index 08c2be3..0000000 --- a/WebKit/mac/ForwardingHeaders/kjs/interpreter.h +++ /dev/null @@ -1 +0,0 @@ -#import <JavaScriptCore/interpreter.h> diff --git a/WebKit/mac/ForwardingHeaders/kjs/lookup.h b/WebKit/mac/ForwardingHeaders/kjs/lookup.h deleted file mode 100644 index 5e2ffa0..0000000 --- a/WebKit/mac/ForwardingHeaders/kjs/lookup.h +++ /dev/null @@ -1 +0,0 @@ -#import <JavaScriptCore/lookup.h> diff --git a/WebKit/mac/ForwardingHeaders/kjs/operations.h b/WebKit/mac/ForwardingHeaders/kjs/operations.h deleted file mode 100644 index eb80f49..0000000 --- a/WebKit/mac/ForwardingHeaders/kjs/operations.h +++ /dev/null @@ -1 +0,0 @@ -#include <JavaScriptCore/operations.h> diff --git a/WebKit/mac/ForwardingHeaders/kjs/protect.h b/WebKit/mac/ForwardingHeaders/kjs/protect.h deleted file mode 100644 index e4e0499..0000000 --- a/WebKit/mac/ForwardingHeaders/kjs/protect.h +++ /dev/null @@ -1 +0,0 @@ -#import <JavaScriptCore/protect.h> diff --git a/WebKit/mac/History/WebBackForwardList.mm b/WebKit/mac/History/WebBackForwardList.mm index 20988b8..2f0c214 100644 --- a/WebKit/mac/History/WebBackForwardList.mm +++ b/WebKit/mac/History/WebBackForwardList.mm @@ -82,7 +82,7 @@ WebBackForwardList *kit(BackForwardList* backForwardList) - (id)initWithBackForwardList:(PassRefPtr<BackForwardList>)backForwardList { - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundOne(); self = [super init]; if (!self) return nil; @@ -115,20 +115,26 @@ WebBackForwardList *kit(BackForwardList* backForwardList) return; BackForwardList* backForwardList = core(self); - ASSERT(backForwardList->closed()); - backForwardLists().remove(backForwardList); - backForwardList->deref(); - + ASSERT(backForwardList); + if (backForwardList) { + ASSERT(backForwardList->closed()); + backForwardLists().remove(backForwardList); + backForwardList->deref(); + } + [super dealloc]; } - (void)finalize { - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundOne(); BackForwardList* backForwardList = core(self); - ASSERT(backForwardList->closed()); - backForwardLists().remove(backForwardList); - backForwardList->deref(); + ASSERT(backForwardList); + if (backForwardList) { + ASSERT(backForwardList->closed()); + backForwardLists().remove(backForwardList); + backForwardList->deref(); + } [super finalize]; } @@ -138,7 +144,7 @@ WebBackForwardList *kit(BackForwardList* backForwardList) core(self)->close(); } -- (void)addItem:(WebHistoryItem *)entry; +- (void)addItem:(WebHistoryItem *)entry { core(self)->addItem(core(entry)); @@ -198,14 +204,14 @@ static NSArray* vectorToNSArray(HistoryItemVector& list) return result; } -- (NSArray *)backListWithLimit:(int)limit; +- (NSArray *)backListWithLimit:(int)limit { HistoryItemVector list; core(self)->backListWithLimit(limit, list); return vectorToNSArray(list); } -- (NSArray *)forwardListWithLimit:(int)limit; +- (NSArray *)forwardListWithLimit:(int)limit { HistoryItemVector list; core(self)->forwardListWithLimit(limit, list); diff --git a/WebKit/mac/History/WebHistory.mm b/WebKit/mac/History/WebHistory.mm index 417aadb..313378b 100644 --- a/WebKit/mac/History/WebHistory.mm +++ b/WebKit/mac/History/WebHistory.mm @@ -60,7 +60,6 @@ NSString *DatesArrayKey = @"WebHistoryDates"; NSMutableDictionary *_entriesByURL; DateToEntriesMap* _entriesByDate; NSMutableArray *_orderedLastVisitedDays; - WebHistoryItem *_lastVisitedEntry; BOOL itemLimitSet; int itemLimit; BOOL ageInDaysLimitSet; @@ -94,9 +93,6 @@ NSString *DatesArrayKey = @"WebHistoryDates"; - (void)addVisitedLinksToPageGroup:(PageGroup&)group; -- (WebHistoryItem *)lastVisitedEntry; -- (void)setLastVisitedEntry:(WebHistoryItem *)lastVisitedEntry; - @end @implementation WebHistoryPrivate @@ -127,7 +123,6 @@ NSString *DatesArrayKey = @"WebHistoryDates"; { [_entriesByURL release]; [_orderedLastVisitedDays release]; - [_lastVisitedEntry release]; delete _entriesByDate; [super dealloc]; } @@ -648,19 +643,6 @@ static WebHistoryDateKey timeIntervalForBeginningOfDay(NSTimeInterval interval) } } -- (WebHistoryItem *)lastVisitedEntry -{ - return _lastVisitedEntry; -} - -- (void)setLastVisitedEntry:(WebHistoryItem *)lastVisitedEntry -{ - if (_lastVisitedEntry == lastVisitedEntry) - return; - [_lastVisitedEntry release]; - _lastVisitedEntry = [lastVisitedEntry retain]; -} - @end @implementation WebHistory @@ -821,39 +803,23 @@ static WebHistoryDateKey timeIntervalForBeginningOfDay(NSTimeInterval interval) @implementation WebHistory (WebInternal) -- (void)_visitedURL:(NSURL *)url withTitle:(NSString *)title method:(NSString *)method wasFailure:(BOOL)wasFailure serverRedirectURL:(NSString *)serverRedirectURL isClientRedirect:(BOOL)isClientRedirect +- (void)_visitedURL:(NSURL *)url withTitle:(NSString *)title method:(NSString *)method wasFailure:(BOOL)wasFailure { - if (isClientRedirect) { - ASSERT(!serverRedirectURL); - if (WebHistoryItem *lastVisitedEntry = [_historyPrivate lastVisitedEntry]) - core(lastVisitedEntry)->addRedirectURL([url _web_originalDataAsString]); - } - WebHistoryItem *entry = [_historyPrivate visitedURL:url withTitle:title]; - [_historyPrivate setLastVisitedEntry:entry]; HistoryItem* item = core(entry); item->setLastVisitWasFailure(wasFailure); if ([method length]) - item->setLastVisitWasHTTPNonGet([method caseInsensitiveCompare:@"GET"]); + item->setLastVisitWasHTTPNonGet([method caseInsensitiveCompare:@"GET"] && (![[url scheme] caseInsensitiveCompare:@"http"] || ![[url scheme] caseInsensitiveCompare:@"https"])); - if (serverRedirectURL) { - ASSERT(!isClientRedirect); - item->addRedirectURL(serverRedirectURL); - } + item->setRedirectURLs(std::auto_ptr<Vector<String> >()); NSArray *entries = [[NSArray alloc] initWithObjects:entry, nil]; [self _sendNotification:WebHistoryItemsAddedNotification entries:entries]; [entries release]; } -- (void)_visitedURLForRedirectWithoutHistoryItem:(NSURL *)url -{ - if (WebHistoryItem *lastVisitedEntry = [_historyPrivate lastVisitedEntry]) - core(lastVisitedEntry)->addRedirectURL([url _web_originalDataAsString]); -} - - (void)_addVisitedLinksToPageGroup:(WebCore::PageGroup&)group { [_historyPrivate addVisitedLinksToPageGroup:group]; diff --git a/WebKit/mac/History/WebHistoryInternal.h b/WebKit/mac/History/WebHistoryInternal.h index 9e69734..b4431c5 100644 --- a/WebKit/mac/History/WebHistoryInternal.h +++ b/WebKit/mac/History/WebHistoryInternal.h @@ -33,7 +33,6 @@ namespace WebCore { } @interface WebHistory (WebInternal) -- (void)_visitedURL:(NSURL *)URL withTitle:(NSString *)title method:(NSString *)method wasFailure:(BOOL)wasFailure serverRedirectURL:(NSString *)serverRedirectURL isClientRedirect:(BOOL)isClientRedirect; -- (void)_visitedURLForRedirectWithoutHistoryItem:(NSURL *)url; +- (void)_visitedURL:(NSURL *)URL withTitle:(NSString *)title method:(NSString *)method wasFailure:(BOOL)wasFailure; - (void)_addVisitedLinksToPageGroup:(WebCore::PageGroup&)group; @end diff --git a/WebKit/mac/History/WebHistoryItem.mm b/WebKit/mac/History/WebHistoryItem.mm index 1d2de1d..ca80437 100644 --- a/WebKit/mac/History/WebHistoryItem.mm +++ b/WebKit/mac/History/WebHistoryItem.mm @@ -107,7 +107,7 @@ void WKNotifyHistoryItemChanged() - (id)initWithURLString:(NSString *)URLString title:(NSString *)title lastVisitedTimeInterval:(NSTimeInterval)time { - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundOne(); return [self initWithWebCoreHistoryItem:HistoryItem::create(URLString, title, time)]; } @@ -126,7 +126,7 @@ void WKNotifyHistoryItemChanged() - (void)finalize { - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundOne(); // FIXME: ~HistoryItem is what releases the history item's icon from the icon database // It's probably not good to release icons from the database only when the object is garbage-collected. // Need to change design so this happens at a predictable time. @@ -140,7 +140,7 @@ void WKNotifyHistoryItemChanged() - (id)copyWithZone:(NSZone *)zone { - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundOne(); WebHistoryItem *copy = (WebHistoryItem *)NSCopyObject(self, 0, zone); RefPtr<HistoryItem> item = core(_private)->copy(); copy->_private = kitPrivate(item.get()); @@ -175,7 +175,7 @@ void WKNotifyHistoryItemChanged() core(_private)->setAlternateTitle(alternateTitle); } -- (NSString *)alternateTitle; +- (NSString *)alternateTitle { return nsStringNilIfEmpty(core(_private)->alternateTitle()); } @@ -299,7 +299,7 @@ static WebWindowWatcher *_windowWatcher = nil; - (id)initWithWebCoreHistoryItem:(PassRefPtr<HistoryItem>)item { - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundOne(); // Need to tell WebCore what function to call for the // "History Item has Changed" notification - no harm in doing this // everytime a WebHistoryItem is created @@ -325,7 +325,7 @@ static WebWindowWatcher *_windowWatcher = nil; core(_private)->setVisitCount(count); } -- (void)setViewState:(id)statePList; +- (void)setViewState:(id)statePList { core(_private)->setViewState(statePList); } @@ -422,11 +422,6 @@ static WebWindowWatcher *_windowWatcher = nil; core(_private)->visited(title, [NSDate timeIntervalSinceReferenceDate]); } -- (void)_setVisitCount:(int)count -{ - core(_private)->setVisitCount(count); -} - - (void)_recordInitialVisit { core(_private)->recordInitialVisit(); diff --git a/WebKit/mac/History/WebHistoryItemInternal.h b/WebKit/mac/History/WebHistoryItemInternal.h index 74a8074..fe2ae1a 100644 --- a/WebKit/mac/History/WebHistoryItemInternal.h +++ b/WebKit/mac/History/WebHistoryItemInternal.h @@ -52,7 +52,6 @@ extern void WKNotifyHistoryItemChanged(); - (void)_mergeAutoCompleteHints:(WebHistoryItem *)otherItem; - (void)setTitle:(NSString *)title; - (void)_visitedWithTitle:(NSString *)title; -- (void)_setVisitCount:(int)count; - (void)_recordInitialVisit; @end diff --git a/WebKit/mac/Misc/WebCache.mm b/WebKit/mac/Misc/WebCache.mm index a60159f..46fb341 100644 --- a/WebKit/mac/Misc/WebCache.mm +++ b/WebKit/mac/Misc/WebCache.mm @@ -30,6 +30,7 @@ #import "WebViewInternal.h" #import <WebCore/ApplicationCacheStorage.h> #import <WebCore/Cache.h> +#import <WebCore/CrossOriginPreflightResultCache.h> @implementation WebCache @@ -107,9 +108,12 @@ WebCacheModel cacheModel = [WebView _cacheModel]; [WebView _setCacheModel:WebCacheModelDocumentViewer]; [WebView _setCacheModel:cacheModel]; - + // Empty the application cache. WebCore::cacheStorage().empty(); + + // Empty the Cross-Origin Preflight cache + WebCore::CrossOriginPreflightResultCache::shared().empty(); } + (void)setDisabled:(BOOL)disabled diff --git a/WebKit/mac/Misc/WebCoreStatistics.mm b/WebKit/mac/Misc/WebCoreStatistics.mm index 05c2659..2fe5710 100644 --- a/WebKit/mac/Misc/WebCoreStatistics.mm +++ b/WebKit/mac/Misc/WebCoreStatistics.mm @@ -95,7 +95,7 @@ using namespace WebCore; gcController().garbageCollectNow(); } -+ (void)garbageCollectJavaScriptObjectsOnAlternateThreadForDebugging:(BOOL)waitUntilDone; ++ (void)garbageCollectJavaScriptObjectsOnAlternateThreadForDebugging:(BOOL)waitUntilDone { gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone); } diff --git a/WebKit/mac/Misc/WebIconDatabase.mm b/WebKit/mac/Misc/WebIconDatabase.mm index 3b42406..d4df14b 100644 --- a/WebKit/mac/Misc/WebIconDatabase.mm +++ b/WebKit/mac/Misc/WebIconDatabase.mm @@ -94,7 +94,7 @@ static WebIconDatabaseClient* defaultClient() - init { [super init]; - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundOne(); _private = [[WebIconDatabasePrivate alloc] init]; diff --git a/WebKit/mac/Misc/WebIconFetcher.mm b/WebKit/mac/Misc/WebIconFetcher.mm index bec7c12..a31ab7d 100644 --- a/WebKit/mac/Misc/WebIconFetcher.mm +++ b/WebKit/mac/Misc/WebIconFetcher.mm @@ -71,14 +71,16 @@ private: - (void)dealloc { - reinterpret_cast<IconFetcher*>(_private)->deref(); + if (_private) + reinterpret_cast<IconFetcher*>(_private)->deref(); [super dealloc]; } - (void)finalize { - reinterpret_cast<IconFetcher*>(_private)->deref(); + if (_private) + reinterpret_cast<IconFetcher*>(_private)->deref(); [super finalize]; } diff --git a/WebKit/mac/Misc/WebKitNSStringExtras.m b/WebKit/mac/Misc/WebKitNSStringExtras.m index 2e75e9e..f3077d3 100644 --- a/WebKit/mac/Misc/WebKitNSStringExtras.m +++ b/WebKit/mac/Misc/WebKitNSStringExtras.m @@ -50,7 +50,7 @@ static BOOL canUseFastRenderer(const UniChar *buffer, unsigned length) return YES; } -- (void)_web_drawAtPoint:(NSPoint)point font:(NSFont *)font textColor:(NSColor *)textColor; +- (void)_web_drawAtPoint:(NSPoint)point font:(NSFont *)font textColor:(NSColor *)textColor { // FIXME: Would be more efficient to change this to C++ and use Vector<UChar, 2048>. unsigned length = [self length]; diff --git a/WebKit/mac/Misc/WebKitVersionChecks.h b/WebKit/mac/Misc/WebKitVersionChecks.h index 6c60d6a..169b4cf 100644 --- a/WebKit/mac/Misc/WebKitVersionChecks.h +++ b/WebKit/mac/Misc/WebKitVersionChecks.h @@ -49,8 +49,8 @@ #define WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES 0x020E0000 // 526.0.0 #define WEBKIT_FIRST_VERSION_WITH_MORE_STRICT_LOCAL_RESOURCE_SECURITY_RESTRICTION 0x02100200 // 528.2.0 #define WEBKIT_FIRST_VERSION_WITH_RELOAD_FROM_ORIGIN 0x02100700 // 528.7.0 -#define WEBKIT_FIRST_VERSION_WITHOUT_MAIL_THREAD_WORKAROUND 0x02100700 // 528.7.0 #define WEBKIT_FIRST_VERSION_WITHOUT_WEBVIEW_INIT_THREAD_WORKAROUND 0x02100700 // 528.7.0 +#define WEBKIT_FIRST_VERSION_WITH_ROUND_TWO_MAIN_THREAD_EXCEPTIONS 0x02120400 // 530.4.0 #ifdef __cplusplus extern "C" { diff --git a/WebKit/mac/Misc/WebNSFileManagerExtras.m b/WebKit/mac/Misc/WebNSFileManagerExtras.m index 0c10725..f32b4c0 100644 --- a/WebKit/mac/Misc/WebNSFileManagerExtras.m +++ b/WebKit/mac/Misc/WebNSFileManagerExtras.m @@ -28,10 +28,12 @@ #import <WebKit/WebNSFileManagerExtras.h> +#import <WebCore/FoundationExtras.h> #import <WebKit/WebKitNSStringExtras.h> #import <WebKitSystemInterface.h> #import <wtf/Assertions.h> +#import <pthread.h> #import <sys/mount.h> @implementation NSFileManager (WebNSFileManagerExtras) @@ -144,11 +146,47 @@ return [carbonPathPieces componentsJoinedByString:@":"]; } +typedef struct MetaDataInfo +{ + NSString *URLString; + NSString *referrer; + NSString *path; +} MetaDataInfo; + +static void *setMetaData(void* context) +{ + MetaDataInfo *info = (MetaDataInfo *)context; + WKSetMetadataURL(info->URLString, info->referrer, info->path); + + HardRelease(info->URLString); + HardRelease(info->referrer); + HardRelease(info->path); + + free(info); + return 0; +} + - (void)_webkit_setMetadataURL:(NSString *)URLString referrer:(NSString *)referrer atPath:(NSString *)path { ASSERT(URLString); ASSERT(path); - WKSetMetadataURL(URLString, referrer, path); + + // Spawn a background thread for WKSetMetadataURL because this function will not return until mds has + // journaled the data we're're trying to set. Depending on what other I/O is going on, it can take some + // time. + pthread_t tid; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + MetaDataInfo *info = malloc(sizeof(MetaDataInfo)); + + info->URLString = HardRetainWithNSRelease([URLString copy]); + info->referrer = HardRetainWithNSRelease([referrer copy]); + info->path = HardRetainWithNSRelease([path copy]); + + pthread_create(&tid, &attr, setMetaData, info); + pthread_attr_destroy(&attr); } - (NSString *)_webkit_startupVolumeName diff --git a/WebKit/mac/Misc/WebNSURLExtras.h b/WebKit/mac/Misc/WebNSURLExtras.h index f8823b9..40f7cf7 100644 --- a/WebKit/mac/Misc/WebNSURLExtras.h +++ b/WebKit/mac/Misc/WebNSURLExtras.h @@ -60,6 +60,7 @@ - (NSURL *)_webkit_URLByRemovingResourceSpecifier; - (BOOL)_webkit_isJavaScriptURL; +- (BOOL)_webkit_isFileURL; - (NSString *)_webkit_scriptIfJavaScriptURL; - (BOOL)_webkit_isFTPDirectoryURL; diff --git a/WebKit/mac/Misc/WebNSURLExtras.mm b/WebKit/mac/Misc/WebNSURLExtras.mm index b388c22..a081f1a 100644 --- a/WebKit/mac/Misc/WebNSURLExtras.mm +++ b/WebKit/mac/Misc/WebNSURLExtras.mm @@ -571,6 +571,7 @@ static CFStringRef createStringWithEscapedUnsafeCharacters(CFStringRef string) free(after); result = mapHostNames(result, !needsHostNameDecoding); + result = [result precomposedStringWithCanonicalMapping]; return WebCFAutorelease(createStringWithEscapedUnsafeCharacters((CFStringRef)result)); } diff --git a/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.h b/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.h new file mode 100644 index 0000000..539372c --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if USE(PLUGIN_HOST_PROCESS) + +#ifndef HostedNetscapePluginStream_h +#define HostedNetscapePluginStream_h + +#include <WebCore/NetscapePlugInStreamLoader.h> +#include <WebKit/npapi.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> +#include <wtf/RetainPtr.h> + +namespace WebCore { + class FrameLoader; + class NetscapePlugInStreamLoader; +} + +namespace WebKit { + +class NetscapePluginInstanceProxy; + +class HostedNetscapePluginStream : public RefCounted<HostedNetscapePluginStream> + , private WebCore::NetscapePlugInStreamLoaderClient { +public: + static PassRefPtr<HostedNetscapePluginStream> create(NetscapePluginInstanceProxy* instance, uint32_t streamID, NSURLRequest *request) + { + return adoptRef(new HostedNetscapePluginStream(instance, streamID, request)); + } + + uint32_t streamID() const { return m_streamID; } + + void startStreamWithResponse(NSURLResponse *response); + void didReceiveData(WebCore::NetscapePlugInStreamLoader*, const char* bytes, int length); + void didFinishLoading(WebCore::NetscapePlugInStreamLoader*); + + void start(); + void stop(); + + void cancelLoad(NPReason reason); + +private: + NSError *errorForReason(NPReason) const; + void cancelLoad(NSError *); + + HostedNetscapePluginStream(NetscapePluginInstanceProxy*, uint32_t streamID, NSURLRequest *); + + void startStream(NSURL *, long long expectedContentLength, NSDate *lastModifiedDate, NSString *mimeType, NSData *headers); + + NSError *pluginCancelledConnectionError() const; + + // NetscapePlugInStreamLoaderClient methods. + void didReceiveResponse(WebCore::NetscapePlugInStreamLoader*, const WebCore::ResourceResponse&); + void didFail(WebCore::NetscapePlugInStreamLoader*, const WebCore::ResourceError&); + bool wantsAllStreams() const; + + RefPtr<NetscapePluginInstanceProxy> m_instance; + uint32_t m_streamID; + bool m_isTerminated; + RetainPtr<NSMutableURLRequest> m_request; + + RetainPtr<NSURL> m_requestURL; + RetainPtr<NSURL> m_responseURL; + RetainPtr<NSString> m_mimeType; + + WebCore::FrameLoader* m_frameLoader; + RefPtr<WebCore::NetscapePlugInStreamLoader> m_loader; +}; + +} + +#endif // HostedNetscapePluginStream_h +#endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.mm b/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.mm new file mode 100644 index 0000000..c2abc92 --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.mm @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if USE(PLUGIN_HOST_PROCESS) + +#import "HostedNetscapePluginStream.h" + +#import "NetscapePluginHostProxy.h" +#import "NetscapePluginInstanceProxy.h" +#import "WebFrameInternal.h" +#import "WebHostedNetscapePluginView.h" +#import "WebKitErrorsPrivate.h" +#import "WebKitPluginHost.h" +#import "WebKitSystemInterface.h" +#import "WebNSURLExtras.h" +#import "WebNSURLRequestExtras.h" +#import <WebCore/DocumentLoader.h> +#import <WebCore/Frame.h> +#import <WebCore/FrameLoader.h> +#import <WebCore/WebCoreURLResponse.h> + +using namespace WebCore; + +namespace WebKit { + +HostedNetscapePluginStream::HostedNetscapePluginStream(NetscapePluginInstanceProxy* instance, uint32_t streamID, NSURLRequest *request) + : m_instance(instance) + , m_streamID(streamID) + , m_isTerminated(false) + , m_request(AdoptNS, [request mutableCopy]) + , m_requestURL([request URL]) + , m_frameLoader(0) +{ + if (core([instance->pluginView() webFrame])->loader()->shouldHideReferrer([request URL], core([instance->pluginView() webFrame])->loader()->outgoingReferrer())) + [m_request.get() _web_setHTTPReferrer:nil]; +} + +void HostedNetscapePluginStream::startStreamWithResponse(NSURLResponse *response) +{ + didReceiveResponse(0, response); +} + +void HostedNetscapePluginStream::startStream(NSURL *responseURL, long long expectedContentLength, NSDate *lastModifiedDate, NSString *mimeType, NSData *headers) +{ + m_responseURL = responseURL; + m_mimeType = mimeType; + + char* mimeTypeUTF8 = const_cast<char*>([mimeType UTF8String]); + int mimeTypeUTF8Length = mimeTypeUTF8 ? strlen (mimeTypeUTF8) + 1 : 0; + + const char *url = [responseURL _web_URLCString]; + int urlLength = url ? strlen(url) + 1 : 0; + + _WKPHStartStream(m_instance->hostProxy()->port(), + m_instance->pluginID(), + m_streamID, + const_cast<char*>(url), urlLength, + expectedContentLength, + [lastModifiedDate timeIntervalSince1970], + mimeTypeUTF8, mimeTypeUTF8Length, + const_cast<char*>(reinterpret_cast<const char*>([headers bytes])), [headers length]); +} + +void HostedNetscapePluginStream::didReceiveData(WebCore::NetscapePlugInStreamLoader*, const char* bytes, int length) +{ + _WKPHStreamDidReceiveData(m_instance->hostProxy()->port(), + m_instance->pluginID(), + m_streamID, + const_cast<char*>(bytes), length); +} + +void HostedNetscapePluginStream::didFinishLoading(WebCore::NetscapePlugInStreamLoader*) +{ + _WKPHStreamDidFinishLoading(m_instance->hostProxy()->port(), + m_instance->pluginID(), + m_streamID); + m_instance->disconnectStream(this); +} + +void HostedNetscapePluginStream::didReceiveResponse(NetscapePlugInStreamLoader*, const ResourceResponse& response) +{ + NSURLResponse *r = response.nsURLResponse(); + + NSMutableData *theHeaders = nil; + long long expectedContentLength = [r expectedContentLength]; + + if ([r isKindOfClass:[NSHTTPURLResponse class]]) { + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)r; + theHeaders = [NSMutableData dataWithCapacity:1024]; + + // FIXME: it would be nice to be able to get the raw HTTP header block. + // This includes the HTTP version, the real status text, + // all headers in their original order and including duplicates, + // and all original bytes verbatim, rather than sent through Unicode translation. + // Unfortunately NSHTTPURLResponse doesn't provide access at that low a level. + + [theHeaders appendBytes:"HTTP " length:5]; + char statusStr[10]; + long statusCode = [httpResponse statusCode]; + snprintf(statusStr, sizeof(statusStr), "%ld", statusCode); + [theHeaders appendBytes:statusStr length:strlen(statusStr)]; + [theHeaders appendBytes:" OK\n" length:4]; + + // HACK: pass the headers through as UTF-8. + // This is not the intended behavior; we're supposed to pass original bytes verbatim. + // But we don't have the original bytes, we have NSStrings built by the URL loading system. + // It hopefully shouldn't matter, since RFC2616/RFC822 require ASCII-only headers, + // but surely someone out there is using non-ASCII characters, and hopefully UTF-8 is adequate here. + // It seems better than NSASCIIStringEncoding, which will lose information if non-ASCII is used. + + NSDictionary *headerDict = [httpResponse allHeaderFields]; + NSArray *keys = [[headerDict allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; + NSEnumerator *i = [keys objectEnumerator]; + NSString *k; + while ((k = [i nextObject]) != nil) { + NSString *v = [headerDict objectForKey:k]; + [theHeaders appendData:[k dataUsingEncoding:NSUTF8StringEncoding]]; + [theHeaders appendBytes:": " length:2]; + [theHeaders appendData:[v dataUsingEncoding:NSUTF8StringEncoding]]; + [theHeaders appendBytes:"\n" length:1]; + } + + // If the content is encoded (most likely compressed), then don't send its length to the plugin, + // which is only interested in the decoded length, not yet known at the moment. + // <rdar://problem/4470599> tracks a request for -[NSURLResponse expectedContentLength] to incorporate this logic. + NSString *contentEncoding = (NSString *)[[(NSHTTPURLResponse *)r allHeaderFields] objectForKey:@"Content-Encoding"]; + if (contentEncoding && ![contentEncoding isEqualToString:@"identity"]) + expectedContentLength = -1; + + [theHeaders appendBytes:"\0" length:1]; + } + + startStream([r URL], expectedContentLength, WKGetNSURLResponseLastModifiedDate(r), [r _webcore_MIMEType], theHeaders); +} + +static NPReason reasonForError(NSError *error) +{ + if (!error) + return NPRES_DONE; + + if ([[error domain] isEqualToString:NSURLErrorDomain] && [error code] == NSURLErrorCancelled) + return NPRES_USER_BREAK; + + return NPRES_NETWORK_ERR; +} + +void HostedNetscapePluginStream::didFail(WebCore::NetscapePlugInStreamLoader*, const WebCore::ResourceError& error) +{ + if (NetscapePluginHostProxy* hostProxy = m_instance->hostProxy()) + _WKPHStreamDidFail(hostProxy->port(), m_instance->pluginID(), m_streamID, reasonForError(error)); +} + +bool HostedNetscapePluginStream::wantsAllStreams() const +{ + // FIXME: Implement. + return false; +} + +void HostedNetscapePluginStream::start() +{ + ASSERT(m_request); + ASSERT(!m_frameLoader); + ASSERT(!m_loader); + + m_loader = NetscapePlugInStreamLoader::create(core([m_instance->pluginView() webFrame]), this); + m_loader->setShouldBufferData(false); + + m_loader->documentLoader()->addPlugInStreamLoader(m_loader.get()); + m_loader->load(m_request.get()); +} + +void HostedNetscapePluginStream::stop() +{ + ASSERT(!m_frameLoader); + + if (!m_loader->isDone()) + m_loader->cancel(m_loader->cancelledError()); +} + +void HostedNetscapePluginStream::cancelLoad(NPReason reason) +{ + cancelLoad(errorForReason(reason)); +} + +void HostedNetscapePluginStream::cancelLoad(NSError *error) +{ + if (m_frameLoader) { + ASSERT(!m_loader); + + DocumentLoader* documentLoader = m_frameLoader->activeDocumentLoader(); + ASSERT(documentLoader); + + if (documentLoader->isLoadingMainResource()) + documentLoader->cancelMainResourceLoad(error); + return; + } + + if (!m_loader->isDone()) + m_loader->cancel(error); + m_instance->disconnectStream(this); +} + +NSError *HostedNetscapePluginStream::pluginCancelledConnectionError() const +{ + return [[[NSError alloc] _initWithPluginErrorCode:WebKitErrorPlugInCancelledConnection + contentURL:m_responseURL ? m_responseURL.get() : m_requestURL.get() + pluginPageURL:nil + pluginName:[[m_instance->pluginView() pluginPackage] name] + MIMEType:m_mimeType.get()] autorelease]; +} + +NSError *HostedNetscapePluginStream::errorForReason(NPReason reason) const +{ + if (reason == NPRES_DONE) + return nil; + + if (reason == NPRES_USER_BREAK) + return [NSError _webKitErrorWithDomain:NSURLErrorDomain + code:NSURLErrorCancelled + URL:m_responseURL ? m_responseURL.get() : m_requestURL.get()]; + + return pluginCancelledConnectionError(); +} + +} // namespace WebKit + +#endif // USE(PLUGIN_HOST_PROCESS) + diff --git a/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.h b/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.h new file mode 100644 index 0000000..d550dac --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if USE(PLUGIN_HOST_PROCESS) + +#ifndef NetscapePluginHostManager_h +#define NetscapePluginHostManager_h + +#import <wtf/HashMap.h> +#import <wtf/PassRefPtr.h> + +@class WebHostedNetscapePluginView; +@class WebNetscapePluginPackage; + +namespace WebKit { + +class NetscapePluginInstanceProxy; +class NetscapePluginHostProxy; + +class NetscapePluginHostManager { +public: + static NetscapePluginHostManager& shared(); + + PassRefPtr<NetscapePluginInstanceProxy> instantiatePlugin(WebNetscapePluginPackage *, WebHostedNetscapePluginView *, NSString *mimeType, NSArray *attributeKeys, NSArray *attributeValues, NSString *userAgent, NSURL *sourceURL); + + void pluginHostDied(NetscapePluginHostProxy*); + + static void createPropertyListFile(WebNetscapePluginPackage *); + +private: + NetscapePluginHostProxy* hostForPackage(WebNetscapePluginPackage *); + + NetscapePluginHostManager(); + ~NetscapePluginHostManager(); + + bool spawnPluginHost(WebNetscapePluginPackage *, mach_port_t clientPort, mach_port_t& pluginHostPort, ProcessSerialNumber& pluginHostPSN); + + bool initializeVendorPort(); + + mach_port_t m_pluginVendorPort; + + // FIXME: This should really be a HashMap of RetainPtrs, but that doesn't work right now. + typedef HashMap<WebNetscapePluginPackage*, NetscapePluginHostProxy*> PluginHostMap; + PluginHostMap m_pluginHosts; +}; + +} // namespace WebKit + +#endif // NetscapePluginHostManager_h +#endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.mm b/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.mm new file mode 100644 index 0000000..08a6d6a --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/NetscapePluginHostManager.mm @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if USE(PLUGIN_HOST_PROCESS) + +#import "NetscapePluginHostManager.h" + +#import "NetscapePluginHostProxy.h" +#import "NetscapePluginInstanceProxy.h" +#import "WebKitSystemInterface.h" +#import "WebNetscapePluginPackage.h" +#import <mach/mach_port.h> +#import <servers/bootstrap.h> +#import <spawn.h> +#import <wtf/Assertions.h> +#import <wtf/RetainPtr.h> +#import <wtf/StdLibExtras.h> + +extern "C" { +#import "WebKitPluginAgent.h" +#import "WebKitPluginHost.h" +} + +using namespace std; + +namespace WebKit { + +NetscapePluginHostManager& NetscapePluginHostManager::shared() +{ + DEFINE_STATIC_LOCAL(NetscapePluginHostManager, pluginHostManager, ()); + + return pluginHostManager; +} + +static const NSString *pluginHostAppName = @"WebKitPluginHost.app"; + +NetscapePluginHostManager::NetscapePluginHostManager() + : m_pluginVendorPort(MACH_PORT_NULL) +{ +} + +NetscapePluginHostManager::~NetscapePluginHostManager() +{ +} + +NetscapePluginHostProxy* NetscapePluginHostManager::hostForPackage(WebNetscapePluginPackage *package) +{ + pair<PluginHostMap::iterator, bool> result = m_pluginHosts.add(package, 0); + + // The package was already in the map, just return it. + if (!result.second) + return result.first->second; + + mach_port_t clientPort; + if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &clientPort) != KERN_SUCCESS) + return 0; + + mach_port_t pluginHostPort; + ProcessSerialNumber pluginHostPSN; + if (!spawnPluginHost(package, clientPort, pluginHostPort, pluginHostPSN)) { + mach_port_destroy(mach_task_self(), clientPort); + return 0; + } + + NetscapePluginHostProxy* hostProxy = new NetscapePluginHostProxy(clientPort, pluginHostPort, pluginHostPSN); + + CFRetain(package); + result.first->second = hostProxy; + + return hostProxy; +} + +bool NetscapePluginHostManager::spawnPluginHost(WebNetscapePluginPackage *package, mach_port_t clientPort, mach_port_t& pluginHostPort, ProcessSerialNumber& pluginHostPSN) +{ + if (m_pluginVendorPort == MACH_PORT_NULL) { + if (!initializeVendorPort()) + return false; + } + + mach_port_t renderServerPort = WKInitializeRenderServer(); + if (renderServerPort == MACH_PORT_NULL) + return false; + + NSString *pluginHostAppPath = [[NSBundle bundleWithIdentifier:@"com.apple.WebKit"] pathForAuxiliaryExecutable:pluginHostAppName]; + NSString *pluginHostAppExecutablePath = [[NSBundle bundleWithPath:pluginHostAppPath] executablePath]; + + NSDictionary *launchProperties = [[NSDictionary alloc] initWithObjectsAndKeys: + pluginHostAppExecutablePath, @"pluginHostPath", + [NSNumber numberWithInt:[package pluginHostArchitecture]], @"cpuType", + nil]; + + NSData *data = [NSPropertyListSerialization dataFromPropertyList:launchProperties format:NSPropertyListBinaryFormat_v1_0 errorDescription:0]; + ASSERT(data); + + [launchProperties release]; + + kern_return_t kr = _WKPASpawnPluginHost(m_pluginVendorPort, reinterpret_cast<uint8_t*>(const_cast<void*>([data bytes])), [data length], &pluginHostPort); + + if (kr == MACH_SEND_INVALID_DEST) { + // The plug-in vendor port has gone away for some reason. Try to reinitialize it. + m_pluginVendorPort = MACH_PORT_NULL; + if (!initializeVendorPort()) + return false; + + // And spawn the plug-in host again. + kr = _WKPASpawnPluginHost(m_pluginVendorPort, reinterpret_cast<uint8_t*>(const_cast<void*>([data bytes])), [data length], &pluginHostPort); + } + + if (kr != KERN_SUCCESS) { + // FIXME: Check for invalid dest and try to re-spawn the plug-in agent. + LOG_ERROR("Failed to spawn plug-in host, error %x", kr); + return false; + } + + NSString *visibleName = [NSString stringWithFormat:@"%@ Plug-in Host - %@", [[NSProcessInfo processInfo] processName], [package filename]]; + + NSDictionary *hostProperties = [[NSDictionary alloc] initWithObjectsAndKeys: + visibleName, @"visibleName", + [package path], @"bundlePath", + nil]; + + data = [NSPropertyListSerialization dataFromPropertyList:hostProperties format:NSPropertyListBinaryFormat_v1_0 errorDescription:nil]; + ASSERT(data); + + [hostProperties release]; + + ProcessSerialNumber psn; + GetCurrentProcess(&psn); + + kr = _WKPHCheckInWithPluginHost(pluginHostPort, (uint8_t*)[data bytes], [data length], clientPort, psn.highLongOfPSN, psn.lowLongOfPSN, renderServerPort, + &pluginHostPSN.highLongOfPSN, &pluginHostPSN.lowLongOfPSN); + + if (kr != KERN_SUCCESS) { + mach_port_deallocate(mach_task_self(), pluginHostPort); + LOG_ERROR("Failed to check in with plug-in host, error %x", kr); + + return false; + } + + return true; +} + +bool NetscapePluginHostManager::initializeVendorPort() +{ + ASSERT(m_pluginVendorPort == MACH_PORT_NULL); + + // Get the plug-in agent port. + mach_port_t pluginAgentPort; + if (bootstrap_look_up(bootstrap_port, "com.apple.WebKit.PluginAgent", &pluginAgentPort) != KERN_SUCCESS) { + LOG_ERROR("Failed to look up the plug-in agent port"); + return false; + } + + NSData *appNameData = [[[NSProcessInfo processInfo] processName] dataUsingEncoding:NSUTF8StringEncoding]; + + // Tell the plug-in agent that we exist. + if (_WKPACheckInApplication(pluginAgentPort, (uint8_t*)[appNameData bytes], [appNameData length], &m_pluginVendorPort) != KERN_SUCCESS) + return false; + + // FIXME: Should we add a notification for when the vendor port dies? + + return true; +} + +void NetscapePluginHostManager::pluginHostDied(NetscapePluginHostProxy* pluginHost) +{ + PluginHostMap::iterator end = m_pluginHosts.end(); + + // This has O(n) complexity but the number of active plug-in hosts is very small so it shouldn't matter. + for (PluginHostMap::iterator it = m_pluginHosts.begin(); it != end; ++it) { + if (it->second == pluginHost) { + m_pluginHosts.remove(it); + return; + } + } +} + +PassRefPtr<NetscapePluginInstanceProxy> NetscapePluginHostManager::instantiatePlugin(WebNetscapePluginPackage *pluginPackage, WebHostedNetscapePluginView *pluginView, NSString *mimeType, NSArray *attributeKeys, NSArray *attributeValues, NSString *userAgent, NSURL *sourceURL) +{ + NetscapePluginHostProxy* hostProxy = hostForPackage(pluginPackage); + if (!hostProxy) + return 0; + + RetainPtr<NSMutableDictionary> properties(AdoptNS, [[NSMutableDictionary alloc] init]); + + if (mimeType) + [properties.get() setObject:mimeType forKey:@"mimeType"]; + + ASSERT_ARG(userAgent, userAgent); + [properties.get() setObject:userAgent forKey:@"userAgent"]; + + ASSERT_ARG(attributeKeys, attributeKeys); + [properties.get() setObject:attributeKeys forKey:@"attributeKeys"]; + + ASSERT_ARG(attributeValues, attributeValues); + [properties.get() setObject:attributeValues forKey:@"attributeValues"]; + + if (sourceURL) + [properties.get() setObject:[sourceURL absoluteString] forKey:@"sourceURL"]; + + NSData *data = [NSPropertyListSerialization dataFromPropertyList:properties.get() format:NSPropertyListBinaryFormat_v1_0 errorDescription:nil]; + ASSERT(data); + + RefPtr<NetscapePluginInstanceProxy> instance = NetscapePluginInstanceProxy::create(hostProxy, pluginView); + uint32_t requestID = instance->nextRequestID(); + kern_return_t kr = _WKPHInstantiatePlugin(hostProxy->port(), requestID, (uint8_t*)[data bytes], [data length], instance->pluginID()); + if (kr == MACH_SEND_INVALID_DEST) { + // The plug-in host must have died, but we haven't received the death notification yet. + pluginHostDied(hostProxy); + + // Try to spawn it again. + hostProxy = hostForPackage(pluginPackage); + + // Create a new instance. + instance = NetscapePluginInstanceProxy::create(hostProxy, pluginView); + requestID = instance->nextRequestID(); + kr = _WKPHInstantiatePlugin(hostProxy->port(), requestID, (uint8_t*)[data bytes], [data length], instance->pluginID()); + } + + auto_ptr<NetscapePluginInstanceProxy::InstantiatePluginReply> reply = instance->waitForReply<NetscapePluginInstanceProxy::InstantiatePluginReply>(requestID); + if (!reply.get() || reply->m_resultCode != KERN_SUCCESS) { + instance->invalidate(); + return 0; + } + + instance->setRenderContextID(reply->m_renderContextID); + instance->setUseSoftwareRenderer(reply->m_useSoftwareRenderer); + + return instance.release(); +} + +void NetscapePluginHostManager::createPropertyListFile(WebNetscapePluginPackage *package) +{ + NSString *pluginHostAppPath = [[NSBundle bundleWithIdentifier:@"com.apple.WebKit"] pathForAuxiliaryExecutable:pluginHostAppName]; + NSString *pluginHostAppExecutablePath = [[NSBundle bundleWithPath:pluginHostAppPath] executablePath]; + NSString *bundlePath = [package path]; + + pid_t pid; + posix_spawnattr_t attr; + posix_spawnattr_init(&attr); + + // Set the architecture. + size_t ocount = 0; + int cpuTypes[1] = { [package pluginHostArchitecture] }; + posix_spawnattr_setbinpref_np(&attr, 1, cpuTypes, &ocount); + + // Spawn the plug-in host and tell it to call the registration function. + const char* args[] = { [pluginHostAppExecutablePath fileSystemRepresentation], "-createPluginMIMETypesPreferences", [bundlePath fileSystemRepresentation], 0 }; + + int result = posix_spawn(&pid, args[0], 0, &attr, const_cast<char* const*>(args), 0); + posix_spawnattr_destroy(&attr); + + if (!result && pid > 0) { + // Wait for the process to finish. + while (waitpid(pid, 0, 0) == -1) { } + } +} + + +} // namespace WebKit + +#endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.h b/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.h new file mode 100644 index 0000000..4676f47 --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if USE(PLUGIN_HOST_PROCESS) + +#ifndef NetscapePluginHostProxy_h +#define NetscapePluginHostProxy_h + +#include <dispatch/dispatch.h> +#include <wtf/HashMap.h> +#include <wtf/RetainPtr.h> +#include <wtf/PassRefPtr.h> + +namespace WebKit { + +class NetscapePluginInstanceProxy; + +class NetscapePluginHostProxy { +public: + NetscapePluginHostProxy(mach_port_t clientPort, mach_port_t pluginHostPort, const ProcessSerialNumber& pluginHostPSN); + + mach_port_t port() const { return m_pluginHostPort; } + mach_port_t clientPort() const { return m_clientPort; } + + void addPluginInstance(NetscapePluginInstanceProxy*); + void removePluginInstance(NetscapePluginInstanceProxy*); + + NetscapePluginInstanceProxy* pluginInstance(uint32_t pluginID); + + void setMenuBarVisible(bool); + void setModal(bool); + + void applicationDidBecomeActive(); + + bool processRequests(); + +private: + ~NetscapePluginHostProxy(); + void pluginHostDied(); + + void beginModal(); + void endModal(); + + static void deadNameNotificationCallback(CFMachPortRef port, void *msg, CFIndex size, void *info); + + typedef HashMap<uint32_t, RefPtr<NetscapePluginInstanceProxy> > PluginInstanceMap; + PluginInstanceMap m_instances; + + mach_port_t m_clientPort; + mach_port_t m_portSet; + +#ifdef USE_LIBDISPATCH + dispatch_source_t m_clientPortSource; +#else + RetainPtr<CFRunLoopSourceRef> m_clientPortSource; +#endif + mach_port_t m_pluginHostPort; + RetainPtr<CFMachPortRef> m_deadNameNotificationPort; + + RetainPtr<id> m_activationObserver; + RetainPtr<NSWindow *> m_placeholderWindow; + unsigned m_isModal; + bool m_menuBarIsVisible; + const ProcessSerialNumber m_pluginHostPSN; +}; + +} // namespace WebKit + +#endif // NetscapePluginHostProxy_h +#endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm b/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm new file mode 100644 index 0000000..c0beb2f --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm @@ -0,0 +1,847 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if USE(PLUGIN_HOST_PROCESS) + +#import "NetscapePluginHostProxy.h" + +#import <mach/mach.h> +#import <wtf/StdLibExtras.h> + +#import "HostedNetscapePluginStream.h" +#import "NetscapePluginHostManager.h" +#import "NetscapePluginInstanceProxy.h" +#import "WebFrameInternal.h" +#import "WebHostedNetscapePluginView.h" +#import "WebKitSystemInterface.h" +#import <WebCore/Frame.h> +#import <WebCore/IdentifierRep.h> +#import <WebCore/ScriptController.h> + +extern "C" { +#import "WebKitPluginHost.h" +#import "WebKitPluginClientServer.h" +} + +using namespace std; +using namespace JSC; +using namespace WebCore; + +namespace WebKit { + +class PluginDestroyDeferrer { +public: + PluginDestroyDeferrer(NetscapePluginInstanceProxy* proxy) + : m_proxy(proxy) + { + m_proxy->willCallPluginFunction(); + } + + ~PluginDestroyDeferrer() + { + m_proxy->didCallPluginFunction(); + } + +private: + RefPtr<NetscapePluginInstanceProxy> m_proxy; +}; + +typedef HashMap<mach_port_t, NetscapePluginHostProxy*> PluginProxyMap; +static PluginProxyMap& pluginProxyMap() +{ + DEFINE_STATIC_LOCAL(PluginProxyMap, pluginProxyMap, ()); + + return pluginProxyMap; +} + +NetscapePluginHostProxy::NetscapePluginHostProxy(mach_port_t clientPort, mach_port_t pluginHostPort, const ProcessSerialNumber& pluginHostPSN) + : m_clientPort(clientPort) + , m_portSet(MACH_PORT_NULL) + , m_pluginHostPort(pluginHostPort) + , m_isModal(false) + , m_menuBarIsVisible(true) + , m_pluginHostPSN(pluginHostPSN) +{ + pluginProxyMap().add(m_clientPort, this); + + // FIXME: We should use libdispatch for this. + CFMachPortContext context = { 0, this, 0, 0, 0 }; + m_deadNameNotificationPort.adoptCF(CFMachPortCreate(0, deadNameNotificationCallback, &context, 0)); + + mach_port_t previous; + mach_port_request_notification(mach_task_self(), pluginHostPort, MACH_NOTIFY_DEAD_NAME, 0, + CFMachPortGetPort(m_deadNameNotificationPort.get()), MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous); + ASSERT(previous == MACH_PORT_NULL); + + RetainPtr<CFRunLoopSourceRef> deathPortSource(AdoptCF, CFMachPortCreateRunLoopSource(0, m_deadNameNotificationPort.get(), 0)); + + CFRunLoopAddSource(CFRunLoopGetCurrent(), deathPortSource.get(), kCFRunLoopDefaultMode); + +#ifdef USE_LIBDISPATCH + // FIXME: Unfortunately we can't use a dispatch source here until <rdar://problem/6393180> has been resolved. + m_clientPortSource = dispatch_source_mig_create(m_clientPort, WKWebKitPluginClient_subsystem.maxsize, 0, + dispatch_get_main_queue(), WebKitPluginClient_server); +#else + m_clientPortSource.adoptCF(WKCreateMIGServerSource((mig_subsystem_t)&WKWebKitPluginClient_subsystem, m_clientPort)); + CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), kCFRunLoopDefaultMode); + CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSEventTrackingRunLoopMode); +#endif +} + +NetscapePluginHostProxy::~NetscapePluginHostProxy() +{ + pluginProxyMap().remove(m_clientPort); + + // Free the port set + if (m_portSet) { + mach_port_extract_member(mach_task_self(), m_clientPort, m_portSet); + mach_port_extract_member(mach_task_self(), CFMachPortGetPort(m_deadNameNotificationPort.get()), m_portSet); + mach_port_destroy(mach_task_self(), m_portSet); + } + + ASSERT(m_clientPortSource); +#ifdef USE_LIBDISPATCH + dispatch_release(m_clientPortSource); +#else + CFRunLoopSourceInvalidate(m_clientPortSource.get()); + m_clientPortSource = 0; +#endif +} + +void NetscapePluginHostProxy::pluginHostDied() +{ + PluginInstanceMap instances; + m_instances.swap(instances); + + PluginInstanceMap::const_iterator end = instances.end(); + for (PluginInstanceMap::const_iterator it = instances.begin(); it != end; ++it) + it->second->pluginHostDied(); + + NetscapePluginHostManager::shared().pluginHostDied(this); + + // The plug-in crashed while its menu bar was hidden. Make sure to show it. + if (!m_menuBarIsVisible) + setMenuBarVisible(true); + + // The plug-in crashed while it had a modal dialog up. + if (m_isModal) + endModal(); + + delete this; +} + +void NetscapePluginHostProxy::addPluginInstance(NetscapePluginInstanceProxy* instance) +{ + ASSERT(!m_instances.contains(instance->pluginID())); + + m_instances.set(instance->pluginID(), instance); +} + +void NetscapePluginHostProxy::removePluginInstance(NetscapePluginInstanceProxy* instance) +{ + ASSERT(m_instances.get(instance->pluginID()) == instance); + + m_instances.remove(instance->pluginID()); +} + +NetscapePluginInstanceProxy* NetscapePluginHostProxy::pluginInstance(uint32_t pluginID) +{ + return m_instances.get(pluginID).get(); +} + +void NetscapePluginHostProxy::deadNameNotificationCallback(CFMachPortRef port, void *msg, CFIndex size, void *info) +{ + ASSERT(msg && static_cast<mach_msg_header_t*>(msg)->msgh_id == MACH_NOTIFY_DEAD_NAME); + + static_cast<NetscapePluginHostProxy*>(info)->pluginHostDied(); +} + +void NetscapePluginHostProxy::setMenuBarVisible(bool visible) +{ + m_menuBarIsVisible = visible; + + [NSMenu setMenuBarVisible:visible]; + if (visible) { + // Make ourselves the front app + ProcessSerialNumber psn; + GetCurrentProcess(&psn); + SetFrontProcess(&psn); + } +} + +void NetscapePluginHostProxy::applicationDidBecomeActive() +{ + SetFrontProcess(&m_pluginHostPSN); +} + +void NetscapePluginHostProxy::beginModal() +{ + ASSERT(!m_placeholderWindow); + ASSERT(!m_activationObserver); + + m_placeholderWindow.adoptNS([[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 1, 1) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]); + + m_activationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillBecomeActiveNotification object:NSApp queue:nil + usingBlock:^(NSNotification *){ applicationDidBecomeActive(); }]; + + // We need to be able to get the setModal(false) call from the plug-in host. + CFRunLoopAddSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSModalPanelRunLoopMode); + + [NSApp runModalForWindow:m_placeholderWindow.get()]; +} + +void NetscapePluginHostProxy::endModal() +{ + ASSERT(m_placeholderWindow); + ASSERT(m_activationObserver); + + [[NSNotificationCenter defaultCenter] removeObserver:m_activationObserver.get()]; + m_activationObserver = nil; + + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_clientPortSource.get(), (CFStringRef)NSModalPanelRunLoopMode); + + [NSApp stopModal]; + [m_placeholderWindow.get() orderOut:nil]; + m_placeholderWindow = 0; + + // Make ourselves the front process. + ProcessSerialNumber psn; + GetCurrentProcess(&psn); + SetFrontProcess(&psn); +} + + +void NetscapePluginHostProxy::setModal(bool modal) +{ + if (modal == m_isModal) + return; + + m_isModal = modal; + + if (m_isModal) + beginModal(); + else + endModal(); +} + +bool NetscapePluginHostProxy::processRequests() +{ + if (!m_portSet) { + mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &m_portSet); + mach_port_insert_member(mach_task_self(), m_clientPort, m_portSet); + mach_port_insert_member(mach_task_self(), CFMachPortGetPort(m_deadNameNotificationPort.get()), m_portSet); + } + + char buffer[4096]; + + mach_msg_header_t* msg = reinterpret_cast<mach_msg_header_t*>(buffer); + + kern_return_t kr = mach_msg(msg, MACH_RCV_MSG, 0, sizeof(buffer), m_portSet, 0, MACH_PORT_NULL); + + if (kr != KERN_SUCCESS) { + LOG_ERROR("Could not receive mach message, error %x", kr); + return false; + } + + if (msg->msgh_local_port == m_clientPort) { + __ReplyUnion__WKWebKitPluginClient_subsystem reply; + mach_msg_header_t* replyHeader = reinterpret_cast<mach_msg_header_t*>(&reply); + + if (WebKitPluginClient_server(msg, replyHeader) && replyHeader->msgh_remote_port != MACH_PORT_NULL) { + kr = mach_msg(replyHeader, MACH_SEND_MSG, replyHeader->msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL); + + if (kr != KERN_SUCCESS) { + LOG_ERROR("Could not send mach message, error %x", kr); + return false; + } + } + + return true; + } + + if (msg->msgh_local_port == CFMachPortGetPort(m_deadNameNotificationPort.get())) { + ASSERT(msg->msgh_id == MACH_NOTIFY_DEAD_NAME); + pluginHostDied(); + return false; + } + + ASSERT_NOT_REACHED(); + return false; +} + +} // namespace WebKit + +using namespace WebKit; + +// Helper class for deallocating data +class DataDeallocator { +public: + DataDeallocator(data_t data, mach_msg_type_number_t dataLength) + : m_data(reinterpret_cast<vm_address_t>(data)) + , m_dataLength(dataLength) + { + } + + ~DataDeallocator() + { + if (!m_data) + return; + + vm_deallocate(mach_task_self(), m_data, m_dataLength); + } + +private: + vm_address_t m_data; + vm_size_t m_dataLength; +}; + +// MiG callbacks +kern_return_t WKPCStatusText(mach_port_t clientPort, uint32_t pluginID, data_t text, mach_msg_type_number_t textCnt) +{ + DataDeallocator deallocator(text, textCnt); + + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + instanceProxy->status(text); + return KERN_SUCCESS; +} + +kern_return_t WKPCLoadURL(mach_port_t clientPort, uint32_t pluginID, data_t url, mach_msg_type_number_t urlLength, data_t target, mach_msg_type_number_t targetLength, + data_t postData, mach_msg_type_number_t postDataLength, uint32_t flags, + uint16_t* outResult, uint32_t* outStreamID) +{ + DataDeallocator urlDeallocator(url, urlLength); + DataDeallocator targetDeallocator(target, targetLength); + DataDeallocator postDataDeallocator(postData, postDataLength); + + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + uint32_t streamID = 0; + NPError result = instanceProxy->loadURL(url, target, postData, postDataLength, static_cast<LoadURLFlags>(flags), streamID); + + *outResult = result; + *outStreamID = streamID; + return KERN_SUCCESS; +} + +kern_return_t WKPCCancelLoadURL(mach_port_t clientPort, uint32_t pluginID, uint32_t streamID, int16_t reason) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + HostedNetscapePluginStream* pluginStream = instanceProxy->pluginStream(streamID); + if (!pluginStream) + return KERN_FAILURE; + + pluginStream->cancelLoad(reason); + return KERN_SUCCESS; +} + +kern_return_t WKPCInvalidateRect(mach_port_t clientPort, uint32_t pluginID, double x, double y, double width, double height) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + instanceProxy->invalidateRect(x, y, width, height); + return KERN_SUCCESS; +} + +kern_return_t WKPCGetScriptableNPObjectReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::GetScriptableNPObjectReply(objectID)); + return KERN_SUCCESS; +} + +kern_return_t WKPCBooleanReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, boolean_t result) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::BooleanReply(result)); + return KERN_SUCCESS; +} + +kern_return_t WKPCBooleanAndDataReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, boolean_t returnValue, data_t resultData, mach_msg_type_number_t resultLength) +{ + DataDeallocator deallocator(resultData, resultLength); + + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + RetainPtr<CFDataRef> result(AdoptCF, CFDataCreate(0, reinterpret_cast<UInt8*>(resultData), resultLength)); + instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::BooleanAndDataReply(returnValue, result)); + + return KERN_SUCCESS; +} + +kern_return_t WKPCInstantiatePluginReply(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, kern_return_t result, uint32_t renderContextID, boolean_t useSoftwareRenderer) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + instanceProxy->setCurrentReply(requestID, new NetscapePluginInstanceProxy::InstantiatePluginReply(result, renderContextID, useSoftwareRenderer)); + return KERN_SUCCESS; +} + +kern_return_t WKPCGetWindowNPObject(mach_port_t clientPort, uint32_t pluginID, uint32_t* outObjectID) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + uint32_t objectID; + if (!instanceProxy->getWindowNPObject(objectID)) + return KERN_FAILURE; + + *outObjectID = objectID; + return KERN_SUCCESS; +} + +kern_return_t WKPCGetPluginElementNPObject(mach_port_t clientPort, uint32_t pluginID, uint32_t* outObjectID) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + uint32_t objectID; + if (!instanceProxy->getPluginElementNPObject(objectID)) + return KERN_FAILURE; + + *outObjectID = objectID; + return KERN_SUCCESS; +} + +kern_return_t WKPCReleaseObject(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + instanceProxy->releaseObject(objectID); + return KERN_SUCCESS; +} + +kern_return_t WKPCEvaluate(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, data_t scriptData, mach_msg_type_number_t scriptLength) +{ + DataDeallocator deallocator(scriptData, scriptLength); + + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + PluginDestroyDeferrer deferrer(instanceProxy); + + String script = String::fromUTF8WithLatin1Fallback(scriptData, scriptLength); + + data_t resultData = 0; + mach_msg_type_number_t resultLength = 0; + boolean_t returnValue = instanceProxy->evaluate(objectID, script, resultData, resultLength); + + _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength); + if (resultData) + mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength); + + return KERN_SUCCESS; +} + +kern_return_t WKPCGetStringIdentifier(mach_port_t clientPort, data_t name, mach_msg_type_number_t nameCnt, uint64_t* identifier) +{ + DataDeallocator deallocator(name, nameCnt); + + COMPILE_ASSERT(sizeof(*identifier) == sizeof(IdentifierRep*), identifier_sizes); + + *identifier = reinterpret_cast<uint64_t>(IdentifierRep::get(name)); + return KERN_SUCCESS; +} + +kern_return_t WKPCGetIntIdentifier(mach_port_t clientPort, int32_t value, uint64_t* identifier) +{ + COMPILE_ASSERT(sizeof(*identifier) == sizeof(NPIdentifier), identifier_sizes); + + *identifier = reinterpret_cast<uint64_t>(IdentifierRep::get(value)); + return KERN_SUCCESS; +} + +static Identifier identifierFromIdentifierRep(IdentifierRep* identifier) +{ + ASSERT(IdentifierRep::isValid(identifier)); + ASSERT(identifier->isString()); + + const char* str = identifier->string(); + return Identifier(JSDOMWindow::commonJSGlobalData(), String::fromUTF8WithLatin1Fallback(str, strlen(str))); +} + +kern_return_t WKPCInvoke(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier, + data_t argumentsData, mach_msg_type_number_t argumentsLength) +{ + DataDeallocator deallocator(argumentsData, argumentsLength); + + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + PluginDestroyDeferrer deferrer(instanceProxy); + + IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier); + if (!IdentifierRep::isValid(identifier)) { + _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, false, 0, 0); + return KERN_SUCCESS; + } + + Identifier methodNameIdentifier = identifierFromIdentifierRep(identifier); + + data_t resultData = 0; + mach_msg_type_number_t resultLength = 0; + boolean_t returnValue = instanceProxy->invoke(objectID, methodNameIdentifier, argumentsData, argumentsLength, resultData, resultLength); + + _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength); + if (resultData) + mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength); + + return KERN_SUCCESS; +} + +kern_return_t WKPCInvokeDefault(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, + data_t argumentsData, mach_msg_type_number_t argumentsLength) +{ + DataDeallocator deallocator(argumentsData, argumentsLength); + + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + PluginDestroyDeferrer deferrer(instanceProxy); + + data_t resultData = 0; + mach_msg_type_number_t resultLength = 0; + boolean_t returnValue = instanceProxy->invokeDefault(objectID, argumentsData, argumentsLength, resultData, resultLength); + + _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength); + if (resultData) + mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength); + + return KERN_SUCCESS; +} + +kern_return_t WKPCConstruct(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID, + data_t argumentsData, mach_msg_type_number_t argumentsLength, + boolean_t* returnValue, data_t* resultData, mach_msg_type_number_t* resultLength) +{ + DataDeallocator deallocator(argumentsData, argumentsLength); + + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + PluginDestroyDeferrer deferrer(instanceProxy); + + *returnValue = instanceProxy->construct(objectID, argumentsData, argumentsLength, *resultData, *resultLength); + + return KERN_SUCCESS; +} + +kern_return_t WKPCGetProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier); + if (!IdentifierRep::isValid(identifier)) + return KERN_FAILURE; + + PluginDestroyDeferrer deferrer(instanceProxy); + + data_t resultData = 0; + mach_msg_type_number_t resultLength = 0; + boolean_t returnValue; + + if (identifier->isString()) { + Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier); + returnValue = instanceProxy->getProperty(objectID, propertyNameIdentifier, resultData, resultLength); + } else + returnValue = instanceProxy->setProperty(objectID, identifier->number(), resultData, resultLength); + + _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength); + if (resultData) + mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength); + + return KERN_SUCCESS; +} + +kern_return_t WKPCSetProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID, uint64_t serverIdentifier, data_t valueData, mach_msg_type_number_t valueLength, boolean_t* returnValue) +{ + DataDeallocator deallocator(valueData, valueLength); + + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + PluginDestroyDeferrer deferrer(instanceProxy); + + IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier); + if (!IdentifierRep::isValid(identifier)) + *returnValue = false; + + if (identifier->isString()) { + Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier); + *returnValue = instanceProxy->setProperty(objectID, propertyNameIdentifier, valueData, valueLength); + } else + *returnValue = instanceProxy->setProperty(objectID, identifier->number(), valueData, valueLength); + + return KERN_SUCCESS; +} + +kern_return_t WKPCRemoveProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID, uint64_t serverIdentifier, boolean_t* returnValue) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + PluginDestroyDeferrer deferrer(instanceProxy); + + IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier); + if (!IdentifierRep::isValid(identifier)) + return KERN_FAILURE; + + if (identifier->isString()) { + Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier); + *returnValue = instanceProxy->removeProperty(objectID, propertyNameIdentifier); + } else + *returnValue = instanceProxy->removeProperty(objectID, identifier->number()); + + return KERN_SUCCESS; +} + +kern_return_t WKPCHasProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + PluginDestroyDeferrer deferrer(instanceProxy); + + IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier); + if (!IdentifierRep::isValid(identifier)) { + _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, false); + return KERN_SUCCESS; + } + + boolean_t returnValue; + if (identifier->isString()) { + Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier); + returnValue = instanceProxy->hasProperty(objectID, propertyNameIdentifier); + } else + returnValue = instanceProxy->hasProperty(objectID, identifier->number()); + + _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue); + + return KERN_SUCCESS; +} + +kern_return_t WKPCHasMethod(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + PluginDestroyDeferrer deferrer(instanceProxy); + + IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier); + if (!IdentifierRep::isValid(identifier)) { + _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, false); + return KERN_SUCCESS; + } + + Identifier methodNameIdentifier = identifierFromIdentifierRep(identifier); + boolean_t returnValue = instanceProxy->hasMethod(objectID, methodNameIdentifier); + + _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue); + + return KERN_SUCCESS; +} + +kern_return_t WKPCIdentifierInfo(mach_port_t clientPort, uint64_t serverIdentifier, data_t* infoData, mach_msg_type_number_t* infoLength) +{ + IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier); + if (!IdentifierRep::isValid(identifier)) + return KERN_FAILURE; + + id info; + if (identifier->isString()) { + const char* str = identifier->string(); + info = [NSData dataWithBytesNoCopy:(void*)str length:strlen(str) freeWhenDone:NO]; + } else + info = [NSNumber numberWithInt:identifier->number()]; + + RetainPtr<NSData*> data = [NSPropertyListSerialization dataFromPropertyList:info format:NSPropertyListBinaryFormat_v1_0 errorDescription:0]; + ASSERT(data); + + *infoLength = [data.get() length]; + mig_allocate(reinterpret_cast<vm_address_t*>(infoData), *infoLength); + + memcpy(*infoData, [data.get() bytes], *infoLength); + + return KERN_SUCCESS; +} + +kern_return_t WKPCEnumerate(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); + if (!instanceProxy) + return KERN_FAILURE; + + data_t resultData = 0; + mach_msg_type_number_t resultLength = 0; + boolean_t returnValue = instanceProxy->enumerate(objectID, resultData, resultLength); + + _WKPHBooleanAndDataReply(hostProxy->port(), instanceProxy->pluginID(), requestID, returnValue, resultData, resultLength); + + if (resultData) + mig_deallocate(reinterpret_cast<vm_address_t>(resultData), resultLength); + + return KERN_SUCCESS; +} + +kern_return_t WKPCSetMenuBarVisible(mach_port_t clientPort, boolean_t menuBarVisible) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + hostProxy->setMenuBarVisible(menuBarVisible); + + return KERN_SUCCESS; +} + +kern_return_t WKPCSetModal(mach_port_t clientPort, boolean_t modal) +{ + NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); + if (!hostProxy) + return KERN_FAILURE; + + hostProxy->setModal(modal); + + return KERN_SUCCESS; +} + +#endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h b/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h new file mode 100644 index 0000000..3f9132d --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if USE(PLUGIN_HOST_PROCESS) + +#ifndef NetscapePluginInstanceProxy_h +#define NetscapePluginInstanceProxy_h + +#include <JavaScriptCore/Protect.h> +#include <WebCore/Timer.h> +#include <WebKit/npapi.h> +#include <wtf/Deque.h> +#include <wtf/HashMap.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RetainPtr.h> +#include "WebKitPluginHostTypes.h" + +namespace WebCore { + class String; +} + +namespace JSC { + namespace Bindings { + class Instance; + class RootObject; + } +} +@class WebHostedNetscapePluginView; + +namespace WebKit { + +class HostedNetscapePluginStream; +class NetscapePluginHostProxy; +class ProxyInstance; + +class NetscapePluginInstanceProxy : public RefCounted<NetscapePluginInstanceProxy> { +public: + static PassRefPtr<NetscapePluginInstanceProxy> create(NetscapePluginHostProxy* pluginHostProxy, WebHostedNetscapePluginView *pluginView) + { + return adoptRef(new NetscapePluginInstanceProxy(pluginHostProxy, pluginView)); + } + ~NetscapePluginInstanceProxy(); + + uint32_t pluginID() const + { + ASSERT(m_pluginID); + + return m_pluginID; + } + uint32_t renderContextID() const { return m_renderContextID; } + void setRenderContextID(uint32_t renderContextID) { m_renderContextID = renderContextID; } + + bool useSoftwareRenderer() const { return m_useSoftwareRenderer; } + void setUseSoftwareRenderer(bool useSoftwareRenderer) { m_useSoftwareRenderer = useSoftwareRenderer; } + + WebHostedNetscapePluginView *pluginView() const { return m_pluginView; } + NetscapePluginHostProxy* hostProxy() const { return m_pluginHostProxy; } + + HostedNetscapePluginStream *pluginStream(uint32_t streamID); + void disconnectStream(HostedNetscapePluginStream*); + + void pluginHostDied(); + + void resize(NSRect size, NSRect clipRect); + void destroy(); + void focusChanged(bool hasFocus); + void windowFocusChanged(bool hasFocus); + void windowFrameChanged(NSRect frame); + + void mouseEvent(NSView *pluginView, NSEvent *, NPCocoaEventType); + void keyEvent(NSView *pluginView, NSEvent *, NPCocoaEventType); + void insertText(NSString *); + + void print(CGContextRef, unsigned width, unsigned height); + + void startTimers(bool throttleTimers); + void stopTimers(); + + void invalidateRect(double x, double y, double width, double height); + + // NPRuntime + bool getWindowNPObject(uint32_t& objectID); + bool getPluginElementNPObject(uint32_t& objectID); + void releaseObject(uint32_t objectID); + + bool evaluate(uint32_t objectID, const WebCore::String& script, data_t& resultData, mach_msg_type_number_t& resultLength); + bool invoke(uint32_t objectID, const JSC::Identifier& methodName, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength); + bool invokeDefault(uint32_t objectID, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength); + bool construct(uint32_t objectID, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength); + bool enumerate(uint32_t objectID, data_t& resultData, mach_msg_type_number_t& resultLength); + + bool getProperty(uint32_t objectID, const JSC::Identifier& propertyName, data_t &resultData, mach_msg_type_number_t& resultLength); + bool getProperty(uint32_t objectID, unsigned propertyName, data_t &resultData, mach_msg_type_number_t& resultLength); + bool setProperty(uint32_t objectID, const JSC::Identifier& propertyName, data_t valueData, mach_msg_type_number_t valueLength); + bool setProperty(uint32_t objectID, unsigned propertyName, data_t valueData, mach_msg_type_number_t valueLength); + bool removeProperty(uint32_t objectID, const JSC::Identifier& propertyName); + bool removeProperty(uint32_t objectID, unsigned propertyName); + bool hasProperty(uint32_t objectID, const JSC::Identifier& propertyName); + bool hasProperty(uint32_t objectID, unsigned propertyName); + bool hasMethod(uint32_t objectID, const JSC::Identifier& methodName); + + void status(const char* message); + NPError loadURL(const char* url, const char* target, const char* postData, uint32_t postDataLength, LoadURLFlags, uint32_t& requestID); + + PassRefPtr<JSC::Bindings::Instance> createBindingsInstance(PassRefPtr<JSC::Bindings::RootObject>); + RetainPtr<NSData *> marshalValues(JSC::ExecState*, const JSC::ArgList& args); + void marshalValue(JSC::ExecState*, JSC::JSValuePtr value, data_t& resultData, mach_msg_type_number_t& resultLength); + JSC::JSValuePtr demarshalValue(JSC::ExecState*, const char* valueData, mach_msg_type_number_t valueLength); + + void addInstance(ProxyInstance*); + void removeInstance(ProxyInstance*); + + void invalidate(); + + void willCallPluginFunction(); + void didCallPluginFunction(); + bool shouldStop(); + + uint32_t nextRequestID(); + + // Reply structs + struct Reply { + enum Type { + InstantiatePlugin, + GetScriptableNPObject, + BooleanAndData, + Boolean + }; + + Reply(Type type) + : m_type(type) + { + } + + virtual ~Reply() { } + + Type m_type; + }; + + struct InstantiatePluginReply : public Reply { + static const int ReplyType = InstantiatePlugin; + + InstantiatePluginReply(kern_return_t resultCode, uint32_t renderContextID, boolean_t useSoftwareRenderer) + : Reply(InstantiatePlugin) + , m_resultCode(resultCode) + , m_renderContextID(renderContextID) + , m_useSoftwareRenderer(useSoftwareRenderer) + { + } + + kern_return_t m_resultCode; + uint32_t m_renderContextID; + boolean_t m_useSoftwareRenderer; + }; + + struct GetScriptableNPObjectReply : public Reply { + static const Reply::Type ReplyType = GetScriptableNPObject; + + GetScriptableNPObjectReply(uint32_t objectID) + : Reply(ReplyType) + , m_objectID(objectID) + { + } + + uint32_t m_objectID; + }; + + struct BooleanReply : public Reply { + static const Reply::Type ReplyType = Boolean; + + BooleanReply(boolean_t result) + : Reply(ReplyType) + , m_result(result) + { + } + + boolean_t m_result; + }; + + struct BooleanAndDataReply : public Reply { + static const Reply::Type ReplyType = BooleanAndData; + + BooleanAndDataReply(boolean_t returnValue, RetainPtr<CFDataRef> result) + : Reply(ReplyType) + , m_returnValue(returnValue) + , m_result(result) + { + } + + boolean_t m_returnValue; + RetainPtr<CFDataRef> m_result; + }; + + void setCurrentReply(uint32_t requestID, Reply* reply) + { + ASSERT(!m_replies.contains(requestID)); + m_replies.set(requestID, reply); + } + + template <typename T> + std::auto_ptr<T> waitForReply(uint32_t requestID) + { + m_waitingForReply = true; + + Reply* reply = processRequestsAndWaitForReply(requestID); + if (reply) + ASSERT(reply->m_type == T::ReplyType); + + m_waitingForReply = false; + return std::auto_ptr<T>(static_cast<T*>(reply)); + } + +private: + NetscapePluginInstanceProxy(NetscapePluginHostProxy*, WebHostedNetscapePluginView *); + + NPError loadRequest(NSURLRequest *, const char* cTarget, bool currentEventIsUserGesture, uint32_t& streamID); + + class PluginRequest; + void performRequest(PluginRequest*); + void evaluateJavaScript(PluginRequest*); + + void stopAllStreams(); + Reply* processRequestsAndWaitForReply(uint32_t requestID); + + void cleanup(); + + NetscapePluginHostProxy* m_pluginHostProxy; + WebHostedNetscapePluginView *m_pluginView; + + void requestTimerFired(WebCore::Timer<NetscapePluginInstanceProxy>*); + WebCore::Timer<NetscapePluginInstanceProxy> m_requestTimer; + Deque<PluginRequest*> m_pluginRequests; + + HashMap<uint32_t, RefPtr<HostedNetscapePluginStream> > m_streams; + + uint32_t m_currentURLRequestID; + + uint32_t m_pluginID; + uint32_t m_renderContextID; + boolean_t m_useSoftwareRenderer; + + bool m_waitingForReply; + HashMap<uint32_t, Reply*> m_replies; + + // NPRuntime + uint32_t idForObject(JSC::JSObject*); + + void addValueToArray(NSMutableArray *, JSC::ExecState* exec, JSC::JSValuePtr value); + + bool demarshalValueFromArray(JSC::ExecState*, NSArray *array, NSUInteger& index, JSC::JSValuePtr& result); + void demarshalValues(JSC::ExecState*, data_t valuesData, mach_msg_type_number_t valuesLength, JSC::ArgList& result); + + uint32_t m_objectIDCounter; + typedef HashMap<uint32_t, JSC::ProtectedPtr<JSC::JSObject> > ObjectMap; + ObjectMap m_objects; + + typedef HashSet<ProxyInstance*> ProxyInstanceSet; + ProxyInstanceSet m_instances; + + unsigned m_pluginFunctionCallDepth; + bool m_shouldStopSoon; + uint32_t m_currentRequestID; +}; + +} // namespace WebKit + +#endif // NetscapePluginInstanceProxy_h +#endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm b/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm new file mode 100644 index 0000000..2ef921a --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm @@ -0,0 +1,1154 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if USE(PLUGIN_HOST_PROCESS) + +#import "NetscapePluginInstanceProxy.h" + +#import "HostedNetscapePluginStream.h" +#import "NetscapePluginHostProxy.h" +#import "ProxyInstance.h" +#import "WebDataSourceInternal.h" +#import "WebFrameInternal.h" +#import "WebHostedNetscapePluginView.h" +#import "WebNSDataExtras.h" +#import "WebNSURLExtras.h" +#import "WebKitNSStringExtras.h" +#import "WebPluginRequest.h" +#import "WebViewInternal.h" +#import "WebUIDelegate.h" +#import "WebUIDelegatePrivate.h" + +#import <mach/mach.h> +#import <WebCore/DocumentLoader.h> +#import <WebCore/Frame.h> +#import <WebCore/FrameLoader.h> +#import <WebCore/FrameTree.h> +#import <WebCore/npruntime_impl.h> +#import <WebCore/runtime_object.h> +#import <WebCore/ScriptController.h> +#import <WebCore/ScriptValue.h> +#include <runtime/JSLock.h> +#include <runtime/PropertyNameArray.h> +#import <utility> + +extern "C" { +#import "WebKitPluginClientServer.h" +#import "WebKitPluginHost.h" +} + +using namespace JSC; +using namespace JSC::Bindings; +using namespace std; +using namespace WebCore; + +namespace WebKit { + +class NetscapePluginInstanceProxy::PluginRequest { +public: + PluginRequest(uint32_t requestID, NSURLRequest *request, NSString *frameName, bool didStartFromUserGesture) + : m_requestID(requestID) + , m_request(request) + , m_frameName(frameName) + , m_didStartFromUserGesture(didStartFromUserGesture) + { + } + + uint32_t requestID() const { return m_requestID; } + NSURLRequest *request() const { return m_request.get(); } + NSString *frameName() const { return m_frameName.get(); } + bool didStartFromUserGesture() const { return m_didStartFromUserGesture; } + +private: + uint32_t m_requestID; + RetainPtr<NSURLRequest *> m_request; + RetainPtr<NSString *> m_frameName; + bool m_didStartFromUserGesture; +}; + +static uint32_t pluginIDCounter; + +NetscapePluginInstanceProxy::NetscapePluginInstanceProxy(NetscapePluginHostProxy* pluginHostProxy, WebHostedNetscapePluginView *pluginView) + : m_pluginHostProxy(pluginHostProxy) + , m_pluginView(pluginView) + , m_requestTimer(this, &NetscapePluginInstanceProxy::requestTimerFired) + , m_currentURLRequestID(0) + , m_renderContextID(0) + , m_useSoftwareRenderer(false) + , m_waitingForReply(false) + , m_objectIDCounter(0) + , m_pluginFunctionCallDepth(0) + , m_shouldStopSoon(false) + , m_currentRequestID(0) +{ + ASSERT(m_pluginView); + + // Assign a plug-in ID. + do { + m_pluginID = ++pluginIDCounter; + } while (pluginHostProxy->pluginInstance(m_pluginID) || !m_pluginID); + + pluginHostProxy->addPluginInstance(this); +} + +NetscapePluginInstanceProxy::~NetscapePluginInstanceProxy() +{ + ASSERT(!m_pluginHostProxy); + + m_pluginID = 0; + deleteAllValues(m_replies); +} + +void NetscapePluginInstanceProxy::resize(NSRect size, NSRect clipRect) +{ + _WKPHResizePluginInstance(m_pluginHostProxy->port(), m_pluginID, size.origin.x, size.origin.y, size.size.width, size.size.height); +} + +void NetscapePluginInstanceProxy::stopAllStreams() +{ + Vector<RefPtr<HostedNetscapePluginStream> > streamsCopy; + copyValuesToVector(m_streams, streamsCopy); + for (size_t i = 0; i < streamsCopy.size(); i++) + streamsCopy[i]->stop(); +} + +void NetscapePluginInstanceProxy::cleanup() +{ + stopAllStreams(); + + m_requestTimer.stop(); + + // Clear the object map, this will cause any outstanding JS objects that the plug-in had a reference to + // to go away when the next garbage collection takes place. + m_objects.clear(); + + if (Frame* frame = core([m_pluginView webFrame])) + frame->script()->cleanupScriptObjectsForPlugin(m_pluginView); + + ProxyInstanceSet instances; + instances.swap(m_instances); + + // Invalidate all proxy instances. + ProxyInstanceSet::const_iterator end = instances.end(); + for (ProxyInstanceSet::const_iterator it = instances.begin(); it != end; ++it) + (*it)->invalidate(); + + m_pluginView = nil; +} + +void NetscapePluginInstanceProxy::invalidate() +{ + // If the plug-in host has died, the proxy will be null. + if (!m_pluginHostProxy) + return; + + m_pluginHostProxy->removePluginInstance(this); + m_pluginHostProxy = 0; +} + +void NetscapePluginInstanceProxy::destroy() +{ + uint32_t requestID = nextRequestID(); + + _WKPHDestroyPluginInstance(m_pluginHostProxy->port(), m_pluginID, requestID); + + // We don't care about the reply here - we just want to block until the plug-in instance has been torn down. + waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID); + + cleanup(); + invalidate(); +} + +HostedNetscapePluginStream *NetscapePluginInstanceProxy::pluginStream(uint32_t streamID) +{ + return m_streams.get(streamID).get(); +} + +void NetscapePluginInstanceProxy::disconnectStream(HostedNetscapePluginStream* stream) +{ + m_streams.remove(stream->streamID()); +} + +void NetscapePluginInstanceProxy::pluginHostDied() +{ + m_pluginHostProxy = 0; + + [m_pluginView pluginHostDied]; + + cleanup(); +} + +void NetscapePluginInstanceProxy::focusChanged(bool hasFocus) +{ + _WKPHPluginInstanceFocusChanged(m_pluginHostProxy->port(), m_pluginID, hasFocus); +} + +void NetscapePluginInstanceProxy::windowFocusChanged(bool hasFocus) +{ + _WKPHPluginInstanceWindowFocusChanged(m_pluginHostProxy->port(), m_pluginID, hasFocus); +} + +void NetscapePluginInstanceProxy::windowFrameChanged(NSRect frame) +{ + _WKPHPluginInstanceWindowFrameChanged(m_pluginHostProxy->port(), m_pluginID, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height, + // FIXME: Is it always correct to pass the rect of the first screen here? + NSMaxY([[[NSScreen screens] objectAtIndex:0] frame])); +} + +void NetscapePluginInstanceProxy::startTimers(bool throttleTimers) +{ + _WKPHPluginInstanceStartTimers(m_pluginHostProxy->port(), m_pluginID, throttleTimers); +} + +void NetscapePluginInstanceProxy::mouseEvent(NSView *pluginView, NSEvent *event, NPCocoaEventType type) +{ + NSPoint screenPoint = [[event window] convertBaseToScreen:[event locationInWindow]]; + NSPoint pluginPoint = [pluginView convertPoint:[event locationInWindow] fromView:nil]; + + int clickCount; + if (type == NPCocoaEventMouseEntered || type == NPCocoaEventMouseExited) + clickCount = 0; + else + clickCount = [event clickCount]; + + + _WKPHPluginInstanceMouseEvent(m_pluginHostProxy->port(), m_pluginID, + [event timestamp], + type, [event modifierFlags], + pluginPoint.x, pluginPoint.y, + screenPoint.x, screenPoint.y, + // FIXME: Is it always correct to pass the rect of the first screen here? + NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]), + [event buttonNumber], clickCount, + [event deltaX], [event deltaY], [event deltaZ]); +} + +void NetscapePluginInstanceProxy::keyEvent(NSView *pluginView, NSEvent *event, NPCocoaEventType type) +{ + NSData *charactersData = [[event characters] dataUsingEncoding:NSUTF8StringEncoding]; + NSData *charactersIgnoringModifiersData = [[event charactersIgnoringModifiers] dataUsingEncoding:NSUTF8StringEncoding]; + + _WKPHPluginInstanceKeyboardEvent(m_pluginHostProxy->port(), m_pluginID, + [event timestamp], + type, [event modifierFlags], + const_cast<char*>(reinterpret_cast<const char*>([charactersData bytes])), [charactersData length], + const_cast<char*>(reinterpret_cast<const char*>([charactersIgnoringModifiersData bytes])), [charactersIgnoringModifiersData length], + [event isARepeat], [event keyCode]); +} + +void NetscapePluginInstanceProxy::insertText(NSString *text) +{ + NSData *textData = [text dataUsingEncoding:NSUTF8StringEncoding]; + + _WKPHPluginInstanceInsertText(m_pluginHostProxy->port(), m_pluginID, + const_cast<char*>(reinterpret_cast<const char*>([textData bytes])), [textData length]); +} + +void NetscapePluginInstanceProxy::print(CGContextRef context, unsigned width, unsigned height) +{ + uint32_t requestID = nextRequestID(); + _WKPHPluginInstancePrint(m_pluginHostProxy->port(), m_pluginID, requestID, width, height); + + auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID); + if (!reply.get() || !reply->m_returnValue) + return; + + RetainPtr<CGDataProvider> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(reply->m_result.get())); + RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); + RetainPtr<CGImageRef> image(AdoptCF, CGImageCreate(width, height, 8, 32, width * 4, colorSpace.get(), kCGImageAlphaFirst, dataProvider.get(), 0, false, kCGRenderingIntentDefault)); + + // Flip the context and draw the image. + CGContextSaveGState(context); + CGContextTranslateCTM(context, 0.0, height); + CGContextScaleCTM(context, 1.0, -1.0); + + CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.get()); + + CGContextRestoreGState(context); +} + +void NetscapePluginInstanceProxy::stopTimers() +{ + _WKPHPluginInstanceStopTimers(m_pluginHostProxy->port(), m_pluginID); +} + +void NetscapePluginInstanceProxy::status(const char* message) +{ + RetainPtr<CFStringRef> status(AdoptCF, CFStringCreateWithCString(NULL, message, kCFStringEncodingUTF8)); + + if (!status) + return; + + WebView *wv = [m_pluginView webView]; + [[wv _UIDelegateForwarder] webView:wv setStatusText:(NSString *)status.get()]; +} + +NPError NetscapePluginInstanceProxy::loadURL(const char* url, const char* target, const char* postData, uint32_t postLen, LoadURLFlags flags, uint32_t& streamID) +{ + if (!url) + return NPERR_INVALID_PARAM; + + NSMutableURLRequest *request = [m_pluginView requestWithURLCString:url]; + + if (flags & IsPost) { + NSData *httpBody = nil; + + if (flags & PostDataIsFile) { + // If we're posting a file, buf is either a file URL or a path to the file. + RetainPtr<CFStringRef> bufString(AdoptCF, CFStringCreateWithCString(kCFAllocatorDefault, postData, kCFStringEncodingWindowsLatin1)); + if (!bufString) + return NPERR_INVALID_PARAM; + + NSURL *fileURL = [NSURL _web_URLWithDataAsString:(NSString *)bufString.get()]; + NSString *path; + if ([fileURL isFileURL]) + path = [fileURL path]; + else + path = (NSString *)bufString.get(); + httpBody = [NSData dataWithContentsOfFile:[path _webkit_fixedCarbonPOSIXPath]]; + if (!httpBody) + return NPERR_FILE_NOT_FOUND; + } else + httpBody = [NSData dataWithBytes:postData length:postLen]; + + if (![httpBody length]) + return NPERR_INVALID_PARAM; + + [request setHTTPMethod:@"POST"]; + + if (flags & AllowHeadersInPostData) { + if ([httpBody _web_startsWithBlankLine]) + httpBody = [httpBody subdataWithRange:NSMakeRange(1, [httpBody length] - 1)]; + else { + NSInteger location = [httpBody _web_locationAfterFirstBlankLine]; + if (location != NSNotFound) { + // If the blank line is somewhere in the middle of postData, everything before is the header. + NSData *headerData = [httpBody subdataWithRange:NSMakeRange(0, location)]; + NSMutableDictionary *header = [headerData _webkit_parseRFC822HeaderFields]; + unsigned dataLength = [httpBody length] - location; + + // Sometimes plugins like to set Content-Length themselves when they post, + // but CFNetwork does not like that. So we will remove the header + // and instead truncate the data to the requested length. + NSString *contentLength = [header objectForKey:@"Content-Length"]; + + if (contentLength) + dataLength = min(static_cast<unsigned>([contentLength intValue]), dataLength); + [header removeObjectForKey:@"Content-Length"]; + + if ([header count] > 0) + [request setAllHTTPHeaderFields:header]; + + // Everything after the blank line is the actual content of the POST. + httpBody = [httpBody subdataWithRange:NSMakeRange(location, dataLength)]; + } + } + } + + if (![httpBody length]) + return NPERR_INVALID_PARAM; + + // Plug-ins expect to receive uncached data when doing a POST (3347134). + [request setCachePolicy:NSURLRequestReloadIgnoringCacheData]; + [request setHTTPBody:httpBody]; + } + + return loadRequest(request, target, flags & CurrentEventIsUserGesture, streamID); +} + +void NetscapePluginInstanceProxy::performRequest(PluginRequest* pluginRequest) +{ + ASSERT(m_pluginView); + + NSURLRequest *request = pluginRequest->request(); + NSString *frameName = pluginRequest->frameName(); + WebFrame *frame = nil; + + NSURL *URL = [request URL]; + NSString *JSString = [URL _webkit_scriptIfJavaScriptURL]; + + ASSERT(frameName || JSString); + if (frameName) { + // FIXME - need to get rid of this window creation which + // bypasses normal targeted link handling + frame = kit(core([m_pluginView webFrame])->loader()->findFrameForNavigation(frameName)); + if (!frame) { + WebView *currentWebView = [m_pluginView webView]; + NSDictionary *features = [[NSDictionary alloc] init]; + WebView *newWebView = [[currentWebView _UIDelegateForwarder] webView:currentWebView + createWebViewWithRequest:nil + windowFeatures:features]; + [features release]; + + if (!newWebView) { + _WKPHLoadURLNotify(m_pluginHostProxy->port(), m_pluginID, pluginRequest->requestID(), NPERR_GENERIC_ERROR); + return; + } + + frame = [newWebView mainFrame]; + core(frame)->tree()->setName(frameName); + [[newWebView _UIDelegateForwarder] webViewShow:newWebView]; + } + } + + if (JSString) { + ASSERT(!frame || [m_pluginView webFrame] == frame); + evaluateJavaScript(pluginRequest); + } else + [frame loadRequest:request]; +} + +void NetscapePluginInstanceProxy::evaluateJavaScript(PluginRequest* pluginRequest) +{ + NSURL *URL = [pluginRequest->request() URL]; + NSString *JSString = [URL _webkit_scriptIfJavaScriptURL]; + ASSERT(JSString); + + NSString *result = [[m_pluginView webFrame] _stringByEvaluatingJavaScriptFromString:JSString forceUserGesture:pluginRequest->didStartFromUserGesture()]; + + // Don't continue if stringByEvaluatingJavaScriptFromString caused the plug-in to stop. + if (!m_pluginHostProxy) + return; + + if (pluginRequest->frameName() != nil) + return; + + if ([result length] > 0) { + // Don't call NPP_NewStream and other stream methods if there is no JS result to deliver. This is what Mozilla does. + NSData *JSData = [result dataUsingEncoding:NSUTF8StringEncoding]; + + RefPtr<HostedNetscapePluginStream> stream = HostedNetscapePluginStream::create(this, pluginRequest->requestID(), pluginRequest->request()); + + RetainPtr<NSURLResponse> response(AdoptNS, [[NSURLResponse alloc] initWithURL:URL + MIMEType:@"text/plain" + expectedContentLength:[JSData length] + textEncodingName:nil]); + stream->startStreamWithResponse(response.get()); + stream->didReceiveData(0, static_cast<const char*>([JSData bytes]), [JSData length]); + stream->didFinishLoading(0); + } +} + +void NetscapePluginInstanceProxy::requestTimerFired(Timer<NetscapePluginInstanceProxy>*) +{ + ASSERT(!m_pluginRequests.isEmpty()); + ASSERT(m_pluginView); + + PluginRequest* request = m_pluginRequests.first(); + m_pluginRequests.removeFirst(); + + if (!m_pluginRequests.isEmpty()) + m_requestTimer.startOneShot(0); + + performRequest(request); + delete request; +} + +NPError NetscapePluginInstanceProxy::loadRequest(NSURLRequest *request, const char* cTarget, bool currentEventIsUserGesture, uint32_t& requestID) +{ + NSURL *URL = [request URL]; + + if (!URL) + return NPERR_INVALID_URL; + + // Don't allow requests to be loaded when the document loader is stopping all loaders. + if ([[m_pluginView dataSource] _documentLoader]->isStopping()) + return NPERR_GENERIC_ERROR; + + NSString *target = nil; + if (cTarget) { + // Find the frame given the target string. + target = [NSString stringWithCString:cTarget encoding:NSISOLatin1StringEncoding]; + } + WebFrame *frame = [m_pluginView webFrame]; + + // don't let a plugin start any loads if it is no longer part of a document that is being + // displayed unless the loads are in the same frame as the plugin. + if ([[m_pluginView dataSource] _documentLoader] != core([m_pluginView webFrame])->loader()->activeDocumentLoader() && + (!cTarget || [frame findFrameNamed:target] != frame)) { + return NPERR_GENERIC_ERROR; + } + + NSString *JSString = [URL _webkit_scriptIfJavaScriptURL]; + if (JSString != nil) { + if (![[[m_pluginView webView] preferences] isJavaScriptEnabled]) { + // Return NPERR_GENERIC_ERROR if JS is disabled. This is what Mozilla does. + return NPERR_GENERIC_ERROR; + } + } else { + if (!FrameLoader::canLoad(URL, String(), core([m_pluginView webFrame])->document())) + return NPERR_GENERIC_ERROR; + } + + // FIXME: Handle wraparound + requestID = ++m_currentURLRequestID; + + if (cTarget || JSString) { + // Make when targetting a frame or evaluating a JS string, perform the request after a delay because we don't + // want to potentially kill the plug-in inside of its URL request. + + if (JSString && target && [frame findFrameNamed:target] != frame) { + // For security reasons, only allow JS requests to be made on the frame that contains the plug-in. + return NPERR_INVALID_PARAM; + } + + PluginRequest* pluginRequest = new PluginRequest(requestID, request, target, currentEventIsUserGesture); + m_pluginRequests.append(pluginRequest); + m_requestTimer.startOneShot(0); + } else { + RefPtr<HostedNetscapePluginStream> stream = HostedNetscapePluginStream::create(this, requestID, request); + + m_streams.add(requestID, stream); + stream->start(); + } + + return NPERR_NO_ERROR; +} + +NetscapePluginInstanceProxy::Reply* NetscapePluginInstanceProxy::processRequestsAndWaitForReply(uint32_t requestID) +{ + Reply* reply = 0; + + while (!(reply = m_replies.take(requestID))) { + if (!m_pluginHostProxy->processRequests()) + return 0; + } + + ASSERT(reply); + return reply; +} + +uint32_t NetscapePluginInstanceProxy::idForObject(JSObject* object) +{ + uint32_t objectID = 0; + + // Assign an object ID. + do { + objectID = ++m_objectIDCounter; + } while (!m_objectIDCounter || m_objectIDCounter == static_cast<uint32_t>(-1) || m_objects.contains(objectID)); + + m_objects.set(objectID, object); + + return objectID; +} + +// NPRuntime support +bool NetscapePluginInstanceProxy::getWindowNPObject(uint32_t& objectID) +{ + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + if (!frame->script()->isEnabled()) + objectID = 0; + else + objectID = idForObject(frame->script()->windowShell()->window()); + + return true; +} + +bool NetscapePluginInstanceProxy::getPluginElementNPObject(uint32_t& objectID) +{ + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + if (JSObject* object = frame->script()->jsObjectForPluginElement([m_pluginView element])) + objectID = idForObject(object); + else + objectID = 0; + + return true; +} + +void NetscapePluginInstanceProxy::releaseObject(uint32_t objectID) +{ + m_objects.remove(objectID); +} + +bool NetscapePluginInstanceProxy::evaluate(uint32_t objectID, const String& script, data_t& resultData, mach_msg_type_number_t& resultLength) +{ + resultData = 0; + resultLength = 0; + + if (!m_objects.contains(objectID)) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + JSLock lock(false); + + ProtectedPtr<JSGlobalObject> globalObject = frame->script()->globalObject(); + ExecState* exec = globalObject->globalExec(); + + globalObject->globalData()->timeoutChecker.start(); + Completion completion = JSC::evaluate(exec, globalObject->globalScopeChain(), makeSource(script)); + globalObject->globalData()->timeoutChecker.stop(); + ComplType type = completion.complType(); + + JSValuePtr result; + if (type == Normal) + result = completion.value(); + + if (!result) + result = jsUndefined(); + + marshalValue(exec, result, resultData, resultLength); + exec->clearException(); + return true; +} + +bool NetscapePluginInstanceProxy::invoke(uint32_t objectID, const Identifier& methodName, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength) +{ + resultData = 0; + resultLength = 0; + + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + JSValuePtr function = object->get(exec, methodName); + CallData callData; + CallType callType = function.getCallData(callData); + if (callType == CallTypeNone) + return false; + + ArgList argList; + demarshalValues(exec, argumentsData, argumentsLength, argList); + + ProtectedPtr<JSGlobalObject> globalObject = frame->script()->globalObject(); + globalObject->globalData()->timeoutChecker.start(); + JSValuePtr value = call(exec, function, callType, callData, object, argList); + globalObject->globalData()->timeoutChecker.stop(); + + marshalValue(exec, value, resultData, resultLength); + exec->clearException(); + return true; +} + +bool NetscapePluginInstanceProxy::invokeDefault(uint32_t objectID, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + CallData callData; + CallType callType = object->getCallData(callData); + if (callType == CallTypeNone) + return false; + + ArgList argList; + demarshalValues(exec, argumentsData, argumentsLength, argList); + + ProtectedPtr<JSGlobalObject> globalObject = frame->script()->globalObject(); + globalObject->globalData()->timeoutChecker.start(); + JSValuePtr value = call(exec, object, callType, callData, object, argList); + globalObject->globalData()->timeoutChecker.stop(); + + marshalValue(exec, value, resultData, resultLength); + exec->clearException(); + return true; +} + +bool NetscapePluginInstanceProxy::construct(uint32_t objectID, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + + ConstructData constructData; + ConstructType constructType = object->getConstructData(constructData); + if (constructType == ConstructTypeNone) + return false; + + ArgList argList; + demarshalValues(exec, argumentsData, argumentsLength, argList); + + ProtectedPtr<JSGlobalObject> globalObject = frame->script()->globalObject(); + globalObject->globalData()->timeoutChecker.start(); + JSValuePtr value = JSC::construct(exec, object, constructType, constructData, argList); + globalObject->globalData()->timeoutChecker.stop(); + + marshalValue(exec, value, resultData, resultLength); + exec->clearException(); + return true; +} + +bool NetscapePluginInstanceProxy::getProperty(uint32_t objectID, const Identifier& propertyName, data_t& resultData, mach_msg_type_number_t& resultLength) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + JSValuePtr value = object->get(exec, propertyName); + + marshalValue(exec, value, resultData, resultLength); + exec->clearException(); + return true; +} + +bool NetscapePluginInstanceProxy::getProperty(uint32_t objectID, unsigned propertyName, data_t& resultData, mach_msg_type_number_t& resultLength) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + JSValuePtr value = object->get(exec, propertyName); + + marshalValue(exec, value, resultData, resultLength); + exec->clearException(); + return true; +} + +bool NetscapePluginInstanceProxy::setProperty(uint32_t objectID, const Identifier& propertyName, data_t valueData, mach_msg_type_number_t valueLength) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + + JSValuePtr value = demarshalValue(exec, valueData, valueLength); + PutPropertySlot slot; + object->put(exec, propertyName, value, slot); + + exec->clearException(); + return true; +} + +bool NetscapePluginInstanceProxy::setProperty(uint32_t objectID, unsigned propertyName, data_t valueData, mach_msg_type_number_t valueLength) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + + JSValuePtr value = demarshalValue(exec, valueData, valueLength); + object->put(exec, propertyName, value); + + exec->clearException(); + return true; +} + +bool NetscapePluginInstanceProxy::removeProperty(uint32_t objectID, const Identifier& propertyName) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + if (!object->hasProperty(exec, propertyName)) { + exec->clearException(); + return false; + } + + JSLock lock(false); + object->deleteProperty(exec, propertyName); + exec->clearException(); + return true; +} + +bool NetscapePluginInstanceProxy::removeProperty(uint32_t objectID, unsigned propertyName) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + if (!object->hasProperty(exec, propertyName)) { + exec->clearException(); + return false; + } + + JSLock lock(false); + object->deleteProperty(exec, propertyName); + exec->clearException(); + return true; +} + +bool NetscapePluginInstanceProxy::hasProperty(uint32_t objectID, const Identifier& propertyName) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + bool result = object->hasProperty(exec, propertyName); + exec->clearException(); + + return result; +} + +bool NetscapePluginInstanceProxy::hasProperty(uint32_t objectID, unsigned propertyName) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + bool result = object->hasProperty(exec, propertyName); + exec->clearException(); + + return result; +} + +bool NetscapePluginInstanceProxy::hasMethod(uint32_t objectID, const Identifier& methodName) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + JSValuePtr func = object->get(exec, methodName); + exec->clearException(); + return !func.isUndefined(); +} + +bool NetscapePluginInstanceProxy::enumerate(uint32_t objectID, data_t& resultData, mach_msg_type_number_t& resultLength) +{ + JSObject* object = m_objects.get(objectID); + if (!object) + return false; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + ExecState* exec = frame->script()->globalObject()->globalExec(); + JSLock lock(false); + + PropertyNameArray propertyNames(exec); + object->getPropertyNames(exec, propertyNames); + + NSMutableArray *array = [[NSMutableArray alloc] init]; + for (unsigned i = 0; i < propertyNames.size(); i++) { + uint64_t methodName = reinterpret_cast<uint64_t>(_NPN_GetStringIdentifier(propertyNames[i].ustring().UTF8String().c_str())); + + [array addObject:[NSNumber numberWithLongLong:methodName]]; + } + + NSData *data = [NSPropertyListSerialization dataFromPropertyList:array format:NSPropertyListBinaryFormat_v1_0 errorDescription:0]; + ASSERT(data); + + resultLength = [data length]; + mig_allocate(reinterpret_cast<vm_address_t*>(&resultData), resultLength); + + memcpy(resultData, [data bytes], resultLength); + + exec->clearException(); + + return true; +} + +void NetscapePluginInstanceProxy::addValueToArray(NSMutableArray *array, ExecState* exec, JSValuePtr value) +{ + JSLock lock(false); + + if (value.isString()) { + [array addObject:[NSNumber numberWithInt:StringValueType]]; + [array addObject:String(value.toString(exec))]; + } else if (value.isNumber()) { + [array addObject:[NSNumber numberWithInt:DoubleValueType]]; + [array addObject:[NSNumber numberWithDouble:value.toNumber(exec)]]; + } else if (value.isBoolean()) { + [array addObject:[NSNumber numberWithInt:BoolValueType]]; + [array addObject:[NSNumber numberWithBool:value.toBoolean(exec)]]; + } else if (value.isNull()) + [array addObject:[NSNumber numberWithInt:NullValueType]]; + else if (value.isObject()) { + JSObject* object = asObject(value); + if (object->classInfo() == &RuntimeObjectImp::s_info) { + RuntimeObjectImp* imp = static_cast<RuntimeObjectImp*>(object); + if (ProxyInstance* instance = static_cast<ProxyInstance*>(imp->getInternalInstance())) { + [array addObject:[NSNumber numberWithInt:NPObjectValueType]]; + [array addObject:[NSNumber numberWithInt:instance->objectID()]]; + } + } else { + [array addObject:[NSNumber numberWithInt:JSObjectValueType]]; + [array addObject:[NSNumber numberWithInt:idForObject(object)]]; + } + } else + [array addObject:[NSNumber numberWithInt:VoidValueType]]; +} + +void NetscapePluginInstanceProxy::marshalValue(ExecState* exec, JSValuePtr value, data_t& resultData, mach_msg_type_number_t& resultLength) +{ + RetainPtr<NSMutableArray*> array(AdoptNS, [[NSMutableArray alloc] init]); + + addValueToArray(array.get(), exec, value); + + RetainPtr<NSData *> data = [NSPropertyListSerialization dataFromPropertyList:array.get() format:NSPropertyListBinaryFormat_v1_0 errorDescription:0]; + ASSERT(data); + + resultLength = [data.get() length]; + mig_allocate(reinterpret_cast<vm_address_t*>(&resultData), resultLength); + + memcpy(resultData, [data.get() bytes], resultLength); +} + +RetainPtr<NSData *> NetscapePluginInstanceProxy::marshalValues(ExecState* exec, const ArgList& args) +{ + RetainPtr<NSMutableArray*> array(AdoptNS, [[NSMutableArray alloc] init]); + + for (unsigned i = 0; i < args.size(); i++) + addValueToArray(array.get(), exec, args.at(exec, i)); + + RetainPtr<NSData *> data = [NSPropertyListSerialization dataFromPropertyList:array.get() format:NSPropertyListBinaryFormat_v1_0 errorDescription:0]; + ASSERT(data); + + return data; +} + +bool NetscapePluginInstanceProxy::demarshalValueFromArray(ExecState* exec, NSArray *array, NSUInteger& index, JSValuePtr& result) +{ + if (index == [array count]) + return false; + + int type = [[array objectAtIndex:index++] intValue]; + switch (type) { + case VoidValueType: + result = jsUndefined(); + return true; + case NullValueType: + result = jsNull(); + return true; + case BoolValueType: + result = jsBoolean([[array objectAtIndex:index++] boolValue]); + return true; + case DoubleValueType: + result = jsNumber(exec, [[array objectAtIndex:index++] doubleValue]); + return true; + case StringValueType: { + NSString *string = [array objectAtIndex:index++]; + + result = jsString(exec, String(string)); + return true; + } + case JSObjectValueType: { + uint32_t objectID = [[array objectAtIndex:index++] intValue]; + + result = m_objects.get(objectID); + ASSERT(result); + return true; + } + case NPObjectValueType: { + uint32_t objectID = [[array objectAtIndex:index++] intValue]; + + Frame* frame = core([m_pluginView webFrame]); + if (!frame) + return false; + + if (!frame->script()->isEnabled()) + return false; + + RefPtr<RootObject> rootObject = frame->script()->createRootObject(m_pluginView); + if (!rootObject) + return false; + + result = ProxyInstance::create(rootObject.release(), this, objectID)->createRuntimeObject(exec); + return true; + } + default: + ASSERT_NOT_REACHED(); + return false; + } +} + +JSValuePtr NetscapePluginInstanceProxy::demarshalValue(ExecState* exec, const char* valueData, mach_msg_type_number_t valueLength) +{ + RetainPtr<NSData*> data(AdoptNS, [[NSData alloc] initWithBytesNoCopy:(void*)valueData length:valueLength freeWhenDone:NO]); + + RetainPtr<NSArray*> array = [NSPropertyListSerialization propertyListFromData:data.get() + mutabilityOption:NSPropertyListImmutable + format:0 + errorDescription:0]; + NSUInteger position = 0; + JSValuePtr value; + bool result = demarshalValueFromArray(exec, array.get(), position, value); + ASSERT_UNUSED(result, result); + + return value; +} + +void NetscapePluginInstanceProxy::demarshalValues(ExecState* exec, data_t valuesData, mach_msg_type_number_t valuesLength, ArgList& result) +{ + RetainPtr<NSData*> data(AdoptNS, [[NSData alloc] initWithBytesNoCopy:valuesData length:valuesLength freeWhenDone:NO]); + + RetainPtr<NSArray*> array = [NSPropertyListSerialization propertyListFromData:data.get() + mutabilityOption:NSPropertyListImmutable + format:0 + errorDescription:0]; + NSUInteger position = 0; + JSValuePtr value; + while (demarshalValueFromArray(exec, array.get(), position, value)) + result.append(value); +} + +PassRefPtr<Instance> NetscapePluginInstanceProxy::createBindingsInstance(PassRefPtr<RootObject> rootObject) +{ + uint32_t requestID = nextRequestID(); + + if (_WKPHGetScriptableNPObject(m_pluginHostProxy->port(), m_pluginID, requestID) != KERN_SUCCESS) + return 0; + + auto_ptr<GetScriptableNPObjectReply> reply = waitForReply<GetScriptableNPObjectReply>(requestID); + if (!reply.get()) + return 0; + + if (!reply->m_objectID) + return 0; + + return ProxyInstance::create(rootObject, this, reply->m_objectID); +} + +void NetscapePluginInstanceProxy::addInstance(ProxyInstance* instance) +{ + ASSERT(!m_instances.contains(instance)); + + m_instances.add(instance); +} + +void NetscapePluginInstanceProxy::removeInstance(ProxyInstance* instance) +{ + ASSERT(m_instances.contains(instance)); + + m_instances.remove(instance); +} + +void NetscapePluginInstanceProxy::willCallPluginFunction() +{ + m_pluginFunctionCallDepth++; +} + +void NetscapePluginInstanceProxy::didCallPluginFunction() +{ + ASSERT(m_pluginFunctionCallDepth > 0); + m_pluginFunctionCallDepth--; + + // If -stop was called while we were calling into a plug-in function, and we're no longer + // inside a plug-in function, stop now. + if (!m_pluginFunctionCallDepth && m_shouldStopSoon) { + m_shouldStopSoon = false; + [m_pluginView stop]; + } +} + +bool NetscapePluginInstanceProxy::shouldStop() +{ + if (m_pluginFunctionCallDepth) { + m_shouldStopSoon = true; + return false; + } + + return true; +} + +uint32_t NetscapePluginInstanceProxy::nextRequestID() +{ + uint32_t requestID = ++m_currentRequestID; + + // We don't want to return the HashMap empty/deleted "special keys" + if (requestID == 0 || requestID == static_cast<uint32_t>(-1)) + return nextRequestID(); + + return requestID; +} + +void NetscapePluginInstanceProxy::invalidateRect(double x, double y, double width, double height) +{ + ASSERT(m_pluginView); + + [m_pluginView setNeedsDisplayInRect:NSMakeRect(x, y, width, height)]; +} + + +} // namespace WebKit + +#endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/ProxyInstance.h b/WebKit/mac/Plugins/Hosted/ProxyInstance.h new file mode 100644 index 0000000..1e2e2dc --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/ProxyInstance.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2009 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if USE(PLUGIN_HOST_PROCESS) + +#ifndef ProxyInstance_h +#define ProxyInstance_h + +#include <WebCore/runtime.h> +#include <WebCore/runtime_root.h> +#include <wtf/OwnPtr.h> +#include "WebKitPluginHostTypes.h" + +namespace WebKit { + +class ProxyClass; +class NetscapePluginInstanceProxy; + +class ProxyInstance : public JSC::Bindings::Instance { +public: + static PassRefPtr<ProxyInstance> create(PassRefPtr<JSC::Bindings::RootObject> rootObject, NetscapePluginInstanceProxy* instanceProxy, uint32_t objectID) + { + return adoptRef(new ProxyInstance(rootObject, instanceProxy, objectID)); + } + ~ProxyInstance(); + + JSC::Bindings::MethodList methodsNamed(const JSC::Identifier&); + JSC::Bindings::Field* fieldNamed(const JSC::Identifier&); + + JSC::JSValuePtr fieldValue(JSC::ExecState*, const JSC::Bindings::Field*) const; + void setFieldValue(JSC::ExecState*, const JSC::Bindings::Field*, JSC::JSValuePtr) const; + + void invalidate(); + + uint32_t objectID() const { return m_objectID; } + +private: + ProxyInstance(PassRefPtr<JSC::Bindings::RootObject>, NetscapePluginInstanceProxy*, uint32_t objectID); + + virtual JSC::Bindings::Class *getClass() const; + + virtual JSC::JSValuePtr invokeMethod(JSC::ExecState*, const JSC::Bindings::MethodList&, const JSC::ArgList& args); + + virtual bool supportsInvokeDefaultMethod() const; + virtual JSC::JSValuePtr invokeDefaultMethod(JSC::ExecState*, const JSC::ArgList&); + + virtual bool supportsConstruct() const; + virtual JSC::JSValuePtr invokeConstruct(JSC::ExecState*, const JSC::ArgList&); + + virtual JSC::JSValuePtr defaultValue(JSC::ExecState*, JSC::PreferredPrimitiveType) const; + virtual JSC::JSValuePtr valueOf(JSC::ExecState*) const; + + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + + JSC::JSValuePtr stringValue(JSC::ExecState*) const; + JSC::JSValuePtr numberValue(JSC::ExecState*) const; + JSC::JSValuePtr booleanValue() const; + + JSC::JSValuePtr invoke(JSC::ExecState*, InvokeType, uint64_t identifier, const JSC::ArgList& args); + + NetscapePluginInstanceProxy* m_instanceProxy; + uint32_t m_objectID; + JSC::Bindings::FieldMap m_fields; + JSC::Bindings::MethodMap m_methods; +}; + +} + +#endif // ProxyInstance_h +#endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/ProxyInstance.mm b/WebKit/mac/Plugins/Hosted/ProxyInstance.mm new file mode 100644 index 0000000..01e64ba --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/ProxyInstance.mm @@ -0,0 +1,369 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if USE(PLUGIN_HOST_PROCESS) + +#import "ProxyInstance.h" + +#import "NetscapePluginHostProxy.h" +#import "NetscapePluginInstanceProxy.h" +#import <runtime/PropertyNameArray.h> +#import <WebCore/IdentifierRep.h> +#import <WebCore/JSDOMWindow.h> +#import <WebCore/npruntime_impl.h> + +extern "C" { +#import "WebKitPluginHost.h" +} + +using namespace JSC; +using namespace JSC::Bindings; +using namespace std; +using namespace WebCore; + +namespace WebKit { + +class ProxyClass : public JSC::Bindings::Class { +private: + virtual MethodList methodsNamed(const Identifier&, Instance*) const; + virtual Field* fieldNamed(const Identifier&, Instance*) const; +}; + +MethodList ProxyClass::methodsNamed(const Identifier& identifier, Instance* instance) const +{ + return static_cast<ProxyInstance*>(instance)->methodsNamed(identifier); +} + +Field* ProxyClass::fieldNamed(const Identifier& identifier, Instance* instance) const +{ + return static_cast<ProxyInstance*>(instance)->fieldNamed(identifier); +} + +static ProxyClass* proxyClass() +{ + DEFINE_STATIC_LOCAL(ProxyClass, proxyClass, ()); + return &proxyClass; +} + +class ProxyField : public JSC::Bindings::Field { +public: + ProxyField(uint64_t serverIdentifier) + : m_serverIdentifier(serverIdentifier) + { + } + + uint64_t serverIdentifier() const { return m_serverIdentifier; } + +private: + virtual JSValuePtr valueFromInstance(ExecState*, const Instance*) const; + virtual void setValueToInstance(ExecState*, const Instance*, JSValuePtr) const; + + uint64_t m_serverIdentifier; +}; + +JSValuePtr ProxyField::valueFromInstance(ExecState* exec, const Instance* instance) const +{ + return static_cast<const ProxyInstance*>(instance)->fieldValue(exec, this); +} + +void ProxyField::setValueToInstance(ExecState* exec, const Instance* instance, JSValuePtr value) const +{ + static_cast<const ProxyInstance*>(instance)->setFieldValue(exec, this, value); +} + +class ProxyMethod : public JSC::Bindings::Method { +public: + ProxyMethod(uint64_t serverIdentifier) + : m_serverIdentifier(serverIdentifier) + { + } + + uint64_t serverIdentifier() const { return m_serverIdentifier; } + +private: + virtual int numParameters() const { return 0; } + + uint64_t m_serverIdentifier; +}; + +ProxyInstance::ProxyInstance(PassRefPtr<RootObject> rootObject, NetscapePluginInstanceProxy* instanceProxy, uint32_t objectID) + : Instance(rootObject) + , m_instanceProxy(instanceProxy) + , m_objectID(objectID) +{ + m_instanceProxy->addInstance(this); +} + +ProxyInstance::~ProxyInstance() +{ + deleteAllValues(m_fields); + deleteAllValues(m_methods); + + if (!m_instanceProxy) + return; + + m_instanceProxy->removeInstance(this); + + invalidate(); +} + +JSC::Bindings::Class *ProxyInstance::getClass() const +{ + return proxyClass(); +} + +JSValuePtr ProxyInstance::invoke(JSC::ExecState* exec, InvokeType type, uint64_t identifier, const JSC::ArgList& args) +{ + RetainPtr<NSData*> arguments(m_instanceProxy->marshalValues(exec, args)); + + uint32_t requestID = m_instanceProxy->nextRequestID(); + + if (_WKPHNPObjectInvoke(m_instanceProxy->hostProxy()->port(), m_instanceProxy->pluginID(), requestID, m_objectID, + type, identifier, (char*)[arguments.get() bytes], [arguments.get() length]) != KERN_SUCCESS) + return jsUndefined(); + + auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = m_instanceProxy->waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID); + if (!reply.get() || !reply->m_returnValue) + return jsUndefined(); + + return m_instanceProxy->demarshalValue(exec, (char*)CFDataGetBytePtr(reply->m_result.get()), CFDataGetLength(reply->m_result.get())); +} + +JSValuePtr ProxyInstance::invokeMethod(ExecState* exec, const MethodList& methodList, const ArgList& args) +{ + ASSERT(methodList.size() == 1); + + ProxyMethod* method = static_cast<ProxyMethod*>(methodList[0]); + + return invoke(exec, Invoke, method->serverIdentifier(), args); +} + +bool ProxyInstance::supportsInvokeDefaultMethod() const +{ + uint32_t requestID = m_instanceProxy->nextRequestID(); + + if (_WKPHNPObjectHasInvokeDefaultMethod(m_instanceProxy->hostProxy()->port(), + m_instanceProxy->pluginID(), requestID, + m_objectID) != KERN_SUCCESS) + return false; + + auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = m_instanceProxy->waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID); + if (reply.get() && reply->m_result) + return true; + + return false; +} + +JSValuePtr ProxyInstance::invokeDefaultMethod(ExecState* exec, const ArgList& args) +{ + return invoke(exec, InvokeDefault, 0, args); +} + +bool ProxyInstance::supportsConstruct() const +{ + uint32_t requestID = m_instanceProxy->nextRequestID(); + + if (_WKPHNPObjectHasConstructMethod(m_instanceProxy->hostProxy()->port(), + m_instanceProxy->pluginID(), requestID, + m_objectID) != KERN_SUCCESS) + return false; + + auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = m_instanceProxy->waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID); + if (reply.get() && reply->m_result) + return true; + + return false; +} + +JSValuePtr ProxyInstance::invokeConstruct(ExecState* exec, const ArgList& args) +{ + return invoke(exec, Construct, 0, args); +} + +JSValuePtr ProxyInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const +{ + if (hint == PreferString) + return stringValue(exec); + if (hint == PreferNumber) + return numberValue(exec); + return valueOf(exec); +} + +JSValuePtr ProxyInstance::stringValue(ExecState* exec) const +{ + // FIXME: Implement something sensible. + return jsString(exec, ""); +} + +JSValuePtr ProxyInstance::numberValue(ExecState* exec) const +{ + // FIXME: Implement something sensible. + return jsNumber(exec, 0); +} + +JSValuePtr ProxyInstance::booleanValue() const +{ + // FIXME: Implement something sensible. + return jsBoolean(false); +} + +JSValuePtr ProxyInstance::valueOf(ExecState* exec) const +{ + return stringValue(exec); +} + +void ProxyInstance::getPropertyNames(ExecState* exec, PropertyNameArray& nameArray) +{ + uint32_t requestID = m_instanceProxy->nextRequestID(); + + if (_WKPHNPObjectEnumerate(m_instanceProxy->hostProxy()->port(), m_instanceProxy->pluginID(), requestID, m_objectID) != KERN_SUCCESS) + return; + + auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = m_instanceProxy->waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID); + + if (!reply.get() || !reply->m_returnValue) + return; + + RetainPtr<NSArray*> array = [NSPropertyListSerialization propertyListFromData:(NSData *)reply->m_result.get() + mutabilityOption:NSPropertyListImmutable + format:0 + errorDescription:0]; + + for (NSNumber *number in array.get()) { + IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>([number longLongValue]); + if (!IdentifierRep::isValid(identifier)) + continue; + + if (identifier->isString()) { + const char* str = identifier->string(); + nameArray.add(Identifier(JSDOMWindow::commonJSGlobalData(), String::fromUTF8WithLatin1Fallback(str, strlen(str)))); + } else + nameArray.add(Identifier::from(exec, identifier->number())); + } +} + +MethodList ProxyInstance::methodsNamed(const Identifier& identifier) +{ + if (Method* method = m_methods.get(identifier.ustring().rep())) { + MethodList methodList; + methodList.append(method); + return methodList; + } + + uint64_t methodName = reinterpret_cast<uint64_t>(_NPN_GetStringIdentifier(identifier.ascii())); + uint32_t requestID = m_instanceProxy->nextRequestID(); + + if (_WKPHNPObjectHasMethod(m_instanceProxy->hostProxy()->port(), + m_instanceProxy->pluginID(), requestID, + m_objectID, methodName) != KERN_SUCCESS) + return MethodList(); + + auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = m_instanceProxy->waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID); + if (reply.get() && reply->m_result) { + Method* method = new ProxyMethod(methodName); + + m_methods.set(identifier.ustring().rep(), method); + + MethodList methodList; + methodList.append(method); + return methodList; + } + + return MethodList(); +} + +Field* ProxyInstance::fieldNamed(const Identifier& identifier) +{ + if (Field* field = m_fields.get(identifier.ustring().rep())) + return field; + + uint64_t propertyName = reinterpret_cast<uint64_t>(_NPN_GetStringIdentifier(identifier.ascii())); + uint32_t requestID = m_instanceProxy->nextRequestID(); + + if (_WKPHNPObjectHasProperty(m_instanceProxy->hostProxy()->port(), + m_instanceProxy->pluginID(), requestID, + m_objectID, propertyName) != KERN_SUCCESS) + return 0; + + auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = m_instanceProxy->waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID); + if (reply.get() && reply->m_result) { + Field* field = new ProxyField(propertyName); + + m_fields.set(identifier.ustring().rep(), field); + + return field; + } + + return 0; +} + +JSC::JSValuePtr ProxyInstance::fieldValue(ExecState* exec, const Field* field) const +{ + uint64_t serverIdentifier = static_cast<const ProxyField*>(field)->serverIdentifier(); + uint32_t requestID = m_instanceProxy->nextRequestID(); + + if (_WKPHNPObjectGetProperty(m_instanceProxy->hostProxy()->port(), + m_instanceProxy->pluginID(), requestID, + m_objectID, serverIdentifier) != KERN_SUCCESS) + return jsUndefined(); + + auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = m_instanceProxy->waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID); + if (!reply.get() || !reply->m_returnValue) + return jsUndefined(); + + return m_instanceProxy->demarshalValue(exec, (char*)CFDataGetBytePtr(reply->m_result.get()), CFDataGetLength(reply->m_result.get())); +} + +void ProxyInstance::setFieldValue(ExecState* exec, const Field* field, JSValuePtr value) const +{ + uint64_t serverIdentifier = static_cast<const ProxyField*>(field)->serverIdentifier(); + uint32_t requestID = m_instanceProxy->nextRequestID(); + + data_t valueData; + mach_msg_type_number_t valueLength; + + m_instanceProxy->marshalValue(exec, value, valueData, valueLength); + kern_return_t kr = _WKPHNPObjectSetProperty(m_instanceProxy->hostProxy()->port(), + m_instanceProxy->pluginID(), requestID, + m_objectID, serverIdentifier, valueData, valueLength); + mig_deallocate(reinterpret_cast<vm_address_t>(valueData), valueLength); + if (kr != KERN_SUCCESS) + return; + + auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = m_instanceProxy->waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID); +} + +void ProxyInstance::invalidate() +{ + if (NetscapePluginHostProxy* hostProxy = m_instanceProxy->hostProxy()) + _WKPHNPObjectRelease(hostProxy->port(), + m_instanceProxy->pluginID(), m_objectID); + m_instanceProxy = 0; +} + +} // namespace WebKit + +#endif // USE(PLUGIN_HOST_PROCESS) + diff --git a/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.h b/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.h new file mode 100644 index 0000000..8b68b7b --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if USE(PLUGIN_HOST_PROCESS) + +#import "WebBaseNetscapePluginView.h" +#import "WebKitSystemInterface.h" + +#import <wtf/RefPtr.h> + +namespace WebKit { + class NetscapePluginInstanceProxy; +} + +@interface WebHostedNetscapePluginView : WebBaseNetscapePluginView +{ + RetainPtr<NSArray> _attributeKeys; + RetainPtr<NSArray> _attributeValues; + + RetainPtr<CALayer> _pluginLayer; + WKSoftwareCARendererRef _softwareRenderer; + + RefPtr<WebKit::NetscapePluginInstanceProxy> _proxy; + BOOL _pluginHostDied; +} + +- (id)initWithFrame:(NSRect)r + pluginPackage:(WebNetscapePluginPackage *)thePluginPackage + URL:(NSURL *)URL + baseURL:(NSURL *)baseURL + MIMEType:(NSString *)MIME + attributeKeys:(NSArray *)keys + attributeValues:(NSArray *)values + loadManually:(BOOL)loadManually + element:(PassRefPtr<WebCore::HTMLPlugInElement>)element; + +- (void)pluginHostDied; +@end + +#endif // USE(PLUGIN_HOST_PROCESS) + diff --git a/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm b/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm new file mode 100644 index 0000000..c17d249 --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#if USE(PLUGIN_HOST_PROCESS) + +#import "WebHostedNetscapePluginView.h" + +#import "NetscapePluginInstanceProxy.h" +#import "NetscapePluginHostManager.h" +#import "NetscapePluginHostProxy.h" +#import "WebTextInputWindowController.h" +#import "WebView.h" +#import "WebViewInternal.h" +#import "WebUIDelegate.h" + +#import <CoreFoundation/CoreFoundation.h> +#import <WebCore/HTMLPlugInElement.h> +#import <WebCore/runtime.h> +#import <WebCore/runtime_root.h> +#import <WebCore/WebCoreObjCExtras.h> +#import <runtime/InitializeThreading.h> +#import <wtf/Assertions.h> + +using namespace WebKit; + +extern "C" { +#include "WebKitPluginClientServer.h" +#include "WebKitPluginHost.h" +} + +@implementation WebHostedNetscapePluginView + ++ (void)initialize +{ + JSC::initializeThreading(); +#ifndef BUILDING_ON_TIGER + WebCoreObjCFinalizeOnMainThread(self); +#endif + WKSendUserChangeNotifications(); +} + +- (id)initWithFrame:(NSRect)frame + pluginPackage:(WebNetscapePluginPackage *)pluginPackage + URL:(NSURL *)URL + baseURL:(NSURL *)baseURL + MIMEType:(NSString *)MIME + attributeKeys:(NSArray *)keys + attributeValues:(NSArray *)values + loadManually:(BOOL)loadManually + element:(PassRefPtr<WebCore::HTMLPlugInElement>)element +{ + self = [super initWithFrame:frame pluginPackage:pluginPackage URL:URL baseURL:baseURL MIMEType:MIME attributeKeys:keys attributeValues:values loadManually:loadManually element:element]; + if (!self) + return nil; + + return self; +} + +- (void)handleMouseMoved:(NSEvent *)event +{ + if (_isStarted && _proxy) + _proxy->mouseEvent(self, event, NPCocoaEventMouseMoved); +} + +- (void)setAttributeKeys:(NSArray *)keys andValues:(NSArray *)values +{ + ASSERT(!_attributeKeys && !_attributeValues); + + _attributeKeys.adoptNS([keys copy]); + _attributeValues.adoptNS([values copy]); +} + +- (BOOL)createPlugin +{ + ASSERT(!_proxy); + + NSString *userAgent = [[self webView] userAgentForURL:_baseURL.get()]; + + _proxy = NetscapePluginHostManager::shared().instantiatePlugin(_pluginPackage.get(), self, _MIMEType.get(), _attributeKeys.get(), _attributeValues.get(), userAgent, _sourceURL.get()); + if (!_proxy) + return NO; + + if (_proxy->useSoftwareRenderer()) + _softwareRenderer = WKSoftwareCARendererCreate(_proxy->renderContextID()); + else { + _pluginLayer = WKMakeRenderLayer(_proxy->renderContextID()); + self.wantsLayer = YES; + } + + // Update the window frame. + _proxy->windowFrameChanged([[self window] frame]); + + return YES; +} + +- (void)setLayer:(CALayer *)newLayer +{ + [super setLayer:newLayer]; + + if (_pluginLayer) + [newLayer addSublayer:_pluginLayer.get()]; +} + +- (void)loadStream +{ +} + +- (void)updateAndSetWindow +{ + if (!_proxy) + return; + + // Use AppKit to convert view coordinates to NSWindow coordinates. + NSRect boundsInWindow = [self convertRect:[self bounds] toView:nil]; + NSRect visibleRectInWindow = [self convertRect:[self visibleRect] toView:nil]; + + // Flip Y to convert NSWindow coordinates to top-left-based window coordinates. + float borderViewHeight = [[self currentWindow] frame].size.height; + boundsInWindow.origin.y = borderViewHeight - NSMaxY(boundsInWindow); + visibleRectInWindow.origin.y = borderViewHeight - NSMaxY(visibleRectInWindow); + + _proxy->resize(boundsInWindow, visibleRectInWindow); +} + +- (void)windowFocusChanged:(BOOL)hasFocus +{ + if (_proxy) + _proxy->windowFocusChanged(hasFocus); +} + +- (BOOL)shouldStop +{ + if (!_proxy) + return YES; + + return _proxy->shouldStop(); +} + +- (void)destroyPlugin +{ + if (_proxy) { + if (_softwareRenderer) { + WKSoftwareCARendererDestroy(_softwareRenderer); + _softwareRenderer = 0; + } + + _proxy->destroy(); + _proxy = 0; + } + + _pluginLayer = 0; +} + +- (void)startTimers +{ + if (_proxy) + _proxy->startTimers(_isCompletelyObscured); +} + +- (void)stopTimers +{ + if (_proxy) + _proxy->stopTimers(); +} + +- (void)focusChanged +{ + if (_proxy) + _proxy->focusChanged(_hasFocus); +} + +- (void)windowFrameDidChange:(NSNotification *)notification +{ + if (_proxy && [self window]) + _proxy->windowFrameChanged([[self window] frame]); +} + +- (void)addWindowObservers +{ + [super addWindowObservers]; + + ASSERT([self window]); + + NSWindow *window = [self window]; + + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self selector:@selector(windowFrameDidChange:) + name:NSWindowDidMoveNotification object:window]; + [notificationCenter addObserver:self selector:@selector(windowFrameDidChange:) + name:NSWindowDidResizeNotification object:window]; + + if (_proxy) + _proxy->windowFrameChanged([window frame]); + [self updateAndSetWindow]; +} + +- (void)removeWindowObservers +{ + [super removeWindowObservers]; + + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter removeObserver:self name:NSWindowDidMoveNotification object:nil]; + [notificationCenter removeObserver:self name:NSWindowDidResizeNotification object:nil]; +} + +- (void)mouseDown:(NSEvent *)event +{ + if (_isStarted && _proxy) + _proxy->mouseEvent(self, event, NPCocoaEventMouseDown); +} + +- (void)mouseUp:(NSEvent *)event +{ + if (_isStarted && _proxy) + _proxy->mouseEvent(self, event, NPCocoaEventMouseUp); +} + +- (void)mouseDragged:(NSEvent *)event +{ + if (_isStarted && _proxy) + _proxy->mouseEvent(self, event, NPCocoaEventMouseDragged); +} + +- (void)mouseEntered:(NSEvent *)event +{ + if (_isStarted && _proxy) + _proxy->mouseEvent(self, event, NPCocoaEventMouseEntered); +} + +- (void)mouseExited:(NSEvent *)event +{ + if (_isStarted && _proxy) + _proxy->mouseEvent(self, event, NPCocoaEventMouseExited); +} + +- (NSTextInputContext *)inputContext +{ + return [[WebTextInputWindowController sharedTextInputWindowController] inputContext]; +} + +- (void)keyDown:(NSEvent *)event +{ + if (!_isStarted || !_proxy) + return; + + NSString *string = nil; + if ([[WebTextInputWindowController sharedTextInputWindowController] interpretKeyEvent:event string:&string]) { + if (string) + _proxy->insertText(string); + return; + } + + _proxy->keyEvent(self, event, NPCocoaEventKeyDown); +} + +- (void)keyUp:(NSEvent *)event +{ + if (_isStarted && _proxy) + _proxy->keyEvent(self, event, NPCocoaEventKeyUp); +} + +- (void)pluginHostDied +{ + _pluginHostDied = YES; + + _pluginLayer = nil; + _proxy = 0; + + // No need for us to be layer backed anymore + self.wantsLayer = NO; + + [self setNeedsDisplay:YES]; +} + + +- (void)drawRect:(NSRect)rect +{ + if (_proxy) { + if (_softwareRenderer) { + if ([NSGraphicsContext currentContextDrawingToScreen]) + WKSoftwareCARendererRender(_softwareRenderer, (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort], NSRectToCGRect(rect)); + else + _proxy->print(reinterpret_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]), [self bounds].size.width, [self bounds].size.height); + } + + return; + } + + if (_pluginHostDied) { + static NSImage *nullPlugInImage; + if (!nullPlugInImage) { + NSBundle *bundle = [NSBundle bundleForClass:[WebHostedNetscapePluginView class]]; + nullPlugInImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"nullplugin" ofType:@"tiff"]]; + [nullPlugInImage setFlipped:YES]; + } + + if (!nullPlugInImage) + return; + + NSSize imageSize = [nullPlugInImage size]; + NSSize viewSize = [self bounds].size; + + NSPoint point = NSMakePoint((viewSize.width - imageSize.width) / 2.0, (viewSize.height - imageSize.height) / 2.0); + [nullPlugInImage drawAtPoint:point fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; + } +} + +- (PassRefPtr<JSC::Bindings::Instance>)createPluginBindingsInstance:(PassRefPtr<JSC::Bindings::RootObject>)rootObject +{ + if (!_proxy) + return 0; + + return _proxy->createBindingsInstance(rootObject); +} + +@end + +#endif diff --git a/WebKit/mac/Plugins/Hosted/WebKitPluginAgent.defs b/WebKit/mac/Plugins/Hosted/WebKitPluginAgent.defs new file mode 100644 index 0000000..0f332b6 --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/WebKitPluginAgent.defs @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <WebKit/WebKitPluginHostTypes.defs> + +subsystem WebKitPluginAgent 100; + +serverprefix WKPA; +userprefix _WKPA; + +routine CheckInApplication(serverPort :mach_port_t; + ServerAuditToken token :audit_token_t; + applicationName :application_name_t; + out pluginVendorPort :mach_port_make_send_t); + +routine SpawnPluginHost(pluginVendorPort :mach_port_t; + sreplyport _replyPort :mach_port_make_send_once_t; + options :plist_bytes_t; + out pluginHostPort: mach_port_move_send_t); + +routine CheckInPluginHost(serverPort :mach_port_t; + pluginHostPort :mach_port_move_send_t; + ServerAuditToken token :audit_token_t); diff --git a/WebKit/mac/Plugins/Hosted/WebKitPluginAgentReply.defs b/WebKit/mac/Plugins/Hosted/WebKitPluginAgentReply.defs new file mode 100644 index 0000000..c802b3d --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/WebKitPluginAgentReply.defs @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <WebKit/WebKitPluginHostTypes.defs> + +subsystem WebKitPluginAgentReply 200; + +serverprefix WKPA; +userprefix _WKPA; + +skip; // CheckInApplication + +simpleroutine SpawnPluginHostReply(_replyPort :mach_port_move_send_once_t; + in pluginHostPort: mach_port_move_send_t); + +skip; // CheckInPluginHost diff --git a/WebKit/mac/Plugins/Hosted/WebKitPluginClient.defs b/WebKit/mac/Plugins/Hosted/WebKitPluginClient.defs new file mode 100644 index 0000000..6128517 --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/WebKitPluginClient.defs @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <WebKit/WebKitPluginHostTypes.defs> + +// FIXME: Come up with a better name. +subsystem WebKitPluginClient 300; + +serverprefix WK; +userprefix _WK; + +simpleroutine PCStatusText(clientPort :mach_port_t; + pluginID :uint32_t; + text :data_t); + +routine PCLoadURL(clientPort :mach_port_t; + pluginID :uint32_t; + url :data_t; + target :data_t; + postData :data_t; + flags: uint32_t; + out resultCode :uint16_t; + out requestID :uint32_t); + +simpleroutine PCCancelLoadURL(clientPort :mach_port_t; + pluginID :uint32_t; + streamID :uint32_t; + reason :int16_t); + +simpleroutine PCInvalidateRect(clientPort :mach_port_t; + pluginID :uint32_t; + x :double; + y :double; + width :double; + height :double); + +// NPRuntime + +routine PCGetStringIdentifier(clientPort :mach_port_t; + name :data_t; + out identifier :uint64_t); + +routine PCGetIntIdentifier(clientPort :mach_port_t; + value :int32_t; + out identifier: uint64_t); + +routine PCGetWindowNPObject(clientPort :mach_port_t; + pluginID :uint32_t; + out objectID :uint32_t); +routine PCGetPluginElementNPObject(clientPort :mach_port_t; + pluginID :uint32_t; + out objectID :uint32_t); + +routine PCReleaseObject(clientPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t); + +simpleroutine PCEvaluate(clientPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + objectID :uint32_t; + script :data_t); + +simpleroutine PCInvoke(clientPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + objectID :uint32_t; + methodNameIdentifier :uint64_t; + arguments :data_t); + +simpleroutine PCInvokeDefault(clientPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + objectID :uint32_t; + arguments :data_t); + +routine PCConstruct(clientPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + arguments :data_t; + out returnValue :boolean_t; + out result :data_t, dealloc); + +simpleroutine PCGetProperty(clientPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + objectID :uint32_t; + propertyNameIdentifier :uint64_t); + +routine PCSetProperty(clientPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + propertyNameIdentifier :uint64_t; + value :data_t; + out returnValue :boolean_t); + +routine PCRemoveProperty(clientPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t; + propertyNameIdentifier :uint64_t; + out returnValue :boolean_t); + +simpleroutine PCHasProperty(clientPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + objectID :uint32_t; + propertyNameIdentifier :uint64_t); + +simpleroutine PCHasMethod(clientPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + objectID :uint32_t; + methodNameIdentifier :uint64_t); + +routine PCIdentifierInfo(clientPort :mach_port_t; + identifier :uint64_t; + out info :data_t, dealloc); + +simpleroutine PCEnumerate(clientPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + objectID :uint32_t); + +// Misc + +simpleroutine PCSetMenuBarVisible(clientPort :mach_port_t; + visible :boolean_t); + +simpleroutine PCSetModal(clientPort :mach_port_t; + modal :boolean_t); + +// Replies +simpleroutine PCInstantiatePluginReply(clientPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + result :kern_return_t; + renderContextID :uint32_t; + useSoftwareRenderer :boolean_t); + +simpleroutine PCGetScriptableNPObjectReply(clientPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + objectID :uint32_t); + +simpleroutine PCBooleanReply(clientPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + result :boolean_t); + +simpleroutine PCBooleanAndDataReply(clientPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + returnValue :boolean_t; + result :data_t); diff --git a/WebKit/mac/Plugins/Hosted/WebKitPluginHost.defs b/WebKit/mac/Plugins/Hosted/WebKitPluginHost.defs new file mode 100644 index 0000000..c6c38aa --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/WebKitPluginHost.defs @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <WebKit/WebKitPluginHostTypes.defs> + +subsystem WebKitPluginHost 300; + +serverprefix WK; +userprefix _WK; + +routine PHCheckInWithPluginHost(pluginHostPort :mach_port_t; + options :plist_bytes_t; + clientPort :mach_port_make_send_t; + clientPSNHigh :uint32_t; + clientPSNLow :uint32_t; + renderPort :mach_port_copy_send_t; + out pluginHostPSNHigh :uint32_t; + out pluginHostPSNLow :uint32_t); + +simpleroutine PHInstantiatePlugin(pluginHostPort :mach_port_t; + requestID :uint32_t; + options :plist_bytes_t; + pluginID :uint32_t); + +simpleroutine PHResizePluginInstance(pluginHostPort :mach_port_t; + pluginID :uint32_t; + x :double; + y :double; + width :double; + height :double); +simpleroutine PHPluginInstanceFocusChanged(pluginHostPort :mach_port_t; + pluginID :uint32_t; + hasFocus :boolean_t); +simpleroutine PHPluginInstanceWindowFocusChanged(pluginHostPort :mach_port_t; + pluginID :uint32_t; + hasFocus :boolean_t); +simpleroutine PHPluginInstanceWindowFrameChanged(pluginHostPort :mach_port_t; + pluginID :uint32_t; + x :double; + y :double; + width :double; + height :double; + maxScreenY :double); + +simpleroutine PHPluginInstanceMouseEvent(pluginHostPort :mach_port_t; + pluginID :uint32_t; + timestamp :double; + eventType :uint32_t; + modifierFlags :uint32_t; + pluginX :double; + pluginY :double; + screenX :double; + screenY :double; + maxScreenY :double; + buttonNumber :int32_t; + clickCount :int32_t; + deltaX :double; + deltaY :double; + deltaZ: double); + +simpleroutine PHPluginInstanceKeyboardEvent(pluginHostPort :mach_port_t; + pluginID :uint32_t; + timestamp :double; + eventType :uint32_t; + modifierFlags :uint32_t; + characters :data_t; + charactersIgnoringModifiers :data_t; + isARepeat :boolean_t; + keyCode :uint16_t); + +simpleroutine PHPluginInstanceInsertText(pluginHostPort :mach_port_t; + pluginID :uint32_t; + text :data_t); + +simpleroutine PHPluginInstanceStartTimers(pluginHostPort :mach_port_t; + pluginID :uint32_t; + throttleTimers :boolean_t); +simpleroutine PHPluginInstanceStopTimers(pluginHostPort :mach_port_t; + pluginID :uint32_t); + +simpleroutine PHPluginInstancePrint(pluginHostPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + width :uint32_t; + height :uint32_t); + +simpleroutine PHDestroyPluginInstance(pluginHostPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t); + + +// Streams +simpleroutine PHStartStream(pluginHostPort :mach_port_t; + pluginID :uint32_t; + streamID :uint32_t; + responseURL :data_t; + expectedContentLength :int64_t; + lastModifiedTimeInterval :double; + mimeType :data_t; + headers :data_t); + +simpleroutine PHStreamDidReceiveData(pluginHostPort :mach_port_t; + pluginID :uint32_t; + streamID :uint32_t; + data :data_t); + +simpleroutine PHStreamDidFinishLoading(pluginHostPort :mach_port_t; + pluginID :uint32_t; + streamID :uint32_t); + +simpleroutine PHStreamDidFail(pluginHostPort :mach_port_t; + pluginID :uint32_t; + streamID :uint32_t; + reason :int16_t); + +simpleroutine PHLoadURLNotify(pluginHostPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + reason :int16_t); + +// NPRuntime + +simpleroutine PHGetScriptableNPObject(pluginHostPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t); + +simpleroutine PHNPObjectHasProperty(pluginHostPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + objectID :uint32_t; + propertyName :uint64_t); + +simpleroutine PHNPObjectHasMethod(pluginHostPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + objectID :uint32_t; + methodName :uint64_t); + +simpleroutine PHNPObjectInvoke(pluginHostPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + objectID :uint32_t; + invokeType :uint32_t; + methodName :uint64_t; + arguments :data_t); + +simpleroutine PHNPObjectHasInvokeDefaultMethod(pluginHostPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + objectID :uint32_t); + +simpleroutine PHNPObjectHasConstructMethod(pluginHostPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + objectID :uint32_t); + +simpleroutine PHNPObjectGetProperty(pluginHostPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + objectID :uint32_t; + propertyName :uint64_t); + +simpleroutine PHNPObjectSetProperty(pluginHostPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + objectID :uint32_t; + propertyName :uint64_t; + value :data_t); + +simpleroutine PHNPObjectRelease(pluginHostPort :mach_port_t; + pluginID :uint32_t; + objectID :uint32_t); + +simpleroutine PHNPObjectEnumerate(pluginHostPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + objectID :uint32_t); + +// Replies + +simpleroutine PHBooleanReply(clientPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + result :boolean_t); + +simpleroutine PHBooleanAndDataReply(pluginHostPort :mach_port_t; + pluginID :uint32_t; + requestID :uint32_t; + returnValue :boolean_t; + result :data_t); diff --git a/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.defs b/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.defs new file mode 100644 index 0000000..ee53520 --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.defs @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <mach/std_types.defs> +#include <mach/mach_types.defs> + +import <WebKit/WebKitPluginHostTypes.h>; + +type plist_bytes_t = ^array [] of uint8_t; +type application_name_t = ^array [] of uint8_t; +type data_t = ^array [] of char; diff --git a/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.h b/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.h new file mode 100644 index 0000000..a5efde9 --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/WebKitPluginHostTypes.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WebKitPluginHostTypes_h +#define WebKitPluginHostTypes_h + +typedef uint8_t* plist_bytes_t; +typedef uint8_t* application_name_t; + +typedef char* data_t; + +#ifndef __MigTypeCheck +#define __MigTypeCheck 1 +#endif + +enum LoadURLFlags { + IsPost = 1 << 0, + PostDataIsFile = 1 << 1, + AllowHeadersInPostData = 1 << 2, + CurrentEventIsUserGesture = 1 << 3, +}; + +enum InvokeType { + Invoke, + InvokeDefault, + Construct +}; + +enum ValueType { + VoidValueType, + NullValueType, + BoolValueType, + DoubleValueType, + StringValueType, + JSObjectValueType, + NPObjectValueType +}; + +#endif // WebKitPluginHostTypes_h diff --git a/WebKit/mac/Plugins/Hosted/WebTextInputWindowController.h b/WebKit/mac/Plugins/Hosted/WebTextInputWindowController.h new file mode 100644 index 0000000..9f036ee --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/WebTextInputWindowController.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2009 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if USE(PLUGIN_HOST_PROCESS) + +#ifndef WebTextInputWindowController_h +#define WebTextInputWindowController_h + +@class WebTextInputPanel; + +@interface WebTextInputWindowController : NSObject { + WebTextInputPanel *_panel; +} + ++ (WebTextInputWindowController *)sharedTextInputWindowController; + +- (NSTextInputContext *)inputContext; +- (BOOL)interpretKeyEvent:(NSEvent *)event string:(NSString **)string; + +@end + +#endif // WebTextInputWindowController_h + +#endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/WebTextInputWindowController.m b/WebKit/mac/Plugins/Hosted/WebTextInputWindowController.m new file mode 100644 index 0000000..c168e6e --- /dev/null +++ b/WebKit/mac/Plugins/Hosted/WebTextInputWindowController.m @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2009 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if USE(PLUGIN_HOST_PROCESS) + +#import "WebTextInputWindowController.h" + +#import <WebKitSystemInterface.h> + +@interface WebTextInputPanel : NSPanel { + NSTextView *_inputTextView; +} + +- (NSTextInputContext *)_inputContext; +- (BOOL)_interpretKeyEvent:(NSEvent *)event string:(NSString **)string; + +@end + +#define inputWindowHeight 20 + +@implementation WebTextInputPanel + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [_inputTextView release]; + + [super dealloc]; +} + +- (id)init +{ + self = [super initWithContentRect:NSZeroRect styleMask:WKGetInputPanelWindowStyle() backing:NSBackingStoreBuffered defer:YES]; + if (!self) + return nil; + + // Set the frame size. + NSRect visibleFrame = [[NSScreen mainScreen] visibleFrame]; + NSRect frame = NSMakeRect(visibleFrame.origin.x, visibleFrame.origin.y, visibleFrame.size.width, inputWindowHeight); + + [self setFrame:frame display:NO]; + + _inputTextView = [[NSTextView alloc] initWithFrame:[self.contentView frame]]; + _inputTextView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable | NSViewMaxXMargin | NSViewMinXMargin | NSViewMaxYMargin | NSViewMinYMargin; + + NSScrollView* scrollView = [[NSScrollView alloc] initWithFrame:[self.contentView frame]]; + scrollView.documentView = _inputTextView; + self.contentView = scrollView; + [scrollView release]; + + [self setFloatingPanel:YES]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(_keyboardInputSourceChanged:) + name:NSTextInputContextKeyboardSelectionDidChangeNotification + object:nil]; + + return self; +} + +- (void)_keyboardInputSourceChanged:(NSNotification *)notification +{ + [_inputTextView setString:@""]; + [self orderOut:nil]; +} + +- (BOOL)_interpretKeyEvent:(NSEvent *)event string:(NSString **)string +{ + BOOL hadMarkedText = [_inputTextView hasMarkedText]; + + *string = nil; + + if (![[_inputTextView inputContext] handleEvent:event]) + return NO; + + if ([_inputTextView hasMarkedText]) { + // Don't show the input method window for dead keys + if ([[event characters] length] > 0) + [self orderFront:nil]; + + return YES; + } + + if (hadMarkedText) { + [self orderOut:nil]; + + NSString *text = [[_inputTextView textStorage] string]; + if ([text length] > 0) + *string = [[text copy] autorelease]; + } + + [_inputTextView setString:@""]; + return hadMarkedText; +} + +- (NSTextInputContext *)_inputContext +{ + return [_inputTextView inputContext]; +} + +@end + +@implementation WebTextInputWindowController + ++ (WebTextInputWindowController *)sharedTextInputWindowController +{ + static WebTextInputWindowController *textInputWindowController; + if (!textInputWindowController) + textInputWindowController = [[WebTextInputWindowController alloc] init]; + + return textInputWindowController; +} + +- (id)init +{ + self = [super init]; + if (!self) + return nil; + + _panel = [[WebTextInputPanel alloc] init]; + + return self; +} + +- (NSTextInputContext *)inputContext +{ + return [_panel _inputContext]; +} + +- (BOOL)interpretKeyEvent:(NSEvent *)event string:(NSString **)string +{ + return [_panel _interpretKeyEvent:event string:string]; +} + +@end + +#endif // USE(PLUGIN_HOST_PROCESS) + diff --git a/WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm b/WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm index a29be2d..96f7644 100644 --- a/WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm +++ b/WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm @@ -43,6 +43,7 @@ #import <WebCore/Frame.h> #import <WebCore/FrameLoader.h> #import <WebCore/WebCoreObjCExtras.h> +#import <WebCore/WebCoreURLResponse.h> #import <WebKitSystemInterface.h> #import <wtf/HashMap.h> #import <wtf/StdLibExtras.h> @@ -53,6 +54,26 @@ using namespace WebCore; static NSString *CarbonPathFromPOSIXPath(NSString *posixPath); +class PluginStopDeferrer { +public: + PluginStopDeferrer(WebNetscapePluginView* pluginView) + : m_pluginView(pluginView) + { + ASSERT(m_pluginView); + + [m_pluginView.get() willCallPlugInFunction]; + } + + ~PluginStopDeferrer() + { + ASSERT(m_pluginView); + [m_pluginView.get() didCallPlugInFunction]; + } + +private: + RetainPtr<WebNetscapePluginView> m_pluginView; +}; + typedef HashMap<NPStream*, NPP> StreamMap; static StreamMap& streams() { @@ -217,9 +238,12 @@ void WebNetscapePluginStream::startStream(NSURL *url, long long expectedContentL // FIXME: Need a way to check if stream is seekable - [m_pluginView.get() willCallPlugInFunction]; - NPError npErr = m_pluginFuncs->newstream(m_plugin, (char *)[m_mimeType.get() UTF8String], &m_stream, NO, &m_transferMode); - [m_pluginView.get() didCallPlugInFunction]; + NPError npErr; + { + PluginStopDeferrer deferrer(m_pluginView.get()); + npErr = m_pluginFuncs->newstream(m_plugin, (char *)[m_mimeType.get() UTF8String], &m_stream, NO, &m_transferMode); + } + LOG(Plugins, "NPP_NewStream URL=%@ MIME=%@ error=%d", m_responseURL.get(), m_mimeType.get(), npErr); if (npErr != NPERR_NO_ERROR) { @@ -324,7 +348,7 @@ void WebNetscapePluginStream::didReceiveResponse(NetscapePlugInStreamLoader*, co // startStreamResponseURL:... will null-terminate. } - startStream([r URL], expectedContentLength, WKGetNSURLResponseLastModifiedDate(r), [r MIMEType], theHeaders); + startStream([r URL], expectedContentLength, WKGetNSURLResponseLastModifiedDate(r), [r _webcore_MIMEType], theHeaders); } void WebNetscapePluginStream::startStreamWithResponse(NSURLResponse *response) @@ -339,12 +363,11 @@ bool WebNetscapePluginStream::wantsAllStreams() const void *value = 0; NPError error; - [m_pluginView.get() willCallPlugInFunction]; { + PluginStopDeferrer deferrer(m_pluginView.get()); JSC::JSLock::DropAllLocks dropAllLocks(false); error = m_pluginFuncs->getvalue(m_plugin, NPPVpluginWantsAllNetworkStreams, &value); } - [m_pluginView.get() didCallPlugInFunction]; if (error != NPERR_NO_ERROR) return false; @@ -369,9 +392,9 @@ void WebNetscapePluginStream::destroyStream() ASSERT(m_path); NSString *carbonPath = CarbonPathFromPOSIXPath(m_path.get()); ASSERT(carbonPath != NULL); - [m_pluginView.get() willCallPlugInFunction]; + + PluginStopDeferrer deferrer(m_pluginView.get()); m_pluginFuncs->asfile(m_plugin, &m_stream, [carbonPath fileSystemRepresentation]); - [m_pluginView.get() didCallPlugInFunction]; LOG(Plugins, "NPP_StreamAsFile responseURL=%@ path=%s", m_responseURL.get(), carbonPath); } @@ -394,12 +417,11 @@ void WebNetscapePluginStream::destroyStream() } if (m_newStreamSuccessful) { - [m_pluginView.get() willCallPlugInFunction]; + PluginStopDeferrer deferrer(m_pluginView.get()); #if !LOG_DISABLED NPError npErr = #endif m_pluginFuncs->destroystream(m_plugin, &m_stream, m_reason); - [m_pluginView.get() didCallPlugInFunction]; LOG(Plugins, "NPP_DestroyStream responseURL=%@ error=%d", m_responseURL.get(), npErr); } @@ -415,9 +437,8 @@ void WebNetscapePluginStream::destroyStream() if (m_sendNotification) { // NPP_URLNotify expects the request URL, not the response URL. - [m_pluginView.get() willCallPlugInFunction]; + PluginStopDeferrer deferrer(m_pluginView.get()); m_pluginFuncs->urlnotify(m_plugin, [m_requestURL.get() _web_URLCString], m_reason, m_notifyData); - [m_pluginView.get() didCallPlugInFunction]; LOG(Plugins, "NPP_URLNotify requestURL=%@ reason=%d", m_requestURL.get(), m_reason); } @@ -488,9 +509,8 @@ void WebNetscapePluginStream::deliverData() int32 totalBytesDelivered = 0; while (totalBytesDelivered < totalBytes) { - [m_pluginView.get() willCallPlugInFunction]; + PluginStopDeferrer deferrer(m_pluginView.get()); int32 deliveryBytes = m_pluginFuncs->writeready(m_plugin, &m_stream); - [m_pluginView.get() didCallPlugInFunction]; LOG(Plugins, "NPP_WriteReady responseURL=%@ bytes=%d", m_responseURL.get(), deliveryBytes); if (m_isTerminated) @@ -504,9 +524,8 @@ void WebNetscapePluginStream::deliverData() } else { deliveryBytes = MIN(deliveryBytes, totalBytes - totalBytesDelivered); NSData *subdata = [m_deliveryData.get() subdataWithRange:NSMakeRange(totalBytesDelivered, deliveryBytes)]; - [m_pluginView.get() willCallPlugInFunction]; + PluginStopDeferrer deferrer(m_pluginView.get()); deliveryBytes = m_pluginFuncs->write(m_plugin, &m_stream, m_offset, [subdata length], (void *)[subdata bytes]); - [m_pluginView.get() didCallPlugInFunction]; if (deliveryBytes < 0) { // Netscape documentation says that a negative result from NPP_Write means cancel the load. cancelLoadAndDestroyStreamWithError(pluginCancelledConnectionError()); @@ -523,9 +542,8 @@ void WebNetscapePluginStream::deliverData() if (totalBytesDelivered < totalBytes) { NSMutableData *newDeliveryData = [[NSMutableData alloc] initWithCapacity:totalBytes - totalBytesDelivered]; [newDeliveryData appendBytes:(char *)[m_deliveryData.get() bytes] + totalBytesDelivered length:totalBytes - totalBytesDelivered]; - [m_deliveryData.get() release]; - m_deliveryData = newDeliveryData; - [newDeliveryData release]; + + m_deliveryData.adoptNS(newDeliveryData); } else { [m_deliveryData.get() setLength:0]; if (m_reason != WEB_REASON_NONE) diff --git a/WebKit/mac/Plugins/WebBaseNetscapePluginView.h b/WebKit/mac/Plugins/WebBaseNetscapePluginView.h index b2ea2b1..ec0a3df 100644 --- a/WebKit/mac/Plugins/WebBaseNetscapePluginView.h +++ b/WebKit/mac/Plugins/WebBaseNetscapePluginView.h @@ -31,6 +31,8 @@ #import "WebNetscapePluginPackage.h" +#import <wtf/PassRefPtr.h> +#import <wtf/RefPtr.h> #import <wtf/RetainPtr.h> @class DOMElement; @@ -38,6 +40,10 @@ @class WebFrame; @class WebView; +namespace WebCore { + class HTMLPlugInElement; +} + @interface WebBaseNetscapePluginView : NSView { RetainPtr<WebNetscapePluginPackage> _pluginPackage; @@ -52,7 +58,7 @@ BOOL _hasFocus; BOOL _isCompletelyObscured; - RetainPtr<DOMElement> _element; + RefPtr<WebCore::HTMLPlugInElement> _element; RetainPtr<NSString> _MIMEType; RetainPtr<NSURL> _baseURL; RetainPtr<NSURL> _sourceURL; @@ -68,7 +74,7 @@ attributeKeys:(NSArray *)keys attributeValues:(NSArray *)values loadManually:(BOOL)loadManually - DOMElement:(DOMElement *)anElement; + element:(PassRefPtr<WebCore::HTMLPlugInElement>)element; - (WebNetscapePluginPackage *)pluginPackage; @@ -83,6 +89,7 @@ - (WebDataSource *)dataSource; - (WebView *)webView; - (NSWindow *)currentWindow; +- (WebCore::HTMLPlugInElement*)element; - (void)removeTrackingRect; - (void)resetTrackingRect; diff --git a/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm b/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm index a2a8b50..26057fa 100644 --- a/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm +++ b/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm @@ -44,7 +44,9 @@ #import <WebCore/Element.h> #import <WebCore/Frame.h> #import <WebCore/FrameLoader.h> +#import <WebCore/HTMLPlugInElement.h> #import <WebCore/Page.h> +#import <WebCore/RenderView.h> #import <WebKit/DOMPrivate.h> #import <runtime/InitializeThreading.h> #import <wtf/Assertions.h> @@ -73,14 +75,14 @@ using namespace WebCore; attributeKeys:(NSArray *)keys attributeValues:(NSArray *)values loadManually:(BOOL)loadManually - DOMElement:(DOMElement *)anElement + element:(PassRefPtr<WebCore::HTMLPlugInElement>)element { self = [super initWithFrame:frame]; if (!self) return nil; _pluginPackage = pluginPackage; - _element = anElement; + _element = element; _sourceURL.adoptNS([URL copy]); _baseURL.adoptNS([baseURL copy]); _MIMEType.adoptNS([MIME copy]); @@ -237,11 +239,23 @@ using namespace WebCore; [self startTimers]; } +- (NSRect)_windowClipRect +{ + RenderObject* renderer = _element->renderer(); + + if (renderer && renderer->view()) { + if (FrameView* frameView = renderer->view()->frameView()) + return frameView->windowClipRectForLayer(renderer->enclosingLayer(), true); + } + + return NSZeroRect; +} + - (NSRect)visibleRect { // WebCore may impose an additional clip (via CSS overflow or clip properties). Fetch // that clip now. - return NSIntersectionRect([self convertRect:[_element.get() _windowClipRect] fromView:nil], [super visibleRect]); + return NSIntersectionRect([self convertRect:[self _windowClipRect] fromView:nil], [super visibleRect]); } - (BOOL)acceptsFirstResponder @@ -558,7 +572,7 @@ using namespace WebCore; - (WebDataSource *)dataSource { - WebFrame *webFrame = kit(core(_element.get())->document()->frame()); + WebFrame *webFrame = kit(_element->document()->frame()); return [webFrame _dataSource]; } @@ -577,6 +591,11 @@ using namespace WebCore; return [self window] ? [self window] : [[self webView] hostWindow]; } +- (WebCore::HTMLPlugInElement*)element +{ + return _element.get(); +} + // We want to treat these as regular keyboard events. - (void)cut:(id)sender diff --git a/WebKit/mac/Plugins/WebBasePluginPackage.mm b/WebKit/mac/Plugins/WebBasePluginPackage.mm index 7b5ef8e..1bddbcf 100644 --- a/WebKit/mac/Plugins/WebBasePluginPackage.mm +++ b/WebKit/mac/Plugins/WebBasePluginPackage.mm @@ -198,12 +198,18 @@ { } -- (NSDictionary *)pListForPath:(NSString *)pListPath createFile:(BOOL)createFile +- (void)createPropertyListFile { - if (createFile && [self load] && BP_CreatePluginMIMETypesPreferences) { + if ([self load] && BP_CreatePluginMIMETypesPreferences) { BP_CreatePluginMIMETypesPreferences(); [self unload]; } +} + +- (NSDictionary *)pListForPath:(NSString *)pListPath createFile:(BOOL)createFile +{ + if (createFile) + [self createPropertyListFile]; NSDictionary *pList = nil; NSData *data = [NSData dataWithContentsOfFile:pListPath]; diff --git a/WebKit/mac/Plugins/WebKitPluginContainerView.h b/WebKit/mac/Plugins/WebKitPluginContainerView.h deleted file mode 100644 index a67c105..0000000 --- a/WebKit/mac/Plugins/WebKitPluginContainerView.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2007 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. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. - */ - -#import <Cocoa/Cocoa.h> - -@class DOMElement; - -@interface WebKitPluginContainerView : NSView -{ - DOMElement *_element; -} - -- (id)initWithFrame:(NSRect)r - DOMElement:(DOMElement *)anElement; - -- (id)objectForWebScript; - -@end diff --git a/WebKit/mac/Plugins/WebKitPluginContainerView.mm b/WebKit/mac/Plugins/WebKitPluginContainerView.mm deleted file mode 100644 index fb61644..0000000 --- a/WebKit/mac/Plugins/WebKitPluginContainerView.mm +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2007 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. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. - */ - -#import "WebKitPluginContainerView.h" -#import <WebKit/DOMPrivate.h> - -@implementation WebKitPluginContainerView - -- (id)initWithFrame:(NSRect)frame - DOMElement:(DOMElement *)anElement -{ - [super initWithFrame:frame]; - - _element = [anElement retain]; - - return self; -} - -- (void)dealloc -{ - [_element release]; - - [super dealloc]; -} - -- (NSRect)visibleRect -{ - if (![self window]) - return [super visibleRect]; - - // WebCore may impose an additional clip (via CSS overflow or clip properties). Fetch - // that clip now. - return NSIntersectionRect([self convertRect:[_element _windowClipRect] fromView:nil], [super visibleRect]); -} - -- (BOOL)respondsToSelector:(SEL)selector -{ - if (selector == @selector(objectForWebScript)) - return [[[self subviews] objectAtIndex: 0] respondsToSelector:selector]; - return [super respondsToSelector:selector]; -} - -- (id)objectForWebScript -{ - return [[[self subviews] objectAtIndex: 0] objectForWebScript]; -} - -@end - diff --git a/WebKit/mac/Plugins/WebNetscapeDeprecatedFunctions.h b/WebKit/mac/Plugins/WebNetscapeDeprecatedFunctions.h index 93c3194..dc8bf4d 100644 --- a/WebKit/mac/Plugins/WebNetscapeDeprecatedFunctions.h +++ b/WebKit/mac/Plugins/WebNetscapeDeprecatedFunctions.h @@ -27,9 +27,17 @@ #import <CoreServices/CoreServices.h> +#ifdef __cplusplus +extern "C" { +#endif + extern OSErr WebGetDiskFragment(const FSSpec *fileSpec, UInt32 offset, UInt32 length, ConstStr63Param fragName, CFragLoadOptions options, CFragConnectionID *connID, Ptr *mainAddr, Str255 errMessage); extern OSErr WebCloseConnection(CFragConnectionID *connID); extern SInt16 WebLMGetCurApRefNum(void); extern void WebLMSetCurApRefNum(SInt16 value); +#ifdef __cplusplus +} +#endif + #endif /* ENABLE(NETSCAPE_PLUGIN_API) && !defined(__LP64__) */ diff --git a/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.h b/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.h index 8b6f6e7..4613fcd 100644 --- a/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.h +++ b/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.h @@ -53,10 +53,24 @@ public: virtual void focusChanged(bool hasFocus); virtual void* platformWindow(NSWindow*); + private: bool sendMouseEvent(NSEvent*, NPCocoaEventType); bool sendKeyEvent(NSEvent*, NPCocoaEventType); bool sendEvent(NPCocoaEvent*); + +#ifndef __LP64__ + void installKeyEventHandler(); + void removeKeyEventHandler(); + + static OSStatus TSMEventHandler(EventHandlerCallRef, EventRef, void *eventHandler); + OSStatus handleTSMEvent(EventRef); + + EventHandlerRef m_keyEventHandler; +#else + inline void installKeyEventHandler() { } + void removeKeyEventHandler() { } +#endif }; #endif //WebNetscapePluginEventHandlerCocoa_h diff --git a/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.mm b/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.mm index 288a356..e3fb362 100644 --- a/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.mm +++ b/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.mm @@ -27,10 +27,16 @@ #import "WebNetscapePluginEventHandlerCocoa.h" +#import "WebKitSystemInterface.h" #import "WebNetscapePluginView.h" +#import <wtf/UnusedParam.h> +#import <wtf/Vector.h> WebNetscapePluginEventHandlerCocoa::WebNetscapePluginEventHandlerCocoa(WebNetscapePluginView* pluginView) : WebNetscapePluginEventHandler(pluginView) +#ifndef __LP64__ + , m_keyEventHandler(0) +#endif { } @@ -117,9 +123,13 @@ void WebNetscapePluginEventHandlerCocoa::keyDown(NSEvent *event) { bool retval = sendKeyEvent(event, NPCocoaEventKeyDown); +#ifndef __LP64__ // If the plug-in did not handle the event, pass it on to the Input Manager. - if (!retval) - [m_pluginView interpretKeyEvents:[NSArray arrayWithObject:event]]; + if (retval) + WKSendKeyEventToTSM(event); +#else + UNUSED_PARAM(retval); +#endif } void WebNetscapePluginEventHandlerCocoa::keyUp(NSEvent *event) @@ -173,6 +183,11 @@ void WebNetscapePluginEventHandlerCocoa::focusChanged(bool hasFocus) event.data.focus.hasFocus = hasFocus; sendEvent(&event); + + if (hasFocus) + installKeyEventHandler(); + else + removeKeyEventHandler(); } void* WebNetscapePluginEventHandlerCocoa::platformWindow(NSWindow* window) @@ -202,4 +217,67 @@ bool WebNetscapePluginEventHandlerCocoa::sendEvent(NPCocoaEvent* event) return result; } +#ifndef __LP64__ + +void WebNetscapePluginEventHandlerCocoa::installKeyEventHandler() +{ + static const EventTypeSpec TSMEvents[] = + { + { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } + }; + + if (!m_keyEventHandler) + InstallEventHandler(GetWindowEventTarget((WindowRef)[[m_pluginView window] windowRef]), + NewEventHandlerUPP(TSMEventHandler), + GetEventTypeCount(TSMEvents), + TSMEvents, + this, + &m_keyEventHandler); +} + +void WebNetscapePluginEventHandlerCocoa::removeKeyEventHandler() +{ + if (m_keyEventHandler) { + RemoveEventHandler(m_keyEventHandler); + m_keyEventHandler = 0; + } +} + +OSStatus WebNetscapePluginEventHandlerCocoa::TSMEventHandler(EventHandlerCallRef inHandlerRef, EventRef event, void* eventHandler) +{ + return static_cast<WebNetscapePluginEventHandlerCocoa*>(eventHandler)->handleTSMEvent(event); +} + +OSStatus WebNetscapePluginEventHandlerCocoa::handleTSMEvent(EventRef eventRef) +{ + ASSERT(GetEventKind(eventRef) == kEventTextInputUnicodeForKeyEvent); + + // Get the text buffer size. + ByteCount size; + OSStatus result = GetEventParameter(eventRef, kEventParamTextInputSendText, typeUnicodeText, 0, 0, &size, 0); + if (result != noErr) + return result; + + unsigned length = size / sizeof(UniChar); + Vector<UniChar, 16> characters(length); + + // Now get the actual text. + result = GetEventParameter(eventRef, kEventParamTextInputSendText, typeUnicodeText, 0, size, 0, characters.data()); + if (result != noErr) + return result; + + RetainPtr<CFStringRef> text(AdoptCF, CFStringCreateWithCharacters(0, characters.data(), length)); + + NPCocoaEvent event; + + initializeEvent(&event, NPCocoaEventTextInput); + event.data.text.text = (NPNSString*)text.get(); + + sendEvent(&event); + + return noErr; +} + +#endif // __LP64__ + #endif // ENABLE(NETSCAPE_PLUGIN_API) diff --git a/WebKit/mac/Plugins/WebNetscapePluginPackage.m b/WebKit/mac/Plugins/WebNetscapePluginPackage.mm index b3ad0bd..38ddddc 100644 --- a/WebKit/mac/Plugins/WebNetscapePluginPackage.m +++ b/WebKit/mac/Plugins/WebNetscapePluginPackage.mm @@ -35,6 +35,12 @@ #import "WebNetscapeDeprecatedFunctions.h" #import <WebCore/npruntime_impl.h> +#if USE(PLUGIN_HOST_PROCESS) +#import "NetscapePluginHostManager.h" + +using namespace WebKit; +#endif + #ifdef SUPPORT_CFM typedef void (* FunctionPointer)(void); typedef void (* TransitionVector)(void); @@ -288,6 +294,12 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer); { return pluginHostArchitecture; } + +- (void)createPropertyListFile +{ + NetscapePluginHostManager::createPropertyListFile(self); +} + #endif - (void)launchRealPlayer @@ -323,8 +335,8 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer); [self _unloadWithShutdown:YES]; } -- (BOOL)load -{ +- (BOOL)_tryLoad +{ NP_GetEntryPointsFuncPtr NP_GetEntryPoints = NULL; NP_InitializeFuncPtr NP_Initialize = NULL; NPError npErr; @@ -347,7 +359,7 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer); if (isBundle) { #endif if (!CFBundleLoadExecutable(cfBundle)) - goto abort; + return NO; #if !LOG_DISABLED currentTime = CFAbsoluteTimeGetCurrent(); duration = currentTime - start; @@ -359,14 +371,14 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer); if (isCFM) { pluginMainFunc = (MainFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("main") ); if (!pluginMainFunc) - goto abort; + return NO; } else { #endif NP_Initialize = (NP_InitializeFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_Initialize")); NP_GetEntryPoints = (NP_GetEntryPointsFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_GetEntryPoints")); NP_Shutdown = (NPP_ShutdownProcPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_Shutdown")); if (!NP_Initialize || !NP_GetEntryPoints || !NP_Shutdown) - goto abort; + return NO; #ifdef SUPPORT_CFM } } else { @@ -378,17 +390,17 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer); err = FSPathMakeRef((UInt8 *)[path fileSystemRepresentation], &fref, NULL); if (err != noErr) { LOG_ERROR("FSPathMakeRef failed. Error=%d", err); - goto abort; + return NO; } err = FSGetCatalogInfo(&fref, kFSCatInfoNone, NULL, NULL, &spec, NULL); if (err != noErr) { LOG_ERROR("FSGetCatalogInfo failed. Error=%d", err); - goto abort; + return NO; } err = WebGetDiskFragment(&spec, 0, kCFragGoesToEOF, nil, kPrivateCFragCopy, &connID, (Ptr *)&pluginMainFunc, nil); if (err != noErr) { LOG_ERROR("WebGetDiskFragment failed. Error=%d", err); - goto abort; + return NO; } #if !LOG_DISABLED currentTime = CFAbsoluteTimeGetCurrent(); @@ -399,7 +411,7 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer); pluginMainFunc = (MainFuncPtr)functionPointerForTVector((TransitionVector)pluginMainFunc); if (!pluginMainFunc) { - goto abort; + return NO; } // NOTE: pluginMainFunc is freed after it is called. Be sure not to return before that. @@ -480,14 +492,14 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer); NP_Shutdown = (NPP_ShutdownProcPtr)functionPointerForTVector((TransitionVector)shutdownFunction); if (!isBundle) // Don't free pluginMainFunc if we got it from a bundle because it is owned by CFBundle in that case. - free(pluginMainFunc); + free(reinterpret_cast<void*>(pluginMainFunc)); // Workaround for 3270576. The RealPlayer plug-in fails to load if its preference file is out of date. // Launch the RealPlayer application to refresh the file. if (npErr != NPERR_NO_ERROR) { if (npErr == NPERR_MODULE_LOAD_FAILED_ERROR && [[self filename] isEqualToString:RealPlayerPluginFilename]) [self launchRealPlayer]; - goto abort; + return NO; } #if !LOG_DISABLED currentTime = CFAbsoluteTimeGetCurrent(); @@ -514,7 +526,7 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer); pluginFuncs.setvalue = (NPP_SetValueProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.setvalue); // LiveConnect support - pluginFuncs.javaClass = (NPP_GetJavaClassProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.javaClass); + pluginFuncs.javaClass = (JRIGlobalRef)functionPointerForTVector((TransitionVector)pluginFuncs.javaClass); if (pluginFuncs.javaClass) { LOG(LiveConnect, "%@: CFM entry point for NPP_GetJavaClass = %p", [self name], pluginFuncs.javaClass); } else { @@ -586,7 +598,7 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer); LOG(Plugins, "%f NP_Initialize timing started", initializeStart); npErr = NP_Initialize(&browserFuncs); if (npErr != NPERR_NO_ERROR) - goto abort; + return NO; #if !LOG_DISABLED currentTime = CFAbsoluteTimeGetCurrent(); duration = currentTime - initializeStart; @@ -597,7 +609,7 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer); npErr = NP_GetEntryPoints(&pluginFuncs); if (npErr != NPERR_NO_ERROR) - goto abort; + return NO; pluginSize = pluginFuncs.size; pluginVersion = pluginFuncs.version; @@ -617,9 +629,14 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer); #endif LOG(Plugins, "%f Total load time: %f seconds", currentTime, duration); - return [super load]; + return YES; +} + +- (BOOL)load +{ + if ([self _tryLoad]) + return [super load]; -abort: [self _unloadWithShutdown:NO]; return NO; } @@ -724,11 +741,7 @@ TransitionVector tVectorForFunctionPointer(FunctionPointer fp) [self closeResourceFile:resourceRef]; #ifdef SUPPORT_CFM - if (isBundle) -#endif - CFBundleUnloadExecutable(cfBundle); -#ifdef SUPPORT_CFM - else + if (!isBundle) WebCloseConnection(&connID); #endif diff --git a/WebKit/mac/Plugins/WebNetscapePluginView.h b/WebKit/mac/Plugins/WebNetscapePluginView.h index 9d2555b..783b7fb 100644 --- a/WebKit/mac/Plugins/WebNetscapePluginView.h +++ b/WebKit/mac/Plugins/WebNetscapePluginView.h @@ -52,14 +52,12 @@ typedef union PluginPort { NP_CGContext cgPort; } PluginPort; -typedef struct _NPPluginTextInputFuncs NPPluginTextInputFuncs; - // Because the Adobe 7.x Acrobat plug-in has a hard coded check for a view named // "WebNetscapePluginDocumentView", this class must retain the old name in order // for the plug-in to function correctly. (rdar://problem/4699455) #define WebNetscapePluginView WebNetscapePluginDocumentView -@interface WebNetscapePluginView : WebBaseNetscapePluginView<WebPluginManualLoader, NSTextInput> +@interface WebNetscapePluginView : WebBaseNetscapePluginView<WebPluginManualLoader> { RefPtr<WebNetscapePluginStream> _manualStream; #ifndef BUILDING_ON_TIGER @@ -101,9 +99,8 @@ typedef struct _NPPluginTextInputFuncs NPPluginTextInputFuncs; HashSet<RefPtr<WebNetscapePluginStream> > streams; RetainPtr<NSMutableDictionary> _pendingFrameLoads; + BOOL _isFlash; BOOL _isSilverlight; - - NPPluginTextInputFuncs *textInputFuncs; } + (WebNetscapePluginView *)currentPluginView; @@ -117,7 +114,7 @@ typedef struct _NPPluginTextInputFuncs NPPluginTextInputFuncs; attributeKeys:(NSArray *)keys attributeValues:(NSArray *)values loadManually:(BOOL)loadManually - DOMElement:(DOMElement *)anElement; + element:(PassRefPtr<WebCore::HTMLPlugInElement>)element; - (NPP)plugin; diff --git a/WebKit/mac/Plugins/WebNetscapePluginView.mm b/WebKit/mac/Plugins/WebNetscapePluginView.mm index a792e21..cef33a4 100644 --- a/WebKit/mac/Plugins/WebNetscapePluginView.mm +++ b/WebKit/mac/Plugins/WebNetscapePluginView.mm @@ -35,6 +35,7 @@ #import "WebFrameInternal.h" #import "WebFrameView.h" #import "WebGraphicsExtras.h" +#import "WebKitErrorsPrivate.h" #import "WebKitLogging.h" #import "WebKitNSStringExtras.h" #import "WebKitSystemInterface.h" @@ -59,19 +60,22 @@ #import <WebCore/Element.h> #import <WebCore/Frame.h> #import <WebCore/FrameLoader.h> -#import <WebCore/FrameTree.h> +#import <WebCore/FrameTree.h> +#import <WebCore/HTMLPlugInElement.h> #import <WebCore/Page.h> #import <WebCore/PluginMainThreadScheduler.h> #import <WebCore/ScriptController.h> #import <WebCore/SoftLinking.h> #import <WebCore/WebCoreObjCExtras.h> -#import <WebKit/nptextinput.h> +#import <WebCore/WebCoreURLResponse.h> #import <WebKit/DOMPrivate.h> #import <WebKit/WebUIDelegate.h> #import <runtime/InitializeThreading.h> #import <wtf/Assertions.h> #import <objc/objc-runtime.h> +using std::max; + #define LoginWindowDidSwitchFromUserNotification @"WebLoginWindowDidSwitchFromUserNotification" #define LoginWindowDidSwitchToUserNotification @"WebLoginWindowDidSwitchToUserNotification" @@ -91,6 +95,7 @@ static inline bool isDrawingModelQuickDraw(NPDrawingModel drawingModel) - (void)_destroyPlugin; - (NSBitmapImageRep *)_printedPluginBitmap; - (void)_redeliverStream; +- (BOOL)_shouldCancelSrcStream; @end static WebNetscapePluginView *currentPluginView = nil; @@ -489,6 +494,11 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) #endif /* NP_NO_QUICKDRAW */ case NPDrawingModelCoreGraphics: { + if (![self canDraw]) { + portState = NULL; + break; + } + ASSERT([NSView focusView] == self); CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]); @@ -620,10 +630,6 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) if (!page) return NO; - bool wasDeferring = page->defersLoading(); - if (!wasDeferring) - page->setDefersLoading(true); - // Can only send drawRect (updateEvt) to CoreGraphics plugins when actually drawing ASSERT((drawingModel != NPDrawingModelCoreGraphics) || !eventIsDrawRect || [NSView focusView] == self); @@ -667,9 +673,6 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) free(portState); } - if (!wasDeferring) - page->setDefersLoading(false); - return acceptedEvent; } @@ -894,10 +897,18 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) { // A plug-in can only update if it's (1) already been started (2) isn't stopped // and (3) is able to draw on-screen. To meet condition (3) the plug-in must not - // be hidden and be attached to a window. QuickDraw plug-ins are an important - // excpetion to rule (3) because they manually must be told when to stop writing + // be hidden and be attached to a window. There are two exceptions to this rule: + // + // Exception 1: QuickDraw plug-ins must be manually told when to stop writing // bits to the window backing store, thus to do so requires a new call to // NPP_SetWindow() with an empty NPWindow struct. + // + // Exception 2: CoreGraphics plug-ins expect to have their drawable area updated + // when they are moved to a background tab, via a NPP_SetWindow call. This is + // accomplished by allowing -saveAndSetNewPortStateForUpdate to "clip-out" the window's + // clipRect. Flash is curently an exception to this. See 6453738. + // + if (!_isStarted) return; @@ -907,9 +918,11 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) #else if (drawingModel == NPDrawingModelQuickDraw) [self tellQuickTimeToChill]; - else if (drawingModel == NPDrawingModelCoreGraphics && ![self canDraw]) + else if (drawingModel == NPDrawingModelCoreGraphics && ![self canDraw] && _isFlash) { + // The Flash plug-in does not expect an NPP_SetWindow call from WebKit in this case. + // See Exception 2 above. return; - + } #endif // NP_NO_QUICKDRAW BOOL didLockFocus = [NSView focusView] != self && [self lockFocusIfCanDraw]; @@ -920,7 +933,9 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) [self restorePortState:portState]; if (portState != (PortState)1) free(portState); - } + } else if (drawingModel == NPDrawingModelCoreGraphics) + [self setWindowIfNecessary]; + if (didLockFocus) [self unlockFocus]; } @@ -938,11 +953,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) NPError npErr; ASSERT(!inSetWindow); - inSetWindow = YES; - - // A CoreGraphics plugin's window may only be set while the plugin is being updated - ASSERT((drawingModel != NPDrawingModelCoreGraphics) || [NSView focusView] == self); - + inSetWindow = YES; [self willCallPlugInFunction]; { JSC::JSLock::DropAllLocks dropAllLocks(false); @@ -961,8 +972,9 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) #endif /* NP_NO_QUICKDRAW */ case NPDrawingModelCoreGraphics: - LOG(Plugins, "NPP_SetWindow (CoreGraphics): %d, window=%p, context=%p, window.x:%d window.y:%d window.width:%d window.height:%d", - npErr, nPort.cgPort.window, nPort.cgPort.context, (int)window.x, (int)window.y, (int)window.width, (int)window.height); + LOG(Plugins, "NPP_SetWindow (CoreGraphics): %d, window=%p, context=%p, window.x:%d window.y:%d window.width:%d window.height:%d window.clipRect size:%dx%d", + npErr, nPort.cgPort.window, nPort.cgPort.context, (int)window.x, (int)window.y, (int)window.width, (int)window.height, + window.clipRect.right - window.clipRect.left, window.clipRect.bottom - window.clipRect.top); break; case NPDrawingModelCoreAnimation: @@ -1056,19 +1068,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) // Create the event handler _eventHandler.set(WebNetscapePluginEventHandler::create(self)); - - // Get the text input vtable - if (eventModel == NPEventModelCocoa) { - [self willCallPlugInFunction]; - { - JSC::JSLock::DropAllLocks dropAllLocks(false); - NPPluginTextInputFuncs *value = 0; - if (![_pluginPackage.get() pluginFuncs]->getvalue(plugin, NPPVpluginTextInputFuncs, &value) == NPERR_NO_ERROR && value) - textInputFuncs = value; - } - [self didCallPlugInFunction]; - } - + return YES; } @@ -1076,14 +1076,19 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) - (void)setLayer:(CALayer *)newLayer { [super setLayer:newLayer]; - - if (_pluginLayer) + + if (_pluginLayer) { + _pluginLayer.get().autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable; [newLayer addSublayer:_pluginLayer.get()]; + } } #endif - (void)loadStream { + if ([self _shouldCancelSrcStream]) + return; + if (_loadManually) { [self _redeliverStream]; return; @@ -1136,8 +1141,6 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) [_pluginPackage.get() close]; _eventHandler.clear(); - - textInputFuncs = 0; } - (NPEventModel)eventModel @@ -1150,7 +1153,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) return plugin; } -- (void)setAttributeKeys:(NSArray *)keys andValues:(NSArray *)values; +- (void)setAttributeKeys:(NSArray *)keys andValues:(NSArray *)values { ASSERT([keys count] == [values count]); @@ -1203,9 +1206,9 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) attributeKeys:(NSArray *)keys attributeValues:(NSArray *)values loadManually:(BOOL)loadManually - DOMElement:(DOMElement *)element + element:(PassRefPtr<WebCore::HTMLPlugInElement>)element { - self = [super initWithFrame:frame pluginPackage:pluginPackage URL:URL baseURL:baseURL MIMEType:MIME attributeKeys:keys attributeValues:values loadManually:loadManually DOMElement:element]; + self = [super initWithFrame:frame pluginPackage:pluginPackage URL:URL baseURL:baseURL MIMEType:MIME attributeKeys:keys attributeValues:values loadManually:loadManually element:element]; if (!self) return nil; @@ -1358,7 +1361,20 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) return; if (!_manualStream->plugin()) { - + // Check if the load should be cancelled + if ([self _shouldCancelSrcStream]) { + NSURLResponse *response = [[self dataSource] response]; + + NSError *error = [[NSError alloc] _initWithPluginErrorCode:WebKitErrorPlugInWillHandleLoad + contentURL:[response URL] + pluginPageURL:nil + pluginName:nil // FIXME: Get this from somewhere + MIMEType:[response _webcore_MIMEType]]; + [[self dataSource] _documentLoader]->cancelMainResourceLoad(error); + [error release]; + return; + } + _manualStream->setRequestURL([[[self dataSource] request] URL]); _manualStream->setPlugin([self plugin]); ASSERT(_manualStream->plugin()); @@ -1392,160 +1408,11 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) _manualStream->didFinishLoading(0); } -#pragma mark NSTextInput implementation - - (NSTextInputContext *)inputContext { -#ifndef NP_NO_CARBON - if (!_isStarted || eventModel == NPEventModelCarbon) - return nil; -#endif - - return [super inputContext]; -} - -- (BOOL)hasMarkedText -{ - ASSERT(eventModel == NPEventModelCocoa); - ASSERT(_isStarted); - - if (textInputFuncs && textInputFuncs->hasMarkedText) - return textInputFuncs->hasMarkedText(plugin); - - return NO; -} - -- (void)insertText:(id)aString -{ - ASSERT(eventModel == NPEventModelCocoa); - ASSERT(_isStarted); - - if (textInputFuncs && textInputFuncs->insertText) - textInputFuncs->insertText(plugin, aString); -} - -- (NSRange)markedRange -{ - ASSERT(eventModel == NPEventModelCocoa); - ASSERT(_isStarted); - - if (textInputFuncs && textInputFuncs->markedRange) - return textInputFuncs->markedRange(plugin); - - return NSMakeRange(NSNotFound, 0); -} - -- (NSRange)selectedRange -{ - ASSERT(eventModel == NPEventModelCocoa); - ASSERT(_isStarted); - - if (textInputFuncs && textInputFuncs->selectedRange) - return textInputFuncs->selectedRange(plugin); - - return NSMakeRange(NSNotFound, 0); -} - -- (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange -{ - ASSERT(eventModel == NPEventModelCocoa); - ASSERT(_isStarted); - - if (textInputFuncs && textInputFuncs->setMarkedText) - textInputFuncs->setMarkedText(plugin, aString, selRange); -} - -- (void)unmarkText -{ - ASSERT(eventModel == NPEventModelCocoa); - ASSERT(_isStarted); - - if (textInputFuncs && textInputFuncs->unmarkText) - textInputFuncs->unmarkText(plugin); -} - -- (NSArray *)validAttributesForMarkedText -{ - ASSERT(eventModel == NPEventModelCocoa); - ASSERT(_isStarted); - - if (textInputFuncs && textInputFuncs->validAttributesForMarkedText) - return textInputFuncs->validAttributesForMarkedText(plugin); - - return [NSArray array]; -} - -- (NSAttributedString *)attributedSubstringFromRange:(NSRange)theRange -{ - ASSERT(eventModel == NPEventModelCocoa); - ASSERT(_isStarted); - - if (textInputFuncs && textInputFuncs->attributedSubstringFromRange) - return textInputFuncs->attributedSubstringFromRange(plugin, theRange); - return nil; } -- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint -{ - ASSERT(eventModel == NPEventModelCocoa); - ASSERT(_isStarted); - - if (textInputFuncs && textInputFuncs->characterIndexForPoint) { - // Convert the point to window coordinates - NSPoint point = [[self window] convertScreenToBase:thePoint]; - - // And view coordinates - point = [self convertPoint:point fromView:nil]; - - return textInputFuncs->characterIndexForPoint(plugin, point); - } - - return NSNotFound; -} - -- (void)doCommandBySelector:(SEL)aSelector -{ - ASSERT(eventModel == NPEventModelCocoa); - ASSERT(_isStarted); - - if (textInputFuncs && textInputFuncs->doCommandBySelector) - textInputFuncs->doCommandBySelector(plugin, aSelector); -} - -- (NSRect)firstRectForCharacterRange:(NSRange)theRange -{ - ASSERT(eventModel == NPEventModelCocoa); - ASSERT(_isStarted); - - if (textInputFuncs && textInputFuncs->firstRectForCharacterRange) { - NSRect rect = textInputFuncs->firstRectForCharacterRange(plugin, theRange); - - // Convert the rect to window coordinates - rect = [self convertRect:rect toView:nil]; - - // Convert the rect location to screen coordinates - rect.origin = [[self window] convertBaseToScreen:rect.origin]; - - return rect; - } - - return NSZeroRect; -} - -// test for 10.4 because of <rdar://problem/4243463> -#ifdef BUILDING_ON_TIGER -- (long)conversationIdentifier -{ - return (long)self; -} -#else -- (NSInteger)conversationIdentifier -{ - return (NSInteger)self; -} -#endif - @end @implementation WebNetscapePluginView (WebNPPCallbacks) @@ -1945,11 +1812,6 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) (float)invalidRect->right - invalidRect->left, (float)invalidRect->bottom - invalidRect->top)]; } --(BOOL)isOpaque -{ - return YES; -} - - (void)invalidateRegion:(NPRegion)invalidRegion { LOG(Plugins, "NPN_InvalidateRegion"); @@ -1986,18 +1848,6 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) [[self window] displayIfNeeded]; } -static NPBrowserTextInputFuncs *browserTextInputFuncs() -{ - static NPBrowserTextInputFuncs inputFuncs = { - 0, - sizeof(NPBrowserTextInputFuncs), - NPN_MarkedTextAbandoned, - NPN_MarkedTextSelectionChanged - }; - - return &inputFuncs; -} - - (NPError)getVariable:(NPNVariable)variable value:(void *)value { switch (variable) { @@ -2021,7 +1871,7 @@ static NPBrowserTextInputFuncs *browserTextInputFuncs() if (!_element) return NPERR_GENERIC_ERROR; - NPObject *plugInScriptObject = (NPObject *)[_element.get() _NPObject]; + NPObject *plugInScriptObject = _element->getNPObject(); // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess> if (plugInScriptObject) @@ -2082,14 +1932,7 @@ static NPBrowserTextInputFuncs *browserTextInputFuncs() *(NPBool *)value = TRUE; return NPERR_NO_ERROR; } - - case NPNVbrowserTextInputFuncs: - { - if (eventModel == NPEventModelCocoa) { - *(NPBrowserTextInputFuncs **)value = browserTextInputFuncs(); - return NPERR_NO_ERROR; - } - } + default: break; } @@ -2205,6 +2048,19 @@ static NPBrowserTextInputFuncs *browserTextInputFuncs() @implementation WebNetscapePluginView (Internal) +- (BOOL)_shouldCancelSrcStream +{ + ASSERT(_isStarted); + + // Check if we should cancel the load + NPBool cancelSrcStream = 0; + if ([_pluginPackage.get() pluginFuncs]->getvalue && + [_pluginPackage.get() pluginFuncs]->getvalue(plugin, NPPVpluginCancelSrcStream, &cancelSrcStream) == NPERR_NO_ERROR && cancelSrcStream) + return YES; + + return NO; +} + - (NPError)_createPlugin { plugin = (NPP)calloc(1, sizeof(NPP_t)); @@ -2217,6 +2073,7 @@ static NPBrowserTextInputFuncs *browserTextInputFuncs() PluginMainThreadScheduler::scheduler().registerPlugin(plugin); + _isFlash = [[[_pluginPackage.get() bundle] bundleIdentifier] isEqualToString:@"com.macromedia.Flash Player.plugin"]; _isSilverlight = [[[_pluginPackage.get() bundle] bundleIdentifier] isEqualToString:@"com.microsoft.SilverlightPlugin"]; [[self class] setCurrentPluginView:self]; diff --git a/WebKit/mac/Plugins/WebPlugin.h b/WebKit/mac/Plugins/WebPlugin.h index bd0600e..797634f 100644 --- a/WebKit/mac/Plugins/WebPlugin.h +++ b/WebKit/mac/Plugins/WebPlugin.h @@ -100,7 +100,7 @@ @discussion This method is only sent to the plug-in if the WebPlugInShouldLoadMainResourceKey argument passed to the plug-in was NO. */ -- (void)webPlugInMainResourceDidReceiveResponse:(NSURLResponse *)response WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_AFTER_WEBKIT_VERSION_3_1); +- (void)webPlugInMainResourceDidReceiveResponse:(NSURLResponse *)response WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_IN_WEBKIT_VERSION_4_0); /*! @method webPlugInMainResourceDidReceiveData: @@ -109,7 +109,7 @@ @discussion This method is only sent to the plug-in if the WebPlugInShouldLoadMainResourceKey argument passed to the plug-in was NO. */ -- (void)webPlugInMainResourceDidReceiveData:(NSData *)data WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_AFTER_WEBKIT_VERSION_3_1); +- (void)webPlugInMainResourceDidReceiveData:(NSData *)data WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_IN_WEBKIT_VERSION_4_0); /*! @method webPlugInMainResourceDidFailWithError: @@ -118,7 +118,7 @@ @discussion This method is only sent to the plug-in if the WebPlugInShouldLoadMainResourceKey argument passed to the plug-in was NO. */ -- (void)webPlugInMainResourceDidFailWithError:(NSError *)error WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_AFTER_WEBKIT_VERSION_3_1); +- (void)webPlugInMainResourceDidFailWithError:(NSError *)error WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_IN_WEBKIT_VERSION_4_0); /*! @method webPlugInMainResourceDidFinishLoading @@ -127,6 +127,6 @@ @discussion This method is only sent to the plug-in if the WebPlugInShouldLoadMainResourceKey argument passed to the plug-in was NO. */ -- (void)webPlugInMainResourceDidFinishLoading WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_AFTER_WEBKIT_VERSION_3_1); +- (void)webPlugInMainResourceDidFinishLoading WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_IN_WEBKIT_VERSION_4_0); @end diff --git a/WebKit/mac/Plugins/WebPluginContainerPrivate.h b/WebKit/mac/Plugins/WebPluginContainerPrivate.h index c9d64d5..af7251d 100644 --- a/WebKit/mac/Plugins/WebPluginContainerPrivate.h +++ b/WebKit/mac/Plugins/WebPluginContainerPrivate.h @@ -28,10 +28,24 @@ #import <Cocoa/Cocoa.h> +#if !defined(ENABLE_PLUGIN_PROXY_FOR_VIDEO) +#define ENABLE_PLUGIN_PROXY_FOR_VIDEO 1 +#endif + +#if ENABLE_PLUGIN_PROXY_FOR_VIDEO +@class WebMediaPlayerProxy; +#endif + @interface NSObject (WebPlugInContainerPrivate) - (id)_webPluginContainerCheckIfAllowedToLoadRequest:(NSURLRequest *)Request inFrame:(NSString *)target resultObject:(id)obj selector:(SEL)selector; - (void)_webPluginContainerCancelCheckIfAllowedToLoadRequest:(id)checkIdentifier; +#if ENABLE_PLUGIN_PROXY_FOR_VIDEO +- (void)_webPluginContainerSetMediaPlayerProxy:(WebMediaPlayerProxy *)proxy forElement:(DOMElement *)element; + +- (void)_webPluginContainerPostMediaPlayerNotification:(int)notification forElement:(DOMElement *)element; +#endif + @end diff --git a/WebKit/mac/Plugins/WebPluginController.mm b/WebKit/mac/Plugins/WebPluginController.mm index b618bd6..54d9615 100644 --- a/WebKit/mac/Plugins/WebPluginController.mm +++ b/WebKit/mac/Plugins/WebPluginController.mm @@ -31,12 +31,17 @@ #import <Foundation/NSURLRequest.h> #import <runtime/JSLock.h> +#import <WebCore/DocumentLoader.h> +#import <WebCore/DOMNodeInternal.h> #import <WebCore/Frame.h> #import <WebCore/FrameLoader.h> -#import <WebCore/ResourceRequest.h> +#import <WebCore/HTMLMediaElement.h> +#import <WebCore/HTMLNames.h> +#import <WebCore/MediaPlayerProxy.h> #import <WebCore/PlatformString.h> -#import <WebCore/DocumentLoader.h> +#import <WebCore/ResourceRequest.h> #import <WebCore/ScriptController.h> +#import <WebCore/WebCoreURLResponse.h> #import <WebKit/WebDataSourceInternal.h> #import <WebKit/WebFrameInternal.h> #import <WebKit/WebFrameView.h> @@ -55,6 +60,7 @@ #import <WebKit/WebViewInternal.h> using namespace WebCore; +using namespace HTMLNames; @interface NSView (PluginSecrets) - (void)setContainingWindow:(NSWindow *)w; @@ -185,6 +191,10 @@ static NSMutableSet *pluginViews = nil; [_views addObject:view]; [[_documentView _webView] addPluginInstanceView:view]; + BOOL oldDefersCallbacks = [[self webView] defersCallbacks]; + if (!oldDefersCallbacks) + [[self webView] setDefersCallbacks:YES]; + LOG(Plugins, "initializing plug-in %@", view); if ([view respondsToSelector:@selector(webPlugInInitialize)]) { JSC::JSLock::DropAllLocks dropAllLocks(false); @@ -194,6 +204,9 @@ static NSMutableSet *pluginViews = nil; [view pluginInitialize]; } + if (!oldDefersCallbacks) + [[self webView] setDefersCallbacks:NO]; + if (_started) { LOG(Plugins, "starting plug-in %@", view); if ([view respondsToSelector:@selector(webPlugInStart)]) { @@ -406,7 +419,7 @@ static void cancelOutstandingCheck(const void *item, void *context) contentURL:[response URL] pluginPageURL:nil pluginName:nil // FIXME: Get this from somewhere - MIMEType:[response MIMEType]]; + MIMEType:[response _webcore_MIMEType]]; [_dataSource _documentLoader]->cancelMainResourceLoad(error); [error release]; } @@ -430,4 +443,36 @@ static void cancelOutstandingCheck(const void *item, void *context) [pluginView webPlugInMainResourceDidFinishLoading]; } +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) +static WebCore::HTMLMediaElement* mediaProxyClient(DOMElement* element) +{ + if (!element) { + LOG_ERROR("nil element passed"); + return nil; + } + + Node* node = [element _node]; + if (!node || (!node->hasTagName(HTMLNames::videoTag) && !node->hasTagName(HTMLNames::audioTag))) { + LOG_ERROR("invalid media element passed"); + return nil; + } + + return static_cast<WebCore::HTMLMediaElement*>(node); +} + +- (void)_webPluginContainerSetMediaPlayerProxy:(WebMediaPlayerProxy *)proxy forElement:(DOMElement *)element +{ + WebCore::HTMLMediaElement* client = mediaProxyClient(element); + if (client) + client->setMediaPlayerProxy(proxy); +} + +- (void)_webPluginContainerPostMediaPlayerNotification:(int)notification forElement:(DOMElement *)element +{ + WebCore::HTMLMediaElement* client = mediaProxyClient(element); + if (client) + client->deliverNotification((MediaPlayerProxyNotificationType)notification); +} +#endif + @end diff --git a/WebKit/mac/Plugins/WebPluginViewFactory.h b/WebKit/mac/Plugins/WebPluginViewFactory.h index 583a73d..a215906 100644 --- a/WebKit/mac/Plugins/WebPluginViewFactory.h +++ b/WebKit/mac/Plugins/WebPluginViewFactory.h @@ -66,7 +66,7 @@ extern NSString *WebPlugInContainingElementKey; For compatibility with older versions of WebKit, the plug-in should assume that the value for WebPlugInShouldLoadMainResourceKey is NO if it is absent from the arguments dictionary. */ -extern NSString *WebPlugInShouldLoadMainResourceKey AVAILABLE_AFTER_WEBKIT_VERSION_3_1; +extern NSString *WebPlugInShouldLoadMainResourceKey AVAILABLE_IN_WEBKIT_VERSION_4_0; /*! @protocol WebPlugInViewFactory diff --git a/WebKit/mac/Plugins/npapi.mm b/WebKit/mac/Plugins/npapi.mm index eb32c2b..79eff2a 100644 --- a/WebKit/mac/Plugins/npapi.mm +++ b/WebKit/mac/Plugins/npapi.mm @@ -28,7 +28,6 @@ #if ENABLE(NETSCAPE_PLUGIN_API) #import <WebKit/npapi.h> -#import <WebKit/nptextinput.h> #import "WebNetscapePluginView.h" #import "WebKitLogging.h" @@ -192,18 +191,4 @@ NPError NPN_PopUpContextMenu(NPP instance, NPMenu *menu) return [pluginViewForInstance(instance) popUpContextMenu:menu]; } -void NPN_MarkedTextAbandoned(NPP instance) -{ - WebNetscapePluginView *pluginView = pluginViewForInstance(instance); - - [[NSInputManager currentInputManager] markedTextAbandoned:pluginView]; -} - -void NPN_MarkedTextSelectionChanged(NPP instance, NSRange newSel) -{ - WebNetscapePluginView *pluginView = pluginViewForInstance(instance); - - [[NSInputManager currentInputManager] markedTextSelectionChanged:newSel client:pluginView]; -} - #endif diff --git a/WebKit/mac/Plugins/nptextinput.h b/WebKit/mac/Plugins/nptextinput.h deleted file mode 100644 index 2ed3146..0000000 --- a/WebKit/mac/Plugins/nptextinput.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2008, Apple Inc. and The Mozilla Foundation. - * 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. - * 3. Neither the names of Apple Inc. ("Apple") or The Mozilla - * Foundation ("Mozilla") nor the names of their contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE, MOZILLA AND THEIR 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, MOZILLA OR - * THEIR 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 __OBJC__ -#error "npinput.h can only be included from Objective-C code." -#endif - -#ifndef _NP_TEXTINPUT_H_ -#define _NP_TEXTINPUT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include <WebKit/npapi.h> - -#import <Cocoa/Cocoa.h> - -typedef void (*NPP_InsertTextFunc)(NPP npp, id aString); -typedef void (*NPP_DoCommandBySelectorFunc)(NPP npp, SEL aSelector); -typedef void (*NPP_SetMarkedTextFunc)(NPP npp, id aString, NSRange selRange); -typedef void (*NPP_UnmarkTextFunc)(NPP npp); -typedef BOOL (*NPP_HasMarkedTextFunc)(NPP npp); -typedef NSAttributedString * (*NPP_AttributedSubstringFromRangeFunc)(NPP npp, NSRange theRange); -typedef NSRange (*NPP_MarkedRangeFunc)(NPP npp); -typedef NSRange (*NPP_SelectedRangeFunc)(NPP npp); -typedef NSRect (*NPP_FirstRectForCharacterRangeFunc)(NPP npp, NSRange theRange); -typedef unsigned long long (*NPP_CharacterIndexForPointFunc)(NPP npp, NSPoint thePoint); -typedef NSArray *(*NPP_ValidAttributesForMarkedTextFunc)(NPP npp); - -typedef struct _NPPluginTextInputFuncs { - uint16 size; - uint16 version; - - NPP_InsertTextFunc insertText; - NPP_DoCommandBySelectorFunc doCommandBySelector; - NPP_SetMarkedTextFunc setMarkedText; - NPP_UnmarkTextFunc unmarkText; - NPP_HasMarkedTextFunc hasMarkedText; - NPP_AttributedSubstringFromRangeFunc attributedSubstringFromRange; - NPP_MarkedRangeFunc markedRange; - NPP_SelectedRangeFunc selectedRange; - NPP_FirstRectForCharacterRangeFunc firstRectForCharacterRange; - NPP_CharacterIndexForPointFunc characterIndexForPoint; - NPP_ValidAttributesForMarkedTextFunc validAttributesForMarkedText; -} NPPluginTextInputFuncs; - -void NPP_InsertText(NPP npp, id aString); -void NPP_DoCommandBySelector(NPP npp, SEL aSelector); -void NPP_SetMarkedText(NPP npp, id aString, NSRange selRange); -void NPP_UnmarkText(NPP npp); -BOOL NPP_HasMarkedText(NPP npp); -NSAttributedString *NPP_AttributedSubstringFromRange(NPP npp, NSRange theRange); -NSRange NPP_MarkedRange(NPP npp); -NSRange NPP_SelectedRange(NPP npp); -NSRect NPP_FirstRectForCharacterRange(NPP npp, NSRange theRange); -unsigned long long NPP_CharacterIndexForPoint(NPP npp, NSPoint thePoint); -NSArray *NPP_ValidAttributesForMarkedText(NPP npp); - -typedef void (*NPN_MarkedTextAbandonedFunc)(NPP npp); -typedef void (*NPN_MarkedTextSelectionChangedFunc)(NPP npp, NSRange newSel); - -typedef struct _NPBrowserTextInputFuncs { - uint16 size; - uint16 version; - - NPN_MarkedTextAbandonedFunc markedTextAbandoned; - NPN_MarkedTextSelectionChangedFunc markedTextSelectionChanged; -} NPBrowserTextInputFuncs; - -void NPN_MarkedTextAbandoned(NPP npp); -void NPN_MarkedTextSelectionChanged(NPP npp, NSRange newSel); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/WebKit/mac/Storage/WebDatabaseManager.mm b/WebKit/mac/Storage/WebDatabaseManager.mm index fa9eea6..a84f235 100644 --- a/WebKit/mac/Storage/WebDatabaseManager.mm +++ b/WebKit/mac/Storage/WebDatabaseManager.mm @@ -29,6 +29,8 @@ #import "WebDatabaseManagerPrivate.h" #import "WebDatabaseManagerInternal.h" +#if ENABLE(DATABASE) + #import "WebDatabaseTrackerClient.h" #import "WebSecurityOriginInternal.h" @@ -137,3 +139,5 @@ void WebKitInitializeDatabasesIfNecessary() initialized = YES; } + +#endif diff --git a/WebKit/mac/Storage/WebDatabaseManagerInternal.h b/WebKit/mac/Storage/WebDatabaseManagerInternal.h index 2065a4e..6a4ad1d 100644 --- a/WebKit/mac/Storage/WebDatabaseManagerInternal.h +++ b/WebKit/mac/Storage/WebDatabaseManagerInternal.h @@ -26,4 +26,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if ENABLE(DATABASE) + void WebKitInitializeDatabasesIfNecessary(); + +#endif diff --git a/WebKit/mac/Storage/WebDatabaseManagerPrivate.h b/WebKit/mac/Storage/WebDatabaseManagerPrivate.h index faa4e5d..e373b1c 100644 --- a/WebKit/mac/Storage/WebDatabaseManagerPrivate.h +++ b/WebKit/mac/Storage/WebDatabaseManagerPrivate.h @@ -26,6 +26,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if ENABLE(DATABASE) + extern NSString *WebDatabaseDirectoryDefaultsKey; extern NSString *WebDatabaseDisplayNameKey; @@ -62,3 +64,5 @@ extern NSString *WebDatabaseIdentifierKey; - (void)deleteDatabase:(NSString *)databaseIdentifier withOrigin:(WebSecurityOrigin *)origin; @end + +#endif diff --git a/WebKit/mac/Storage/WebDatabaseTrackerClient.h b/WebKit/mac/Storage/WebDatabaseTrackerClient.h index 5db444c..d06cfe9 100644 --- a/WebKit/mac/Storage/WebDatabaseTrackerClient.h +++ b/WebKit/mac/Storage/WebDatabaseTrackerClient.h @@ -26,6 +26,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if ENABLE(DATABASE) + #import <WebCore/DatabaseTrackerClient.h> class WebDatabaseTrackerClient : public WebCore::DatabaseTrackerClient { @@ -38,3 +40,5 @@ public: private: WebDatabaseTrackerClient(); }; + +#endif diff --git a/WebKit/mac/Storage/WebDatabaseTrackerClient.mm b/WebKit/mac/Storage/WebDatabaseTrackerClient.mm index 48530d6..89626fb 100644 --- a/WebKit/mac/Storage/WebDatabaseTrackerClient.mm +++ b/WebKit/mac/Storage/WebDatabaseTrackerClient.mm @@ -28,6 +28,8 @@ #import "WebDatabaseTrackerClient.h" +#if ENABLE(DATABASE) + #import "WebDatabaseManagerPrivate.h" #import "WebSecurityOriginInternal.h" #import <wtf/RetainPtr.h> @@ -67,3 +69,5 @@ void WebDatabaseTrackerClient::dispatchDidModifyDatabase(SecurityOrigin* origin, object:webSecurityOrigin.get() userInfo:userInfo.get()]; } + +#endif diff --git a/WebKit/mac/Storage/WebSecurityOrigin.mm b/WebKit/mac/Storage/WebSecurityOrigin.mm index 85313d0..56a21f5 100644 --- a/WebKit/mac/Storage/WebSecurityOrigin.mm +++ b/WebKit/mac/Storage/WebSecurityOrigin.mm @@ -71,12 +71,20 @@ using namespace WebCore; - (unsigned long long)usage { +#if ENABLE(DATABASE) return DatabaseTracker::tracker().usageForOrigin(reinterpret_cast<SecurityOrigin*>(_private)); +#else + return 0; +#endif } - (unsigned long long)quota { +#if ENABLE(DATABASE) return DatabaseTracker::tracker().quotaForOrigin(reinterpret_cast<SecurityOrigin*>(_private)); +#else + return 0; +#endif } // Sets the storage quota (in bytes) @@ -84,7 +92,9 @@ using namespace WebCore; // This will simply prevent new data from being added to databases in that origin - (void)setQuota:(unsigned long long)quota { +#if ENABLE(DATABASE) DatabaseTracker::tracker().setQuota(reinterpret_cast<SecurityOrigin*>(_private), quota); +#endif } - (BOOL)isEqual:(id)anObject diff --git a/WebKit/mac/Storage/WebSecurityOriginPrivate.h b/WebKit/mac/Storage/WebSecurityOriginPrivate.h index 0796c6e..c7836f8 100644 --- a/WebKit/mac/Storage/WebSecurityOriginPrivate.h +++ b/WebKit/mac/Storage/WebSecurityOriginPrivate.h @@ -49,4 +49,5 @@ // This will simply prevent new data from being added to databases in that origin - (void)setQuota:(unsigned long long)quota; + @end diff --git a/WebKit/mac/WebCoreSupport/WebChromeClient.h b/WebKit/mac/WebCoreSupport/WebChromeClient.h index 29a4c25..6974cb1 100644 --- a/WebKit/mac/WebCoreSupport/WebChromeClient.h +++ b/WebKit/mac/WebCoreSupport/WebChromeClient.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * * Redistribution and use in source and binary forms, with or without @@ -104,9 +104,12 @@ public: virtual void setToolTip(const WebCore::String&); virtual void print(WebCore::Frame*); - +#if ENABLE(DATABASE) virtual void exceededDatabaseQuota(WebCore::Frame*, const WebCore::String& databaseName); - +#endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); +#endif virtual void populateVisitedLinks(); #if ENABLE(DASHBOARD_SUPPORT) @@ -135,6 +138,13 @@ public: virtual void disableSuddenTermination(); virtual void formStateDidChange(const WebCore::Node*) { } +#if USE(ACCELERATED_COMPOSITING) + virtual void attachRootGraphicsLayer(WebCore::Frame*, WebCore::GraphicsLayer*); + virtual void setNeedsOneShotDrawingSynchronization(); +#endif + + virtual void requestGeolocationPermissionForFrame(WebCore::Frame*, WebCore::Geolocation*); + private: WebView *m_webView; }; diff --git a/WebKit/mac/WebCoreSupport/WebChromeClient.mm b/WebKit/mac/WebCoreSupport/WebChromeClient.mm index 6b5d138..2ca86d1 100644 --- a/WebKit/mac/WebCoreSupport/WebChromeClient.mm +++ b/WebKit/mac/WebCoreSupport/WebChromeClient.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * * Redistribution and use in source and binary forms, with or without @@ -34,6 +34,7 @@ #import "WebElementDictionary.h" #import "WebFrameInternal.h" #import "WebFrameView.h" +#import "WebGeolocationInternal.h" #import "WebHTMLViewInternal.h" #import "WebHistoryInternal.h" #import "WebKitSystemInterface.h" @@ -49,6 +50,7 @@ #import <WebCore/FloatRect.h> #import <WebCore/Frame.h> #import <WebCore/FrameLoadRequest.h> +#import <WebCore/Geolocation.h> #import <WebCore/HitTestResult.h> #import <WebCore/IntRect.h> #import <WebCore/Page.h> @@ -61,6 +63,10 @@ #import <wtf/PassRefPtr.h> #import <wtf/Vector.h> +#if USE(ACCELERATED_COMPOSITING) +#import <WebCore/GraphicsLayer.h> +#endif + @interface NSView (WebNSViewDetails) - (NSView *)_findLastViewInKeyViewLoop; @end @@ -494,6 +500,7 @@ void WebChromeClient::print(Frame* frame) CallUIDelegate(m_webView, @selector(webView:printFrameView:), frameView); } +#if ENABLE(DATABASE) void WebChromeClient::exceededDatabaseQuota(Frame* frame, const String& databaseName) { BEGIN_BLOCK_OBJC_EXCEPTIONS; @@ -509,6 +516,14 @@ void WebChromeClient::exceededDatabaseQuota(Frame* frame, const String& database END_BLOCK_OBJC_EXCEPTIONS; } +#endif + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +void WebChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded) +{ + // FIXME: Free some space. +} +#endif void WebChromeClient::populateVisitedLinks() { @@ -643,6 +658,36 @@ void WebChromeClient::enableSuddenTermination() #endif } +#if USE(ACCELERATED_COMPOSITING) +void WebChromeClient::attachRootGraphicsLayer(Frame* frame, GraphicsLayer* graphicsLayer) +{ + WebFrameView *frameView = [kit(frame) frameView]; + WebHTMLView *docView = (WebHTMLView *)[frameView documentView]; + if (graphicsLayer) + [docView attachRootLayer:graphicsLayer->nativeLayer()]; + else + [docView detachRootLayer]; +} + +void WebChromeClient::setNeedsOneShotDrawingSynchronization() +{ + [m_webView _setNeedsOneShotDrawingSynchronization:YES]; +} +#endif + +void WebChromeClient::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + WebSecurityOrigin *webOrigin = [[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:frame->document()->securityOrigin()]; + WebGeolocation *webGeolocation = [[WebGeolocation alloc] _initWithWebCoreGeolocation:geolocation]; + CallUIDelegate(m_webView, @selector(webView:frame:requestGeolocationPermission:securityOrigin:), kit(frame), webGeolocation, webOrigin); + [webOrigin release]; + [webGeolocation release]; + + END_BLOCK_OBJC_EXCEPTIONS; +} + @implementation WebOpenPanelResultListener - (id)initWithChooser:(PassRefPtr<FileChooser>)chooser diff --git a/WebKit/mac/WebCoreSupport/WebEditorClient.h b/WebKit/mac/WebCoreSupport/WebEditorClient.h index 2845b97..fd4b46f 100644 --- a/WebKit/mac/WebCoreSupport/WebEditorClient.h +++ b/WebKit/mac/WebCoreSupport/WebEditorClient.h @@ -101,6 +101,7 @@ public: virtual void learnWord(const WebCore::String&); virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength); virtual void checkGrammarOfString(const UChar*, int length, WTF::Vector<WebCore::GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength); + virtual void checkSpellingAndGrammarOfParagraph(const UChar* text, int length, bool checkGrammar, WTF::Vector<WebCore::TextCheckingResult>& results); virtual void updateSpellingUIWithGrammarString(const WebCore::String&, const WebCore::GrammarDetail&); virtual void updateSpellingUIWithMisspelledWord(const WebCore::String&); virtual void showSpellingUI(bool show); diff --git a/WebKit/mac/WebCoreSupport/WebEditorClient.mm b/WebKit/mac/WebCoreSupport/WebEditorClient.mm index 67d3cc2..9911a32 100644 --- a/WebKit/mac/WebCoreSupport/WebEditorClient.mm +++ b/WebKit/mac/WebCoreSupport/WebEditorClient.mm @@ -80,7 +80,7 @@ WebViewInsertAction kit(EditorInsertAction coreAction) @interface WebEditCommand : NSObject { - EditCommand *m_command; + RefPtr<EditCommand> m_command; } + (WebEditCommand *)commandWithEditCommand:(PassRefPtr<EditCommand>)command; @@ -102,7 +102,7 @@ WebViewInsertAction kit(EditorInsertAction coreAction) { ASSERT(command); [super init]; - m_command = command.releaseRef(); + m_command = command; return self; } @@ -110,15 +110,14 @@ WebViewInsertAction kit(EditorInsertAction coreAction) { if (WebCoreObjCScheduleDeallocateOnMainThread([WebEditCommand class], self)) return; - - m_command->deref(); + [super dealloc]; } - (void)finalize { ASSERT_MAIN_THREAD(); - m_command->deref(); + [super finalize]; } @@ -127,9 +126,9 @@ WebViewInsertAction kit(EditorInsertAction coreAction) return [[[WebEditCommand alloc] initWithEditCommand:command] autorelease]; } -- (EditCommand *)command; +- (EditCommand *)command { - return m_command; + return m_command.get(); } @end @@ -596,6 +595,50 @@ void WebEditorClient::checkGrammarOfString(const UChar* text, int length, Vector #endif } +void WebEditorClient::checkSpellingAndGrammarOfParagraph(const UChar* text, int length, bool checkGrammar, Vector<TextCheckingResult>& results) +{ +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) + NSString *textString = [[NSString alloc] initWithCharactersNoCopy:const_cast<UChar*>(text) length:length freeWhenDone:NO]; + NSTextCheckingTypes checkingTypes = checkGrammar ? (NSTextCheckingTypeOrthography | NSTextCheckingTypeSpelling | NSTextCheckingTypeGrammar) : (NSTextCheckingTypeOrthography | NSTextCheckingTypeSpelling); + NSArray *incomingResults = [[NSSpellChecker sharedSpellChecker] checkString:textString range:NSMakeRange(0, [textString length]) types:checkingTypes options:nil inSpellDocumentWithTag:spellCheckerDocumentTag() orthography:NULL wordCount:NULL]; + [textString release]; + for (NSTextCheckingResult *incomingResult in incomingResults) { + NSRange resultRange = [incomingResult range]; + NSTextCheckingType resultType = [incomingResult resultType]; + ASSERT(resultRange.location != NSNotFound && resultRange.length > 0); + if (NSTextCheckingTypeSpelling == resultType) { + TextCheckingResult result; + result.resultType = 1; + result.location = resultRange.location; + result.length = resultRange.length; + results.append(result); + } else if (checkGrammar && NSTextCheckingTypeGrammar == resultType) { + TextCheckingResult result; + NSArray *details = [incomingResult grammarDetails]; + result.resultType = 2; + result.location = resultRange.location; + result.length = resultRange.length; + for (NSDictionary *incomingDetail in details) { + ASSERT(incomingDetail); + GrammarDetail detail; + NSValue *detailRangeAsNSValue = [incomingDetail objectForKey:NSGrammarRange]; + ASSERT(detailRangeAsNSValue); + NSRange detailNSRange = [detailRangeAsNSValue rangeValue]; + ASSERT(detailNSRange.location != NSNotFound && detailNSRange.length > 0); + detail.location = detailNSRange.location; + detail.length = detailNSRange.length; + detail.userDescription = [incomingDetail objectForKey:NSGrammarUserDescription]; + NSArray *guesses = [incomingDetail objectForKey:NSGrammarCorrections]; + for (NSString *guess in guesses) + detail.guesses.append(String(guess)); + result.details.append(detail); + } + results.append(result); + } + } +#endif +} + void WebEditorClient::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail) { #ifndef BUILDING_ON_TIGER diff --git a/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h index 03c00ee..823e0a4 100644 --- a/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h +++ b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h @@ -139,7 +139,7 @@ private: virtual void committedLoad(WebCore::DocumentLoader*, const char*, int); virtual void finishedLoading(WebCore::DocumentLoader*); virtual void updateGlobalHistory(); - virtual void updateGlobalHistoryForRedirectWithoutHistoryItem(); + virtual void updateGlobalHistoryRedirectLinks(); virtual bool shouldGoToHistoryItem(WebCore::HistoryItem*) const; @@ -177,17 +177,18 @@ private: virtual PassRefPtr<WebCore::Frame> createFrame(const WebCore::KURL& url, const WebCore::String& name, WebCore::HTMLFrameOwnerElement*, const WebCore::String& referrer, bool allowsScrolling, int marginWidth, int marginHeight); - virtual WebCore::Widget* createPlugin(const WebCore::IntSize&, WebCore::Element*, const WebCore::KURL&, const Vector<WebCore::String>&, + virtual WebCore::Widget* createPlugin(const WebCore::IntSize&, WebCore::HTMLPlugInElement*, const WebCore::KURL&, const Vector<WebCore::String>&, const Vector<WebCore::String>&, const WebCore::String&, bool); virtual void redirectDataToPlugin(WebCore::Widget* pluginWidget); - virtual WebCore::Widget* createJavaAppletWidget(const WebCore::IntSize&, WebCore::Element*, const WebCore::KURL& baseURL, + virtual WebCore::Widget* createJavaAppletWidget(const WebCore::IntSize&, WebCore::HTMLAppletElement*, const WebCore::KURL& baseURL, const Vector<WebCore::String>& paramNames, const Vector<WebCore::String>& paramValues); virtual WebCore::ObjectContentType objectContentType(const WebCore::KURL& url, const WebCore::String& mimeType); virtual WebCore::String overrideMediaType() const; virtual void windowObjectCleared(); + virtual void documentElementAvailable(); virtual void didPerformFirstNavigation() const; virtual void registerForIconNotification(bool listen); diff --git a/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm index 6f02729..95ac174 100644 --- a/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm +++ b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm @@ -84,11 +84,13 @@ #import <WebCore/FrameLoaderTypes.h> #import <WebCore/FrameTree.h> #import <WebCore/FrameView.h> +#import <WebCore/HTMLAppletElement.h> #import <WebCore/HTMLHeadElement.h> #import <WebCore/HTMLFormElement.h> #import <WebCore/HTMLFrameElement.h> #import <WebCore/HTMLFrameOwnerElement.h> #import <WebCore/HTMLNames.h> +#import <WebCore/HTMLPlugInElement.h> #import <WebCore/HistoryItem.h> #import <WebCore/HitTestResult.h> #import <WebCore/IconDatabase.h> @@ -786,39 +788,27 @@ void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader) void WebFrameLoaderClient::updateGlobalHistory() { DocumentLoader* loader = core(m_webFrame.get())->loader()->documentLoader(); - - if (loader->urlForHistoryReflectsServerRedirect()) { - [[WebHistory optionalSharedHistory] _visitedURL:loader->urlForHistory() - withTitle:loader->title() - method:loader->request().httpMethod() - wasFailure:loader->urlForHistoryReflectsFailure() - serverRedirectURL:loader->url() - isClientRedirect:NO]; - return; - } - - if (loader->urlForHistoryReflectsClientRedirect()) { - [[WebHistory optionalSharedHistory] _visitedURL:loader->urlForHistory() - withTitle:loader->title() - method:loader->request().httpMethod() - wasFailure:loader->urlForHistoryReflectsFailure() - serverRedirectURL:nil - isClientRedirect:YES]; - return; - } - [[WebHistory optionalSharedHistory] _visitedURL:loader->urlForHistory() withTitle:loader->title() - method:loader->request().httpMethod() - wasFailure:loader->urlForHistoryReflectsFailure() - serverRedirectURL:nil - isClientRedirect:NO]; + method:loader->originalRequestCopy().httpMethod() + wasFailure:loader->urlForHistoryReflectsFailure()]; + + updateGlobalHistoryRedirectLinks(); } -void WebFrameLoaderClient::updateGlobalHistoryForRedirectWithoutHistoryItem() +void WebFrameLoaderClient::updateGlobalHistoryRedirectLinks() { DocumentLoader* loader = core(m_webFrame.get())->loader()->documentLoader(); - [[WebHistory optionalSharedHistory] _visitedURLForRedirectWithoutHistoryItem:loader->url()]; + + if (!loader->clientRedirectSourceForHistory().isNull()) { + if (WebHistoryItem *item = [[WebHistory optionalSharedHistory] _itemForURLString:loader->clientRedirectSourceForHistory()]) + core(item)->addRedirectURL(loader->clientRedirectDestinationForHistory()); + } + + if (!loader->serverRedirectSourceForHistory().isNull()) { + if (WebHistoryItem *item = [[WebHistory optionalSharedHistory] _itemForURLString:loader->serverRedirectSourceForHistory()]) + core(item)->addRedirectURL(loader->serverRedirectDestinationForHistory()); + } } bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const @@ -907,13 +897,8 @@ void WebFrameLoaderClient::frameLoadCompleted() // See WebFrameLoaderClient::provisionalLoadStarted. if ([getWebView(m_webFrame.get()) drawsBackground]) [[m_webFrame->_private->webFrameView _scrollView] setDrawsBackground:YES]; - - // Even if already complete, we might have set a previous item on a frame that - // didn't do any data loading on the past transaction. Make sure to clear these out. - core(m_webFrame.get())->loader()->setPreviousHistoryItem(0); } - void WebFrameLoaderClient::saveViewStateToItem(HistoryItem* item) { if (!item) @@ -1399,7 +1384,7 @@ static Class netscapePluginViewClass() #endif } -Widget* WebFrameLoaderClient::createPlugin(const IntSize& size, Element* element, const KURL& url, +Widget* WebFrameLoaderClient::createPlugin(const IntSize& size, HTMLPlugInElement* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually) { BEGIN_BLOCK_OBJC_EXCEPTIONS; @@ -1442,6 +1427,12 @@ Widget* WebFrameLoaderClient::createPlugin(const IntSize& size, Element* element } NSString *extension = [[URL path] pathExtension]; +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) + // don't allow proxy plug-in selection by file extension + if (element->hasTagName(videoTag) || element->hasTagName(audioTag)) + extension = @""; +#endif + if (!pluginPackage && [extension length] != 0) { pluginPackage = [webView _pluginForExtension:extension]; if (pluginPackage) { @@ -1470,7 +1461,7 @@ Widget* WebFrameLoaderClient::createPlugin(const IntSize& size, Element* element attributeKeys:kit(paramNames) attributeValues:kit(paramValues) loadManually:loadManually - DOMElement:kit(element)] autorelease]; + element:element] autorelease]; return new NetscapePluginWidget(pluginView); } @@ -1524,7 +1515,7 @@ void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget) END_BLOCK_OBJC_EXCEPTIONS; } -Widget* WebFrameLoaderClient::createJavaAppletWidget(const IntSize& size, Element* element, const KURL& baseURL, +Widget* WebFrameLoaderClient::createJavaAppletWidget(const IntSize& size, HTMLAppletElement* element, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues) { BEGIN_BLOCK_OBJC_EXCEPTIONS; @@ -1548,7 +1539,7 @@ Widget* WebFrameLoaderClient::createJavaAppletWidget(const IntSize& size, Elemen } if (parameterValue(paramNames, paramValues, "height").isNull()) { [names addObject:@"height"]; - [values addObject:[NSString stringWithFormat:@"%d", size.width()]]; + [values addObject:[NSString stringWithFormat:@"%d", size.height()]]; } view = pluginView(m_webFrame.get(), (WebPluginPackage *)pluginPackage, names, values, baseURL, kit(element), NO); } @@ -1562,7 +1553,7 @@ Widget* WebFrameLoaderClient::createJavaAppletWidget(const IntSize& size, Elemen attributeKeys:kit(paramNames) attributeValues:kit(paramValues) loadManually:NO - DOMElement:kit(element)] autorelease]; + element:element] autorelease]; } else { ASSERT_NOT_REACHED(); } @@ -1596,6 +1587,9 @@ String WebFrameLoaderClient::overrideMediaType() const return String(); } +void WebFrameLoaderClient::documentElementAvailable() { +} + void WebFrameLoaderClient::windowObjectCleared() { Frame *frame = core(m_webFrame.get()); diff --git a/WebKit/mac/WebCoreSupport/WebGeolocation.mm b/WebKit/mac/WebCoreSupport/WebGeolocation.mm new file mode 100644 index 0000000..89d6ad9 --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebGeolocation.mm @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2009 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebGeolocationInternal.h" +#import <WebCore/Geolocation.h> + +using namespace WebCore; + +@implementation WebGeolocation (WebInternal) + +- (id)_initWithWebCoreGeolocation:(WebCoreGeolocation *)geolocation +{ + ASSERT(geolocation); + + self = [super init]; + if (self) { + geolocation->ref(); + _private = reinterpret_cast<WebGeolocationPrivate*>(geolocation); + } + return self; +} + +@end + +@implementation WebGeolocation + +- (BOOL)shouldClearCache +{ + return reinterpret_cast<Geolocation*>(_private)->shouldClearCache(); +} + +- (void)setIsAllowed:(BOOL)allowed +{ + reinterpret_cast<Geolocation*>(_private)->setIsAllowed(allowed); +} + +- (void)dealloc +{ + if (_private) + reinterpret_cast<Geolocation*>(_private)->deref(); + [super dealloc]; +} + +@end diff --git a/WebKit/mac/WebCoreSupport/WebGeolocationInternal.h b/WebKit/mac/WebCoreSupport/WebGeolocationInternal.h new file mode 100644 index 0000000..8145d4d --- /dev/null +++ b/WebKit/mac/WebCoreSupport/WebGeolocationInternal.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2009 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebGeolocationPrivate.h" + +namespace WebCore { + class Geolocation; +} + +typedef WebCore::Geolocation WebCoreGeolocation; + +@interface WebGeolocation (WebInternal) + +- (id)_initWithWebCoreGeolocation:(WebCoreGeolocation *)geolocation; + +@end diff --git a/WebKit/android/plugins/sample/main.h b/WebKit/mac/WebCoreSupport/WebGeolocationPrivate.h index 8bf520e..5807f7c 100644 --- a/WebKit/android/plugins/sample/main.h +++ b/WebKit/mac/WebCoreSupport/WebGeolocationPrivate.h @@ -1,30 +1,37 @@ /* - * Copyright 2008, The Android Open Source Project + * Copyright (C) 2009 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * * Redistributions of source code must retain the above copyright + * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright + * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#include <npapi.h> -#include <npfunctions.h> -#include <npruntime.h> -extern NPNetscapeFuncs* browser; +#import <Foundation/Foundation.h> + +@class WebGeolocationPrivate; + +@interface WebGeolocation : NSObject { +@private + WebGeolocationPrivate *_private; +} + +- (BOOL)shouldClearCache; +- (void)setIsAllowed:(BOOL)allowed; +@end diff --git a/WebKit/mac/WebCoreSupport/WebInspectorClient.h b/WebKit/mac/WebCoreSupport/WebInspectorClient.h index 6a807c7..41a8fa5 100644 --- a/WebKit/mac/WebCoreSupport/WebInspectorClient.h +++ b/WebKit/mac/WebCoreSupport/WebInspectorClient.h @@ -48,6 +48,8 @@ public: virtual WebCore::Page* createPage(); virtual WebCore::String localizedStringsURL(); + virtual WebCore::String hiddenPanels(); + virtual void showWindow(); virtual void closeWindow(); diff --git a/WebKit/mac/WebCoreSupport/WebInspectorClient.mm b/WebKit/mac/WebCoreSupport/WebInspectorClient.mm index 03d85ae..cc4cfdb 100644 --- a/WebKit/mac/WebCoreSupport/WebInspectorClient.mm +++ b/WebKit/mac/WebCoreSupport/WebInspectorClient.mm @@ -94,6 +94,14 @@ String WebInspectorClient::localizedStringsURL() return String(); } +String WebInspectorClient::hiddenPanels() +{ + NSString *hiddenPanels = [[NSUserDefaults standardUserDefaults] stringForKey:@"WebKitInspectorHiddenPanels"]; + if (hiddenPanels) + return hiddenPanels; + return String(); +} + void WebInspectorClient::showWindow() { updateWindowTitle(); diff --git a/WebKit/mac/WebCoreSupport/WebPasteboardHelper.mm b/WebKit/mac/WebCoreSupport/WebPasteboardHelper.mm index 274045f..a8c49ff 100644 --- a/WebKit/mac/WebCoreSupport/WebPasteboardHelper.mm +++ b/WebKit/mac/WebCoreSupport/WebPasteboardHelper.mm @@ -53,7 +53,7 @@ String WebPasteboardHelper::plainTextFromPasteboard(const NSPasteboard *pasteboa NSArray *types = [pasteboard types]; if ([types containsObject:NSStringPboardType]) - return [pasteboard stringForType:NSStringPboardType]; + return [[pasteboard stringForType:NSStringPboardType] precomposedStringWithCanonicalMapping]; NSAttributedString *attributedString = nil; NSString *string; @@ -63,15 +63,15 @@ String WebPasteboardHelper::plainTextFromPasteboard(const NSPasteboard *pasteboa if (!attributedString && [types containsObject:NSRTFPboardType]) attributedString = [[NSAttributedString alloc] initWithRTF:[pasteboard dataForType:NSRTFPboardType] documentAttributes:nil]; if (attributedString) { - string = [[attributedString string] copy]; + string = [[attributedString string] precomposedStringWithCanonicalMapping]; [attributedString release]; - return [string autorelease]; + return string; } if ([types containsObject:NSFilenamesPboardType]) { string = [[pasteboard propertyListForType:NSFilenamesPboardType] componentsJoinedByString:@"\n"]; if (string) - return string; + return [string precomposedStringWithCanonicalMapping]; } NSURL *URL; diff --git a/WebKit/mac/WebCoreSupport/WebViewFactory.mm b/WebKit/mac/WebCoreSupport/WebViewFactory.mm index 9ccdfff..ea82acc 100644 --- a/WebKit/mac/WebCoreSupport/WebViewFactory.mm +++ b/WebKit/mac/WebCoreSupport/WebViewFactory.mm @@ -341,12 +341,16 @@ - (NSString *)contextMenuItemTagWritingDirectionMenu { +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) + return UI_STRING("Paragraph Direction", "Paragraph direction context sub-menu item"); +#else return UI_STRING("Writing Direction", "Writing direction context sub-menu item"); +#endif } - (NSString *)contextMenuItemTagTextDirectionMenu { - return UI_STRING("Text Direction", "Text direction context sub-menu item"); + return UI_STRING("Selection Direction", "Selection direction context sub-menu item"); } - (NSString *)contextMenuItemTagDefaultDirection diff --git a/WebKit/mac/WebKit.exp b/WebKit/mac/WebKit.exp index d166894..cb26943 100644 --- a/WebKit/mac/WebKit.exp +++ b/WebKit/mac/WebKit.exp @@ -1,3 +1,4 @@ +.objc_class_name_WebApplicationCache .objc_class_name_WebArchive .objc_class_name_WebBackForwardList .objc_class_name_WebCache diff --git a/WebKit/mac/WebKitPrefix.h b/WebKit/mac/WebKitPrefix.h index 3e26ab4..4ecd713 100644 --- a/WebKit/mac/WebKitPrefix.h +++ b/WebKit/mac/WebKitPrefix.h @@ -68,20 +68,20 @@ typedef float CGFloat; #ifdef __OBJC__ #import <Cocoa/Cocoa.h> -#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 -#define BUILDING_ON_TIGER 1 -#elif MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 -#define BUILDING_ON_LEOPARD 1 -#endif #endif +#include <wtf/Platform.h> + #include "EmptyProtocolDefinitions.h" #if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_TIGER) && defined(__x86_64__) #define WTF_USE_PLUGIN_HOST_PROCESS 1 #endif -#include <wtf/Platform.h> +// Accelerated compositing (also needs to be set in WebCore/config.h) +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) +#define WTF_USE_ACCELERATED_COMPOSITING 0 +#endif /* WebKit has no way to pull settings from WebCore/config.h for now */ /* so we assume WebKit is always being compiled on top of JavaScriptCore */ diff --git a/WebKit/mac/WebView/WebArchive.mm b/WebKit/mac/WebView/WebArchive.mm index c6cc9b1..89c8335 100644 --- a/WebKit/mac/WebView/WebArchive.mm +++ b/WebKit/mac/WebView/WebArchive.mm @@ -53,7 +53,7 @@ static NSString * const WebSubframeArchivesKey = @"WebSubframeArchives"; NSArray *cachedSubresources; NSArray *cachedSubframeArchives; @private - LegacyWebArchive* coreArchive; + RefPtr<LegacyWebArchive> coreArchive; } - (id)initWithCoreArchive:(PassRefPtr<LegacyWebArchive>)coreArchive; @@ -76,7 +76,7 @@ static NSString * const WebSubframeArchivesKey = @"WebSubframeArchives"; self = [super init]; if (!self) return nil; - coreArchive = LegacyWebArchive::create().releaseRef(); + coreArchive = LegacyWebArchive::create(); return self; } @@ -87,33 +87,26 @@ static NSString * const WebSubframeArchivesKey = @"WebSubframeArchives"; [self release]; return nil; } - coreArchive = _coreArchive.releaseRef(); + coreArchive = _coreArchive; return self; } - (LegacyWebArchive*)coreArchive { - return coreArchive; + return coreArchive.get(); } - (void)setCoreArchive:(PassRefPtr<LegacyWebArchive>)newCoreArchive { ASSERT(coreArchive); ASSERT(newCoreArchive); - if (coreArchive) - coreArchive->deref(); - coreArchive = newCoreArchive.releaseRef(); + coreArchive = newCoreArchive; } - (void)dealloc { if (WebCoreObjCScheduleDeallocateOnMainThread([WebArchivePrivate class], self)) return; - - if (coreArchive) { - coreArchive->deref(); - coreArchive = 0; - } [cachedMainResource release]; [cachedSubresources release]; @@ -122,23 +115,13 @@ static NSString * const WebSubframeArchivesKey = @"WebSubframeArchives"; [super dealloc]; } -- (void)finalize -{ - if (coreArchive) { - coreArchive->deref(); - coreArchive = 0; - } - - [super finalize]; -} - @end @implementation WebArchive - (id)init { - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); self = [super init]; if (!self) @@ -166,7 +149,7 @@ static BOOL isArrayOfClass(id object, Class elementClass) return [[self _webkit_invokeOnMainThread] initWithMainResource:mainResource subresources:subresources subframeArchives:subframeArchives]; #endif - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); self = [super init]; if (!self) @@ -219,7 +202,7 @@ static BOOL isArrayOfClass(id object, Class elementClass) - (id)initWithData:(NSData *)data { - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); self = [super init]; if (!self) @@ -296,7 +279,7 @@ static BOOL isArrayOfClass(id object, Class elementClass) return [[self _webkit_invokeOnMainThread] mainResource]; #endif - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); // Currently from WebKit API perspective, WebArchives are entirely immutable once created // If they ever become mutable, we'll need to rethink this. @@ -316,7 +299,7 @@ static BOOL isArrayOfClass(id object, Class elementClass) return [[self _webkit_invokeOnMainThread] subresources]; #endif - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); // Currently from WebKit API perspective, WebArchives are entirely immutable once created // If they ever become mutable, we'll need to rethink this. @@ -337,8 +320,9 @@ static BOOL isArrayOfClass(id object, Class elementClass) } } } - - return [[_private->cachedSubresources retain] autorelease]; + // Maintain the WebKit 3 behavior of this API, which is documented and + // relied upon by some clients, of returning nil if there are no subresources. + return [_private->cachedSubresources count] ? [[_private->cachedSubresources retain] autorelease] : nil; } - (NSArray *)subframeArchives @@ -348,7 +332,7 @@ static BOOL isArrayOfClass(id object, Class elementClass) return [[self _webkit_invokeOnMainThread] subframeArchives]; #endif - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); // Currently from WebKit API perspective, WebArchives are entirely immutable once created // If they ever become mutable, we'll need to rethink this. @@ -373,7 +357,7 @@ static BOOL isArrayOfClass(id object, Class elementClass) - (NSData *)data { - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); #if !LOG_DISABLED CFAbsoluteTime start = CFAbsoluteTimeGetCurrent(); @@ -396,7 +380,7 @@ static BOOL isArrayOfClass(id object, Class elementClass) - (id)_initWithCoreLegacyWebArchive:(PassRefPtr<WebCore::LegacyWebArchive>)coreLegacyWebArchive { - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); self = [super init]; if (!self) @@ -413,7 +397,7 @@ static BOOL isArrayOfClass(id object, Class elementClass) - (WebCore::LegacyWebArchive *)_coreLegacyWebArchive { - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); return [_private coreArchive]; } diff --git a/WebKit/mac/WebView/WebDataSource.mm b/WebKit/mac/WebView/WebDataSource.mm index 12afcb3..57347d3 100644 --- a/WebKit/mac/WebView/WebDataSource.mm +++ b/WebKit/mac/WebView/WebDataSource.mm @@ -88,9 +88,12 @@ using namespace WebCore; if (WebCoreObjCScheduleDeallocateOnMainThread([WebDataSourcePrivate class], self)) return; - ASSERT(!loader->isLoading()); - loader->detachDataSource(); - loader->deref(); + ASSERT(loader); + if (loader) { + ASSERT(!loader->isLoading()); + loader->detachDataSource(); + loader->deref(); + } [representation release]; @@ -101,9 +104,12 @@ using namespace WebCore; { ASSERT_MAIN_THREAD(); - ASSERT(!loader->isLoading()); - loader->detachDataSource(); - loader->deref(); + ASSERT(loader); + if (loader) { + ASSERT(!loader->isLoading()); + loader->detachDataSource(); + loader->deref(); + } [super finalize]; } @@ -484,9 +490,14 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl _private->loader->getSubresources(coreSubresources); NSMutableArray *subresources = [[NSMutableArray alloc] initWithCapacity:coreSubresources.size()]; - for (unsigned i = 0; i < coreSubresources.size(); ++i) - [subresources addObject:[[[WebResource alloc] _initWithCoreResource:coreSubresources[i]] autorelease]]; - + for (unsigned i = 0; i < coreSubresources.size(); ++i) { + WebResource *resource = [[WebResource alloc] _initWithCoreResource:coreSubresources[i]]; + if (resource) { + [subresources addObject:resource]; + [resource release]; + } + } + return [subresources autorelease]; } diff --git a/WebKit/mac/WebView/WebFrame.mm b/WebKit/mac/WebView/WebFrame.mm index 0ac300e..2aa5fab 100644 --- a/WebKit/mac/WebView/WebFrame.mm +++ b/WebKit/mac/WebView/WebFrame.mm @@ -611,7 +611,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader) // We need to give the part the opportunity to adjust the page height at each step. for (float i = 0; i < docHeight; i += currPageHeight) { float proposedBottom = min(docHeight, i + printHeight); - _private->coreFrame->adjustPageHeight(&proposedBottom, i, proposedBottom, i); + view->adjustPageHeight(&proposedBottom, i, proposedBottom, i); currPageHeight = max(1.0f, proposedBottom - i); for (float j = 0; j < docWidth; j += printWidth) { NSValue* val = [NSValue valueWithRect: NSMakeRect(j, i, printWidth, currPageHeight)]; @@ -622,7 +622,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader) return pages; } -- (BOOL)_getVisibleRect:(NSRect*)rect; +- (BOOL)_getVisibleRect:(NSRect*)rect { ASSERT_ARG(rect, rect); if (RenderPart* ownerRenderer = _private->coreFrame->ownerRenderer()) { @@ -678,7 +678,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader) if (startNode && startNode->renderer()) { RenderLayer *layer = startNode->renderer()->enclosingLayer(); if (layer) - layer->scrollRectToVisible(enclosingIntRect(rangeRect), false, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignToEdgeIfNeeded); + layer->scrollRectToVisible(enclosingIntRect(rangeRect), false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); } } @@ -701,7 +701,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader) RenderView* root = static_cast<RenderView *>(_private->coreFrame->document()->renderer()); if (!root) return nil; - return _private->coreFrame->document()->axObjectCache()->get(root)->wrapper(); + return _private->coreFrame->document()->axObjectCache()->getOrCreate(root)->wrapper(); #else return nil; #endif @@ -715,7 +715,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader) SelectionController selection; selection.setSelection(_private->coreFrame->selection()->selection()); selection.modify(alteration, direction, granularity); - return [DOMRange _wrapRange:selection.toRange().get()]; + return [DOMRange _wrapRange:selection.toNormalizedRange().get()]; } - (TextGranularity)_selectionGranularity @@ -793,7 +793,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader) - (DOMRange *)_markDOMRange { - return [DOMRange _wrapRange:_private->coreFrame->mark().toRange().get()]; + return [DOMRange _wrapRange:_private->coreFrame->mark().toNormalizedRange().get()]; } // Given proposedRange, returns an extended range that includes adjacent whitespace that should @@ -824,8 +824,8 @@ static inline WebDataSource *dataSource(DocumentLoader* loader) RefPtr<Range> range = _private->coreFrame->document()->createRange(); int exception = 0; - range->setStart(newStart.node(), newStart.offset(), exception); - range->setEnd(newStart.node(), newStart.offset(), exception); + range->setStart(newStart.node(), newStart.m_offset, exception); + range->setEnd(newStart.node(), newStart.m_offset, exception); return [DOMRange _wrapRange:range.get()]; } @@ -909,15 +909,6 @@ static inline WebDataSource *dataSource(DocumentLoader* loader) return [DOMDocumentFragment _wrapDocumentFragment:createFragmentFromNodes(_private->coreFrame->document(), nodesVector).get()]; } -- (void)_replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle -{ - if (_private->coreFrame->selection()->isNone() || !fragment) - return; - - applyCommand(ReplaceSelectionCommand::create(_private->coreFrame->document(), [fragment _documentFragment], selectReplacement, smartReplace, matchStyle)); - _private->coreFrame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded); -} - - (void)_replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle { DOMDocumentFragment *fragment = [DOMDocumentFragment _wrapDocumentFragment:_private->coreFrame->document()->createDocumentFragment().get()]; @@ -925,41 +916,19 @@ static inline WebDataSource *dataSource(DocumentLoader* loader) [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle]; } -- (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace -{ - DOMDocumentFragment *fragment = [self _documentFragmentWithMarkupString:markupString baseURLString:baseURLString]; - [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO]; -} - -- (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace -{ - [self _replaceSelectionWithFragment:kit(createFragmentFromText(_private->coreFrame->selection()->toRange().get(), text).get()) - selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES]; -} - - (void)_insertParagraphSeparatorInQuotedContent { if (_private->coreFrame->selection()->isNone()) return; TypingCommand::insertParagraphSeparatorInQuotedContent(_private->coreFrame->document()); - _private->coreFrame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded); + _private->coreFrame->revealSelection(ScrollAlignment::alignToEdgeIfNeeded); } - (VisiblePosition)_visiblePositionForPoint:(NSPoint)point { - IntPoint outerPoint(point); - HitTestResult result = _private->coreFrame->eventHandler()->hitTestResultAtPoint(outerPoint, true); - Node* node = result.innerNode(); - if (!node) - return VisiblePosition(); - RenderObject* renderer = node->renderer(); - if (!renderer) - return VisiblePosition(); - VisiblePosition visiblePos = renderer->positionForCoordinates(result.localPoint().x(), result.localPoint().y()); - if (visiblePos.isNull()) - visiblePos = VisiblePosition(Position(node, 0)); - return visiblePos; + // FIXME: Someone with access to Apple's sources could remove this needless wrapper call. + return _private->coreFrame->visiblePositionForPoint(IntPoint(point)); } - (DOMRange *)_characterRangeAtPoint:(NSPoint)point @@ -1094,7 +1063,8 @@ static inline WebDataSource *dataSource(DocumentLoader* loader) - (BOOL)_isFrameSet { - return _private->coreFrame->isFrameSet(); + Document* document = _private->coreFrame->document(); + return document && document->isFrameSet(); } - (BOOL)_firstLayoutDone @@ -1109,14 +1079,14 @@ static inline WebDataSource *dataSource(DocumentLoader* loader) - (NSRange)_selectedNSRange { - return [self _convertToNSRange:_private->coreFrame->selection()->toRange().get()]; + return [self _convertToNSRange:_private->coreFrame->selection()->toNormalizedRange().get()]; } - (void)_selectNSRange:(NSRange)range { RefPtr<Range> domRange = [self _convertToDOMRange:range]; if (domRange) - _private->coreFrame->selection()->setSelection(Selection(domRange.get(), SEL_DEFAULT_AFFINITY)); + _private->coreFrame->selection()->setSelection(VisibleSelection(domRange.get(), SEL_DEFAULT_AFFINITY)); } - (BOOL)_isDisplayingStandaloneImage @@ -1217,6 +1187,27 @@ static inline WebDataSource *dataSource(DocumentLoader* loader) return controller->numberOfActiveAnimations(); } +- (void)_replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle +{ + if (_private->coreFrame->selection()->isNone() || !fragment) + return; + + applyCommand(ReplaceSelectionCommand::create(_private->coreFrame->document(), [fragment _documentFragment], selectReplacement, smartReplace, matchStyle)); + _private->coreFrame->revealSelection(ScrollAlignment::alignToEdgeIfNeeded); +} + +- (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace +{ + DOMDocumentFragment* fragment = kit(createFragmentFromText(_private->coreFrame->selection()->toNormalizedRange().get(), text).get()); + [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES]; +} + +- (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace +{ + DOMDocumentFragment *fragment = [self _documentFragmentWithMarkupString:markupString baseURLString:baseURLString]; + [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO]; +} + @end @implementation WebFrame diff --git a/WebKit/mac/WebView/WebFrameInternal.h b/WebKit/mac/WebView/WebFrameInternal.h index fa17ed9..473e691 100644 --- a/WebKit/mac/WebView/WebFrameInternal.h +++ b/WebKit/mac/WebView/WebFrameInternal.h @@ -167,10 +167,7 @@ WebView *getWebView(WebFrame *webFrame); - (DOMDocumentFragment *)_documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString; - (DOMDocumentFragment *)_documentFragmentWithNodesAsParagraphs:(NSArray *)nodes; -- (void)_replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle; - (void)_replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle; -- (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace; -- (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace; - (void)_insertParagraphSeparatorInQuotedContent; diff --git a/WebKit/mac/WebView/WebFramePrivate.h b/WebKit/mac/WebView/WebFramePrivate.h index 2ea686e..e3e3540 100644 --- a/WebKit/mac/WebView/WebFramePrivate.h +++ b/WebKit/mac/WebView/WebFramePrivate.h @@ -35,6 +35,7 @@ #define ENABLE_NETSCAPE_PLUGIN_API 1 #endif +@class DOMDocumentFragment; @class DOMNode; @class WebIconFetcher; @class WebScriptObject; @@ -95,4 +96,8 @@ typedef enum { // Returns the total number of currently running animations (includes both CSS transitions and CSS animations). - (unsigned) _numberOfActiveAnimations; +- (void)_replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle; +- (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace; +- (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace; + @end diff --git a/WebKit/mac/WebView/WebFrameView.mm b/WebKit/mac/WebView/WebFrameView.mm index 132fb93..bc51bb5 100644 --- a/WebKit/mac/WebView/WebFrameView.mm +++ b/WebKit/mac/WebView/WebFrameView.mm @@ -49,6 +49,7 @@ #import "WebNSWindowExtras.h" #import "WebPDFView.h" #import "WebPreferenceKeysPrivate.h" +#import "WebResourceInternal.h" #import "WebSystemInterface.h" #import "WebViewFactory.h" #import "WebViewInternal.h" @@ -314,9 +315,18 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl WKDisableCGDeferredUpdates(); if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_MAIN_THREAD_EXCEPTIONS)) - setDefaultThreadViolationBehavior(LogOnFirstThreadViolation); + setDefaultThreadViolationBehavior(LogOnFirstThreadViolation, ThreadViolationRoundOne); + + bool throwExceptionsForRoundTwo = WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_ROUND_TWO_MAIN_THREAD_EXCEPTIONS); +#ifdef MAIL_THREAD_WORKAROUND + // Even if old Mail is linked with new WebKit, don't throw exceptions. + if (needMailThreadWorkaround()) + throwExceptionsForRoundTwo = false; +#endif + if (!throwExceptionsForRoundTwo) + setDefaultThreadViolationBehavior(LogOnFirstThreadViolation, ThreadViolationRoundTwo); } - + _private = [[WebFrameViewPrivate alloc] init]; WebDynamicScrollBarsView *scrollView = [[WebDynamicScrollBarsView alloc] initWithFrame:NSMakeRect(0.0f, 0.0f, frame.size.width, frame.size.height)]; diff --git a/WebKit/mac/WebView/WebHTMLRepresentation.mm b/WebKit/mac/WebView/WebHTMLRepresentation.mm index 604a17a..3f69870 100644 --- a/WebKit/mac/WebView/WebHTMLRepresentation.mm +++ b/WebKit/mac/WebView/WebHTMLRepresentation.mm @@ -137,7 +137,7 @@ static NSArray *concatenateArrays(NSArray *first, NSArray *second) [super finalize]; } -- (void)_redirectDataToManualLoader:(id<WebPluginManualLoader>)manualLoader forPluginView:(NSView *)pluginView; +- (void)_redirectDataToManualLoader:(id<WebPluginManualLoader>)manualLoader forPluginView:(NSView *)pluginView { _private->manualLoader = manualLoader; _private->pluginView = pluginView; @@ -150,7 +150,7 @@ static NSArray *concatenateArrays(NSArray *first, NSArray *second) - (BOOL)_isDisplayingWebArchive { - return [[[_private->dataSource response] MIMEType] _webkit_isCaseInsensitiveEqualToString:@"application/x-webarchive"]; + return [[_private->dataSource _responseMIMEType] _webkit_isCaseInsensitiveEqualToString:@"application/x-webarchive"]; } - (void)receivedData:(NSData *)data withDataSource:(WebDataSource *)dataSource diff --git a/WebKit/mac/WebView/WebHTMLView.mm b/WebKit/mac/WebView/WebHTMLView.mm index be4d8db..c4ca174 100644 --- a/WebKit/mac/WebView/WebHTMLView.mm +++ b/WebKit/mac/WebView/WebHTMLView.mm @@ -48,7 +48,6 @@ #import "WebHTMLViewInternal.h" #import "WebKitLogging.h" #import "WebKitNSStringExtras.h" -#import "WebKitPluginContainerView.h" #import "WebKitVersionChecks.h" #import "WebLocalizableStrings.h" #import "WebNodeHighlight.h" @@ -114,6 +113,10 @@ #import <limits> #import <runtime/InitializeThreading.h> +#if USE(ACCELERATED_COMPOSITING) +#import <QuartzCore/QuartzCore.h> +#endif + using namespace WebCore; using namespace HTMLNames; using namespace WTF; @@ -129,6 +132,15 @@ using namespace WTF; } @end +@interface WebResponderChainSink : NSResponder { + NSResponder* _lastResponderInChain; + BOOL _receivedUnhandledCommand; +} +- (id)initWithResponderChain:(NSResponder *)chain; +- (void)detach; +- (BOOL)receivedUnhandledCommand; +@end + static IMP oldSetCursorIMP = NULL; #ifdef BUILDING_ON_TIGER @@ -142,7 +154,7 @@ static void resetCursorRects(NSWindow* self, SEL cmd) if ([view isKindOfClass:[WebHTMLView class]]) { WebHTMLView *htmlView = (WebHTMLView*)view; NSPoint localPoint = [htmlView convertPoint:point fromView:nil]; - NSDictionary *dict = [htmlView elementAtPoint:point allowShadowContent:NO]; + NSDictionary *dict = [htmlView elementAtPoint:localPoint allowShadowContent:NO]; DOMElement *element = [dict objectForKey:WebElementDOMNodeKey]; if (![element isKindOfClass:[DOMHTMLAppletElement class]] && ![element isKindOfClass:[DOMHTMLObjectElement class]] && ![element isKindOfClass:[DOMHTMLEmbedElement class]]) @@ -164,7 +176,7 @@ static void setCursor(NSWindow* self, SEL cmd, NSPoint point) if ([view isKindOfClass:[WebHTMLView class]]) { WebHTMLView *htmlView = (WebHTMLView*)view; NSPoint localPoint = [htmlView convertPoint:point fromView:nil]; - NSDictionary *dict = [htmlView elementAtPoint:point allowShadowContent:NO]; + NSDictionary *dict = [htmlView elementAtPoint:localPoint allowShadowContent:NO]; DOMElement *element = [dict objectForKey:WebElementDOMNodeKey]; if (![element isKindOfClass:[DOMHTMLAppletElement class]] && ![element isKindOfClass:[DOMHTMLObjectElement class]] && ![element isKindOfClass:[DOMHTMLEmbedElement class]]) @@ -174,6 +186,20 @@ static void setCursor(NSWindow* self, SEL cmd, NSPoint point) } #endif +#if USE(ACCELERATED_COMPOSITING) +@interface WebLayerHostingView : NSView +@end + +@implementation WebLayerHostingView +// Empty NSViews intercept rightMouseDown: to do context menu handling, but we need the WebLayerHostingView to +// let right mouse clicks through. +- (void)rightMouseDown:(NSEvent *)theEvent +{ + [[self nextResponder] performSelector:_cmd withObject:theEvent]; +} +@end +#endif // USE(ACCELERATED_COMPOSITING) + extern "C" { // Need to declare these attribute names because AppKit exports them but does not make them available in API or SPI headers. @@ -289,6 +315,9 @@ static CachedResourceClient* promisedDataClient() - (NSString *)_plainTextFromPasteboard:(NSPasteboard *)pasteboard; - (void)_pasteWithPasteboard:(NSPasteboard *)pasteboard allowPlainText:(BOOL)allowPlainText; - (void)_pasteAsPlainTextWithPasteboard:(NSPasteboard *)pasteboard; +- (void)_removeMouseMovedObserverUnconditionally; +- (void)_removeSuperviewObservers; +- (void)_removeWindowObservers; - (BOOL)_shouldInsertFragment:(DOMDocumentFragment *)fragment replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action; - (BOOL)_shouldInsertText:(NSString *)text replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action; - (BOOL)_shouldReplaceSelectionWithText:(NSString *)text givenAction:(WebViewInsertAction)action; @@ -372,9 +401,17 @@ struct WebHTMLViewInterpretKeyEventsParameters { BOOL ignoringMouseDraggedEvents; BOOL printing; BOOL avoidingPrintOrphan; + BOOL observingMouseMovedNotifications; + BOOL observingSuperviewNotifications; + BOOL observingWindowNotifications; + BOOL resigningFirstResponder; id savedSubviews; BOOL subviewsSetAside; + +#if USE(ACCELERATED_COMPOSITING) + NSView *layerHostingView; +#endif NSEvent *mouseDownEvent; // Kept after handling the event. BOOL handlingMouseDownEvent; @@ -523,6 +560,10 @@ static NSCellStateValue kit(TriState state) dataSource = nil; highlighters = nil; promisedDragTIFFDataSource = 0; + +#if USE(ACCELERATED_COMPOSITING) + layerHostingView = nil; +#endif } @end @@ -755,6 +796,49 @@ static NSURL* uniqueURLWithRelativePart(NSString *relativePart) [[self _frame] _replaceSelectionWithText:text selectReplacement:NO smartReplace:[self _canSmartReplaceWithPasteboard:pasteboard]]; } +- (void)_removeMouseMovedObserverUnconditionally +{ + if (!_private || !_private->observingMouseMovedNotifications) + return; + + [[NSNotificationCenter defaultCenter] removeObserver:self name:WKMouseMovedNotification() object:nil]; + _private->observingMouseMovedNotifications = false; +} + +- (void)_removeSuperviewObservers +{ + if (!_private || !_private->observingSuperviewNotifications) + return; + + NSView *superview = [self superview]; + if (!superview || ![self window]) + return; + + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter removeObserver:self name:NSViewFrameDidChangeNotification object:superview]; + [notificationCenter removeObserver:self name:NSViewBoundsDidChangeNotification object:superview]; + + _private->observingSuperviewNotifications = false; +} + +- (void)_removeWindowObservers +{ + if (!_private->observingWindowNotifications) + return; + + NSWindow *window = [self window]; + if (!window) + return; + + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter removeObserver:self name:NSWindowDidBecomeKeyNotification object:nil]; + [notificationCenter removeObserver:self name:NSWindowDidResignKeyNotification object:nil]; + [notificationCenter removeObserver:self name:NSWindowWillCloseNotification object:window]; + [notificationCenter removeObserver:self name:WKWindowWillOrderOnScreenNotification() object:window]; + + _private->observingWindowNotifications = false; +} + - (BOOL)_shouldInsertFragment:(DOMDocumentFragment *)fragment replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action { WebView *webView = [self _webView]; @@ -789,7 +873,7 @@ static NSURL* uniqueURLWithRelativePart(NSString *relativePart) - (DOMRange *)_selectedRange { Frame* coreFrame = core([self _frame]); - return coreFrame ? kit(coreFrame->selection()->toRange().get()) : nil; + return coreFrame ? kit(coreFrame->selection()->toNormalizedRange().get()) : nil; } - (BOOL)_shouldDeleteRange:(DOMRange *)range @@ -1064,7 +1148,7 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info) NSPoint origin = [[self superview] bounds].origin; if (!NSEqualPoints(_private->lastScrollPosition, origin)) { if (Frame* coreFrame = core([self _frame])) - coreFrame->sendScrollEvent(); + coreFrame->eventHandler()->sendScrollEvent(); [_private->compController endRevertingChange:NO moveLeft:NO]; WebView *webView = [self _webView]; @@ -1088,15 +1172,34 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info) ASSERT(!_private->subviewsSetAside); ASSERT(_private->savedSubviews == nil); _private->savedSubviews = _subviews; +#if USE(ACCELERATED_COMPOSITING) + // We need to keep the layer-hosting view in the subviews, otherwise the layers flash. + if (_private->layerHostingView) { + NSArray* newSubviews = [[NSArray alloc] initWithObjects:_private->layerHostingView, nil]; + _subviews = newSubviews; + } else + _subviews = nil; +#else _subviews = nil; +#endif _private->subviewsSetAside = YES; } - (void)_restoreSubviews { ASSERT(_private->subviewsSetAside); +#if USE(ACCELERATED_COMPOSITING) + if (_private->layerHostingView) { + [_subviews release]; + _subviews = _private->savedSubviews; + } else { + ASSERT(_subviews == nil); + _subviews = _private->savedSubviews; + } +#else ASSERT(_subviews == nil); _subviews = _private->savedSubviews; +#endif _private->savedSubviews = nil; _private->subviewsSetAside = NO; } @@ -1111,7 +1214,9 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info) - (void)willRemoveSubview:(NSView *)subview { - if (_private->enumeratingSubviews) + // Have to null-check _private, since this can be called via -dealloc when + // cleaning up the the layerHostingView. + if (_private && _private->enumeratingSubviews) LOG(View, "A view of class %s was removed during subview enumeration for layout or printing mode change. We will still do layout or the printing mode change even though this view is no longer in the view hierarchy.", object_getClassName([subview class])); } @@ -1833,7 +1938,7 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info) - (void)close { - // Check for a nil _private here incase we were created with initWithCoder. In that case, the WebView is just throwing + // Check for a nil _private here in case we were created with initWithCoder. In that case, the WebView is just throwing // out the archived WebHTMLView and recreating a new one if needed. So close doesn't need to do anything in that case. if (!_private || _private->closed) return; @@ -1843,14 +1948,21 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info) [self _cancelUpdateMouseoverTimer]; [self _cancelUpdateFocusedAndActiveStateTimer]; [self _clearLastHitViewIfSelf]; - // FIXME: This is slow; should remove individual observers instead. - [[NSNotificationCenter defaultCenter] removeObserver:self]; + [self _removeMouseMovedObserverUnconditionally]; + [self _removeWindowObservers]; + [self _removeSuperviewObservers]; [_private->pluginController destroyAllPlugins]; [_private->pluginController setDataSource:nil]; // remove tooltips before clearing _private so removeTrackingRect: will work correctly [self removeAllToolTips]; + +#if USE(ACCELERATED_COMPOSITING) + if (_private->layerHostingView) + [[self _webView] _stoppedAcceleratedCompositingForFrame:[self _frame]]; +#endif + [_private clear]; - + Page* page = core([self _webView]); if (page) page->dragController()->setDraggingImageURL(KURL()); @@ -1976,10 +2088,10 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info) if (!document) return nil; DOMHTMLAnchorElement *anchor = (DOMHTMLAnchorElement *)[document createElement:@"a"]; - NSString *URLString = [URL _web_originalDataAsString]; + NSString *URLString = [URL _web_originalDataAsString]; // Original data is ASCII-only, so there is no need to precompose. if ([URLString length] == 0) return nil; - NSString *URLTitleString = [pasteboard stringForType:WebURLNamePboardType]; + NSString *URLTitleString = [[pasteboard stringForType:WebURLNamePboardType] precomposedStringWithCanonicalMapping]; DOMText *text = [document createTextNode:URLTitleString]; [anchor setHref:URLString]; [anchor appendChild:text]; @@ -1988,7 +2100,7 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info) return fragment; } if (pboardType == NSStringPboardType) - return kit(createFragmentFromText(core(context), [pasteboard stringForType:NSStringPboardType]).get()); + return kit(createFragmentFromText(core(context), [[pasteboard stringForType:NSStringPboardType] precomposedStringWithCanonicalMapping]).get()); return nil; } @@ -2022,6 +2134,15 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info) } #endif +- (BOOL)_isUsingAcceleratedCompositing +{ +#if USE(ACCELERATED_COMPOSITING) + return _private->layerHostingView != nil; +#else + return NO; +#endif +} + @end @implementation NSView (WebHTMLViewFileInternal) @@ -2052,6 +2173,23 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info) @end +@interface NSString (WebHTMLViewFileInternal) +- (BOOL)matchesExtensionEquivalent:(NSString *)extension; +@end + +@implementation NSString (WebHTMLViewFileInternal) + +- (BOOL)matchesExtensionEquivalent:(NSString *)extension +{ + if ([self hasSuffix:extension]) + return YES; + else if ([extension isEqualToString:@"jpeg"] && [self hasSuffix:@"jpg"]) + return YES; + return NO; +} + +@end + #ifdef BUILDING_ON_TIGER // The following is a workaround for @@ -2167,8 +2305,8 @@ static String commandNameForSelector(SEL selector) // Remove the trailing colon. const char* selectorName = sel_getName(selector); size_t selectorNameLength = strlen(selectorName); - ASSERT(selectorNameLength >= 2); - ASSERT(selectorName[selectorNameLength - 1] == ':'); + if (selectorNameLength < 2 || selectorName[selectorNameLength - 1] != ':') + return String(); return String(selectorName, selectorNameLength - 1); } @@ -2267,6 +2405,10 @@ WEBCORE_COMMAND(moveToEndOfParagraph) WEBCORE_COMMAND(moveToEndOfParagraphAndModifySelection) WEBCORE_COMMAND(moveToEndOfSentence) WEBCORE_COMMAND(moveToEndOfSentenceAndModifySelection) +WEBCORE_COMMAND(moveToLeftEndOfLine) +WEBCORE_COMMAND(moveToLeftEndOfLineAndModifySelection) +WEBCORE_COMMAND(moveToRightEndOfLine) +WEBCORE_COMMAND(moveToRightEndOfLineAndModifySelection) WEBCORE_COMMAND(moveUp) WEBCORE_COMMAND(moveUpAndModifySelection) WEBCORE_COMMAND(moveWordBackward) @@ -2335,11 +2477,10 @@ WEBCORE_COMMAND(yankAndSelect) - (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType { - if (sendType != nil && [[self pasteboardTypesForSelection] containsObject:sendType] && [self _hasSelection]) { - return self; - } else if (returnType != nil && [[[self class] _insertablePasteboardTypes] containsObject:returnType] && [self _isEditable]) { + BOOL isSendTypeOK = !sendType || ([[self pasteboardTypesForSelection] containsObject:sendType] && [self _hasSelection]); + BOOL isReturnTypeOK = !returnType || ([[[self class] _insertablePasteboardTypes] containsObject:returnType] && [self _isEditable]); + if (isSendTypeOK && isReturnTypeOK) return self; - } return [[self nextResponder] validRequestorForSendType:sendType returnType:returnType]; } @@ -2353,7 +2494,7 @@ WEBCORE_COMMAND(yankAndSelect) COMMAND_PROLOGUE if (Frame* coreFrame = core([self _frame])) - coreFrame->revealSelection(RenderLayer::gAlignCenterAlways); + coreFrame->revealSelection(ScrollAlignment::alignCenterAlways); } - (NSCellStateValue)selectionHasStyle:(CSSStyleDeclaration*)style @@ -2426,7 +2567,14 @@ WEBCORE_COMMAND(yankAndSelect) } return [self _canEdit]; } - + + if (action == @selector(makeBaseWritingDirectionNatural:)) { + NSMenuItem *menuItem = (NSMenuItem *)item; + if ([menuItem isKindOfClass:[NSMenuItem class]]) + [menuItem setState:NSOffState]; + return NO; + } + if (action == @selector(toggleBaseWritingDirection:)) { NSMenuItem *menuItem = (NSMenuItem *)item; if ([menuItem isKindOfClass:[NSMenuItem class]]) { @@ -2566,7 +2714,7 @@ WEBCORE_COMMAND(yankAndSelect) - (void)addMouseMovedObserver { - if (!_private->dataSource || ![self _isTopHTMLView]) + if (!_private->dataSource || ![self _isTopHTMLView] || _private->observingMouseMovedNotifications) return; // Unless the Dashboard asks us to do this for all windows, keep an observer going only for the key window. @@ -2580,12 +2728,7 @@ WEBCORE_COMMAND(yankAndSelect) [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mouseMovedNotification:) name:WKMouseMovedNotification() object:nil]; [self _frameOrBoundsChanged]; -} - -- (void)removeMouseMovedObserverUnconditionally -{ - [[NSNotificationCenter defaultCenter] removeObserver:self - name:WKMouseMovedNotification() object:nil]; + _private->observingMouseMovedNotifications = true; } - (void)removeMouseMovedObserver @@ -2597,7 +2740,7 @@ WEBCORE_COMMAND(yankAndSelect) #endif [[self _webView] _mouseDidMoveOverElement:nil modifierFlags:0]; - [self removeMouseMovedObserverUnconditionally]; + [self _removeMouseMovedObserverUnconditionally]; } - (void)addSuperviewObservers @@ -2610,66 +2753,48 @@ WEBCORE_COMMAND(yankAndSelect) // to extend the background the full height of the space and because some elements have // sizes that are based on the total size of the view. - NSView *superview = [self superview]; - if (superview && [self window]) { - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_frameOrBoundsChanged) - name:NSViewFrameDidChangeNotification object:superview]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_frameOrBoundsChanged) - name:NSViewBoundsDidChangeNotification object:superview]; - - // In addition to registering for frame/bounds change notifications, call -_frameOrBoundsChanged. - // It will check the current size/scroll against the previous layout's size/scroll. We need to - // do this here to catch the case where the WebView is laid out at one size, removed from its - // window, resized, and inserted into another window. Our frame/bounds changed notifications - // will not be sent in that situation, since we only watch for changes while in the view hierarchy. - [self _frameOrBoundsChanged]; - } -} + if (_private->observingSuperviewNotifications) + return; -- (void)removeSuperviewObservers -{ NSView *superview = [self superview]; - if (superview && [self window]) { - [[NSNotificationCenter defaultCenter] removeObserver:self - name:NSViewFrameDidChangeNotification object:superview]; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:NSViewBoundsDidChangeNotification object:superview]; - } + if (!superview || ![self window]) + return; + + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self selector:@selector(_frameOrBoundsChanged) name:NSViewFrameDidChangeNotification object:superview]; + [notificationCenter addObserver:self selector:@selector(_frameOrBoundsChanged) name:NSViewBoundsDidChangeNotification object:superview]; + + // In addition to registering for frame/bounds change notifications, call -_frameOrBoundsChanged. + // It will check the current size/scroll against the previous layout's size/scroll. We need to + // do this here to catch the case where the WebView is laid out at one size, removed from its + // window, resized, and inserted into another window. Our frame/bounds changed notifications + // will not be sent in that situation, since we only watch for changes while in the view hierarchy. + [self _frameOrBoundsChanged]; + + _private->observingSuperviewNotifications = true; } - (void)addWindowObservers { + if (_private->observingWindowNotifications) + return; + NSWindow *window = [self window]; - if (window) { - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidBecomeKey:) - name:NSWindowDidBecomeKeyNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidResignKey:) - name:NSWindowDidResignKeyNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowWillClose:) - name:NSWindowWillCloseNotification object:window]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowWillOrderOnScreen:) - name:WKWindowWillOrderOnScreenNotification() object:window]; - } -} - -- (void)removeWindowObservers -{ - NSWindow *window = [self window]; - if (window) { - [[NSNotificationCenter defaultCenter] removeObserver:self - name:NSWindowDidBecomeKeyNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:NSWindowDidResignKeyNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:NSWindowWillCloseNotification object:window]; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:WKWindowWillOrderOnScreenNotification() object:window]; - } + if (!window) + return; + + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:nil]; + [notificationCenter addObserver:self selector:@selector(windowDidResignKey:) name:NSWindowDidResignKeyNotification object:nil]; + [notificationCenter addObserver:self selector:@selector(windowWillClose:) name:NSWindowWillCloseNotification object:window]; + [notificationCenter addObserver:self selector:@selector(windowWillOrderOnScreen:) name:WKWindowWillOrderOnScreenNotification() object:window]; + + _private->observingWindowNotifications = true; } - (void)viewWillMoveToSuperview:(NSView *)newSuperview { - [self removeSuperviewObservers]; + [self _removeSuperviewObservers]; } - (void)viewDidMoveToSuperview @@ -2694,9 +2819,9 @@ static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, v return; // FIXME: Some of these calls may not work because this view may be already removed from it's superview. - [self removeMouseMovedObserverUnconditionally]; - [self removeWindowObservers]; - [self removeSuperviewObservers]; + [self _removeMouseMovedObserverUnconditionally]; + [self _removeWindowObservers]; + [self _removeSuperviewObservers]; [self _cancelUpdateMouseoverTimer]; [self _cancelUpdateFocusedAndActiveStateTimer]; @@ -2811,12 +2936,14 @@ static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, v return; } - if (minPageWidth > 0.0) - coreFrame->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth, adjustViewSize); - else { - coreFrame->forceLayout(!adjustViewSize); - if (adjustViewSize) - coreFrame->view()->adjustViewSize(); + if (FrameView* coreView = coreFrame->view()) { + if (minPageWidth > 0.0) + coreView->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth, adjustViewSize); + else { + coreView->forceLayout(!adjustViewSize); + if (adjustViewSize) + coreView->adjustViewSize(); + } } _private->needsLayout = NO; @@ -2993,6 +3120,16 @@ static void _updateFocusedAndActiveStateTimerCallback(CFRunLoopTimerRef timer, v if (subviewsWereSetAside) [self _setAsideSubviews]; + +#if USE(ACCELERATED_COMPOSITING) + if ([[self _webView] _needsOneShotDrawingSynchronization]) { + // Disable screen updates so that drawing into the NSView and + // CALayer updates appear on the screen at the same time. + [[self window] disableScreenUpdatesUntilFlush]; + [CATransaction flush]; + [[self _webView] _setNeedsOneShotDrawingSynchronization:NO]; + } +#endif } // Turn off the additional clip while computing our visibleRect. @@ -3250,8 +3387,8 @@ done: draggingImageURL = [response URL]; wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:data] autorelease]; NSString* filename = [response suggestedFilename]; - String trueExtension = tiffResource->image()->filenameExtension(); - if (![filename hasSuffix:trueExtension]) + NSString* trueExtension(tiffResource->image()->filenameExtension()); + if (![filename matchesExtensionEquivalent:trueExtension]) filename = [[filename stringByAppendingString:@"."] stringByAppendingString:trueExtension]; [wrapper setPreferredFilename:filename]; } @@ -3356,6 +3493,7 @@ noPromisedData: { BOOL resign = [super resignFirstResponder]; if (resign) { + _private->resigningFirstResponder = YES; [_private->compController endRevertingChange:NO moveLeft:NO]; if (![self maintainsInactiveSelection]) { [self deselectAll]; @@ -3363,6 +3501,7 @@ noPromisedData: [self clearFocus]; } [self _updateFocusedAndActiveState]; + _private->resigningFirstResponder = NO; } return resign; } @@ -3443,7 +3582,8 @@ noPromisedData: [self _setPrinting:YES minimumPageWidth:0.0f maximumPageWidth:0.0f adjustViewSize:NO]; float newBottomFloat = *newBottom; - core([self _frame])->adjustPageHeight(&newBottomFloat, oldTop, oldBottom, bottomLimit); + if (FrameView* view = core([self _frame])->view()) + view->adjustPageHeight(&newBottomFloat, oldTop, oldBottom, bottomLimit); #ifdef __LP64__ // If the new bottom is equal to the old bottom (when both are treated as floats), we just copy @@ -3548,7 +3688,7 @@ noPromisedData: Frame* frame = core([self _frame]); if (!frame) return NO; - if (!frame->isFrameSet()) { + if (!frame->document() || !frame->document()->isFrameSet()) { float paperWidth = [self _availablePaperWidthForPrintOperation:[NSPrintOperation currentOperation]]; minLayoutWidth = paperWidth * PrintingMinimumShrinkFactor; maxLayoutWidth = paperWidth * PrintingMaximumShrinkFactor; @@ -3742,7 +3882,7 @@ noPromisedData: COMMAND_PROLOGUE if (Frame* coreFrame = core([self _frame])) - coreFrame->revealSelection(RenderLayer::gAlignCenterAlways); + coreFrame->revealSelection(ScrollAlignment::alignCenterAlways); } - (NSData *)_selectionStartFontAttributesAsRTF @@ -4456,6 +4596,11 @@ static BOOL writingDirectionKeyBindingsEnabled() } #endif +- (void)makeBaseWritingDirectionNatural:(id)sender +{ + LOG_ERROR("Sent from %@.", sender); +} + #if 0 // CSS does not have a way to specify an outline font, which may make this difficult to implement. @@ -4764,6 +4909,27 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point) if ([[[self selectedString] _webkit_stringByTrimmingWhitespace] length] == 0) return; + NSAttributedString *attrString = [self selectedAttributedString]; + + Frame* coreFrame = core([self _frame]); + if (!coreFrame) + return; + + NSRect rect = coreFrame->selectionBounds(); + +#ifndef BUILDING_ON_TIGER + NSDictionary *attributes = [attrString fontAttributesInRange:NSMakeRange(0,1)]; + NSFont *font = [attributes objectForKey:NSFontAttributeName]; + if (font) + rect.origin.y += [font ascender]; +#endif + +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) + [self showDefinitionForAttributedString:attrString atPoint:rect.origin]; + return; +#endif + + // We soft link to get the function that displays the dictionary (either pop-up window or app) to avoid the performance // penalty of linking to another framework. This function changed signature as well as framework between Tiger and Leopard, // so the two cases are handled separately. @@ -4795,12 +4961,6 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point) return; } - NSAttributedString *attrString = [self selectedAttributedString]; - - Frame* coreFrame = core([self _frame]); - if (!coreFrame) - return; - #ifdef BUILDING_ON_TIGER // FIXME: must check for right-to-left here NSWritingDirection writingDirection = NSWritingDirectionLeftToRight; @@ -4808,7 +4968,7 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point) // FIXME: the dictionary API expects the rect for the first line of selection. Passing // the rect for the entire selection, as we do here, positions the pop-up window near // the bottom of the selection rather than at the selected word. - NSRect rect = [self convertRect:coreFrame->selectionBounds() toView:nil]; + rect = [self convertRect:rect toView:nil]; rect.origin = [[self window] convertBaseToScreen:rect.origin]; NSData *data = [attrString RTFFromRange:NSMakeRange(0, [attrString length]) documentAttributes:nil]; dictionaryServiceWindowShow(data, rect, (writingDirection == NSWritingDirectionRightToLeft) ? 1 : 0); @@ -4816,19 +4976,12 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point) // The HIDictionaryWindowShow function requires the origin, in CG screen coordinates, of the first character of text in the selection. // FIXME 4945808: We approximate this in a way that works well when a single word is selected, and less well in some other cases // (but no worse than we did in Tiger) - NSRect rect = coreFrame->selectionBounds(); - - NSDictionary *attributes = [attrString fontAttributesInRange:NSMakeRange(0,1)]; - NSFont *font = [attributes objectForKey:NSFontAttributeName]; - if (font) - rect.origin.y += [font ascender]; - NSPoint windowPoint = [self convertPoint:rect.origin toView:nil]; NSPoint screenPoint = [[self window] convertBaseToScreen:windowPoint]; dictionaryServiceWindowShow(nil, attrString, CFRangeMake(0, [attrString length]), nil, coreGraphicsScreenPointForAppKitScreenPoint(screenPoint), false, nil); -#endif +#endif } - (void)_hoverFeedbackSuspendedChanged @@ -4877,19 +5030,21 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point) if ([self coreCommandBySelector:NSSelectorFromString(commands[i].commandName)].isTextInsertion()) haveTextInsertionCommands = true; } - if (!haveTextInsertionCommands || platformEvent->type() == PlatformKeyboardEvent::Char) - for (size_t i = 0; i < size; ++i) + if (!haveTextInsertionCommands || platformEvent->type() == PlatformKeyboardEvent::Char) { + for (size_t i = 0; i < size; ++i) { if (commands[i].commandName == "insertText:") [self insertText:commands[i].text]; else [self doCommandBySelector:NSSelectorFromString(commands[i].commandName)]; + } + } } _private->interpretKeyEventsParameters = 0; } return (!_private->receivedNOOP && parameters.eventWasHandled) || parameters.consumedByIM; } -- (WebCore::CachedImage*)promisedDragTIFFDataSource +- (WebCore::CachedImage*)promisedDragTIFFDataSource { return _private->promisedDragTIFFDataSource; } @@ -4944,6 +5099,45 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point) [[self _pluginController] destroyAllPlugins]; } +- (BOOL)_isResigningFirstResponder +{ + return _private->resigningFirstResponder; +} + +#if USE(ACCELERATED_COMPOSITING) +- (void)attachRootLayer:(CALayer*)layer +{ + if (!_private->layerHostingView) { + WebLayerHostingView* hostingView = [[WebLayerHostingView alloc] initWithFrame:[self bounds]]; + [hostingView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; + [self addSubview:hostingView]; + [hostingView release]; + // hostingView is owned by being a subview of self + _private->layerHostingView = hostingView; + [[self _webView] _startedAcceleratedCompositingForFrame:[self _frame]]; + } + + // Make a container layer, which will get sized/positioned by AppKit and CA + CALayer* viewLayer = [CALayer layer]; + [_private->layerHostingView setLayer:viewLayer]; + [_private->layerHostingView setWantsLayer:YES]; + + // Parent our root layer in the container layer + [viewLayer addSublayer:layer]; +} + +- (void)detachRootLayer +{ + if (_private->layerHostingView) { + [_private->layerHostingView setLayer:nil]; + [_private->layerHostingView setWantsLayer:NO]; + [_private->layerHostingView removeFromSuperview]; + _private->layerHostingView = nil; + [[self _webView] _stoppedAcceleratedCompositingForFrame:[self _frame]]; + } +} +#endif + @end @implementation WebHTMLView (WebNSTextInputSupport) @@ -5058,7 +5252,11 @@ static BOOL isInPasswordField(Frame* coreFrame) - (NSRange)markedRange { WebFrame *webFrame = [self _frame]; - NSRange result = [webFrame _convertToNSRange:core(webFrame)->editor()->compositionRange().get()]; + Frame* coreFrame = core(webFrame); + if (!coreFrame) + return NSMakeRange(0, 0); + NSRange result = [webFrame _convertToNSRange:coreFrame->editor()->compositionRange().get()]; + LOG(TextInput, "markedRange -> (%u, %u)", result.location, result.length); return result; } @@ -5214,26 +5412,29 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde // Make sure that only direct calls to doCommandBySelector: see the parameters by setting to 0. _private->interpretKeyEventsParameters = 0; - bool eventWasHandled = true; + bool eventWasHandled; WebView *webView = [self _webView]; - Frame* coreFrame = core([self _frame]); - if (![[webView _editingDelegateForwarder] webView:webView doCommandBySelector:selector] && coreFrame) { + if ([[webView _editingDelegateForwarder] webView:webView doCommandBySelector:selector]) + eventWasHandled = true; + else { Editor::Command command = [self coreCommandBySelector:selector]; if (command.isSupported()) eventWasHandled = command.execute(event); - else if ([self _canEdit]) { - // If the command is unsupported and the WebHTMLView is editable, then pass the - // selector to super and say that the event was handled. If the WebHTMLView is - // not editable, then do not say that the event was handled. This is important - // because of selectors like scrollPageDown:, which come as input method events - // when editing is enabled but keyboard events when it is not. These events are - // handled by the next responder in the responder chain. + else { + // If WebKit does not support this command, we need to pass the selector to super. _private->selectorForDoCommandBySelector = 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. + WebResponderChainSink *sink = [[WebResponderChainSink alloc] initWithResponderChain:self]; [super doCommandBySelector:selector]; + eventWasHandled = ![sink receivedUnhandledCommand]; + [sink detach]; + [sink release]; + _private->selectorForDoCommandBySelector = 0; - } else - eventWasHandled = false; + } } if (parameters) @@ -5474,7 +5675,7 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde // Get preceeding word stem WebFrame *frame = [_view _frame]; - DOMRange *selection = kit(core(frame)->selection()->toRange().get()); + DOMRange *selection = kit(core(frame)->selection()->toNormalizedRange().get()); DOMRange *wholeWord = [frame _rangeByAlteringCurrentSelection:SelectionController::EXTEND direction:SelectionController::BACKWARD granularity:WordGranularity]; DOMRange *prefix = [wholeWord cloneRange]; @@ -5744,7 +5945,7 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde if (!attributedString) { Frame* coreFrame = core([self _frame]); if (coreFrame) { - RefPtr<Range> range = coreFrame->selection()->selection().toRange(); + RefPtr<Range> range = coreFrame->selection()->selection().toNormalizedRange(); attributedString = [NSAttributedString _web_attributedStringFromRange:range.get()]; } } @@ -5773,7 +5974,7 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde return [self elementAtPoint:point allowShadowContent:NO]; } -- (NSDictionary *)elementAtPoint:(NSPoint)point allowShadowContent:(BOOL)allow; +- (NSDictionary *)elementAtPoint:(NSPoint)point allowShadowContent:(BOOL)allow { Frame* coreFrame = core([self _frame]); if (!coreFrame) @@ -5847,3 +6048,38 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde } @end + +@implementation WebResponderChainSink + +- (id)initWithResponderChain:(NSResponder *)chain +{ + self = [super init]; + _lastResponderInChain = chain; + while (NSResponder *next = [_lastResponderInChain nextResponder]) + _lastResponderInChain = next; + [_lastResponderInChain setNextResponder:self]; + return self; +} + +- (void)detach +{ + [_lastResponderInChain setNextResponder:nil]; + _lastResponderInChain = nil; +} + +- (BOOL)receivedUnhandledCommand +{ + return _receivedUnhandledCommand; +} + +- (void)noResponderFor:(SEL)selector +{ + _receivedUnhandledCommand = YES; +} + +- (void)doCommandBySelector:(SEL)selector +{ + _receivedUnhandledCommand = YES; +} + +@end diff --git a/WebKit/mac/WebView/WebHTMLViewInternal.h b/WebKit/mac/WebView/WebHTMLViewInternal.h index 0fb0cdc..a32df02 100644 --- a/WebKit/mac/WebView/WebHTMLViewInternal.h +++ b/WebKit/mac/WebView/WebHTMLViewInternal.h @@ -58,4 +58,11 @@ namespace WebCore { - (void)setPromisedDragTIFFDataSource:(WebCore::CachedImage*)source; - (void)_web_layoutIfNeededRecursive; - (void)_destroyAllWebPlugins; +- (BOOL)_isResigningFirstResponder; + +#if USE(ACCELERATED_COMPOSITING) +- (void)attachRootLayer:(CALayer*)layer; +- (void)detachRootLayer; +#endif + @end diff --git a/WebKit/mac/WebView/WebHTMLViewPrivate.h b/WebKit/mac/WebView/WebHTMLViewPrivate.h index 40de97f..0d73884 100644 --- a/WebKit/mac/WebView/WebHTMLViewPrivate.h +++ b/WebKit/mac/WebView/WebHTMLViewPrivate.h @@ -119,6 +119,7 @@ // SPI for DumpRenderTree - (void)_updateFocusedAndActiveState; +- (BOOL)_isUsingAcceleratedCompositing; // SPI for printing (should be converted to API someday). When the WebHTMLView isn't being printed // directly, this method must be called before paginating, or the computed height might be incorrect. diff --git a/WebKit/mac/WebView/WebPDFRepresentation.m b/WebKit/mac/WebView/WebPDFRepresentation.m index 1a2ddab..7eae380 100644 --- a/WebKit/mac/WebView/WebPDFRepresentation.m +++ b/WebKit/mac/WebView/WebPDFRepresentation.m @@ -26,7 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import <WebKit/WebDataSource.h> +#import <WebKit/WebDataSourcePrivate.h> #import <WebKit/WebFrame.h> #import <WebKit/WebFrameView.h> #import <WebKit/WebNSObjectExtras.h> @@ -111,7 +111,7 @@ NSData *data = [dataSource data]; NSArray *postScriptMIMETypes = [[self class] postScriptMIMETypes]; - NSString *mimeType = [[dataSource response] MIMEType]; + NSString *mimeType = [dataSource _responseMIMEType]; if ([postScriptMIMETypes containsObject:mimeType]) { data = [self convertPostScriptDataSourceToPDF:data]; if ([data length] == 0) diff --git a/WebKit/mac/WebView/WebPDFView.mm b/WebKit/mac/WebView/WebPDFView.mm index 2cb5374..0c872b9 100644 --- a/WebKit/mac/WebView/WebPDFView.mm +++ b/WebKit/mac/WebView/WebPDFView.mm @@ -341,7 +341,7 @@ static BOOL _PDFSelectionsAreEqual(PDFSelection *selectionA, PDFSelection *selec NSString *appName = nil; NSImage *appIcon = nil; - _applicationInfoForMIMEType([[dataSource response] MIMEType], &appName, &appIcon); + _applicationInfoForMIMEType([dataSource _responseMIMEType], &appName, &appIcon); if (!appName) appName = UI_STRING("Finder", "Default application name for Open With context menu"); diff --git a/WebKit/mac/WebView/WebPreferenceKeysPrivate.h b/WebKit/mac/WebView/WebPreferenceKeysPrivate.h index 98daec0..e22113c 100644 --- a/WebKit/mac/WebView/WebPreferenceKeysPrivate.h +++ b/WebKit/mac/WebView/WebPreferenceKeysPrivate.h @@ -41,6 +41,7 @@ #define WebKitDefaultFontSizePreferenceKey @"WebKitDefaultFontSize" #define WebKitDefaultFixedFontSizePreferenceKey @"WebKitDefaultFixedFontSize" #define WebKitDefaultTextEncodingNamePreferenceKey @"WebKitDefaultTextEncodingName" +#define WebKitUsesEncodingDetectorPreferenceKey @"WebKitUsesEncodingDetector" #define WebKitUserStyleSheetEnabledPreferenceKey @"WebKitUserStyleSheetEnabledPreferenceKey" #define WebKitUserStyleSheetLocationPreferenceKey @"WebKitUserStyleSheetLocationPreferenceKey" #define WebKitShouldPrintBackgroundsPreferenceKey @"WebKitShouldPrintBackgroundsPreferenceKey" @@ -48,6 +49,8 @@ #define WebKitShrinksStandaloneImagesToFitPreferenceKey @"WebKitShrinksStandaloneImagesToFit" #define WebKitJavaEnabledPreferenceKey @"WebKitJavaEnabled" #define WebKitJavaScriptEnabledPreferenceKey @"WebKitJavaScriptEnabled" +#define WebKitWebSecurityEnabledPreferenceKey @"WebKitWebSecurityEnabled" +#define WebKitAllowUniversalAccessFromFileURLsPreferenceKey @"WebKitAllowUniversalAccessFromFileURLs" #define WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey @"WebKitJavaScriptCanOpenWindowsAutomatically" #define WebKitPluginsEnabledPreferenceKey @"WebKitPluginsEnabled" #define WebKitDatabasesEnabledPreferenceKey @"WebKitDatabasesEnabledPreferenceKey" diff --git a/WebKit/mac/WebView/WebPreferences.mm b/WebKit/mac/WebView/WebPreferences.mm index e595861..6db14bd 100644 --- a/WebKit/mac/WebView/WebPreferences.mm +++ b/WebKit/mac/WebView/WebPreferences.mm @@ -306,6 +306,7 @@ static WebCacheModel cacheModelForMainBundle(void) @"16", WebKitDefaultFontSizePreferenceKey, @"13", WebKitDefaultFixedFontSizePreferenceKey, @"ISO-8859-1", WebKitDefaultTextEncodingNamePreferenceKey, + [NSNumber numberWithBool:NO], WebKitUsesEncodingDetectorPreferenceKey, [NSNumber numberWithBool:NO], WebKitUserStyleSheetEnabledPreferenceKey, @"", WebKitUserStyleSheetLocationPreferenceKey, [NSNumber numberWithBool:NO], WebKitShouldPrintBackgroundsPreferenceKey, @@ -313,6 +314,8 @@ static WebCacheModel cacheModelForMainBundle(void) [NSNumber numberWithBool:NO], WebKitShrinksStandaloneImagesToFitPreferenceKey, [NSNumber numberWithBool:YES], WebKitJavaEnabledPreferenceKey, [NSNumber numberWithBool:YES], WebKitJavaScriptEnabledPreferenceKey, + [NSNumber numberWithBool:YES], WebKitWebSecurityEnabledPreferenceKey, + [NSNumber numberWithBool:YES], WebKitAllowUniversalAccessFromFileURLsPreferenceKey, [NSNumber numberWithBool:YES], WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey, [NSNumber numberWithBool:YES], WebKitPluginsEnabledPreferenceKey, [NSNumber numberWithBool:YES], WebKitDatabasesEnabledPreferenceKey, @@ -663,7 +666,7 @@ static WebCacheModel cacheModelForMainBundle(void) return [self _boolValueForKey: WebKitAllowAnimatedImagesPreferenceKey]; } -- (void)setAllowsAnimatedImages:(BOOL)flag; +- (void)setAllowsAnimatedImages:(BOOL)flag { [self _setBoolValue: flag forKey: WebKitAllowAnimatedImagesPreferenceKey]; } @@ -688,7 +691,7 @@ static WebCacheModel cacheModelForMainBundle(void) return [self _boolValueForKey: WebKitDisplayImagesKey]; } -- (void)setAutosaves:(BOOL)flag; +- (void)setAutosaves:(BOOL)flag { _private->autosaves = flag; } @@ -862,6 +865,36 @@ static WebCacheModel cacheModelForMainBundle(void) _private->automaticallyDetectsCacheModel = automaticallyDetectsCacheModel; } +- (BOOL)usesEncodingDetector +{ + return [self _boolValueForKey: WebKitUsesEncodingDetectorPreferenceKey]; +} + +- (void)setUsesEncodingDetector:(BOOL)flag +{ + [self _setBoolValue: flag forKey: WebKitUsesEncodingDetectorPreferenceKey]; +} + +- (BOOL)isWebSecurityEnabled +{ + return [self _boolValueForKey: WebKitWebSecurityEnabledPreferenceKey]; +} + +- (void)setWebSecurityEnabled:(BOOL)flag +{ + [self _setBoolValue: flag forKey: WebKitWebSecurityEnabledPreferenceKey]; +} + +- (BOOL)allowUniversalAccessFromFileURLs +{ + return [self _boolValueForKey: WebKitAllowUniversalAccessFromFileURLsPreferenceKey]; +} + +- (void)setAllowUniversalAccessFromFileURLs:(BOOL)flag +{ + [self _setBoolValue: flag forKey: WebKitAllowUniversalAccessFromFileURLsPreferenceKey]; +} + - (NSTimeInterval)_backForwardCacheExpirationInterval { // FIXME: There's probably no good reason to read from the standard user defaults instead of self. @@ -878,7 +911,7 @@ static WebCacheModel cacheModelForMainBundle(void) [self _setFloatValue:factor forKey:WebKitPDFScaleFactorPreferenceKey]; } -- (PDFDisplayMode)PDFDisplayMode; +- (PDFDisplayMode)PDFDisplayMode { PDFDisplayMode value = [self _integerValueForKey:WebKitPDFDisplayModePreferenceKey]; if (value != kPDFDisplaySinglePage && value != kPDFDisplaySinglePageContinuous && value != kPDFDisplayTwoUp && value != kPDFDisplayTwoUpContinuous) { diff --git a/WebKit/mac/WebView/WebPreferencesPrivate.h b/WebKit/mac/WebView/WebPreferencesPrivate.h index 99ff49c..ae94cce 100644 --- a/WebKit/mac/WebView/WebPreferencesPrivate.h +++ b/WebKit/mac/WebView/WebPreferencesPrivate.h @@ -59,6 +59,9 @@ extern NSString *WebPreferencesRemovedNotification; - (BOOL)applicationChromeModeEnabled; - (void)setApplicationChromeModeEnabled:(BOOL)flag; +- (BOOL)usesEncodingDetector; +- (void)setUsesEncodingDetector:(BOOL)flag; + - (BOOL)respectStandardStyleKeyEquivalents; - (void)setRespectStandardStyleKeyEquivalents:(BOOL)flag; @@ -89,6 +92,12 @@ extern NSString *WebPreferencesRemovedNotification; - (BOOL)localStorageEnabled; - (void)setLocalStorageEnabled:(BOOL)localStorageEnabled; +- (BOOL)isWebSecurityEnabled; +- (void)setWebSecurityEnabled:(BOOL)flag; + +- (BOOL)allowUniversalAccessFromFileURLs; +- (void)setAllowUniversalAccessFromFileURLs:(BOOL)flag; + - (BOOL)zoomsTextOnly; - (void)setZoomsTextOnly:(BOOL)zoomsTextOnly; diff --git a/WebKit/mac/WebView/WebResource.mm b/WebKit/mac/WebView/WebResource.mm index a5caa41..e62ed1e 100644 --- a/WebKit/mac/WebView/WebResource.mm +++ b/WebKit/mac/WebView/WebResource.mm @@ -121,7 +121,7 @@ static NSString * const WebResourceResponseKey = @"WebResourceResponse" - (id)initWithCoder:(NSCoder *)decoder { - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); self = [super init]; if (!self) @@ -205,7 +205,7 @@ static NSString * const WebResourceResponseKey = @"WebResourceResponse" return [[self _webkit_invokeOnMainThread] data]; #endif - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); if (!_private->coreResource) return nil; @@ -221,7 +221,7 @@ static NSString * const WebResourceResponseKey = @"WebResourceResponse" return [[self _webkit_invokeOnMainThread] URL]; #endif - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); if (!_private->coreResource) return nil; @@ -236,7 +236,7 @@ static NSString * const WebResourceResponseKey = @"WebResourceResponse" return [[self _webkit_invokeOnMainThread] MIMEType]; #endif - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); if (!_private->coreResource) return nil; @@ -251,7 +251,7 @@ static NSString * const WebResourceResponseKey = @"WebResourceResponse" return [[self _webkit_invokeOnMainThread] textEncodingName]; #endif - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); if (!_private->coreResource) return nil; @@ -266,7 +266,7 @@ static NSString * const WebResourceResponseKey = @"WebResourceResponse" return [[self _webkit_invokeOnMainThread] frameName]; #endif - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); if (!_private->coreResource) return nil; @@ -323,7 +323,7 @@ static NSString * const WebResourceResponseKey = @"WebResourceResponse" } #endif - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); if (!_private->coreResource) return; @@ -343,7 +343,7 @@ static NSString * const WebResourceResponseKey = @"WebResourceResponse" return [[self _webkit_invokeOnMainThread] _initWithData:data URL:URL MIMEType:MIMEType textEncodingName:textEncodingName frameName:frameName response:response copyData:copyData]; #endif - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); self = [super init]; if (!self) @@ -379,7 +379,7 @@ static NSString * const WebResourceResponseKey = @"WebResourceResponse" return [[self _webkit_invokeOnMainThread] _suggestedFilename]; #endif - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); if (!_private->coreResource) return nil; @@ -404,7 +404,7 @@ static NSString * const WebResourceResponseKey = @"WebResourceResponse" return [[self _webkit_invokeOnMainThread] _response]; #endif - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); NSURLResponse *response = nil; if (_private->coreResource) @@ -419,7 +419,7 @@ static NSString * const WebResourceResponseKey = @"WebResourceResponse" return [[self _webkit_invokeOnMainThread] _stringValue]; #endif - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); WebCore::TextEncoding encoding; if (_private->coreResource) @@ -435,12 +435,14 @@ static NSString * const WebResourceResponseKey = @"WebResourceResponse" #ifdef MAIL_THREAD_WORKAROUND +static const double newMailBundleVersion = 1050.0; + @implementation WebResource (WebMailThreadWorkaround) + (BOOL)_needMailThreadWorkaroundIfCalledOffMainThread { - static BOOL isOldMail = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_MAIL_THREAD_WORKAROUND) - && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.mail"]; + static BOOL isOldMail = [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.mail"] + && [[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] doubleValue] < newMailBundleVersion; return isOldMail; } diff --git a/WebKit/mac/WebView/WebScriptDebugDelegate.h b/WebKit/mac/WebView/WebScriptDebugDelegate.h index 7334127..823cc35 100644 --- a/WebKit/mac/WebView/WebScriptDebugDelegate.h +++ b/WebKit/mac/WebView/WebScriptDebugDelegate.h @@ -37,7 +37,7 @@ #if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD) typedef int WebSourceId; #else -typedef int WebSourceId; // FIXME <rdar://problem/6263293>: Turn this int into an intptr_t once <rdar://problem/6263297> is fixed. +typedef intptr_t WebSourceId; #endif @class WebView; diff --git a/WebKit/mac/WebView/WebScriptDebugger.mm b/WebKit/mac/WebView/WebScriptDebugger.mm index d97cbcf..384f826 100644 --- a/WebKit/mac/WebView/WebScriptDebugger.mm +++ b/WebKit/mac/WebView/WebScriptDebugger.mm @@ -94,7 +94,9 @@ void WebScriptDebugger::initGlobalCallFrame(const DebuggerCallFrame& debuggerCal m_globalCallFrame = m_topCallFrame; WebView *webView = [webFrame webView]; - [[webView _scriptDebugDelegateForwarder] webView:webView didEnterCallFrame:m_topCallFrame.get() sourceId:static_cast<WebSourceId>(0) line:-1 forWebFrame:webFrame]; + WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView); + if (implementations->didEnterCallFrameFunc) + CallScriptDebugDelegate(implementations->didEnterCallFrameFunc, webView, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:), m_topCallFrame.get(), static_cast<NSInteger>(0), -1, webFrame); m_callingDelegate = false; } @@ -112,14 +114,23 @@ void WebScriptDebugger::sourceParsed(ExecState* exec, const SourceCode& source, WebFrame *webFrame = toWebFrame(exec->dynamicGlobalObject()); WebView *webView = [webFrame webView]; + WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView); + if (errorLine == -1) { - [[webView _scriptDebugDelegateForwarder] webView:webView didParseSource:nsSource baseLineNumber:source.firstLine() fromURL:nsURL sourceId:static_cast<WebSourceId>(source.provider()->asID()) forWebFrame:webFrame]; - [[webView _scriptDebugDelegateForwarder] webView:webView didParseSource:nsSource fromURL:[nsURL absoluteString] sourceId:static_cast<WebSourceId>(source.provider()->asID()) forWebFrame:webFrame]; // deprecated delegate method + if (implementations->didParseSourceFunc) { + if (implementations->didParseSourceExpectsBaseLineNumber) + CallScriptDebugDelegate(implementations->didParseSourceFunc, webView, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:), nsSource, source.firstLine(), nsURL, source.provider()->asID(), webFrame); + else + CallScriptDebugDelegate(implementations->didParseSourceFunc, webView, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:), nsSource, [nsURL absoluteString], source.provider()->asID(), webFrame); + } } else { NSString* nsErrorMessage = toNSString(errorMsg); NSDictionary *info = [[NSDictionary alloc] initWithObjectsAndKeys:nsErrorMessage, WebScriptErrorDescriptionKey, [NSNumber numberWithUnsignedInt:errorLine], WebScriptErrorLineNumberKey, nil]; NSError *error = [[NSError alloc] initWithDomain:WebScriptErrorDomain code:WebScriptGeneralErrorCode userInfo:info]; - [[webView _scriptDebugDelegateForwarder] webView:webView failedToParseSource:nsSource baseLineNumber:source.firstLine() fromURL:nsURL withError:error forWebFrame:webFrame]; + + if (implementations->failedToParseSourceFunc) + CallScriptDebugDelegate(implementations->failedToParseSourceFunc, webView, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:), nsSource, source.firstLine(), nsURL, error, webFrame); + [error release]; [info release]; } @@ -139,7 +150,9 @@ void WebScriptDebugger::callEvent(const DebuggerCallFrame& debuggerCallFrame, in m_topCallFrame.adoptNS([[WebScriptCallFrame alloc] _initWithGlobalObject:core(webFrame)->script()->windowScriptObject() debugger:this caller:m_topCallFrame.get() debuggerCallFrame:debuggerCallFrame]); WebView *webView = [webFrame webView]; - [[webView _scriptDebugDelegateForwarder] webView:webView didEnterCallFrame:m_topCallFrame.get() sourceId:static_cast<WebSourceId>(sourceID) line:lineNumber forWebFrame:webFrame]; + WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView); + if (implementations->didEnterCallFrameFunc) + CallScriptDebugDelegate(implementations->didEnterCallFrameFunc, webView, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame); m_callingDelegate = false; } @@ -155,7 +168,10 @@ void WebScriptDebugger::atStatement(const DebuggerCallFrame& debuggerCallFrame, WebView *webView = [webFrame webView]; [m_topCallFrame.get() _setDebuggerCallFrame:debuggerCallFrame]; - [[webView _scriptDebugDelegateForwarder] webView:webView willExecuteStatement:m_topCallFrame.get() sourceId:static_cast<WebSourceId>(sourceID) line:lineNumber forWebFrame:webFrame]; + + WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView); + if (implementations->willExecuteStatementFunc) + CallScriptDebugDelegate(implementations->willExecuteStatementFunc, webView, @selector(webView:willExecuteStatement:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame); m_callingDelegate = false; } @@ -171,7 +187,10 @@ void WebScriptDebugger::returnEvent(const DebuggerCallFrame& debuggerCallFrame, WebView *webView = [webFrame webView]; [m_topCallFrame.get() _setDebuggerCallFrame:debuggerCallFrame]; - [[webView _scriptDebugDelegateForwarder] webView:webView willLeaveCallFrame:m_topCallFrame.get() sourceId:static_cast<WebSourceId>(sourceID) line:lineNumber forWebFrame:webFrame]; + + WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView); + if (implementations->willLeaveCallFrameFunc) + CallScriptDebugDelegate(implementations->willLeaveCallFrameFunc, webView, @selector(webView:willLeaveCallFrame:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame); [m_topCallFrame.get() _clearDebuggerCallFrame]; m_topCallFrame = [m_topCallFrame.get() caller]; @@ -190,7 +209,9 @@ void WebScriptDebugger::exception(const DebuggerCallFrame& debuggerCallFrame, in WebView *webView = [webFrame webView]; [m_topCallFrame.get() _setDebuggerCallFrame:debuggerCallFrame]; - [[webView _scriptDebugDelegateForwarder] webView:webView exceptionWasRaised:m_topCallFrame.get() sourceId:static_cast<WebSourceId>(sourceID) line:lineNumber forWebFrame:webFrame]; + WebScriptDebugDelegateImplementationCache* implementations = WebViewGetScriptDebugDelegateImplementations(webView); + if (implementations->exceptionWasRaisedFunc) + CallScriptDebugDelegate(implementations->exceptionWasRaisedFunc, webView, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:), m_topCallFrame.get(), sourceID, lineNumber, webFrame); m_callingDelegate = false; } diff --git a/WebKit/mac/WebView/WebTextIterator.h b/WebKit/mac/WebView/WebTextIterator.h index ab5ca4e..d0c92f9 100644 --- a/WebKit/mac/WebView/WebTextIterator.h +++ b/WebKit/mac/WebView/WebTextIterator.h @@ -44,7 +44,9 @@ /*! @method advance - @abstract Makes the WebTextIterator iterate to the next visible text element. + @abstract Moves the WebTextIterator to the next bit of text or boundary between runs of text. + The iterator can break up runs of text however it finds convenient, so clients need to handle + text runs that are broken up into arbitrary pieces. */ - (void)advance; @@ -55,22 +57,30 @@ - (BOOL)atEnd; /*! - @method currentRange - @result A range, indicating the position within the document of the current text. + @method currentTextLength + @result Length of the current text. Length of zero means that the iterator is at a boundary, + such as an image, that separates runs of text. */ -- (DOMRange *)currentRange; +- (WebNSUInteger)currentTextLength; /*! @method currentTextPointer - @result A pointer to the current text. The pointer becomes invalid after any modification is made to the document; it must be used right away. + @result A pointer to the current text. Like the WebTextIterator itself, the pointer becomes + invalid after any modification is made to the document; it must be used before the document + is changed or the iterator is advanced. */ - (const unichar *)currentTextPointer; /*! - @method currentTextLength - @result lengthPtr Length of the current text. + @method currentRange + @abstract A function that identifies the specific document range that text corresponds to. + This can be quite costly to compute for non-text items, so when possible this should only + be called once the caller has determined that the text is text it wants to process. If you + call currentRange every time you advance the iterator, performance will be extremely slow + due to the cost of computing a DOM range. + @result A DOM range indicating the position within the document of the current text. */ -- (WebNSUInteger)currentTextLength; +- (DOMRange *)currentRange; @end diff --git a/WebKit/mac/WebView/WebUIDelegate.h b/WebKit/mac/WebView/WebUIDelegate.h index 8440bcb..c3dd9ff 100644 --- a/WebKit/mac/WebView/WebUIDelegate.h +++ b/WebKit/mac/WebView/WebUIDelegate.h @@ -133,7 +133,7 @@ typedef enum { @abstract Call this method to return an array of filenames from the file open panel. @param fileNames */ -- (void)chooseFilenames:(NSArray *)fileNames WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_AFTER_WEBKIT_VERSION_3_1); +- (void)chooseFilenames:(NSArray *)fileNames WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_IN_WEBKIT_VERSION_4_0); /*! @method cancel @@ -419,7 +419,7 @@ typedef enum { @discussion This method is passed a callback object instead of giving a return value so that it can be handled with a sheet. */ -- (void)webView:(WebView *)sender runOpenPanelForFileButtonWithResultListener:(id<WebOpenPanelResultListener>)resultListener allowMultipleFiles:(BOOL)allowMultipleFiles WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_AFTER_WEBKIT_VERSION_3_1); +- (void)webView:(WebView *)sender runOpenPanelForFileButtonWithResultListener:(id<WebOpenPanelResultListener>)resultListener allowMultipleFiles:(BOOL)allowMultipleFiles WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_IN_WEBKIT_VERSION_4_0); /*! @method webView:mouseDidMoveOverElement:modifierFlags: diff --git a/WebKit/mac/WebView/WebUIDelegatePrivate.h b/WebKit/mac/WebView/WebUIDelegatePrivate.h index bb4d780..8e67963 100644 --- a/WebKit/mac/WebView/WebUIDelegatePrivate.h +++ b/WebKit/mac/WebView/WebUIDelegatePrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -74,6 +74,7 @@ enum { WebMenuItemTagTextDirectionRightToLeft, WebMenuItemTagBaseApplication = 10000 }; +@class WebGeolocation; @class WebSecurityOrigin; @interface NSObject (WebUIDelegatePrivate) @@ -109,5 +110,7 @@ enum { - (BOOL)webView:(WebView *)sender shouldReplaceUploadFile:(NSString *)path usingGeneratedFilename:(NSString **)filename; - (NSString *)webView:(WebView *)sender generateReplacementFile:(NSString *)path; - + +- (BOOL)webView:(WebView *)sender frame:(WebFrame *)frame requestGeolocationPermission:(WebGeolocation *)geolocation securityOrigin:(WebSecurityOrigin *)origin; + @end diff --git a/WebKit/mac/WebView/WebView.mm b/WebKit/mac/WebView/WebView.mm index d3bbf4e..eabbc9d 100644 --- a/WebKit/mac/WebView/WebView.mm +++ b/WebKit/mac/WebView/WebView.mm @@ -39,7 +39,6 @@ #import "WebDatabaseManagerInternal.h" #import "WebDefaultEditingDelegate.h" #import "WebDefaultPolicyDelegate.h" -#import "WebDefaultScriptDebugDelegate.h" #import "WebDefaultUIDelegate.h" #import "WebDocument.h" #import "WebDocumentInternal.h" @@ -84,6 +83,7 @@ #import "WebPolicyDelegate.h" #import "WebPreferenceKeysPrivate.h" #import "WebPreferencesPrivate.h" +#import "WebScriptDebugDelegate.h" #import "WebTextIterator.h" #import "WebUIDelegate.h" #import "WebUIDelegatePrivate.h" @@ -92,6 +92,7 @@ #import <WebCore/ApplicationCacheStorage.h> #import <WebCore/Cache.h> #import <WebCore/ColorMac.h> +#import <WebCore/Cursor.h> #import <WebCore/Document.h> #import <WebCore/DocumentLoader.h> #import <WebCore/DragController.h> @@ -128,15 +129,14 @@ #import <WebKit/DOMExtensions.h> #import <WebKit/DOMPrivate.h> #import <WebKitSystemInterface.h> +#import <mach-o/dyld.h> +#import <objc/objc-auto.h> +#import <objc/objc-runtime.h> #import <runtime/ArrayPrototype.h> #import <runtime/DateInstance.h> #import <runtime/InitializeThreading.h> #import <runtime/JSLock.h> #import <runtime/JSValue.h> -#import <mach-o/dyld.h> -#import <objc/objc-auto.h> -#import <objc/objc-runtime.h> -#import <runtime/InitializeThreading.h> #import <wtf/Assertions.h> #import <wtf/HashTraits.h> #import <wtf/RefCountedLeakCounter.h> @@ -232,6 +232,10 @@ macro(moveToEndOfParagraph) \ macro(moveToEndOfParagraphAndModifySelection) \ macro(moveToEndOfSentence) \ macro(moveToEndOfSentenceAndModifySelection) \ +macro(moveToLeftEndOfLine) \ +macro(moveToLeftEndOfLineAndModifySelection) \ +macro(moveToRightEndOfLine) \ +macro(moveToRightEndOfLineAndModifySelection) \ macro(moveUp) \ macro(moveUpAndModifySelection) \ macro(moveWordBackward) \ @@ -287,6 +291,11 @@ macro(yankAndSelect) \ #define AppleKeyboardUIMode CFSTR("AppleKeyboardUIMode") #define UniversalAccessDomain CFSTR("com.apple.universalaccess") +#if USE(ACCELERATED_COMPOSITING) +#define UsingAcceleratedCompositingProperty @"_isUsingAcceleratedCompositing" +#endif + + static BOOL s_didSetCacheModel; static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer; @@ -340,7 +349,6 @@ static const char webViewIsOpen[] = "At least one WebView is still open."; id editingDelegate; id editingDelegateForwarder; id scriptDebugDelegate; - id scriptDebugDelegateForwarder; WebInspector *inspector; WebNodeHighlight *currentNodeHighlight; @@ -362,6 +370,7 @@ static const char webViewIsOpen[] = "At least one WebView is still open."; WebResourceDelegateImplementationCache resourceLoadDelegateImplementations; WebFrameLoadDelegateImplementationCache frameLoadDelegateImplementations; + WebScriptDebugDelegateImplementationCache scriptDebugDelegateImplementations; void *observationInfo; @@ -406,6 +415,14 @@ static const char webViewIsOpen[] = "At least one WebView is still open."; // When this flag is set, we will not make any subviews underneath this WebView. This means no WebFrameViews and no WebHTMLViews. BOOL useDocumentViews; + +#if USE(ACCELERATED_COMPOSITING) + // When this flag is set, next time a WebHTMLView draws, it needs to temporarily disable screen updates + // so that the NSView drawing is visually synchronized with CALayer updates. + BOOL needsOneShotDrawingSynchronization; + // Number of WebHTMLViews using accelerated compositing. Used to implement _isUsingAcceleratedCompositing. + int acceleratedFramesCount; +#endif } @end @@ -535,7 +552,6 @@ static BOOL grammarCheckingEnabled; [UIDelegateForwarder release]; [frameLoadDelegateForwarder release]; [editingDelegateForwarder release]; - [scriptDebugDelegateForwarder release]; [mediaStyle release]; @@ -661,6 +677,22 @@ static void WebKitInitializeApplicationCachePathIfNecessary() initialized = YES; } +static bool runningLeopardMail() +{ +#ifdef BUILDING_ON_LEOPARD + return [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.mail"]; +#endif + return NO; +} + +static bool runningTigerMail() +{ +#ifdef BUILDING_ON_TIGER + return [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.mail"]; +#endif + return NO; +} + - (void)_registerDraggedTypes { NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes]; @@ -678,7 +710,7 @@ static void WebKitInitializeApplicationCachePathIfNecessary() - (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName usesDocumentViews:(BOOL)usesDocumentViews { - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); #ifndef NDEBUG WTF::RefCountedLeakCounter::suppressMessages(webViewIsOpen); @@ -709,7 +741,9 @@ static void WebKitInitializeApplicationCachePathIfNecessary() WebKitInitializeLoggingChannelsIfNecessary(); WebCore::InitializeLoggingChannelsIfNecessary(); [WebHistoryItem initWindowWatcherIfNecessary]; +#if ENABLE(DATABASE) WebKitInitializeDatabasesIfNecessary(); +#endif WebKitInitializeApplicationCachePathIfNecessary(); patchMailRemoveAttributesMethod(); didOneTimeInitialization = true; @@ -722,11 +756,15 @@ static void WebKitInitializeApplicationCachePathIfNecessary() [WebFrame _createMainFrameWithPage:_private->page frameName:frameName frameView:frameView]; #ifndef BUILDING_ON_TIGER + NSRunLoop *runLoop = [NSRunLoop mainRunLoop]; +#else + NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; +#endif + if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES)) - [self scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; + [self scheduleInRunLoop:runLoop forMode:(NSString *)kCFRunLoopCommonModes]; else - [self scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; -#endif + [self scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode]; [self _addToAllWebViewsSet]; [self setGroupName:groupName]; @@ -905,7 +943,7 @@ static void WebKitInitializeApplicationCachePathIfNecessary() return uniqueExtensions; } -+ (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType; ++ (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType { MIMEType = [MIMEType lowercaseString]; Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType]; @@ -938,7 +976,7 @@ static void WebKitInitializeApplicationCachePathIfNecessary() return NO; } -- (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType; +- (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType { if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType]) return YES; @@ -1089,7 +1127,7 @@ static void WebKitInitializeApplicationCachePathIfNecessary() // Need this to make leak messages accurate. if (applicationIsTerminating) { gcController().garbageCollectNow(); - [WebCache empty]; + [WebCache setDisabled:YES]; } #endif } @@ -1296,6 +1334,7 @@ static void WebKitInitializeApplicationCachePathIfNecessary() settings->setDefaultFixedFontSize([preferences defaultFixedFontSize]); settings->setDefaultFontSize([preferences defaultFontSize]); settings->setDefaultTextEncodingName([preferences defaultTextEncodingName]); + settings->setUsesEncodingDetector([preferences usesEncodingDetector]); settings->setFantasyFontFamily([preferences fantasyFontFamily]); settings->setFixedFontFamily([preferences fixedFontFamily]); settings->setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]); @@ -1303,6 +1342,8 @@ static void WebKitInitializeApplicationCachePathIfNecessary() settings->setLocalStorageDatabasePath([preferences _localStorageDatabasePath]); settings->setJavaEnabled([preferences isJavaEnabled]); settings->setJavaScriptEnabled([preferences isJavaScriptEnabled]); + settings->setWebSecurityEnabled([preferences isWebSecurityEnabled]); + settings->setAllowUniversalAccessFromFileURLs([preferences allowUniversalAccessFromFileURLs]); settings->setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]); settings->setMinimumFontSize([preferences minimumFontSize]); settings->setMinimumLogicalFontSize([preferences minimumLogicalFontSize]); @@ -1332,15 +1373,13 @@ static void WebKitInitializeApplicationCachePathIfNecessary() settings->setUserStyleSheetLocation([NSURL URLWithString:@""]); settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]); settings->setNeedsKeyboardEventDisambiguationQuirks([self _needsKeyboardEventDisambiguationQuirks]); + settings->setNeedsLeopardMailQuirks(runningLeopardMail()); + settings->setNeedsTigerMailQuirks(runningTigerMail()); settings->setNeedsSiteSpecificQuirks(_private->useSiteSpecificSpoofing); settings->setWebArchiveDebugModeEnabled([preferences webArchiveDebugModeEnabled]); - settings->disableRangeMutationForOldAppleMail(WKAppVersionCheckLessThan(@"com.apple.mail", -1, 4.0)); settings->setOfflineWebApplicationCacheEnabled([preferences offlineWebApplicationCacheEnabled]); settings->setZoomsTextOnly([preferences zoomsTextOnly]); settings->setEnforceCSSMIMETypeInStrictMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1)); -#ifdef BUILDING_ON_LEOPARD - settings->setNeedsIChatMemoryCacheCallsQuirk([[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.iChat"]); -#endif } static inline IMP getMethod(id o, SEL s) @@ -1418,6 +1457,37 @@ WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementati return &webView->_private->frameLoadDelegateImplementations; } +- (void)_cacheScriptDebugDelegateImplementations +{ + WebScriptDebugDelegateImplementationCache *cache = &_private->scriptDebugDelegateImplementations; + id delegate = _private->scriptDebugDelegate; + + if (!delegate) { + bzero(cache, sizeof(WebScriptDebugDelegateImplementationCache)); + return; + } + + cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:)); + if (cache->didParseSourceFunc) + cache->didParseSourceExpectsBaseLineNumber = YES; + else + cache->didParseSourceFunc = getMethod(delegate, @selector(webView:didParseSource:fromURL:sourceId:forWebFrame:)); + + cache->failedToParseSourceFunc = getMethod(delegate, @selector(webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:)); + cache->didEnterCallFrameFunc = getMethod(delegate, @selector(webView:didEnterCallFrame:sourceId:line:forWebFrame:)); + cache->willExecuteStatementFunc = getMethod(delegate, @selector(webView:willExecuteStatement:sourceId:line:forWebFrame:)); + cache->willLeaveCallFrameFunc = getMethod(delegate, @selector(webView:willLeaveCallFrame:sourceId:line:forWebFrame:)); + cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:)); +} + +WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplementations(WebView *webView) +{ + static WebScriptDebugDelegateImplementationCache empty; + if (!webView) + return ∅ + return &webView->_private->scriptDebugDelegateImplementations; +} + - (id)_policyDelegateForwarder { if (!_private->policyDelegateForwarder) @@ -1444,19 +1514,12 @@ WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementati return _private->editingDelegateForwarder; } -- (id)_scriptDebugDelegateForwarder -{ - if (!_private->scriptDebugDelegateForwarder) - _private->scriptDebugDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->scriptDebugDelegate defaultTarget:[WebDefaultScriptDebugDelegate sharedScriptDebugDelegate] catchExceptions:_private->catchesDelegateExceptions]; - return _private->scriptDebugDelegateForwarder; -} - - (void)_closeWindow { [[self _UIDelegateForwarder] webViewClose:self]; } -+ (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType; ++ (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType { [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType]; [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType]; @@ -1467,7 +1530,7 @@ WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementati MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType); } -+ (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme; ++ (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme { NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme]; [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType]; @@ -1559,7 +1622,11 @@ WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementati static NSSet *manualNotifyKeys = nil; if (!manualNotifyKeys) manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey, - _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil]; + _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, +#if USE(ACCELERATED_COMPOSITING) + UsingAcceleratedCompositingProperty, // used by DRT +#endif + nil]; if ([manualNotifyKeys containsObject:key]) return NO; return YES; @@ -1994,9 +2061,9 @@ WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementati if (!coreFrame) return nil; - Selection selectionInsideRect(coreFrame->visiblePositionForPoint(rectStart), coreFrame->visiblePositionForPoint(rectEnd)); + VisibleSelection selectionInsideRect(coreFrame->visiblePositionForPoint(rectStart), coreFrame->visiblePositionForPoint(rectEnd)); - return [[[WebTextIterator alloc] initWithRange:[DOMRange _wrapRange:selectionInsideRect.toRange().get()]] autorelease]; + return [[[WebTextIterator alloc] initWithRange:[DOMRange _wrapRange:selectionInsideRect.toNormalizedRange().get()]] autorelease]; } - (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource @@ -2071,6 +2138,59 @@ WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementati return _private->page->areMemoryCacheClientCallsEnabled(); } +- (void)_setJavaScriptURLsAreAllowed:(BOOL)areAllowed +{ + _private->page->setJavaScriptURLsAreAllowed(areAllowed); +} + ++ (NSCursor *)_pointingHandCursor +{ + return handCursor().impl(); +} + +#if USE(ACCELERATED_COMPOSITING) +- (BOOL)_needsOneShotDrawingSynchronization +{ + return _private->needsOneShotDrawingSynchronization; +} + +- (void)_setNeedsOneShotDrawingSynchronization:(BOOL)needsSynchronization +{ + _private->needsOneShotDrawingSynchronization = needsSynchronization; +} + +- (void)_startedAcceleratedCompositingForFrame:(WebFrame*)webFrame +{ + BOOL entering = _private->acceleratedFramesCount == 0; + if (entering) + [self willChangeValueForKey:UsingAcceleratedCompositingProperty]; + ++_private->acceleratedFramesCount; + if (entering) + [self didChangeValueForKey:UsingAcceleratedCompositingProperty]; +} + +- (void)_stoppedAcceleratedCompositingForFrame:(WebFrame*)webFrame +{ + BOOL leaving = _private->acceleratedFramesCount == 1; + ASSERT(_private->acceleratedFramesCount > 0); + + if (leaving) + [self willChangeValueForKey:UsingAcceleratedCompositingProperty]; + --_private->acceleratedFramesCount; + if (leaving) + [self didChangeValueForKey:UsingAcceleratedCompositingProperty]; +} +#endif + +- (BOOL)_isUsingAcceleratedCompositing +{ +#if USE(ACCELERATED_COMPOSITING) + return _private->acceleratedFramesCount > 0; +#else + return NO; +#endif +} + @end @implementation _WebSafeForwarder @@ -2270,9 +2390,10 @@ WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementati static bool needsWebViewInitThreadWorkaround() { - static BOOL isOldInstaller = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_WEBVIEW_INIT_THREAD_WORKAROUND) - && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.installer"]; - return isOldInstaller && !pthread_main_np(); + static BOOL isOldClient = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_WEBVIEW_INIT_THREAD_WORKAROUND) + && ([[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.installer"] || + [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Automator"]); + return isOldClient && !pthread_main_np(); } - (id)initWithFrame:(NSRect)f @@ -2285,7 +2406,7 @@ static bool needsWebViewInitThreadWorkaround() if (needsWebViewInitThreadWorkaround()) return [[self _webkit_invokeOnMainThread] initWithFrame:f frameName:frameName groupName:groupName]; - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); return [self _initWithFrame:f frameName:frameName groupName:groupName usesDocumentViews:YES]; } @@ -2294,7 +2415,7 @@ static bool needsWebViewInitThreadWorkaround() if (needsWebViewInitThreadWorkaround()) return [[self _webkit_invokeOnMainThread] initWithCoder:decoder]; - WebCoreThreadViolationCheck(); + WebCoreThreadViolationCheckRoundTwo(); WebView *result = nil; @try { @@ -2500,7 +2621,8 @@ static bool needsWebViewInitThreadWorkaround() [self removeWindowObservers]; [self removeSizeObservers]; - } + } else + _private->page->willMoveOffscreen(); } - (void)viewDidMoveToWindow @@ -2515,6 +2637,7 @@ static bool needsWebViewInitThreadWorkaround() if ([self window]) { [self addWindowObservers]; [self addSizeObservers]; + _private->page->didMoveOnscreen(); } } @@ -2538,10 +2661,14 @@ static bool needsWebViewInitThreadWorkaround() BOOL windowIsKey = [window isKeyWindow]; BOOL windowOrSheetIsKey = windowIsKey || [[window attachedSheet] isKeyWindow]; - NSResponder *firstResponder = [window firstResponder]; + WebFrameView *mainFrameView = [[self mainFrame] frameView]; + id <WebDocumentView> documentView = [mainFrameView documentView]; + BOOL documentViewIsResigningFirstResponder = [documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _isResigningFirstResponder]; + + NSResponder *firstResponder = [window firstResponder]; if ([firstResponder isKindOfClass:[NSView class]] - && [(NSView*)firstResponder isDescendantOf:[[self mainFrame] frameView]]) - page->focusController()->setActive(windowIsKey); + && [(NSView *)firstResponder isDescendantOf:mainFrameView]) + page->focusController()->setActive(windowIsKey && !documentViewIsResigningFirstResponder); Frame* focusedFrame = page->focusController()->focusedOrMainFrame(); frame->selection()->setFocused(frame == focusedFrame && windowOrSheetIsKey); @@ -3001,6 +3128,11 @@ static bool needsWebViewInitThreadWorkaround() - (NSWindow *)hostWindow { + // -[WebView hostWindow] can sometimes be called from the WebView's [super dealloc] method + // so we check here to make sure it's not null. + if (!_private) + return nil; + return _private->hostWindow; } @@ -3522,18 +3654,14 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag) - (void)scheduleInRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode { -#ifndef BUILDING_ON_TIGER if (runLoop && mode) core(self)->addSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode)); -#endif } - (void)unscheduleFromRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode { -#ifndef BUILDING_ON_TIGER if (runLoop && mode) core(self)->removeSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode)); -#endif } - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection @@ -3660,8 +3788,8 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag) - (void)setScriptDebugDelegate:(id)delegate { _private->scriptDebugDelegate = delegate; - [_private->scriptDebugDelegateForwarder release]; - _private->scriptDebugDelegateForwarder = nil; + [self _cacheScriptDebugDelegateImplementations]; + if (delegate) [self _attachScriptDebuggerToAllFrames]; else @@ -4058,7 +4186,7 @@ static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValuePtr jsV return kit(page->mainFrame()->editor()->rangeForPoint(IntPoint([self convertPoint:point toView:nil])).get()); } -- (BOOL)_shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag; +- (BOOL)_shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag { // FIXME: This quirk is needed due to <rdar://problem/4985321> - We can phase it out once Aperture can adopt the new behavior on their end if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_APERTURE_QUIRK) && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Aperture"]) @@ -4096,7 +4224,7 @@ static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValuePtr jsV Frame* coreFrame = core([self _selectedOrMainFrame]); if (!coreFrame) return nil; - return kit(coreFrame->selection()->toRange().get()); + return kit(coreFrame->selection()->toNormalizedRange().get()); } - (NSSelectionAffinity)selectionAffinity @@ -4370,7 +4498,7 @@ FOR_EACH_RESPONDER_SELECTOR(FORWARD) @implementation WebView (WebViewEditingInMail) -- (void)_insertNewlineInQuotedContent; +- (void)_insertNewlineInQuotedContent { [[self _selectedOrMainFrame] _insertParagraphSeparatorInQuotedContent]; } @@ -5148,6 +5276,20 @@ static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SE return nil; } +static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer1, NSInteger integer2, id object2) +{ + if (!delegate) + return nil; + if (!self->_private->catchesDelegateExceptions) + return implementation(delegate, selector, self, object1, integer1, integer2, object2); + @try { + return implementation(delegate, selector, self, object1, integer1, integer2, object2); + } @catch(id exception) { + ReportDiscardedDelegateException(selector, exception); + } + return nil; +} + static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, NSInteger integer, id object3) { if (!delegate) @@ -5162,6 +5304,34 @@ static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SE return nil; } +static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer1, id object2, NSInteger integer2, id object3) +{ + if (!delegate) + return nil; + if (!self->_private->catchesDelegateExceptions) + return implementation(delegate, selector, self, object1, integer1, object2, integer2, object3); + @try { + return implementation(delegate, selector, self, object1, integer1, object2, integer2, object3); + } @catch(id exception) { + ReportDiscardedDelegateException(selector, exception); + } + return nil; +} + +static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer, id object2, id object3, id object4) +{ + if (!delegate) + return nil; + if (!self->_private->catchesDelegateExceptions) + return implementation(delegate, selector, self, object1, integer, object2, object3, object4); + @try { + return implementation(delegate, selector, self, object1, integer, object2, object3, object4); + } @catch(id exception) { + ReportDiscardedDelegateException(selector, exception); + } + return nil; +} + static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSTimeInterval interval, id object2, id object3) { if (!delegate) @@ -5303,6 +5473,26 @@ BOOL CallResourceLoadDelegateReturningBoolean(BOOL result, IMP implementation, W return result; } +id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, NSInteger integer, id object3) +{ + return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, object2, integer, object3); +} + +id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer1, id object2, NSInteger integer2, id object3) +{ + return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer1, object2, integer2, object3); +} + +id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer, id object2, id object3, id object4) +{ + return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer, object2, object3, object4); +} + +id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer1, NSInteger integer2, id object2) +{ + return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer1, integer2, object2); +} + // The form delegate needs to have it's own implementation, because the first argument is never the WebView id CallFormDelegate(WebView *self, SEL selector, id object1, id object2) diff --git a/WebKit/mac/WebView/WebViewInternal.h b/WebKit/mac/WebView/WebViewInternal.h index 25afb64..ad4f19c 100644 --- a/WebKit/mac/WebView/WebViewInternal.h +++ b/WebKit/mac/WebView/WebViewInternal.h @@ -81,7 +81,6 @@ typedef WebCore::Page WebCorePage; - (id)_UIDelegateForwarder; - (id)_editingDelegateForwarder; - (id)_policyDelegateForwarder; -- (id)_scriptDebugDelegateForwarder; - (void)_pushPerformingProgrammaticFocus; - (void)_popPerformingProgrammaticFocus; - (void)_incrementProgressForIdentifier:(id)identifier response:(NSURLResponse *)response; @@ -145,6 +144,13 @@ typedef WebCore::Page WebCorePage; + (BOOL)_canHandleRequest:(NSURLRequest *)request forMainFrame:(BOOL)forMainFrame; +#if USE(ACCELERATED_COMPOSITING) +- (BOOL)_needsOneShotDrawingSynchronization; +- (void)_setNeedsOneShotDrawingSynchronization:(BOOL)needsSynchronization; +- (void)_startedAcceleratedCompositingForFrame:(WebFrame*)webFrame; +- (void)_stoppedAcceleratedCompositingForFrame:(WebFrame*)webFrame; +#endif + @end typedef struct _WebResourceDelegateImplementationCache { @@ -183,8 +189,19 @@ typedef struct _WebFrameLoadDelegateImplementationCache { IMP didFinishDocumentLoadForFrameFunc; } WebFrameLoadDelegateImplementationCache; +typedef struct _WebScriptDebugDelegateImplementationCache { + BOOL didParseSourceExpectsBaseLineNumber; + IMP didParseSourceFunc; + IMP failedToParseSourceFunc; + IMP didEnterCallFrameFunc; + IMP willExecuteStatementFunc; + IMP willLeaveCallFrameFunc; + IMP exceptionWasRaisedFunc; +} WebScriptDebugDelegateImplementationCache; + WebResourceDelegateImplementationCache* WebViewGetResourceLoadDelegateImplementations(WebView *webView); WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementations(WebView *webView); +WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplementations(WebView *webView); #ifdef __cplusplus @@ -220,4 +237,9 @@ id CallResourceLoadDelegate(IMP, WebView *, SEL, id, id, NSInteger, id); BOOL CallResourceLoadDelegateReturningBoolean(BOOL, IMP, WebView *, SEL, id, id); +id CallScriptDebugDelegate(IMP, WebView *, SEL, id, id, NSInteger, id); +id CallScriptDebugDelegate(IMP, WebView *, SEL, id, NSInteger, id, NSInteger, id); +id CallScriptDebugDelegate(IMP, WebView *, SEL, id, NSInteger, id, id, id); +id CallScriptDebugDelegate(IMP, WebView *, SEL, id, NSInteger, NSInteger, id); + #endif diff --git a/WebKit/mac/WebView/WebViewPrivate.h b/WebKit/mac/WebView/WebViewPrivate.h index 95e1249..ada0e01 100644 --- a/WebKit/mac/WebView/WebViewPrivate.h +++ b/WebKit/mac/WebView/WebViewPrivate.h @@ -406,6 +406,13 @@ Could be worth adding to the API. - (void)setMemoryCacheDelegateCallsEnabled:(BOOL)suspend; - (BOOL)areMemoryCacheDelegateCallsEnabled; +- (void)_setJavaScriptURLsAreAllowed:(BOOL)setJavaScriptURLsAreAllowed; + ++ (NSCursor *)_pointingHandCursor; + +// SPI for DumpRenderTree +- (BOOL)_isUsingAcceleratedCompositing; + @end @interface WebView (WebViewPrintingPrivate) diff --git a/WebKit/qt/Api/qwebdatabase.cpp b/WebKit/qt/Api/qwebdatabase.cpp index 489ab17..0203d72 100644 --- a/WebKit/qt/Api/qwebdatabase.cpp +++ b/WebKit/qt/Api/qwebdatabase.cpp @@ -19,6 +19,9 @@ #include "config.h" #include "qwebdatabase.h" + +#if ENABLE(DATABASE) + #include "qwebdatabase_p.h" #include "qwebsecurityorigin.h" #include "qwebsecurityorigin_p.h" @@ -146,3 +149,5 @@ void QWebDatabase::removeDatabase(const QWebDatabase &db) QWebDatabase::~QWebDatabase() { } + +#endif diff --git a/WebKit/qt/Api/qwebdatabase.h b/WebKit/qt/Api/qwebdatabase.h index f4c368a..4e832bb 100644 --- a/WebKit/qt/Api/qwebdatabase.h +++ b/WebKit/qt/Api/qwebdatabase.h @@ -26,7 +26,7 @@ namespace WebCore { class DatabaseDetails; -}; +} class QWebDatabasePrivate; class QWebSecurityOrigin; diff --git a/WebKit/qt/Api/qwebdatabase_p.h b/WebKit/qt/Api/qwebdatabase_p.h index 988fb16..145115e 100644 --- a/WebKit/qt/Api/qwebdatabase_p.h +++ b/WebKit/qt/Api/qwebdatabase_p.h @@ -19,6 +19,8 @@ #ifndef _WEBDATABASE_P_H_ #define _WEBDATABASE_P_H_ +#if ENABLE(DATABASE) + #include <QString> #include <QtCore/qshareddata.h> @@ -36,3 +38,5 @@ public: #endif +#endif + diff --git a/WebKit/qt/Api/qwebframe.cpp b/WebKit/qt/Api/qwebframe.cpp index 4e82d54..725a880 100644 --- a/WebKit/qt/Api/qwebframe.cpp +++ b/WebKit/qt/Api/qwebframe.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2008,2009 Nokia Corporation and/or its subsidiary(-ies) Copyright (C) 2007 Staikos Computing Services Inc. This library is free software; you can redistribute it and/or @@ -106,6 +106,63 @@ void QWEBKIT_EXPORT qt_drt_setJavaScriptProfilingEnabled(QWebFrame* qframe, bool controller->disableProfiler(); } +// Pause a given CSS animation or transition on the target node at a specific time. +// If the animation or transition is already paused, it will update its pause time. +// This method is only intended to be used for testing the CSS animation and transition system. +bool QWEBKIT_EXPORT qt_drt_pauseAnimation(QWebFrame *qframe, const QString &animationName, double time, const QString &elementId) +{ + Frame* frame = QWebFramePrivate::core(qframe); + if (!frame) + return false; + + AnimationController* controller = frame->animation(); + if (!controller) + return false; + + Document* doc = frame->document(); + Q_ASSERT(doc); + + Node* coreNode = doc->getElementById(elementId); + if (!coreNode || !coreNode->renderer()) + return false; + + return controller->pauseAnimationAtTime(coreNode->renderer(), animationName, time); +} + +bool QWEBKIT_EXPORT qt_drt_pauseTransitionOfProperty(QWebFrame *qframe, const QString &propertyName, double time, const QString &elementId) +{ + Frame* frame = QWebFramePrivate::core(qframe); + if (!frame) + return false; + + AnimationController* controller = frame->animation(); + if (!controller) + return false; + + Document* doc = frame->document(); + Q_ASSERT(doc); + + Node* coreNode = doc->getElementById(elementId); + if (!coreNode || !coreNode->renderer()) + return false; + + return controller->pauseTransitionAtTime(coreNode->renderer(), propertyName, time); +} + +// Returns the total number of currently running animations (includes both CSS transitions and CSS animations). +int QWEBKIT_EXPORT qt_drt_numberOfActiveAnimations(QWebFrame *qframe) +{ + Frame* frame = QWebFramePrivate::core(qframe); + if (!frame) + return false; + + AnimationController* controller = frame->animation(); + if (!controller) + return false; + + return controller->numberOfActiveAnimations(); +} + void QWebFramePrivate::init(QWebFrame *qframe, WebCore::Page *webcorePage, QWebFrameData *frameData) { q = qframe; @@ -224,7 +281,7 @@ QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData) if (!frameData->url.isEmpty()) { WebCore::ResourceRequest request(frameData->url, frameData->referrer); - d->frame->loader()->load(request, frameData->name); + d->frame->loader()->load(request, frameData->name, false); } } @@ -255,24 +312,48 @@ QWebFrame::~QWebFrame() If you want to ensure that your QObjects remain accessible after loading a new URL, you should add them in a slot connected to the javaScriptWindowObjectCleared() signal. + + The \a object will never be explicitly deleted by QtWebKit. */ void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object) { - JSC::JSLock lock(false); - JSDOMWindow *window = toJSDOMWindow(d->frame); - JSC::Bindings::RootObject *root = d->frame->script()->bindingRootObject(); - if (!window) { - qDebug() << "Warning: couldn't get window object"; - return; - } + addToJavaScriptWindowObject(name, object, QScriptEngine::QtOwnership); +} + +/*! + \fn void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object, QScriptEngine::ValueOwnership own) + \overload + + Make \a object available under \a name from within the frame's JavaScript + context. The \a object will be inserted as a child of the frame's window + object. + + Qt properties will be exposed as JavaScript properties and slots as + JavaScript methods. + + If you want to ensure that your QObjects remain accessible after loading a + new URL, you should add them in a slot connected to the + javaScriptWindowObjectCleared() signal. + + The ownership of \a object is specified using \a own. +*/ +void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object, QScriptEngine::ValueOwnership ownership) +{ + JSC::JSLock lock(false); + JSDOMWindow* window = toJSDOMWindow(d->frame); + JSC::Bindings::RootObject* root = d->frame->script()->bindingRootObject(); + if (!window) { + qDebug() << "Warning: couldn't get window object"; + return; + } - JSC::ExecState* exec = window->globalExec(); + JSC::ExecState* exec = window->globalExec(); - JSC::JSObject *runtimeObject = - JSC::Bindings::QtInstance::getQtInstance(object, root)->createRuntimeObject(exec); + JSC::JSObject* runtimeObject = + JSC::Bindings::QtInstance::getQtInstance(object, root, ownership)->createRuntimeObject(exec); - JSC::PutPropertySlot slot; - window->put(exec, JSC::Identifier(exec, (const UChar *) name.constData(), name.length()), runtimeObject, slot); + JSC::PutPropertySlot slot; + window->put(exec, JSC::Identifier(exec, (const UChar *) name.constData(), name.length()), runtimeObject, slot); } /*! @@ -475,7 +556,7 @@ void QWebFrame::load(const QWebNetworkRequest &req) if (!postData.isEmpty()) request.setHTTPBody(WebCore::FormData::create(postData.constData(), postData.size())); - d->frame->loader()->load(request); + d->frame->loader()->load(request, false); if (d->parentFrame()) d->page->d->insideOpenCall = false; @@ -531,7 +612,7 @@ void QWebFrame::load(const QNetworkRequest &req, if (!body.isEmpty()) request.setHTTPBody(WebCore::FormData::create(body.constData(), body.size())); - d->frame->loader()->load(request); + d->frame->loader()->load(request, false); if (d->parentFrame()) d->page->d->insideOpenCall = false; @@ -556,7 +637,7 @@ void QWebFrame::setHtml(const QString &html, const QUrl &baseUrl) const QByteArray utf8 = html.toUtf8(); WTF::RefPtr<WebCore::SharedBuffer> data = WebCore::SharedBuffer::create(utf8.constData(), utf8.length()); WebCore::SubstituteData substituteData(data, WebCore::String("text/html"), WebCore::String("utf-8"), kurl); - d->frame->loader()->load(request, substituteData); + d->frame->loader()->load(request, substituteData, false); } /*! @@ -577,7 +658,7 @@ void QWebFrame::setContent(const QByteArray &data, const QString &mimeType, cons if (actualMimeType.isEmpty()) actualMimeType = QLatin1String("text/html"); WebCore::SubstituteData substituteData(buffer, WebCore::String(actualMimeType), WebCore::String(), kurl); - d->frame->loader()->load(request, substituteData); + d->frame->loader()->load(request, substituteData, false); } @@ -886,7 +967,7 @@ QWebHitTestResult QWebFrame::hitTestContent(const QPoint &pos) const if (!d->frame->view() || !d->frame->contentRenderer()) return QWebHitTestResult(); - HitTestResult result = d->frame->eventHandler()->hitTestResultAtPoint(d->frame->view()->windowToContents(pos), /*allowShadowContent*/ false); + HitTestResult result = d->frame->eventHandler()->hitTestResultAtPoint(d->frame->view()->windowToContents(pos), /*allowShadowContent*/ false, /*ignoreClipping*/ true); return QWebHitTestResult(new QWebHitTestResultPrivate(result)); } @@ -905,6 +986,10 @@ bool QWebFrame::event(QEvent *e) */ void QWebFrame::print(QPrinter *printer) const { + QPainter painter; + if (!painter.begin(printer)) + return; + const qreal zoomFactorX = printer->logicalDpiX() / qt_defaultDpi(); const qreal zoomFactorY = printer->logicalDpiY() / qt_defaultDpi(); @@ -950,7 +1035,6 @@ void QWebFrame::print(QPrinter *printer) const ascending = false; } - QPainter painter(printer); painter.scale(zoomFactorX, zoomFactorY); GraphicsContext ctx(&painter); @@ -988,7 +1072,8 @@ void QWebFrame::print(QPrinter *printer) const #endif // QT_NO_PRINTER /*! - Evaluate JavaScript defined by \a scriptSource using this frame as context. + Evaluates the JavaScript defined by \a scriptSource using this frame as context + and returns the result of the last executed statement. \sa addToJavaScriptWindowObject(), javaScriptWindowObjectCleared() */ @@ -1135,6 +1220,9 @@ QWebHitTestResultPrivate::QWebHitTestResultPrivate(const WebCore::HitTestResult WebCore::Frame *wframe = hitTest.targetFrame(); if (wframe) linkTargetFrame = QWebFramePrivate::kit(wframe); + Element* urlElement = hitTest.URLElement(); + if (urlElement) + linkTarget = urlElement->target(); isContentEditable = hitTest.isContentEditable(); isContentSelected = hitTest.isSelected(); @@ -1279,7 +1367,22 @@ QUrl QWebHitTestResult::linkTitle() const } /*! + \since 4.6 + Returns the name of the target frame that will load the link if it is activated. + + \sa linkTargetFrame +*/ +QString QWebHitTestResult::linkTarget() const +{ + if (!d) + return 0; + return d->linkTarget; +} + +/*! Returns the frame that will load the link if it is activated. + + \sa linkTarget */ QWebFrame *QWebHitTestResult::linkTargetFrame() const { diff --git a/WebKit/qt/Api/qwebframe.h b/WebKit/qt/Api/qwebframe.h index e53e2b5..d0fa193 100644 --- a/WebKit/qt/Api/qwebframe.h +++ b/WebKit/qt/Api/qwebframe.h @@ -25,6 +25,7 @@ #include <QtCore/qurl.h> #include <QtCore/qvariant.h> #include <QtGui/qicon.h> +#include <QtScript/qscriptengine.h> #if QT_VERSION >= 0x040400 #include <QtNetwork/qnetworkaccessmanager.h> #endif @@ -77,6 +78,7 @@ public: QUrl linkUrl() const; QUrl linkTitle() const; QWebFrame *linkTargetFrame() const; + QString linkTarget() const; QString alternateText() const; // for img, area, input and applet @@ -129,6 +131,7 @@ public: void setContent(const QByteArray &data, const QString &mimeType = QString(), const QUrl &baseUrl = QUrl()); void addToJavaScriptWindowObject(const QString &name, QObject *object); + void addToJavaScriptWindowObject(const QString &name, QObject *object, QScriptEngine::ValueOwnership ownership); QString toHtml() const; QString toPlainText() const; QString renderTreeDump() const; diff --git a/WebKit/qt/Api/qwebframe_p.h b/WebKit/qt/Api/qwebframe_p.h index 30f94cf..c541cd3 100644 --- a/WebKit/qt/Api/qwebframe_p.h +++ b/WebKit/qt/Api/qwebframe_p.h @@ -107,6 +107,7 @@ public: QUrl linkUrl; QString linkTitle; QPointer<QWebFrame> linkTargetFrame; + QString linkTarget; QString alternateText; QUrl imageUrl; QPixmap pixmap; diff --git a/WebKit/qt/Api/qwebpage.cpp b/WebKit/qt/Api/qwebpage.cpp index df40fa6..ed94489 100644 --- a/WebKit/qt/Api/qwebpage.cpp +++ b/WebKit/qt/Api/qwebpage.cpp @@ -64,6 +64,7 @@ #include "HitTestResult.h" #include "WindowFeatures.h" #include "LocalizedStrings.h" +#include "Cache.h" #include "runtime/InitializeThreading.h" #include <QApplication> @@ -429,6 +430,14 @@ void QWebPagePrivate::_q_webActionTriggered(bool checked) q->triggerAction(action, checked); } +#ifndef NDEBUG +void QWebPagePrivate::_q_cleanupLeakMessages() +{ + // Need this to make leak messages accurate. + cache()->setCapacities(0, 0, 0); +} +#endif + void QWebPagePrivate::updateAction(QWebPage::WebAction action) { QAction *a = actions[action]; @@ -454,60 +463,35 @@ void QWebPagePrivate::updateAction(QWebPage::WebAction action) case QWebPage::Reload: enabled = !loader->isLoading(); break; - case QWebPage::Cut: - enabled = editor->canCut(); - break; - case QWebPage::Copy: - enabled = editor->canCopy(); - break; - case QWebPage::Paste: - enabled = editor->canPaste(); - break; #ifndef QT_NO_UNDOSTACK case QWebPage::Undo: case QWebPage::Redo: // those two are handled by QUndoStack break; #endif // QT_NO_UNDOSTACK - case QWebPage::MoveToNextChar: - case QWebPage::MoveToPreviousChar: - case QWebPage::MoveToNextWord: - case QWebPage::MoveToPreviousWord: - case QWebPage::MoveToNextLine: - case QWebPage::MoveToPreviousLine: - case QWebPage::MoveToStartOfLine: - case QWebPage::MoveToEndOfLine: - case QWebPage::MoveToStartOfBlock: - case QWebPage::MoveToEndOfBlock: - case QWebPage::MoveToStartOfDocument: - case QWebPage::MoveToEndOfDocument: - case QWebPage::SelectNextChar: - case QWebPage::SelectPreviousChar: - case QWebPage::SelectNextWord: - case QWebPage::SelectPreviousWord: - case QWebPage::SelectNextLine: - case QWebPage::SelectPreviousLine: - case QWebPage::SelectStartOfLine: - case QWebPage::SelectEndOfLine: - case QWebPage::SelectStartOfBlock: - case QWebPage::SelectEndOfBlock: - case QWebPage::SelectStartOfDocument: - case QWebPage::SelectEndOfDocument: - case QWebPage::DeleteStartOfWord: - case QWebPage::DeleteEndOfWord: + case QWebPage::SelectAll: // editor command is always enabled + break; case QWebPage::SetTextDirectionDefault: case QWebPage::SetTextDirectionLeftToRight: case QWebPage::SetTextDirectionRightToLeft: - case QWebPage::ToggleBold: - case QWebPage::ToggleItalic: - case QWebPage::ToggleUnderline: - enabled = editor->canEditRichly(); - if (enabled) - checked = editor->command(editorCommandForWebActions(action)).state() != FalseTriState; - else - checked = false; + enabled = editor->canEdit(); + checked = false; + break; + default: { + // see if it's an editor command + const char* commandName = editorCommandForWebActions(action); + + // if it's an editor command, let it's logic determine state + if (commandName) { + Editor::Command command = editor->command(commandName); + enabled = command.isEnabled(); + if (enabled) + checked = command.state() != FalseTriState; + else + checked = false; + } break; - default: break; + } } a->setEnabled(enabled); @@ -561,6 +545,8 @@ void QWebPagePrivate::updateEditorActions() updateAction(QWebPage::ToggleBold); updateAction(QWebPage::ToggleItalic); updateAction(QWebPage::ToggleUnderline); + updateAction(QWebPage::InsertParagraphSeparator); + updateAction(QWebPage::InsertLineSeparator); } void QWebPagePrivate::timerEvent(QTimerEvent *ev) @@ -1052,9 +1038,9 @@ QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const case Qt::ImCursorPosition: { Frame *frame = d->page->focusController()->focusedFrame(); if (frame) { - Selection selection = frame->selection()->selection(); + VisibleSelection selection = frame->selection()->selection(); if (selection.isCaret()) { - return QVariant(selection.start().offset()); + return QVariant(selection.start().m_offset); } } return QVariant(); @@ -1119,8 +1105,13 @@ QVariant QWebPage::inputMethodQuery(Qt::InputMethodQuery property) const \enum QWebPage::WebAction This enum describes the types of action which can be performed on the web page. - Actions which are related to text editing, cursor movement, and text selection - only have an effect if \l contentEditable is true. + + Actions only have an effect when they are applicable. The availability of + actions can be be determined by checking \l{QAction::}{enabled()} on the + action returned by \l{QWebPage::}{action()}. + + One method of enabling the text editing, cursor movement, and text selection actions + is by setting \l contentEditable to true. \value NoWebAction No action is triggered. \value OpenLink Open the current link. @@ -1251,6 +1242,9 @@ QWebPage::QWebPage(QObject *parent) setView(qobject_cast<QWidget *>(parent)); connect(this, SIGNAL(loadProgress(int)), this, SLOT(_q_onLoadProgressChanged(int))); +#ifndef NDEBUG + connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(_q_cleanupLeakMessages())); +#endif } /*! @@ -1340,7 +1334,7 @@ void QWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg) { #ifndef QT_NO_MESSAGEBOX - QMessageBox::information(d->view, mainFrame()->title(), msg, QMessageBox::Ok); + QMessageBox::information(d->view, tr("JavaScript Alert - %1").arg(mainFrame()->url().host()), msg, QMessageBox::Ok); #endif } @@ -1355,7 +1349,7 @@ bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg) #ifdef QT_NO_MESSAGEBOX return true; #else - return QMessageBox::Yes == QMessageBox::information(d->view, mainFrame()->title(), msg, QMessageBox::Yes, QMessageBox::No); + return QMessageBox::Yes == QMessageBox::information(d->view, tr("JavaScript Confirm - %1").arg(mainFrame()->url().host()), msg, QMessageBox::Yes, QMessageBox::No); #endif } @@ -1372,7 +1366,7 @@ bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QStr { bool ok = false; #ifndef QT_NO_INPUTDIALOG - QString x = QInputDialog::getText(d->view, mainFrame()->title(), msg, QLineEdit::Normal, defaultValue, &ok); + QString x = QInputDialog::getText(d->view, tr("JavaScript Prompt - %1").arg(mainFrame()->url().host()), msg, QLineEdit::Normal, defaultValue, &ok); if (ok && result) { *result = x; } @@ -1471,9 +1465,16 @@ void QWebPage::triggerAction(WebAction action, bool checked) openNewWindow(url, frame); break; } - case CopyLinkToClipboard: + case CopyLinkToClipboard: { +#if defined(Q_WS_X11) + bool oldSelectionMode = Pasteboard::generalPasteboard()->isSelectionMode(); + Pasteboard::generalPasteboard()->setSelectionMode(true); + editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText()); + Pasteboard::generalPasteboard()->setSelectionMode(oldSelectionMode); +#endif editor->copyURL(d->hitTestResult.linkUrl(), d->hitTestResult.linkText()); break; + } case OpenImageInNewWindow: openNewWindow(d->hitTestResult.imageUrl(), frame); break; @@ -1550,7 +1551,7 @@ void QWebPage::setViewportSize(const QSize &size) const if (frame->d->frame && frame->d->frame->view()) { WebCore::FrameView* view = frame->d->frame->view(); view->setFrameRect(QRect(QPoint(0, 0), size)); - frame->d->frame->forceLayout(); + view->forceLayout(); view->adjustViewSize(); } } @@ -1580,7 +1581,7 @@ void QWebPage::setFixedLayoutSize(const QSize &size) const if (frame->d->frame && frame->d->frame->view()) { WebCore::FrameView* view = frame->d->frame->view(); view->setFixedLayoutSize(size); - frame->d->frame->forceLayout(); + view->forceLayout(); } } @@ -1602,7 +1603,7 @@ void QWebPage::setUseFixedLayout(bool useFixedLayout) if (frame->d->frame && frame->d->frame->view()) { WebCore::FrameView* view = frame->d->frame->view(); view->setUseFixedLayout(useFixedLayout); - frame->d->frame->forceLayout(); + view->forceLayout(); } } @@ -1632,7 +1633,7 @@ bool QWebPage::acceptNavigationRequest(QWebFrame *frame, const QWebNetworkReques return true; case DelegateExternalLinks: - if (WebCore::FrameLoader::shouldTreatSchemeAsLocal(request.url().scheme())) + if (WebCore::FrameLoader::shouldTreatURLSchemeAsLocal(request.url().scheme())) return true; emit linkClicked(request.url()); return false; @@ -1790,6 +1791,9 @@ QAction *QWebPage::action(WebAction action) const case MoveToEndOfDocument: text = tr("Move the cursor to the end of the document"); break; + case SelectAll: + text = tr("Select all"); + break; case SelectNextChar: text = tr("Select to the next character"); break; @@ -1862,6 +1866,13 @@ QAction *QWebPage::action(WebAction action) const text = contextMenuItemTagInspectElement(); break; + case InsertParagraphSeparator: + text = tr("Insert a new paragraph"); + break; + case InsertLineSeparator: + text = tr("Insert a new line"); + break; + case NoWebAction: return 0; } @@ -2389,7 +2400,8 @@ QWebPluginFactory *QWebPage::pluginFactory() const \list \o %Platform% and %Subplatform% are expanded to the windowing system and the operation system. \o %Security% expands to U if SSL is enabled, otherwise N. SSL is enabled if QSslSocket::supportsSsl() returns true. - \o %Locale% is replaced with QLocale::name(). + \o %Locale% is replaced with QLocale::name(). The locale is determined from the view of the QWebPage. If no view is set on the QWebPage, + then a default constructed QLocale is used instead. \o %WebKitVersion% currently expands to 527+ \o %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version. \endlist @@ -2577,7 +2589,7 @@ void QWebPagePrivate::_q_onLoadProgressChanged(int) { \sa bytesReceived() */ quint64 QWebPage::totalBytes() const { - return d->m_bytesReceived; + return d->m_totalBytes; } @@ -2587,7 +2599,7 @@ quint64 QWebPage::totalBytes() const { \sa totalBytes() */ quint64 QWebPage::bytesReceived() const { - return d->m_totalBytes; + return d->m_bytesReceived; } /*! @@ -2621,10 +2633,13 @@ quint64 QWebPage::bytesReceived() const { /*! \fn void QWebPage::linkHovered(const QString &link, const QString &title, const QString &textContent) - This signal is emitted when the mouse is hovering over a link. - The first parameter is the \a link url, the second is the link \a title - if any, and third \a textContent is the text content. Method is emitter with both - empty parameters when the mouse isn't hovering over any link element. + This signal is emitted when the mouse hovers over a link. + + \a link contains the link url. + \a title is the link element's title, if it is specified in the markup. + \a textContent provides text within the link element, e.g., text inside an HTML anchor tag. + + When the mouse leaves the link element the signal is emitted with empty parameters. \sa linkClicked() */ diff --git a/WebKit/qt/Api/qwebpage.h b/WebKit/qt/Api/qwebpage.h index 2bbbc2a..2853fcc 100644 --- a/WebKit/qt/Api/qwebpage.h +++ b/WebKit/qt/Api/qwebpage.h @@ -325,6 +325,9 @@ protected: private: Q_PRIVATE_SLOT(d, void _q_onLoadProgressChanged(int)) Q_PRIVATE_SLOT(d, void _q_webActionTriggered(bool checked)) +#ifndef NDEBUG + Q_PRIVATE_SLOT(d, void _q_cleanupLeakMessages()) +#endif QWebPagePrivate *d; friend class QWebFrame; diff --git a/WebKit/qt/Api/qwebpage_p.h b/WebKit/qt/Api/qwebpage_p.h index fd915a2..a897bf1 100644 --- a/WebKit/qt/Api/qwebpage_p.h +++ b/WebKit/qt/Api/qwebpage_p.h @@ -79,6 +79,9 @@ public: void _q_onLoadProgressChanged(int); void _q_webActionTriggered(bool checked); +#ifndef NDEBUG + void _q_cleanupLeakMessages(); +#endif void updateAction(QWebPage::WebAction action); void updateNavigationActions(); void updateEditorActions(); diff --git a/WebKit/qt/Api/qwebsecurityorigin.cpp b/WebKit/qt/Api/qwebsecurityorigin.cpp index 5217362..c08785f 100644 --- a/WebKit/qt/Api/qwebsecurityorigin.cpp +++ b/WebKit/qt/Api/qwebsecurityorigin.cpp @@ -101,7 +101,11 @@ int QWebSecurityOrigin::port() const */ qint64 QWebSecurityOrigin::databaseUsage() const { +#if ENABLE(DATABASE) return DatabaseTracker::tracker().usageForOrigin(d->origin.get()); +#else + return 0; +#endif } /*! @@ -109,7 +113,11 @@ qint64 QWebSecurityOrigin::databaseUsage() const */ qint64 QWebSecurityOrigin::databaseQuota() const { +#if ENABLE(DATABASE) return DatabaseTracker::tracker().quotaForOrigin(d->origin.get()); +#else + return 0; +#endif } /*! @@ -121,7 +129,9 @@ qint64 QWebSecurityOrigin::databaseQuota() const */ void QWebSecurityOrigin::setDatabaseQuota(qint64 quota) { +#if ENABLE(DATABASE) DatabaseTracker::tracker().setQuota(d->origin.get(), quota); +#endif } /*! diff --git a/WebKit/qt/Api/qwebsecurityorigin.h b/WebKit/qt/Api/qwebsecurityorigin.h index ebe4a77..b52194d 100644 --- a/WebKit/qt/Api/qwebsecurityorigin.h +++ b/WebKit/qt/Api/qwebsecurityorigin.h @@ -28,7 +28,7 @@ namespace WebCore { class SecurityOrigin; class ChromeClientQt; -}; +} class QWebSecurityOriginPrivate; class QWebDatabase; diff --git a/WebKit/qt/Api/qwebsettings.cpp b/WebKit/qt/Api/qwebsettings.cpp index 42baf93..f6acc42 100644 --- a/WebKit/qt/Api/qwebsettings.cpp +++ b/WebKit/qt/Api/qwebsettings.cpp @@ -183,6 +183,10 @@ void QWebSettingsPrivate::apply() value = attributes.value(QWebSettings::LocalStorageDatabaseEnabled, global->attributes.value(QWebSettings::LocalStorageDatabaseEnabled)); settings->setLocalStorageEnabled(value); + + value = attributes.value(QWebSettings::AllowUniversalAccessFromFileUrls, + global->attributes.value(QWebSettings::AllowUniversalAccessFromFileUrls)); + settings->setAllowUniversalAccessFromFileURLs(value); } else { QList<QWebSettingsPrivate *> settings = *::allSettings(); for (int i = 0; i < settings.count(); ++i) @@ -236,10 +240,6 @@ QWebSettings *QWebSettings::globalSettings() setOfflineStoragePath() with an appropriate file path, and can limit the quota for each application by calling setOfflineStorageDefaultQuota(). - The performance of Web applications can be enhanced with the use of an - offline cache. This can be enabled by calling setOfflineWebApplicationCache() - with an appropriate file path. - \sa QWebPage::settings(), QWebView::settings(), {Browser} */ @@ -292,8 +292,7 @@ QWebSettings *QWebSettings::globalSettings() programs. \value JavaEnabled Enables or disables Java applets. Currently Java applets are not supported. - \value PluginsEnabled Enables or disables plugins in web pages. - Currently Flash and other plugins are not supported. + \value PluginsEnabled Enables or disables plugins in Web pages. \value PrivateBrowsingEnabled Private browsing prevents WebKit from recording visited pages in the history and storing web page icons. \value JavascriptCanOpenWindows Specifies whether JavaScript programs @@ -315,6 +314,8 @@ QWebSettings *QWebSettings::globalSettings() web application cache feature is enabled or not. \value LocalStorageDatabaseEnabled Specifies whether support for the HTML 5 local storage feature is enabled or not. + \value AllowUniversalAccessFromFileUrls Specifies whether documents from file + Urls should be granted universal access (e.g., to HTTP and HTTPS documents). */ /*! @@ -343,6 +344,7 @@ QWebSettings::QWebSettings() d->attributes.insert(QWebSettings::OfflineStorageDatabaseEnabled, true); d->attributes.insert(QWebSettings::OfflineWebApplicationCacheEnabled, true); d->attributes.insert(QWebSettings::LocalStorageDatabaseEnabled, true); + d->attributes.insert(QWebSettings::AllowUniversalAccessFromFileUrls, true); d->offlineStorageDefaultQuota = 5 * 1024 * 1024; } @@ -710,9 +712,10 @@ qint64 QWebSettings::offlineStorageDefaultQuota() return QWebSettings::globalSettings()->d->offlineStorageDefaultQuota; } -/*! - \since 4.5 - +/* + \internal + \relates QWebSettings + Sets the path for HTML5 offline web application cache storage to \a path. \a path must point to an existing directory where the cache is stored. @@ -721,22 +724,23 @@ qint64 QWebSettings::offlineStorageDefaultQuota() \sa offlineWebApplicationCachePath() */ -void QWebSettings::setOfflineWebApplicationCachePath(const QString& path) +void QWEBKIT_EXPORT qt_websettings_setOfflineWebApplicationCachePath(const QString& path) { #if ENABLE(OFFLINE_WEB_APPLICATIONS) WebCore::cacheStorage().setCacheDirectory(path); #endif } -/*! - \since 4.5 - +/* + \internal + \relates QWebSettings + Returns the path of the HTML5 offline web application cache storage or an empty string if the feature is disabled. \sa setOfflineWebApplicationCachePath() */ -QString QWebSettings::offlineWebApplicationCachePath() +QString QWEBKIT_EXPORT qt_websettings_offlineWebApplicationCachePath() { #if ENABLE(OFFLINE_WEB_APPLICATIONS) return WebCore::cacheStorage().cacheDirectory(); @@ -747,6 +751,7 @@ QString QWebSettings::offlineWebApplicationCachePath() /* \since 4.5 + \relates QWebSettings Sets the path for HTML5 local storage databases to \a path. @@ -756,7 +761,6 @@ QString QWebSettings::offlineWebApplicationCachePath() \sa localStorageDatabasePath() */ - void QWEBKIT_EXPORT qt_websettings_setLocalStorageDatabasePath(QWebSettings* settings, const QString& path) { QWebSettingsPrivate *d = settings->handle(); @@ -766,6 +770,7 @@ void QWEBKIT_EXPORT qt_websettings_setLocalStorageDatabasePath(QWebSettings* set /* \since 4.5 + \relates QWebSettings Returns the path for HTML5 local storage databases or an empty string if the feature is disabled. diff --git a/WebKit/qt/Api/qwebsettings.h b/WebKit/qt/Api/qwebsettings.h index 4251fbb..5610797 100644 --- a/WebKit/qt/Api/qwebsettings.h +++ b/WebKit/qt/Api/qwebsettings.h @@ -63,7 +63,8 @@ public: PrintElementBackgrounds, OfflineStorageDatabaseEnabled, OfflineWebApplicationCacheEnabled, - LocalStorageDatabaseEnabled + LocalStorageDatabaseEnabled, + AllowUniversalAccessFromFileUrls }; enum WebGraphic { MissingImageGraphic, @@ -112,9 +113,6 @@ public: static void setOfflineStorageDefaultQuota(qint64 maximumSize); static qint64 offlineStorageDefaultQuota(); - static void setOfflineWebApplicationCachePath(const QString& path); - static QString offlineWebApplicationCachePath(); - inline QWebSettingsPrivate* handle() const { return d; } private: diff --git a/WebKit/qt/ChangeLog b/WebKit/qt/ChangeLog index 04575c9..ba6d3ae 100644 --- a/WebKit/qt/ChangeLog +++ b/WebKit/qt/ChangeLog @@ -1,8 +1,355 @@ -2009-02-03 Mark Rowe <mrowe@apple.com> +2009-03-26 Simon Hausmann <simon.hausmann@nokia.com> - Merge r40508. + Rubber-stamped by Tor Arne Vestbø. + + Fix the documentation of the QLocale usage in userAgentForUrl. + + * Api/qwebpage.cpp: + +2009-03-20 Erik L. Bunce <elbunce@xendom.com> + + Reviewed by Simon Hausmann. + + Fix for InsertParagraphSeparator and InsertLineSeparator so that + QWebPage::action() creates QActions for them. Also make sure they get + updated appropriately. + + * Api/qwebpage.cpp: + (QWebPagePrivate::updateEditorActions): + (QWebPage::action): + * tests/qwebpage/tst_qwebpage.cpp: + (tst_QWebPage::textEditing): + +2009-03-20 Erik L. Bunce <elbunce@xendom.com> + + Reviewed by Tor Arne Vestbø. + + Fix QWebPage::WebActions action states to more closely match when they are + actually applicable and remove erroneous documentation. + + * Most WebActions implemented using editor commands now use the + Editor::Command::isEnabled() to control their availability. + * SelectAll is always enabled (since it's editor command is). + * SetTextDirection{} family of WebActions are available when canEdit() is true + and not just canEditRichly(). + + Fix and clarify documentation about the availability of various web actions. + + * Api/qwebpage.cpp: + (QWebPagePrivate::updateAction): + (QWebPagePrivate::updateEditorActions): + * tests/qwebpage/tst_qwebpage.cpp: + (tst_QWebPage::textSelection): + +2009-03-19 Ariya Hidayat <ariya.hidayat@trolltech.com> + + Reviewed by Simon Hausmann. + + Fixes pedantic compilation in QtWebKit. + + There are no semi-colons after namespace declarations. + + * Api/qwebdatabase.h: + * Api/qwebsecurityorigin.h: + +2009-03-19 David Boddie <dboddie@trolltech.com> + + Reviewed by Simon Hausmann. + + Doc: Removed obsolete warning about Flash and other plugins. + + * Api/qwebsettings.cpp: + +2009-03-19 Paul Olav Tvete <paul.tvete@nokia.com> + + Reviewed by Simon Hausmann. + + Properly escape tooltip text + + ManualTest: http://xkcd.com/554/ + + * WebCoreSupport/ChromeClientQt.cpp: + (WebCore::ChromeClientQt::setToolTip): + +2009-03-10 Adam Treat <adam.treat@torchmobile.com> + + Build fix for Qt after r41555. + + * Api/qwebpage.cpp: + (QWebPage::acceptNavigationRequest): + +2009-03-10 Xan Lopez <xlopez@igalia.com> + + Build fix, no review. + + * Api/qwebpage.cpp: + (QWebPage::inputMethodQuery): + +2009-03-07 Adam Treat <adam.treat@torchmobile.com> + + Reviewed by Cameron Zwarich. + + These methods are clearly returning the wrong values as the two were + returning swapped information. + + * Api/qwebpage.cpp: + (QWebPage::totalBytes): + (QWebPage::bytesReceived): + +2009-03-05 Ariya Hidayat <ariya.hidayat@nokia.com> + + Rubber-stamped by Simon Hausmann. + + [Qt] NPAPI plugins are supported, adjust the API documentation. + + * Api/qwebsettings.cpp: + +2009-03-04 Adam Barth <abath@webkit.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=24356 + + Fix WebKit style for allowUniversalAccessFromFileURLs. + + * Api/qwebsettings.cpp: + (QWebSettingsPrivate::apply): - 2009-02-02 Geoffrey Garen <ggaren@apple.com> +2009-03-03 Adam Barth <abarth@webkit.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=24340 + + Expose AllowUniversalAccessFromFileUrls to Qt clients. + + * Api/qwebsettings.cpp: + (QWebSettingsPrivate::apply): + (QWebSettings::QWebSettings): + * Api/qwebsettings.h: + +2009-03-03 Ariya Hidayat <ariya.hidayat@trolltech.com> + + Rubber-stamped by Simon Hausmann. + + [Qt] Create and update the action for SelectAll. + + * Api/qwebpage.cpp: + (QWebPagePrivate::updateAction): + (QWebPagePrivate::updateEditorActions): + (QWebPage::action): + * tests/qwebpage/tst_qwebpage.cpp: + (tst_QWebPage::textSelection): + +2009-03-02 Adam Treat <adam.treat@torchmobile.com> + + Reviewed by Eric Seidel. + + Add three new drt helper functions that enable all of the tests in + LayoutTests/animation/* and LayoutTests/transitions/* to now pass. + + * Api/qwebframe.cpp: + (qt_drt_pauseAnimation): + (qt_drt_pauseTransitionOfProperty): + (qt_drt_numberOfActiveAnimations): + +2009-03-02 Benjamin C Meyer <benjamin.meyer@torchmobile.com> + + Reviewed by George Staikos. + + https://bugs.webkit.org/show_bug.cgi?id=21230 + On X11 match the behavior of Firefox and also copy the url to the + clipboard selection when the action Copy Link Location is executed. + + * Api/qwebpage.cpp: + (QWebPage::triggerAction): + +2009-02-25 Kavindra Palaraja <kavindra.palaraja@nokia.com> + + Reviewed by Simon Hausmann. + + Fix the documentation for the linkHovered signal. + + * Api/qwebpage.cpp: + +2009-02-23 Adam Treat <adam.treat@torchmobile.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=24094 + Make sure to empty the cache on exit to get rid of superfluous leak messages + for CachedResource's in order to keep the leak messages accurate. This + is analagous to what the Mac port is doing on application exit when all + WebView's have been closed. + + * Api/qwebpage.cpp: + (QWebPagePrivate::_q_cleanupLeakMessages): + (QWebPage::QWebPage): + * Api/qwebpage.h: + * Api/qwebpage_p.h: + +2009-02-23 Thiago Macieira <thiago.macieira@nokia.com> + + Reviewed by Simon Hausmann. + + Fix the Copyright notices in a few files + + * WebKit_pch.h: + +2009-02-16 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Tor Arne Vestbø. + + Avoid loading plugins when they're disabled in the settings. + + * WebCoreSupport/FrameLoaderClientQt.cpp: + (WebCore::FrameLoaderClientQt::canShowMIMEType): Don't call into the + PluginDatabase if plugins are disabled in the settings. + +2009-02-13 Benjamin C Meyer <benjamin.meyer@torchmobile.com> + + Reviewed by Nikolas Zimmermann. + + https://bugs.webkit.org/show_bug.cgi?id=23738 + Expose the url elements target frame string. This is the sister function + to the existing linkTargetFrame which returns the QWebFrame*. When the + linkTargetFrame is 0 it is useful to know what the target was to be. + + * Api/qwebframe.cpp: + (QWebHitTestResultPrivate::QWebHitTestResultPrivate): + (QWebHitTestResult::linkTarget): + * Api/qwebframe.h: + * Api/qwebframe_p.h: + * tests/qwebframe/tst_qwebframe.cpp: + +2009-02-13 David Boddie <dboddie@trolltech.com> + + Reviewed by Simon Hausmann. + + Removed documentation for internal functions. + + * Api/qwebsettings.cpp: + +2009-02-13 Martin Smith <msmith@trolltech.com> + + Reviewed by Simon Hausmann. + + Corrected some minor qdoc errors. + + * Api/qwebsettings.cpp: + +2009-02-11 Dimitri Dupuis-latour <dupuislatour@apple.com> + + Stub out InspectorClientQt::hiddenPanels. + + Reviewed by Timothy Hatcher. + + * WebCoreSupport/InspectorClientQt.cpp: + (WebCore::InspectorClientQt::hiddenPanels): + * WebCoreSupport/InspectorClientQt.h: + +2009-02-10 Karsten Heimrich <kheimric@trolltech.com> + + Reviewed by Simon Hausmann. + + Fixes missing navigation/url update while clicking on anchor inside + webpage. + + * WebCoreSupport/FrameLoaderClientQt.cpp: + (WebCore::FrameLoaderClientQt::dispatchDidChangeLocationWithinPage): + update and emit in case we navigate inside a webpage + +2009-02-10 Adam Treat <adam.treat@torchmobile.com> + + Fix the Qt build as class Selection is now VisibleSelection. + + * Api/qwebpage.cpp: + (QWebPage::inputMethodQuery): + +2009-02-06 Geoffrey Garen <ggaren@apple.com> + + Build fix. + + * WebCoreSupport/FrameLoaderClientQt.cpp: + (WebCore::FrameLoaderClientQt::updateGlobalHistoryRedirectLinks): + * WebCoreSupport/FrameLoaderClientQt.h: + +2009-02-06 Kavindra Palaraja <kavindra.palaraja@nokia.com> + + Reviewed by Simon Hausmann. + + Doc - made 2 functions internal as they are not part of the API anymore (and this fixes 2 qdoc warnings) + + * Api/qwebsettings.cpp: + +2009-02-06 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Tor Arne Vestbø. + + Added an overload of QWebFrame::addToJavaScriptWindowObject that takes a QScriptEngine::ValueOwnership parameter. + + * Api/qwebframe.cpp: + (QWebFrame::addToJavaScriptWindowObject): New overload. + * Api/qwebframe.h: + * tests/qwebframe/tst_qwebframe.cpp: Added unit tests for ownership + models. + +2009-02-06 Aaron Boodman <aa@chromium.org> + + Reviewed by Holger Freyther. + + * WebCoreSupport/FrameLoaderClientQt.cpp: + (WebCore::FrameLoaderClientQt::documentElementAvailable):) + Fix compile error in Qt build introduced by the below change (r40694). + +2009-02-05 Aaron Boodman <aa@chromium.org> + + Reviewed by Dave Hyatt. + + https://bugs.webkit.org/show_bug.cgi?id=23708 + Adds documentElementAvailable() callback to FrameLoaderClient. + + * WebCoreSupport/FrameLoaderClientQt.cpp: + (WebCore::FrameLoaderClient::documentElementAvailable): + Stub out documentElementAvailable(). + * WebCoreSupport/FrameLoaderClientQt.h: + Ditto. + +2009-02-04 David Boddie <dboddie@trolltech.com> + + Reviewed by Simon Hausmann. + + Doc: Documented the return value of the evaluateJavaScript() function. + + * Api/qwebframe.cpp: + +2009-02-03 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Tor Arne Vestbø. + + Added a unit test to verify the succesful conversion from QByteArray to + JSByteArray and back to QByteArray. + + * tests/qwebframe/tst_qwebframe.cpp: + +2009-02-02 Geoffrey Garen <ggaren@apple.com> + + Build fix. + + * Api/qwebframe.cpp: + (QWebFrame::QWebFrame): + (QWebFrame::load): + (QWebFrame::setHtml): + (QWebFrame::setContent): + +2009-02-02 Geoffrey Garen <ggaren@apple.com> + + Build fix. + + * WebCoreSupport/FrameLoaderClientQt.cpp: + (WebCore::FrameLoaderClientQt::createFrame): + +2009-02-02 Geoffrey Garen <ggaren@apple.com> Reviewed by Sam Weinig. @@ -15,22 +362,78 @@ (WebCore::FrameLoaderClientQt::createFrame): * WebCoreSupport/FrameLoaderClientQt.h: -2009-02-03 Mark Rowe <mrowe@apple.com> +2009-02-02 Anders Carlsson <andersca@apple.com> + + Reviewed by Dan Bernstein. + + Update for changes to WebCore. + + * WebCoreSupport/FrameLoaderClientQt.cpp: + (WebCore::FrameLoaderClientQt::createPlugin): + (WebCore::FrameLoaderClientQt::createJavaAppletWidget): + * WebCoreSupport/FrameLoaderClientQt.h: + +2009-02-02 Adam Treat <adam.treat@torchmobile.com> - Merge r40436. + Reviewed by Nikolas Zimmermann. + + https://bugs.webkit.org/show_bug.cgi?id=23587 + Refactor HitTestRequest to eliminate all the ugly boolean arguments and + use an enum bitflag instead. Cleanup all the code that constructs the + various HitTestRequests to make the code more readable. + + * Api/qwebframe.cpp: + (QWebFrame::hitTestContent): - 2009-01-30 Geoffrey Garen <ggaren@apple.com> +2009-02-02 Adam Treat <adam.treat@torchmobile.com> + + Fix the Qt build to call forceLayout on the view instead. + + * Api/qwebpage.cpp: + (QWebPage::setFixedLayoutSize): + (QWebPage::setUseFixedLayout): + +2009-02-02 Holger Hans Peter Freyther <zecke@selfish.org> + + Reviewed by Darin Adler. + + Move Frame::forceLayout, Frame::adjustPageHeight and Frame::forceLayoutWithPageWidthRange to FrameView + + https://bugs.webkit.org/show_bug.cgi?id=23428 + + FrameView::forceLayout could be killed but the comment might + contain a value over the the plain FrameView::layout... + + Adjust the WebCore/WebKit consumers of these methods. + + * Api/qwebpage.cpp: + (QWebPage::setViewportSize): + * WebCoreSupport/FrameLoaderClientQt.cpp: + (WebCore::FrameLoaderClientQt::forceLayout): + +2009-01-30 Geoffrey Garen <ggaren@apple.com> Build fix. * WebCoreSupport/FrameLoaderClientQt.cpp: (WebCore::FrameLoaderClientQt::createFrame): -2009-02-03 Mark Rowe <mrowe@apple.com> +2009-01-30 Holger Hans Peter Freyther <zecke@selfish.org> + + Reviewed by Simon Hausmann. - Merge r40432. + https://bugs.webkit.org/show_bug.cgi?id=22056 + + Kill FrameLoaderClient.cpp, move the code over to Frame::createView + + FrameLoaderClient is supposed to be an interface, move the + to be shared code to Frame which is a controller and is + allowed to create a FrameView. + + * WebCoreSupport/FrameLoaderClientQt.cpp: + (WebCore::FrameLoaderClientQt::transitionToCommittedForNewPage): - 2009-01-30 Geoffrey Garen <ggaren@apple.com> +2009-01-30 Geoffrey Garen <ggaren@apple.com> Reviewed by Sam Weinig. @@ -40,6 +443,64 @@ * Api/qwebpage.cpp: (QWebPage::triggerAction): +2009-01-30 Brady Eidson <beidson@apple.com> + + Reviewed by Sam Weinig + + Remove FrameLoaderClient code that is now handled by FrameLoader itself + + * WebCoreSupport/FrameLoaderClientQt.cpp: + (WebCore::FrameLoaderClientQt::frameLoadCompleted): + +2009-01-30 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Tor Arne Vestbø. + + Hide the Offline Web Application Cache path API from the public API + for now. + + * Api/qwebsettings.cpp: + (qt_websettings_setOfflineWebApplicationCachePath): + (qt_websettings_offlineWebApplicationCachePath): + * Api/qwebsettings.h: + +2009-01-28 Adam Treat <adam.treat@torchmobile.com> + + Reviewed by Nikolas Zimmermann and George Staikos. + + https://bugs.webkit.org/show_bug.cgi?id=23557 + Do not clip the QWebFrame::hitTestContent method to the visible viewport + and add a regression test to make sure it works. + + * Api/qwebframe.cpp: + (QWebFrame::hitTestContent): + * tests/qwebframe/tst_qwebframe.cpp: + +2009-01-28 Ariya Hidayat <ariya.hidayat@trolltech.com> + + Rubber-stamped by Simon Hausmann. + + Provide default implementations of JavaScript dialog boxes like in + most web browsers, i.e. indicate that is from JavaScript and show the + frame URL. + + * Api/qwebpage.cpp: + (QWebPage::javaScriptAlert): + (QWebPage::javaScriptConfirm): + (QWebPage::javaScriptPrompt): + +2009-01-27 Ariya Hidayat <ariya.hidayat@trolltech.com> + + Reviewed by Simon Hausmann. + + http://www.qtsoftware.com/developer/task-tracker/index_html?id=238391&method=entry + + [Qt] If QPainter fails to start on a QPrinter instance, do not + continue printing. + + * Api/qwebframe.cpp: + (QWebFrame::print): + 2009-01-27 Brady Eidson <beidson@apple.com> Reviewed by Dan Bernstein diff --git a/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp b/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp index c545769..5199a5a 100644 --- a/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp +++ b/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp @@ -47,6 +47,7 @@ #include "qwebsecurityorigin_p.h" #include <qtooltip.h> +#include <qtextdocument.h> namespace WebCore { @@ -373,7 +374,7 @@ void ChromeClientQt::setToolTip(const String &tip) view->setToolTip(QString()); QToolTip::hideText(); } else { - QString dtip = QLatin1String("<p>") + tip + QLatin1String("</p>"); + QString dtip = QLatin1String("<p>") + Qt::escape(tip) + QLatin1String("</p>"); view->setToolTip(dtip); } #else @@ -386,15 +387,25 @@ void ChromeClientQt::print(Frame *frame) emit m_webPage->printRequested(QWebFramePrivate::kit(frame)); } +#if ENABLE(DATABASE) void ChromeClientQt::exceededDatabaseQuota(Frame* frame, const String& databaseName) { quint64 quota = QWebSettings::offlineStorageDefaultQuota(); -#if ENABLE(DATABASE) + if (!DatabaseTracker::tracker().hasEntryForOrigin(frame->document()->securityOrigin())) DatabaseTracker::tracker().setQuota(frame->document()->securityOrigin(), quota); -#endif + emit m_webPage->databaseQuotaExceeded(QWebFramePrivate::kit(frame), databaseName); } +#endif + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +void ChromeClientQt::reachedMaxAppCacheSize(int64_t spaceNeeded) +{ + // FIXME: Free some space. + notImplemented(); +} +#endif void ChromeClientQt::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> prpFileChooser) { diff --git a/WebKit/qt/WebCoreSupport/ChromeClientQt.h b/WebKit/qt/WebCoreSupport/ChromeClientQt.h index a13bb7c..7922000 100644 --- a/WebKit/qt/WebCoreSupport/ChromeClientQt.h +++ b/WebKit/qt/WebCoreSupport/ChromeClientQt.h @@ -113,9 +113,12 @@ namespace WebCore { virtual void setToolTip(const String&); virtual void print(Frame*); - +#if ENABLE(DATABASE) virtual void exceededDatabaseQuota(Frame*, const String&); - +#endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); +#endif virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>); virtual void formStateDidChange(const Node*) { } diff --git a/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp b/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp index af96201..025bd4f 100644 --- a/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp +++ b/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp @@ -45,11 +45,14 @@ #include "RenderPart.h" #include "ResourceRequest.h" #include "HistoryItem.h" +#include "HTMLAppletElement.h" #include "HTMLFormElement.h" +#include "HTMLPlugInElement.h" #include "NotImplemented.h" #include "QNetworkReplyHandler.h" #include "ResourceHandleInternal.h" #include "ResourceHandle.h" +#include "Settings.h" #include "qwebpage.h" #include "qwebframe.h" @@ -214,12 +217,12 @@ void FrameLoaderClientQt::transitionToCommittedForNewPage() QBrush brush = m_webFrame->page()->palette().brush(QPalette::Base); QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor(); - WebCore::FrameLoaderClient::transitionToCommittedForNewPage(m_frame, m_webFrame->page()->viewportSize(), - backgroundColor, !backgroundColor.alpha(), - m_webFrame->page()->fixedLayoutSize(), - m_webFrame->page()->useFixedLayout(), - (ScrollbarMode)m_webFrame->scrollBarPolicy(Qt::Horizontal), - (ScrollbarMode)m_webFrame->scrollBarPolicy(Qt::Vertical)); + m_frame->createView(m_webFrame->page()->viewportSize(), + backgroundColor, !backgroundColor.alpha(), + m_webFrame->page()->fixedLayoutSize(), + m_webFrame->page()->useFixedLayout(), + (ScrollbarMode)m_webFrame->scrollBarPolicy(Qt::Horizontal), + (ScrollbarMode)m_webFrame->scrollBarPolicy(Qt::Vertical)); } @@ -231,7 +234,9 @@ void FrameLoaderClientQt::makeRepresentation(DocumentLoader*) void FrameLoaderClientQt::forceLayout() { - m_frame->forceLayout(true); + FrameView* view = m_frame->view(); + if (view) + view->forceLayout(true); } @@ -298,7 +303,11 @@ void FrameLoaderClientQt::dispatchDidChangeLocationWithinPage() if (dumpFrameLoaderCallbacks) printf("%s - didChangeLocationWithinPageForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame))); - notImplemented(); + if (!m_webFrame) + return; + + emit m_webFrame->urlChanged(m_webFrame->url()); + m_webFrame->page()->d->updateNavigationActions(); } @@ -508,7 +517,8 @@ bool FrameLoaderClientQt::canShowMIMEType(const String& MIMEType) const if (MIMETypeRegistry::isSupportedNonImageMIMEType(MIMEType)) return true; - if (PluginDatabase::installedPlugins()->isMIMETypeRegistered(MIMEType)) + if (m_frame && m_frame->settings() && m_frame->settings()->arePluginsEnabled() + && PluginDatabase::installedPlugins()->isMIMETypeRegistered(MIMEType)) return true; return false; @@ -530,9 +540,6 @@ String FrameLoaderClientQt::generatedMIMETypeForURLScheme(const String& URLSchem void FrameLoaderClientQt::frameLoadCompleted() { // Note: Can be called multiple times. - // Even if already complete, we might have set a previous item on a frame that - // didn't do any data loading on the past transaction. Make sure to clear these out. - m_frame->loader()->setPreviousHistoryItem(0); } @@ -608,6 +615,11 @@ void FrameLoaderClientQt::windowObjectCleared() emit m_webFrame->javaScriptWindowObjectCleared(); } +void FrameLoaderClientQt::documentElementAvailable() +{ + return; +} + void FrameLoaderClientQt::didPerformFirstNavigation() const { if (m_frame->tree()->parent() || !m_webFrame) @@ -627,7 +639,7 @@ void FrameLoaderClientQt::updateGlobalHistory() history->addHistoryEntry(m_frame->loader()->documentLoader()->urlForHistory().prettyURL()); } -void FrameLoaderClientQt::updateGlobalHistoryForRedirectWithoutHistoryItem() +void FrameLoaderClientQt::updateGlobalHistoryRedirectLinks() { } @@ -971,7 +983,7 @@ PassRefPtr<Frame> FrameLoaderClientQt::createFrame(const KURL& url, const String FrameLoadType loadType = m_frame->loader()->loadType(); FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedBackForwardList; - childFrame->loader()->loadURL(frameData.url, frameData.referrer, String(), childLoadType, 0, 0); + childFrame->loader()->loadURL(frameData.url, frameData.referrer, String(), false, childLoadType, 0, 0); // The frame's onload handler may have removed it from the document. if (!childFrame->tree()->parent()) @@ -1060,7 +1072,7 @@ public: } }; -Widget* FrameLoaderClientQt::createPlugin(const IntSize& pluginSize, Element* element, const KURL& url, const Vector<String>& paramNames, +Widget* FrameLoaderClientQt::createPlugin(const IntSize& pluginSize, HTMLPlugInElement* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually) { // qDebug()<<"------ Creating plugin in FrameLoaderClientQt::createPlugin for "<<url.prettyURL() << mimeType; @@ -1148,7 +1160,7 @@ void FrameLoaderClientQt::redirectDataToPlugin(Widget* pluginWidget) m_hasSentResponseToPlugin = false; } -Widget* FrameLoaderClientQt::createJavaAppletWidget(const IntSize&, Element*, const KURL& baseURL, +Widget* FrameLoaderClientQt::createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues) { notImplemented(); diff --git a/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h b/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h index 908d2aa..c49bb62 100644 --- a/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h +++ b/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h @@ -147,7 +147,7 @@ namespace WebCore { virtual void finishedLoading(DocumentLoader*); virtual void updateGlobalHistory(); - virtual void updateGlobalHistoryForRedirectWithoutHistoryItem(); + virtual void updateGlobalHistoryRedirectLinks(); virtual bool shouldGoToHistoryItem(HistoryItem*) const; virtual ResourceError cancelledError(const ResourceRequest&); @@ -187,15 +187,16 @@ namespace WebCore { virtual PassRefPtr<Frame> createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight) ; - virtual Widget* createPlugin(const IntSize&, Element*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool); + virtual Widget* createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool); virtual void redirectDataToPlugin(Widget* pluginWidget); - virtual Widget* createJavaAppletWidget(const IntSize&, Element*, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues); + virtual Widget* createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues); virtual ObjectContentType objectContentType(const KURL& url, const String& mimeType); virtual String overrideMediaType() const; virtual void windowObjectCleared(); + virtual void documentElementAvailable(); virtual void didPerformFirstNavigation() const; virtual void registerForIconNotification(bool); diff --git a/WebKit/qt/WebCoreSupport/InspectorClientQt.cpp b/WebKit/qt/WebCoreSupport/InspectorClientQt.cpp index 7335280..fe4d43a 100644 --- a/WebKit/qt/WebCoreSupport/InspectorClientQt.cpp +++ b/WebKit/qt/WebCoreSupport/InspectorClientQt.cpp @@ -114,6 +114,12 @@ String InspectorClientQt::localizedStringsURL() return String(); } +String InspectorClientQt::hiddenPanels() +{ + notImplemented(); + return String(); +} + void InspectorClientQt::showWindow() { if (!m_webPage) diff --git a/WebKit/qt/WebCoreSupport/InspectorClientQt.h b/WebKit/qt/WebCoreSupport/InspectorClientQt.h index 49c2d56..60ed77a 100644 --- a/WebKit/qt/WebCoreSupport/InspectorClientQt.h +++ b/WebKit/qt/WebCoreSupport/InspectorClientQt.h @@ -52,6 +52,8 @@ namespace WebCore { virtual String localizedStringsURL(); + virtual String hiddenPanels(); + virtual void showWindow(); virtual void closeWindow(); virtual bool windowVisible(); diff --git a/WebKit/qt/WebKit_pch.h b/WebKit/qt/WebKit_pch.h index 9ef73f6..ae8ec88 100644 --- a/WebKit/qt/WebKit_pch.h +++ b/WebKit/qt/WebKit_pch.h @@ -1,7 +1,7 @@ /* * This file is part of the precompiled header for all of WebKit. * - * Copyright (C) 2007 Trolltech + * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public diff --git a/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp b/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp index 38a3543..d9c97c8 100644 --- a/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp +++ b/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2008,2009 Nokia Corporation and/or its subsidiary(-ies) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -576,6 +576,9 @@ private slots: void ipv6HostEncoding(); void metaData(); void popupFocus(); + void hitTestContent(); + void jsByteArray(); + void ownership(); private: QString evalJS(const QString&s) { // Convert an undefined return variant to the string "undefined" @@ -2272,5 +2275,95 @@ void tst_QWebFrame::popupFocus() "The input field should have a blinking caret"); } +void tst_QWebFrame::hitTestContent() +{ + QString html("<html><body><p>A paragraph</p><br/><br/><br/><a href=\"about:blank\" target=\"_foo\">link text</a></body></html>"); + + QWebPage page; + QWebFrame* frame = page.mainFrame(); + frame->setHtml(html); + page.setViewportSize(QSize(200, 0)); //no height so link is not visible + QWebHitTestResult result = frame->hitTestContent(QPoint(10, 100)); + QCOMPARE(result.linkText(), QString("link text")); + QCOMPARE(result.linkTarget(), QString("_foo")); +} + +void tst_QWebFrame::jsByteArray() +{ + QByteArray ba("hello world"); + m_myObject->setByteArrayProperty(ba); + + // read-only property + QCOMPARE(m_myObject->byteArrayProperty(), ba); + QString type; + QVariant v = evalJSV("myObject.byteArrayProperty"); + QCOMPARE(int(v.type()), int(QVariant::ByteArray)); + + QCOMPARE(v.toByteArray(), ba); +} + +void tst_QWebFrame::ownership() +{ + // test ownership + { + QPointer<QObject> ptr = new QObject(); + QVERIFY(ptr != 0); + { + QWebPage page; + QWebFrame* frame = page.mainFrame(); + frame->addToJavaScriptWindowObject("test", ptr, QScriptEngine::ScriptOwnership); + } + QVERIFY(ptr == 0); + } + { + QPointer<QObject> ptr = new QObject(); + QVERIFY(ptr != 0); + QObject* before = ptr; + { + QWebPage page; + QWebFrame* frame = page.mainFrame(); + frame->addToJavaScriptWindowObject("test", ptr, QScriptEngine::QtOwnership); + } + QVERIFY(ptr == before); + delete ptr; + } + { + QObject* parent = new QObject(); + QObject* child = new QObject(parent); + QWebPage page; + QWebFrame* frame = page.mainFrame(); + frame->addToJavaScriptWindowObject("test", child, QScriptEngine::QtOwnership); + QVariant v = frame->evaluateJavaScript("test"); + QCOMPARE(qvariant_cast<QObject*>(v), child); + delete parent; + v = frame->evaluateJavaScript("test"); + QCOMPARE(qvariant_cast<QObject*>(v), (QObject *)0); + } + { + QPointer<QObject> ptr = new QObject(); + QVERIFY(ptr != 0); + { + QWebPage page; + QWebFrame* frame = page.mainFrame(); + frame->addToJavaScriptWindowObject("test", ptr, QScriptEngine::AutoOwnership); + } + // no parent, so it should be like ScriptOwnership + QVERIFY(ptr == 0); + } + { + QObject* parent = new QObject(); + QPointer<QObject> child = new QObject(parent); + QVERIFY(child != 0); + { + QWebPage page; + QWebFrame* frame = page.mainFrame(); + frame->addToJavaScriptWindowObject("test", child, QScriptEngine::AutoOwnership); + } + // has parent, so it should be like QtOwnership + QVERIFY(child != 0); + delete parent; + } +} + QTEST_MAIN(tst_QWebFrame) #include "tst_qwebframe.moc" diff --git a/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp b/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp index 6f2ce3b..d85e880 100644 --- a/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp +++ b/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp @@ -879,6 +879,7 @@ void tst_QWebPage::textSelection() QCOMPARE(page->selectedText().trimmed(), QString::fromLatin1("The quick brown fox")); // these actions must exist + QVERIFY(page->action(QWebPage::SelectAll) != 0); QVERIFY(page->action(QWebPage::SelectNextChar) != 0); QVERIFY(page->action(QWebPage::SelectPreviousChar) != 0); QVERIFY(page->action(QWebPage::SelectNextWord) != 0); @@ -906,10 +907,14 @@ void tst_QWebPage::textSelection() QCOMPARE(page->action(QWebPage::SelectStartOfDocument)->isEnabled(), false); QCOMPARE(page->action(QWebPage::SelectEndOfDocument)->isEnabled(), false); + // ..but SelectAll is awalys enabled + QCOMPARE(page->action(QWebPage::SelectAll)->isEnabled(), true); + // make it editable before navigating the cursor page->setContentEditable(true); // here the actions are enabled after contentEditable is true + QCOMPARE(page->action(QWebPage::SelectAll)->isEnabled(), true); QCOMPARE(page->action(QWebPage::SelectNextChar)->isEnabled(), true); QCOMPARE(page->action(QWebPage::SelectPreviousChar)->isEnabled(), true); QCOMPARE(page->action(QWebPage::SelectNextWord)->isEnabled(), true); @@ -951,6 +956,8 @@ void tst_QWebPage::textEditing() QVERIFY(page->action(QWebPage::ToggleBold) != 0); QVERIFY(page->action(QWebPage::ToggleItalic) != 0); QVERIFY(page->action(QWebPage::ToggleUnderline) != 0); + QVERIFY(page->action(QWebPage::InsertParagraphSeparator) != 0); + QVERIFY(page->action(QWebPage::InsertLineSeparator) != 0); // right now they are disabled because contentEditable is false QCOMPARE(page->action(QWebPage::DeleteStartOfWord)->isEnabled(), false); @@ -961,6 +968,8 @@ void tst_QWebPage::textEditing() QCOMPARE(page->action(QWebPage::ToggleBold)->isEnabled(), false); QCOMPARE(page->action(QWebPage::ToggleItalic)->isEnabled(), false); QCOMPARE(page->action(QWebPage::ToggleUnderline)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::InsertParagraphSeparator)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::InsertLineSeparator)->isEnabled(), false); // make it editable before navigating the cursor page->setContentEditable(true); @@ -974,6 +983,8 @@ void tst_QWebPage::textEditing() QCOMPARE(page->action(QWebPage::ToggleBold)->isEnabled(), true); QCOMPARE(page->action(QWebPage::ToggleItalic)->isEnabled(), true); QCOMPARE(page->action(QWebPage::ToggleUnderline)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::InsertParagraphSeparator)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::InsertLineSeparator)->isEnabled(), true); delete page; } diff --git a/WebKit/win/ChangeLog b/WebKit/win/ChangeLog index bbafe2e..5f89f66 100644 --- a/WebKit/win/ChangeLog +++ b/WebKit/win/ChangeLog @@ -1,19 +1,291 @@ -2009-02-12 Mark Rowe <mrowe@apple.com> +2009-03-26 Dan Bernstein <mitz@apple.com> - Merge r40886. + Reviewed by Adam Roben. + + - add close() to the WebView API. + + * Interfaces/IWebView.idl: + * WebView.cpp: + (WebView::close): + * WebView.h: + +2009-03-24 Brent Fulgham <bfulgham@webkit.org> + + Reviewed by Adam Roben. + + https://bugs.webkit.org/show_bug.cgi?id=24779 + Conditionalize CFNetwork-specific code in WebView to permit + support for other network backends. + + * WebView.cpp: + (WebView::setCacheModel): Add CFNETWORK check around CFNetwork + specific cache implementation. + (updateSharedSettingsFromPreferencesIfNeeded): Add CFNETWORK + check around use of CFHTTPCookie code. + +2009-03-23 Sam Weinig <sam@webkit.org> + + Reviewed by Dan Bernstein. + + Fix for <rdar://problem/6140966> + Empty Caches does not clear the Cross-site XMLHttpRequest preflight cache + + * WebCache.cpp: + (WebCache::empty): Also add application cache emptying to match the mac. + +2009-03-18 Steve Falkenburg <sfalken@apple.com> + + Add webViewClosing to private UI delegate. + + Reviewed by Adam Roben. + + * Interfaces/IWebUIDelegatePrivate.idl: + * Interfaces/WebKit.idl: + * WebView.cpp: + (WebView::close): + +2009-03-17 Dan Bernstein <mitz@apple.com> + + Reviewed by Adam Roben. + + - WebKit part of adding a mechanism for controlling the caching of + responses through WebFrameLoaderClient + + * Interfaces/IWebResourceLoadDelegatePrivate.idl: Added the + IWebResourceLoadDelegatePrivate3 interface, containing the new + delegate method shouldCacheResponse(). + + * Interfaces/IWebURLRequest.idl: Added the isEqual() method. + + * WebCoreSupport/WebFrameLoaderClient.cpp: + (WebFrameLoaderClient::shouldCacheResponse): Implemented this new + FrameLoaderDelegate method by calling through to the resource load + delegate, if it implements shouldCacheResponse(), and returning true + otherwise. + + * WebCoreSupport/WebFrameLoaderClient.h: + + * WebMutableURLRequest.cpp: + (WebMutableURLRequest::isEqual): Added. + (WebMutableURLRequest::setValue): Implemented. + + * WebMutableURLRequest.h: Declared isEqual(). + +2009-03-16 Darin Adler <darin@apple.com> + + Reviewed by Dan Bernstein. + + <rdar://problem/6577174> Rename the text directionality submenus to “Paragraph Direction†and “Selection Direction†+ + For now, change only the localized strings, not the terminology in the code. + + * WebCoreLocalizedStrings.cpp: + (WebCore::contextMenuItemTagWritingDirectionMenu): Changed string here. + (WebCore::contextMenuItemTagTextDirectionMenu): And here. + +2009-03-16 Adam Roben <aroben@apple.com> + + Add IWebFramePrivate::isDisplayingStandaloneImage + + This uses the same logic that -[WebFrame _isDisplayingStandaloneImage] + uses. + + Reviewed by Darin Adler. + + * Interfaces/IWebFramePrivate.idl: Added isDisplayingStandaloneImage. + + * WebFrame.cpp: + (WebFrame::isDisplayingStandaloneImage): Added. Returns true if our + Document is an image document. + + * WebFrame.h: Added isDisplayingStandaloneImage. + +2009-03-12 Peter Kasting <pkasting@google.com> + + Reviewed by Darin Fisher. + + https://bugs.webkit.org/show_bug.cgi?id=24502 + Make horizontal scrolling on Windows always go the correct direction. + + * WebView.cpp: + (WebView::mouseWheel): + (WebViewWndProc): + * WebView.h: + +2009-03-12 Adam Roben <aroben@apple.com> + + Implement DOMHTMLDocument::title + + Reviewed by Dan Bernstein. + + * DOMHTMLClasses.cpp: + (DOMHTMLDocument::title): Call through to WebCore::Document (with + obligatory COM error checking/type conversions). + +2009-03-11 Adam Roben <aroben@apple.com> + + Export functions needed by ThreadSpecific from WebKit + + Reviewed by John Sullivan. + + * WebKit.vcproj/WebKit.def: + * WebKit.vcproj/WebKit_debug.def: + Export WTF::tlsKeyCount and WTF::tlsKeys. + +2009-03-10 Steve Falkenburg <sfalken@apple.com> + + <rdar://problem/6662167> When clicking in Top Sites search field, WebHistory::findIndex fails causing crash in BookmarksSearcher::collectHistorySearchResults + + Round CFAbsoluteDates to the nearest second when converting to/from the Windows DATE format. + + This corrects for inaccuracies introduced by round-tripping between DATE (day based) and CFAbsoluteDate (second based). + The WebKit COM API on Windows uses DATE, while our history storage uses CFAbsoluteTime. This could lead to WebKit + saying there was browsing history for a particular day, and then return no history items when we requested a + list of sites visited that day. + + Reviewed by Ada Chan. + + * MarshallingHelpers.cpp: + (MarshallingHelpers::DATEToCFAbsoluteTime): + (MarshallingHelpers::CFAbsoluteTimeToDATE): - 2009-02-11 Brady Eidson <beidson@apple.com> +2009-03-08 Mark Rowe <mrowe@apple.com> + + Reviewed by Oliver Hunt. + + Split ScrollAlignment and ScrollBehavior out of RenderLayer.h so that + Frame.h no longer needs to include it. This cuts the size of the symbols + for a debug build by around 3%. + + * WebView.cpp: + (WebView::centerSelectionInVisibleArea): + +2009-03-07 Dan Bernstein <mitz@apple.com> + + Reviewed by Mark Rowe. + + - WebKit part of removing build-time and run-time support for legacy + versions of CFNetwork and Core Graphics + + * WebView.cpp: + (WebView::setCacheModel): + +2009-03-04 Adam Barth <abath@webkit.org> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=24356 + + Fix WebKit style for allowUniversalAccessFromFileURLs. + + * Interfaces/IWebPreferencesPrivate.idl: + * WebPreferenceKeysPrivate.h: + * WebPreferences.cpp: + (WebPreferences::initializeDefaultSettings): + (WebPreferences::allowUniversalAccessFromFileURLs): + (WebPreferences::setAllowUniversalAccessFromFileURLs): + * WebPreferences.h: + * WebView.cpp: + (WebView::notifyPreferencesChanged): + +2009-02-27 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Add a preference to reduce the power of file:// URLs. + + * Interfaces/IWebPreferencesPrivate.idl: + * WebPreferenceKeysPrivate.h: + * WebPreferences.cpp: + (WebPreferences::initializeDefaultSettings): + (WebPreferences::allowUniversalAccessFromFileUrls): + (WebPreferences::setAllowUniversalAccessFromFileUrls): + * WebPreferences.h: + * WebView.cpp: + (WebView::notifyPreferencesChanged): + +2009-02-19 Alexey Proskuryakov <ap@webkit.org> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=24024 + REGRESSION (r39845): Assertion failure in -[WebHistoryItem dictionaryRepresentation] when + archiving a submission to about:blank + + I don't know how to make an automated test for this bug. + + * WebHistory.cpp: (WebHistory::visitedURL): Account for the fact that HTTP method may be + non-empty for non-HTTP requests. + +2009-02-25 Andreia Gaita <shana@jitted.com> + + Reviewed by Alp Toker. + + Update Win def files with recent JavaScriptCore API additions. + + * WebKit.vcproj/WebKit.def: + * WebKit.vcproj/WebKit_Cairo.def: + * WebKit.vcproj/WebKit_debug.def: + +2009-02-24 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + Related to <rdar://problem/6590295> + Allow disabling javascript: urls. + + * Interfaces/IWebViewPrivate.idl: + * WebView.cpp: + (WebView::setJavaScriptURLsAreAllowed): + * WebView.h: + +2009-02-24 Adam Roben <aroben@apple.com> + + Windows build fix + + * WebKit.vcproj/WebKit.def: + * WebKit.vcproj/WebKit_debug.def: + Export WTF::ThreadCondition::timedWait. + +2009-02-12 Brady Eidson <beidson@apple.com> + + Reviewed by Kevin Decker + + <rdar://problem/6582180> - Wrong HTTP method applied to history item. + + * WebCoreSupport/WebFrameLoaderClient.cpp: + (WebFrameLoaderClient::updateGlobalHistory): Check the original request, not any + redirected request. + +2009-02-11 Brady Eidson <beidson@apple.com> Fix my last checkin for more effect. * WebHistoryItem.cpp: (WebHistoryItem::initFromDictionaryRepresentation): -2009-02-12 Mark Rowe <mrowe@apple.com> +2009-02-11 Adam Roben <aroben@apple.com> + + Windows fix for Bug 22239: Implement missing animation & transition + APIs on LayoutTestController for non-mac platforms + + <https://bugs.webkit.org/show_bug.cgi?id=22239> + + Reviewed by Simon Fraser. + + * Interfaces/IWebFramePrivate.idl: Added pauseAnimation, + pauseTransition, and numberOfActiveAnimations. + + * WebFrame.cpp: + (WebFrame::pauseAnimation): + (WebFrame::pauseTransition): + (WebFrame::numberOfActiveAnimation): + Added. These all call through to AnimationController. - Merge r40882. + * WebFrame.h: Added pauseAnimation, pauseTransition, and + numberOfActiveAnimations. - 2009-02-11 Brady Eidson <beidson@apple.com> +2009-02-11 Brady Eidson <beidson@apple.com> Reviewed by Mark Rowe @@ -35,11 +307,96 @@ (WebHistoryItem::initFromDictionaryRepresentation): Add the negative-visit-count-correction-logic as implemented for Mac in http://trac.webkit.org/changeset/40851. -2009-02-06 Mark Rowe <mrowe@apple.com> +2009-02-11 Dimitri Dupuis-latour <dupuislatour@apple.com> + + Stub out WebInspectorClient::hiddenPanels. + + Reviewed by Timothy Hatcher. + + * WebCoreSupport/WebInspectorClient.cpp: + (WebInspectorClient::hiddenPanels): + * WebCoreSupport/WebInspectorClient.h: + +2009-02-11 Adam Roben <aroben@apple.com> + + Don't release the shared WebHistory instance on quit + + This matches Mac, and prevents a race condition when the process exits + that depends on the order in which global destructors are invoked. + + Reviewed by Alexey Proskuryakov. + + * WebHistory.cpp: + (sharedHistoryStorage): Changed to use DEFINE_STATIC_LOCAL so the + destructor is never called. + +2009-02-10 Adam Roben <aroben@apple.com> + + Fix recursive WebView destruction when running DumpRenderTree + + DumpRenderTree would call DestroyWindow on a WebView's host window, + which would send a WM_DESTROY message to the WebView's window. Inside + the WebView's WndProc, we would hold a ref to the WebView, then call + close() and revokeDragDrop(), which would release all remaining + references to the WebView other than the ref we held in the WndProc. + When the WndProc exited, the final ref to the WebView would be + released, invoking WebView's destructor. At this point, + IsWindow(m_viewWindow) would return true, since we were still in the + process of handling WM_DESTROY, so we would call DestroyWindow on the + WebView's window again, re-entering the WndProc and re-reffing the + WebView, leading to recursive destruction. + + Reviewed by Alexey Proskuryakov. + + * WebView.cpp: + (WebView::~WebView): Don't call DestroyWindow if our window is already + being destroyed. + (WebViewWndProc): Only hold an extra ref to the WebView when we're not + being destroyed. + +2009-02-06 Adam Roben <aroben@apple.com> + + Build fix + + Reviewed by Sam Weinig. + + * WebCoreSupport/WebFrameLoaderClient.cpp: Added missing #include. + (WebFrameLoaderClient::updateGlobalHistoryRedirectLinks): Removed + incorrect .get(), and changed to use the new overload of + WebHistory::itemForURLString. + + * WebHistory.cpp: + (WebHistory::itemForURLString): Made this const. + (WebHistory::itemForURLString): Added an overload that takes a + WebCore::String and returns the IWebHistoryItem instead of using an + out parameter. + + * WebHistory.h: Added public overload of itemForURLString. + + * WebView.cpp: + (WebView::prepareCandidateWindow): + (WebView::onIMERequestCharPosition): + (WebView::onIMERequestReconvertString): + Updated for toRange -> toNormalizedRange rename. - Merge r40726. +2009-02-06 Geoffrey Garen <ggaren@apple.com> - 2009-02-06 Dan Bernstein <mitz@apple.com> + Reviewed by Sam Weinig. + + Part III of <rdar://problem/6552272>. + + Refactored to use the redirect data WebCore makes available, instead of + tracking loading state in WebKit. + + * WebCoreSupport/WebFrameLoaderClient.cpp: + (WebFrameLoaderClient::updateGlobalHistory): + (WebFrameLoaderClient::updateGlobalHistoryRedirectLinks): + * WebCoreSupport/WebFrameLoaderClient.h: + * WebHistory.cpp: + (WebHistory::visitedURL): + * WebHistory.h: + +2009-02-06 Dan Bernstein <mitz@apple.com> Reviewed by Anders Carlsson. @@ -51,11 +408,14 @@ size. Also reduced the inline capacity of the vector used for weekly visit counts to 5, which is the expected maximum size. -2009-02-06 Mark Rowe <mrowe@apple.com> +2009-02-06 Brent Fulgham <bfulgham@webkit.org> - Merge r40713. + Build fix. - 2009-02-06 Maciej Stachowiak <mjs@apple.com> + * WebKit.vcproj/WebKit.vcproj: Re-enable missing file in Release + target of Cairo. + +2009-02-06 Maciej Stachowiak <mjs@apple.com> Rubber stamped by Dan Bernstein. @@ -64,11 +424,7 @@ * WebHistoryItem.cpp: (WebHistoryItem::initFromDictionaryRepresentation): -2009-02-06 Mark Rowe <mrowe@apple.com> - - Merge r40712. - - 2009-02-05 Maciej Stachowiak <mjs@apple.com> and Brady Eidson <beidson@apple.com> +2009-02-05 Maciej Stachowiak <mjs@apple.com> and Brady Eidson <beidson@apple.com> Reviewed by Dan Bernstein and Geoff Garen.. @@ -89,89 +445,74 @@ (WebHistoryItem::recordInitialVisit): Tell WebCore to record an initial visit. * WebHistoryItem.h: -2009-02-04 Steve Falkenburg <sfalken@apple.com> +2009-02-05 Brent Fulgham <bfulgham@webkit.org> - Merge r40365. + Reviewed by Sam Weinig <sam@webkit.org> - 2009-01-29 Adam Roben <aroben@apple.com> + Build fix. Update file for recently removed EventTargetNodeCast. + * DOMCoreClasses.cpp: + (DOMNode::dispatchEvent): - Build fix after r40353 +2009-02-05 Aaron Boodman <aa@chromium.org> - * WebCoreSupport/WebFrameLoaderClient.cpp: - (WebFrameLoaderClient::loadURLIntoChild): Removed the check for - FrameLoadTypeReloadAllowingStaleData. + Reviewed by Dave Hyatt. -2009-02-04 Steve Falkenburg <sfalken@apple.com> + https://bugs.webkit.org/show_bug.cgi?id=23708 + Adds documentElementAvailable() callback to FrameLoaderClient. - Merge r40511. + * WebFrame.cpp: + (WebFrame::documentElementAvailable): + Stub out documentElementAvailable() + * WebFrame.h: + Ditto. - 2009-02-02 Geoffrey Garen <ggaren@apple.com> +2009-02-04 Geoffrey Garen <ggaren@apple.com> Build fix. - * WebCoreSupport/WebFrameLoaderClient.cpp: - (WebFrameLoaderClient::loadURLIntoChild): - -2009-02-04 Steve Falkenburg <sfalken@apple.com> - - Merge part of r40470. - - 2009-01-31 Matt Lilek <webkit@mattlilek.com> - - Not reviewed, build fixes. - - * WebCoreSupport/WebContextMenuClient.cpp: - (WebContextMenuClient::searchWithGoogle): - -2009-02-03 Mark Rowe <mrowe@apple.com> - - Merge r40392. - - 2009-01-29 Sam Weinig <sam@webkit.org> + * WebHistory.cpp: + (WebHistory::visitedURL): - Fix Windows build +2009-02-04 Geoffrey Garen <ggaren@apple.com> - * WebHistoryItem.cpp: - (WebHistoryItem::initFromDictionaryRepresentation): + Reviewed by Mark Rowe. + + Part I of <rdar://problem/6552272>. -2009-02-03 Mark Rowe <mrowe@apple.com> + Clear the redirectURLs entry when first visiting a site, so sites that + only redirect you the first time you visit them can later learn that + they don't redirect. - Merge r40529. + * WebHistory.cpp: + (WebHistory::visitedURL): - 2009-02-03 Geoffrey Garen <ggaren@apple.com> +2009-02-03 Geoffrey Garen <ggaren@apple.com> Build fix. * WebHistory.cpp: (WebHistory::visitedURL): -2009-02-03 Mark Rowe <mrowe@apple.com> - - Merge r40528. - - 2009-02-02 Geoffrey Garen <ggaren@apple.com> +2009-02-02 Geoffrey Garen <ggaren@apple.com> Build fix. * WebHistory.cpp: (WebHistory::visitedURL): -2009-02-03 Mark Rowe <mrowe@apple.com> +2009-02-02 Hiroaki Nakamura <hnakamur@gmail.com> - Merge r40511. - - 2009-02-02 Geoffrey Garen <ggaren@apple.com> - - Build fix. - - * WebCoreSupport/WebFrameLoaderClient.cpp: - (WebFrameLoaderClient::loadURLIntoChild): + Reviewed by Adam Roben. -2009-02-03 Mark Rowe <mrowe@apple.com> + Fixes https://bugs.webkit.org/show_bug.cgi?id=15813 + Modify pre-build step to properly handle the errorlevel + shell command. - Merge r40508. + * WebKit.vcproj/WebKit.vcproj: Change errorlevel handling + for all targets so prefast is only enabled in builds + where /analyze is available. - 2009-02-02 Geoffrey Garen <ggaren@apple.com> +2009-02-02 Geoffrey Garen <ggaren@apple.com> Reviewed by Sam Weinig. @@ -199,11 +540,7 @@ * WebHistory.h: See above. -2009-02-03 Mark Rowe <mrowe@apple.com> - - Merge r40503. - - 2009-02-02 Brady Eidson <beidson@apple.com> +2009-02-02 Brady Eidson <beidson@apple.com> Reviewed by Dan Bernstein @@ -221,42 +558,69 @@ (WebHistoryItem::visitedWithTitle): * WebHistoryItem.h: -2009-02-03 Mark Rowe <mrowe@apple.com> +2009-02-02 Anders Carlsson <andersca@apple.com> - Merge r40382. + Fix build. + + * WebCoreSupport/WebFrameLoaderClient.cpp: + (WebFrameLoaderClient::createPlugin): + * WebCoreSupport/WebFrameLoaderClient.h: - 2009-01-29 Sam Weinig <sam@webkit.org> +2009-02-02 Anders Carlsson <andersca@apple.com> - Reviewed by Anders Carlsson. + Reviewed by Dan Bernstein. - Second step in tracking the urls a HistoryItem was redirected through - Add SPI to access the array of redirect urls associated with a HistoryItem. + Update for changes to WebCore. - * Interfaces/IWebHistoryItemPrivate.idl: - * WebHistoryItem.cpp: - (WebHistoryItem::dictionaryRepresentation): - (WebHistoryItem::redirectURLs): - * WebHistoryItem.h: + * WebFrame.cpp: + (WebFrame::createJavaAppletWidget): + * WebFrame.h: -2009-02-03 Mark Rowe <mrowe@apple.com> +2009-02-02 Holger Hans Peter Freyther <zecke@selfish.org> - Merge r40380. + Reviewed by Darin Adler. - 2009-01-29 Sam Weinig <sam@webkit.org> + Move Frame::forceLayout, Frame::adjustPageHeight and Frame::forceLayoutWithPageWidthRange to FrameView - Reviewed by Mark Rowe. + https://bugs.webkit.org/show_bug.cgi?id=23428 - First step in tracking the urls a HistoryItem was redirected through. + FrameView::forceLayout could be killed but the comment might + contain a value over the the plain FrameView::layout... - * WebHistoryItem.cpp: - (WebHistoryItem::initFromDictionaryRepresentation): - (WebHistoryItem::dictionaryRepresentation): + Adjust the WebCore/WebKit consumers of these methods. + + * WebCoreSupport/WebFrameLoaderClient.cpp: + (WebFrameLoaderClient::forceLayout): + +2009-01-31 Matt Lilek <webkit@mattlilek.com> + + Not reviewed, build fixes. + + * WebCoreSupport/WebContextMenuClient.cpp: + (WebContextMenuClient::searchWithGoogle): + * WebFrame.cpp: + (WebFrame::setInPrintingMode): + (WebFrame::isFrameSet): + * WebView.cpp: + (WebView::notifyPreferencesChanged): + +2009-01-30 Adam Barth <abarth@webkit.org> + + Reviewed by Sam Weinig. -2009-02-03 Mark Rowe <mrowe@apple.com> + Add a pref to disable web security. - Merge r40436. + * Interfaces/IWebPreferencesPrivate.idl: + * WebPreferenceKeysPrivate.h: + * WebPreferences.cpp: + (WebPreferences::initializeDefaultSettings): + (WebPreferences::isWebSecurityEnabled): + (WebPreferences::setWebSecurityEnabled): + * WebPreferences.h: + * WebView.cpp: + (WebView::notifyPreferencesChanged): - 2009-01-30 Geoffrey Garen <ggaren@apple.com> +2009-01-30 Geoffrey Garen <ggaren@apple.com> Build fix. @@ -264,24 +628,59 @@ * WebCoreSupport/WebFrameLoaderClient.cpp: (WebFrameLoaderClient::loadURLIntoChild): -2009-02-03 Mark Rowe <mrowe@apple.com> +2009-01-30 Holger Hans Peter Freyther <zecke@selfish.org> - Merge r40353. + Reviewed by Simon Hausmann. - 2009-01-28 Geoffrey Garen <ggaren@apple.com> + Kill FrameLoaderClient.cpp, move the code over to Frame::createView - Reviewed by Sam Weinig. + FrameLoaderClient is supposed to be an interface, move the + to be shared code to Frame which is a controller and is + allowed to create a FrameView. - Updated for WebCore rename. + * WebCoreSupport/WebFrameLoaderClient.cpp: + (WebFrameLoaderClient::transitionToCommittedForNewPage): - * WebView.cpp: - (WebView::setCustomTextEncodingName): +2009-01-30 Brady Eidson <beidson@apple.com> + + Reviewed by Sam Weinig -2009-02-03 Mark Rowe <mrowe@apple.com> + Remove FrameLoaderClient code that is now handled by FrameLoader itself - Merge r40366. + * WebFrame.cpp: + (WebFrame::frameLoadCompleted): + +2009-01-29 Sam Weinig <sam@webkit.org> + + Fix Windows build + + * WebHistoryItem.cpp: + (WebHistoryItem::initFromDictionaryRepresentation): + +2009-01-29 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + Second step in tracking the urls a HistoryItem was redirected through + Add SPI to access the array of redirect urls associated with a HistoryItem. + + * Interfaces/IWebHistoryItemPrivate.idl: + * WebHistoryItem.cpp: + (WebHistoryItem::dictionaryRepresentation): + (WebHistoryItem::redirectURLs): + * WebHistoryItem.h: + +2009-01-29 Sam Weinig <sam@webkit.org> + + Reviewed by Mark Rowe. + + First step in tracking the urls a HistoryItem was redirected through. - 2009-01-29 Adam Roben <aroben@apple.com> + * WebHistoryItem.cpp: + (WebHistoryItem::initFromDictionaryRepresentation): + (WebHistoryItem::dictionaryRepresentation): + +2009-01-29 Adam Roben <aroben@apple.com> Fix Bug 23623: Windowed Flash instances aren't captured when a WebView receives a WM_PRINTCLIENT message @@ -313,6 +712,23 @@ * WebView.h: Added windowsToPaint parameters to paintIntoBackingStore and updateBackingStore (which I also made private). +2009-01-29 Adam Roben <aroben@apple.com> + + Build fix after r40353 + + * WebCoreSupport/WebFrameLoaderClient.cpp: + (WebFrameLoaderClient::loadURLIntoChild): Removed the check for + FrameLoadTypeReloadAllowingStaleData. + +2009-01-28 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Updated for WebCore rename. + + * WebView.cpp: + (WebView::setCustomTextEncodingName): + 2009-01-27 Brady Eidson <beidson@apple.com> Reviewed by Dan Bernstein diff --git a/WebKit/win/DOMCoreClasses.cpp b/WebKit/win/DOMCoreClasses.cpp index 2da3e28..19f076f 100644 --- a/WebKit/win/DOMCoreClasses.cpp +++ b/WebKit/win/DOMCoreClasses.cpp @@ -381,7 +381,7 @@ HRESULT STDMETHODCALLTYPE DOMNode::dispatchEvent( return hr; WebCore::ExceptionCode ec = 0; - *result = WebCore::EventTargetNodeCast(m_node)->dispatchEvent(domEvent->coreEvent(), ec) ? TRUE : FALSE; + *result = m_node->dispatchEvent(domEvent->coreEvent(), ec) ? TRUE : FALSE; #if 0 // FIXME - raise dom exceptions WebCore::raiseOnDOMError(ec); #endif diff --git a/WebKit/win/DOMHTMLClasses.cpp b/WebKit/win/DOMHTMLClasses.cpp index 037aa88..ceb0374 100644 --- a/WebKit/win/DOMHTMLClasses.cpp +++ b/WebKit/win/DOMHTMLClasses.cpp @@ -180,10 +180,18 @@ HRESULT STDMETHODCALLTYPE DOMHTMLDocument::QueryInterface(REFIID riid, void** pp // DOMHTMLDocument ------------------------------------------------------------ HRESULT STDMETHODCALLTYPE DOMHTMLDocument::title( - /* [retval][out] */ BSTR* /*result*/) + /* [retval][out] */ BSTR* result) { - ASSERT_NOT_REACHED(); - return E_NOTIMPL; + if (!result) + return E_POINTER; + + *result = 0; + + if (!m_document || !m_document->isHTMLDocument()) + return E_FAIL; + + *result = BString(m_document->title()).release(); + return S_OK; } HRESULT STDMETHODCALLTYPE DOMHTMLDocument::setTitle( diff --git a/WebKit/win/ForEachCoClass.h b/WebKit/win/ForEachCoClass.h index 94976e6..e1eeac1 100644 --- a/WebKit/win/ForEachCoClass.h +++ b/WebKit/win/ForEachCoClass.h @@ -31,11 +31,17 @@ #include "ProgIDMacros.h" +#if ENABLE(DATABASE) +#define WEB_DATABASE_MANAGER(macro) macro(WebDatabaseManager) +#else +#define WEB_DATABASE_MANAGER(macro) +#endif + // Items may only be added to the end of this macro. No items may be removed from it. #define FOR_EACH_COCLASS(macro) \ macro(CFDictionaryPropertyBag) \ macro(WebCache) \ - macro(WebDatabaseManager) \ + WEB_DATABASE_MANAGER(macro) \ macro(WebDownload) \ macro(WebError) \ macro(WebHistory) \ diff --git a/WebKit/win/Interfaces/IWebFramePrivate.idl b/WebKit/win/Interfaces/IWebFramePrivate.idl index d1f6cbf..f00bec5 100755 --- a/WebKit/win/Interfaces/IWebFramePrivate.idl +++ b/WebKit/win/Interfaces/IWebFramePrivate.idl @@ -83,4 +83,10 @@ interface IWebFramePrivate : IUnknown HRESULT paintDocumentRectToContext([in] RECT rect, [in] OLE_HANDLE deviceContext); HRESULT elementDoesAutoComplete([in] IDOMElement* element, [out, retval] BOOL* result); + + HRESULT pauseAnimation([in] BSTR animationName, [in] IDOMNode* node, [in] double secondsFromNow, [out, retval] BOOL* animationWasRunning); + HRESULT pauseTransition([in] BSTR propertyName, [in] IDOMNode* node, [in] double secondsFromNow, [out, retval] BOOL* transitionWasRunning); + HRESULT numberOfActiveAnimations([out, retval] UINT* number); + + HRESULT isDisplayingStandaloneImage([out, retval] BOOL* result); } diff --git a/WebKit/win/Interfaces/IWebPreferencesPrivate.idl b/WebKit/win/Interfaces/IWebPreferencesPrivate.idl index aa1073f..b9e05ec 100644 --- a/WebKit/win/Interfaces/IWebPreferencesPrivate.idl +++ b/WebKit/win/Interfaces/IWebPreferencesPrivate.idl @@ -69,4 +69,10 @@ interface IWebPreferencesPrivate : IUnknown HRESULT setFontSmoothingContrast([in] float contrast); HRESULT fontSmoothingContrast([out, retval] float* contrast); + + HRESULT isWebSecurityEnabled([out, retval] BOOL* enabled); + HRESULT setWebSecurityEnabled([in] BOOL enabled); + + HRESULT allowUniversalAccessFromFileURLs([out, retval] BOOL *allowAccess); + HRESULT setAllowUniversalAccessFromFileURLs([in] BOOL allowAccess); } diff --git a/WebKit/win/Interfaces/IWebResourceLoadDelegatePrivate.idl b/WebKit/win/Interfaces/IWebResourceLoadDelegatePrivate.idl index 95040bf..df23091 100644 --- a/WebKit/win/Interfaces/IWebResourceLoadDelegatePrivate.idl +++ b/WebKit/win/Interfaces/IWebResourceLoadDelegatePrivate.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,7 +35,6 @@ interface IWebDataSource; interface IWebURLResponse; interface IWebURLRequest; - /*! @category WebResourceLoadDelegatePrivate */ @@ -70,3 +69,14 @@ interface IWebResourceLoadDelegatePrivate2 : IWebResourceLoadDelegatePrivate { HRESULT shouldUseCredentialStorage([in] IWebView* webView, [in] unsigned long identifier, [in] IWebDataSource* dataSource, [out, retval] BOOL* shouldUse); } + +[ + object, + oleautomation, + uuid(099DC3C1-34B5-4169-ABBF-0C63CBC25605), + pointer_default(unique) +] +interface IWebResourceLoadDelegatePrivate3 : IWebResourceLoadDelegatePrivate2 +{ + HRESULT shouldCacheResponse([in] IWebView* webView, [in] unsigned long identifier, [in] IWebURLResponse* response, [in] const char* data, [in] unsigned long long length, [in] IWebDataSource* dataSource, [out, retval] BOOL* shouldCache); +} diff --git a/WebKit/win/Interfaces/IWebUIDelegatePrivate.idl b/WebKit/win/Interfaces/IWebUIDelegatePrivate.idl index 5ef53d9..c6d3bbd 100755 --- a/WebKit/win/Interfaces/IWebUIDelegatePrivate.idl +++ b/WebKit/win/Interfaces/IWebUIDelegatePrivate.idl @@ -92,3 +92,14 @@ interface IWebUIDelegatePrivate4 : IWebUIDelegatePrivate3 HRESULT embeddedViewWithArguments([in] IWebView* sender, [in] IWebFrame* frame, [in] IPropertyBag* arguments, [out, retval] IWebEmbeddedView** view); HRESULT webViewSendResizeMessage([in] UINT uMsg, [in] WPARAM wParam, [in] LPARAM lParam); } + +[ + object, + oleautomation, + uuid(df3b4283-6868-4a1f-97f6-baf0b33f239c), + pointer_default(unique) +] +interface IWebUIDelegatePrivate5 : IWebUIDelegatePrivate4 +{ + HRESULT webViewClosing([in] IWebView* sender); +} diff --git a/WebKit/win/Interfaces/IWebURLRequest.idl b/WebKit/win/Interfaces/IWebURLRequest.idl index 0f72fa8..4b27592 100644 --- a/WebKit/win/Interfaces/IWebURLRequest.idl +++ b/WebKit/win/Interfaces/IWebURLRequest.idl @@ -110,4 +110,6 @@ interface IWebURLRequest : IUnknown HRESULT isEmpty([out, retval] BOOL* result); HRESULT mutableCopy([out, retval] IWebMutableURLRequest** result); + + HRESULT isEqual([in] IWebURLRequest* other, [out, retval] BOOL* result); } diff --git a/WebKit/win/Interfaces/IWebView.idl b/WebKit/win/Interfaces/IWebView.idl index e38406b..04e996c 100644 --- a/WebKit/win/Interfaces/IWebView.idl +++ b/WebKit/win/Interfaces/IWebView.idl @@ -723,6 +723,18 @@ interface IWebView : IUnknown + (void)registerURLSchemeAsLocal:(NSString *)scheme; */ HRESULT registerURLSchemeAsLocal([in] BSTR scheme); + + /*! + @method close + @abstract Closes the receiver, unloading its web page and canceling any pending loads. + Once the receiver has closed, it will no longer respond to requests or fire delegate methods. + (However, the -close method itself may fire delegate methods.) + @discussion A garbage collected application is required to call close when the receiver is no longer needed. + The close method will be called automatically when the window or hostWindow closes and shouldCloseWithWindow returns YES. + A non-garbage collected application can still call close, providing a convenient way to prevent receiver + from doing any more loading and firing any future delegate methods. + */ + HRESULT close(); } /* diff --git a/WebKit/win/Interfaces/IWebViewPrivate.idl b/WebKit/win/Interfaces/IWebViewPrivate.idl index c32a20b..4362f89 100644 --- a/WebKit/win/Interfaces/IWebViewPrivate.idl +++ b/WebKit/win/Interfaces/IWebViewPrivate.idl @@ -157,4 +157,6 @@ interface IWebViewPrivate : IUnknown HRESULT registerEmbeddedViewMIMEType([in] BSTR mimeType); HRESULT setMemoryCacheDelegateCallsEnabled([in] BOOL enabled); + + HRESULT setJavaScriptURLsAreAllowed([in] BOOL areAllowed); } diff --git a/WebKit/win/Interfaces/WebKit.idl b/WebKit/win/Interfaces/WebKit.idl index a78a5d3..338ab71 100644 --- a/WebKit/win/Interfaces/WebKit.idl +++ b/WebKit/win/Interfaces/WebKit.idl @@ -367,3 +367,4 @@ library WebKit } } + diff --git a/WebKit/win/MarshallingHelpers.cpp b/WebKit/win/MarshallingHelpers.cpp index 60f2749..0cec6de 100644 --- a/WebKit/win/MarshallingHelpers.cpp +++ b/WebKit/win/MarshallingHelpers.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "WebKitDLL.h" #include "MarshallingHelpers.h" +#include "MathExtras.h" #pragma warning(push, 0) #include <WebCore/IntRect.h> @@ -144,12 +145,12 @@ CFAbsoluteTime MarshallingHelpers::DATEToCFAbsoluteTime(DATE date) // the reference date. Positive values indicate dates/times after the // reference date. - return (date + windowsEpochAbsoluteTime()) * secondsPerDay; + return round((date + windowsEpochAbsoluteTime()) * secondsPerDay); } DATE MarshallingHelpers::CFAbsoluteTimeToDATE(CFAbsoluteTime absoluteTime) { - return (absoluteTime/secondsPerDay - windowsEpochAbsoluteTime()); + return (round(absoluteTime)/secondsPerDay - windowsEpochAbsoluteTime()); } // utility method to store a 1-dim string vector into a newly created SAFEARRAY diff --git a/WebKit/win/WebCache.cpp b/WebKit/win/WebCache.cpp index 2e5c2e9..c7351b0 100644 --- a/WebKit/win/WebCache.cpp +++ b/WebKit/win/WebCache.cpp @@ -30,7 +30,9 @@ #include "CFDictionaryPropertyBag.h" #pragma warning(push, 0) +#include <WebCore/ApplicationCacheStorage.h> #include <WebCore/Cache.h> +#include <WebCore/CrossOriginPreflightResultCache.h> #pragma warning(pop) // WebCache --------------------------------------------------------------------------- @@ -206,6 +208,13 @@ HRESULT STDMETHODCALLTYPE WebCache::empty( void) return S_OK; WebCore::cache()->setDisabled(true); WebCore::cache()->setDisabled(false); + + // Empty the application cache. + WebCore::cacheStorage().empty(); + + // Empty the Cross-Origin Preflight cache + WebCore::CrossOriginPreflightResultCache::shared().empty(); + return S_OK; } diff --git a/WebKit/win/WebCoreLocalizedStrings.cpp b/WebKit/win/WebCoreLocalizedStrings.cpp index 21dc35d..c383818 100644 --- a/WebKit/win/WebCoreLocalizedStrings.cpp +++ b/WebKit/win/WebCoreLocalizedStrings.cpp @@ -68,8 +68,8 @@ String WebCore::contextMenuItemTagBold() { return String(LPCTSTR_UI_STRING("Bold String WebCore::contextMenuItemTagItalic() { return String(LPCTSTR_UI_STRING("Italic", "Italic context menu item")); } String WebCore::contextMenuItemTagUnderline() { return String(LPCTSTR_UI_STRING("Underline", "Underline context menu item")); } String WebCore::contextMenuItemTagOutline() { return String(LPCTSTR_UI_STRING("Outline", "Outline context menu item")); } -String WebCore::contextMenuItemTagWritingDirectionMenu() { return String(LPCTSTR_UI_STRING("Writing Direction", "Writing direction context sub-menu item")); } -String WebCore::contextMenuItemTagTextDirectionMenu() { return String(LPCTSTR_UI_STRING("Text Direction", "Text direction context sub-menu item")); } +String WebCore::contextMenuItemTagWritingDirectionMenu() { return String(LPCTSTR_UI_STRING("Paragraph Direction", "Paragraph direction context sub-menu item")); } +String WebCore::contextMenuItemTagTextDirectionMenu() { return String(LPCTSTR_UI_STRING("Selection Direction", "Selection direction context sub-menu item")); } String WebCore::contextMenuItemTagDefaultDirection() { return String(LPCTSTR_UI_STRING("Default", "Default writing direction context menu item")); } String WebCore::contextMenuItemTagLeftToRight() { return String(LPCTSTR_UI_STRING("Left to Right", "Left to Right context menu item")); } String WebCore::contextMenuItemTagRightToLeft() { return String(LPCTSTR_UI_STRING("Right to Left", "Right to Left context menu item")); } diff --git a/WebKit/win/WebCoreSupport/WebChromeClient.cpp b/WebKit/win/WebCoreSupport/WebChromeClient.cpp index 9aec24b..1f0c09c 100644 --- a/WebKit/win/WebCoreSupport/WebChromeClient.cpp +++ b/WebKit/win/WebCoreSupport/WebChromeClient.cpp @@ -506,6 +506,7 @@ void WebChromeClient::print(Frame* frame) uiDelegate2->printFrame(m_webView, kit(frame)); } +#if ENABLE(DATABASE) void WebChromeClient::exceededDatabaseQuota(Frame* frame, const String& databaseIdentifier) { COMPtr<WebSecurityOrigin> origin(AdoptCOM, WebSecurityOrigin::createInstance(frame->document()->securityOrigin())); @@ -540,6 +541,16 @@ void WebChromeClient::exceededDatabaseQuota(Frame* frame, const String& database } } } +#endif + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +#include "ApplicationCacheStorage.h" +void WebChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded) +{ + // FIXME: Free some space. + notImplemented(); +} +#endif void WebChromeClient::populateVisitedLinks() { diff --git a/WebKit/win/WebCoreSupport/WebChromeClient.h b/WebKit/win/WebCoreSupport/WebChromeClient.h index cb9f470..4aa7422 100644 --- a/WebKit/win/WebCoreSupport/WebChromeClient.h +++ b/WebKit/win/WebCoreSupport/WebChromeClient.h @@ -105,7 +105,13 @@ public: virtual void print(WebCore::Frame*); +#if ENABLE(DATABASE) virtual void exceededDatabaseQuota(WebCore::Frame*, const WebCore::String&); +#endif + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); +#endif virtual void populateVisitedLinks(); diff --git a/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp b/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp index 1af1673..c307660 100644 --- a/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp +++ b/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp @@ -41,6 +41,7 @@ #include "WebError.h" #include "WebFrame.h" #include "WebHistory.h" +#include "WebHistoryItem.h" #include "WebMutableURLRequest.h" #include "WebNotificationCenter.h" #include "WebScriptDebugServer.h" @@ -53,9 +54,11 @@ #include <WebCore/FrameLoader.h> #include <WebCore/FrameTree.h> #include <WebCore/FrameView.h> +#include <WebCore/HTMLAppletElement.h> #include <WebCore/HTMLFrameElement.h> #include <WebCore/HTMLFrameOwnerElement.h> #include <WebCore/HTMLNames.h> +#include <WebCore/HTMLPlugInElement.h> #include <WebCore/HistoryItem.h> #include <WebCore/Page.h> #include <WebCore/PluginPackage.h> @@ -91,7 +94,9 @@ bool WebFrameLoaderClient::hasWebView() const void WebFrameLoaderClient::forceLayout() { - core(m_webFrame)->forceLayout(true); + FrameView* view = core(m_webFrame)->view(); + if (view) + view->forceLayout(true); } void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request) @@ -221,6 +226,25 @@ void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader* loader, unsign resourceLoadDelegate->didFailLoadingWithError(webView, identifier, webError.get(), getWebDataSource(loader)); } +bool WebFrameLoaderClient::shouldCacheResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response, const unsigned char* data, const unsigned long long length) +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate))) + return true; + + COMPtr<IWebResourceLoadDelegatePrivate3> resourceLoadDelegatePrivate(Query, resourceLoadDelegate); + if (!resourceLoadDelegatePrivate) + return true; + + COMPtr<IWebURLResponse> urlResponse(WebURLResponse::createInstance(response)); + BOOL shouldCache; + if (SUCCEEDED(resourceLoadDelegatePrivate->shouldCacheResponse(webView, identifier, urlResponse.get(), data, length, getWebDataSource(loader), &shouldCache))) + return shouldCache; + + return true; +} + void WebFrameLoaderClient::dispatchDidHandleOnloadEvents() { WebView* webView = m_webFrame->webView(); @@ -457,27 +481,31 @@ void WebFrameLoaderClient::updateGlobalHistory() return; DocumentLoader* loader = core(m_webFrame)->loader()->documentLoader(); - - if (loader->urlForHistoryReflectsServerRedirect()) { - history->visitedURL(loader->urlForHistory(), loader->title(), loader->request().httpMethod(), loader->urlForHistoryReflectsFailure(), loader->url(), false); - return; - } - - if (loader->urlForHistoryReflectsClientRedirect()) { - history->visitedURL(loader->urlForHistory(), loader->title(), loader->request().httpMethod(), loader->urlForHistoryReflectsFailure(), KURL(), true); - return; - } - - history->visitedURL(loader->urlForHistory(), loader->title(), loader->request().httpMethod(), loader->urlForHistoryReflectsFailure(), KURL(), false); + history->visitedURL(loader->urlForHistory(), loader->title(), loader->originalRequestCopy().httpMethod(), loader->urlForHistoryReflectsFailure()); + updateGlobalHistoryRedirectLinks(); } -void WebFrameLoaderClient::updateGlobalHistoryForRedirectWithoutHistoryItem() +void WebFrameLoaderClient::updateGlobalHistoryRedirectLinks() { WebHistory* history = WebHistory::sharedHistory(); if (!history) return; + DocumentLoader* loader = core(m_webFrame)->loader()->documentLoader(); - history->visitedURLForRedirectWithoutHistoryItem(loader->url()); + + if (!loader->clientRedirectSourceForHistory().isNull()) { + if (COMPtr<IWebHistoryItem> iWebHistoryItem = history->itemForURLString(loader->clientRedirectSourceForHistory())) { + COMPtr<WebHistoryItem> webHistoryItem(Query, iWebHistoryItem); + webHistoryItem->historyItem()->addRedirectURL(loader->clientRedirectDestinationForHistory()); + } + } + + if (!loader->serverRedirectSourceForHistory().isNull()) { + if (COMPtr<IWebHistoryItem> iWebHistoryItem = history->itemForURLString(loader->serverRedirectSourceForHistory())) { + COMPtr<WebHistoryItem> webHistoryItem(Query, iWebHistoryItem); + webHistoryItem->historyItem()->addRedirectURL(loader->serverRedirectDestinationForHistory()); + } + } } bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem*) const @@ -548,7 +576,7 @@ void WebFrameLoaderClient::transitionToCommittedForNewPage() view->frameRect(&rect); bool transparent = view->transparent(); Color backgroundColor = transparent ? Color::transparent : Color::white; - WebCore::FrameLoaderClient::transitionToCommittedForNewPage(core(m_webFrame), IntRect(rect).size(), backgroundColor, transparent, IntSize(), false); + core(m_webFrame)->createView(IntRect(rect).size(), backgroundColor, transparent, IntSize(), false); } bool WebFrameLoaderClient::canCachePage() const @@ -627,7 +655,7 @@ void WebFrameLoaderClient::loadURLIntoChild(const KURL& originalURL, const Strin core(childFrame)->loader()->loadURL(url, referrer, frameName, false, childLoadType, 0, 0); } -Widget* WebFrameLoaderClient::createPlugin(const IntSize& pluginSize, Element* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually) +Widget* WebFrameLoaderClient::createPlugin(const IntSize& pluginSize, HTMLPlugInElement* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually) { WebView* webView = m_webFrame->webView(); diff --git a/WebKit/win/WebCoreSupport/WebFrameLoaderClient.h b/WebKit/win/WebCoreSupport/WebFrameLoaderClient.h index 3877273..ac7a8c7 100644 --- a/WebKit/win/WebCoreSupport/WebFrameLoaderClient.h +++ b/WebKit/win/WebCoreSupport/WebFrameLoaderClient.h @@ -56,6 +56,7 @@ public: virtual void dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long identifier, int lengthReceived); virtual void dispatchDidFinishLoading(WebCore::DocumentLoader*, unsigned long identifier); virtual void dispatchDidFailLoading(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::ResourceError&); + virtual bool shouldCacheResponse(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::ResourceResponse&, const unsigned char* data, unsigned long long length); virtual void dispatchDidHandleOnloadEvents(); virtual void dispatchDidReceiveServerRedirectForProvisionalLoad(); @@ -86,7 +87,7 @@ public: virtual void finishedLoading(WebCore::DocumentLoader*); virtual void updateGlobalHistory(); - virtual void updateGlobalHistoryForRedirectWithoutHistoryItem(); + virtual void updateGlobalHistoryRedirectLinks(); virtual bool shouldGoToHistoryItem(WebCore::HistoryItem*) const; virtual PassRefPtr<WebCore::DocumentLoader> createDocumentLoader(const WebCore::ResourceRequest&, const WebCore::SubstituteData&); @@ -100,7 +101,7 @@ public: virtual PassRefPtr<WebCore::Frame> createFrame(const WebCore::KURL& url, const WebCore::String& name, WebCore::HTMLFrameOwnerElement* ownerElement, const WebCore::String& referrer, bool allowsScrolling, int marginWidth, int marginHeight); - virtual WebCore::Widget* createPlugin(const WebCore::IntSize&, WebCore::Element*, const WebCore::KURL&, const Vector<WebCore::String>&, const Vector<WebCore::String>&, const WebCore::String&, bool loadManually); + virtual WebCore::Widget* createPlugin(const WebCore::IntSize&, WebCore::HTMLPlugInElement*, const WebCore::KURL&, const Vector<WebCore::String>&, const Vector<WebCore::String>&, const WebCore::String&, bool loadManually); virtual void redirectDataToPlugin(WebCore::Widget* pluginWidget); virtual bool shouldUsePluginDocument(const WebCore::String& mimeType) const; diff --git a/WebKit/win/WebCoreSupport/WebInspectorClient.cpp b/WebKit/win/WebCoreSupport/WebInspectorClient.cpp index 56cf0df..5bb1a83 100644 --- a/WebKit/win/WebCoreSupport/WebInspectorClient.cpp +++ b/WebKit/win/WebCoreSupport/WebInspectorClient.cpp @@ -201,6 +201,13 @@ String WebInspectorClient::localizedStringsURL() return CFURLGetString(url.get()); } + +String WebInspectorClient::hiddenPanels() +{ + // FIXME: implement this + return String(); +} + void WebInspectorClient::showWindow() { showWindowWithoutNotifications(); diff --git a/WebKit/win/WebCoreSupport/WebInspectorClient.h b/WebKit/win/WebCoreSupport/WebInspectorClient.h index 86317f6..b497788 100644 --- a/WebKit/win/WebCoreSupport/WebInspectorClient.h +++ b/WebKit/win/WebCoreSupport/WebInspectorClient.h @@ -50,6 +50,8 @@ public: virtual WebCore::String localizedStringsURL(); + virtual WebCore::String hiddenPanels(); + virtual void showWindow(); virtual void closeWindow(); virtual bool windowVisible(); diff --git a/WebKit/win/WebDatabaseManager.cpp b/WebKit/win/WebDatabaseManager.cpp index d4974ed..c16a600 100644 --- a/WebKit/win/WebDatabaseManager.cpp +++ b/WebKit/win/WebDatabaseManager.cpp @@ -30,6 +30,8 @@ #include "WebDatabaseManager.h" #include "WebKitDLL.h" +#if ENABLE(DATABASE) + #include "CFDictionaryPropertyBag.h" #include "COMEnumVariant.h" #include "MarshallingHelpers.h" @@ -364,3 +366,5 @@ void WebKitSetWebDatabasesPathIfNecessary() pathSet = true; } + +#endif diff --git a/WebKit/win/WebDatabaseManager.h b/WebKit/win/WebDatabaseManager.h index 303f1e8..f7084ba 100644 --- a/WebKit/win/WebDatabaseManager.h +++ b/WebKit/win/WebDatabaseManager.h @@ -29,6 +29,8 @@ #ifndef WebDatabaseManager_h #define WebDatabaseManager_h +#if ENABLE(DATABASE) + #include <WebCore/DatabaseTrackerClient.h> #include "WebKit.h" @@ -85,3 +87,5 @@ private: void WebKitSetWebDatabasesPathIfNecessary(); #endif + +#endif diff --git a/WebKit/win/WebFrame.cpp b/WebKit/win/WebFrame.cpp index 009111a..f1877fe 100644 --- a/WebKit/win/WebFrame.cpp +++ b/WebKit/win/WebFrame.cpp @@ -69,10 +69,12 @@ #include <WebCore/GDIObjectCounter.h> #include <WebCore/GraphicsContext.h> #include <WebCore/HistoryItem.h> +#include <WebCore/HTMLAppletElement.h> #include <WebCore/HTMLFormElement.h> #include <WebCore/HTMLFormControlElement.h> #include <WebCore/HTMLInputElement.h> #include <WebCore/HTMLNames.h> +#include <WebCore/HTMLPlugInElement.h> #include <WebCore/JSDOMWindow.h> #include <WebCore/KeyboardEvent.h> #include <WebCore/MIMETypeRegistry.h> @@ -1049,6 +1051,87 @@ HRESULT WebFrame::elementDoesAutoComplete(IDOMElement *element, BOOL *result) return S_OK; } +HRESULT WebFrame::pauseAnimation(BSTR animationName, IDOMNode* node, double secondsFromNow, BOOL* animationWasRunning) +{ + if (!node || !animationWasRunning) + return E_POINTER; + + *animationWasRunning = FALSE; + + Frame* frame = core(this); + if (!frame) + return E_FAIL; + + AnimationController* controller = frame->animation(); + if (!controller) + return E_FAIL; + + COMPtr<DOMNode> domNode(Query, node); + if (!domNode) + return E_FAIL; + + *animationWasRunning = controller->pauseAnimationAtTime(domNode->node()->renderer(), String(animationName, SysStringLen(animationName)), secondsFromNow); + return S_OK; +} + +HRESULT WebFrame::pauseTransition(BSTR propertyName, IDOMNode* node, double secondsFromNow, BOOL* transitionWasRunning) +{ + if (!node || !transitionWasRunning) + return E_POINTER; + + *transitionWasRunning = FALSE; + + Frame* frame = core(this); + if (!frame) + return E_FAIL; + + AnimationController* controller = frame->animation(); + if (!controller) + return E_FAIL; + + COMPtr<DOMNode> domNode(Query, node); + if (!domNode) + return E_FAIL; + + *transitionWasRunning = controller->pauseTransitionAtTime(domNode->node()->renderer(), String(propertyName, SysStringLen(propertyName)), secondsFromNow); + return S_OK; +} + +HRESULT WebFrame::numberOfActiveAnimations(UINT* number) +{ + if (!number) + return E_POINTER; + + *number = 0; + + Frame* frame = core(this); + if (!frame) + return E_FAIL; + + AnimationController* controller = frame->animation(); + if (!controller) + return E_FAIL; + + *number = controller->numberOfActiveAnimations(); + return S_OK; +} + +HRESULT WebFrame::isDisplayingStandaloneImage(BOOL* result) +{ + if (!result) + return E_POINTER; + + *result = FALSE; + + Frame* frame = core(this); + if (!frame) + return E_FAIL; + + Document* document = frame->document(); + *result = document && document->isImageDocument(); + return S_OK; +} + HRESULT WebFrame::controlsInForm(IDOMElement* form, IDOMElement** controls, int* cControls) { if (!form) @@ -1288,8 +1371,6 @@ String WebFrame::generatedMIMETypeForURLScheme(const String& /*URLScheme*/) cons void WebFrame::frameLoadCompleted() { - if (Frame* coreFrame = core(this)) - coreFrame->loader()->setPreviousHistoryItem(0); } void WebFrame::restoreViewState() @@ -1523,7 +1604,7 @@ void WebFrame::startDownload(const ResourceRequest&) notImplemented(); } -Widget* WebFrame::createJavaAppletWidget(const IntSize& pluginSize, Element* element, const KURL& /*baseURL*/, const Vector<String>& paramNames, const Vector<String>& paramValues) +Widget* WebFrame::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement* element, const KURL& /*baseURL*/, const Vector<String>& paramNames, const Vector<String>& paramValues) { PluginView* pluginView = PluginView::create(core(this), pluginSize, element, KURL(), paramNames, paramValues, "application/x-java-applet", false); @@ -1595,6 +1676,10 @@ void WebFrame::windowObjectCleared() } } +void WebFrame::documentElementAvailable() +{ +} + void WebFrame::didPerformFirstNavigation() const { COMPtr<IWebPreferences> preferences; @@ -1643,7 +1728,7 @@ HRESULT STDMETHODCALLTYPE WebFrame::setInPrintingMode( return S_OK; Frame* coreFrame = core(this); - if (!coreFrame) + if (!coreFrame || !coreFrame->document()) return E_FAIL; m_inPrintingMode = !!value; @@ -1652,7 +1737,7 @@ HRESULT STDMETHODCALLTYPE WebFrame::setInPrintingMode( // according to the paper size float minLayoutWidth = 0.0f; float maxLayoutWidth = 0.0f; - if (m_inPrintingMode && !coreFrame->isFrameSet()) { + if (m_inPrintingMode && !coreFrame->document()->isFrameSet()) { if (!printDC) { ASSERT_NOT_REACHED(); return E_POINTER; @@ -1868,10 +1953,10 @@ HRESULT STDMETHODCALLTYPE WebFrame::isFrameSet( *result = FALSE; Frame* coreFrame = core(this); - if (!coreFrame) + if (!coreFrame || !coreFrame->document()) return E_FAIL; - *result = coreFrame->isFrameSet() ? TRUE : FALSE; + *result = coreFrame->document()->isFrameSet() ? TRUE : FALSE; return S_OK; } diff --git a/WebKit/win/WebFrame.h b/WebKit/win/WebFrame.h index bf234d3..bca32d4 100644 --- a/WebKit/win/WebFrame.h +++ b/WebKit/win/WebFrame.h @@ -223,7 +223,13 @@ public: virtual HRESULT STDMETHODCALLTYPE elementDoesAutoComplete( /* [in] */ IDOMElement* element, /* [retval][out] */ BOOL* result); - + + virtual HRESULT STDMETHODCALLTYPE pauseAnimation(BSTR animationName, IDOMNode*, double secondsFromNow, BOOL* animationWasRunning); + virtual HRESULT STDMETHODCALLTYPE pauseTransition(BSTR propertyName, IDOMNode*, double secondsFromNow, BOOL* transitionWasRunning); + virtual HRESULT STDMETHODCALLTYPE numberOfActiveAnimations(UINT*); + + virtual HRESULT STDMETHODCALLTYPE isDisplayingStandaloneImage(BOOL*); + // IWebDocumentText virtual HRESULT STDMETHODCALLTYPE supportsTextEncoding( /* [retval][out] */ BOOL* result); @@ -280,12 +286,13 @@ public: virtual void dispatchDidFailLoad(const WebCore::ResourceError&); virtual void startDownload(const WebCore::ResourceRequest&); - virtual WebCore::Widget* createJavaAppletWidget(const WebCore::IntSize&, WebCore::Element*, const WebCore::KURL& baseURL, const Vector<WebCore::String>& paramNames, const Vector<WebCore::String>& paramValues); + virtual WebCore::Widget* createJavaAppletWidget(const WebCore::IntSize&, WebCore::HTMLAppletElement*, const WebCore::KURL& baseURL, const Vector<WebCore::String>& paramNames, const Vector<WebCore::String>& paramValues); virtual WebCore::ObjectContentType objectContentType(const WebCore::KURL& url, const WebCore::String& mimeType); virtual WebCore::String overrideMediaType() const; virtual void windowObjectCleared(); + virtual void documentElementAvailable(); virtual void didPerformFirstNavigation() const; virtual void registerForIconNotification(bool listen); diff --git a/WebKit/win/WebHistory.cpp b/WebKit/win/WebHistory.cpp index 5ee2e32..e647e01 100644 --- a/WebKit/win/WebHistory.cpp +++ b/WebKit/win/WebHistory.cpp @@ -41,6 +41,7 @@ #include <WebCore/PageGroup.h> #include <WebCore/HistoryItem.h> #pragma warning( pop ) +#include <wtf/StdLibExtras.h> using namespace WebCore; @@ -176,7 +177,7 @@ ULONG STDMETHODCALLTYPE WebHistory::Release(void) static inline COMPtr<WebHistory>& sharedHistoryStorage() { - static COMPtr<WebHistory> sharedHistory; + DEFINE_STATIC_LOCAL(COMPtr<WebHistory>, sharedHistory, ()); return sharedHistory; } @@ -680,18 +681,11 @@ HRESULT WebHistory::addItem(IWebHistoryItem* entry, bool discardDuplicate, bool* return hr; } -void WebHistory::visitedURL(const KURL& url, const String& title, const String& httpMethod, bool wasFailure, const KURL& serverRedirectURL, bool isClientRedirect) +void WebHistory::visitedURL(const KURL& url, const String& title, const String& httpMethod, bool wasFailure) { - if (isClientRedirect) { - ASSERT(serverRedirectURL.isEmpty()); - if (m_lastVisitedEntry) - m_lastVisitedEntry->historyItem()->addRedirectURL(url.string()); - } - RetainPtr<CFStringRef> urlString(AdoptCF, url.string().createCFString()); IWebHistoryItem* entry = (IWebHistoryItem*) CFDictionaryGetValue(m_entriesByURL.get(), urlString.get()); - if (entry) { COMPtr<IWebHistoryItemPrivate> entryPrivate(Query, entry); if (!entryPrivate) @@ -724,21 +718,16 @@ void WebHistory::visitedURL(const KURL& url, const String& title, const String& addItemToDateCaches(entry); - m_lastVisitedEntry.query(entry); - COMPtr<IWebHistoryItemPrivate> entryPrivate(Query, entry); if (!entryPrivate) return; entryPrivate->setLastVisitWasFailure(wasFailure); if (!httpMethod.isEmpty()) - entryPrivate->setLastVisitWasHTTPNonGet(!equalIgnoringCase(httpMethod, "GET")); + entryPrivate->setLastVisitWasHTTPNonGet(!equalIgnoringCase(httpMethod, "GET") && (url.protocolIs("http") || url.protocolIs("https"))); - if (!serverRedirectURL.isEmpty()) { - ASSERT(!isClientRedirect); - COMPtr<WebHistoryItem> item(Query, entry); - item->historyItem()->addRedirectURL(serverRedirectURL); - } + COMPtr<WebHistoryItem> item(Query, entry); + item->historyItem()->setRedirectURLs(std::auto_ptr<Vector<String> >()); CFDictionaryPropertyBag* userInfo = createUserInfoFromHistoryItem( getNotificationString(kWebHistoryItemsAddedNotification), entry); @@ -746,15 +735,9 @@ void WebHistory::visitedURL(const KURL& url, const String& title, const String& releaseUserInfo(userInfo); } -void WebHistory::visitedURLForRedirectWithoutHistoryItem(const KURL& url) -{ - if (m_lastVisitedEntry) - m_lastVisitedEntry->historyItem()->addRedirectURL(url.string()); -} - HRESULT WebHistory::itemForURLString( /* [in] */ CFStringRef urlString, - /* [retval][out] */ IWebHistoryItem** item) + /* [retval][out] */ IWebHistoryItem** item) const { if (!item) return E_FAIL; @@ -792,6 +775,17 @@ HRESULT WebHistory::removeItemForURLString(CFStringRef urlString) return hr; } +COMPtr<IWebHistoryItem> WebHistory::itemForURLString(const String& urlString) const +{ + RetainPtr<CFStringRef> urlCFString(AdoptCF, urlString.createCFString()); + if (!urlCFString) + return 0; + COMPtr<IWebHistoryItem> item; + if (FAILED(itemForURLString(urlCFString.get(), &item))) + return 0; + return item; +} + HRESULT WebHistory::addItemToDateCaches(IWebHistoryItem* entry) { HRESULT hr = S_OK; diff --git a/WebKit/win/WebHistory.h b/WebKit/win/WebHistory.h index 111f6ae..b1031b7 100644 --- a/WebKit/win/WebHistory.h +++ b/WebKit/win/WebHistory.h @@ -115,10 +115,11 @@ public: // WebHistory static WebHistory* sharedHistory(); - void visitedURL(const WebCore::KURL&, const WebCore::String& title, const WebCore::String& httpMethod, bool wasFailure, const WebCore::KURL& serverRedirectURL, bool isClientRedirect); - void visitedURLForRedirectWithoutHistoryItem(const WebCore::KURL&); + void visitedURL(const WebCore::KURL&, const WebCore::String& title, const WebCore::String& httpMethod, bool wasFailure); void addVisitedLinksToPageGroup(WebCore::PageGroup&); + COMPtr<IWebHistoryItem> itemForURLString(const WebCore::String&) const; + private: enum NotificationType { @@ -144,14 +145,13 @@ private: bool findIndex(int* index, CFAbsoluteTime forDay); static CFAbsoluteTime timeToDate(CFAbsoluteTime time); BSTR getNotificationString(NotificationType notifyType); - HRESULT itemForURLString(CFStringRef urlString, IWebHistoryItem** item); + HRESULT itemForURLString(CFStringRef urlString, IWebHistoryItem** item) const; ULONG m_refCount; RetainPtr<CFMutableDictionaryRef> m_entriesByURL; RetainPtr<CFMutableArrayRef> m_datesWithEntries; RetainPtr<CFMutableArrayRef> m_entriesByDate; COMPtr<WebPreferences> m_preferences; - COMPtr<WebHistoryItem> m_lastVisitedEntry; }; #endif diff --git a/WebKit/win/WebKit.vcproj/WebKit.def b/WebKit/win/WebKit.vcproj/WebKit.def index fa3f2bc..cc49cd0 100644 --- a/WebKit/win/WebKit.vcproj/WebKit.def +++ b/WebKit/win/WebKit.vcproj/WebKit.def @@ -12,9 +12,14 @@ EXPORTS JSClassRelease JSClassRetain JSContextGetGlobalObject + JSContextGetGroup + JSContextGroupCreate + JSContextGroupRelease + JSContextGroupRetain JSEvaluateScript JSGarbageCollect JSGlobalContextCreate + JSGlobalContextCreateInGroup JSGlobalContextRelease JSGlobalContextRetain JSObjectCallAsConstructor @@ -32,6 +37,7 @@ EXPORTS JSObjectMakeArray JSObjectMakeConstructor JSObjectMakeDate + JSObjectMakeError JSObjectMakeFunction JSObjectMakeFunctionWithCallback JSObjectMakeRegExp @@ -121,6 +127,9 @@ EXPORTS ?lock@Mutex@WTF@@QAEXXZ ?lockAtomicallyInitializedStaticMutex@WTF@@YAXXZ ?signal@ThreadCondition@WTF@@QAEXXZ + ?timedWait@ThreadCondition@WTF@@QAE_NAAVMutex@2@N@Z + ?tlsKeyCount@WTF@@YAAAJXZ + ?tlsKeys@WTF@@YAPAKXZ ?tryLock@Mutex@WTF@@QAE_NXZ ?unlock@Mutex@WTF@@QAEXXZ ?unlockAtomicallyInitializedStaticMutex@WTF@@YAXXZ diff --git a/WebKit/win/WebKit.vcproj/WebKit.vcproj b/WebKit/win/WebKit.vcproj/WebKit.vcproj index 0740e8a..b578aee 100644 --- a/WebKit/win/WebKit.vcproj/WebKit.vcproj +++ b/WebKit/win/WebKit.vcproj/WebKit.vcproj @@ -23,7 +23,7 @@ >
<Tool
Name="VCPreBuildEventTool"
- CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

touch "$(WebKitOutputDir)\tmp.cpp"
cl /analyze /nologo /c "$(WebKitOutputDir)\tmp.cpp" 2>&1 | findstr D9040
if ERRORLEVEL 0 set EnablePREfast="false" else set EnablePREfast="true"
if ERRORLEVEL 0 set AnalyzeWithLargeStack="" AnalyzeWithLargeStack="/analyze:65536"

mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"
xcopy /y /d "$(WebKitLibrariesDir)\include\JavaScriptCore\JavaScriptCore\*" "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"

bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
+ CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

touch "$(WebKitOutputDir)\tmp.cpp"
cl /analyze /nologo /c "$(WebKitOutputDir)\tmp.cpp" 2>&1 | findstr D9040
if ERRORLEVEL 1 (set EnablePREfast="true") else (set EnablePREfast="false")
if ERRORLEVEL 1 (set AnalyzeWithLargeStack="/analyze:65536") else (set AnalyzeWithLargeStack="")

mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"
xcopy /y /d "$(WebKitLibrariesDir)\include\JavaScriptCore\JavaScriptCore\*" "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"

bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
/>
<Tool
Name="VCCustomBuildTool"
@@ -99,7 +99,7 @@ >
<Tool
Name="VCPreBuildEventTool"
- CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

touch "$(WebKitOutputDir)\tmp.cpp"
cl /analyze /nologo /c "$(WebKitOutputDir)\tmp.cpp" 2>&1 | findstr D9040
if ERRORLEVEL 0 set EnablePREfast="false" else set EnablePREfast="true"
if ERRORLEVEL 0 set AnalyzeWithLargeStack="" AnalyzeWithLargeStack="/analyze:65536"

mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"
xcopy /y /d "$(WebKitLibrariesDir)\include\JavaScriptCore\JavaScriptCore\*" "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"

bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
+ CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

touch "$(WebKitOutputDir)\tmp.cpp"
cl /analyze /nologo /c "$(WebKitOutputDir)\tmp.cpp" 2>&1 | findstr D9040
if ERRORLEVEL 1 (set EnablePREfast="true") else (set EnablePREfast="false")
if ERRORLEVEL 1 (set AnalyzeWithLargeStack="/analyze:65536") else (set AnalyzeWithLargeStack="")

mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"
xcopy /y /d "$(WebKitLibrariesDir)\include\JavaScriptCore\JavaScriptCore\*" "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"

bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
/>
<Tool
Name="VCCustomBuildTool"
@@ -174,7 +174,7 @@ >
<Tool
Name="VCPreBuildEventTool"
- CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

touch "$(WebKitOutputDir)\tmp.cpp"
cl /analyze /nologo /c "$(WebKitOutputDir)\tmp.cpp" 2>&1 | findstr D9040
if ERRORLEVEL 0 set EnablePREfast="false" else set EnablePREfast="true"
if ERRORLEVEL 0 set AnalyzeWithLargeStack="" AnalyzeWithLargeStack="/analyze:65536"

mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"
xcopy /y /d "$(WebKitLibrariesDir)\include\JavaScriptCore\JavaScriptCore\*" "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"

bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
+ CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

touch "$(WebKitOutputDir)\tmp.cpp"
cl /analyze /nologo /c "$(WebKitOutputDir)\tmp.cpp" 2>&1 | findstr D9040
if ERRORLEVEL 1 (set EnablePREfast="true") else (set EnablePREfast="false")
if ERRORLEVEL 1 (set AnalyzeWithLargeStack="/analyze:65536") else (set AnalyzeWithLargeStack="")

mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"
xcopy /y /d "$(WebKitLibrariesDir)\include\JavaScriptCore\JavaScriptCore\*" "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"

bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
/>
<Tool
Name="VCCustomBuildTool"
@@ -252,7 +252,7 @@ >
<Tool
Name="VCPreBuildEventTool"
- CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

touch "$(WebKitOutputDir)\tmp.cpp"
cl /analyze /nologo /c "$(WebKitOutputDir)\tmp.cpp" 2>&1 | findstr D9040
if ERRORLEVEL 0 set EnablePREfast="false" else set EnablePREfast="true"
if ERRORLEVEL 0 set AnalyzeWithLargeStack="" AnalyzeWithLargeStack="/analyze:65536"

mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"
xcopy /y /d "$(WebKitLibrariesDir)\include\JavaScriptCore\JavaScriptCore\*" "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"

bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
+ CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

touch "$(WebKitOutputDir)\tmp.cpp"
cl /analyze /nologo /c "$(WebKitOutputDir)\tmp.cpp" 2>&1 | findstr D9040
if ERRORLEVEL 1 (set EnablePREfast="true") else (set EnablePREfast="false")
if ERRORLEVEL 1 (set AnalyzeWithLargeStack="/analyze:65536") else (set AnalyzeWithLargeStack="")

mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"
xcopy /y /d "$(WebKitLibrariesDir)\include\JavaScriptCore\JavaScriptCore\*" "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"

bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
/>
<Tool
Name="VCCustomBuildTool"
@@ -331,7 +331,7 @@ >
<Tool
Name="VCPreBuildEventTool"
- CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

touch "$(WebKitOutputDir)\tmp.cpp"
cl /analyze /nologo /c "$(WebKitOutputDir)\tmp.cpp" 2>&1 | findstr D9040
if ERRORLEVEL 0 set EnablePREfast="false" else set EnablePREfast="true"
if ERRORLEVEL 0 set AnalyzeWithLargeStack="" AnalyzeWithLargeStack="/analyze:65536"

mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"
xcopy /y /d "$(WebKitLibrariesDir)\include\JavaScriptCore\JavaScriptCore\*" "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"

bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
+ CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

touch "$(WebKitOutputDir)\tmp.cpp"
cl /analyze /nologo /c "$(WebKitOutputDir)\tmp.cpp" 2>&1 | findstr D9040
if ERRORLEVEL 1 (set EnablePREfast="true") else (set EnablePREfast="false")
if ERRORLEVEL 1 (set AnalyzeWithLargeStack="/analyze:65536") else (set AnalyzeWithLargeStack="")

mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"
xcopy /y /d "$(WebKitLibrariesDir)\include\JavaScriptCore\JavaScriptCore\*" "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"

bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
/>
<Tool
Name="VCCustomBuildTool"
@@ -408,7 +408,7 @@ >
<Tool
Name="VCPreBuildEventTool"
- CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

touch "$(WebKitOutputDir)\tmp.cpp"
cl /analyze /nologo /c "$(WebKitOutputDir)\tmp.cpp" 2>&1 | findstr D9040
if ERRORLEVEL 0 set EnablePREfast="false" else set EnablePREfast="true"
if ERRORLEVEL 0 set AnalyzeWithLargeStack="" AnalyzeWithLargeStack="/analyze:65536"

mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"
xcopy /y /d "$(WebKitLibrariesDir)\include\JavaScriptCore\JavaScriptCore\*" "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"

bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
+ CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

touch "$(WebKitOutputDir)\tmp.cpp"
cl /analyze /nologo /c "$(WebKitOutputDir)\tmp.cpp" 2>&1 | findstr D9040
if ERRORLEVEL 1 (set EnablePREfast="true") else (set EnablePREfast="false")
if ERRORLEVEL 1 (set AnalyzeWithLargeStack="/analyze:65536") else (set AnalyzeWithLargeStack="")

mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"
xcopy /y /d "$(WebKitLibrariesDir)\include\JavaScriptCore\JavaScriptCore\*" "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"

bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
/>
<Tool
Name="VCCustomBuildTool"
@@ -487,7 +487,7 @@ >
<Tool
Name="VCPreBuildEventTool"
- CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

touch "$(WebKitOutputDir)\tmp.cpp"
cl /analyze /nologo /c "$(WebKitOutputDir)\tmp.cpp" 2>&1 | findstr D9040
if ERRORLEVEL 0 set EnablePREfast="false" else set EnablePREfast="true"
if ERRORLEVEL 0 set AnalyzeWithLargeStack="" AnalyzeWithLargeStack="/analyze:65536"

mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"
xcopy /y /d "$(WebKitLibrariesDir)\include\JavaScriptCore\JavaScriptCore\*" "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"

bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
+ CommandLine="set PATH=%SystemDrive%\cygwin\bin;%PATH%
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

touch "$(WebKitOutputDir)\tmp.cpp"
cl /analyze /nologo /c "$(WebKitOutputDir)\tmp.cpp" 2>&1 | findstr D9040
if ERRORLEVEL 1 (set EnablePREfast="true") else (set EnablePREfast="false")
if ERRORLEVEL 1 (set AnalyzeWithLargeStack="/analyze:65536") else (set AnalyzeWithLargeStack="")

mkdir 2>NUL "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"
xcopy /y /d "$(WebKitLibrariesDir)\include\JavaScriptCore\JavaScriptCore\*" "$(WebKitOutputDir)\include\JavaScriptCore\JavaScriptCore"

bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
/>
<Tool
Name="VCCustomBuildTool"
@@ -1448,7 +1448,6 @@ >
<FileConfiguration
Name="Release_Cairo|Win32"
- ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
diff --git a/WebKit/win/WebKit.vcproj/WebKit_Cairo.def b/WebKit/win/WebKit.vcproj/WebKit_Cairo.def index 50b3675..bc1a3f2 100755 --- a/WebKit/win/WebKit.vcproj/WebKit_Cairo.def +++ b/WebKit/win/WebKit.vcproj/WebKit_Cairo.def @@ -12,9 +12,14 @@ EXPORTS JSClassRelease JSClassRetain JSContextGetGlobalObject + JSContextGetGroup + JSContextGroupCreate + JSContextGroupRelease + JSContextGroupRetain JSEvaluateScript JSGarbageCollect JSGlobalContextCreate + JSGlobalContextCreateInGroup JSGlobalContextRelease JSGlobalContextRetain JSObjectCallAsConstructor @@ -32,6 +37,7 @@ EXPORTS JSObjectMakeArray JSObjectMakeConstructor JSObjectMakeDate + JSObjectMakeError JSObjectMakeFunction JSObjectMakeFunctionWithCallback JSObjectMakeRegExp diff --git a/WebKit/win/WebKit.vcproj/WebKit_debug.def b/WebKit/win/WebKit.vcproj/WebKit_debug.def index 6ed6a90..9fecf25 100644 --- a/WebKit/win/WebKit.vcproj/WebKit_debug.def +++ b/WebKit/win/WebKit.vcproj/WebKit_debug.def @@ -12,9 +12,14 @@ EXPORTS JSClassRelease JSClassRetain JSContextGetGlobalObject + JSContextGetGroup + JSContextGroupCreate + JSContextGroupRelease + JSContextGroupRetain JSEvaluateScript JSGarbageCollect JSGlobalContextCreate + JSGlobalContextCreateInGroup JSGlobalContextRelease JSGlobalContextRetain JSObjectCallAsConstructor @@ -32,6 +37,7 @@ EXPORTS JSObjectMakeArray JSObjectMakeConstructor JSObjectMakeDate + JSObjectMakeError JSObjectMakeFunction JSObjectMakeFunctionWithCallback JSObjectMakeRegExp @@ -121,6 +127,9 @@ EXPORTS ?lock@Mutex@WTF@@QAEXXZ ?lockAtomicallyInitializedStaticMutex@WTF@@YAXXZ ?signal@ThreadCondition@WTF@@QAEXXZ + ?timedWait@ThreadCondition@WTF@@QAE_NAAVMutex@2@N@Z + ?tlsKeyCount@WTF@@YAAAJXZ + ?tlsKeys@WTF@@YAPAKXZ ?tryLock@Mutex@WTF@@QAE_NXZ ?unlock@Mutex@WTF@@QAEXXZ ?unlockAtomicallyInitializedStaticMutex@WTF@@YAXXZ diff --git a/WebKit/win/WebMutableURLRequest.cpp b/WebKit/win/WebMutableURLRequest.cpp index 63a060e..035fac3 100644 --- a/WebKit/win/WebMutableURLRequest.cpp +++ b/WebKit/win/WebMutableURLRequest.cpp @@ -33,6 +33,7 @@ #include <CFNetwork/CFURLRequestPriv.h> #pragma warning(push, 0) #include <WebCore/BString.h> +#include <WebCore/COMPtr.h> #include <WebCore/CString.h> #include <WebCore/FormData.h> #include <WebCore/NotImplemented.h> @@ -240,6 +241,22 @@ HRESULT STDMETHODCALLTYPE WebMutableURLRequest::isEmpty( return S_OK; } +HRESULT STDMETHODCALLTYPE WebMutableURLRequest::isEqual( + /* [in] */ IWebURLRequest* other, + /* [out, retval] */ BOOL* result) +{ + COMPtr<WebMutableURLRequest> requestImpl(Query, other); + + if (!requestImpl) { + *result = FALSE; + return S_OK; + } + + *result = m_request == requestImpl->resourceRequest(); + return S_OK; +} + + // IWebMutableURLRequest -------------------------------------------------------- HRESULT STDMETHODCALLTYPE WebMutableURLRequest::addValue( @@ -314,11 +331,13 @@ HRESULT STDMETHODCALLTYPE WebMutableURLRequest::setURL( } HRESULT STDMETHODCALLTYPE WebMutableURLRequest::setValue( - /* [in] */ BSTR /*value*/, - /* [in] */ BSTR /*field*/) + /* [in] */ BSTR value, + /* [in] */ BSTR field) { - ASSERT_NOT_REACHED(); - return E_NOTIMPL; + String valueString(value, SysStringLen(value)); + String fieldString(field, SysStringLen(field)); + m_request.setHTTPHeaderField(fieldString, valueString); + return S_OK; } HRESULT STDMETHODCALLTYPE WebMutableURLRequest::setAllowsAnyHTTPSCertificate(void) diff --git a/WebKit/win/WebMutableURLRequest.h b/WebKit/win/WebMutableURLRequest.h index 1007a02..77dc1a0 100644 --- a/WebKit/win/WebMutableURLRequest.h +++ b/WebKit/win/WebMutableURLRequest.h @@ -113,6 +113,10 @@ public: virtual HRESULT STDMETHODCALLTYPE mutableCopy( /* [out, retval] */ IWebMutableURLRequest** result); + virtual HRESULT STDMETHODCALLTYPE isEqual( + /* [in] */ IWebURLRequest* other, + /* [out, retval] */ BOOL* result); + // IWebMutableURLRequest virtual HRESULT STDMETHODCALLTYPE addValue( /* [in] */ BSTR value, diff --git a/WebKit/win/WebPreferenceKeysPrivate.h b/WebKit/win/WebPreferenceKeysPrivate.h index 758254e..8426271 100644 --- a/WebKit/win/WebPreferenceKeysPrivate.h +++ b/WebKit/win/WebPreferenceKeysPrivate.h @@ -47,6 +47,8 @@ #define WebKitTextAreasAreResizablePreferenceKey "WebKitTextAreasAreResizable" #define WebKitJavaEnabledPreferenceKey "WebKitJavaEnabled" #define WebKitJavaScriptEnabledPreferenceKey "WebKitJavaScriptEnabled" +#define WebKitWebSecurityEnabledPreferenceKey "WebKitWebSecurityEnabled" +#define WebKitAllowUniversalAccessFromFileURLsPreferenceKey "WebKitAllowUniversalAccessFromFileURLs" #define WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey "WebKitJavaScriptCanOpenWindowsAutomatically" #define WebKitPluginsEnabledPreferenceKey "WebKitPluginsEnabled" #define WebKitDatabasesEnabledPreferenceKey "WebKitDatabasesEnabled" diff --git a/WebKit/win/WebPreferences.cpp b/WebKit/win/WebPreferences.cpp index 5fcd319..ac77376 100644 --- a/WebKit/win/WebPreferences.cpp +++ b/WebKit/win/WebPreferences.cpp @@ -203,6 +203,8 @@ void WebPreferences::initializeDefaultSettings() CFDictionaryAddValue(defaults, CFSTR(WebKitTextAreasAreResizablePreferenceKey), kCFBooleanFalse); CFDictionaryAddValue(defaults, CFSTR(WebKitJavaEnabledPreferenceKey), kCFBooleanTrue); CFDictionaryAddValue(defaults, CFSTR(WebKitJavaScriptEnabledPreferenceKey), kCFBooleanTrue); + CFDictionaryAddValue(defaults, CFSTR(WebKitWebSecurityEnabledPreferenceKey), kCFBooleanTrue); + CFDictionaryAddValue(defaults, CFSTR(WebKitAllowUniversalAccessFromFileURLsPreferenceKey), kCFBooleanTrue); CFDictionaryAddValue(defaults, CFSTR(WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey), kCFBooleanTrue); CFDictionaryAddValue(defaults, CFSTR(WebKitPluginsEnabledPreferenceKey), kCFBooleanTrue); CFDictionaryAddValue(defaults, CFSTR(WebKitDatabasesEnabledPreferenceKey), kCFBooleanTrue); @@ -751,6 +753,34 @@ HRESULT STDMETHODCALLTYPE WebPreferences::setJavaScriptEnabled( return S_OK; } +HRESULT STDMETHODCALLTYPE WebPreferences::isWebSecurityEnabled( + /* [retval][out] */ BOOL* enabled) +{ + *enabled = boolValueForKey(CFSTR(WebKitWebSecurityEnabledPreferenceKey)); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebPreferences::setWebSecurityEnabled( + /* [in] */ BOOL enabled) +{ + setBoolValue(CFSTR(WebKitWebSecurityEnabledPreferenceKey), enabled); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebPreferences::allowUniversalAccessFromFileURLs( + /* [retval][out] */ BOOL* allowAccess) +{ + *allowAccess = boolValueForKey(CFSTR(WebKitAllowUniversalAccessFromFileURLsPreferenceKey)); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebPreferences::setAllowUniversalAccessFromFileURLs( + /* [in] */ BOOL allowAccess) +{ + setBoolValue(CFSTR(WebKitAllowUniversalAccessFromFileURLsPreferenceKey), allowAccess); + return S_OK; +} + HRESULT STDMETHODCALLTYPE WebPreferences::javaScriptCanOpenWindowsAutomatically( /* [retval][out] */ BOOL* enabled) { diff --git a/WebKit/win/WebPreferences.h b/WebKit/win/WebPreferences.h index 6ab3dcb..b6bcf6d 100644 --- a/WebKit/win/WebPreferences.h +++ b/WebKit/win/WebPreferences.h @@ -344,6 +344,18 @@ public: virtual HRESULT STDMETHODCALLTYPE setFontSmoothingContrast( /* [in] */ float contrast); + virtual HRESULT STDMETHODCALLTYPE isWebSecurityEnabled( + /* [retval][out] */ BOOL* enabled); + + virtual HRESULT STDMETHODCALLTYPE setWebSecurityEnabled( + /* [in] */ BOOL enabled); + + virtual HRESULT STDMETHODCALLTYPE allowUniversalAccessFromFileURLs( + /* [retval][out] */ BOOL* allowAccess); + + virtual HRESULT STDMETHODCALLTYPE setAllowUniversalAccessFromFileURLs( + /* [in] */ BOOL allowAccess); + // WebPreferences // This method accesses a different preference key than developerExtrasEnabled. diff --git a/WebKit/win/WebSecurityOrigin.cpp b/WebKit/win/WebSecurityOrigin.cpp index c027b13..baec72e 100644 --- a/WebKit/win/WebSecurityOrigin.cpp +++ b/WebKit/win/WebSecurityOrigin.cpp @@ -33,6 +33,10 @@ #include <WebCore/BString.h> #include <WebCore/DatabaseTracker.h> +#if !ENABLE(DATABASE) +#include <wtf/UnusedParam.h> +#endif + using namespace WebCore; // WebSecurityOrigin --------------------------------------------------------------- @@ -126,28 +130,43 @@ HRESULT STDMETHODCALLTYPE WebSecurityOrigin::port( HRESULT STDMETHODCALLTYPE WebSecurityOrigin::usage( /* [retval][out] */ unsigned long long* result) { +#if ENABLE(DATABASE) if (!result) return E_POINTER; *result = DatabaseTracker::tracker().usageForOrigin(m_securityOrigin.get()); return S_OK; +#else + UNUSED_PARAM(result); + return E_NOTIMPL; +#endif } HRESULT STDMETHODCALLTYPE WebSecurityOrigin::quota( /* [retval][out] */ unsigned long long* result) { +#if ENABLE(DATABASE) if (!result) return E_POINTER; *result = DatabaseTracker::tracker().quotaForOrigin(m_securityOrigin.get()); return S_OK; +#else + UNUSED_PARAM(result); + return E_NOTIMPL; +#endif } HRESULT STDMETHODCALLTYPE WebSecurityOrigin::setQuota( /* [in] */ unsigned long long quota) { +#if ENABLE(DATABASE) DatabaseTracker::tracker().setQuota(m_securityOrigin.get(), quota); return S_OK; +#else + UNUSED_PARAM(quota); + return E_NOTIMPL; +#endif } diff --git a/WebKit/win/WebSecurityOrigin.h b/WebKit/win/WebSecurityOrigin.h index a4d9f01..368a7e8 100644 --- a/WebKit/win/WebSecurityOrigin.h +++ b/WebKit/win/WebSecurityOrigin.h @@ -57,7 +57,7 @@ public: virtual HRESULT STDMETHODCALLTYPE port( /* [retval][out] */ unsigned short* result); - + virtual HRESULT STDMETHODCALLTYPE usage( /* [retval][out] */ unsigned long long* result); @@ -66,6 +66,7 @@ public: virtual HRESULT STDMETHODCALLTYPE setQuota( /* [in] */ unsigned long long quota); + private: WebSecurityOrigin(WebCore::SecurityOrigin*); ~WebSecurityOrigin(); diff --git a/WebKit/win/WebView.cpp b/WebKit/win/WebView.cpp index eb176dc..afacef5 100644 --- a/WebKit/win/WebView.cpp +++ b/WebKit/win/WebView.cpp @@ -50,7 +50,6 @@ #include "WebNotificationCenter.h" #include "WebPreferences.h" #pragma warning( push, 0 ) -#include <CoreGraphics/CGContext.h> #include <WebCore/ApplicationCacheStorage.h> #include <WebCore/AXObjectCache.h> #include <WebCore/BString.h> @@ -105,10 +104,21 @@ #include <JavaScriptCore/InitializeThreading.h> #include <JavaScriptCore/JSLock.h> #include <JavaScriptCore/JSValue.h> + +#if PLATFORM(CG) +#include <CoreGraphics/CGContext.h> +#endif + +#if PLATFORM(CF) +#include <CoreFoundation/CoreFoundation.h> +#endif + +#if USE(CFNETWORK) #include <CFNetwork/CFURLCachePriv.h> #include <CFNetwork/CFURLProtocolPriv.h> -#include <CoreFoundation/CoreFoundation.h> #include <WebKitSystemInterface/WebKitSystemInterface.h> +#endif + #include <wtf/HashSet.h> #include <dimm.h> #include <oleacc.h> @@ -127,20 +137,6 @@ static HashSet<WebView*> pendingDeleteBackingStoreSet; static String osVersion(); static String webKitVersion(); -typedef CFURLCacheRef (*CopySharedURLCacheFunction)(); - -static HMODULE findCFNetworkModule() -{ - if (HMODULE module = GetModuleHandleA("CFNetwork")) - return module; - return GetModuleHandleA("CFNetwork_debug"); -} - -static CopySharedURLCacheFunction findCopySharedURLCacheFunction() -{ - return reinterpret_cast<CopySharedURLCacheFunction>(GetProcAddress(findCFNetworkModule(), "CFURLCacheCopySharedURLCache")); -} - WebView* kit(Page* page) { return page ? static_cast<WebChromeClient*>(page->chrome()->client())->webView() : 0; @@ -328,7 +324,7 @@ WebView::~WebView() // <rdar://4958382> m_viewWindow will be destroyed when m_hostWindow is destroyed, but if // setHostWindow was never called we will leak our HWND. If we still have a valid HWND at // this point, we should just destroy it ourselves. - if (::IsWindow(m_viewWindow)) + if (!isBeingDestroyed() && ::IsWindow(m_viewWindow)) ::DestroyWindow(m_viewWindow); // the tooltip window needs to be explicitly destroyed since it isn't a WS_CHILD @@ -380,18 +376,11 @@ void WebView::removeFromAllWebViewsSet() void WebView::setCacheModel(WebCacheModel cacheModel) { +#if USE(CFNETWORK) if (s_didSetCacheModel && cacheModel == s_cacheModel) return; - // Once we require a newer version of CFNetwork with the CFURLCacheCopySharedURLCache function, - // we can call CFURLCacheCopySharedURLCache directly and eliminate copySharedURLCache. - static CopySharedURLCacheFunction copySharedURLCache = findCopySharedURLCacheFunction(); - RetainPtr<CFURLCacheRef> cfurlCache; - if (copySharedURLCache) - cfurlCache.adoptCF(copySharedURLCache()); - else - cfurlCache = CFURLCacheSharedURLCache(); - + RetainPtr<CFURLCacheRef> cfurlCache(AdoptCF, CFURLCacheCopySharedURLCache()); RetainPtr<CFStringRef> cfurlCacheDirectory(AdoptCF, wkCopyFoundationCacheDirectory()); if (!cfurlCacheDirectory) cfurlCacheDirectory.adoptCF(WebCore::localUserSpecificStorageDirectory().createCFString()); @@ -563,6 +552,7 @@ void WebView::setCacheModel(WebCacheModel cacheModel) s_didSetCacheModel = true; s_cacheModel = cacheModel; return; +#endif } WebCacheModel WebView::cacheModel() @@ -594,13 +584,19 @@ WebCacheModel WebView::maxCacheModelInAnyInstance() return cacheModel; } -void WebView::close() +HRESULT STDMETHODCALLTYPE WebView::close() { if (m_didClose) - return; + return S_OK; m_didClose = true; + if (m_uiDelegatePrivate) { + COMPtr<IWebUIDelegatePrivate5> uiDelegatePrivate5(Query, m_uiDelegatePrivate); + if (uiDelegatePrivate5) + uiDelegatePrivate5->webViewClosing(this); + } + removeFromAllWebViewsSet(); Frame* frame = m_page->mainFrame(); @@ -648,6 +644,7 @@ void WebView::close() } deleteBackingStore(); + return S_OK; } void WebView::repaint(const WebCore::IntRect& windowRect, bool contentChanged, bool immediate, bool repaintContentOnly) @@ -1333,7 +1330,7 @@ bool WebView::handleMouseEvent(UINT message, WPARAM wParam, LPARAM lParam) return handled; } -bool WebView::mouseWheel(WPARAM wParam, LPARAM lParam, bool isHorizontal) +bool WebView::mouseWheel(WPARAM wParam, LPARAM lParam, bool isMouseHWheel) { // Ctrl+Mouse wheel doesn't ever go into WebCore. It is used to // zoom instead (Mac zooms the whole Desktop, but Windows browsers trigger their @@ -1347,7 +1344,7 @@ bool WebView::mouseWheel(WPARAM wParam, LPARAM lParam, bool isHorizontal) return true; } - PlatformWheelEvent wheelEvent(m_viewWindow, wParam, lParam, isHorizontal); + PlatformWheelEvent wheelEvent(m_viewWindow, wParam, lParam, isMouseHWheel); Frame* coreFrame = core(m_mainFrame); if (!coreFrame) return false; @@ -1682,11 +1679,13 @@ static LRESULT CALLBACK WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, L { LRESULT lResult = 0; LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0); - COMPtr<WebView> webView = reinterpret_cast<WebView*>(longPtr); // hold a ref, since the WebView could go away in an event handler. + WebView* webView = reinterpret_cast<WebView*>(longPtr); WebFrame* mainFrameImpl = webView ? webView->topLevelFrame() : 0; if (!mainFrameImpl || webView->isBeingDestroyed()) return DefWindowProc(hWnd, message, wParam, lParam); + // hold a ref, since the WebView could go away in an event handler. + COMPtr<WebView> protector(webView); ASSERT(webView); // Windows Media Player has a modal message loop that will deliver messages @@ -1734,7 +1733,7 @@ static LRESULT CALLBACK WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, L case WM_VISTA_MOUSEHWHEEL: if (Frame* coreFrame = core(mainFrameImpl)) if (coreFrame->view()->didFirstLayout()) - handled = webView->mouseWheel(wParam, lParam, (wParam & MK_SHIFT) || message == WM_VISTA_MOUSEHWHEEL); + handled = webView->mouseWheel(wParam, lParam, message == WM_VISTA_MOUSEHWHEEL); break; case WM_SYSKEYDOWN: handled = webView->keyDown(wParam, lParam, true); @@ -1778,7 +1777,7 @@ static LRESULT CALLBACK WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, L COMPtr<IWebUIDelegatePrivate> uiDelegatePrivate; if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate) - uiDelegatePrivate->webViewReceivedFocus(webView.get()); + uiDelegatePrivate->webViewReceivedFocus(webView); FocusController* focusController = webView->page()->focusController(); if (Frame* frame = focusController->focusedFrame()) { @@ -1796,7 +1795,7 @@ static LRESULT CALLBACK WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, L HWND newFocusWnd = reinterpret_cast<HWND>(wParam); if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate) - uiDelegatePrivate->webViewLostFocus(webView.get(), (OLE_HANDLE)(ULONG64)newFocusWnd); + uiDelegatePrivate->webViewLostFocus(webView, (OLE_HANDLE)(ULONG64)newFocusWnd); FocusController* focusController = webView->page()->focusController(); Frame* frame = focusController->focusedOrMainFrame(); @@ -1872,7 +1871,7 @@ static LRESULT CALLBACK WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, L } if (SUCCEEDED(webView->uiDelegate(&uiDelegate)) && uiDelegate && SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**) &uiDelegatePrivate)) && uiDelegatePrivate && - SUCCEEDED(uiDelegatePrivate->webViewGetDlgCode(webView.get(), keyCode, &dlgCode))) + SUCCEEDED(uiDelegatePrivate->webViewGetDlgCode(webView, keyCode, &dlgCode))) return dlgCode; handled = false; break; @@ -2169,7 +2168,9 @@ HRESULT STDMETHODCALLTYPE WebView::initWithFrame( m_preferences = sharedPreferences; InitializeLoggingChannelsIfNecessary(); +#if ENABLE(DATABASE) WebKitSetWebDatabasesPathIfNecessary(); +#endif WebKitSetApplicationCachePathIfNecessary(); m_page = new Page(new WebChromeClient(this), new WebContextMenuClient(this), new WebEditorClient(this), new WebDragClient(this), new WebInspectorClient(this)); @@ -3129,7 +3130,7 @@ HRESULT STDMETHODCALLTYPE WebView::centerSelectionInVisibleArea( if (!coreFrame) return E_FAIL; - coreFrame->revealSelection(RenderLayer::gAlignCenterAlways); + coreFrame->revealSelection(ScrollAlignment::alignCenterAlways); return S_OK; } @@ -4204,6 +4205,16 @@ HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification) return hr; settings->setLocalStorageEnabled(enabled); + hr = prefsPrivate->isWebSecurityEnabled(&enabled); + if (FAILED(hr)) + return hr; + settings->setWebSecurityEnabled(!!enabled); + + hr = prefsPrivate->allowUniversalAccessFromFileURLs(&enabled); + if (FAILED(hr)) + return hr; + settings->setAllowUniversalAccessFromFileURLs(!!enabled); + #if USE(SAFARI_THEME) hr = prefsPrivate->shouldPaintNativeControls(&enabled); if (FAILED(hr)) @@ -4231,9 +4242,11 @@ HRESULT updateSharedSettingsFromPreferencesIfNeeded(IWebPreferences* preferences if (FAILED(hr)) return hr; +#if USE(CFNETWORK) // Set cookie storage accept policy if (CFHTTPCookieStorageRef cookieStorage = currentCookieStorage()) CFHTTPCookieStorageSetCookieAcceptPolicy(cookieStorage, acceptPolicy); +#endif return S_OK; } @@ -4680,7 +4693,7 @@ void WebView::releaseIMMContext(HIMC hIMC) void WebView::prepareCandidateWindow(Frame* targetFrame, HIMC hInputContext) { IntRect caret; - if (RefPtr<Range> range = targetFrame->selection()->selection().toRange()) { + if (RefPtr<Range> range = targetFrame->selection()->selection().toNormalizedRange()) { ExceptionCode ec = 0; RefPtr<Range> tempRange = range->cloneRange(ec); caret = targetFrame->firstRectForRange(tempRange.get()); @@ -4843,7 +4856,7 @@ bool WebView::onIMERequestCharPosition(Frame* targetFrame, IMECHARPOSITION* char { IntRect caret; ASSERT(charPos->dwCharPos == 0 || targetFrame->editor()->hasComposition()); - if (RefPtr<Range> range = targetFrame->editor()->hasComposition() ? targetFrame->editor()->compositionRange() : targetFrame->selection()->selection().toRange()) { + if (RefPtr<Range> range = targetFrame->editor()->hasComposition() ? targetFrame->editor()->compositionRange() : targetFrame->selection()->selection().toNormalizedRange()) { ExceptionCode ec = 0; RefPtr<Range> tempRange = range->cloneRange(ec); tempRange->setStart(tempRange->startContainer(ec), tempRange->startOffset(ec) + charPos->dwCharPos, ec); @@ -4861,7 +4874,7 @@ bool WebView::onIMERequestCharPosition(Frame* targetFrame, IMECHARPOSITION* char bool WebView::onIMERequestReconvertString(Frame* targetFrame, RECONVERTSTRING* reconvertString, LRESULT* result) { - RefPtr<Range> selectedRange = targetFrame->selection()->toRange(); + RefPtr<Range> selectedRange = targetFrame->selection()->toNormalizedRange(); String text = selectedRange->text(); if (!reconvertString) { *result = sizeof(RECONVERTSTRING) + text.length() * sizeof(UChar); @@ -5160,6 +5173,12 @@ HRESULT WebView::setMemoryCacheDelegateCallsEnabled(BOOL enabled) return S_OK; } +HRESULT WebView::setJavaScriptURLsAreAllowed(BOOL areAllowed) +{ + m_page->setJavaScriptURLsAreAllowed(areAllowed); + return S_OK; +} + class EnumTextMatches : public IEnumTextMatches { long m_ref; diff --git a/WebKit/win/WebView.h b/WebKit/win/WebView.h index 281defd..23905b7 100644 --- a/WebKit/win/WebView.h +++ b/WebKit/win/WebView.h @@ -296,6 +296,8 @@ public: virtual HRESULT STDMETHODCALLTYPE registerURLSchemeAsLocal( /* [in] */ BSTR scheme); + virtual HRESULT STDMETHODCALLTYPE close(); + // IWebIBActions virtual HRESULT STDMETHODCALLTYPE takeStringURLFrom( @@ -724,6 +726,9 @@ public: virtual HRESULT STDMETHODCALLTYPE setMemoryCacheDelegateCallsEnabled( /* [in] */ BOOL enabled); + virtual HRESULT STDMETHODCALLTYPE setJavaScriptURLsAreAllowed( + /* [in] */ BOOL areAllowed); + // WebView bool shouldUseEmbeddedView(const WebCore::String& mimeType) const; @@ -736,7 +741,7 @@ public: bool onInitMenuPopup(WPARAM, LPARAM); bool onUninitMenuPopup(WPARAM, LPARAM); void performContextMenuAction(WPARAM, LPARAM, bool byPosition); - bool mouseWheel(WPARAM, LPARAM, bool isHorizontal); + bool mouseWheel(WPARAM, LPARAM, bool isMouseHWheel); bool execCommand(WPARAM wParam, LPARAM lParam); bool keyDown(WPARAM, LPARAM, bool systemKeyDown = false); bool keyUp(WPARAM, LPARAM, bool systemKeyDown = false); @@ -753,7 +758,6 @@ public: void frameRect(RECT* rect); void closeWindow(); void closeWindowSoon(); - void close(); bool didClose() const { return m_didClose; } bool transparent() const { return m_transparent; } diff --git a/WebKit/wx/ChangeLog b/WebKit/wx/ChangeLog index a7212f0..c82850a 100644 --- a/WebKit/wx/ChangeLog +++ b/WebKit/wx/ChangeLog @@ -1,3 +1,93 @@ +2009-03-02 Kevin Ollivier <kevino@theolliviers.com> + + Build fixes for wxWidgets Mac trunk build. + + * WebView.h: + * bindings/python/webview.i: + * bindings/python/wxwebkit-py.bkl: + * dependencies.bkl: + * presets/wxwebkit.bkl: + +2009-02-11 Dimitri Dupuis-latour <dupuislatour@apple.com> + + Stub out InspectorClientWx::hiddenPanels. + + Reviewed by Timothy Hatcher. + + * WebKitSupport/InspectorClientWx.cpp: + (WebCore::InspectorClientWx::hiddenPanels): + * WebKitSupport/InspectorClientWx.h: + +2009-02-06 Geoffrey Garen <ggaren@apple.com> + + Build fix. + + * WebKitSupport/FrameLoaderClientWx.cpp: + (WebCore::FrameLoaderClientWx::updateGlobalHistoryRedirectLinks): + * WebKitSupport/FrameLoaderClientWx.h: + +2009-02-05 Aaron Boodman <aa@chromium.org> + + Reviewed by Dave Hyatt. + + https://bugs.webkit.org/show_bug.cgi?id=23708 + Adds documentElementAvailable() callback to FrameLoaderClient. + + * WebKitSupport/FrameLoaderClientWx.cpp: + (WebCore::FrameLoaderClientWx::documentElementAvailable): + Stub out documentElementAvailable(). + * WebKitSupport/FrameLoaderClientWx.h: + Ditto. + +2009-02-02 Geoffrey Garen <ggaren@apple.com> + + Build fix. + + * WebKitSupport/FrameLoaderClientWx.cpp: + (WebCore::FrameLoaderClientWx::updateGlobalHistoryForRedirectWithoutHistoryItem): + (WebCore::FrameLoaderClientWx::createPlugin): + (WebCore::FrameLoaderClientWx::createJavaAppletWidget): + * WebKitSupport/FrameLoaderClientWx.h: + +2009-02-02 Geoffrey Garen <ggaren@apple.com> + + Build fix. + + * WebFrame.cpp: + (wxWebFrame::LoadURL): + +2009-01-31 Darin Adler <darin@apple.com> + + Build fix. + + * WebView.cpp: + (wxWebView::OnSize): call sendResizeEvent on EventHandler. + +2009-01-29 David Kilzer <ddkilzer@apple.com> + + Build fix for Wx: Finish de-RefCount-ing FrameLoaderClientWx + + * WebKitSupport/FrameLoaderClientWx.cpp: + (WebCore::FrameLoaderClientWx::ref): Removed. + (WebCore::FrameLoaderClientWx::deref): Removed. + * WebKitSupport/FrameLoaderClientWx.h: Ditto. + +2009-01-28 David Kilzer <ddkilzer@apple.com> + + Bug 23490: Remove initialRefCount argument from RefCounted class + + <https://bugs.webkit.org/show_bug.cgi?id=23490> + + Reviewed by Darin Adler. + + FrameLoaderClientWx is no longer a RefCounted class. + + * WebKitSupport/FrameLoaderClientWx.cpp: + (WebCore::FrameLoaderClientWx::FrameLoaderClientWx): Removed call + to the RefCounted<FrameLoaderClientWx>(0) super constructor. + * WebKitSupport/FrameLoaderClientWx.h: Don't include RefCounted.h + and stop inheriting from RefCounted<FrameLoaderClientWx>. + 2009-01-27 Brady Eidson <beidson@apple.com> Reviewed by Dan Bernstein diff --git a/WebKit/wx/WebFrame.cpp b/WebKit/wx/WebFrame.cpp index 7bfcc5d..b479a41 100644 --- a/WebKit/wx/WebFrame.cpp +++ b/WebKit/wx/WebFrame.cpp @@ -39,16 +39,17 @@ #include "RenderTreeAsText.h" #include "RenderObject.h" #include "RenderView.h" - -#include "EditorClientWx.h" -#include "FrameLoaderClientWx.h" - #include "ScriptController.h" #include "ScriptValue.h" +#include "TextEncoding.h" + #include "JSDOMBinding.h" #include <runtime/JSValue.h> #include <runtime/UString.h> +#include "EditorClientWx.h" +#include "FrameLoaderClientWx.h" + #include "wx/wxprec.h" #ifndef WX_PRECOMP #include "wx/wx.h" @@ -141,7 +142,7 @@ void wxWebFrame::SetPageSource(const wxString& source, const wxString& baseUrl) { if (m_impl->frame && m_impl->frame->loader()) { WebCore::FrameLoader* loader = m_impl->frame->loader(); - loader->begin(WebCore::KURL(static_cast<const char*>(baseUrl.mb_str(wxConvUTF8)))); + loader->begin(WebCore::KURL(WebCore::KURL(), static_cast<const char*>(baseUrl.mb_str(wxConvUTF8)), WebCore::UTF8Encoding())); loader->write(static_cast<const WebCore::String>(source)); loader->end(); } @@ -194,7 +195,7 @@ bool wxWebFrame::FindString(const wxString& string, bool forward, bool caseSensi void wxWebFrame::LoadURL(const wxString& url) { if (m_impl->frame && m_impl->frame->loader()) { - WebCore::KURL kurl = WebCore::KURL(static_cast<const char*>(url.mb_str(wxConvUTF8))); + WebCore::KURL kurl = WebCore::KURL(WebCore::KURL(), static_cast<const char*>(url.mb_str(wxConvUTF8)), WebCore::UTF8Encoding()); // NB: This is an ugly fix, but CURL won't load sub-resources if the // protocol is omitted; sadly, it will not emit an error, either, so // there's no way for us to catch this problem the correct way yet. @@ -209,7 +210,7 @@ void wxWebFrame::LoadURL(const wxString& url) kurl.setPath("//" + kurl.path()); } } - m_impl->frame->loader()->load(kurl); + m_impl->frame->loader()->load(kurl, false); } } diff --git a/WebKit/wx/WebKitSupport/ChromeClientWx.cpp b/WebKit/wx/WebKitSupport/ChromeClientWx.cpp index 29fef0e..411f795 100644 --- a/WebKit/wx/WebKitSupport/ChromeClientWx.cpp +++ b/WebKit/wx/WebKitSupport/ChromeClientWx.cpp @@ -348,10 +348,19 @@ void ChromeClientWx::print(Frame*) notImplemented(); } +#if ENABLE(DATABASE) void ChromeClientWx::exceededDatabaseQuota(Frame*, const String&) { notImplemented(); } +#endif + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +void ChromeClientWx::reachedMaxAppCacheSize(int64_t spaceNeeded) +{ + notImplemented(); +} +#endif void ChromeClientWx::scroll(const IntSize&, const IntRect&, const IntRect&) { diff --git a/WebKit/wx/WebKitSupport/ChromeClientWx.h b/WebKit/wx/WebKitSupport/ChromeClientWx.h index 74e0023..d7f4152 100644 --- a/WebKit/wx/WebKitSupport/ChromeClientWx.h +++ b/WebKit/wx/WebKitSupport/ChromeClientWx.h @@ -110,7 +110,13 @@ public: virtual void print(Frame*); +#if ENABLE(DATABASE) virtual void exceededDatabaseQuota(Frame*, const String&); +#endif + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); +#endif virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>); diff --git a/WebKit/wx/WebKitSupport/FrameLoaderClientWx.cpp b/WebKit/wx/WebKitSupport/FrameLoaderClientWx.cpp index a34576d..3cfd86e 100644 --- a/WebKit/wx/WebKitSupport/FrameLoaderClientWx.cpp +++ b/WebKit/wx/WebKitSupport/FrameLoaderClientWx.cpp @@ -70,8 +70,7 @@ inline int wxNavTypeFromWebNavType(NavigationType type){ } FrameLoaderClientWx::FrameLoaderClientWx() - : RefCounted<FrameLoaderClientWx>(0) - , m_frame(0) + : m_frame(0) { } @@ -95,16 +94,6 @@ void FrameLoaderClientWx::detachFrameLoader() m_frame = 0; } -void FrameLoaderClientWx::ref() -{ - RefCounted<FrameLoaderClientWx>::ref(); -} - -void FrameLoaderClientWx::deref() -{ - RefCounted<FrameLoaderClientWx>::deref(); -} - bool FrameLoaderClientWx::hasWebView() const { notImplemented(); @@ -531,6 +520,11 @@ void FrameLoaderClientWx::updateGlobalHistory() notImplemented(); } +void FrameLoaderClientWx::updateGlobalHistoryRedirectLinks() +{ + notImplemented(); +} + bool FrameLoaderClientWx::shouldGoToHistoryItem(WebCore::HistoryItem*) const { notImplemented(); @@ -791,7 +785,7 @@ ObjectContentType FrameLoaderClientWx::objectContentType(const KURL& url, const return ObjectContentType(); } -Widget* FrameLoaderClientWx::createPlugin(const IntSize&, Element*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool loadManually) +Widget* FrameLoaderClientWx::createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool loadManually) { notImplemented(); return 0; @@ -809,7 +803,7 @@ ResourceError FrameLoaderClientWx::pluginWillHandleLoadError(const ResourceRespo return ResourceError(); } -Widget* FrameLoaderClientWx::createJavaAppletWidget(const IntSize&, Element*, const KURL& baseURL, +Widget* FrameLoaderClientWx::createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues) { notImplemented(); @@ -827,6 +821,10 @@ void FrameLoaderClientWx::windowObjectCleared() notImplemented(); } +void FrameLoaderClientWx::documentElementAvailable() +{ +} + void FrameLoaderClientWx::didPerformFirstNavigation() const { notImplemented(); diff --git a/WebKit/wx/WebKitSupport/FrameLoaderClientWx.h b/WebKit/wx/WebKitSupport/FrameLoaderClientWx.h index 9ad4ddc..43b3a8f 100644 --- a/WebKit/wx/WebKitSupport/FrameLoaderClientWx.h +++ b/WebKit/wx/WebKitSupport/FrameLoaderClientWx.h @@ -31,7 +31,6 @@ #include "FrameLoaderClient.h" #include "FrameLoader.h" #include "KURL.h" -#include "RefCounted.h" #include "ResourceResponse.h" class wxWebView; @@ -48,7 +47,7 @@ namespace WebCore { struct LoadErrorResetToken; - class FrameLoaderClientWx : public FrameLoaderClient, public RefCounted<FrameLoaderClientWx> { + class FrameLoaderClientWx : public FrameLoaderClient { public: FrameLoaderClientWx(); ~FrameLoaderClientWx(); @@ -56,9 +55,6 @@ namespace WebCore { void setWebView(wxWebView *webview); virtual void detachFrameLoader(); - virtual void ref(); - virtual void deref(); - virtual bool hasWebView() const; // mainly for assertions virtual bool hasBackForwardList() const; @@ -149,6 +145,7 @@ namespace WebCore { virtual void transitionToCommittedForNewPage(); virtual void updateGlobalHistory(); + virtual void updateGlobalHistoryRedirectLinks(); virtual bool shouldGoToHistoryItem(HistoryItem*) const; virtual void saveScrollPositionAndViewStateToItem(HistoryItem*); virtual bool canCachePage() const; @@ -192,16 +189,17 @@ namespace WebCore { virtual PassRefPtr<Frame> createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight); - virtual Widget* createPlugin(const IntSize&, Element*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool loadManually) ; + virtual Widget* createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool loadManually) ; virtual void redirectDataToPlugin(Widget* pluginWidget); virtual ResourceError pluginWillHandleLoadError(const ResourceResponse&); - virtual Widget* createJavaAppletWidget(const IntSize&, Element*, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues); + virtual Widget* createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues); virtual ObjectContentType objectContentType(const KURL& url, const String& mimeType); virtual String overrideMediaType() const; virtual void windowObjectCleared(); + virtual void documentElementAvailable(); virtual void didPerformFirstNavigation() const; diff --git a/WebKit/wx/WebKitSupport/InspectorClientWx.cpp b/WebKit/wx/WebKitSupport/InspectorClientWx.cpp index 9e87da6..75e4595 100644 --- a/WebKit/wx/WebKitSupport/InspectorClientWx.cpp +++ b/WebKit/wx/WebKitSupport/InspectorClientWx.cpp @@ -59,6 +59,12 @@ String InspectorClientWx::localizedStringsURL() return String(); } +String InspectorClientWx::hiddenPanels() +{ + notImplemented(); + return String(); +} + void InspectorClientWx::showWindow() { notImplemented(); diff --git a/WebKit/wx/WebKitSupport/InspectorClientWx.h b/WebKit/wx/WebKitSupport/InspectorClientWx.h index 6dd05df..ad3ad5b 100644 --- a/WebKit/wx/WebKitSupport/InspectorClientWx.h +++ b/WebKit/wx/WebKitSupport/InspectorClientWx.h @@ -45,6 +45,8 @@ public: virtual String localizedStringsURL(); + virtual String hiddenPanels(); + virtual void showWindow(); virtual void closeWindow(); diff --git a/WebKit/wx/WebView.cpp b/WebKit/wx/WebView.cpp index 6ed8aef..94c760b 100644 --- a/WebKit/wx/WebView.cpp +++ b/WebKit/wx/WebView.cpp @@ -481,7 +481,7 @@ void wxWebView::OnSize(wxSizeEvent& event) { if (m_isInitialized && m_mainFrame) { WebCore::Frame* frame = m_mainFrame->GetFrame(); - frame->sendResizeEvent(); + frame->eventHandler()->sendResizeEvent(); frame->view()->layout(); frame->view()->adjustScrollbars(); } diff --git a/WebKit/wx/WebView.h b/WebKit/wx/WebView.h index 387d193..b041b08 100644 --- a/WebKit/wx/WebView.h +++ b/WebKit/wx/WebView.h @@ -58,7 +58,9 @@ namespace WebCore { #define WXDLLIMPEXP_WEBKIT #endif // SWIG +#ifndef SWIG extern WXDLLIMPEXP_WEBKIT const wxChar* wxWebViewNameStr; +#endif class WXDLLIMPEXP_WEBKIT wxWebView : public wxWindow { diff --git a/WebKit/wx/bindings/python/webview.i b/WebKit/wx/bindings/python/webview.i index e9926ad..44b38ab 100644 --- a/WebKit/wx/bindings/python/webview.i +++ b/WebKit/wx/bindings/python/webview.i @@ -31,12 +31,13 @@ #include "WebView.h" #include "WebBrowserShell.h" %} - //--------------------------------------------------------------------------- %import core.i %import windows.i +MAKE_CONST_WXSTRING(WebViewNameStr); + MustHaveApp(wxWebView); MustHaveApp(wxWebBrowserShell); diff --git a/WebKit/wx/bindings/python/wxwebkit-py.bkl b/WebKit/wx/bindings/python/wxwebkit-py.bkl index d6c2f7a..8c49a67 100644 --- a/WebKit/wx/bindings/python/wxwebkit-py.bkl +++ b/WebKit/wx/bindings/python/wxwebkit-py.bkl @@ -81,9 +81,10 @@ Bakefile for wxWebKit Python bindings. <if cond="FORMAT=='gnu'"> <sys-lib>png</sys-lib> <set var="MAC_FLAGS"> - <if cond="WX_PORT=='mac'">-bundle -undefined dynamic_lookup</if> + <if cond="PLATFORM_OS=='mac'">-bundle -undefined dynamic_lookup</if> </set> + <sys-lib>python2.5</sys-lib> <ldflags>$(MAC_FLAGS)</ldflags> </if> <if cond="FORMAT in ['msvc','msvs2005prj']"> diff --git a/WebKit/wx/dependencies.bkl b/WebKit/wx/dependencies.bkl index e9eedb4..cbdb7e3 100644 --- a/WebKit/wx/dependencies.bkl +++ b/WebKit/wx/dependencies.bkl @@ -139,11 +139,11 @@ and WebCore. Include this file to use these settings. <if cond="FORMAT=='gnu'"> <!-- Mac includes ICU with the system, but doesn't include headers or icu-config, so we have to hardcode settings there. --> - <set var="ICU_INCLUDE"><if cond="WX_PORT=='mac'">$(WK_ROOT)/JavaScriptCore/icu</if></set> - <set var="ICU_INCLUDE"><if cond="WX_PORT=='mac'">$(WK_ROOT)/WebCore/icu</if></set> - <set var="ICU_LIB"><if cond="WX_PORT=='mac'">icucore</if></set> - <set var="ICU_LDFLAGS"><if cond="WX_PORT=='gtk2'">$(DOLLAR)(shell icu-config --ldflags)</if></set> - <set var="ICU_CFLAGS"><if cond="WX_PORT=='gtk2'">$(DOLLAR)(shell icu-config --cppflags)</if></set> + <set var="ICU_INCLUDE"><if cond="PLATFORM_OS=='mac'">$(WK_ROOT)/JavaScriptCore/icu</if></set> + <set var="ICU_INCLUDE"><if cond="PLATFORM_OS=='mac'">$(WK_ROOT)/WebCore/icu</if></set> + <set var="ICU_LIB"><if cond="PLATFORM_OS=='mac'">icucore</if></set> + <set var="ICU_LDFLAGS"><if cond="PLATFORM_OS=='linux'">$(DOLLAR)(shell icu-config --ldflags)</if></set> + <set var="ICU_CFLAGS"><if cond="PLATFORM_OS=='linux'">$(DOLLAR)(shell icu-config --cppflags)</if></set> <include>$(ICU_INCLUDE)</include> <sys-lib>$(ICU_LIB)</sys-lib> diff --git a/WebKit/wx/presets/wxwebkit.bkl b/WebKit/wx/presets/wxwebkit.bkl index df21c67..026ac55 100644 --- a/WebKit/wx/presets/wxwebkit.bkl +++ b/WebKit/wx/presets/wxwebkit.bkl @@ -71,6 +71,17 @@ and WebCore. Include this file to use these settings. </option> </if> + <if cond="not isdefined('PLATFORM_OS')"> + <option name="PLATFORM_OS"> + <values>linux,mac,win</values> + <default-value force="1">win</default-value> + <description> + Platform the wx library is being built on + </description> + </option> + </if> + + <if cond="not isdefined('DEBUG')"> <option name="DEBUG"> <values>0,1</values> |
