diff options
Diffstat (limited to 'WebKit')
125 files changed, 11097 insertions, 609 deletions
diff --git a/WebKit/ChangeLog b/WebKit/ChangeLog index 1b7118f..134a252 100644 --- a/WebKit/ChangeLog +++ b/WebKit/ChangeLog @@ -1,3 +1,22 @@ +2010-02-04 Mark Rowe <mrowe@apple.com> + + Reviewed by Timothy Hatcher. + + Build fix. Remove a symbol corresponding to an inline function from the linker export + file to prevent a weak external failure. + + * WebKit.xcodeproj/project.pbxproj: Accommodate rename of script. + +2010-02-04 John Sullivan <sullivan@apple.com> + + https://bugs.webkit.org/show_bug.cgi?id=34611 + WebLocalizedString() could use an assertion that it is being called on the main thread + + Reviewed by Tim Hatcher. + + * WebKit.xcodeproj/project.pbxproj: + Updated for renamed file (WebLocalizableStrings.m -> WebLocalizableStrings.mm) + 2010-01-29 Mark Rowe <mrowe@apple.com> Sort Xcode projects. diff --git a/WebKit/WebKit.xcodeproj/project.pbxproj b/WebKit/WebKit.xcodeproj/project.pbxproj index f6f4a9e..dda5966 100644 --- a/WebKit/WebKit.xcodeproj/project.pbxproj +++ b/WebKit/WebKit.xcodeproj/project.pbxproj @@ -295,7 +295,6 @@ 939811070824BF01008DF038 /* WebView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51A8B57A042834F700CA2D3A /* WebView.mm */; }; 939811080824BF01008DF038 /* WebPolicyDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51443F9B0429392B00CA2D3A /* WebPolicyDelegate.mm */; }; 9398110A0824BF01008DF038 /* WebDefaultUIDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 515E27D00458CA4B00CA2D3A /* WebDefaultUIDelegate.m */; }; - 9398110D0824BF01008DF038 /* WebLocalizableStrings.m in Sources */ = {isa = PBXBuildFile; fileRef = BEE18F9A0472B73200CA289C /* WebLocalizableStrings.m */; }; 9398110E0824BF01008DF038 /* WebKitSystemBits.m in Sources */ = {isa = PBXBuildFile; fileRef = BEE52D4B0473032500CA289C /* WebKitSystemBits.m */; }; 939811120824BF01008DF038 /* WebNSURLExtras.mm in Sources */ = {isa = PBXBuildFile; fileRef = BE6DC39A04C62C4E004D0EF6 /* WebNSURLExtras.mm */; }; 939811130824BF01008DF038 /* WebHistory.mm in Sources */ = {isa = PBXBuildFile; fileRef = 65DA2608052CC18700A97B31 /* WebHistory.mm */; }; @@ -349,6 +348,7 @@ DD89682009AA87240097E7F0 /* WebElementDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = DD89681E09AA87240097E7F0 /* WebElementDictionary.h */; }; DD89682109AA87240097E7F0 /* WebElementDictionary.mm in Sources */ = {isa = PBXBuildFile; fileRef = DD89681F09AA87240097E7F0 /* WebElementDictionary.mm */; }; E15663190FB61C1F00C199CA /* WebDownload.mm in Sources */ = {isa = PBXBuildFile; fileRef = E15663180FB61C1F00C199CA /* WebDownload.mm */; }; + ED5B9524111B725A00472298 /* WebLocalizableStrings.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED5B9523111B725A00472298 /* WebLocalizableStrings.mm */; }; ED6BE2E7088C32B50044DEDC /* WebNSAttributedStringExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = ED6BE2E5088C32B50044DEDC /* WebNSAttributedStringExtras.h */; }; ED6BE2E8088C32B50044DEDC /* WebNSAttributedStringExtras.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED6BE2E6088C32B50044DEDC /* WebNSAttributedStringExtras.mm */; }; ED7F6D8B0980683500C235ED /* WebNSDataExtrasPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = ED7F6D8A0980683500C235ED /* WebNSDataExtrasPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -633,7 +633,6 @@ BECD14290565830A005BB09C /* WebNSDataExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebNSDataExtras.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; BECD142A0565830A005BB09C /* WebNSDataExtras.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebNSDataExtras.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; BEE18F990472B73200CA289C /* WebLocalizableStrings.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebLocalizableStrings.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; - BEE18F9A0472B73200CA289C /* WebLocalizableStrings.m */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebLocalizableStrings.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; BEE52D4A0473032500CA289C /* WebKitSystemBits.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebKitSystemBits.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; BEE52D4B0473032500CA289C /* WebKitSystemBits.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebKitSystemBits.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; C0167BF60D7F5DD00028696E /* WebScriptDebugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebScriptDebugger.h; sourceTree = "<group>"; }; @@ -650,6 +649,7 @@ ED2B2474033A2DA800C1A526 /* WebNSPasteboardExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebNSPasteboardExtras.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; ED2B2475033A2DA800C1A526 /* WebNSPasteboardExtras.mm */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebNSPasteboardExtras.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; ED3B48DE0CC51F7E00DFF1EB /* StringsNotToBeLocalized.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = StringsNotToBeLocalized.txt; sourceTree = SOURCE_ROOT; }; + ED5B9523111B725A00472298 /* WebLocalizableStrings.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebLocalizableStrings.mm; sourceTree = "<group>"; }; ED6BE2E5088C32B50044DEDC /* WebNSAttributedStringExtras.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebNSAttributedStringExtras.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; ED6BE2E6088C32B50044DEDC /* WebNSAttributedStringExtras.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebNSAttributedStringExtras.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; ED7F6D8A0980683500C235ED /* WebNSDataExtrasPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebNSDataExtrasPrivate.h; sourceTree = "<group>"; }; @@ -917,7 +917,7 @@ 1C0D40850AC1C8F40009C113 /* WebKitVersionChecks.h */, 1C0D40860AC1C8F40009C113 /* WebKitVersionChecks.m */, BEE18F990472B73200CA289C /* WebLocalizableStrings.h */, - BEE18F9A0472B73200CA289C /* WebLocalizableStrings.m */, + ED5B9523111B725A00472298 /* WebLocalizableStrings.mm */, EDE9837E0BCDF5FE00FDAE28 /* WebNSArrayExtras.h */, EDE9837F0BCDF5FE00FDAE28 /* WebNSArrayExtras.m */, ED6BE2E5088C32B50044DEDC /* WebNSAttributedStringExtras.h */, @@ -1566,7 +1566,7 @@ 939811270824BF01008DF038 /* Frameworks */, 939D054F09DA02D500984996 /* Check For Global Initializers */, 9337D6540EBFE54D00DA3CB5 /* Check For Exit Time Destructors */, - 5D0D54210E98631D0029E223 /* Check For Weak VTables */, + 5D0D54210E98631D0029E223 /* Check For Weak VTables and Externals */, 5DE6D18C0FCF231B002DE28C /* Symlink WebKitPluginHost in to place */, ); buildRules = ( @@ -1654,7 +1654,7 @@ shellPath = /bin/sh; shellScript = "mkdir -p \"${TARGET_BUILD_DIR}/${PRIVATE_HEADERS_FOLDER_PATH}\"\nmkdir -p \"${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}\"\nmkdir -p \"${BUILT_PRODUCTS_DIR}/DerivedSources/WebKit\"\n\nif [ \"${ACTION}\" = \"build\" -o \"${ACTION}\" = \"install\" -o \"${ACTION}\" = \"installhdrs\" ]; then\n make -C mac -f \"MigrateHeaders.make\" -j `/usr/sbin/sysctl -n hw.availcpu`\nfi\n"; }; - 5D0D54210E98631D0029E223 /* Check For Weak VTables */ = { + 5D0D54210E98631D0029E223 /* Check For Weak VTables and Externals */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1662,12 +1662,12 @@ inputPaths = ( "$(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)", ); - name = "Check For Weak VTables"; + name = "Check For Weak VTables and Externals"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - 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"; + shellScript = "if [ \"${ACTION}\" = \"installhdrs\" ]; then\n exit 0;\nfi\n\nif [ -f ../WebKitTools/Scripts/check-for-weak-vtables-and-externals ]; then\n ../WebKitTools/Scripts/check-for-weak-vtables-and-externals || exit $?\nfi"; }; 5D2F7DB70C687A5A00B5B72B /* Update Info.plist with version information */ = { isa = PBXShellScriptBuildPhase; @@ -1824,7 +1824,6 @@ 939810C50824BF01008DF038 /* WebKitStatistics.m in Sources */, 9398110E0824BF01008DF038 /* WebKitSystemBits.m in Sources */, 1C0D40880AC1C8F40009C113 /* WebKitVersionChecks.m in Sources */, - 9398110D0824BF01008DF038 /* WebLocalizableStrings.m in Sources */, 5185F62810712B97007AA393 /* WebNavigationData.mm in Sources */, 0AB752380FA2E4DB00D7CBB1 /* WebNetscapeContainerCheckContextInfo.mm in Sources */, 0AEBFF640F9FA8BE000D486B /* WebNetscapeContainerCheckPrivate.mm in Sources */, @@ -1889,6 +1888,7 @@ 939810E80824BF01008DF038 /* WebViewFactory.mm in Sources */, 0FD3B0F91076C3F700039B96 /* WebWindowAnimation.m in Sources */, 41F4485010338E8C0030E55E /* WebWorkersPrivate.mm in Sources */, + ED5B9524111B725A00472298 /* WebLocalizableStrings.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/WebKit/chromium/ChangeLog b/WebKit/chromium/ChangeLog index 58c37a8..9cd3644 100644 --- a/WebKit/chromium/ChangeLog +++ b/WebKit/chromium/ChangeLog @@ -1,3 +1,1274 @@ +2010-02-12 Jeremy Orlow <jorlow@chromium.org> + + Reviewed by Darin Fisher. + + [Chromium] Add a blockedByPolicy output to WebStorageArea::setItem. + https://bugs.webkit.org/show_bug.cgi?id=34897 + + * public/WebStorageArea.h: + (WebKit::WebStorageArea::setItem): + * src/WebStorageAreaImpl.cpp: + (WebKit::WebStorageAreaImpl::setItem): + * src/WebStorageAreaImpl.h: + +2010-02-11 Jeremy Orlow <jorlow@chromium.org> + + Reviewed by David Levin. + + [Chromium] Add ENABLE_RUBY to the feature defines gypi + https://bugs.webkit.org/show_bug.cgi?id=34841 + + * features.gypi: + +2010-02-12 Yury Semikhatsky <yurys@chromium.org> + + Reviewed by Pavel Feldman. + + Chromium: Web Inspector on an element in a page where JS is blocked crashes the renderer + + https://bugs.webkit.org/show_bug.cgi?id=34890 + + * src/DebuggerAgentImpl.cpp: + (WebKit::DebuggerAgentImpl::createUtilityContext): + +2010-02-11 Mikhail Naganov <mnaganov@chromium.org> + + Reviewed by Pavel Feldman. + + [Chromium] Ignore subsequent requests of the same profiler log + chunks. This eliminates emission of several instances for the same + heap snapshot. + + https://bugs.webkit.org/show_bug.cgi?id=34833 + + * src/js/ProfilerAgent.js: + (devtools.ProfilerAgent): + (devtools.ProfilerAgent.prototype.initializeProfiling): + (devtools.ProfilerAgent.prototype._getNextLogLines): + (devtools.ProfilerAgent.prototype.startProfiling): + (devtools.ProfilerAgent.prototype._didGetActiveProfilerModules): + (devtools.ProfilerAgent.prototype._didGetLogLines): + +2010-02-10 James Hawkins <jhawkins@chromium.org> + + Reviewed by Eric Seidel. + + [Chromium] Remove code from SuggestionsPopup that was removed in a + previous revision of AutocompletePopup and accidentally added back in + the refactoring. + + https://bugs.webkit.org/show_bug.cgi?id=34818 + + * src/AutoFillPopupMenuClient.cpp: + * src/AutoFillPopupMenuClient.h: Added property svn:eol-style. + * src/SuggestionsPopupMenuClient.cpp: + (WebKit::SuggestionsPopupMenuClient::popupDidHide): + (WebKit::SuggestionsPopupMenuClient::setTextFromItem): + (WebKit::SuggestionsPopupMenuClient::initialize): + * src/SuggestionsPopupMenuClient.h: + +2010-02-10 Nate Chapin <japhet@chromium.org> + + Reviewed by Adam Barth. + + Update call to V8DOMWrapper::lookupDOMWrapper() to match new parameters. + + https://bugs.webkit.org/show_bug.cgi?id=34768 + + * src/DebuggerAgentImpl.cpp: + (WebKit::DebuggerAgentImpl::createUtilityContext): + +2010-02-10 Kenneth Russell <kbr@google.com> + + Reviewed by Oliver Hunt. + + Remove automatic viewport resizing + https://bugs.webkit.org/show_bug.cgi?id=34766 + + Removed automatic viewport resizing per conclusions on the WebGL + mailing list. Added test verifying new behavior and updated a + couple of previous tests failing after this change. + + * src/GraphicsContext3D.cpp: + (WebCore::GraphicsContext3DInternal::reshape): + +2010-02-10 Yury Semikhatsky <yurys@chromium.org> + + Reviewed by Pavel Feldman. + + Chromium Win build fix. Add third_party/nss to the dependencies list on Windows. + + https://bugs.webkit.org/show_bug.cgi?id=34789 + + * DEPS: + +2010-02-10 Yury Semikhatsky <yurys@chromium.org> + + Reviewed by Pavel Feldman. + + Rolling Chromium dependencies to match Chromium revision 38580. + + https://bugs.webkit.org/show_bug.cgi?id=34789 + + * DEPS: + +2010-02-10 Yury Semikhatsky <yurys@chromium.org> + + Reviewed by Pavel Feldman. + + Use v8::Debug::ProcessDebugMessages instead of executing an empty function + + https://bugs.webkit.org/show_bug.cgi?id=34704 + + * src/DebuggerAgent.h: + * src/DebuggerAgentImpl.cpp: + (WebKit::DebuggerAgentImpl::processDebugCommands): + * src/DebuggerAgentImpl.h: + * src/ToolsAgent.h: + * src/WebDevToolsAgentImpl.cpp: + * src/WebDevToolsAgentImpl.h: + * src/js/DebuggerAgent.js: + (devtools.DebuggerAgent.prototype.addBreakpoint): + * src/js/DevToolsHostStub.js: + (.RemoteDebuggerAgentStub.prototype.processDebugCommands): + * src/js/InjectDispatch.js: + (dispatch): + * src/js/ProfilerAgent.js: + (devtools.ProfilerAgent.prototype.startProfiling): + (devtools.ProfilerAgent.prototype.stopProfiling): + * src/js/Tests.js: + +2010-02-10 Tony Chang <tony@chromium.org> + + Unreviewed, build fix for Chromium Mac take 2. + + * src/AutoFillPopupMenuClient.cpp: + (WebKit::AutoFillPopupMenuClient::removeSuggestionAtIndex): + +2010-02-10 Tony Chang <tony@chromium.org> + + Unreviewed, build fix for Chromium Mac. + + * src/AutoFillPopupMenuClient.cpp: + (WebKit::AutoFillPopupMenuClient::removeSuggestionAtIndex): + +2010-02-09 James Hawkins <jhawkins@chromium.org> + + Reviewed by Darin Fisher. + + [Chromium] Refactor AutocompletePopupMenuClient into a base class, + SuggestionsPopupMenuClient, and two derived classes, + AutocompletePopupMenuClient and AutoFillPopupMenuClient. Currently + the behavior of suggestions popups has not changed. + + https://bugs.webkit.org/show_bug.cgi?id=34721 + + * WebKit.gyp: + * public/WebView.h: + * src/AutoFillPopupMenuClient.cpp: Added. + * src/AutoFillPopupMenuClient.h: Added. + * src/AutocompletePopupMenuClient.cpp: + (WebKit::AutocompletePopupMenuClient::getSuggestionsCount): + (WebKit::AutocompletePopupMenuClient::getSuggestion): + (WebKit::AutocompletePopupMenuClient::removeSuggestionAtIndex): + (WebKit::AutocompletePopupMenuClient::initialize): + (WebKit::AutocompletePopupMenuClient::setSuggestions): + * src/AutocompletePopupMenuClient.h: + * src/SuggestionsPopupMenuClient.cpp: Added. + * src/SuggestionsPopupMenuClient.h: Added. + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::WebViewImpl): + (WebKit::WebViewImpl::keyEvent): + (WebKit::WebViewImpl::autocompleteHandleKeyEvent): + (WebKit::WebViewImpl::applyAutofillSuggestions): + (WebKit::WebViewImpl::applyAutoFillSuggestions): + (WebKit::WebViewImpl::applyAutocompleteSuggestions): + * src/WebViewImpl.h: + +2010-02-09 Chris Guillory <ctguil@google.com> + + Reviewed by Darin Fisher. + + [Chromium] Add function for accessibility object state change notifications. + + https://bugs.webkit.org/show_bug.cgi?id=34464 + + * gyp_webkit: + * public/WebViewClient.h: + (WebKit::WebViewClient::didChangeAccessibilityObjectState): + * src/ChromeClientImpl.cpp: + (WebKit::ChromeClientImpl::didChangeAccessibilityObjectState): + * src/ChromeClientImpl.h: + +2010-02-09 Mikhail Naganov <mnaganov@chromium.org> + + Reviewed by Pavel Feldman. + + Continuing debugger and profiler unforking: narrow scope of JSC-specific ifdefs. + Also, enable JAVASCRIPT_DEBUGGER explicitly in features, it appears to be required + for really enabling it in V8 bindings generation. + + https://bugs.webkit.org/show_bug.cgi?id=34706 + + * features.gypi: + +2010-02-09 Jian Li <jianli@chromium.org> + + Reviewed by Darin Fisher. + + [chromium] Add the chromium interface to support Blob.slice. + https://bugs.webkit.org/show_bug.cgi?id=34652 + + * WebKit.gyp: + * public/WebFileInfo.h: Added. + * public/WebHTTPBody.h: + * src/WebHTTPBody.cpp: + (WebKit::WebHTTPBody::elementAt): + (WebKit::WebHTTPBody::appendFile): + +2010-02-09 Yury Semikhatsky <yurys@chromium.org> + + Unreviewed. Follow-up fix. + + Add missing devTools.css file. + + https://bugs.webkit.org/show_bug.cgi?id=34756 + + * src/js/devTools.css: Added. + +2010-02-09 Yury Semikhatsky <yurys@chromium.org> + + Reviewed by Pavel Feldman. + + Upstream DevTools Images and .css files. + + https://bugs.webkit.org/show_bug.cgi?id=34756 + + * WebKit.gypi: + * src/js/DevTools.css: Added. + * src/js/Images/segmentChromium.png: Added. + * src/js/Images/segmentHoverChromium.png: Added. + * src/js/Images/segmentHoverEndChromium.png: Added. + * src/js/Images/segmentSelectedChromium.png: Added. + * src/js/Images/segmentSelectedEndChromium.png: Added. + * src/js/Images/statusbarBackgroundChromium.png: Added. + * src/js/Images/statusbarBottomBackgroundChromium.png: Added. + * src/js/Images/statusbarButtonsChromium.png: Added. + * src/js/Images/statusbarMenuButtonChromium.png: Added. + * src/js/Images/statusbarMenuButtonSelectedChromium.png: Added. + +2010-02-09 Yury Semikhatsky <yurys@chromium.org> + + Reviewed by Pavel Feldman. + + Upstream JavaScript part of DevTools WebKit API implementation(now + with the added files). + + https://bugs.webkit.org/show_bug.cgi?id=34744 + + * WebKit.gypi: Added. + * src/js/DebuggerAgent.js: Added. + (devtools.DebuggerAgent): + (devtools.DebuggerAgent.prototype.reset): + (devtools.DebuggerAgent.prototype.initUI): + (devtools.DebuggerAgent.prototype.resolveScriptSource.this.requestSeqToCallback_.cmd.getSequenceNumber): + (devtools.DebuggerAgent.prototype.resolveScriptSource): + (devtools.DebuggerAgent.prototype.pauseExecution): + (devtools.DebuggerAgent.prototype.addBreakpoint): + (devtools.DebuggerAgent.prototype.removeBreakpoint): + (devtools.DebuggerAgent.prototype.updateBreakpoint): + (devtools.DebuggerAgent.prototype.stepIntoStatement): + (devtools.DebuggerAgent.prototype.stepOutOfFunction): + (devtools.DebuggerAgent.prototype.stepOverStatement): + (devtools.DebuggerAgent.prototype.resumeExecution): + (devtools.DebuggerAgent.prototype.createExceptionMessage_): + (devtools.DebuggerAgent.prototype.showPendingExceptionMessage_): + (devtools.DebuggerAgent.prototype.clearExceptionMessage_): + (devtools.DebuggerAgent.prototype.pauseOnExceptions): + (devtools.DebuggerAgent.prototype.setPauseOnExceptions): + (devtools.DebuggerAgent.prototype.requestEvaluate): + (devtools.DebuggerAgent.prototype.resolveChildren): + (devtools.DebuggerAgent.prototype.resolveScope.this.requestSeqToCallback_.cmd.getSequenceNumber): + (devtools.DebuggerAgent.prototype.resolveScope): + (devtools.DebuggerAgent.prototype.resolveFrameVariables_.scopeResponseHandler): + (devtools.DebuggerAgent.prototype.resolveFrameVariables_): + (devtools.DebuggerAgent.prototype.resolveCompletionsOnFrame): + (devtools.DebuggerAgent.prototype.getScriptContextType): + (devtools.DebuggerAgent.prototype.requestClearBreakpoint_): + (devtools.DebuggerAgent.prototype.requestChangeBreakpoint_): + (devtools.DebuggerAgent.prototype.requestBacktrace_): + (devtools.DebuggerAgent.sendCommand_): + (devtools.DebuggerAgent.prototype.stepCommand_): + (devtools.DebuggerAgent.prototype.requestLookup_): + (devtools.DebuggerAgent.prototype.setContextId_.this.requestSeqToCallback_.cmd.getSequenceNumber): + (devtools.DebuggerAgent.prototype.setContextId_): + (devtools.DebuggerAgent.prototype.handleDebuggerOutput_): + (devtools.DebuggerAgent.prototype.handleBreakEvent_): + (devtools.DebuggerAgent.prototype.handleExceptionEvent_): + (devtools.DebuggerAgent.prototype.handleScriptsResponse_): + (devtools.DebuggerAgent.prototype.isScriptFromInspectedContext_): + (devtools.DebuggerAgent.prototype.handleSetBreakpointResponse_): + (devtools.DebuggerAgent.prototype.handleAfterCompileEvent_): + (devtools.DebuggerAgent.prototype.addScriptInfo_): + (devtools.DebuggerAgent.prototype.handleClearBreakpointResponse_): + (devtools.DebuggerAgent.prototype.handleBacktraceResponse_): + (devtools.DebuggerAgent.prototype.doHandleBacktraceResponse_): + (devtools.DebuggerAgent.prototype.evaluateInCallFrame): + (devtools.DebuggerAgent.prototype.invokeCallbackForResponse_): + (devtools.DebuggerAgent.prototype.formatCallFrame_): + (devtools.DebuggerAgent.formatObjectProperties_): + (devtools.DebuggerAgent.propertiesToProxies_): + (devtools.DebuggerAgent.formatObjectProxy_): + (devtools.DebuggerAgent.webkitToV8LineNumber_): + (devtools.DebuggerAgent.v8ToWwebkitLineNumber_): + (devtools.ScriptInfo): + (devtools.ScriptInfo.prototype.getLineOffset): + (devtools.ScriptInfo.prototype.getContextType): + (devtools.ScriptInfo.prototype.getUrl): + (devtools.ScriptInfo.prototype.isUnresolved): + (devtools.ScriptInfo.prototype.getBreakpointInfo): + (devtools.ScriptInfo.prototype.addBreakpointInfo): + (devtools.ScriptInfo.prototype.removeBreakpointInfo): + (devtools.BreakpointInfo): + (devtools.BreakpointInfo.prototype.getLine): + (devtools.BreakpointInfo.prototype.getV8Id): + (devtools.BreakpointInfo.prototype.setV8Id): + (devtools.BreakpointInfo.prototype.markAsRemoved): + (devtools.BreakpointInfo.prototype.isRemoved): + (devtools.CallFrame): + (devtools.CallFrame.prototype.evaluate_): + (devtools.DebugCommand): + (devtools.DebugCommand.prototype.getSequenceNumber): + (devtools.DebugCommand.prototype.toJSONProtocol): + (devtools.DebuggerMessage): + (devtools.DebuggerMessage.prototype.getType): + (devtools.DebuggerMessage.prototype.getEvent): + (devtools.DebuggerMessage.prototype.getCommand): + (devtools.DebuggerMessage.prototype.getRequestSeq): + (devtools.DebuggerMessage.prototype.isRunning): + (devtools.DebuggerMessage.prototype.isSuccess): + (devtools.DebuggerMessage.prototype.getMessage): + (devtools.DebuggerMessage.prototype.getBody): + (devtools.DebuggerMessage.prototype.lookup): + * src/js/DevTools.js: Added. + (devtools.dispatch): + (devtools.ToolsAgent): + (devtools.ToolsAgent.prototype.reset): + (devtools.ToolsAgent.prototype.evaluateJavaScript): + (devtools.ToolsAgent.prototype.getDebuggerAgent): + (devtools.ToolsAgent.prototype.getProfilerAgent): + (devtools.ToolsAgent.prototype.frameNavigate_): + (devtools.ToolsAgent.prototype.dispatchOnClient_): + (devtools.ToolsAgent.prototype.evaluate): + (WebInspector.setResourcesPanelEnabled): + (debugPrint): + (devtools): + (WebInspector.loaded): + (): + (WebInspector.ScriptView.prototype.setupSourceFrameIfNeeded): + (WebInspector.ScriptView.prototype.didResolveScriptSource_): + (WebInspector.UnresolvedPropertyValue): + (WebInspector.UIString): + (WebInspector.resourceTrackingWasEnabled): + (WebInspector.resourceTrackingWasDisabled): + (WebInspector.TestController.prototype.runAfterPendingDispatches): + (WebInspector.queuesAreEmpty): + (WebInspector.pausedScript): + * src/js/DevToolsHostStub.js: Added. + (.RemoteDebuggerAgentStub): + (.RemoteDebuggerAgentStub.prototype.getContextId): + (.RemoteProfilerAgentStub): + (.RemoteProfilerAgentStub.prototype.getActiveProfilerModules): + (.RemoteProfilerAgentStub.prototype.getLogLines): + (.RemoteToolsAgentStub): + (.RemoteToolsAgentStub.prototype.dispatchOnInjectedScript): + (.RemoteToolsAgentStub.prototype.dispatchOnInspectorController): + (.RemoteToolsAgentStub.prototype.executeVoidJavaScript): + (.ProfilerStubHelper): + (.ProfilerStubHelper.GetInstance): + (.ProfilerStubHelper.prototype.StopProfiling): + (.ProfilerStubHelper.prototype.StartProfiling): + (.ProfilerStubHelper.prototype.getActiveProfilerModules): + (.ProfilerStubHelper.prototype.getLogLines): + (.RemoteDebuggerCommandExecutorStub): + (.RemoteDebuggerCommandExecutorStub.prototype.DebuggerCommand): + (.RemoteDebuggerCommandExecutorStub.prototype.DebuggerPauseScript): + (.RemoteDebuggerCommandExecutorStub.prototype.sendResponse_): + (.DevToolsHostStub): + (.DevToolsHostStub.prototype.reset): + (.DevToolsHostStub.prototype.setting): + (.DevToolsHostStub.prototype.setSetting): + * src/js/HeapProfilerPanel.js: Added. + (WebInspector.ProfilesPanel.prototype.addSnapshot): + (WebInspector.HeapSnapshotView): + (WebInspector.HeapSnapshotView.prototype.get statusBarItems): + (WebInspector.HeapSnapshotView.prototype.get profile): + (WebInspector.HeapSnapshotView.prototype.set profile): + (WebInspector.HeapSnapshotView.prototype.show): + (WebInspector.HeapSnapshotView.prototype.hide): + (WebInspector.HeapSnapshotView.prototype.resize): + (WebInspector.HeapSnapshotView.prototype.refresh): + (WebInspector.HeapSnapshotView.prototype.refreshShowAsPercents): + (WebInspector.HeapSnapshotView.prototype._deleteSearchMatchedFlags): + (WebInspector.HeapSnapshotView.prototype.searchCanceled): + (WebInspector.HeapSnapshotView.prototype.performSearch): + (WebInspector.HeapSnapshotView.prototype.jumpToFirstSearchResult.WebInspector.CPUProfileView.prototype.jumpToFirstSearchResult.jumpToLastSearchResult.WebInspector.CPUProfileView.prototype.jumpToLastSearchResult.jumpToNextSearchResult.WebInspector.CPUProfileView.prototype.jumpToNextSearchResult.jumpToPreviousSearchResult.WebInspector.CPUProfileView.prototype.jumpToPreviousSearchResult.showingFirstSearchResult.WebInspector.CPUProfileView.prototype.showingFirstSearchResult.showingLastSearchResult.WebInspector.CPUProfileView.prototype.showingLastSearchResult._jumpToSearchResult.WebInspector.CPUProfileView.prototype._jumpToSearchResult.refreshVisibleData): + (WebInspector.HeapSnapshotView.prototype._changeBase): + (WebInspector.HeapSnapshotView.prototype._createSnapshotDataGridList): + (WebInspector.HeapSnapshotView.prototype._mouseDownInDataGrid): + (WebInspector.HeapSnapshotView.prototype.get _isShowingAsPercent): + (WebInspector.HeapSnapshotView.prototype._percentClicked): + (WebInspector.HeapSnapshotView.prototype._resetDataGridList): + (WebInspector.HeapSnapshotView.prototype._sortData): + (WebInspector.HeapSnapshotView.prototype._updateBaseOptions): + (WebInspector.HeapSnapshotView.prototype._updatePercentButton): + (WebInspector.HeapSnapshotView.prototype._updateSummaryGraph): + (WebInspector.HeapSnapshotView.SearchHelper.operations.LESS): + (WebInspector.HeapSnapshotView.SearchHelper.operations.LESS_OR_EQUAL): + (WebInspector.HeapSnapshotView.SearchHelper.operations.EQUAL): + (WebInspector.HeapSnapshotView.SearchHelper.operations.GREATER_OR_EQUAL): + (WebInspector.HeapSnapshotView.SearchHelper.operations.GREATER): + (WebInspector.HeapSnapshotView.SearchHelper.parseOperationAndNumber): + (WebInspector.HeapSummaryCalculator): + (WebInspector.HeapSummaryCalculator.prototype.computeSummaryValues): + (WebInspector.HeapSummaryCalculator.prototype.formatValue): + (WebInspector.HeapSummaryCalculator.prototype.get showAsPercent): + (WebInspector.HeapSummaryCalculator.prototype.set showAsPercent): + (WebInspector.HeapSummaryCountCalculator): + (WebInspector.HeapSummaryCountCalculator.prototype._highFromLow): + (WebInspector.HeapSummaryCountCalculator.prototype._valueToString): + (WebInspector.HeapSummarySizeCalculator): + (WebInspector.HeapSummarySizeCalculator.prototype._highFromLow): + (WebInspector.HeapSnapshotSidebarTreeElement): + (WebInspector.HeapSnapshotSidebarTreeElement.prototype.get mainTitle): + (WebInspector.HeapSnapshotSidebarTreeElement.prototype.set mainTitle): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.get _hasRetainers): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.get _parent): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype._populate.if): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype._populate): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.produceDiff): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.sort): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.signForDelta): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.showDeltaAsPercent): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.getTotalCount): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.getTotalSize): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.get countPercent): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.get sizePercent): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.get countDeltaPercent): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.get sizeDeltaPercent): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.get data): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.createCell): + (WebInspector.HeapSnapshotDataGridNode): + (WebInspector.HeapSnapshotDataGridList): + (WebInspector.HeapSnapshotDataGridList.prototype.appendChild): + (WebInspector.HeapSnapshotDataGridList.prototype.insertChild): + (WebInspector.HeapSnapshotDataGridList.prototype.removeChildren): + (WebInspector.HeapSnapshotDataGridList.prototype.populateChildren): + (WebInspector.HeapSnapshotDataGridList.propertyComparator.comparator): + (WebInspector.HeapSnapshotDataGridList.propertyComparator): + (WebInspector.HeapSnapshotDataGridRetainerNode): + (WebInspector.HeapSnapshotDataGridRetainerNode.prototype.get sizePercent): + (WebInspector.HeapSnapshotDataGridRetainerNode.prototype.get sizeDeltaPercent): + (WebInspector.HeapSnapshotDataGridRetainerNode.prototype._calculateRetainers): + (WebInspector.HeapSnapshotProfileType): + (WebInspector.HeapSnapshotProfileType.prototype.get buttonTooltip): + (WebInspector.HeapSnapshotProfileType.prototype.get buttonStyle): + (WebInspector.HeapSnapshotProfileType.prototype.buttonClicked): + (WebInspector.HeapSnapshotProfileType.prototype.get welcomeMessage): + (WebInspector.HeapSnapshotProfileType.prototype.createSidebarTreeElementForProfile): + (WebInspector.HeapSnapshotProfileType.prototype.createView): + (): + * src/js/InjectDispatch.js: Added. + (InspectorControllerDispatcher.dispatch): + (ApuAgentDispatcher.dispatchToApu): + (dispatch): + (devtools): + * src/js/InspectorControllerImpl.js: Added. + (devtools.InspectorBackendImpl): + (devtools.InspectorBackendImpl.prototype.toggleNodeSearch): + (devtools.InspectorBackendImpl.prototype.debuggerEnabled): + (devtools.InspectorBackendImpl.prototype.profilerEnabled): + (devtools.InspectorBackendImpl.prototype.addBreakpoint): + (devtools.InspectorBackendImpl.prototype.removeBreakpoint): + (devtools.InspectorBackendImpl.prototype.updateBreakpoint): + (devtools.InspectorBackendImpl.prototype.pauseInDebugger): + (devtools.InspectorBackendImpl.prototype.resumeDebugger): + (devtools.InspectorBackendImpl.prototype.stepIntoStatementInDebugger): + (devtools.InspectorBackendImpl.prototype.stepOutOfFunctionInDebugger): + (devtools.InspectorBackendImpl.prototype.stepOverStatementInDebugger): + (devtools.InspectorBackendImpl.prototype.setPauseOnExceptionsState): + (devtools.InspectorBackendImpl.prototype.pauseOnExceptionsState): + (devtools.InspectorBackendImpl.prototype.pauseOnExceptions): + (devtools.InspectorBackendImpl.prototype.setPauseOnExceptions): + (devtools.InspectorBackendImpl.prototype.startProfiling): + (devtools.InspectorBackendImpl.prototype.stopProfiling): + (devtools.InspectorBackendImpl.prototype.getProfileHeaders): + (devtools.InspectorBackendImpl.prototype.addFullProfile): + (devtools.InspectorBackendImpl.prototype.getProfile): + (devtools.InspectorBackendImpl.prototype.takeHeapSnapshot): + (devtools.InspectorBackendImpl.prototype.dispatchOnInjectedScript): + (devtools.InspectorBackendImpl.prototype.installInspectorControllerDelegate_): + (devtools.InspectorBackendImpl.prototype.callInspectorController_): + * src/js/ProfilerAgent.js: Added. + (devtools.ProfilerAgent): + (devtools.ProfilerAgent.prototype.setupProfilerProcessorCallbacks): + (devtools.ProfilerAgent.prototype.initializeProfiling): + (devtools.ProfilerAgent.prototype.startProfiling): + (devtools.ProfilerAgent.prototype.stopProfiling): + (devtools.ProfilerAgent.prototype.didGetActiveProfilerModules_): + (devtools.ProfilerAgent.prototype.didGetLogLines_): + * src/js/ProfilerProcessor.js: Added. + (devtools.profiler.WebKitViewBuilder): + (devtools.profiler.WebKitViewBuilder.prototype.createViewNode): + (devtools.profiler.WebKitViewNode): + (set get devtools.profiler.WebKitViewNode.prototype.initFuncInfo_): + (devtools.profiler.JsProfile): + (devtools.profiler.JsProfile.prototype.skipThisFunction): + (devtools.profiler.Processor): + (devtools.profiler.Processor.prototype.printError): + (devtools.profiler.Processor.prototype.skipDispatch): + (devtools.profiler.Processor.prototype.setCallbacks): + (devtools.profiler.Processor.prototype.setNewProfileCallback): + (devtools.profiler.Processor.prototype.processProfiler_.switch.break): + (devtools.profiler.Processor.prototype.processProfiler_): + (devtools.profiler.Processor.prototype.processCodeCreation_): + (devtools.profiler.Processor.prototype.processCodeMove_): + (devtools.profiler.Processor.prototype.processCodeDelete_): + (devtools.profiler.Processor.prototype.processFunctionCreation_): + (devtools.profiler.Processor.prototype.processFunctionMove_): + (devtools.profiler.Processor.prototype.processFunctionDelete_): + (devtools.profiler.Processor.prototype.processTick_): + (devtools.profiler.Processor.prototype.processTickV2_): + (devtools.profiler.Processor.prototype.processHeapSampleBegin_): + (devtools.profiler.Processor.prototype.processHeapSampleStats_): + (devtools.profiler.Processor.prototype.processHeapSampleItem_): + (devtools.profiler.Processor.prototype.processHeapJsConsItem_): + (devtools.profiler.Processor.prototype.processHeapJsRetItem_.mergeRetainers): + (devtools.profiler.Processor.prototype.processHeapJsRetItem_): + (devtools.profiler.Processor.prototype.processHeapSampleEnd_): + (devtools.profiler.Processor.prototype.createProfileForView): + * src/js/Tests.js: Added. + (.TestSuite): + (.TestSuite.prototype.fail): + (.TestSuite.prototype.assertEquals): + (.TestSuite.prototype.assertTrue): + (.TestSuite.prototype.assertContains): + (.TestSuite.prototype.takeControl): + (.TestSuite.prototype.releaseControl): + (.TestSuite.prototype.reportOk_): + (.TestSuite.prototype.reportFailure_): + (.TestSuite.prototype.runTest): + (.TestSuite.prototype.showPanel): + (.TestSuite.prototype.addSniffer.receiver.methodName): + (.TestSuite.prototype.addSniffer): + (.TestSuite.prototype.testHostIsPresent): + (.TestSuite.prototype.testElementsTreeRoot): + (.TestSuite.prototype.testMainResource): + (.TestSuite.prototype.testResourceContentLength.this.addSniffer.): + (.TestSuite.prototype.testResourceHeaders): + (.TestSuite.prototype.testCachedResourceMimeType.this.addSniffer.): + (.TestSuite.prototype.testCachedResourceMimeType): + (.TestSuite.prototype.testProfilerTab): + (.TestSuite.prototype.testScriptsTabIsPopulatedOnInspectedPageRefresh.waitUntilScriptIsParsed): + (.TestSuite.prototype.testScriptsTabIsPopulatedOnInspectedPageRefresh.checkScriptsPanel): + (.TestSuite.prototype.testScriptsTabIsPopulatedOnInspectedPageRefresh): + (.TestSuite.prototype.testNoScriptDuplicatesOnPanelSwitch.switchToElementsTab): + (.TestSuite.prototype.testNoScriptDuplicatesOnPanelSwitch.switchToScriptsTab): + (.TestSuite.prototype.testNoScriptDuplicatesOnPanelSwitch.checkScriptsPanel): + (.TestSuite.prototype.testNoScriptDuplicatesOnPanelSwitch.checkNoDuplicates): + (.TestSuite.prototype.testPauseOnException): + (.TestSuite.prototype.testPauseWhenLoadingDevTools): + (.TestSuite.prototype.testPauseWhenScriptIsRunning.testScriptPauseAfterDelay): + (.TestSuite.prototype.testPauseWhenScriptIsRunning.testScriptPause): + (.TestSuite.prototype.testPauseWhenScriptIsRunning): + (.TestSuite.prototype.optionsToString_): + (.TestSuite.prototype.evaluateInConsole_): + (.TestSuite.prototype.waitForSetBreakpointResponse_): + (.TestSuite.prototype.testEvalOnCallFrame.setBreakpointCallback): + (.TestSuite.prototype.testEvalOnCallFrame.waitForBreakpointHit): + (.TestSuite.prototype.testCompletionOnPause): + (.TestSuite.prototype.testCompletionOnPause.testLocalsCompletion): + (.TestSuite.prototype.testCompletionOnPause.testThisCompletion): + (.TestSuite.prototype.testCompletionOnPause.testFieldCompletion): + (.TestSuite.prototype.testCompletionOnPause.checkCompletions): + (.TestSuite.prototype.testAutoContinueOnSyntaxError.checkScriptsList): + (.TestSuite.prototype.testAutoContinueOnSyntaxError.waitForExceptionEvent.test): + (.TestSuite.prototype.testAutoContinueOnSyntaxError.waitForExceptionEvent): + (.TestSuite.prototype._checkExecutionLine): + (.TestSuite.prototype._scriptsAreParsed): + (.TestSuite.prototype._waitForScriptPause): + (.TestSuite.prototype._checkSourceFrameWhenLoaded.checkExecLine): + (.TestSuite.prototype._checkSourceFrameWhenLoaded): + (.TestSuite.prototype._performSteps.doNextAction): + (.TestSuite.prototype._performSteps): + (.TestSuite.prototype._executeCodeWhenScriptsAreParsed.executeFunctionInInspectedPage): + (.TestSuite.prototype._waitUntilScriptsAreParsed.waitForAllScripts): + (.TestSuite.prototype._waitUntilScriptsAreParsed): + (.TestSuite.prototype._executeFunctionForStepTest): + (.TestSuite.prototype.testStepOver): + (.TestSuite.prototype.testStepOut): + (.TestSuite.prototype.testStepIn): + (.TestSuite.prototype._evaluateXpath): + (.TestSuite.prototype._findNode): + (.TestSuite.prototype._findText): + (.TestSuite.prototype._nodeIterator): + (.TestSuite.prototype._checkScopeSectionDiv): + (.TestSuite.prototype._expandScopeSections.updateListener): + (.TestSuite.prototype._expandScopeSections): + (.TestSuite.prototype.testExpandScope): + (.TestSuite.prototype.testExpandScope.examineScopes): + (.TestSuite.prototype._findChildProperty): + (.TestSuite.prototype._hookGetPropertiesCallback.accessor.getProperties): + (.TestSuite.prototype._hookGetPropertiesCallback.try): + (.TestSuite.prototype._hookGetPropertiesCallback): + (.TestSuite.prototype.testDebugIntrinsicProperties.expandLocalScope): + (.TestSuite.prototype.testDebugIntrinsicProperties): + (.TestSuite.prototype.testDebugIntrinsicProperties.expandAndCheckNextProperty): + (.TestSuite.prototype.testDebugIntrinsicProperties.checkProperty): + (.TestSuite.createKeyEvent): + (.TestSuite.prototype.testConsoleLog.assertNext): + (.TestSuite.prototype.testConsoleLog): + (.TestSuite.prototype.testEvalGlobal.initEval): + (.TestSuite.prototype.testEvalGlobal): + (.TestSuite.prototype.testShowStoragePanel.this.addSniffer.): + (.TestSuite.prototype.testShowStoragePanel.this.addSniffer): + (.uiTests.runAllTests): + (.uiTests.runTest): + +2010-02-09 Yury Semikhatsky <yurys@chromium.org> + + Reviewed by Pavel Feldman. + + Upstream JavaScript part of DevTools WebKit API implementation + + https://bugs.webkit.org/show_bug.cgi?id=34744 + + * WebKit.gypi: Added. + * src/js/DebuggerAgent.js: Added. + (devtools.DebuggerAgent): + (devtools.DebuggerAgent.prototype.reset): + (devtools.DebuggerAgent.prototype.initUI): + (devtools.DebuggerAgent.prototype.resolveScriptSource.this.requestSeqToCallback_.cmd.getSequenceNumber): + (devtools.DebuggerAgent.prototype.resolveScriptSource): + (devtools.DebuggerAgent.prototype.pauseExecution): + (devtools.DebuggerAgent.prototype.addBreakpoint): + (devtools.DebuggerAgent.prototype.removeBreakpoint): + (devtools.DebuggerAgent.prototype.updateBreakpoint): + (devtools.DebuggerAgent.prototype.stepIntoStatement): + (devtools.DebuggerAgent.prototype.stepOutOfFunction): + (devtools.DebuggerAgent.prototype.stepOverStatement): + (devtools.DebuggerAgent.prototype.resumeExecution): + (devtools.DebuggerAgent.prototype.createExceptionMessage_): + (devtools.DebuggerAgent.prototype.showPendingExceptionMessage_): + (devtools.DebuggerAgent.prototype.clearExceptionMessage_): + (devtools.DebuggerAgent.prototype.pauseOnExceptions): + (devtools.DebuggerAgent.prototype.setPauseOnExceptions): + (devtools.DebuggerAgent.prototype.requestEvaluate): + (devtools.DebuggerAgent.prototype.resolveChildren): + (devtools.DebuggerAgent.prototype.resolveScope.this.requestSeqToCallback_.cmd.getSequenceNumber): + (devtools.DebuggerAgent.prototype.resolveScope): + (devtools.DebuggerAgent.prototype.resolveFrameVariables_.scopeResponseHandler): + (devtools.DebuggerAgent.prototype.resolveFrameVariables_): + (devtools.DebuggerAgent.prototype.resolveCompletionsOnFrame): + (devtools.DebuggerAgent.prototype.getScriptContextType): + (devtools.DebuggerAgent.prototype.requestClearBreakpoint_): + (devtools.DebuggerAgent.prototype.requestChangeBreakpoint_): + (devtools.DebuggerAgent.prototype.requestBacktrace_): + (devtools.DebuggerAgent.sendCommand_): + (devtools.DebuggerAgent.prototype.stepCommand_): + (devtools.DebuggerAgent.prototype.requestLookup_): + (devtools.DebuggerAgent.prototype.setContextId_.this.requestSeqToCallback_.cmd.getSequenceNumber): + (devtools.DebuggerAgent.prototype.setContextId_): + (devtools.DebuggerAgent.prototype.handleDebuggerOutput_): + (devtools.DebuggerAgent.prototype.handleBreakEvent_): + (devtools.DebuggerAgent.prototype.handleExceptionEvent_): + (devtools.DebuggerAgent.prototype.handleScriptsResponse_): + (devtools.DebuggerAgent.prototype.isScriptFromInspectedContext_): + (devtools.DebuggerAgent.prototype.handleSetBreakpointResponse_): + (devtools.DebuggerAgent.prototype.handleAfterCompileEvent_): + (devtools.DebuggerAgent.prototype.addScriptInfo_): + (devtools.DebuggerAgent.prototype.handleClearBreakpointResponse_): + (devtools.DebuggerAgent.prototype.handleBacktraceResponse_): + (devtools.DebuggerAgent.prototype.doHandleBacktraceResponse_): + (devtools.DebuggerAgent.prototype.evaluateInCallFrame): + (devtools.DebuggerAgent.prototype.invokeCallbackForResponse_): + (devtools.DebuggerAgent.prototype.formatCallFrame_): + (devtools.DebuggerAgent.formatObjectProperties_): + (devtools.DebuggerAgent.propertiesToProxies_): + (devtools.DebuggerAgent.formatObjectProxy_): + (devtools.DebuggerAgent.webkitToV8LineNumber_): + (devtools.DebuggerAgent.v8ToWwebkitLineNumber_): + (devtools.ScriptInfo): + (devtools.ScriptInfo.prototype.getLineOffset): + (devtools.ScriptInfo.prototype.getContextType): + (devtools.ScriptInfo.prototype.getUrl): + (devtools.ScriptInfo.prototype.isUnresolved): + (devtools.ScriptInfo.prototype.getBreakpointInfo): + (devtools.ScriptInfo.prototype.addBreakpointInfo): + (devtools.ScriptInfo.prototype.removeBreakpointInfo): + (devtools.BreakpointInfo): + (devtools.BreakpointInfo.prototype.getLine): + (devtools.BreakpointInfo.prototype.getV8Id): + (devtools.BreakpointInfo.prototype.setV8Id): + (devtools.BreakpointInfo.prototype.markAsRemoved): + (devtools.BreakpointInfo.prototype.isRemoved): + (devtools.CallFrame): + (devtools.CallFrame.prototype.evaluate_): + (devtools.DebugCommand): + (devtools.DebugCommand.prototype.getSequenceNumber): + (devtools.DebugCommand.prototype.toJSONProtocol): + (devtools.DebuggerMessage): + (devtools.DebuggerMessage.prototype.getType): + (devtools.DebuggerMessage.prototype.getEvent): + (devtools.DebuggerMessage.prototype.getCommand): + (devtools.DebuggerMessage.prototype.getRequestSeq): + (devtools.DebuggerMessage.prototype.isRunning): + (devtools.DebuggerMessage.prototype.isSuccess): + (devtools.DebuggerMessage.prototype.getMessage): + (devtools.DebuggerMessage.prototype.getBody): + (devtools.DebuggerMessage.prototype.lookup): + * src/js/DevTools.js: Added. + (devtools.dispatch): + (devtools.ToolsAgent): + (devtools.ToolsAgent.prototype.reset): + (devtools.ToolsAgent.prototype.evaluateJavaScript): + (devtools.ToolsAgent.prototype.getDebuggerAgent): + (devtools.ToolsAgent.prototype.getProfilerAgent): + (devtools.ToolsAgent.prototype.frameNavigate_): + (devtools.ToolsAgent.prototype.dispatchOnClient_): + (devtools.ToolsAgent.prototype.evaluate): + (WebInspector.setResourcesPanelEnabled): + (debugPrint): + (devtools): + (WebInspector.loaded): + (): + (WebInspector.ScriptView.prototype.setupSourceFrameIfNeeded): + (WebInspector.ScriptView.prototype.didResolveScriptSource_): + (WebInspector.UnresolvedPropertyValue): + (WebInspector.UIString): + (WebInspector.resourceTrackingWasEnabled): + (WebInspector.resourceTrackingWasDisabled): + (WebInspector.TestController.prototype.runAfterPendingDispatches): + (WebInspector.queuesAreEmpty): + (WebInspector.pausedScript): + * src/js/DevToolsHostStub.js: Added. + (.RemoteDebuggerAgentStub): + (.RemoteDebuggerAgentStub.prototype.getContextId): + (.RemoteProfilerAgentStub): + (.RemoteProfilerAgentStub.prototype.getActiveProfilerModules): + (.RemoteProfilerAgentStub.prototype.getLogLines): + (.RemoteToolsAgentStub): + (.RemoteToolsAgentStub.prototype.dispatchOnInjectedScript): + (.RemoteToolsAgentStub.prototype.dispatchOnInspectorController): + (.RemoteToolsAgentStub.prototype.executeVoidJavaScript): + (.ProfilerStubHelper): + (.ProfilerStubHelper.GetInstance): + (.ProfilerStubHelper.prototype.StopProfiling): + (.ProfilerStubHelper.prototype.StartProfiling): + (.ProfilerStubHelper.prototype.getActiveProfilerModules): + (.ProfilerStubHelper.prototype.getLogLines): + (.RemoteDebuggerCommandExecutorStub): + (.RemoteDebuggerCommandExecutorStub.prototype.DebuggerCommand): + (.RemoteDebuggerCommandExecutorStub.prototype.DebuggerPauseScript): + (.RemoteDebuggerCommandExecutorStub.prototype.sendResponse_): + (.DevToolsHostStub): + (.DevToolsHostStub.prototype.reset): + (.DevToolsHostStub.prototype.setting): + (.DevToolsHostStub.prototype.setSetting): + * src/js/HeapProfilerPanel.js: Added. + (WebInspector.ProfilesPanel.prototype.addSnapshot): + (WebInspector.HeapSnapshotView): + (WebInspector.HeapSnapshotView.prototype.get statusBarItems): + (WebInspector.HeapSnapshotView.prototype.get profile): + (WebInspector.HeapSnapshotView.prototype.set profile): + (WebInspector.HeapSnapshotView.prototype.show): + (WebInspector.HeapSnapshotView.prototype.hide): + (WebInspector.HeapSnapshotView.prototype.resize): + (WebInspector.HeapSnapshotView.prototype.refresh): + (WebInspector.HeapSnapshotView.prototype.refreshShowAsPercents): + (WebInspector.HeapSnapshotView.prototype._deleteSearchMatchedFlags): + (WebInspector.HeapSnapshotView.prototype.searchCanceled): + (WebInspector.HeapSnapshotView.prototype.performSearch): + (WebInspector.HeapSnapshotView.prototype.jumpToFirstSearchResult.WebInspector.CPUProfileView.prototype.jumpToFirstSearchResult.jumpToLastSearchResult.WebInspector.CPUProfileView.prototype.jumpToLastSearchResult.jumpToNextSearchResult.WebInspector.CPUProfileView.prototype.jumpToNextSearchResult.jumpToPreviousSearchResult.WebInspector.CPUProfileView.prototype.jumpToPreviousSearchResult.showingFirstSearchResult.WebInspector.CPUProfileView.prototype.showingFirstSearchResult.showingLastSearchResult.WebInspector.CPUProfileView.prototype.showingLastSearchResult._jumpToSearchResult.WebInspector.CPUProfileView.prototype._jumpToSearchResult.refreshVisibleData): + (WebInspector.HeapSnapshotView.prototype._changeBase): + (WebInspector.HeapSnapshotView.prototype._createSnapshotDataGridList): + (WebInspector.HeapSnapshotView.prototype._mouseDownInDataGrid): + (WebInspector.HeapSnapshotView.prototype.get _isShowingAsPercent): + (WebInspector.HeapSnapshotView.prototype._percentClicked): + (WebInspector.HeapSnapshotView.prototype._resetDataGridList): + (WebInspector.HeapSnapshotView.prototype._sortData): + (WebInspector.HeapSnapshotView.prototype._updateBaseOptions): + (WebInspector.HeapSnapshotView.prototype._updatePercentButton): + (WebInspector.HeapSnapshotView.prototype._updateSummaryGraph): + (WebInspector.HeapSnapshotView.SearchHelper.operations.LESS): + (WebInspector.HeapSnapshotView.SearchHelper.operations.LESS_OR_EQUAL): + (WebInspector.HeapSnapshotView.SearchHelper.operations.EQUAL): + (WebInspector.HeapSnapshotView.SearchHelper.operations.GREATER_OR_EQUAL): + (WebInspector.HeapSnapshotView.SearchHelper.operations.GREATER): + (WebInspector.HeapSnapshotView.SearchHelper.parseOperationAndNumber): + (WebInspector.HeapSummaryCalculator): + (WebInspector.HeapSummaryCalculator.prototype.computeSummaryValues): + (WebInspector.HeapSummaryCalculator.prototype.formatValue): + (WebInspector.HeapSummaryCalculator.prototype.get showAsPercent): + (WebInspector.HeapSummaryCalculator.prototype.set showAsPercent): + (WebInspector.HeapSummaryCountCalculator): + (WebInspector.HeapSummaryCountCalculator.prototype._highFromLow): + (WebInspector.HeapSummaryCountCalculator.prototype._valueToString): + (WebInspector.HeapSummarySizeCalculator): + (WebInspector.HeapSummarySizeCalculator.prototype._highFromLow): + (WebInspector.HeapSnapshotSidebarTreeElement): + (WebInspector.HeapSnapshotSidebarTreeElement.prototype.get mainTitle): + (WebInspector.HeapSnapshotSidebarTreeElement.prototype.set mainTitle): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.get _hasRetainers): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.get _parent): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype._populate.if): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype._populate): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.produceDiff): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.sort): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.signForDelta): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.showDeltaAsPercent): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.getTotalCount): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.getTotalSize): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.get countPercent): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.get sizePercent): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.get countDeltaPercent): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.get sizeDeltaPercent): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.get data): + (WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.createCell): + (WebInspector.HeapSnapshotDataGridNode): + (WebInspector.HeapSnapshotDataGridList): + (WebInspector.HeapSnapshotDataGridList.prototype.appendChild): + (WebInspector.HeapSnapshotDataGridList.prototype.insertChild): + (WebInspector.HeapSnapshotDataGridList.prototype.removeChildren): + (WebInspector.HeapSnapshotDataGridList.prototype.populateChildren): + (WebInspector.HeapSnapshotDataGridList.propertyComparator.comparator): + (WebInspector.HeapSnapshotDataGridList.propertyComparator): + (WebInspector.HeapSnapshotDataGridRetainerNode): + (WebInspector.HeapSnapshotDataGridRetainerNode.prototype.get sizePercent): + (WebInspector.HeapSnapshotDataGridRetainerNode.prototype.get sizeDeltaPercent): + (WebInspector.HeapSnapshotDataGridRetainerNode.prototype._calculateRetainers): + (WebInspector.HeapSnapshotProfileType): + (WebInspector.HeapSnapshotProfileType.prototype.get buttonTooltip): + (WebInspector.HeapSnapshotProfileType.prototype.get buttonStyle): + (WebInspector.HeapSnapshotProfileType.prototype.buttonClicked): + (WebInspector.HeapSnapshotProfileType.prototype.get welcomeMessage): + (WebInspector.HeapSnapshotProfileType.prototype.createSidebarTreeElementForProfile): + (WebInspector.HeapSnapshotProfileType.prototype.createView): + (): + * src/js/InjectDispatch.js: Added. + (InspectorControllerDispatcher.dispatch): + (ApuAgentDispatcher.dispatchToApu): + (dispatch): + (devtools): + * src/js/InspectorControllerImpl.js: Added. + (devtools.InspectorBackendImpl): + (devtools.InspectorBackendImpl.prototype.toggleNodeSearch): + (devtools.InspectorBackendImpl.prototype.debuggerEnabled): + (devtools.InspectorBackendImpl.prototype.profilerEnabled): + (devtools.InspectorBackendImpl.prototype.addBreakpoint): + (devtools.InspectorBackendImpl.prototype.removeBreakpoint): + (devtools.InspectorBackendImpl.prototype.updateBreakpoint): + (devtools.InspectorBackendImpl.prototype.pauseInDebugger): + (devtools.InspectorBackendImpl.prototype.resumeDebugger): + (devtools.InspectorBackendImpl.prototype.stepIntoStatementInDebugger): + (devtools.InspectorBackendImpl.prototype.stepOutOfFunctionInDebugger): + (devtools.InspectorBackendImpl.prototype.stepOverStatementInDebugger): + (devtools.InspectorBackendImpl.prototype.setPauseOnExceptionsState): + (devtools.InspectorBackendImpl.prototype.pauseOnExceptionsState): + (devtools.InspectorBackendImpl.prototype.pauseOnExceptions): + (devtools.InspectorBackendImpl.prototype.setPauseOnExceptions): + (devtools.InspectorBackendImpl.prototype.startProfiling): + (devtools.InspectorBackendImpl.prototype.stopProfiling): + (devtools.InspectorBackendImpl.prototype.getProfileHeaders): + (devtools.InspectorBackendImpl.prototype.addFullProfile): + (devtools.InspectorBackendImpl.prototype.getProfile): + (devtools.InspectorBackendImpl.prototype.takeHeapSnapshot): + (devtools.InspectorBackendImpl.prototype.dispatchOnInjectedScript): + (devtools.InspectorBackendImpl.prototype.installInspectorControllerDelegate_): + (devtools.InspectorBackendImpl.prototype.callInspectorController_): + * src/js/ProfilerAgent.js: Added. + (devtools.ProfilerAgent): + (devtools.ProfilerAgent.prototype.setupProfilerProcessorCallbacks): + (devtools.ProfilerAgent.prototype.initializeProfiling): + (devtools.ProfilerAgent.prototype.startProfiling): + (devtools.ProfilerAgent.prototype.stopProfiling): + (devtools.ProfilerAgent.prototype.didGetActiveProfilerModules_): + (devtools.ProfilerAgent.prototype.didGetLogLines_): + * src/js/ProfilerProcessor.js: Added. + (devtools.profiler.WebKitViewBuilder): + (devtools.profiler.WebKitViewBuilder.prototype.createViewNode): + (devtools.profiler.WebKitViewNode): + (set get devtools.profiler.WebKitViewNode.prototype.initFuncInfo_): + (devtools.profiler.JsProfile): + (devtools.profiler.JsProfile.prototype.skipThisFunction): + (devtools.profiler.Processor): + (devtools.profiler.Processor.prototype.printError): + (devtools.profiler.Processor.prototype.skipDispatch): + (devtools.profiler.Processor.prototype.setCallbacks): + (devtools.profiler.Processor.prototype.setNewProfileCallback): + (devtools.profiler.Processor.prototype.processProfiler_.switch.break): + (devtools.profiler.Processor.prototype.processProfiler_): + (devtools.profiler.Processor.prototype.processCodeCreation_): + (devtools.profiler.Processor.prototype.processCodeMove_): + (devtools.profiler.Processor.prototype.processCodeDelete_): + (devtools.profiler.Processor.prototype.processFunctionCreation_): + (devtools.profiler.Processor.prototype.processFunctionMove_): + (devtools.profiler.Processor.prototype.processFunctionDelete_): + (devtools.profiler.Processor.prototype.processTick_): + (devtools.profiler.Processor.prototype.processTickV2_): + (devtools.profiler.Processor.prototype.processHeapSampleBegin_): + (devtools.profiler.Processor.prototype.processHeapSampleStats_): + (devtools.profiler.Processor.prototype.processHeapSampleItem_): + (devtools.profiler.Processor.prototype.processHeapJsConsItem_): + (devtools.profiler.Processor.prototype.processHeapJsRetItem_.mergeRetainers): + (devtools.profiler.Processor.prototype.processHeapJsRetItem_): + (devtools.profiler.Processor.prototype.processHeapSampleEnd_): + (devtools.profiler.Processor.prototype.createProfileForView): + * src/js/Tests.js: Added. + (.TestSuite): + (.TestSuite.prototype.fail): + (.TestSuite.prototype.assertEquals): + (.TestSuite.prototype.assertTrue): + (.TestSuite.prototype.assertContains): + (.TestSuite.prototype.takeControl): + (.TestSuite.prototype.releaseControl): + (.TestSuite.prototype.reportOk_): + (.TestSuite.prototype.reportFailure_): + (.TestSuite.prototype.runTest): + (.TestSuite.prototype.showPanel): + (.TestSuite.prototype.addSniffer.receiver.methodName): + (.TestSuite.prototype.addSniffer): + (.TestSuite.prototype.testHostIsPresent): + (.TestSuite.prototype.testElementsTreeRoot): + (.TestSuite.prototype.testMainResource): + (.TestSuite.prototype.testResourceContentLength.this.addSniffer.): + (.TestSuite.prototype.testResourceHeaders): + (.TestSuite.prototype.testCachedResourceMimeType.this.addSniffer.): + (.TestSuite.prototype.testCachedResourceMimeType): + (.TestSuite.prototype.testProfilerTab): + (.TestSuite.prototype.testScriptsTabIsPopulatedOnInspectedPageRefresh.waitUntilScriptIsParsed): + (.TestSuite.prototype.testScriptsTabIsPopulatedOnInspectedPageRefresh.checkScriptsPanel): + (.TestSuite.prototype.testScriptsTabIsPopulatedOnInspectedPageRefresh): + (.TestSuite.prototype.testNoScriptDuplicatesOnPanelSwitch.switchToElementsTab): + (.TestSuite.prototype.testNoScriptDuplicatesOnPanelSwitch.switchToScriptsTab): + (.TestSuite.prototype.testNoScriptDuplicatesOnPanelSwitch.checkScriptsPanel): + (.TestSuite.prototype.testNoScriptDuplicatesOnPanelSwitch.checkNoDuplicates): + (.TestSuite.prototype.testPauseOnException): + (.TestSuite.prototype.testPauseWhenLoadingDevTools): + (.TestSuite.prototype.testPauseWhenScriptIsRunning.testScriptPauseAfterDelay): + (.TestSuite.prototype.testPauseWhenScriptIsRunning.testScriptPause): + (.TestSuite.prototype.testPauseWhenScriptIsRunning): + (.TestSuite.prototype.optionsToString_): + (.TestSuite.prototype.evaluateInConsole_): + (.TestSuite.prototype.waitForSetBreakpointResponse_): + (.TestSuite.prototype.testEvalOnCallFrame.setBreakpointCallback): + (.TestSuite.prototype.testEvalOnCallFrame.waitForBreakpointHit): + (.TestSuite.prototype.testCompletionOnPause): + (.TestSuite.prototype.testCompletionOnPause.testLocalsCompletion): + (.TestSuite.prototype.testCompletionOnPause.testThisCompletion): + (.TestSuite.prototype.testCompletionOnPause.testFieldCompletion): + (.TestSuite.prototype.testCompletionOnPause.checkCompletions): + (.TestSuite.prototype.testAutoContinueOnSyntaxError.checkScriptsList): + (.TestSuite.prototype.testAutoContinueOnSyntaxError.waitForExceptionEvent.test): + (.TestSuite.prototype.testAutoContinueOnSyntaxError.waitForExceptionEvent): + (.TestSuite.prototype._checkExecutionLine): + (.TestSuite.prototype._scriptsAreParsed): + (.TestSuite.prototype._waitForScriptPause): + (.TestSuite.prototype._checkSourceFrameWhenLoaded.checkExecLine): + (.TestSuite.prototype._checkSourceFrameWhenLoaded): + (.TestSuite.prototype._performSteps.doNextAction): + (.TestSuite.prototype._performSteps): + (.TestSuite.prototype._executeCodeWhenScriptsAreParsed.executeFunctionInInspectedPage): + (.TestSuite.prototype._waitUntilScriptsAreParsed.waitForAllScripts): + (.TestSuite.prototype._waitUntilScriptsAreParsed): + (.TestSuite.prototype._executeFunctionForStepTest): + (.TestSuite.prototype.testStepOver): + (.TestSuite.prototype.testStepOut): + (.TestSuite.prototype.testStepIn): + (.TestSuite.prototype._evaluateXpath): + (.TestSuite.prototype._findNode): + (.TestSuite.prototype._findText): + (.TestSuite.prototype._nodeIterator): + (.TestSuite.prototype._checkScopeSectionDiv): + (.TestSuite.prototype._expandScopeSections.updateListener): + (.TestSuite.prototype._expandScopeSections): + (.TestSuite.prototype.testExpandScope): + (.TestSuite.prototype.testExpandScope.examineScopes): + (.TestSuite.prototype._findChildProperty): + (.TestSuite.prototype._hookGetPropertiesCallback.accessor.getProperties): + (.TestSuite.prototype._hookGetPropertiesCallback.try): + (.TestSuite.prototype._hookGetPropertiesCallback): + (.TestSuite.prototype.testDebugIntrinsicProperties.expandLocalScope): + (.TestSuite.prototype.testDebugIntrinsicProperties): + (.TestSuite.prototype.testDebugIntrinsicProperties.expandAndCheckNextProperty): + (.TestSuite.prototype.testDebugIntrinsicProperties.checkProperty): + (.TestSuite.createKeyEvent): + (.TestSuite.prototype.testConsoleLog.assertNext): + (.TestSuite.prototype.testConsoleLog): + (.TestSuite.prototype.testEvalGlobal.initEval): + (.TestSuite.prototype.testEvalGlobal): + (.TestSuite.prototype.testShowStoragePanel.this.addSniffer.): + (.TestSuite.prototype.testShowStoragePanel.this.addSniffer): + (.uiTests.runAllTests): + (.uiTests.runTest): + +2010-02-09 Avi Drissman <avi@chromium.org> + + Reviewed by David Levin. + + Chromium Mac: Control-A shouldn't select all/Control-C shouldn't copy + https://bugs.webkit.org/show_bug.cgi?id=34615 + + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::keyEventDefault): + +2010-02-08 Evan Martin <evan@chromium.org> + + dlopen() knows how to search the library search path, so just rely on + it. While I'm at it, print out the dlerror() error message on failure. + + [chromium] webgl shouldn't hard code library search path + https://bugs.webkit.org/show_bug.cgi?id=34659 + + * src/GraphicsContext3D.cpp: + (WebCore::GraphicsContext3DInternal::GLConnection::GLConnection): + (WebCore::GraphicsContext3DInternal::GLConnection::create): + +2010-02-08 Charlie Reis <creis@chromium.org> + + Reviewed by Darin Adler. + + onbeforeunload not called at window close + frame or iframe focused + https://bugs.webkit.org/show_bug.cgi?id=27481 + http://code.google.com/p/chromium/issues/detail?id=32615 + http://code.google.com/p/chromium/issues/detail?id=17157 + + Chromium and WebKit on Windows will now fire beforeunload handlers + even if an inner frame is focused. + + Layout tests aren't able to test this bug, since it requires closing + the actual browser window, not calling window.close(). Instead, + test with WebCore/manual-tests/onbeforeunload-focused-iframe.html. + + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::dispatchBeforeUnloadEvent): + +2010-02-08 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by David Levin. + + WebKit/chromium: Custom context menu does not work in inspector. + https://bugs.webkit.org/show_bug.cgi?id=34711 + + * src/WebDevToolsFrontendImpl.cpp: + (WebKit::WebDevToolsFrontendImpl::jsShowContextMenu): + +2010-02-08 Nate Chapin <japhet@chromium.org> + + Reviewed by Darin Fisher. + + Check that the index passed into BackForwardListClientImpl::itemAtIndex() + is valid, and return null if it isn't. + + https://bugs.webkit.org/show_bug.cgi?id=34722 + + * src/BackForwardListClientImpl.cpp: + (WebKit::BackForwardListClientImpl::itemAtIndex): + +2010-02-05 Dumitru Daniliuc <dumi@chromium.org> + + Reviewed by Jeremy Orlow. + + Adding a way to close all database handles pointing to a certain + database as soon as possible. + https://bugs.webkit.org/show_bug.cgi?id=34619 + + * public/WebDatabase.h: + * src/WebDatabase.cpp: + (WebKit::WebDatabase::closeDatabaseImmediately): + +2010-02-08 Dirk Schulze <krit@webkit.org> + + Reviewed by Nikolas Zimmermann. + + Add back an AffineTransform class for use by SVG + https://bugs.webkit.org/show_bug.cgi?id=33750 + + Use AffineTransform instead of TransformationMatrix here. + + * tests/TransparencyWinTest.cpp: + (WebCore::TEST): + +2010-02-07 Jian Li <jianli@chromium.org> + + Reviewed by Darin Fisher. + + [chromium] Change chromium interface to handle DownloadURL format. + https://bugs.webkit.org/show_bug.cgi?id=34655 + + * public/WebDragData.h: + * src/WebDragData.cpp: + (WebKit::WebDragData::downloadMetadata): + (WebKit::WebDragData::setDownloadMetadata): + +2010-02-06 Dimitri Glazkov <dglazkov@chromium.org> + + No review, rolling out r54364. + http://trac.webkit.org/changeset/54364 + https://bugs.webkit.org/show_bug.cgi?id=34464 + + Introduced asserts in layout tests, needs more testing + locally. + + * public/WebViewClient.h: + * src/ChromeClientImpl.cpp: + * src/ChromeClientImpl.h: + +2010-02-05 James Hawkins <jhawkins@chromium.org> + + Reviewed by David Levin. + + [Chromium] Rename autocomplete* to suggestions* to prepare for the + refactoring of AutocompletePopupMenuClient. + + https://bugs.webkit.org/show_bug.cgi?id=34664 + + * public/WebView.h: + * src/AutocompletePopupMenuClient.cpp: + (WebKit::AutocompletePopupMenuClient::popupDidHide): + * src/EditorClientImpl.cpp: + (WebKit::EditorClientImpl::textFieldDidEndEditing): + (WebKit::EditorClientImpl::doAutofill): + * src/WebViewImpl.cpp: + (WebKit::): + (WebKit::WebViewImpl::WebViewImpl): + (WebKit::WebViewImpl::mouseDown): + (WebKit::WebViewImpl::autocompleteHandleKeyEvent): + (WebKit::WebViewImpl::setFocus): + (WebKit::WebViewImpl::applyAutofillSuggestions): + (WebKit::WebViewImpl::hideAutofillPopup): + (WebKit::WebViewImpl::hideSuggestionsPopup): + (WebKit::WebViewImpl::refreshSuggestionsPopup): + * src/WebViewImpl.h: + (WebKit::WebViewImpl::suggestionsPopupDidHide): + +2010-02-05 James Hawkins <jhawkins@chromium.org> + + Reviewed by David Levin. + + [Chromium] Remove an unused forward declaration in WebKitClient.h. + + https://bugs.webkit.org/show_bug.cgi?id=34622 + + * public/WebKitClient.h: + +2010-02-05 James Hawkins <jhawkins@chromium.org> + + Reviewed by Darin Fisher. + + Implement WebInputElement::isActivatedSubmit(). + + https://bugs.webkit.org/show_bug.cgi?id=34623 + + * public/WebInputElement.h: + * src/WebInputElement.cpp: + (WebKit::WebInputElement::isActivatedSubmit): + +2010-02-05 Nate Chapin <japhet@chromium.org> + + Reviewed by Dimitri Glazkov. + + Update code for getting a v8::FunctionTemplate. + + https://bugs.webkit.org/show_bug.cgi?id=34606 + + * src/WebDevToolsAgentImpl.cpp: + (WebKit::WebDevToolsAgentImpl::createInspectorBackendV8Wrapper): + +2010-02-05 Mikhail Naganov <mnaganov@chromium.org> + + Reviewed by Pavel Feldman. + + Enable JAVASCRIPT_DEBUGGER in chromium port. + + https://bugs.webkit.org/show_bug.cgi?id=34638 + + * features.gypi: + +2010-02-04 Yaar Schnitman <yaar@chromium.org> + + Reviewed by Darin Fisher. + + Upstreaming gtests from chromium: UniscribeHelper and TransparencyWin + https://bugs.webkit.org/show_bug.cgi?id=34509 + + Resubmit: The previous commit (r54333) was rolled back. + + * WebKit.gyp: + * tests/TransparencyWinTest.cpp: Added. + (WebCore::RECTToFloatRect): + (WebCore::drawNativeRect): + (WebCore::getPixelAt): + (WebCore::clearTopLayerAlphaChannel): + (WebCore::clearTopLayerAlphaPixel): + (WebCore::operator<<): + (WebCore::TEST): + * tests/UniscribeHelperTest.cpp: Added. + (WebCore::UniscribeTest::UniscribeTest): + (WebCore::UniscribeTest::MakeFont): + (WebCore::UniscribeTest::SetUp): + (WebCore::UniscribeTest::TearDown): + (TEST_F): + +2010-02-04 Drew Wilson <atwilson@chromium.org> + + Reviewed by David Levin. + + WorkerContext.close() does not work in the chromium port + https://bugs.webkit.org/show_bug.cgi?id=34551 + + Test: Adding new downstream test. + + * src/WebWorkerBase.cpp: + (WebKit::WebWorkerBase::workerContextClosedTask): + Now shuts down the worker thread when WorkerContext::close() is invoked. + +2010-02-04 Chris Guillory <chris.guillory@google.com> + + Reviewed by Darin Fisher. + + [Chromium] Add function for AccessibilityObject state change notifications. + + https://bugs.webkit.org/show_bug.cgi?id=34464 + + * public/WebViewClient.h: + (WebKit::WebViewClient::didChangeAccessibilityObjectState): + * src/ChromeClientImpl.cpp: + (WebKit::ChromeClientImpl::didChangeAccessibilityObjectState): + * src/ChromeClientImpl.h: + +2010-02-04 Jeremy Moskovich <jeremy@chromium.org> + + Reviewed by Darin Fisher. + + Update comments to better document the possible values of the + writing direction menu state variables. + + * public/WebContextMenuData.h: + +2010-02-04 Nate Chapin <japhet@chromium.org> + + Reviewed by Dimitri Glazkov. + + Remove references to V8Custom. + + https://bugs.webkit.org/show_bug.cgi?id=32638 + + * src/DebuggerAgentImpl.cpp: + * src/WebDevToolsFrontendImpl.cpp: + 2010-02-04 Yury Semikhatsky <yurys@chromium.org> Unreviewed. Revert 54333 which broke Chromium build. diff --git a/WebKit/chromium/DEPS b/WebKit/chromium/DEPS index fc90187..9c45b83 100644 --- a/WebKit/chromium/DEPS +++ b/WebKit/chromium/DEPS @@ -35,21 +35,22 @@ vars = { 'chromium_deps_svn': 'http://src.chromium.org/svn/trunk/deps/third_party', # Dependencies' revisions to use: - 'chromium_rev': '31834', - 'google-url_rev': '120', - 'gtest_rev': '336', - 'gyp_rev': '751', - 'icu_rev': '31724', + 'chromium_rev': '38580', + 'google-url_rev': '121', + 'gtest_rev': '359', + 'gyp_rev': '781', + 'icu_rev': '37341', 'openvcdiff_rev': '28', - 'ots_rev': '19', - 'skia_rev': '424', - 'v8_rev': '3276', + 'ots_rev': '26', + 'skia_rev': '490', + 'v8_rev': '3781', # Windows: 'cygwin_rev': '11984', - 'ffmpeg_ia32_rev': '30374', + 'ffmpeg_ia32_rev': '34297', 'pthreads-win32_rev': '26716', 'python_24_rev': '22967', + 'nss_rev': '36871', } deps = { @@ -142,6 +143,10 @@ deps_os = { 'third_party/pthreads-win32': Var('chromium_deps_svn')+'/pthreads-win32@'+Var('pthreads-win32_rev'), + + # base.gypi depends on nss on Windows + 'third_party/nss': + Var('chromium_deps_svn')+'/nss@'+Var('nss_rev'), }, 'unix': { # Linux, actually. diff --git a/WebKit/chromium/WebKit.gyp b/WebKit/chromium/WebKit.gyp index 4f6d3f6..4b0ad2b 100644 --- a/WebKit/chromium/WebKit.gyp +++ b/WebKit/chromium/WebKit.gyp @@ -112,6 +112,7 @@ 'public/WebEventListener.h', 'public/WebFileChooserCompletion.h', 'public/WebFileChooserParams.h', + 'public/WebFileInfo.h', 'public/WebFindOptions.h', 'public/WebFrame.h', 'public/WebFrameClient.h', @@ -199,6 +200,8 @@ 'src/AssertMatchingEnums.cpp', 'src/AutocompletePopupMenuClient.cpp', 'src/AutocompletePopupMenuClient.h', + 'src/AutoFillPopupMenuClient.cpp', + 'src/AutoFillPopupMenuClient.h', 'src/BackForwardListClientImpl.cpp', 'src/BackForwardListClientImpl.h', 'src/BoundObject.cpp', @@ -257,6 +260,8 @@ 'src/StorageEventDispatcherImpl.h', 'src/StorageNamespaceProxy.cpp', 'src/StorageNamespaceProxy.h', + 'src/SuggestionsPopupMenuClient.cpp', + 'src/SuggestionsPopupMenuClient.h', 'src/TemporaryGlue.h', 'src/ToolsAgent.h', 'src/WebAccessibilityCache.cpp', @@ -453,6 +458,14 @@ 'tests/KURLTest.cpp', 'tests/RunAllTests.cpp', ], + 'conditions': [ + ['OS=="win"', { + 'sources': [ + 'tests/TransparencyWinTest.cpp', + 'tests/UniscribeHelperTest.cpp', + ], + }], + ], }, ], # targets } diff --git a/WebKit/chromium/WebKit.gypi b/WebKit/chromium/WebKit.gypi new file mode 100644 index 0000000..69b1479 --- /dev/null +++ b/WebKit/chromium/WebKit.gypi @@ -0,0 +1,67 @@ +# +# Copyright (C) 2010 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 +# 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. +# * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +# OWNER 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. +# + +{ + 'variables': { + # List of DevTools source files, ordered by dependencies. It is used both + # for copying them to resource dir, and for generating 'devtools.html' file. + 'devtools_js_files': [ + 'src/js/InspectorControllerImpl.js', + 'src/js/DebuggerAgent.js', + 'src/js/ProfilerAgent.js', + 'src/js/ProfilerProcessor.js', + 'src/js/HeapProfilerPanel.js', + 'src/js/DevTools.js', + 'src/js/DevToolsHostStub.js', + 'src/js/Tests.js', + ], + 'devtools_css_files': [ + 'src/js/devTools.css', + ], + 'devtools_image_files': [ + 'src/js/Images/segmentChromium.png', + 'src/js/Images/segmentHoverChromium.png', + 'src/js/Images/segmentHoverEndChromium.png', + 'src/js/Images/segmentSelectedChromium.png', + 'src/js/Images/segmentSelectedEndChromium.png', + 'src/js/Images/statusbarBackgroundChromium.png', + 'src/js/Images/statusbarBottomBackgroundChromium.png', + 'src/js/Images/statusbarButtonsChromium.png', + 'src/js/Images/statusbarMenuButtonChromium.png', + 'src/js/Images/statusbarMenuButtonSelectedChromium.png', + ], + }, +} + +# Local Variables: +# tab-width:2 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=2 shiftwidth=2: diff --git a/WebKit/chromium/features.gypi b/WebKit/chromium/features.gypi index da2386b..6091b8f 100644 --- a/WebKit/chromium/features.gypi +++ b/WebKit/chromium/features.gypi @@ -47,13 +47,14 @@ 'ENABLE_DASHBOARD_SUPPORT=0', 'ENABLE_DOM_STORAGE=1', 'ENABLE_GEOLOCATION=1', - 'ENABLE_JAVASCRIPT_DEBUGGER=0', + 'ENABLE_JAVASCRIPT_DEBUGGER=1', 'ENABLE_JSC_MULTIPLE_THREADS=0', 'ENABLE_ICONDATABASE=0', 'ENABLE_INDEXED_DATABASE=1', 'ENABLE_NOTIFICATIONS=1', 'ENABLE_OPENTYPE_SANITIZER=1', 'ENABLE_ORIENTATION_EVENTS=0', + 'ENABLE_RUBY=1', 'ENABLE_XHTMLMP=0', 'ENABLE_XSLT=1', 'ENABLE_XPATH=1', diff --git a/WebKit/chromium/public/WebContextMenuData.h b/WebKit/chromium/public/WebContextMenuData.h index 049da9c..5d67046 100644 --- a/WebKit/chromium/public/WebContextMenuData.h +++ b/WebKit/chromium/public/WebContextMenuData.h @@ -103,7 +103,8 @@ struct WebContextMenuData { CheckableMenuItemChecked = 0x2, }; - // Writing direction menu items. + // Writing direction menu items - values are unions of + // CheckableMenuItemFlags. // Currently only used on OS X. int writingDirectionDefault; int writingDirectionLeftToRight; diff --git a/WebKit/chromium/public/WebDatabase.h b/WebKit/chromium/public/WebDatabase.h index 179e828..108201d 100644 --- a/WebKit/chromium/public/WebDatabase.h +++ b/WebKit/chromium/public/WebDatabase.h @@ -72,6 +72,8 @@ public: WEBKIT_API static void updateDatabaseSize( const WebString& originIdentifier, const WebString& databaseName, unsigned long long databaseSize, unsigned long long spaceAvailable); + WEBKIT_API static void closeDatabaseImmediately( + const WebString& originIdentifier, const WebString& databaseName); #if WEBKIT_IMPLEMENTATION WebDatabase(const WTF::PassRefPtr<WebCore::Database>&); diff --git a/WebKit/chromium/public/WebDragData.h b/WebKit/chromium/public/WebDragData.h index 01582a9..0b861c8 100644 --- a/WebKit/chromium/public/WebDragData.h +++ b/WebKit/chromium/public/WebDragData.h @@ -74,6 +74,8 @@ public: WEBKIT_API WebURL downloadURL() const; WEBKIT_API void setDownloadURL(const WebURL&); + WEBKIT_API WebString downloadMetadata() const; + WEBKIT_API void setDownloadMetadata(const WebString&); WEBKIT_API WebString fileExtension() const; WEBKIT_API void setFileExtension(const WebString&); diff --git a/WebKit/chromium/public/WebFileInfo.h b/WebKit/chromium/public/WebFileInfo.h new file mode 100644 index 0000000..4590a30 --- /dev/null +++ b/WebKit/chromium/public/WebFileInfo.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2010 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 + * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 WebFileInfo_h +#define WebFileInfo_h + +namespace WebKit { + +struct WebFileInfo { + // The last modification time of the file, in seconds. + // The value 0.0 means that the time is not set. + double modificationTime; + + WebFileInfo() : modificationTime(0.0) { } +}; + +} // namespace WebKit + +#endif diff --git a/WebKit/chromium/public/WebHTTPBody.h b/WebKit/chromium/public/WebHTTPBody.h index 43f51a6..fcc44ff 100644 --- a/WebKit/chromium/public/WebHTTPBody.h +++ b/WebKit/chromium/public/WebHTTPBody.h @@ -32,6 +32,7 @@ #define WebHTTPBody_h #include "WebData.h" +#include "WebFileInfo.h" #include "WebNonCopyable.h" #include "WebString.h" @@ -50,6 +51,9 @@ public: enum { TypeData, TypeFile } type; WebData data; WebString filePath; + long long fileStart; + long long fileLength; // -1 means to the end of the file. + WebFileInfo fileInfo; }; ~WebHTTPBody() { reset(); } @@ -77,7 +81,9 @@ public: // Append to the list of elements. WEBKIT_API void appendData(const WebData&); - WEBKIT_API void appendFile(const WebString&); + WEBKIT_API void appendFile(const WebString&); // FIXME: to be removed. + // Passing -1 to fileLength means to the end of the file. + WEBKIT_API void appendFile(const WebString&, long long fileStart, long long fileLength, const WebFileInfo&); // Identifies a particular form submission instance. A value of 0 is // used to indicate an unspecified identifier. diff --git a/WebKit/chromium/public/WebInputElement.h b/WebKit/chromium/public/WebInputElement.h index 226624a..59643d1 100644 --- a/WebKit/chromium/public/WebInputElement.h +++ b/WebKit/chromium/public/WebInputElement.h @@ -81,11 +81,12 @@ namespace WebKit { Time, Week }; - + WEBKIT_API bool autoComplete() const; WEBKIT_API bool isEnabledFormControl() const; WEBKIT_API InputType inputType() const; WEBKIT_API WebString formControlType() const; + WEBKIT_API bool isActivatedSubmit() const; WEBKIT_API void setActivatedSubmit(bool); WEBKIT_API void setValue(const WebString& value); WEBKIT_API WebString value() const; @@ -97,7 +98,6 @@ namespace WebKit { // storing autofill data. This is either the field name or its id, an empty // string if it has no name and no id. WEBKIT_API WebString nameForAutofill() const; - }; } // namespace WebKit diff --git a/WebKit/chromium/public/WebKitClient.h b/WebKit/chromium/public/WebKitClient.h index fe6c801..fbaa218 100644 --- a/WebKit/chromium/public/WebKitClient.h +++ b/WebKit/chromium/public/WebKitClient.h @@ -59,7 +59,6 @@ class WebStorageNamespace; class WebThemeEngine; class WebURLLoader; struct WebCookie; -struct WebPluginInfo; template <typename T> class WebVector; class WebKitClient { diff --git a/WebKit/chromium/public/WebStorageArea.h b/WebKit/chromium/public/WebStorageArea.h index 19d98c6..5e2c11c 100644 --- a/WebKit/chromium/public/WebStorageArea.h +++ b/WebKit/chromium/public/WebStorageArea.h @@ -45,6 +45,12 @@ class WebStorageArea { public: virtual ~WebStorageArea() { } + enum Result { + ResultOK = 0, + ResultBlockedByQuota, + ResultBlockedByPolicy + }; + // The number of key/value pairs in the storage area. virtual unsigned length() = 0; @@ -57,10 +63,22 @@ public: // no entry for that key. virtual WebString getItem(const WebString& key) = 0; - // Set the value that corresponds to a specific key. QuotaException is set if - // the StorageArea would have exceeded its quota. The value is NOT set when there's - // an exception. url is the url that should be used if a storage event fires. - virtual void setItem(const WebString& key, const WebString& newValue, const WebURL& url, bool& quotaException, WebString& oldValue) = 0; + // Set the value that corresponds to a specific key. Result will either be ResultOK + // or some particular error. The value is NOT set when there's an error. url is the + // url that should be used if a storage event fires. + virtual void setItem(const WebString& key, const WebString& newValue, const WebURL& url, Result& result, WebString& oldValue) + { + bool quotaException = false; + setItem(key, newValue, url, quotaException, oldValue); + result = quotaException ? ResultBlockedByQuota : ResultOK; + } + // FIXME: Remove soon (once Chrome has rolled past this revision). + virtual void setItem(const WebString& key, const WebString& newValue, const WebURL& url, bool& quotaException, WebString& oldValue) + { + Result result; + setItem(key, newValue, url, result, oldValue); + quotaException = result != ResultOK; + } // Remove the value associated with a particular key. url is the url that should be used // if a storage event fires. diff --git a/WebKit/chromium/public/WebView.h b/WebKit/chromium/public/WebView.h index 7b3294f..99125d4 100644 --- a/WebKit/chromium/public/WebView.h +++ b/WebKit/chromium/public/WebView.h @@ -223,17 +223,35 @@ public: virtual WebAccessibilityObject accessibilityObject() = 0; - // Autofill ------------------------------------------------------------ + // AutoFill / Autocomplete --------------------------------------------- - // Notifies the WebView that autofill suggestions are available for a node. + // DEPRECATED: WebView::applyAutocompleteSuggestions is the new way to + // access this. virtual void applyAutofillSuggestions( const WebNode&, const WebVector<WebString>& suggestions, int defaultSuggestionIndex) = 0; - // Hides the autofill popup if any are showing. + // Notifies the WebView that AutoFill suggestions are available for a node. + virtual void applyAutoFillSuggestions( + const WebNode&, + const WebVector<WebString>& names, + const WebVector<WebString>& labels, + int defaultSuggestionIndex) = 0; + + // Notifies the WebView that Autocomplete suggestions are available for a + // node. + virtual void applyAutocompleteSuggestions( + const WebNode&, + const WebVector<WebString>& suggestions, + int defaultSuggestionIndex) = 0; + + // DEPRECATED: WebView::hideSuggestionsPopup is the new way to access this. virtual void hideAutofillPopup() = 0; + // Hides the suggestions popup if any are showing. + virtual void hideSuggestionsPopup() = 0; + // Context menu -------------------------------------------------------- diff --git a/WebKit/chromium/public/WebViewClient.h b/WebKit/chromium/public/WebViewClient.h index 964d382..4d272bb 100644 --- a/WebKit/chromium/public/WebViewClient.h +++ b/WebKit/chromium/public/WebViewClient.h @@ -252,6 +252,9 @@ public: // accessibility object. virtual void focusAccessibilityObject(const WebAccessibilityObject&) { } + // Notifies embedder that the state of an accessibility object has changed. + virtual void didChangeAccessibilityObjectState(const WebAccessibilityObject&) { } + // Developer tools ----------------------------------------------------- diff --git a/WebKit/chromium/src/AutoFillPopupMenuClient.cpp b/WebKit/chromium/src/AutoFillPopupMenuClient.cpp new file mode 100644 index 0000000..8e6cab4 --- /dev/null +++ b/WebKit/chromium/src/AutoFillPopupMenuClient.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2010 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 + * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 "AutoFillPopupMenuClient.h" + +#include "HTMLInputElement.h" +#include "WebString.h" +#include "WebVector.h" + +using namespace WebCore; + +namespace WebKit { + +unsigned AutoFillPopupMenuClient::getSuggestionsCount() const +{ + return m_names.size(); +} + +WebString AutoFillPopupMenuClient::getSuggestion(unsigned listIndex) const +{ + // FIXME: Modify the PopupMenu to add the label in gray right-justified. + ASSERT(listIndex >= 0 && listIndex < m_names.size()); + return m_names[listIndex] + String(" (") + m_labels[listIndex] + String(")"); +} + +void AutoFillPopupMenuClient::removeSuggestionAtIndex(unsigned listIndex) +{ + // FIXME: Do we want to remove AutoFill suggestions? + ASSERT(listIndex >= 0 && listIndex < m_names.size()); + m_names.remove(listIndex); + m_labels.remove(listIndex); +} + +void AutoFillPopupMenuClient::initialize( + HTMLInputElement* textField, + const WebVector<WebString>& names, + const WebVector<WebString>& labels, + int defaultSuggestionIndex) +{ + ASSERT(names.size() == labels.size()); + ASSERT(defaultSuggestionIndex < static_cast<int>(names.size())); + + // The suggestions must be set before initializing the + // SuggestionsPopupMenuClient. + setSuggestions(names, labels); + + SuggestionsPopupMenuClient::initialize(textField, defaultSuggestionIndex); +} + +void AutoFillPopupMenuClient::setSuggestions(const WebVector<WebString>& names, + const WebVector<WebString>& labels) +{ + ASSERT(names.size() == labels.size()); + + m_names.clear(); + m_labels.clear(); + for (size_t i = 0; i < names.size(); ++i) { + m_names.append(names[i]); + m_labels.append(labels[i]); + } + + // Try to preserve selection if possible. + if (getSelectedIndex() >= static_cast<int>(names.size())) + setSelectedIndex(-1); +} + +} // namespace WebKit diff --git a/WebKit/chromium/src/AutoFillPopupMenuClient.h b/WebKit/chromium/src/AutoFillPopupMenuClient.h new file mode 100644 index 0000000..fe11334 --- /dev/null +++ b/WebKit/chromium/src/AutoFillPopupMenuClient.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2010 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 + * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 AutoFillPopupMenuClient_h +#define AutoFillPopupMenuClient_h + +#include "SuggestionsPopupMenuClient.h" + +namespace WebCore { +class HTMLInputElement; +} + +namespace WebKit { +class WebString; +template <typename T> class WebVector; + +// The AutoFill suggestions popup menu client, used to display name suggestions +// with right-justified labels. +class AutoFillPopupMenuClient : public SuggestionsPopupMenuClient { +public: + // SuggestionsPopupMenuClient implementation: + virtual unsigned getSuggestionsCount() const; + virtual WebString getSuggestion(unsigned listIndex) const; + virtual void removeSuggestionAtIndex(unsigned listIndex); + + void initialize(WebCore::HTMLInputElement*, + const WebVector<WebString>& names, + const WebVector<WebString>& labels, + int defaultSuggestionIndex); + + void setSuggestions(const WebVector<WebString>& names, + const WebVector<WebString>& labels); + +private: + Vector<WebCore::String> m_names; + Vector<WebCore::String> m_labels; +}; + +<<<<<<< HEAD:WebCore/bindings/v8/RuntimeEnabledFeatures.cpp +bool RuntimeEnabledFeatures::isLocalStorageEnabled = true; +bool RuntimeEnabledFeatures::isSessionStorageEnabled = true; +bool RuntimeEnabledFeatures::isNotificationsEnabled = false; +#if PLATFORM(ANDROID) +// These should default to true, to match the behavior with JSC +bool RuntimeEnabledFeatures::isApplicationCacheEnabled = true; +bool RuntimeEnabledFeatures::isGeolocationEnabled = true; +#endif +bool RuntimeEnabledFeatures::isIndexedDatabaseEnabled = false; +======= +} // namespace WebKit +>>>>>>> webkit.org at r54731:WebKit/chromium/src/AutoFillPopupMenuClient.h + +#endif diff --git a/WebKit/chromium/src/AutocompletePopupMenuClient.cpp b/WebKit/chromium/src/AutocompletePopupMenuClient.cpp index 62d4dff..9620ffc 100644 --- a/WebKit/chromium/src/AutocompletePopupMenuClient.cpp +++ b/WebKit/chromium/src/AutocompletePopupMenuClient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2010 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 @@ -31,27 +31,29 @@ #include "config.h" #include "AutocompletePopupMenuClient.h" -#include "CSSStyleSelector.h" -#include "CSSValueKeywords.h" -#include "FrameView.h" #include "HTMLInputElement.h" -#include "RenderTheme.h" +#include "WebString.h" #include "WebVector.h" -#include "WebViewImpl.h" using namespace WebCore; namespace WebKit { -AutocompletePopupMenuClient::AutocompletePopupMenuClient(WebViewImpl* webView) - : m_textField(0) - , m_selectedIndex(0) - , m_webView(webView) +unsigned AutocompletePopupMenuClient::getSuggestionsCount() const { + return m_suggestions.size(); } -AutocompletePopupMenuClient::~AutocompletePopupMenuClient() +WebString AutocompletePopupMenuClient::getSuggestion(unsigned listIndex) const { + ASSERT(listIndex >= 0 && listIndex < m_suggestions.size()); + return m_suggestions[listIndex]; +} + +void AutocompletePopupMenuClient::removeSuggestionAtIndex(unsigned listIndex) +{ + ASSERT(listIndex >= 0 && listIndex < m_suggestions.size()); + m_suggestions.remove(listIndex); } void AutocompletePopupMenuClient::initialize( @@ -60,90 +62,12 @@ void AutocompletePopupMenuClient::initialize( int defaultSuggestionIndex) { ASSERT(defaultSuggestionIndex < static_cast<int>(suggestions.size())); - m_textField = textField; - m_selectedIndex = defaultSuggestionIndex; - setSuggestions(suggestions); - - FontDescription fontDescription; - m_webView->theme()->systemFont(CSSValueWebkitControl, fontDescription); - // Use a smaller font size to match IE/Firefox. - // FIXME: http://crbug.com/7376 use the system size instead of a - // fixed font size value. - fontDescription.setComputedSize(12.0); - Font font(fontDescription, 0, 0); - font.update(textField->document()->styleSelector()->fontSelector()); - // The direction of text in popup menu is set the same as the direction of - // the input element: textField. - m_style.set(new PopupMenuStyle(Color::black, Color::white, font, true, - Length(WebCore::Fixed), - textField->renderer()->style()->direction())); -} - -void AutocompletePopupMenuClient::valueChanged(unsigned listIndex, bool fireEvents) -{ - m_textField->setValue(m_suggestions[listIndex]); - EditorClientImpl* editor = - static_cast<EditorClientImpl*>(m_webView->page()->editorClient()); - ASSERT(editor); - editor->onAutofillSuggestionAccepted( - static_cast<HTMLInputElement*>(m_textField.get())); -} - -String AutocompletePopupMenuClient::itemText(unsigned listIndex) const -{ - return m_suggestions[listIndex]; -} - -PopupMenuStyle AutocompletePopupMenuClient::itemStyle(unsigned listIndex) const -{ - return *m_style; -} - -PopupMenuStyle AutocompletePopupMenuClient::menuStyle() const -{ - return *m_style; -} - -int AutocompletePopupMenuClient::clientPaddingLeft() const -{ - // Bug http://crbug.com/7708 seems to indicate the style can be 0. - RenderStyle* style = textFieldStyle(); - return style ? m_webView->theme()->popupInternalPaddingLeft(style) : 0; -} -int AutocompletePopupMenuClient::clientPaddingRight() const -{ - // Bug http://crbug.com/7708 seems to indicate the style can be 0. - RenderStyle* style = textFieldStyle(); - return style ? m_webView->theme()->popupInternalPaddingRight(style) : 0; -} - -void AutocompletePopupMenuClient::popupDidHide() -{ - m_webView->autoCompletePopupDidHide(); -} - -void AutocompletePopupMenuClient::setTextFromItem(unsigned listIndex) -{ - m_textField->setValue(m_suggestions[listIndex]); -} - -FontSelector* AutocompletePopupMenuClient::fontSelector() const -{ - return m_textField->document()->styleSelector()->fontSelector(); -} - -HostWindow* AutocompletePopupMenuClient::hostWindow() const -{ - return m_textField->document()->view()->hostWindow(); -} + // The suggestions must be set before initializing the + // SuggestionsPopupMenuClient. + setSuggestions(suggestions); -PassRefPtr<Scrollbar> AutocompletePopupMenuClient::createScrollbar( - ScrollbarClient* client, - ScrollbarOrientation orientation, - ScrollbarControlSize size) -{ - return Scrollbar::createNativeScrollbar(client, orientation, size); + SuggestionsPopupMenuClient::initialize(textField, defaultSuggestionIndex); } void AutocompletePopupMenuClient::setSuggestions(const WebVector<WebString>& suggestions) @@ -151,28 +75,10 @@ void AutocompletePopupMenuClient::setSuggestions(const WebVector<WebString>& sug m_suggestions.clear(); for (size_t i = 0; i < suggestions.size(); ++i) m_suggestions.append(suggestions[i]); - // Try to preserve selection if possible. - if (m_selectedIndex >= static_cast<int>(suggestions.size())) - m_selectedIndex = -1; -} -void AutocompletePopupMenuClient::removeItemAtIndex(int index) -{ - ASSERT(index >= 0 && index < static_cast<int>(m_suggestions.size())); - m_suggestions.remove(index); -} - -RenderStyle* AutocompletePopupMenuClient::textFieldStyle() const -{ - RenderStyle* style = m_textField->computedStyle(); - if (!style) { - // It seems we can only have a 0 style in a TextField if the - // node is detached, in which case we the popup shoud not be - // showing. Please report this in http://crbug.com/7708 and - // include the page you were visiting. - ASSERT_NOT_REACHED(); - } - return style; + // Try to preserve selection if possible. + if (getSelectedIndex() >= static_cast<int>(suggestions.size())) + setSelectedIndex(-1); } } // namespace WebKit diff --git a/WebKit/chromium/src/AutocompletePopupMenuClient.h b/WebKit/chromium/src/AutocompletePopupMenuClient.h index ad24e54..16a3771 100644 --- a/WebKit/chromium/src/AutocompletePopupMenuClient.h +++ b/WebKit/chromium/src/AutocompletePopupMenuClient.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2010 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 @@ -28,69 +28,38 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "PopupMenuClient.h" +#ifndef AutocompletePopupMenuClient_h +#define AutocompletePopupMenuClient_h + +#include "SuggestionsPopupMenuClient.h" namespace WebCore { class HTMLInputElement; -class PopupMenuStyle; -class RenderStyle; } namespace WebKit { class WebString; -class WebViewImpl; template <typename T> class WebVector; -// AutocompletePopupMenuClient -class AutocompletePopupMenuClient : public WebCore::PopupMenuClient { +// The Autocomplete suggestions popup menu client, used to display a list of +// autocomplete suggestions. +class AutocompletePopupMenuClient : public SuggestionsPopupMenuClient { public: - AutocompletePopupMenuClient(WebViewImpl* webview); - ~AutocompletePopupMenuClient(); + // SuggestionsPopupMenuClient implementation: + virtual unsigned getSuggestionsCount() const; + virtual WebString getSuggestion(unsigned listIndex) const; + virtual void removeSuggestionAtIndex(unsigned listIndex); void initialize(WebCore::HTMLInputElement*, const WebVector<WebString>& suggestions, int defaultSuggestionIndex); - WebCore::HTMLInputElement* textField() const { return m_textField.get(); } - void setSuggestions(const WebVector<WebString>&); - void removeItemAtIndex(int index); - - // WebCore::PopupMenuClient methods: - virtual void valueChanged(unsigned listIndex, bool fireEvents = true); - virtual WebCore::String itemText(unsigned listIndex) const; - virtual WebCore::String itemToolTip(unsigned lastIndex) const { return WebCore::String(); } - virtual bool itemIsEnabled(unsigned listIndex) const { return true; } - virtual WebCore::PopupMenuStyle itemStyle(unsigned listIndex) const; - virtual WebCore::PopupMenuStyle menuStyle() const; - virtual int clientInsetLeft() const { return 0; } - virtual int clientInsetRight() const { return 0; } - virtual int clientPaddingLeft() const; - virtual int clientPaddingRight() const; - virtual int listSize() const { return m_suggestions.size(); } - virtual int selectedIndex() const { return m_selectedIndex; } - virtual void popupDidHide(); - virtual bool itemIsSeparator(unsigned listIndex) const { return false; } - virtual bool itemIsLabel(unsigned listIndex) const { return false; } - virtual bool itemIsSelected(unsigned listIndex) const { return false; } - virtual bool shouldPopOver() const { return false; } - virtual bool valueShouldChangeOnHotTrack() const { return false; } - virtual void setTextFromItem(unsigned listIndex); - virtual WebCore::FontSelector* fontSelector() const; - virtual WebCore::HostWindow* hostWindow() const; - virtual PassRefPtr<WebCore::Scrollbar> createScrollbar( - WebCore::ScrollbarClient* client, - WebCore::ScrollbarOrientation orientation, - WebCore::ScrollbarControlSize size); private: - WebCore::RenderStyle* textFieldStyle() const; - - RefPtr<WebCore::HTMLInputElement> m_textField; Vector<WebCore::String> m_suggestions; - int m_selectedIndex; - WebViewImpl* m_webView; - OwnPtr<WebCore::PopupMenuStyle> m_style; }; } // namespace WebKit + +#endif diff --git a/WebKit/chromium/src/BackForwardListClientImpl.cpp b/WebKit/chromium/src/BackForwardListClientImpl.cpp index 8feae32..f5b04ab 100644 --- a/WebKit/chromium/src/BackForwardListClientImpl.cpp +++ b/WebKit/chromium/src/BackForwardListClientImpl.cpp @@ -90,7 +90,7 @@ HistoryItem* BackForwardListClientImpl::currentItem() HistoryItem* BackForwardListClientImpl::itemAtIndex(int index) { - if (!m_webView->client()) + if (!m_webView->client() || index > forwardListCount() || -index > backListCount()) return 0; // Since we don't keep the entire back/forward list, we have no way to diff --git a/WebKit/chromium/src/ChromeClientImpl.cpp b/WebKit/chromium/src/ChromeClientImpl.cpp index 9079094..ce2f00c 100644 --- a/WebKit/chromium/src/ChromeClientImpl.cpp +++ b/WebKit/chromium/src/ChromeClientImpl.cpp @@ -659,6 +659,14 @@ void ChromeClientImpl::getPopupMenuInfo(PopupContainer* popupContainer, info->items.swap(outputItems); } +void ChromeClientImpl::didChangeAccessibilityObjectState(AccessibilityObject* obj) +{ + // Alert assistive technology about the accessibility object state change + if (obj) + m_webView->client()->didChangeAccessibilityObjectState(WebAccessibilityObject(obj)); +} + + #if ENABLE(NOTIFICATIONS) NotificationPresenter* ChromeClientImpl::notificationPresenter() const { diff --git a/WebKit/chromium/src/ChromeClientImpl.h b/WebKit/chromium/src/ChromeClientImpl.h index 5a1e9cc..9e8c2e3 100644 --- a/WebKit/chromium/src/ChromeClientImpl.h +++ b/WebKit/chromium/src/ChromeClientImpl.h @@ -34,6 +34,7 @@ #include "ChromeClientChromium.h" namespace WebCore { +class AccessibilityObject; class HTMLParserQuirks; class PopupContainer; class SecurityOrigin; @@ -132,6 +133,7 @@ public: const WebCore::IntRect& bounds, bool activatable, bool handleExternally); + virtual void didChangeAccessibilityObjectState(WebCore::AccessibilityObject*); // ChromeClientImpl: void setCursor(const WebCursorInfo& cursor); diff --git a/WebKit/chromium/src/DebuggerAgent.h b/WebKit/chromium/src/DebuggerAgent.h index cac9686..17cde11 100644 --- a/WebKit/chromium/src/DebuggerAgent.h +++ b/WebKit/chromium/src/DebuggerAgent.h @@ -37,7 +37,10 @@ namespace WebKit { #define DEBUGGER_AGENT_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3, METHOD4, METHOD5) \ /* Requests global context id of the inspected tab. */ \ - METHOD0(getContextId) + METHOD0(getContextId) \ + \ + /* Request v8 to process all debug commands in the queue. */ \ + METHOD0(processDebugCommands) DEFINE_RPC_CLASS(DebuggerAgent, DEBUGGER_AGENT_STRUCT) diff --git a/WebKit/chromium/src/DebuggerAgentImpl.cpp b/WebKit/chromium/src/DebuggerAgentImpl.cpp index 0c3d1ea..d592710 100644 --- a/WebKit/chromium/src/DebuggerAgentImpl.cpp +++ b/WebKit/chromium/src/DebuggerAgentImpl.cpp @@ -51,7 +51,6 @@ using WebCore::Frame; using WebCore::Page; using WebCore::String; using WebCore::V8ClassIndex; -using WebCore::V8Custom; using WebCore::V8DOMWindow; using WebCore::V8DOMWrapper; using WebCore::V8Proxy; @@ -80,6 +79,12 @@ void DebuggerAgentImpl::getContextId() m_delegate->setContextId(m_webdevtoolsAgent->hostId()); } +void DebuggerAgentImpl::processDebugCommands() +{ + DebuggerAgentManager::UtilityContextScope utilityScope; + v8::Debug::ProcessDebugMessages(); +} + void DebuggerAgentImpl::debuggerOutput(const String& command) { m_delegate->debuggerOutput(command); @@ -90,13 +95,21 @@ void DebuggerAgentImpl::debuggerOutput(const String& command) void DebuggerAgentImpl::createUtilityContext(Frame* frame, v8::Persistent<v8::Context>* context) { v8::HandleScope scope; + bool canExecuteScripts = frame->script()->canExecuteScripts(); // Set up the DOM window as the prototype of the new global object. v8::Handle<v8::Context> windowContext = V8Proxy::context(frame); - v8::Handle<v8::Object> windowGlobal = windowContext->Global(); - v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, windowGlobal); - - ASSERT(V8DOMWindow::toNative(windowWrapper) == frame->domWindow()); + v8::Handle<v8::Object> windowGlobal; + v8::Handle<v8::Object> windowWrapper; + if (canExecuteScripts) { + // FIXME: This check prevents renderer from crashing, while providing limited capabilities for + // DOM inspection, Resources tracking, no scripts support, some timeline profiling. Console will + // result in exceptions for each evaluation. There is still some work that needs to be done in + // order to polish the script-less experience. + windowGlobal = windowContext->Global(); + windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), windowGlobal); + ASSERT(V8DOMWindow::toNative(windowWrapper) == frame->domWindow()); + } v8::Handle<v8::ObjectTemplate> globalTemplate = v8::ObjectTemplate::New(); @@ -121,11 +134,13 @@ void DebuggerAgentImpl::createUtilityContext(Frame* frame, v8::Persistent<v8::Co v8::Handle<v8::Object> global = (*context)->Global(); v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__"); - global->Set(implicitProtoString, windowWrapper); + if (canExecuteScripts) + global->Set(implicitProtoString, windowWrapper); // Give the code running in the new context a way to get access to the // original context. - global->Set(v8::String::New("contentWindow"), windowGlobal); + if (canExecuteScripts) + global->Set(v8::String::New("contentWindow"), windowGlobal); } String DebuggerAgentImpl::executeUtilityFunction( @@ -180,22 +195,6 @@ String DebuggerAgentImpl::executeUtilityFunction( return WebCore::toWebCoreStringWithNullCheck(resObj); } -void DebuggerAgentImpl::executeVoidJavaScript(v8::Handle<v8::Context> context) -{ - v8::HandleScope scope; - ASSERT(!context.IsEmpty()); - v8::Context::Scope contextScope(context); - DebuggerAgentManager::UtilityContextScope utilityScope; - - v8::Handle<v8::Value> function = - context->Global()->Get(v8::String::New("devtools$$void")); - ASSERT(function->IsFunction()); - v8::Handle<v8::Value> args[] = { - v8::Local<v8::Value>() - }; - v8::Handle<v8::Function>::Cast(function)->Call(context->Global(), 0, args); -} - WebCore::Page* DebuggerAgentImpl::page() { return m_webViewImpl->page(); diff --git a/WebKit/chromium/src/DebuggerAgentImpl.h b/WebKit/chromium/src/DebuggerAgentImpl.h index 65dc14c..6eaf576 100644 --- a/WebKit/chromium/src/DebuggerAgentImpl.h +++ b/WebKit/chromium/src/DebuggerAgentImpl.h @@ -62,6 +62,7 @@ public: // DebuggerAgent implementation. virtual void getContextId(); + virtual void processDebugCommands(); void debuggerOutput(const WebCore::String& out); @@ -81,10 +82,6 @@ public: bool async, WebCore::String* exception); - // Executes a no-op function in the utility context. We don't use - // executeUtilityFunction for that to avoid script evaluation leading to - // undesirable AfterCompile events. - void executeVoidJavaScript(v8::Handle<v8::Context> context); WebCore::Page* page(); WebDevToolsAgentImpl* webdevtoolsAgent() { return m_webdevtoolsAgent; } diff --git a/WebKit/chromium/src/EditorClientImpl.cpp b/WebKit/chromium/src/EditorClientImpl.cpp index e035e6a..d5bddc5 100644 --- a/WebKit/chromium/src/EditorClientImpl.cpp +++ b/WebKit/chromium/src/EditorClientImpl.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2006, 2007 Apple, Inc. All rights reserved. - * Copyright (C) 2009 Google, Inc. All rights reserved. + * Copyright (C) 2010 Google, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -654,7 +654,7 @@ void EditorClientImpl::textFieldDidEndEditing(Element* element) m_autofillTimer.stop(); // Hide any showing popup. - m_webView->hideAutoCompletePopup(); + m_webView->hideSuggestionsPopup(); if (!m_webView->client()) return; // The page is getting closed, don't fill the password. @@ -748,7 +748,7 @@ void EditorClientImpl::doAutofill(Timer<EditorClientImpl>* timer) && inputElement->selectionEnd() == static_cast<int>(value.length()); if ((!args->autofillOnEmptyValue && value.isEmpty()) || !isCaretAtEnd) { - m_webView->hideAutoCompletePopup(); + m_webView->hideSuggestionsPopup(); return; } diff --git a/WebKit/chromium/src/GraphicsContext3D.cpp b/WebKit/chromium/src/GraphicsContext3D.cpp index 7fe31b0..83574da 100644 --- a/WebKit/chromium/src/GraphicsContext3D.cpp +++ b/WebKit/chromium/src/GraphicsContext3D.cpp @@ -275,14 +275,6 @@ private: , m_glXGetCurrentContext(getCurrentContext) { } - - static void* tryLoad(const char* libName) - { - // We use RTLD_GLOBAL semantics so that GLEW initialization works; - // GLEW expects to be able to open the current process's handle - // and do dlsym's of GL entry points from there. - return dlopen(libName, RTLD_LAZY | RTLD_GLOBAL); - } }; static GLConnection* s_gl; @@ -304,22 +296,13 @@ GraphicsContext3DInternal::GLConnection* GraphicsContext3DInternal::GLConnection return 0; } - void* libGL = 0; - const char* libNames[] = { - "/usr/lib/libGL.so.1", - "/usr/lib32/libGL.so.1", - "/usr/lib64/libGL.so.1", - }; - for (int i = 0; i < sizeof(libNames) / sizeof(const char*); i++) { - libGL = tryLoad(libNames[i]); - if (libGL) - break; - } + // We use RTLD_GLOBAL semantics so that GLEW initialization works; + // GLEW expects to be able to open the current process's handle + // and do dlsym's of GL entry points from there. + void* libGL = dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL); if (!libGL) { - printf("GraphicsContext3D: error opening libGL.so.1\n"); - printf("GraphicsContext3D: tried:\n"); - for (int i = 0; i < sizeof(libNames) / sizeof(const char*); i++) - printf(" %s\n", libNames[i]); + XCloseDisplay(dpy); + printf("GraphicsContext3D: error opening libGL.so.1: %s\n", dlerror()); return 0; } @@ -726,7 +709,6 @@ void GraphicsContext3DInternal::reshape(int width, int height) #endif // FLIP_FRAMEBUFFER_VERTICALLY glClear(GL_COLOR_BUFFER_BIT); - viewportImpl(0, 0, width, height); #if PLATFORM(CG) // Need to reallocate the client-side backing store. diff --git a/WebKit/chromium/src/SuggestionsPopupMenuClient.cpp b/WebKit/chromium/src/SuggestionsPopupMenuClient.cpp new file mode 100644 index 0000000..b4a77a3 --- /dev/null +++ b/WebKit/chromium/src/SuggestionsPopupMenuClient.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2010 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 + * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 "SuggestionsPopupMenuClient.h" + +#include "CSSStyleSelector.h" +#include "CSSValueKeywords.h" +#include "Chrome.h" +#include "FrameView.h" +#include "HTMLInputElement.h" +#include "RenderTheme.h" +#include "WebViewImpl.h" + +using namespace WebCore; + +namespace WebKit { + +SuggestionsPopupMenuClient::SuggestionsPopupMenuClient() + : m_textField(0) + , m_selectedIndex(0) +{ +} + +SuggestionsPopupMenuClient::~SuggestionsPopupMenuClient() +{ +} + +// FIXME: Implement this per-derived class? +void SuggestionsPopupMenuClient::valueChanged(unsigned listIndex, bool fireEvents) +{ + m_textField->setValue(getSuggestion(listIndex)); + + WebViewImpl* webView = getWebView(); + if (!webView) + return; + + EditorClientImpl* editor = + static_cast<EditorClientImpl*>(webView->page()->editorClient()); + ASSERT(editor); + editor->onAutofillSuggestionAccepted( + static_cast<HTMLInputElement*>(m_textField.get())); +} + +String SuggestionsPopupMenuClient::itemText(unsigned listIndex) const +{ + return getSuggestion(listIndex); +} + +PopupMenuStyle SuggestionsPopupMenuClient::itemStyle(unsigned listIndex) const +{ + return *m_style; +} + +PopupMenuStyle SuggestionsPopupMenuClient::menuStyle() const +{ + return *m_style; +} + +int SuggestionsPopupMenuClient::clientPaddingLeft() const +{ + // Bug http://crbug.com/7708 seems to indicate the style can be 0. + RenderStyle* style = textFieldStyle(); + if (!style) + return 0; + + return RenderTheme::defaultTheme()->popupInternalPaddingLeft(style); +} + +int SuggestionsPopupMenuClient::clientPaddingRight() const +{ + // Bug http://crbug.com/7708 seems to indicate the style can be 0. + RenderStyle* style = textFieldStyle(); + if (!style) + return 0; + + return RenderTheme::defaultTheme()->popupInternalPaddingRight(style); +} + +void SuggestionsPopupMenuClient::popupDidHide() +{ + WebViewImpl* webView = getWebView(); + if (webView) + webView->suggestionsPopupDidHide(); +} + +void SuggestionsPopupMenuClient::setTextFromItem(unsigned listIndex) +{ + m_textField->setValue(getSuggestion(listIndex)); +} + +FontSelector* SuggestionsPopupMenuClient::fontSelector() const +{ + return m_textField->document()->styleSelector()->fontSelector(); +} + +HostWindow* SuggestionsPopupMenuClient::hostWindow() const +{ + return m_textField->document()->view()->hostWindow(); +} + +PassRefPtr<Scrollbar> SuggestionsPopupMenuClient::createScrollbar( + ScrollbarClient* client, + ScrollbarOrientation orientation, + ScrollbarControlSize size) +{ + return Scrollbar::createNativeScrollbar(client, orientation, size); +} + +RenderStyle* SuggestionsPopupMenuClient::textFieldStyle() const +{ + RenderStyle* style = m_textField->computedStyle(); + if (!style) { + // It seems we can only have a 0 style in a TextField if the + // node is detached, in which case we the popup shoud not be + // showing. Please report this in http://crbug.com/7708 and + // include the page you were visiting. + ASSERT_NOT_REACHED(); + } + return style; +} + +void SuggestionsPopupMenuClient::initialize(HTMLInputElement* textField, + int defaultSuggestionIndex) +{ + m_textField = textField; + m_selectedIndex = defaultSuggestionIndex; + + FontDescription fontDescription; + RenderTheme::defaultTheme()->systemFont(CSSValueWebkitControl, + fontDescription); + + // Use a smaller font size to match IE/Firefox. + // FIXME: http://crbug.com/7376 use the system size instead of a + // fixed font size value. + fontDescription.setComputedSize(12.0); + Font font(fontDescription, 0, 0); + font.update(textField->document()->styleSelector()->fontSelector()); + // The direction of text in popup menu is set the same as the direction of + // the input element: textField. + m_style.set(new PopupMenuStyle(Color::black, Color::white, font, true, + Length(WebCore::Fixed), + textField->renderer()->style()->direction())); +} + +WebViewImpl* SuggestionsPopupMenuClient::getWebView() const +{ + Frame* frame = m_textField->document()->frame(); + if (!frame) + return 0; + + Page* page = frame->page(); + if (!page) + return 0; + + return static_cast<ChromeClientImpl*>(page->chrome()->client())->webView(); +} + +} // namespace WebKit diff --git a/WebKit/chromium/src/SuggestionsPopupMenuClient.h b/WebKit/chromium/src/SuggestionsPopupMenuClient.h new file mode 100644 index 0000000..edc4c09 --- /dev/null +++ b/WebKit/chromium/src/SuggestionsPopupMenuClient.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2010 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 + * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 "PopupMenuClient.h" + +#ifndef SuggestionsPopupMenuClient_h +#define SuggestionsPopupMenuClient_h + +namespace WebCore { +class HTMLInputElement; +class PopupMenuStyle; +class RenderStyle; +} + +namespace WebKit { +class WebString; +class WebViewImpl; +template <typename T> class WebVector; + +// The Suggestions popup menu client, used to display a list of suggestions. +class SuggestionsPopupMenuClient : public WebCore::PopupMenuClient { +public: + SuggestionsPopupMenuClient(); + virtual ~SuggestionsPopupMenuClient(); + + // Returns the number of suggestions available. + virtual unsigned getSuggestionsCount() const = 0; + + // Returns the suggestion at |listIndex|. + virtual WebString getSuggestion(unsigned listIndex) const = 0; + + // Removes the suggestion at |listIndex| from the list of suggestions. + virtual void removeSuggestionAtIndex(unsigned listIndex) = 0; + + // WebCore::PopupMenuClient methods: + virtual void valueChanged(unsigned listIndex, bool fireEvents = true); + virtual WebCore::String itemText(unsigned listIndex) const; + virtual WebCore::String itemToolTip(unsigned lastIndex) const { return WebCore::String(); } + virtual bool itemIsEnabled(unsigned listIndex) const { return true; } + virtual WebCore::PopupMenuStyle itemStyle(unsigned listIndex) const; + virtual WebCore::PopupMenuStyle menuStyle() const; + virtual int clientInsetLeft() const { return 0; } + virtual int clientInsetRight() const { return 0; } + virtual int clientPaddingLeft() const; + virtual int clientPaddingRight() const; + virtual int listSize() const { return getSuggestionsCount(); } + virtual int selectedIndex() const { return m_selectedIndex; } + virtual void popupDidHide(); + virtual bool itemIsSeparator(unsigned listIndex) const { return false; } + virtual bool itemIsLabel(unsigned listIndex) const { return false; } + virtual bool itemIsSelected(unsigned listIndex) const { return false; } + virtual bool shouldPopOver() const { return false; } + virtual bool valueShouldChangeOnHotTrack() const { return false; } + virtual void setTextFromItem(unsigned listIndex); + virtual WebCore::FontSelector* fontSelector() const; + virtual WebCore::HostWindow* hostWindow() const; + virtual PassRefPtr<WebCore::Scrollbar> createScrollbar( + WebCore::ScrollbarClient* client, + WebCore::ScrollbarOrientation orientation, + WebCore::ScrollbarControlSize size); + +protected: + void initialize(WebCore::HTMLInputElement* textField, + int defaultSuggestionIndex); + + int getSelectedIndex() const { return m_selectedIndex; } + void setSelectedIndex(int index) { m_selectedIndex = index; } + + WebViewImpl* getWebView() const; + WebCore::HTMLInputElement* getTextField() const { return m_textField.get(); } + +private: + WebCore::RenderStyle* textFieldStyle() const; + + RefPtr<WebCore::HTMLInputElement> m_textField; + int m_selectedIndex; + OwnPtr<WebCore::PopupMenuStyle> m_style; +}; + +} // namespace WebKit + +#endif diff --git a/WebKit/chromium/src/ToolsAgent.h b/WebKit/chromium/src/ToolsAgent.h index fd1fcb7..ab48153 100644 --- a/WebKit/chromium/src/ToolsAgent.h +++ b/WebKit/chromium/src/ToolsAgent.h @@ -38,9 +38,6 @@ namespace WebKit { // Tools agent provides API for enabling / disabling other agents as well as // API for auxiliary UI functions such as dom elements highlighting. #define TOOLS_AGENT_STRUCT(METHOD0, METHOD1, METHOD2, METHOD3, METHOD4, METHOD5) \ - /* Request the agent to to run a no-op JavaScript function to trigger v8 execution. */ \ - METHOD0(executeVoidJavaScript) \ - \ /* Dispatches given function on the InspectorController object */ \ METHOD3(dispatchOnInspectorController, int /* call_id */, \ String /* function_name */, String /* json_args */) \ diff --git a/WebKit/chromium/src/WebDatabase.cpp b/WebKit/chromium/src/WebDatabase.cpp index 2cd36b6..50b9220 100644 --- a/WebKit/chromium/src/WebDatabase.cpp +++ b/WebKit/chromium/src/WebDatabase.cpp @@ -32,7 +32,9 @@ #include "WebDatabase.h" #include "Database.h" +#include "DatabaseTask.h" #include "DatabaseThread.h" +#include "DatabaseTracker.h" #include "Document.h" #include "KURL.h" #include "QuotaTracker.h" @@ -106,6 +108,22 @@ void WebDatabase::updateDatabaseSize( originIdentifier, databaseName, databaseSize, spaceAvailable); } +void WebDatabase::closeDatabaseImmediately(const WebString& originIdentifier, const WebString& databaseName) +{ + HashSet<RefPtr<Database> > databaseHandles; + PassRefPtr<SecurityOrigin> originPrp(*WebSecurityOrigin::createFromDatabaseIdentifier(originIdentifier)); + RefPtr<SecurityOrigin> origin = originPrp; + DatabaseTracker::tracker().getOpenDatabases(origin.get(), databaseName, &databaseHandles); + for (HashSet<RefPtr<Database> >::iterator it = databaseHandles.begin(); it != databaseHandles.end(); ++it) { + Database* database = it->get(); + DatabaseThread* databaseThread = database->scriptExecutionContext()->databaseThread(); + if (databaseThread && !databaseThread->terminationRequested()) { + database->stop(); + databaseThread->scheduleTask(DatabaseCloseTask::create(database, 0)); + } + } +} + WebDatabase::WebDatabase(const WTF::PassRefPtr<Database>& database) : m_private(static_cast<WebDatabasePrivate*>(database.releaseRef())) { diff --git a/WebKit/chromium/src/WebDevToolsAgentImpl.cpp b/WebKit/chromium/src/WebDevToolsAgentImpl.cpp index 9d386f3..9ce35b4 100644 --- a/WebKit/chromium/src/WebDevToolsAgentImpl.cpp +++ b/WebKit/chromium/src/WebDevToolsAgentImpl.cpp @@ -52,6 +52,7 @@ #include "ScriptState.h" #include "ScriptValue.h" #include "V8Binding.h" +#include "V8InspectorBackend.h" #include "V8Proxy.h" #include "V8Utilities.h" #include "WebDataSource.h" @@ -87,6 +88,7 @@ using WebCore::ScriptValue; using WebCore::String; using WebCore::V8ClassIndex; using WebCore::V8DOMWrapper; +using WebCore::V8InspectorBackend; using WebCore::V8Proxy; namespace WebKit { @@ -263,11 +265,6 @@ void WebDevToolsAgentImpl::dispatchOnInjectedScript(int callId, int injectedScri async); } -void WebDevToolsAgentImpl::executeVoidJavaScript() -{ - m_debuggerAgentImpl->executeVoidJavaScript(m_utilityContext); -} - void WebDevToolsAgentImpl::dispatchMessageFromFrontend(const WebDevToolsMessageData& data) { if (ToolsAgentDispatch::dispatch(this, data)) @@ -351,7 +348,7 @@ void WebDevToolsAgentImpl::initDevToolsAgentHost() v8::Local<v8::Object> WebDevToolsAgentImpl::createInspectorBackendV8Wrapper() { V8ClassIndex::V8WrapperType descriptorType = V8ClassIndex::INSPECTORBACKEND; - v8::Handle<v8::Function> function = V8DOMWrapper::getTemplate(descriptorType)->GetFunction(); + v8::Handle<v8::Function> function = V8InspectorBackend::GetTemplate()->GetFunction(); if (function.IsEmpty()) { // Return if allocation failed. return v8::Local<v8::Object>(); diff --git a/WebKit/chromium/src/WebDevToolsAgentImpl.h b/WebKit/chromium/src/WebDevToolsAgentImpl.h index 3f5928b..1f81c6d 100644 --- a/WebKit/chromium/src/WebDevToolsAgentImpl.h +++ b/WebKit/chromium/src/WebDevToolsAgentImpl.h @@ -70,7 +70,6 @@ public: // ToolsAgent implementation. virtual void dispatchOnInspectorController(int callId, const WebCore::String& functionName, const WebCore::String& jsonArgs); virtual void dispatchOnInjectedScript(int callId, int injectedScriptId, const WebCore::String& functionName, const WebCore::String& jsonArgs, bool async); - virtual void executeVoidJavaScript(); // WebDevToolsAgentPrivate implementation. virtual void didClearWindowObject(WebFrameImpl* frame); diff --git a/WebKit/chromium/src/WebDevToolsFrontendImpl.cpp b/WebKit/chromium/src/WebDevToolsFrontendImpl.cpp index 0a92319..89fa6e7 100644 --- a/WebKit/chromium/src/WebDevToolsFrontendImpl.cpp +++ b/WebKit/chromium/src/WebDevToolsFrontendImpl.cpp @@ -52,7 +52,6 @@ #include "Settings.h" #include "ToolsAgent.h" #include "V8Binding.h" -#include "V8CustomBinding.h" #include "V8DOMWrapper.h" #include "V8InspectorFrontendHost.h" #include "V8Node.h" @@ -356,7 +355,7 @@ v8::Handle<v8::Value> WebDevToolsFrontendImpl::jsShowContextMenu(const v8::Argum return v8::Undefined(); v8::Local<v8::Object> eventWrapper = v8::Local<v8::Object>::Cast(args[0]); - if (V8DOMWrapper::domWrapperType(eventWrapper) != V8ClassIndex::EVENT) + if (V8DOMWrapper::domWrapperType(eventWrapper) != V8ClassIndex::MOUSEEVENT) return v8::Undefined(); Event* event = V8Event::toNative(eventWrapper); diff --git a/WebKit/chromium/src/WebDragData.cpp b/WebKit/chromium/src/WebDragData.cpp index 3bd4a02..b18ab1b 100644 --- a/WebKit/chromium/src/WebDragData.cpp +++ b/WebKit/chromium/src/WebDragData.cpp @@ -100,6 +100,18 @@ void WebDragData::setDownloadURL(const WebURL& downloadURL) m_private->downloadURL = downloadURL; } +WebString WebDragData::downloadMetadata() const +{ + ASSERT(!isNull()); + return m_private->downloadMetadata; +} + +void WebDragData::setDownloadMetadata(const WebString& downloadMetadata) +{ + ensureMutable(); + m_private->downloadMetadata = downloadMetadata; +} + WebString WebDragData::fileExtension() const { ASSERT(!isNull()); diff --git a/WebKit/chromium/src/WebHTTPBody.cpp b/WebKit/chromium/src/WebHTTPBody.cpp index 335ed5c..3d40869 100644 --- a/WebKit/chromium/src/WebHTTPBody.cpp +++ b/WebKit/chromium/src/WebHTTPBody.cpp @@ -32,6 +32,7 @@ #include "WebHTTPBody.h" #include "FormData.h" +#include "WebFileInfo.h" using namespace WebCore; @@ -78,11 +79,17 @@ bool WebHTTPBody::elementAt(size_t index, Element& result) const result.type = Element::TypeData; result.data.assign(element.m_data.data(), element.m_data.size()); result.filePath.reset(); + result.fileStart = 0; + result.fileLength = 0; + result.fileInfo.modificationTime = 0.0; break; case FormDataElement::encodedFile: result.type = Element::TypeFile; result.data.reset(); result.filePath = element.m_filename; + result.fileStart = 0; // FIXME: to be set from FormData. + result.fileLength = -1; // FIXME: to be set from FormData. + result.fileInfo.modificationTime = 0.0; // FIXME: to be set from FormData. break; default: ASSERT_NOT_REACHED(); @@ -106,6 +113,11 @@ void WebHTTPBody::appendFile(const WebString& filePath) m_private->appendFile(filePath); } +void WebHTTPBody::appendFile(const WebString& filePath, long long fileStart, long long fileLength, const WebFileInfo& fileInfo) +{ + // FIXME: to be implemented. +} + long long WebHTTPBody::identifier() const { ASSERT(!isNull()); diff --git a/WebKit/chromium/src/WebInputElement.cpp b/WebKit/chromium/src/WebInputElement.cpp index ee799f6..9fd317f 100644 --- a/WebKit/chromium/src/WebInputElement.cpp +++ b/WebKit/chromium/src/WebInputElement.cpp @@ -75,7 +75,12 @@ WebString WebInputElement::formControlType() const { return constUnwrap<HTMLInputElement>()->formControlType(); } - + +bool WebInputElement::isActivatedSubmit() const +{ + return constUnwrap<HTMLInputElement>()->isActivatedSubmit(); +} + void WebInputElement::setActivatedSubmit(bool activated) { unwrap<HTMLInputElement>()->setActivatedSubmit(activated); diff --git a/WebKit/chromium/src/WebRuntimeFeatures.cpp b/WebKit/chromium/src/WebRuntimeFeatures.cpp index 0ef8b9b..ad84764 100644 --- a/WebKit/chromium/src/WebRuntimeFeatures.cpp +++ b/WebKit/chromium/src/WebRuntimeFeatures.cpp @@ -123,14 +123,14 @@ bool WebRuntimeFeatures::isSocketsEnabled() void WebRuntimeFeatures::enableNotifications(bool enable) { #if ENABLE(NOTIFICATIONS) - RuntimeEnabledFeatures::setNotificationsEnabled(enable); + RuntimeEnabledFeatures::setWebkitNotificationsEnabled(enable); #endif } bool WebRuntimeFeatures::isNotificationsEnabled() { #if ENABLE(NOTIFICATIONS) - return RuntimeEnabledFeatures::notificationsEnabled(); + return RuntimeEnabledFeatures::webkitNotificationsEnabled(); #else return false; #endif @@ -171,14 +171,14 @@ bool WebRuntimeFeatures::isGeolocationEnabled() void WebRuntimeFeatures::enableIndexedDatabase(bool enable) { #if ENABLE(INDEXED_DATABASE) - RuntimeEnabledFeatures::setIndexedDatabaseEnabled(enable); + RuntimeEnabledFeatures::setIndexedDBEnabled(enable); #endif } bool WebRuntimeFeatures::isIndexedDatabaseEnabled() { #if ENABLE(INDEXED_DATABASE) - return RuntimeEnabledFeatures::indexedDatabaseEnabled(); + return RuntimeEnabledFeatures::indexedDBEnabled(); #else return false; #endif diff --git a/WebKit/chromium/src/WebStorageAreaImpl.cpp b/WebKit/chromium/src/WebStorageAreaImpl.cpp index 92a923a..9a7fd5c 100644 --- a/WebKit/chromium/src/WebStorageAreaImpl.cpp +++ b/WebKit/chromium/src/WebStorageAreaImpl.cpp @@ -66,7 +66,7 @@ WebString WebStorageAreaImpl::getItem(const WebString& key) return m_storageArea->getItem(key); } -void WebStorageAreaImpl::setItem(const WebString& key, const WebString& value, const WebURL& url, bool& quotaException, WebString& oldValue) +void WebStorageAreaImpl::setItem(const WebString& key, const WebString& value, const WebURL& url, Result& result, WebString& oldValue) { int exceptionCode = 0; @@ -75,9 +75,9 @@ void WebStorageAreaImpl::setItem(const WebString& key, const WebString& value, c if (exceptionCode) { ASSERT(exceptionCode == WebCore::QUOTA_EXCEEDED_ERR); - quotaException = true; + result = ResultBlockedByQuota; } else - quotaException = false; + result = ResultOK; } void WebStorageAreaImpl::removeItem(const WebString& key, const WebURL& url, WebString& oldValue) diff --git a/WebKit/chromium/src/WebStorageAreaImpl.h b/WebKit/chromium/src/WebStorageAreaImpl.h index 7e90531..e9a11c2 100644 --- a/WebKit/chromium/src/WebStorageAreaImpl.h +++ b/WebKit/chromium/src/WebStorageAreaImpl.h @@ -45,7 +45,7 @@ public: virtual unsigned length(); virtual WebString key(unsigned index); virtual WebString getItem(const WebString& key); - virtual void setItem(const WebString& key, const WebString& value, const WebURL& url, bool& quotaException, WebString& oldValue); + virtual void setItem(const WebString& key, const WebString& value, const WebURL& url, Result& result, WebString& oldValue); virtual void removeItem(const WebString& key, const WebURL& url, WebString& oldValue); virtual void clear(const WebURL& url, bool& somethingCleared); diff --git a/WebKit/chromium/src/WebViewImpl.cpp b/WebKit/chromium/src/WebViewImpl.cpp index e030d72..ce03523 100644 --- a/WebKit/chromium/src/WebViewImpl.cpp +++ b/WebKit/chromium/src/WebViewImpl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2010 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 @@ -31,6 +31,7 @@ #include "config.h" #include "WebViewImpl.h" +#include "AutoFillPopupMenuClient.h" #include "AutocompletePopupMenuClient.h" #include "AXObjectCache.h" #include "Chrome.h" @@ -148,16 +149,16 @@ COMPILE_ASSERT_MATCHING_ENUM(DragOperationMove); COMPILE_ASSERT_MATCHING_ENUM(DragOperationDelete); COMPILE_ASSERT_MATCHING_ENUM(DragOperationEvery); -// Note that focusOnShow is false so that the autocomplete popup is shown not +// Note that focusOnShow is false so that the suggestions popup is shown not // activated. We need the page to still have focus so the user can keep typing // while the popup is showing. -static const PopupContainerSettings autocompletePopupSettings = { +static const PopupContainerSettings suggestionsPopupSettings = { false, // focusOnShow false, // setTextOnIndexChange false, // acceptOnAbandon true, // loopSelectionNavigation true, // restrictWidthOfListBox. Same as other browser (Fx, IE, and safari) - // For autocomplete, we use the direction of the input field as the direction + // For suggestions, we use the direction of the input field as the direction // of the popup items. The main reason is to keep the display of items in // drop-down the same as the items in the input field. PopupContainerSettings::DOMElementDirection, @@ -239,7 +240,9 @@ WebViewImpl::WebViewImpl(WebViewClient* client) , m_dropEffect(DropEffectDefault) , m_operationsAllowed(WebDragOperationNone) , m_dragOperation(WebDragOperationNone) - , m_autocompletePopupShowing(false) + , m_suggestionsPopupShowing(false) + , m_suggestionsPopupClient(0) + , m_suggestionsPopup(0) , m_isTransparent(false) , m_tabsToLinks(false) { @@ -326,7 +329,7 @@ void WebViewImpl::mouseDown(const WebMouseEvent& event) m_lastMouseDownPoint = WebPoint(event.x, event.y); // If a text field that has focus is clicked again, we should display the - // autocomplete popup. + // suggestions popup. RefPtr<Node> clickedNode; if (event.button == WebMouseEvent::ButtonLeft) { RefPtr<Node> focusedNode = focusedWebCoreNode(); @@ -348,7 +351,7 @@ void WebViewImpl::mouseDown(const WebMouseEvent& event) PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event)); if (clickedNode.get() && clickedNode == focusedWebCoreNode()) { - // Focus has not changed, show the autocomplete popup. + // Focus has not changed, show the suggestions popup. static_cast<EditorClientImpl*>(m_page->editorClient())-> showFormAutofillForNode(clickedNode.get()); } @@ -468,7 +471,7 @@ bool WebViewImpl::keyEvent(const WebKeyboardEvent& event) // event. m_suppressNextKeypressEvent = false; - // Give autocomplete a chance to consume the key events it is interested in. + // Give Autocomplete a chance to consume the key events it is interested in. if (autocompleteHandleKeyEvent(event)) return true; @@ -514,7 +517,7 @@ bool WebViewImpl::keyEvent(const WebKeyboardEvent& event) bool WebViewImpl::autocompleteHandleKeyEvent(const WebKeyboardEvent& event) { - if (!m_autocompletePopupShowing + if (!m_suggestionsPopupShowing // Home and End should be left to the text field to process. || event.windowsKeyCode == VKEY_HOME || event.windowsKeyCode == VKEY_END) @@ -522,7 +525,7 @@ bool WebViewImpl::autocompleteHandleKeyEvent(const WebKeyboardEvent& event) // Pressing delete triggers the removal of the selected suggestion from the DB. if (event.windowsKeyCode == VKEY_DELETE - && m_autocompletePopup->selectedIndex() != -1) { + && m_suggestionsPopup->selectedIndex() != -1) { Node* node = focusedWebCoreNode(); if (!node || (node->nodeType() != Node::ELEMENT_NODE)) { ASSERT_NOT_REACHED(); @@ -534,22 +537,22 @@ bool WebViewImpl::autocompleteHandleKeyEvent(const WebKeyboardEvent& event) return false; } - int selectedIndex = m_autocompletePopup->selectedIndex(); + int selectedIndex = m_suggestionsPopup->selectedIndex(); HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(element); WebString name = inputElement->name(); WebString value = m_autocompletePopupClient->itemText(selectedIndex); m_client->removeAutofillSuggestions(name, value); // Update the entries in the currently showing popup to reflect the // deletion. - m_autocompletePopupClient->removeItemAtIndex(selectedIndex); - refreshAutofillPopup(); + m_autocompletePopupClient->removeSuggestionAtIndex(selectedIndex); + refreshSuggestionsPopup(); return false; } - if (!m_autocompletePopup->isInterestedInEventForKey(event.windowsKeyCode)) + if (!m_suggestionsPopup->isInterestedInEventForKey(event.windowsKeyCode)) return false; - if (m_autocompletePopup->handleKeyEvent(PlatformKeyboardEventBuilder(event))) { + if (m_suggestionsPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event))) { // We need to ignore the next Char event after this otherwise pressing // enter when selecting an item in the menu will go to the page. if (WebInputEvent::RawKeyDown == event.type) @@ -697,6 +700,7 @@ bool WebViewImpl::keyEventDefault(const WebKeyboardEvent& event) case WebInputEvent::RawKeyDown: if (event.modifiers == WebInputEvent::ControlKey) { switch (event.windowsKeyCode) { +#if !OS(DARWIN) case 'A': focusedFrame()->executeCommand(WebString::fromUTF8("SelectAll")); return true; @@ -704,6 +708,7 @@ bool WebViewImpl::keyEventDefault(const WebKeyboardEvent& event) case 'C': focusedFrame()->executeCommand(WebString::fromUTF8("Copy")); return true; +#endif // Match FF behavior in the sense that Ctrl+home/end are the only Ctrl // key combinations which affect scrolling. Safari is buggy in the // sense that it scrolls the page for all Ctrl+scrolling key @@ -976,7 +981,7 @@ void WebViewImpl::setFocus(bool enable) } m_imeAcceptEvents = true; } else { - hideAutoCompletePopup(); + hideSuggestionsPopup(); // Clear focus on the currently focused frame if any. if (!m_page.get()) @@ -1182,7 +1187,7 @@ bool WebViewImpl::dispatchBeforeUnloadEvent() // FIXME: This should really cause a recursive depth-first walk of all // frames in the tree, calling each frame's onbeforeunload. At the moment, // we're consistent with Safari 3.1, not IE/FF. - Frame* frame = m_page->focusController()->focusedOrMainFrame(); + Frame* frame = m_page->mainFrame(); if (!frame) return true; @@ -1558,64 +1563,132 @@ void WebViewImpl::applyAutofillSuggestions( const WebVector<WebString>& suggestions, int defaultSuggestionIndex) { - if (!m_page.get() || suggestions.isEmpty()) { - hideAutoCompletePopup(); + applyAutocompleteSuggestions(node, suggestions, defaultSuggestionIndex); +} + +void WebViewImpl::applyAutoFillSuggestions( + const WebNode& node, + const WebVector<WebString>& names, + const WebVector<WebString>& labels, + int defaultSuggestionIndex) +{ + ASSERT(names.size() == labels.size()); + ASSERT(defaultSuggestionIndex < static_cast<int>(names.size())); + + if (names.isEmpty()) { + hideSuggestionsPopup(); + return; + } + + RefPtr<Node> focusedNode = focusedWebCoreNode(); + // If the node for which we queried the AutoFill suggestions is not the + // focused node, then we have nothing to do. FIXME: also check the + // caret is at the end and that the text has not changed. + if (!focusedNode || focusedNode != PassRefPtr<Node>(node)) { + hideSuggestionsPopup(); return; } + HTMLInputElement* inputElem = + static_cast<HTMLInputElement*>(focusedNode.get()); + + // The first time the AutoFill popup is shown we'll create the client and + // the popup. + if (!m_autoFillPopupClient.get()) + m_autoFillPopupClient.set(new AutoFillPopupMenuClient); + + m_autoFillPopupClient->initialize(inputElem, names, labels, + defaultSuggestionIndex); + + if (m_suggestionsPopupClient != m_autoFillPopupClient.get()) { + hideSuggestionsPopup(); + m_suggestionsPopupClient = m_autoFillPopupClient.get(); + } + + if (!m_autoFillPopup.get()) { + m_autoFillPopup = PopupContainer::create(m_suggestionsPopupClient, + suggestionsPopupSettings); + } + + if (m_suggestionsPopup != m_autoFillPopup.get()) + m_suggestionsPopup = m_autoFillPopup.get(); + + if (m_suggestionsPopupShowing) { + m_autoFillPopupClient->setSuggestions(names, labels); + refreshSuggestionsPopup(); + } else { + m_suggestionsPopup->show(focusedNode->getRect(), + focusedNode->ownerDocument()->view(), 0); + m_suggestionsPopupShowing = true; + } +} + +void WebViewImpl::applyAutocompleteSuggestions( + const WebNode& node, + const WebVector<WebString>& suggestions, + int defaultSuggestionIndex) +{ ASSERT(defaultSuggestionIndex < static_cast<int>(suggestions.size())); - if (RefPtr<Frame> focused = m_page->focusController()->focusedFrame()) { - RefPtr<Document> document = focused->document(); - if (!document.get()) { - hideAutoCompletePopup(); - return; - } + if (!m_page.get() || suggestions.isEmpty()) { + hideSuggestionsPopup(); + return; + } - RefPtr<Node> focusedNode = document->focusedNode(); - // If the node for which we queried the autofill suggestions is not the - // focused node, then we have nothing to do. FIXME: also check the - // carret is at the end and that the text has not changed. - if (!focusedNode.get() || focusedNode != PassRefPtr<Node>(node)) { - hideAutoCompletePopup(); - return; - } + RefPtr<Node> focusedNode = focusedWebCoreNode(); + // If the node for which we queried the Autocomplete suggestions is not the + // focused node, then we have nothing to do. FIXME: also check the + // caret is at the end and that the text has not changed. + if (!focusedNode || focusedNode != PassRefPtr<Node>(node)) { + hideSuggestionsPopup(); + return; + } - if (!focusedNode->hasTagName(HTMLNames::inputTag)) { - ASSERT_NOT_REACHED(); - return; - } + HTMLInputElement* inputElem = + static_cast<HTMLInputElement*>(focusedNode.get()); - HTMLInputElement* inputElem = - static_cast<HTMLInputElement*>(focusedNode.get()); - - // The first time the autocomplete is shown we'll create the client and the - // popup. - if (!m_autocompletePopupClient.get()) - m_autocompletePopupClient.set(new AutocompletePopupMenuClient(this)); - m_autocompletePopupClient->initialize(inputElem, - suggestions, - defaultSuggestionIndex); - if (!m_autocompletePopup.get()) { - m_autocompletePopup = - PopupContainer::create(m_autocompletePopupClient.get(), - autocompletePopupSettings); - } + // The first time the Autocomplete is shown we'll create the client and the + // popup. + if (!m_autocompletePopupClient.get()) + m_autocompletePopupClient.set(new AutocompletePopupMenuClient); - if (m_autocompletePopupShowing) { - m_autocompletePopupClient->setSuggestions(suggestions); - refreshAutofillPopup(); - } else { - m_autocompletePopup->show(focusedNode->getRect(), - focusedNode->ownerDocument()->view(), 0); - m_autocompletePopupShowing = true; - } + m_autocompletePopupClient->initialize(inputElem, suggestions, + defaultSuggestionIndex); + + if (m_suggestionsPopupClient != m_autocompletePopupClient.get()) { + hideSuggestionsPopup(); + m_suggestionsPopupClient = m_autocompletePopupClient.get(); + } + + if (!m_autocompletePopup.get()) { + m_autocompletePopup = PopupContainer::create(m_suggestionsPopupClient, + suggestionsPopupSettings); + } + + if (m_suggestionsPopup != m_autocompletePopup.get()) + m_suggestionsPopup = m_autocompletePopup.get(); + + if (m_suggestionsPopupShowing) { + m_autocompletePopupClient->setSuggestions(suggestions); + refreshSuggestionsPopup(); + } else { + m_suggestionsPopup->show(focusedNode->getRect(), + focusedNode->ownerDocument()->view(), 0); + m_suggestionsPopupShowing = true; } } void WebViewImpl::hideAutofillPopup() { - hideAutoCompletePopup(); + hideSuggestionsPopup(); +} + +void WebViewImpl::hideSuggestionsPopup() +{ + if (m_suggestionsPopupShowing) { + m_suggestionsPopup->hidePopup(); + m_suggestionsPopupShowing = false; + } } void WebViewImpl::performCustomContextMenuAction(unsigned action) @@ -1778,19 +1851,6 @@ void WebViewImpl::observeNewNavigation() #endif } -void WebViewImpl::hideAutoCompletePopup() -{ - if (m_autocompletePopupShowing) { - m_autocompletePopup->hidePopup(); - autoCompletePopupDidHide(); - } -} - -void WebViewImpl::autoCompletePopupDidHide() -{ - m_autocompletePopupShowing = false; -} - void WebViewImpl::setIgnoreInputEvents(bool newValue) { ASSERT(m_ignoreInputEvents != newValue); @@ -1806,23 +1866,23 @@ NotificationPresenterImpl* WebViewImpl::notificationPresenterImpl() } #endif -void WebViewImpl::refreshAutofillPopup() +void WebViewImpl::refreshSuggestionsPopup() { - ASSERT(m_autocompletePopupShowing); + ASSERT(m_suggestionsPopupShowing); // Hide the popup if it has become empty. if (!m_autocompletePopupClient->listSize()) { - hideAutoCompletePopup(); + hideSuggestionsPopup(); return; } - IntRect oldBounds = m_autocompletePopup->boundsRect(); - m_autocompletePopup->refresh(); - IntRect newBounds = m_autocompletePopup->boundsRect(); + IntRect oldBounds = m_suggestionsPopup->boundsRect(); + m_suggestionsPopup->refresh(); + IntRect newBounds = m_suggestionsPopup->boundsRect(); // Let's resize the backing window if necessary. if (oldBounds != newBounds) { WebPopupMenuImpl* popupMenu = - static_cast<WebPopupMenuImpl*>(m_autocompletePopup->client()); + static_cast<WebPopupMenuImpl*>(m_suggestionsPopup->client()); popupMenu->client()->setWindowRect(newBounds); } } diff --git a/WebKit/chromium/src/WebViewImpl.h b/WebKit/chromium/src/WebViewImpl.h index e2292f4..286ac43 100644 --- a/WebKit/chromium/src/WebViewImpl.h +++ b/WebKit/chromium/src/WebViewImpl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2010 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 @@ -58,6 +58,7 @@ class KeyboardEvent; class Page; class PlatformKeyboardEvent; class PopupContainer; +class PopupMenuClient; class Range; class RenderTheme; class Widget; @@ -65,7 +66,9 @@ class Widget; namespace WebKit { class AutocompletePopupMenuClient; +class AutoFillPopupMenuClient; class ContextMenuClientImpl; +class SuggestionsPopupMenuClient; class WebAccessibilityObject; class WebDevToolsAgentPrivate; class WebFrameImpl; @@ -153,7 +156,17 @@ public: const WebNode&, const WebVector<WebString>& suggestions, int defaultSuggestionIndex); + virtual void applyAutoFillSuggestions( + const WebNode&, + const WebVector<WebString>& names, + const WebVector<WebString>& labels, + int defaultSuggestionIndex); + virtual void applyAutocompleteSuggestions( + const WebNode&, + const WebVector<WebString>& suggestions, + int defaultSuggestionIndex); virtual void hideAutofillPopup(); + virtual void hideSuggestionsPopup(); virtual void setScrollbarColors(unsigned inactiveColor, unsigned activeColor, unsigned trackColor); @@ -261,9 +274,10 @@ public: const WebDragData& dragData, WebDragOperationsMask dragSourceOperationMask); - // Hides the autocomplete popup if it is showing. - void hideAutoCompletePopup(); - void autoCompletePopupDidHide(); + void suggestionsPopupDidHide() + { + m_suggestionsPopupShowing = false; + } #if ENABLE(NOTIFICATIONS) // Returns the provider of desktop notifications. @@ -295,10 +309,10 @@ private: // Returns true if the autocomple has consumed the event. bool autocompleteHandleKeyEvent(const WebKeyboardEvent&); - // Repaints the autofill popup. Should be called when the suggestions have - // changed. Note that this should only be called when the autofill popup is - // showing. - void refreshAutofillPopup(); + // Repaints the suggestions popup. Should be called when the suggestions + // have changed. Note that this should only be called when the suggestions + // popup is showing. + void refreshSuggestionsPopup(); // Returns true if the view was scrolled. bool scrollViewWithKeyboard(int keyCode, int modifiers); @@ -393,16 +407,29 @@ private: // current drop target in this WebView (the drop target can accept the drop). WebDragOperation m_dragOperation; - // The autocomplete popup. Kept around and reused every-time new suggestions - // should be shown. - RefPtr<WebCore::PopupContainer> m_autocompletePopup; + // Whether a suggestions popup is currently showing. + bool m_suggestionsPopupShowing; + + // A pointer to the current suggestions popup menu client. This can be + // either an AutoFillPopupMenuClient or an AutocompletePopupMenuClient. We + // do not own this pointer. + SuggestionsPopupMenuClient* m_suggestionsPopupClient; - // Whether the autocomplete popup is currently showing. - bool m_autocompletePopupShowing; + // The AutoFill popup client. + OwnPtr<AutoFillPopupMenuClient> m_autoFillPopupClient; - // The autocomplete client. + // The Autocomplete popup client. OwnPtr<AutocompletePopupMenuClient> m_autocompletePopupClient; + // A pointer to the current suggestions popup. We do not own this pointer. + WebCore::PopupContainer* m_suggestionsPopup; + + // The AutoFill suggestions popup. + RefPtr<WebCore::PopupContainer> m_autoFillPopup; + + // The AutoComplete suggestions popup. + RefPtr<WebCore::PopupContainer> m_autocompletePopup; + OwnPtr<WebDevToolsAgentPrivate> m_devToolsAgent; // Whether the webview is rendering transparently. diff --git a/WebKit/chromium/src/WebWorkerBase.cpp b/WebKit/chromium/src/WebWorkerBase.cpp index 7fd3749..40019e8 100644 --- a/WebKit/chromium/src/WebWorkerBase.cpp +++ b/WebKit/chromium/src/WebWorkerBase.cpp @@ -271,6 +271,8 @@ void WebWorkerBase::workerContextClosedTask(ScriptExecutionContext* context, { if (thisPtr->commonClient()) thisPtr->commonClient()->workerContextClosed(); + + thisPtr->stopWorkerThread(); } void WebWorkerBase::workerContextDestroyed() diff --git a/WebKit/chromium/src/js/DebuggerAgent.js b/WebKit/chromium/src/js/DebuggerAgent.js new file mode 100644 index 0000000..301620a --- /dev/null +++ b/WebKit/chromium/src/js/DebuggerAgent.js @@ -0,0 +1,1528 @@ +/* + * Copyright (C) 2010 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 + * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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. + */ + +/** + * @fileoverview Provides communication interface to remote v8 debugger. See + * protocol decription at http://code.google.com/p/v8/wiki/DebuggerProtocol + */ + +/** + * FIXME: change field naming style to use trailing underscore. + * @constructor + */ +devtools.DebuggerAgent = function() +{ + RemoteDebuggerAgent.debuggerOutput = this.handleDebuggerOutput_.bind(this); + RemoteDebuggerAgent.setContextId = this.setContextId_.bind(this); + + /** + * Id of the inspected page global context. It is used for filtering scripts. + * @type {number} + */ + this.contextId_ = null; + + /** + * Mapping from script id to script info. + * @type {Object} + */ + this.parsedScripts_ = null; + + /** + * Mapping from the request id to the devtools.BreakpointInfo for the + * breakpoints whose v8 ids are not set yet. These breakpoints are waiting for + * "setbreakpoint" responses to learn their ids in the v8 debugger. + * @see #handleSetBreakpointResponse_ + * @type {Object} + */ + this.requestNumberToBreakpointInfo_ = null; + + /** + * Information on current stack frames. + * @type {Array.<devtools.CallFrame>} + */ + this.callFrames_ = []; + + /** + * Whether to stop in the debugger on the exceptions. + * @type {boolean} + */ + this.pauseOnExceptions_ = false; + + /** + * Mapping: request sequence number->callback. + * @type {Object} + */ + this.requestSeqToCallback_ = null; + + /** + * Whether the scripts panel has been shown and initialilzed. + * @type {boolean} + */ + this.scriptsPanelInitialized_ = false; + + /** + * Whether the scripts list should be requested next time when context id is + * set. + * @type {boolean} + */ + this.requestScriptsWhenContextIdSet_ = false; + + /** + * Whether the agent is waiting for initial scripts response. + * @type {boolean} + */ + this.waitingForInitialScriptsResponse_ = false; + + /** + * If backtrace response is received when initial scripts response + * is not yet processed the backtrace handling will be postponed until + * after the scripts response processing. The handler bound to its arguments + * and this agent will be stored in this field then. + * @type {?function()} + */ + this.pendingBacktraceResponseHandler_ = null; + + /** + * Container of all breakpoints set using resource URL. These breakpoints + * survive page reload. Breakpoints set by script id(for scripts that don't + * have URLs) are stored in ScriptInfo objects. + * @type {Object} + */ + this.urlToBreakpoints_ = {}; + + + /** + * Exception message that is shown to user while on exception break. + * @type {WebInspector.ConsoleMessage} + */ + this.currentExceptionMessage_ = null; +}; + + +/** + * A copy of the scope types from v8/src/mirror-delay.js + * @enum {number} + */ +devtools.DebuggerAgent.ScopeType = { + Global: 0, + Local: 1, + With: 2, + Closure: 3, + Catch: 4 +}; + + +/** + * Resets debugger agent to its initial state. + */ +devtools.DebuggerAgent.prototype.reset = function() +{ + this.contextId_ = null; + // No need to request scripts since they all will be pushed in AfterCompile + // events. + this.requestScriptsWhenContextIdSet_ = false; + this.waitingForInitialScriptsResponse_ = false; + + this.parsedScripts_ = {}; + this.requestNumberToBreakpointInfo_ = {}; + this.callFrames_ = []; + this.requestSeqToCallback_ = {}; +}; + + +/** + * Initializes scripts UI. This method is called every time Scripts panel + * is shown. It will send request for context id if it's not set yet. + */ +devtools.DebuggerAgent.prototype.initUI = function() +{ + // Initialize scripts cache when Scripts panel is shown first time. + if (this.scriptsPanelInitialized_) + return; + this.scriptsPanelInitialized_ = true; + if (this.contextId_) { + // We already have context id. This means that we are here from the + // very beginning of the page load cycle and hence will get all scripts + // via after-compile events. No need to request scripts for this session. + // + // There can be a number of scripts from after-compile events that are + // pending addition into the UI. + for (var scriptId in this.parsedScripts_) { + var script = this.parsedScripts_[scriptId]; + WebInspector.parsedScriptSource(scriptId, script.getUrl(), undefined /* script source */, script.getLineOffset()); + } + return; + } + this.waitingForInitialScriptsResponse_ = true; + // Script list should be requested only when current context id is known. + RemoteDebuggerAgent.getContextId(); + this.requestScriptsWhenContextIdSet_ = true; +}; + + +/** + * Asynchronously requests the debugger for the script source. + * @param {number} scriptId Id of the script whose source should be resolved. + * @param {function(source:?string):void} callback Function that will be called + * when the source resolution is completed. "source" parameter will be null + * if the resolution fails. + */ +devtools.DebuggerAgent.prototype.resolveScriptSource = function(scriptId, callback) +{ + var script = this.parsedScripts_[scriptId]; + if (!script || script.isUnresolved()) { + callback(null); + return; + } + + var cmd = new devtools.DebugCommand("scripts", { + "ids": [scriptId], + "includeSource": true + }); + devtools.DebuggerAgent.sendCommand_(cmd); + // Force v8 execution so that it gets to processing the requested command. + RemoteDebuggerAgent.processDebugCommands(); + + this.requestSeqToCallback_[cmd.getSequenceNumber()] = function(msg) { + if (msg.isSuccess()) { + var scriptJson = msg.getBody()[0]; + if (scriptJson) + callback(scriptJson.source); + else + callback(null); + } else + callback(null); + }; +}; + + +/** + * Tells the v8 debugger to stop on as soon as possible. + */ +devtools.DebuggerAgent.prototype.pauseExecution = function() +{ + RemoteDebuggerCommandExecutor.DebuggerPauseScript(); +}; + + +/** + * @param {number} sourceId Id of the script fot the breakpoint. + * @param {number} line Number of the line for the breakpoint. + * @param {?string} condition The breakpoint condition. + */ +devtools.DebuggerAgent.prototype.addBreakpoint = function(sourceId, line, condition) +{ + var script = this.parsedScripts_[sourceId]; + if (!script) + return; + + line = devtools.DebuggerAgent.webkitToV8LineNumber_(line); + + var commandArguments; + if (script.getUrl()) { + var breakpoints = this.urlToBreakpoints_[script.getUrl()]; + if (breakpoints && breakpoints[line]) + return; + if (!breakpoints) { + breakpoints = {}; + this.urlToBreakpoints_[script.getUrl()] = breakpoints; + } + + var breakpointInfo = new devtools.BreakpointInfo(line); + breakpoints[line] = breakpointInfo; + + commandArguments = { + "groupId": this.contextId_, + "type": "script", + "target": script.getUrl(), + "line": line, + "condition": condition + }; + } else { + var breakpointInfo = script.getBreakpointInfo(line); + if (breakpointInfo) + return; + + breakpointInfo = new devtools.BreakpointInfo(line); + script.addBreakpointInfo(breakpointInfo); + + commandArguments = { + "groupId": this.contextId_, + "type": "scriptId", + "target": sourceId, + "line": line, + "condition": condition + }; + } + + var cmd = new devtools.DebugCommand("setbreakpoint", commandArguments); + + this.requestNumberToBreakpointInfo_[cmd.getSequenceNumber()] = breakpointInfo; + + devtools.DebuggerAgent.sendCommand_(cmd); + // Force v8 execution so that it gets to processing the requested command. + // It is necessary for being able to change a breakpoint just after it + // has been created (since we need an existing breakpoint id for that). + RemoteDebuggerAgent.processDebugCommands(); +}; + + +/** + * @param {number} sourceId Id of the script for the breakpoint. + * @param {number} line Number of the line for the breakpoint. + */ +devtools.DebuggerAgent.prototype.removeBreakpoint = function(sourceId, line) +{ + var script = this.parsedScripts_[sourceId]; + if (!script) + return; + + line = devtools.DebuggerAgent.webkitToV8LineNumber_(line); + + var breakpointInfo; + if (script.getUrl()) { + var breakpoints = this.urlToBreakpoints_[script.getUrl()]; + breakpointInfo = breakpoints[line]; + delete breakpoints[line]; + } else { + breakpointInfo = script.getBreakpointInfo(line); + if (breakpointInfo) + script.removeBreakpointInfo(breakpointInfo); + } + + if (!breakpointInfo) + return; + + breakpointInfo.markAsRemoved(); + + var id = breakpointInfo.getV8Id(); + + // If we don't know id of this breakpoint in the v8 debugger we cannot send + // "clearbreakpoint" request. In that case it will be removed in + // "setbreakpoint" response handler when we learn the id. + if (id !== -1) { + this.requestClearBreakpoint_(id); + } +}; + + +/** + * @param {number} sourceId Id of the script for the breakpoint. + * @param {number} line Number of the line for the breakpoint. + * @param {?string} condition New breakpoint condition. + */ +devtools.DebuggerAgent.prototype.updateBreakpoint = function(sourceId, line, condition) +{ + var script = this.parsedScripts_[sourceId]; + if (!script) + return; + + line = devtools.DebuggerAgent.webkitToV8LineNumber_(line); + + var breakpointInfo; + if (script.getUrl()) { + var breakpoints = this.urlToBreakpoints_[script.getUrl()]; + breakpointInfo = breakpoints[line]; + } else + breakpointInfo = script.getBreakpointInfo(line); + + var id = breakpointInfo.getV8Id(); + + // If we don't know id of this breakpoint in the v8 debugger we cannot send + // the "changebreakpoint" request. + if (id !== -1) { + // TODO(apavlov): make use of the real values for "enabled" and + // "ignoreCount" when appropriate. + this.requestChangeBreakpoint_(id, true, condition, null); + } +}; + + +/** + * Tells the v8 debugger to step into the next statement. + */ +devtools.DebuggerAgent.prototype.stepIntoStatement = function() +{ + this.stepCommand_("in"); +}; + + +/** + * Tells the v8 debugger to step out of current function. + */ +devtools.DebuggerAgent.prototype.stepOutOfFunction = function() +{ + this.stepCommand_("out"); +}; + + +/** + * Tells the v8 debugger to step over the next statement. + */ +devtools.DebuggerAgent.prototype.stepOverStatement = function() +{ + this.stepCommand_("next"); +}; + + +/** + * Tells the v8 debugger to continue execution after it has been stopped on a + * breakpoint or an exception. + */ +devtools.DebuggerAgent.prototype.resumeExecution = function() +{ + this.clearExceptionMessage_(); + var cmd = new devtools.DebugCommand("continue"); + devtools.DebuggerAgent.sendCommand_(cmd); +}; + + +/** + * Creates exception message and schedules it for addition to the resource upon + * backtrace availability. + * @param {string} url Resource url. + * @param {number} line Resource line number. + * @param {string} message Exception text. + */ +devtools.DebuggerAgent.prototype.createExceptionMessage_ = function(url, line, message) +{ + this.currentExceptionMessage_ = new WebInspector.ConsoleMessage( + WebInspector.ConsoleMessage.MessageSource.JS, + WebInspector.ConsoleMessage.MessageType.Log, + WebInspector.ConsoleMessage.MessageLevel.Error, + line, + url, + 0 /* group level */, + 1 /* repeat count */, + "[Exception] " + message); +}; + + +/** + * Shows pending exception message that is created with createExceptionMessage_ + * earlier. + */ +devtools.DebuggerAgent.prototype.showPendingExceptionMessage_ = function() +{ + if (!this.currentExceptionMessage_) + return; + var msg = this.currentExceptionMessage_; + var resource = WebInspector.resourceURLMap[msg.url]; + if (resource) { + msg.resource = resource; + WebInspector.panels.resources.addMessageToResource(resource, msg); + } else + this.currentExceptionMessage_ = null; +}; + + +/** + * Clears exception message from the resource. + */ +devtools.DebuggerAgent.prototype.clearExceptionMessage_ = function() +{ + if (this.currentExceptionMessage_) { + var messageElement = this.currentExceptionMessage_._resourceMessageLineElement; + var bubble = messageElement.parentElement; + bubble.removeChild(messageElement); + if (!bubble.firstChild) { + // Last message in bubble removed. + bubble.parentElement.removeChild(bubble); + } + this.currentExceptionMessage_ = null; + } +}; + + +/** + * @return {boolean} True iff the debugger will pause execution on the + * exceptions. + */ +devtools.DebuggerAgent.prototype.pauseOnExceptions = function() +{ + return this.pauseOnExceptions_; +}; + + +/** + * Tells whether to pause in the debugger on the exceptions or not. + * @param {boolean} value True iff execution should be stopped in the debugger + * on the exceptions. + */ +devtools.DebuggerAgent.prototype.setPauseOnExceptions = function(value) +{ + this.pauseOnExceptions_ = value; +}; + + +/** + * Sends "evaluate" request to the debugger. + * @param {Object} arguments Request arguments map. + * @param {function(devtools.DebuggerMessage)} callback Callback to be called + * when response is received. + */ +devtools.DebuggerAgent.prototype.requestEvaluate = function(arguments, callback) +{ + var cmd = new devtools.DebugCommand("evaluate", arguments); + devtools.DebuggerAgent.sendCommand_(cmd); + this.requestSeqToCallback_[cmd.getSequenceNumber()] = callback; +}; + + +/** + * Sends "lookup" request for each unresolved property of the object. When + * response is received the properties will be changed with their resolved + * values. + * @param {Object} object Object whose properties should be resolved. + * @param {function(devtools.DebuggerMessage)} Callback to be called when all + * children are resolved. + * @param {boolean} noIntrinsic Whether intrinsic properties should be included. + */ +devtools.DebuggerAgent.prototype.resolveChildren = function(object, callback, noIntrinsic) +{ + if ("handle" in object) { + var result = []; + devtools.DebuggerAgent.formatObjectProperties_(object, result, noIntrinsic); + callback(result); + } else { + this.requestLookup_([object.ref], function(msg) { + var result = []; + if (msg.isSuccess()) { + var handleToObject = msg.getBody(); + var resolved = handleToObject[object.ref]; + devtools.DebuggerAgent.formatObjectProperties_(resolved, result, noIntrinsic); + callback(result); + } else + callback([]); + }); + } +}; + + +/** + * Sends "scope" request for the scope object to resolve its variables. + * @param {Object} scope Scope to be resolved. + * @param {function(Array.<WebInspector.ObjectPropertyProxy>)} callback + * Callback to be called when all scope variables are resolved. + */ +devtools.DebuggerAgent.prototype.resolveScope = function(scope, callback) +{ + var cmd = new devtools.DebugCommand("scope", { + "frameNumber": scope.frameNumber, + "number": scope.index, + "compactFormat": true + }); + devtools.DebuggerAgent.sendCommand_(cmd); + this.requestSeqToCallback_[cmd.getSequenceNumber()] = function(msg) { + var result = []; + if (msg.isSuccess()) { + var scopeObjectJson = msg.getBody().object; + devtools.DebuggerAgent.formatObjectProperties_(scopeObjectJson, result, true /* no intrinsic */); + } + callback(result); + }; +}; + + +/** + * Sends "scopes" request for the frame object to resolve all variables + * available in the frame. + * @param {number} callFrameId Id of call frame whose variables need to + * be resolved. + * @param {function(Object)} callback Callback to be called when all frame + * variables are resolved. + */ +devtools.DebuggerAgent.prototype.resolveFrameVariables_ = function(callFrameId, callback) +{ + var result = {}; + + var frame = this.callFrames_[callFrameId]; + if (!frame) { + callback(result); + return; + } + + var waitingResponses = 0; + function scopeResponseHandler(msg) { + waitingResponses--; + + if (msg.isSuccess()) { + var properties = msg.getBody().object.properties; + for (var j = 0; j < properties.length; j++) + result[properties[j].name] = true; + } + + // When all scopes are resolved invoke the callback. + if (waitingResponses === 0) + callback(result); + }; + + for (var i = 0; i < frame.scopeChain.length; i++) { + var scope = frame.scopeChain[i].objectId; + if (scope.type === devtools.DebuggerAgent.ScopeType.Global) { + // Do not resolve global scope since it takes for too long. + // TODO(yurys): allow to send only property names in the response. + continue; + } + var cmd = new devtools.DebugCommand("scope", { + "frameNumber": scope.frameNumber, + "number": scope.index, + "compactFormat": true + }); + devtools.DebuggerAgent.sendCommand_(cmd); + this.requestSeqToCallback_[cmd.getSequenceNumber()] = scopeResponseHandler; + waitingResponses++; + } +}; + +/** + * Evaluates the expressionString to an object in the call frame and reports + * all its properties. + * @param{string} expressionString Expression whose properties should be + * collected. + * @param{number} callFrameId The frame id. + * @param{function(Object result,bool isException)} reportCompletions Callback + * function. + */ +devtools.DebuggerAgent.prototype.resolveCompletionsOnFrame = function(expressionString, callFrameId, reportCompletions) +{ + if (expressionString) { + expressionString = "var obj = " + expressionString + + "; var names = {}; for (var n in obj) { names[n] = true; };" + + "names;"; + this.evaluateInCallFrame( + callFrameId, + expressionString, + function(result) { + var names = {}; + if (!result.isException) { + var props = result.value.objectId.properties; + // Put all object properties into the map. + for (var i = 0; i < props.length; i++) + names[props[i].name] = true; + } + reportCompletions(names, result.isException); + }); + } else { + this.resolveFrameVariables_(callFrameId, + function(result) { + reportCompletions(result, false /* isException */); + }); + } +}; + + +/** + * @param{number} scriptId + * @return {string} Type of the context of the script with specified id. + */ +devtools.DebuggerAgent.prototype.getScriptContextType = function(scriptId) +{ + return this.parsedScripts_[scriptId].getContextType(); +}; + + +/** + * Removes specified breakpoint from the v8 debugger. + * @param {number} breakpointId Id of the breakpoint in the v8 debugger. + */ +devtools.DebuggerAgent.prototype.requestClearBreakpoint_ = function(breakpointId) +{ + var cmd = new devtools.DebugCommand("clearbreakpoint", { + "breakpoint": breakpointId + }); + devtools.DebuggerAgent.sendCommand_(cmd); +}; + + +/** + * Changes breakpoint parameters in the v8 debugger. + * @param {number} breakpointId Id of the breakpoint in the v8 debugger. + * @param {boolean} enabled Whether to enable the breakpoint. + * @param {?string} condition New breakpoint condition. + * @param {number} ignoreCount New ignore count for the breakpoint. + */ +devtools.DebuggerAgent.prototype.requestChangeBreakpoint_ = function(breakpointId, enabled, condition, ignoreCount) +{ + var cmd = new devtools.DebugCommand("changebreakpoint", { + "breakpoint": breakpointId, + "enabled": enabled, + "condition": condition, + "ignoreCount": ignoreCount + }); + devtools.DebuggerAgent.sendCommand_(cmd); +}; + + +/** + * Sends "backtrace" request to v8. + */ +devtools.DebuggerAgent.prototype.requestBacktrace_ = function() +{ + var cmd = new devtools.DebugCommand("backtrace", { + "compactFormat":true + }); + devtools.DebuggerAgent.sendCommand_(cmd); +}; + + +/** + * Sends command to v8 debugger. + * @param {devtools.DebugCommand} cmd Command to execute. + */ +devtools.DebuggerAgent.sendCommand_ = function(cmd) +{ + RemoteDebuggerCommandExecutor.DebuggerCommand(cmd.toJSONProtocol()); +}; + + +/** + * Tells the v8 debugger to make the next execution step. + * @param {string} action "in", "out" or "next" action. + */ +devtools.DebuggerAgent.prototype.stepCommand_ = function(action) +{ + this.clearExceptionMessage_(); + var cmd = new devtools.DebugCommand("continue", { + "stepaction": action, + "stepcount": 1 + }); + devtools.DebuggerAgent.sendCommand_(cmd); +}; + + +/** + * Sends "lookup" request to v8. + * @param {number} handle Handle to the object to lookup. + */ +devtools.DebuggerAgent.prototype.requestLookup_ = function(handles, callback) +{ + var cmd = new devtools.DebugCommand("lookup", { + "compactFormat":true, + "handles": handles + }); + devtools.DebuggerAgent.sendCommand_(cmd); + this.requestSeqToCallback_[cmd.getSequenceNumber()] = callback; +}; + + +/** + * Sets debugger context id for scripts filtering. + * @param {number} contextId Id of the inspected page global context. + */ +devtools.DebuggerAgent.prototype.setContextId_ = function(contextId) +{ + this.contextId_ = contextId; + + // If it's the first time context id is set request scripts list. + if (this.requestScriptsWhenContextIdSet_) { + this.requestScriptsWhenContextIdSet_ = false; + var cmd = new devtools.DebugCommand("scripts", { + "includeSource": false + }); + devtools.DebuggerAgent.sendCommand_(cmd); + // Force v8 execution so that it gets to processing the requested command. + RemoteDebuggerAgent.processDebugCommands(); + + var debuggerAgent = this; + this.requestSeqToCallback_[cmd.getSequenceNumber()] = function(msg) { + // Handle the response iff the context id hasn't changed since the request + // was issued. Otherwise if the context id did change all up-to-date + // scripts will be pushed in after compile events and there is no need to + // handle the response. + if (contextId === debuggerAgent.contextId_) + debuggerAgent.handleScriptsResponse_(msg); + + // We received initial scripts response so flush the flag and + // see if there is an unhandled backtrace response. + debuggerAgent.waitingForInitialScriptsResponse_ = false; + if (debuggerAgent.pendingBacktraceResponseHandler_) { + debuggerAgent.pendingBacktraceResponseHandler_(); + debuggerAgent.pendingBacktraceResponseHandler_ = null; + } + }; + } +}; + + +/** + * Handles output sent by v8 debugger. The output is either asynchronous event + * or response to a previously sent request. See protocol definitioun for more + * details on the output format. + * @param {string} output + */ +devtools.DebuggerAgent.prototype.handleDebuggerOutput_ = function(output) +{ + var msg; + try { + msg = new devtools.DebuggerMessage(output); + } catch(e) { + debugPrint("Failed to handle debugger response:\n" + e); + throw e; + } + + if (msg.getType() === "event") { + if (msg.getEvent() === "break") + this.handleBreakEvent_(msg); + else if (msg.getEvent() === "exception") + this.handleExceptionEvent_(msg); + else if (msg.getEvent() === "afterCompile") + this.handleAfterCompileEvent_(msg); + } else if (msg.getType() === "response") { + if (msg.getCommand() === "scripts") + this.invokeCallbackForResponse_(msg); + else if (msg.getCommand() === "setbreakpoint") + this.handleSetBreakpointResponse_(msg); + else if (msg.getCommand() === "clearbreakpoint") + this.handleClearBreakpointResponse_(msg); + else if (msg.getCommand() === "backtrace") + this.handleBacktraceResponse_(msg); + else if (msg.getCommand() === "lookup") + this.invokeCallbackForResponse_(msg); + else if (msg.getCommand() === "evaluate") + this.invokeCallbackForResponse_(msg); + else if (msg.getCommand() === "scope") + this.invokeCallbackForResponse_(msg); + } +}; + + +/** + * @param {devtools.DebuggerMessage} msg + */ +devtools.DebuggerAgent.prototype.handleBreakEvent_ = function(msg) +{ + // Force scrips panel to be shown first. + WebInspector.currentPanel = WebInspector.panels.scripts; + + var body = msg.getBody(); + + var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(body.sourceLine); + this.requestBacktrace_(); +}; + + +/** + * @param {devtools.DebuggerMessage} msg + */ +devtools.DebuggerAgent.prototype.handleExceptionEvent_ = function(msg) +{ + // Force scrips panel to be shown first. + WebInspector.currentPanel = WebInspector.panels.scripts; + + var body = msg.getBody(); + // No script field in the body means that v8 failed to parse the script. We + // resume execution on parser errors automatically. + if (this.pauseOnExceptions_ && body.script) { + var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(body.sourceLine); + this.createExceptionMessage_(body.script.name, line, body.exception.text); + this.requestBacktrace_(); + } else + this.resumeExecution(); +}; + + +/** + * @param {devtools.DebuggerMessage} msg + */ +devtools.DebuggerAgent.prototype.handleScriptsResponse_ = function(msg) +{ + var scripts = msg.getBody(); + for (var i = 0; i < scripts.length; i++) { + var script = scripts[i]; + + // Skip scripts from other tabs. + if (!this.isScriptFromInspectedContext_(script, msg)) + continue; + + // We may already have received the info in an afterCompile event. + if (script.id in this.parsedScripts_) + continue; + this.addScriptInfo_(script, msg); + } +}; + + +/** + * @param {Object} script Json object representing script. + * @param {devtools.DebuggerMessage} msg Debugger response. + */ +devtools.DebuggerAgent.prototype.isScriptFromInspectedContext_ = function(script, msg) +{ + if (!script.context) { + // Always ignore scripts from the utility context. + return false; + } + var context = msg.lookup(script.context.ref); + var scriptContextId = context.data; + if (typeof scriptContextId === "undefined") + return false; // Always ignore scripts from the utility context. + if (this.contextId_ === null) + return true; + // Find the id from context data. The context data has the format "type,id". + var comma = context.data.indexOf(","); + if (comma < 0) + return false; + return (context.data.substring(comma + 1) == this.contextId_); +}; + + +/** + * @param {devtools.DebuggerMessage} msg + */ +devtools.DebuggerAgent.prototype.handleSetBreakpointResponse_ = function(msg) +{ + var requestSeq = msg.getRequestSeq(); + var breakpointInfo = this.requestNumberToBreakpointInfo_[requestSeq]; + if (!breakpointInfo) { + // TODO(yurys): handle this case + return; + } + delete this.requestNumberToBreakpointInfo_[requestSeq]; + if (!msg.isSuccess()) { + // TODO(yurys): handle this case + return; + } + var idInV8 = msg.getBody().breakpoint; + breakpointInfo.setV8Id(idInV8); + + if (breakpointInfo.isRemoved()) + this.requestClearBreakpoint_(idInV8); +}; + + +/** + * @param {devtools.DebuggerMessage} msg + */ +devtools.DebuggerAgent.prototype.handleAfterCompileEvent_ = function(msg) +{ + if (!this.contextId_) { + // Ignore scripts delta if main request has not been issued yet. + return; + } + var script = msg.getBody().script; + + // Ignore scripts from other tabs. + if (!this.isScriptFromInspectedContext_(script, msg)) + return; + this.addScriptInfo_(script, msg); +}; + + +/** + * Adds the script info to the local cache. This method assumes that the script + * is not in the cache yet. + * @param {Object} script Script json object from the debugger message. + * @param {devtools.DebuggerMessage} msg Debugger message containing the script + * data. + */ +devtools.DebuggerAgent.prototype.addScriptInfo_ = function(script, msg) +{ + var context = msg.lookup(script.context.ref); + var contextType; + // Find the type from context data. The context data has the format + // "type,id". + var comma = context.data.indexOf(","); + if (comma < 0) + return + contextType = context.data.substring(0, comma); + this.parsedScripts_[script.id] = new devtools.ScriptInfo(script.id, script.name, script.lineOffset, contextType); + if (this.scriptsPanelInitialized_) { + // Only report script as parsed after scripts panel has been shown. + WebInspector.parsedScriptSource(script.id, script.name, script.source, script.lineOffset); + } +}; + + +/** + * @param {devtools.DebuggerMessage} msg + */ +devtools.DebuggerAgent.prototype.handleClearBreakpointResponse_ = function(msg) +{ + // Do nothing. +}; + + +/** + * Handles response to "backtrace" command. + * @param {devtools.DebuggerMessage} msg + */ +devtools.DebuggerAgent.prototype.handleBacktraceResponse_ = function(msg) +{ + if (this.waitingForInitialScriptsResponse_) + this.pendingBacktraceResponseHandler_ = this.doHandleBacktraceResponse_.bind(this, msg); + else + this.doHandleBacktraceResponse_(msg); +}; + + +/** + * @param {devtools.DebuggerMessage} msg + */ +devtools.DebuggerAgent.prototype.doHandleBacktraceResponse_ = function(msg) +{ + var frames = msg.getBody().frames; + this.callFrames_ = []; + for (var i = 0; i < frames.length; ++i) + this.callFrames_.push(this.formatCallFrame_(frames[i])); + WebInspector.pausedScript(this.callFrames_); + this.showPendingExceptionMessage_(); + InspectorFrontendHost.activateWindow(); +}; + + +/** + * Evaluates code on given callframe. + */ +devtools.DebuggerAgent.prototype.evaluateInCallFrame = function(callFrameId, code, callback) +{ + var callFrame = this.callFrames_[callFrameId]; + callFrame.evaluate_(code, callback); +}; + + +/** + * Handles response to a command by invoking its callback (if any). + * @param {devtools.DebuggerMessage} msg + * @return {boolean} Whether a callback for the given message was found and + * excuted. + */ +devtools.DebuggerAgent.prototype.invokeCallbackForResponse_ = function(msg) +{ + var callback = this.requestSeqToCallback_[msg.getRequestSeq()]; + if (!callback) { + // It may happend if reset was called. + return false; + } + delete this.requestSeqToCallback_[msg.getRequestSeq()]; + callback(msg); + return true; +}; + + +/** + * @param {Object} stackFrame Frame json object from "backtrace" response. + * @return {!devtools.CallFrame} Object containing information related to the + * call frame in the format expected by ScriptsPanel and its panes. + */ +devtools.DebuggerAgent.prototype.formatCallFrame_ = function(stackFrame) +{ + var func = stackFrame.func; + var sourceId = func.scriptId; + + // Add service script if it does not exist. + var existingScript = this.parsedScripts_[sourceId]; + if (!existingScript) { + this.parsedScripts_[sourceId] = new devtools.ScriptInfo(sourceId, null /* name */, 0 /* line */, "unknown" /* type */, true /* unresolved */); + WebInspector.parsedScriptSource(sourceId, null, null, 0); + } + + var funcName = func.name || func.inferredName || "(anonymous function)"; + var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(stackFrame.line); + + // Add basic scope chain info with scope variables. + var scopeChain = []; + var ScopeType = devtools.DebuggerAgent.ScopeType; + for (var i = 0; i < stackFrame.scopes.length; i++) { + var scope = stackFrame.scopes[i]; + scope.frameNumber = stackFrame.index; + var scopeObjectProxy = new WebInspector.ObjectProxy(0, scope, [], 0, "", true); + scopeObjectProxy.isScope = true; + switch(scope.type) { + case ScopeType.Global: + scopeObjectProxy.isDocument = true; + break; + case ScopeType.Local: + scopeObjectProxy.isLocal = true; + scopeObjectProxy.thisObject = devtools.DebuggerAgent.formatObjectProxy_(stackFrame.receiver); + break; + case ScopeType.With: + // Catch scope is treated as a regular with scope by WebKit so we + // also treat it this way. + case ScopeType.Catch: + scopeObjectProxy.isWithBlock = true; + break; + case ScopeType.Closure: + scopeObjectProxy.isClosure = true; + break; + } + scopeChain.push(scopeObjectProxy); + } + return new devtools.CallFrame(stackFrame.index, "function", funcName, sourceId, line, scopeChain); +}; + + +/** + * Collects properties for an object from the debugger response. + * @param {Object} object An object from the debugger protocol response. + * @param {Array.<WebInspector.ObjectPropertyProxy>} result An array to put the + * properties into. + * @param {boolean} noIntrinsic Whether intrinsic properties should be + * included. + */ +devtools.DebuggerAgent.formatObjectProperties_ = function(object, result, noIntrinsic) +{ + devtools.DebuggerAgent.propertiesToProxies_(object.properties, result); + if (noIntrinsic) + return; + + result.push(new WebInspector.ObjectPropertyProxy("__proto__", devtools.DebuggerAgent.formatObjectProxy_(object.protoObject))); + result.push(new WebInspector.ObjectPropertyProxy("constructor", devtools.DebuggerAgent.formatObjectProxy_(object.constructorFunction))); + // Don't add 'prototype' property since it is one of the regualar properties. +}; + + +/** + * For each property in "properties" creates its proxy representative. + * @param {Array.<Object>} properties Receiver properties or locals array from + * "backtrace" response. + * @param {Array.<WebInspector.ObjectPropertyProxy>} Results holder. + */ +devtools.DebuggerAgent.propertiesToProxies_ = function(properties, result) +{ + var map = {}; + for (var i = 0; i < properties.length; ++i) { + var property = properties[i]; + var name = String(property.name); + if (name in map) + continue; + map[name] = true; + var value = devtools.DebuggerAgent.formatObjectProxy_(property.value); + var propertyProxy = new WebInspector.ObjectPropertyProxy(name, value); + result.push(propertyProxy); + } +}; + + +/** + * @param {Object} v An object reference from the debugger response. + * @return {*} The value representation expected by ScriptsPanel. + */ +devtools.DebuggerAgent.formatObjectProxy_ = function(v) +{ + var description; + var hasChildren = false; + if (v.type === "object") { + description = v.className; + hasChildren = true; + } else if (v.type === "function") { + if (v.source) + description = v.source; + else + description = "function " + v.name + "()"; + hasChildren = true; + } else if (v.type === "undefined") + description = "undefined"; + else if (v.type === "null") + description = "null"; + else if (typeof v.value !== "undefined") { + // Check for undefined and null types before checking the value, otherwise + // null/undefined may have blank value. + description = v.value; + } else + description = "<unresolved ref: " + v.ref + ", type: " + v.type + ">"; + + var proxy = new WebInspector.ObjectProxy(0, v, [], 0, description, hasChildren); + proxy.type = v.type; + proxy.isV8Ref = true; + return proxy; +}; + + +/** + * Converts line number from Web Inspector UI(1-based) to v8(0-based). + * @param {number} line Resource line number in Web Inspector UI. + * @return {number} The line number in v8. + */ +devtools.DebuggerAgent.webkitToV8LineNumber_ = function(line) +{ + return line - 1; +}; + + +/** + * Converts line number from v8(0-based) to Web Inspector UI(1-based). + * @param {number} line Resource line number in v8. + * @return {number} The line number in Web Inspector. + */ +devtools.DebuggerAgent.v8ToWwebkitLineNumber_ = function(line) +{ + return line + 1; +}; + + +/** + * @param {number} scriptId Id of the script. + * @param {?string} url Script resource URL if any. + * @param {number} lineOffset First line 0-based offset in the containing + * document. + * @param {string} contextType Type of the script's context: + * "page" - regular script from html page + * "injected" - extension content script + * @param {bool} opt_isUnresolved If true, script will not be resolved. + * @constructor + */ +devtools.ScriptInfo = function(scriptId, url, lineOffset, contextType, opt_isUnresolved) +{ + this.scriptId_ = scriptId; + this.lineOffset_ = lineOffset; + this.contextType_ = contextType; + this.url_ = url; + this.isUnresolved_ = opt_isUnresolved; + + this.lineToBreakpointInfo_ = {}; +}; + + +/** + * @return {number} + */ +devtools.ScriptInfo.prototype.getLineOffset = function() +{ + return this.lineOffset_; +}; + + +/** + * @return {string} + */ +devtools.ScriptInfo.prototype.getContextType = function() +{ + return this.contextType_; +}; + + +/** + * @return {?string} + */ +devtools.ScriptInfo.prototype.getUrl = function() +{ + return this.url_; +}; + + +/** + * @return {?bool} + */ +devtools.ScriptInfo.prototype.isUnresolved = function() +{ + return this.isUnresolved_; +}; + + +/** + * @param {number} line 0-based line number in the script. + * @return {?devtools.BreakpointInfo} Information on a breakpoint at the + * specified line in the script or undefined if there is no breakpoint at + * that line. + */ +devtools.ScriptInfo.prototype.getBreakpointInfo = function(line) +{ + return this.lineToBreakpointInfo_[line]; +}; + + +/** + * Adds breakpoint info to the script. + * @param {devtools.BreakpointInfo} breakpoint + */ +devtools.ScriptInfo.prototype.addBreakpointInfo = function(breakpoint) +{ + this.lineToBreakpointInfo_[breakpoint.getLine()] = breakpoint; +}; + + +/** + * @param {devtools.BreakpointInfo} breakpoint Breakpoint info to be removed. + */ +devtools.ScriptInfo.prototype.removeBreakpointInfo = function(breakpoint) +{ + var line = breakpoint.getLine(); + delete this.lineToBreakpointInfo_[line]; +}; + + + +/** + * @param {number} line Breakpoint 0-based line number in the containing script. + * @constructor + */ +devtools.BreakpointInfo = function(line) +{ + this.line_ = line; + this.v8id_ = -1; + this.removed_ = false; +}; + + +/** + * @return {number} + */ +devtools.BreakpointInfo.prototype.getLine = function(n) +{ + return this.line_; +}; + + +/** + * @return {number} Unique identifier of this breakpoint in the v8 debugger. + */ +devtools.BreakpointInfo.prototype.getV8Id = function(n) +{ + return this.v8id_; +}; + + +/** + * Sets id of this breakpoint in the v8 debugger. + * @param {number} id + */ +devtools.BreakpointInfo.prototype.setV8Id = function(id) +{ + this.v8id_ = id; +}; + + +/** + * Marks this breakpoint as removed from the front-end. + */ +devtools.BreakpointInfo.prototype.markAsRemoved = function() +{ + this.removed_ = true; +}; + + +/** + * @return {boolean} Whether this breakpoint has been removed from the + * front-end. + */ +devtools.BreakpointInfo.prototype.isRemoved = function() +{ + return this.removed_; +}; + + +/** + * Call stack frame data. + * @param {string} id CallFrame id. + * @param {string} type CallFrame type. + * @param {string} functionName CallFrame type. + * @param {string} sourceID Source id. + * @param {number} line Source line. + * @param {Array.<Object>} scopeChain Array of scoped objects. + * @construnctor + */ +devtools.CallFrame = function(id, type, functionName, sourceID, line, scopeChain) +{ + this.id = id; + this.type = type; + this.functionName = functionName; + this.sourceID = sourceID; + this.line = line; + this.scopeChain = scopeChain; +}; + + +/** + * This method issues asynchronous evaluate request, reports result to the + * callback. + * @param {string} expression An expression to be evaluated in the context of + * this call frame. + * @param {function(Object):undefined} callback Callback to report result to. + */ +devtools.CallFrame.prototype.evaluate_ = function(expression, callback) +{ + devtools.tools.getDebuggerAgent().requestEvaluate({ + "expression": expression, + "frame": this.id, + "global": false, + "disable_break": false, + "compactFormat": true + }, + function(response) { + var result = {}; + if (response.isSuccess()) + result.value = devtools.DebuggerAgent.formatObjectProxy_(response.getBody()); + else { + result.value = response.getMessage(); + result.isException = true; + } + callback(result); + }); +}; + + +/** + * JSON based commands sent to v8 debugger. + * @param {string} command Name of the command to execute. + * @param {Object} opt_arguments Command-specific arguments map. + * @constructor + */ +devtools.DebugCommand = function(command, opt_arguments) +{ + this.command_ = command; + this.type_ = "request"; + this.seq_ = ++devtools.DebugCommand.nextSeq_; + if (opt_arguments) + this.arguments_ = opt_arguments; +}; + + +/** + * Next unique number to be used as debugger request sequence number. + * @type {number} + */ +devtools.DebugCommand.nextSeq_ = 1; + + +/** + * @return {number} + */ +devtools.DebugCommand.prototype.getSequenceNumber = function() +{ + return this.seq_; +}; + + +/** + * @return {string} + */ +devtools.DebugCommand.prototype.toJSONProtocol = function() +{ + var json = { + "seq": this.seq_, + "type": this.type_, + "command": this.command_ + } + if (this.arguments_) + json.arguments = this.arguments_; + return JSON.stringify(json); +}; + + +/** + * JSON messages sent from v8 debugger. See protocol definition for more + * details: http://code.google.com/p/v8/wiki/DebuggerProtocol + * @param {string} msg Raw protocol packet as JSON string. + * @constructor + */ +devtools.DebuggerMessage = function(msg) +{ + this.packet_ = JSON.parse(msg); + this.refs_ = []; + if (this.packet_.refs) { + for (var i = 0; i < this.packet_.refs.length; i++) + this.refs_[this.packet_.refs[i].handle] = this.packet_.refs[i]; + } +}; + + +/** + * @return {string} The packet type. + */ +devtools.DebuggerMessage.prototype.getType = function() +{ + return this.packet_.type; +}; + + +/** + * @return {?string} The packet event if the message is an event. + */ +devtools.DebuggerMessage.prototype.getEvent = function() +{ + return this.packet_.event; +}; + + +/** + * @return {?string} The packet command if the message is a response to a + * command. + */ +devtools.DebuggerMessage.prototype.getCommand = function() +{ + return this.packet_.command; +}; + + +/** + * @return {number} The packet request sequence. + */ +devtools.DebuggerMessage.prototype.getRequestSeq = function() +{ + return this.packet_.request_seq; +}; + + +/** + * @return {number} Whether the v8 is running after processing the request. + */ +devtools.DebuggerMessage.prototype.isRunning = function() +{ + return this.packet_.running ? true : false; +}; + + +/** + * @return {boolean} Whether the request succeeded. + */ +devtools.DebuggerMessage.prototype.isSuccess = function() +{ + return this.packet_.success ? true : false; +}; + + +/** + * @return {string} + */ +devtools.DebuggerMessage.prototype.getMessage = function() +{ + return this.packet_.message; +}; + + +/** + * @return {Object} Parsed message body json. + */ +devtools.DebuggerMessage.prototype.getBody = function() +{ + return this.packet_.body; +}; + + +/** + * @param {number} handle Object handle. + * @return {?Object} Returns the object with the handle if it was sent in this + * message(some objects referenced by handles may be missing in the message). + */ +devtools.DebuggerMessage.prototype.lookup = function(handle) +{ + return this.refs_[handle]; +}; diff --git a/WebKit/chromium/src/js/DevTools.js b/WebKit/chromium/src/js/DevTools.js new file mode 100644 index 0000000..dcb181b --- /dev/null +++ b/WebKit/chromium/src/js/DevTools.js @@ -0,0 +1,504 @@ +/* + * Copyright (C) 2010 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 + * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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. + */ + +/** + * FIXME: change field naming style to use trailing underscore. + * @fileoverview Tools is a main class that wires all components of the + * DevTools frontend together. It is also responsible for overriding existing + * WebInspector functionality while it is getting upstreamed into WebCore. + */ + +/** + * Dispatches raw message from the host. + * @param {string} remoteName + * @prama {string} methodName + * @param {string} param1, param2, param3 Arguments to dispatch. + */ +devtools$$dispatch = function(remoteName, methodName, param1, param2, param3) +{ + remoteName = "Remote" + remoteName.substring(0, remoteName.length - 8); + var agent = window[remoteName]; + if (!agent) { + debugPrint("No remote agent '" + remoteName + "' found."); + return; + } + var method = agent[methodName]; + if (!method) { + debugPrint("No method '" + remoteName + "." + methodName + "' found."); + return; + } + method.call(this, param1, param2, param3); +}; + + +devtools.ToolsAgent = function() +{ + RemoteToolsAgent.didDispatchOn = WebInspector.Callback.processCallback; + RemoteToolsAgent.frameNavigate = this.frameNavigate_.bind(this); + RemoteToolsAgent.dispatchOnClient = this.dispatchOnClient_.bind(this); + this.debuggerAgent_ = new devtools.DebuggerAgent(); + this.profilerAgent_ = new devtools.ProfilerAgent(); +}; + + +/** + * Resets tools agent to its initial state. + */ +devtools.ToolsAgent.prototype.reset = function() +{ + this.debuggerAgent_.reset(); +}; + + +/** + * @param {string} script Script exression to be evaluated in the context of the + * inspected page. + * @param {function(Object|string, boolean):undefined} opt_callback Function to + * call with the result. + */ +devtools.ToolsAgent.prototype.evaluateJavaScript = function(script, opt_callback) +{ + InspectorBackend.evaluate(script, opt_callback || function() {}); +}; + + +/** + * @return {devtools.DebuggerAgent} Debugger agent instance. + */ +devtools.ToolsAgent.prototype.getDebuggerAgent = function() +{ + return this.debuggerAgent_; +}; + + +/** + * @return {devtools.ProfilerAgent} Profiler agent instance. + */ +devtools.ToolsAgent.prototype.getProfilerAgent = function() +{ + return this.profilerAgent_; +}; + + +/** + * @param {string} url Url frame navigated to. + * @see tools_agent.h + * @private + */ +devtools.ToolsAgent.prototype.frameNavigate_ = function(url) +{ + this.reset(); + // Do not reset Profiles panel. + var profiles = null; + if ("profiles" in WebInspector.panels) { + profiles = WebInspector.panels["profiles"]; + delete WebInspector.panels["profiles"]; + } + WebInspector.reset(); + if (profiles !== null) + WebInspector.panels["profiles"] = profiles; +}; + + +/** + * @param {string} message Serialized call to be dispatched on WebInspector. + * @private + */ +devtools.ToolsAgent.prototype.dispatchOnClient_ = function(message) +{ + var args = JSON.parse(message); + var methodName = args[0]; + var parameters = args.slice(1); + WebInspector[methodName].apply(WebInspector, parameters); +}; + + +/** + * Evaluates js expression. + * @param {string} expr + */ +devtools.ToolsAgent.prototype.evaluate = function(expr) +{ + RemoteToolsAgent.evaluate(expr); +}; + + +/** + * Enables / disables resources panel in the ui. + * @param {boolean} enabled New panel status. + */ +WebInspector.setResourcesPanelEnabled = function(enabled) +{ + InspectorBackend._resourceTrackingEnabled = enabled; + WebInspector.panels.resources.reset(); +}; + + +/** + * Prints string to the inspector console or shows alert if the console doesn't + * exist. + * @param {string} text + */ +function debugPrint(text) { + var console = WebInspector.console; + if (console) { + console.addMessage(new WebInspector.ConsoleMessage( + WebInspector.ConsoleMessage.MessageSource.JS, + WebInspector.ConsoleMessage.MessageType.Log, + WebInspector.ConsoleMessage.MessageLevel.Log, + 1, "chrome://devtools/<internal>", undefined, -1, text)); + } else + alert(text); +} + + +/** + * Global instance of the tools agent. + * @type {devtools.ToolsAgent} + */ +devtools.tools = null; + + +var context = {}; // Used by WebCore's inspector routines. + +/////////////////////////////////////////////////////////////////////////////// +// Here and below are overrides to existing WebInspector methods only. +// TODO(pfeldman): Patch WebCore and upstream changes. +var oldLoaded = WebInspector.loaded; +WebInspector.loaded = function() +{ + devtools.tools = new devtools.ToolsAgent(); + devtools.tools.reset(); + + Preferences.ignoreWhitespace = false; + Preferences.samplingCPUProfiler = true; + Preferences.heapProfilerPresent = true; + oldLoaded.call(this); + + InspectorFrontendHost.loaded(); +}; + + +(function() +{ + + /** + * Handles an F3 keydown event to focus the Inspector search box. + * @param {KeyboardEvent} event Event to optionally handle + * @return {boolean} whether the event has been handled + */ + function handleF3Keydown(event) { + if (event.keyIdentifier === "F3" && !event.altKey && !event.ctrlKey && !event.shiftKey && !event.metaKey) { + var searchField = document.getElementById("search"); + searchField.focus(); + searchField.select(); + event.preventDefault(); + return true; + } + return false; + } + + + var oldKeyDown = WebInspector.documentKeyDown; + /** + * This override allows to intercept keydown events we want to handle in a + * custom way. Some nested documents (iframes) delegate keydown handling to + * WebInspector.documentKeyDown (e.g. SourceFrame). + * @param {KeyboardEvent} event + * @override + */ + WebInspector.documentKeyDown = function(event) { + var isHandled = handleF3Keydown(event); + if (!isHandled) { + // Mute refresh action. + if (event.keyIdentifier === "F5") + event.preventDefault(); + else if (event.keyIdentifier === "U+0052" /* "R" */ && (event.ctrlKey || event.metaKey)) + event.preventDefault(); + else + oldKeyDown.call(this, event); + } + }; +})(); + + +/** + * This override is necessary for adding script source asynchronously. + * @override + */ +WebInspector.ScriptView.prototype.setupSourceFrameIfNeeded = function() +{ + if (!this._frameNeedsSetup) + return; + + this.attach(); + + if (this.script.source) + this.didResolveScriptSource_(); + else { + var self = this; + devtools.tools.getDebuggerAgent().resolveScriptSource( + this.script.sourceID, + function(source) { + self.script.source = source || WebInspector.UIString("<source is not available>"); + self.didResolveScriptSource_(); + }); + } +}; + + +/** + * Performs source frame setup when script source is aready resolved. + */ +WebInspector.ScriptView.prototype.didResolveScriptSource_ = function() +{ + this.sourceFrame.setContent("text/javascript", this.script.source); + this._sourceFrameSetup = true; + delete this._frameNeedsSetup; +}; + + +/** + * @param {string} type Type of the the property value("object" or "function"). + * @param {string} className Class name of the property value. + * @constructor + */ +WebInspector.UnresolvedPropertyValue = function(type, className) +{ + this.type = type; + this.className = className; +}; + + +(function() +{ + var oldShow = WebInspector.ScriptsPanel.prototype.show; + WebInspector.ScriptsPanel.prototype.show = function() + { + devtools.tools.getDebuggerAgent().initUI(); + this.enableToggleButton.visible = false; + oldShow.call(this); + }; +})(); + + +(function InterceptProfilesPanelEvents() +{ + var oldShow = WebInspector.ProfilesPanel.prototype.show; + WebInspector.ProfilesPanel.prototype.show = function() + { + devtools.tools.getProfilerAgent().initializeProfiling(); + this.enableToggleButton.visible = false; + oldShow.call(this); + // Show is called on every show event of a panel, so + // we only need to intercept it once. + WebInspector.ProfilesPanel.prototype.show = oldShow; + }; +})(); + + +/* + * @override + * TODO(mnaganov): Restore l10n when it will be agreed that it is needed. + */ +WebInspector.UIString = function(string) +{ + return String.vsprintf(string, Array.prototype.slice.call(arguments, 1)); +}; + + +// There is no clear way of setting frame title yet. So sniffing main resource +// load. +(function OverrideUpdateResource() { + var originalUpdateResource = WebInspector.updateResource; + WebInspector.updateResource = function(identifier, payload) + { + originalUpdateResource.call(this, identifier, payload); + var resource = this.resources[identifier]; + if (resource && resource.mainResource && resource.finished) + document.title = WebInspector.UIString("Developer Tools - %s", resource.url); + }; +})(); + + +// Highlight extension content scripts in the scripts list. +(function () { + var original = WebInspector.ScriptsPanel.prototype._addScriptToFilesMenu; + WebInspector.ScriptsPanel.prototype._addScriptToFilesMenu = function(script) + { + var result = original.apply(this, arguments); + var debuggerAgent = devtools.tools.getDebuggerAgent(); + var type = debuggerAgent.getScriptContextType(script.sourceID); + var option = script.filesSelectOption; + if (type === "injected" && option) + option.addStyleClass("injected"); + return result; + }; +})(); + + +/** Pending WebKit upstream by apavlov). Fixes iframe vs drag problem. */ +(function() +{ + var originalDragStart = WebInspector.elementDragStart; + WebInspector.elementDragStart = function(element) + { + if (element) { + var glassPane = document.createElement("div"); + glassPane.style.cssText = "position:absolute;width:100%;height:100%;opacity:0;z-index:1"; + glassPane.id = "glass-pane-for-drag"; + element.parentElement.appendChild(glassPane); + } + + originalDragStart.apply(this, arguments); + }; + + var originalDragEnd = WebInspector.elementDragEnd; + WebInspector.elementDragEnd = function() + { + originalDragEnd.apply(this, arguments); + + var glassPane = document.getElementById("glass-pane-for-drag"); + if (glassPane) + glassPane.parentElement.removeChild(glassPane); + }; +})(); + + +(function () { +var orig = InjectedScriptAccess.prototype.getProperties; +InjectedScriptAccess.prototype.getProperties = function(objectProxy, ignoreHasOwnProperty, abbreviate, callback) +{ + if (objectProxy.isScope) + devtools.tools.getDebuggerAgent().resolveScope(objectProxy.objectId, callback); + else if (objectProxy.isV8Ref) + devtools.tools.getDebuggerAgent().resolveChildren(objectProxy.objectId, callback, false); + else + orig.apply(this, arguments); +}; +})(); + + +(function() +{ +InjectedScriptAccess.prototype.evaluateInCallFrame = function(callFrameId, code, objectGroup, callback) +{ + //TODO(pfeldman): remove once 49084 is rolled. + if (!callback) + callback = objectGroup; + devtools.tools.getDebuggerAgent().evaluateInCallFrame(callFrameId, code, callback); +}; +})(); + + +WebInspector.resourceTrackingWasEnabled = function() +{ + InspectorBackend._resourceTrackingEnabled = true; + this.panels.resources.resourceTrackingWasEnabled(); +}; + +WebInspector.resourceTrackingWasDisabled = function() +{ + InspectorBackend._resourceTrackingEnabled = false; + this.panels.resources.resourceTrackingWasDisabled(); +}; + +(function() +{ +var orig = WebInspector.ConsoleMessage.prototype.setMessageBody; +WebInspector.ConsoleMessage.prototype.setMessageBody = function(args) +{ + for (var i = 0; i < args.length; ++i) { + if (typeof args[i] === "string") + args[i] = WebInspector.ObjectProxy.wrapPrimitiveValue(args[i]); + } + orig.call(this, args); +}; +})(); + + +(function() +{ +var orig = InjectedScriptAccess.prototype.getCompletions; +InjectedScriptAccess.prototype.getCompletions = function(expressionString, includeInspectorCommandLineAPI, callFrameId, reportCompletions) +{ + if (typeof callFrameId === "number") + devtools.tools.getDebuggerAgent().resolveCompletionsOnFrame(expressionString, callFrameId, reportCompletions); + else + return orig.apply(this, arguments); +}; +})(); + + +(function() +{ +WebInspector.ElementsPanel.prototype._nodeSearchButtonClicked = function( event) +{ + InspectorBackend.toggleNodeSearch(); + this.nodeSearchButton.toggled = !this.nodeSearchButton.toggled; +}; +})(); + + +// We need to have a place for postponed tasks +// which should be executed when all the messages between agent and frontend +// are processed. + +WebInspector.runAfterPendingDispatchesQueue = []; + +WebInspector.TestController.prototype.runAfterPendingDispatches = function(callback) +{ + WebInspector.runAfterPendingDispatchesQueue.push(callback); +}; + +WebInspector.queuesAreEmpty = function() +{ + var copy = this.runAfterPendingDispatchesQueue.slice(); + this.runAfterPendingDispatchesQueue = []; + for (var i = 0; i < copy.length; ++i) + copy[i].call(this); +}; + +(function() +{ +var originalAddToFrame = InspectorFrontendHost.addResourceSourceToFrame; +InspectorFrontendHost.addResourceSourceToFrame = function(identifier, element) +{ + var resource = WebInspector.resources[identifier]; + if (!resource) + return; + originalAddToFrame.call(this, identifier, resource.mimeType, element); +}; +})(); + +WebInspector.pausedScript = function(callFrames) +{ + this.panels.scripts.debuggerPaused(callFrames); +}; diff --git a/WebKit/chromium/src/js/DevToolsHostStub.js b/WebKit/chromium/src/js/DevToolsHostStub.js new file mode 100644 index 0000000..8b2f46b --- /dev/null +++ b/WebKit/chromium/src/js/DevToolsHostStub.js @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2010 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 + * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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. + */ + +/** + * @fileoverview These stubs emulate backend functionality and allows + * DevTools frontend to function as a standalone web app. + */ + +if (!window["RemoteDebuggerAgent"]) { + +/** + * FIXME: change field naming style to use trailing underscore. + * @constructor + */ +RemoteDebuggerAgentStub = function() +{ +}; + + +RemoteDebuggerAgentStub.prototype.getContextId = function() +{ + RemoteDebuggerAgent.setContextId(3); +}; + + +RemoteDebuggerAgentStub.prototype.processDebugCommands = function() +{ +}; + + +/** + * @constructor + */ +RemoteProfilerAgentStub = function() +{ +}; + + +RemoteProfilerAgentStub.prototype.getActiveProfilerModules = function() +{ + ProfilerStubHelper.GetInstance().getActiveProfilerModules(); +}; + + +RemoteProfilerAgentStub.prototype.getLogLines = function(pos) +{ + ProfilerStubHelper.GetInstance().getLogLines(pos); +}; + + +/** + * @constructor + */ +RemoteToolsAgentStub = function() +{ +}; + + +RemoteToolsAgentStub.prototype.dispatchOnInjectedScript = function() +{ +}; + + +RemoteToolsAgentStub.prototype.dispatchOnInspectorController = function() +{ +}; + + +/** + * @constructor + */ +ProfilerStubHelper = function() +{ + this.activeProfilerModules_ = devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_NONE; + this.heapProfSample_ = 0; + this.log_ = ''; +}; + + +ProfilerStubHelper.GetInstance = function() +{ + if (!ProfilerStubHelper.instance_) + ProfilerStubHelper.instance_ = new ProfilerStubHelper(); + return ProfilerStubHelper.instance_; +}; + + +ProfilerStubHelper.prototype.StopProfiling = function(modules) +{ + this.activeProfilerModules_ &= ~modules; +}; + + +ProfilerStubHelper.prototype.StartProfiling = function(modules) +{ + var profModules = devtools.ProfilerAgent.ProfilerModules; + if (modules & profModules.PROFILER_MODULE_HEAP_SNAPSHOT) { + if (modules & profModules.PROFILER_MODULE_HEAP_STATS) { + this.log_ += + 'heap-sample-begin,"Heap","allocated",' + + (new Date()).getTime() + '\n' + + 'heap-sample-stats,"Heap","allocated",10000,1000\n'; + this.log_ += + 'heap-sample-item,STRING_TYPE,100,1000\n' + + 'heap-sample-item,CODE_TYPE,10,200\n' + + 'heap-sample-item,MAP_TYPE,20,350\n'; + this.log_ += ProfilerStubHelper.HeapSamples[this.heapProfSample_++]; + this.heapProfSample_ %= ProfilerStubHelper.HeapSamples.length; + this.log_ += 'heap-sample-end,"Heap","allocated"\n'; + } + } else { + if (modules & profModules.PROFILER_MODULE_CPU) + this.log_ += ProfilerStubHelper.ProfilerLogBuffer; + this.activeProfilerModules_ |= modules; + } +}; + + +ProfilerStubHelper.prototype.getActiveProfilerModules = function() +{ + var self = this; + setTimeout(function() { + RemoteProfilerAgent.didGetActiveProfilerModules(self.activeProfilerModules_); + }, 100); +}; + + +ProfilerStubHelper.prototype.getLogLines = function(pos) +{ + var profModules = devtools.ProfilerAgent.ProfilerModules; + var logLines = this.log_.substr(pos); + setTimeout(function() { + RemoteProfilerAgent.didGetLogLines(pos + logLines.length, logLines); + }, 100); +}; + + +ProfilerStubHelper.ProfilerLogBuffer = + 'profiler,begin,1\n' + + 'profiler,resume\n' + + 'code-creation,LazyCompile,0x1000,256,"test1 http://aaa.js:1"\n' + + 'code-creation,LazyCompile,0x2000,256,"test2 http://bbb.js:2"\n' + + 'code-creation,LazyCompile,0x3000,256,"test3 http://ccc.js:3"\n' + + 'tick,0x1010,0x0,3\n' + + 'tick,0x2020,0x0,3,0x1010\n' + + 'tick,0x2020,0x0,3,0x1010\n' + + 'tick,0x3010,0x0,3,0x2020, 0x1010\n' + + 'tick,0x2020,0x0,3,0x1010\n' + + 'tick,0x2030,0x0,3,0x2020, 0x1010\n' + + 'tick,0x2020,0x0,3,0x1010\n' + + 'tick,0x1010,0x0,3\n' + + 'profiler,pause\n'; + + +ProfilerStubHelper.HeapSamples = [ + 'heap-js-cons-item,foo,1,100\n' + + 'heap-js-cons-item,bar,20,2000\n' + + 'heap-js-cons-item,Object,5,100\n' + + 'heap-js-ret-item,foo,bar;3\n' + + 'heap-js-ret-item,bar,foo;5\n' + + 'heap-js-ret-item,Object:0x1234,(roots);1\n', + + 'heap-js-cons-item,foo,2000,200000\n' + + 'heap-js-cons-item,bar,10,1000\n' + + 'heap-js-cons-item,Object,6,120\n' + + 'heap-js-ret-item,foo,bar;7,Object:0x1234;10\n' + + 'heap-js-ret-item,bar,foo;10,Object:0x1234;10\n' + + 'heap-js-ret-item,Object:0x1234,(roots);1\n', + + 'heap-js-cons-item,foo,15,1500\n' + + 'heap-js-cons-item,bar,15,1500\n' + + 'heap-js-cons-item,Object,5,100\n' + + 'heap-js-cons-item,Array,3,1000\n' + + 'heap-js-ret-item,foo,bar;3,Array:0x5678;1\n' + + 'heap-js-ret-item,bar,foo;5,Object:0x1234;8,Object:0x5678;2\n' + + 'heap-js-ret-item,Object:0x1234,(roots);1,Object:0x5678;2\n' + + 'heap-js-ret-item,Object:0x5678,(global property);3,Object:0x1234;5\n' + + 'heap-js-ret-item,Array:0x5678,(global property);3,Array:0x5678;2\n', + + 'heap-js-cons-item,bar,20,2000\n' + + 'heap-js-cons-item,Object,6,120\n' + + 'heap-js-ret-item,bar,foo;5,Object:0x1234;1,Object:0x1235;3\n' + + 'heap-js-ret-item,Object:0x1234,(global property);3\n' + + 'heap-js-ret-item,Object:0x1235,(global property);5\n', + + 'heap-js-cons-item,foo,15,1500\n' + + 'heap-js-cons-item,bar,15,1500\n' + + 'heap-js-cons-item,Array,10,1000\n' + + 'heap-js-ret-item,foo,bar;1,Array:0x5678;1\n' + + 'heap-js-ret-item,bar,foo;5\n' + + 'heap-js-ret-item,Array:0x5678,(roots);3\n', + + 'heap-js-cons-item,bar,20,2000\n' + + 'heap-js-cons-item,baz,15,1500\n' + + 'heap-js-ret-item,bar,baz;3\n' + + 'heap-js-ret-item,baz,bar;3\n' +]; + + +/** + * @constructor + */ +RemoteDebuggerCommandExecutorStub = function() +{ +}; + + +RemoteDebuggerCommandExecutorStub.prototype.DebuggerCommand = function(cmd) +{ + if ('{"seq":2,"type":"request","command":"scripts","arguments":{"includeSource":false}}' === cmd) { + var response1 = + '{"seq":5,"request_seq":2,"type":"response","command":"scripts","' + + 'success":true,"body":[{"handle":61,"type":"script","name":"' + + 'http://www/~test/t.js","id":59,"lineOffset":0,"columnOffset":0,' + + '"lineCount":1,"sourceStart":"function fib(n) {","sourceLength":300,' + + '"scriptType":2,"compilationType":0,"context":{"ref":60}}],"refs":[{' + + '"handle":60,"type":"context","data":"page,3"}],"running":false}'; + this.sendResponse_(response1); + } else if ('{"seq":3,"type":"request","command":"scripts","arguments":{"ids":[59],"includeSource":true}}' === cmd) { + this.sendResponse_( + '{"seq":8,"request_seq":3,"type":"response","command":"scripts",' + + '"success":true,"body":[{"handle":1,"type":"script","name":' + + '"http://www/~test/t.js","id":59,"lineOffset":0,"columnOffset":0,' + + '"lineCount":1,"source":"function fib(n) {return n+1;}",' + + '"sourceLength":244,"scriptType":2,"compilationType":0,"context":{' + + '"ref":0}}],"refs":[{"handle":0,"type":"context","data":"page,3}],"' + + '"running":false}'); + } else if (cmd.indexOf('"command":"profile"') !== -1) { + var cmdObj = JSON.parse(cmd); + if (cmdObj.arguments.command === "resume") + ProfilerStubHelper.GetInstance().StartProfiling(parseInt(cmdObj.arguments.modules)); + else if (cmdObj.arguments.command === "pause") + ProfilerStubHelper.GetInstance().StopProfiling(parseInt(cmdObj.arguments.modules)); + else + debugPrint("Unexpected profile command: " + cmdObj.arguments.command); + } else + debugPrint("Unexpected command: " + cmd); +}; + + +RemoteDebuggerCommandExecutorStub.prototype.DebuggerPauseScript = function() +{ +}; + + +RemoteDebuggerCommandExecutorStub.prototype.sendResponse_ = function(response) +{ + setTimeout(function() { + RemoteDebuggerAgent.debuggerOutput(response); + }, 0); +}; + + +DevToolsHostStub = function() +{ + this.isStub = true; +}; +DevToolsHostStub.prototype.__proto__ = WebInspector.InspectorFrontendHostStub.prototype; + + +DevToolsHostStub.prototype.reset = function() +{ +}; + + +DevToolsHostStub.prototype.setting = function() +{ +}; + + +DevToolsHostStub.prototype.setSetting = function() +{ +}; + + +window["RemoteDebuggerAgent"] = new RemoteDebuggerAgentStub(); +window["RemoteDebuggerCommandExecutor"] = new RemoteDebuggerCommandExecutorStub(); +window["RemoteProfilerAgent"] = new RemoteProfilerAgentStub(); +window["RemoteToolsAgent"] = new RemoteToolsAgentStub(); +InspectorFrontendHost = new DevToolsHostStub(); + +} diff --git a/WebKit/chromium/src/js/HeapProfilerPanel.js b/WebKit/chromium/src/js/HeapProfilerPanel.js new file mode 100644 index 0000000..abbf580 --- /dev/null +++ b/WebKit/chromium/src/js/HeapProfilerPanel.js @@ -0,0 +1,966 @@ +/* + * Copyright (C) 2010 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 + * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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. + */ + +/** + * @fileoverview Heap profiler panel implementation. + */ + +WebInspector.ProfilesPanel.prototype.addSnapshot = function(snapshot) { + snapshot.title = WebInspector.UIString("Snapshot %d", snapshot.number); + snapshot.typeId = WebInspector.HeapSnapshotProfileType.TypeId; + + var snapshots = WebInspector.HeapSnapshotProfileType.snapshots; + snapshots.push(snapshot); + + snapshot.listIndex = snapshots.length - 1; + + if (WebInspector.CPUProfile) + this.addProfileHeader(WebInspector.HeapSnapshotProfileType.TypeId, snapshot); + else + this.addProfileHeader(snapshot); + + this.dispatchEventToListeners("snapshot added"); +} + + +WebInspector.HeapSnapshotView = function(parent, profile) +{ + WebInspector.View.call(this); + + this.element.addStyleClass("heap-snapshot-view"); + + this.parent = parent; + this.parent.addEventListener("snapshot added", this._updateBaseOptions, this); + + this.showCountAsPercent = false; + this.showSizeAsPercent = false; + this.showCountDeltaAsPercent = false; + this.showSizeDeltaAsPercent = false; + + this.categories = { + code: new WebInspector.ResourceCategory("code", WebInspector.UIString("Code"), "rgb(255,121,0)"), + data: new WebInspector.ResourceCategory("data", WebInspector.UIString("Objects"), "rgb(47,102,236)") + }; + + var summaryContainer = document.createElement("div"); + summaryContainer.id = "heap-snapshot-summary-container"; + + this.countsSummaryBar = new WebInspector.SummaryBar(this.categories); + this.countsSummaryBar.element.className = "heap-snapshot-summary"; + this.countsSummaryBar.calculator = new WebInspector.HeapSummaryCountCalculator(); + var countsLabel = document.createElement("div"); + countsLabel.className = "heap-snapshot-summary-label"; + countsLabel.textContent = WebInspector.UIString("Count"); + this.countsSummaryBar.element.appendChild(countsLabel); + summaryContainer.appendChild(this.countsSummaryBar.element); + + this.sizesSummaryBar = new WebInspector.SummaryBar(this.categories); + this.sizesSummaryBar.element.className = "heap-snapshot-summary"; + this.sizesSummaryBar.calculator = new WebInspector.HeapSummarySizeCalculator(); + var sizesLabel = document.createElement("label"); + sizesLabel.className = "heap-snapshot-summary-label"; + sizesLabel.textContent = WebInspector.UIString("Size"); + this.sizesSummaryBar.element.appendChild(sizesLabel); + summaryContainer.appendChild(this.sizesSummaryBar.element); + + this.element.appendChild(summaryContainer); + + var columns = { "cons": { title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true }, + "count": { title: WebInspector.UIString("Count"), width: "54px", sortable: true }, + "size": { title: WebInspector.UIString("Size"), width: "72px", sort: "descending", sortable: true }, + "countDelta": { title: WebInspector.UIString("\xb1 Count"), width: "72px", sortable: true }, + "sizeDelta": { title: WebInspector.UIString("\xb1 Size"), width: "72px", sortable: true } }; + + this.dataGrid = new WebInspector.DataGrid(columns); + this.dataGrid.addEventListener("sorting changed", this._sortData, this); + this.dataGrid.element.addEventListener("mousedown", this._mouseDownInDataGrid.bind(this), true); + this.element.appendChild(this.dataGrid.element); + + this.profile = profile; + + this.baseSelectElement = document.createElement("select"); + this.baseSelectElement.className = "status-bar-item"; + this.baseSelectElement.addEventListener("change", this._changeBase.bind(this), false); + this._updateBaseOptions(); + if (this.profile.listIndex > 0) + this.baseSelectElement.selectedIndex = this.profile.listIndex - 1; + else + this.baseSelectElement.selectedIndex = this.profile.listIndex; + this._resetDataGridList(); + + this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item status-bar-item"); + this.percentButton.addEventListener("click", this._percentClicked.bind(this), false); + + this.refresh(); + + this._updatePercentButton(); +}; + +WebInspector.HeapSnapshotView.prototype = { + + get statusBarItems() + { + return [this.baseSelectElement, this.percentButton.element]; + }, + + get profile() + { + return this._profile; + }, + + set profile(profile) + { + this._profile = profile; + }, + + show: function(parentElement) + { + WebInspector.View.prototype.show.call(this, parentElement); + this.dataGrid.updateWidths(); + }, + + hide: function() + { + WebInspector.View.prototype.hide.call(this); + this._currentSearchResultIndex = -1; + }, + + resize: function() + { + if (this.dataGrid) + this.dataGrid.updateWidths(); + }, + + refresh: function() + { + this.dataGrid.removeChildren(); + + var children = this.snapshotDataGridList.children; + var count = children.length; + for (var index = 0; index < count; ++index) + this.dataGrid.appendChild(children[index]); + + this._updateSummaryGraph(); + }, + + refreshShowAsPercents: function() + { + this._updatePercentButton(); + this.refreshVisibleData(); + }, + + _deleteSearchMatchedFlags: function(node) + { + delete node._searchMatchedConsColumn; + delete node._searchMatchedCountColumn; + delete node._searchMatchedSizeColumn; + delete node._searchMatchedCountDeltaColumn; + delete node._searchMatchedSizeDeltaColumn; + }, + + searchCanceled: function() + { + if (this._searchResults) { + for (var i = 0; i < this._searchResults.length; ++i) { + var profileNode = this._searchResults[i].profileNode; + this._deleteSearchMatchedFlags(profileNode); + profileNode.refresh(); + } + } + + delete this._searchFinishedCallback; + this._currentSearchResultIndex = -1; + this._searchResults = []; + }, + + performSearch: function(query, finishedCallback) + { + // Call searchCanceled since it will reset everything we need before doing a new search. + this.searchCanceled(); + + query = query.trimWhitespace(); + + if (!query.length) + return; + + this._searchFinishedCallback = finishedCallback; + + var helper = WebInspector.HeapSnapshotView.SearchHelper; + + var operationAndNumber = helper.parseOperationAndNumber(query); + var operation = operationAndNumber[0]; + var queryNumber = operationAndNumber[1]; + + var percentUnits = helper.percents.test(query); + var megaBytesUnits = helper.megaBytes.test(query); + var kiloBytesUnits = helper.kiloBytes.test(query); + var bytesUnits = helper.bytes.test(query); + + var queryNumberBytes = (megaBytesUnits ? (queryNumber * 1024 * 1024) : (kiloBytesUnits ? (queryNumber * 1024) : queryNumber)); + + function matchesQuery(heapSnapshotDataGridNode) + { + WebInspector.HeapSnapshotView.prototype._deleteSearchMatchedFlags(heapSnapshotDataGridNode); + + if (percentUnits) { + heapSnapshotDataGridNode._searchMatchedCountColumn = operation(heapSnapshotDataGridNode.countPercent, queryNumber); + heapSnapshotDataGridNode._searchMatchedSizeColumn = operation(heapSnapshotDataGridNode.sizePercent, queryNumber); + heapSnapshotDataGridNode._searchMatchedCountDeltaColumn = operation(heapSnapshotDataGridNode.countDeltaPercent, queryNumber); + heapSnapshotDataGridNode._searchMatchedSizeDeltaColumn = operation(heapSnapshotDataGridNode.sizeDeltaPercent, queryNumber); + } else if (megaBytesUnits || kiloBytesUnits || bytesUnits) { + heapSnapshotDataGridNode._searchMatchedSizeColumn = operation(heapSnapshotDataGridNode.size, queryNumberBytes); + heapSnapshotDataGridNode._searchMatchedSizeDeltaColumn = operation(heapSnapshotDataGridNode.sizeDelta, queryNumberBytes); + } else { + heapSnapshotDataGridNode._searchMatchedCountColumn = operation(heapSnapshotDataGridNode.count, queryNumber); + heapSnapshotDataGridNode._searchMatchedCountDeltaColumn = operation(heapSnapshotDataGridNode.countDelta, queryNumber); + } + + if (heapSnapshotDataGridNode.constructorName.hasSubstring(query, true)) + heapSnapshotDataGridNode._searchMatchedConsColumn = true; + + if (heapSnapshotDataGridNode._searchMatchedConsColumn || + heapSnapshotDataGridNode._searchMatchedCountColumn || + heapSnapshotDataGridNode._searchMatchedSizeColumn || + heapSnapshotDataGridNode._searchMatchedCountDeltaColumn || + heapSnapshotDataGridNode._searchMatchedSizeDeltaColumn) { + heapSnapshotDataGridNode.refresh(); + return true; + } + + return false; + } + + var current = this.snapshotDataGridList.children[0]; + var depth = 0; + var info = {}; + + // The second and subsequent levels of heap snapshot nodes represent retainers, + // so recursive expansion will be infinite, since a graph is being traversed. + // So default to a recursion cap of 2 levels. + var maxDepth = 2; + + while (current) { + if (matchesQuery(current)) + this._searchResults.push({ profileNode: current }); + current = current.traverseNextNode(false, null, (depth >= maxDepth), info); + depth += info.depthChange; + } + + finishedCallback(this, this._searchResults.length); + }, + + jumpToFirstSearchResult: WebInspector.CPUProfileView.prototype.jumpToFirstSearchResult, + jumpToLastSearchResult: WebInspector.CPUProfileView.prototype.jumpToLastSearchResult, + jumpToNextSearchResult: WebInspector.CPUProfileView.prototype.jumpToNextSearchResult, + jumpToPreviousSearchResult: WebInspector.CPUProfileView.prototype.jumpToPreviousSearchResult, + showingFirstSearchResult: WebInspector.CPUProfileView.prototype.showingFirstSearchResult, + showingLastSearchResult: WebInspector.CPUProfileView.prototype.showingLastSearchResult, + _jumpToSearchResult: WebInspector.CPUProfileView.prototype._jumpToSearchResult, + + refreshVisibleData: function() + { + var child = this.dataGrid.children[0]; + while (child) { + child.refresh(); + child = child.traverseNextNode(false, null, true); + } + this._updateSummaryGraph(); + }, + + _changeBase: function() { + if (this.baseSnapshot === WebInspector.HeapSnapshotProfileType.snapshots[this.baseSelectElement.selectedIndex]) + return; + + this._resetDataGridList(); + this.refresh(); + + if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults) + return; + + // The current search needs to be performed again. First negate out previous match + // count by calling the search finished callback with a negative number of matches. + // Then perform the search again with the same query and callback. + this._searchFinishedCallback(this, -this._searchResults.length); + this.performSearch(this.currentQuery, this._searchFinishedCallback); + }, + + _createSnapshotDataGridList: function() + { + if (this._snapshotDataGridList) + delete this._snapshotDataGridList; + + this._snapshotDataGridList = new WebInspector.HeapSnapshotDataGridList(this, this.baseSnapshot.entries, this.profile.entries); + return this._snapshotDataGridList; + }, + + _mouseDownInDataGrid: function(event) + { + if (event.detail < 2) + return; + + var cell = event.target.enclosingNodeOrSelfWithNodeName("td"); + if (!cell || (!cell.hasStyleClass("count-column") && !cell.hasStyleClass("size-column") && !cell.hasStyleClass("countDelta-column") && !cell.hasStyleClass("sizeDelta-column"))) + return; + + if (cell.hasStyleClass("count-column")) + this.showCountAsPercent = !this.showCountAsPercent; + else if (cell.hasStyleClass("size-column")) + this.showSizeAsPercent = !this.showSizeAsPercent; + else if (cell.hasStyleClass("countDelta-column")) + this.showCountDeltaAsPercent = !this.showCountDeltaAsPercent; + else if (cell.hasStyleClass("sizeDelta-column")) + this.showSizeDeltaAsPercent = !this.showSizeDeltaAsPercent; + + this.refreshShowAsPercents(); + + event.preventDefault(); + event.stopPropagation(); + }, + + get _isShowingAsPercent() + { + return this.showCountAsPercent && this.showSizeAsPercent && this.showCountDeltaAsPercent && this.showSizeDeltaAsPercent; + }, + + _percentClicked: function(event) + { + var currentState = this._isShowingAsPercent; + this.showCountAsPercent = !currentState; + this.showSizeAsPercent = !currentState; + this.showCountDeltaAsPercent = !currentState; + this.showSizeDeltaAsPercent = !currentState; + this.refreshShowAsPercents(); + }, + + _resetDataGridList: function() + { + this.baseSnapshot = WebInspector.HeapSnapshotProfileType.snapshots[this.baseSelectElement.selectedIndex]; + var lastComparator = WebInspector.HeapSnapshotDataGridList.propertyComparator("size", false); + if (this.snapshotDataGridList) + lastComparator = this.snapshotDataGridList.lastComparator; + this.snapshotDataGridList = this._createSnapshotDataGridList(); + this.snapshotDataGridList.sort(lastComparator, true); + }, + + _sortData: function() + { + var sortAscending = this.dataGrid.sortOrder === "ascending"; + var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier; + var sortProperty = { + "cons": ["constructorName", null], + "count": ["count", null], + "size": ["size", "count"], + "countDelta": this.showCountDeltaAsPercent ? ["countDeltaPercent", null] : ["countDelta", null], + "sizeDelta": this.showSizeDeltaAsPercent ? ["sizeDeltaPercent", "countDeltaPercent"] : ["sizeDelta", "sizeDeltaPercent"] + }[sortColumnIdentifier]; + + this.snapshotDataGridList.sort(WebInspector.HeapSnapshotDataGridList.propertyComparator(sortProperty[0], sortProperty[1], sortAscending)); + + this.refresh(); + }, + + _updateBaseOptions: function() + { + var list = WebInspector.HeapSnapshotProfileType.snapshots; + // We're assuming that snapshots can only be added. + if (this.baseSelectElement.length === list.length) + return; + + for (var i = this.baseSelectElement.length, n = list.length; i < n; ++i) { + var baseOption = document.createElement("option"); + baseOption.label = WebInspector.UIString("Compared to %s", list[i].title); + this.baseSelectElement.appendChild(baseOption); + } + }, + + _updatePercentButton: function() + { + if (this._isShowingAsPercent) { + this.percentButton.title = WebInspector.UIString("Show absolute counts and sizes."); + this.percentButton.toggled = true; + } else { + this.percentButton.title = WebInspector.UIString("Show counts and sizes as percentages."); + this.percentButton.toggled = false; + } + }, + + _updateSummaryGraph: function() + { + this.countsSummaryBar.calculator.showAsPercent = this._isShowingAsPercent; + this.countsSummaryBar.update(this.profile.lowlevels); + + this.sizesSummaryBar.calculator.showAsPercent = this._isShowingAsPercent; + this.sizesSummaryBar.update(this.profile.lowlevels); + } +}; + +WebInspector.HeapSnapshotView.prototype.__proto__ = WebInspector.View.prototype; + +WebInspector.HeapSnapshotView.SearchHelper = { + // In comparators, we assume that a value from a node is passed as the first parameter. + operations: { LESS: function (a, b) { return a !== null && a < b; }, + LESS_OR_EQUAL: function (a, b) { return a !== null && a <= b; }, + EQUAL: function (a, b) { return a !== null && a === b; }, + GREATER_OR_EQUAL: function (a, b) { return a !== null && a >= b; }, + GREATER: function (a, b) { return a !== null && a > b; } }, + + operationParsers: { LESS: /^<(\d+)/, + LESS_OR_EQUAL: /^<=(\d+)/, + GREATER_OR_EQUAL: /^>=(\d+)/, + GREATER: /^>(\d+)/ }, + + parseOperationAndNumber: function(query) + { + var operations = WebInspector.HeapSnapshotView.SearchHelper.operations; + var parsers = WebInspector.HeapSnapshotView.SearchHelper.operationParsers; + for (var operation in parsers) { + var match = query.match(parsers[operation]); + if (match !== null) + return [operations[operation], parseFloat(match[1])]; + } + return [operations.EQUAL, parseFloat(query)]; + }, + + percents: /%$/, + + megaBytes: /MB$/i, + + kiloBytes: /KB$/i, + + bytes: /B$/i +} + +WebInspector.HeapSummaryCalculator = function(lowLevelField) +{ + this.total = 1; + this.lowLevelField = lowLevelField; +} + +WebInspector.HeapSummaryCalculator.prototype = { + computeSummaryValues: function(lowLevels) + { + var highLevels = {data: 0, code: 0}; + this.total = 0; + for (var item in lowLevels) { + var highItem = this._highFromLow(item); + if (highItem) { + var value = lowLevels[item][this.lowLevelField]; + highLevels[highItem] += value; + this.total += value; + } + } + var result = {categoryValues: highLevels}; + if (!this.showAsPercent) + result.total = this.total; + return result; + }, + + formatValue: function(value) + { + if (this.showAsPercent) + return WebInspector.UIString("%.2f%%", value / this.total * 100.0); + else + return this._valueToString(value); + }, + + get showAsPercent() + { + return this._showAsPercent; + }, + + set showAsPercent(x) + { + this._showAsPercent = x; + } +} + +WebInspector.HeapSummaryCountCalculator = function() +{ + WebInspector.HeapSummaryCalculator.call(this, "count"); +} + +WebInspector.HeapSummaryCountCalculator.prototype = { + _highFromLow: function(type) { + if (type === "CODE_TYPE" || type === "SHARED_FUNCTION_INFO_TYPE" || type === "SCRIPT_TYPE") return "code"; + if (type === "STRING_TYPE" || type === "HEAP_NUMBER_TYPE" || type.match(/^JS_/)) return "data"; + return null; + }, + + _valueToString: function(value) { + return value.toString(); + } +} + +WebInspector.HeapSummaryCountCalculator.prototype.__proto__ = WebInspector.HeapSummaryCalculator.prototype; + +WebInspector.HeapSummarySizeCalculator = function() +{ + WebInspector.HeapSummaryCalculator.call(this, "size"); +} + +WebInspector.HeapSummarySizeCalculator.prototype = { + _highFromLow: function(type) { + if (type === "CODE_TYPE" || type === "SHARED_FUNCTION_INFO_TYPE" || type === "SCRIPT_TYPE") return "code"; + if (type === "STRING_TYPE" || type === "HEAP_NUMBER_TYPE" || type.match(/^JS_/) || type.match(/_ARRAY_TYPE$/)) return "data"; + return null; + }, + + _valueToString: Number.bytesToString +} + +WebInspector.HeapSummarySizeCalculator.prototype.__proto__ = WebInspector.HeapSummaryCalculator.prototype; + +WebInspector.HeapSnapshotSidebarTreeElement = function(snapshot) +{ + this.profile = snapshot; + + WebInspector.SidebarTreeElement.call(this, "heap-snapshot-sidebar-tree-item", "", "", snapshot, false); + + this.refreshTitles(); +}; + +WebInspector.HeapSnapshotSidebarTreeElement.prototype = { + get mainTitle() + { + if (this._mainTitle) + return this._mainTitle; + return this.profile.title; + }, + + set mainTitle(x) + { + this._mainTitle = x; + this.refreshTitles(); + } +}; + +WebInspector.HeapSnapshotSidebarTreeElement.prototype.__proto__ = WebInspector.ProfileSidebarTreeElement.prototype; + +WebInspector.HeapSnapshotDataGridNodeWithRetainers = function(owningTree) +{ + this.tree = owningTree; + + WebInspector.DataGridNode.call(this, null, this._hasRetainers); + + this.addEventListener("populate", this._populate, this); +}; + +WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype = { + isEmptySet: function(set) + { + for (var x in set) + return false; + return true; + }, + + get _hasRetainers() + { + return !this.isEmptySet(this.retainers); + }, + + get _parent() + { + // For top-level nodes, return owning tree as a parent, not data grid. + return this.parent !== this.dataGrid ? this.parent : this.tree; + }, + + _populate: function(event) + { + var self = this; + this.produceDiff(this.baseRetainers, this.retainers, function(baseItem, snapshotItem) { + self.appendChild(new WebInspector.HeapSnapshotDataGridRetainerNode(self.snapshotView, baseItem, snapshotItem, self.tree)); + }); + + if (this._parent) { + var currentComparator = this._parent.lastComparator; + if (currentComparator) + this.sort(currentComparator, true); + } + + this.removeEventListener("populate", this._populate, this); + }, + + produceDiff: function(baseEntries, currentEntries, callback) + { + for (var item in currentEntries) + callback(baseEntries[item], currentEntries[item]); + + for (item in baseEntries) { + if (!(item in currentEntries)) + callback(baseEntries[item], null); + } + }, + + sort: function(comparator, force) { + if (!force && this.lastComparator === comparator) + return; + + this.children.sort(comparator); + var childCount = this.children.length; + for (var childIndex = 0; childIndex < childCount; ++childIndex) + this.children[childIndex]._recalculateSiblings(childIndex); + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i]; + if (!force && (!child.expanded || child.lastComparator === comparator)) + continue; + child.sort(comparator, force); + } + this.lastComparator = comparator; + }, + + signForDelta: function(delta) { + if (delta === 0) + return ""; + if (delta > 0) + return "+"; + else + // Math minus sign, same width as plus. + return "\u2212"; + }, + + showDeltaAsPercent: function(value) { + if (value === Number.POSITIVE_INFINITY) + return WebInspector.UIString("new"); + else if (value === Number.NEGATIVE_INFINITY) + return WebInspector.UIString("deleted"); + if (value > 1000.0) + return WebInspector.UIString("%s >1000%%", this.signForDelta(value)); + return WebInspector.UIString("%s%.2f%%", this.signForDelta(value), Math.abs(value)); + }, + + getTotalCount: function() { + if (!this._count) { + this._count = 0; + for (var i = 0, n = this.children.length; i < n; ++i) + this._count += this.children[i].count; + } + return this._count; + }, + + getTotalSize: function() { + if (!this._size) { + this._size = 0; + for (var i = 0, n = this.children.length; i < n; ++i) + this._size += this.children[i].size; + } + return this._size; + }, + + get countPercent() + { + return this.count / this._parent.getTotalCount() * 100.0; + }, + + get sizePercent() + { + return this.size / this._parent.getTotalSize() * 100.0; + }, + + get countDeltaPercent() + { + if (this.baseCount > 0) { + if (this.count > 0) + return this.countDelta / this.baseCount * 100.0; + else + return Number.NEGATIVE_INFINITY; + } else + return Number.POSITIVE_INFINITY; + }, + + get sizeDeltaPercent() + { + if (this.baseSize > 0) { + if (this.size > 0) + return this.sizeDelta / this.baseSize * 100.0; + else + return Number.NEGATIVE_INFINITY; + } else + return Number.POSITIVE_INFINITY; + }, + + get data() + { + var data = {}; + + data["cons"] = this.constructorName; + + if (this.snapshotView.showCountAsPercent) + data["count"] = WebInspector.UIString("%.2f%%", this.countPercent); + else + data["count"] = this.count; + + if (this.size !== null) { + if (this.snapshotView.showSizeAsPercent) + data["size"] = WebInspector.UIString("%.2f%%", this.sizePercent); + else + data["size"] = Number.bytesToString(this.size); + } else + data["size"] = ""; + + if (this.snapshotView.showCountDeltaAsPercent) + data["countDelta"] = this.showDeltaAsPercent(this.countDeltaPercent); + else + data["countDelta"] = WebInspector.UIString("%s%d", this.signForDelta(this.countDelta), Math.abs(this.countDelta)); + + if (this.sizeDelta !== null) { + if (this.snapshotView.showSizeDeltaAsPercent) + data["sizeDelta"] = this.showDeltaAsPercent(this.sizeDeltaPercent); + else + data["sizeDelta"] = WebInspector.UIString("%s%s", this.signForDelta(this.sizeDelta), Number.bytesToString(Math.abs(this.sizeDelta))); + } else + data["sizeDelta"] = ""; + + return data; + }, + + createCell: function(columnIdentifier) + { + var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier); + + if ((columnIdentifier === "cons" && this._searchMatchedConsColumn) || + (columnIdentifier === "count" && this._searchMatchedCountColumn) || + (columnIdentifier === "size" && this._searchMatchedSizeColumn) || + (columnIdentifier === "countDelta" && this._searchMatchedCountDeltaColumn) || + (columnIdentifier === "sizeDelta" && this._searchMatchedSizeDeltaColumn)) + cell.addStyleClass("highlight"); + + return cell; + } +}; + +WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.__proto__ = WebInspector.DataGridNode.prototype; + +WebInspector.HeapSnapshotDataGridNode = function(snapshotView, baseEntry, snapshotEntry, owningTree) +{ + this.snapshotView = snapshotView; + + if (!snapshotEntry) + snapshotEntry = { cons: baseEntry.cons, count: 0, size: 0, retainers: {} }; + this.constructorName = snapshotEntry.cons; + this.count = snapshotEntry.count; + this.size = snapshotEntry.size; + this.retainers = snapshotEntry.retainers; + + if (!baseEntry) + baseEntry = { count: 0, size: 0, retainers: {} }; + this.baseCount = baseEntry.count; + this.countDelta = this.count - this.baseCount; + this.baseSize = baseEntry.size; + this.sizeDelta = this.size - this.baseSize; + this.baseRetainers = baseEntry.retainers; + + WebInspector.HeapSnapshotDataGridNodeWithRetainers.call(this, owningTree); +}; + +WebInspector.HeapSnapshotDataGridNode.prototype.__proto__ = WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype; + +WebInspector.HeapSnapshotDataGridList = function(snapshotView, baseEntries, snapshotEntries) +{ + this.tree = this; + this.snapshotView = snapshotView; + this.children = []; + this.lastComparator = null; + this.populateChildren(baseEntries, snapshotEntries); +}; + +WebInspector.HeapSnapshotDataGridList.prototype = { + appendChild: function(child) + { + this.insertChild(child, this.children.length); + }, + + insertChild: function(child, index) + { + this.children.splice(index, 0, child); + }, + + removeChildren: function() + { + this.children = []; + }, + + populateChildren: function(baseEntries, snapshotEntries) + { + var self = this; + this.produceDiff(baseEntries, snapshotEntries, function(baseItem, snapshotItem) { + self.appendChild(new WebInspector.HeapSnapshotDataGridNode(self.snapshotView, baseItem, snapshotItem, self)); + }); + }, + + produceDiff: WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.produceDiff, + sort: WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.sort, + getTotalCount: WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.getTotalCount, + getTotalSize: WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.getTotalSize +}; + +WebInspector.HeapSnapshotDataGridList.propertyComparators = [{}, {}]; + +WebInspector.HeapSnapshotDataGridList.propertyComparator = function(property, property2, isAscending) +{ + var propertyHash = property + "#" + property2; + var comparator = this.propertyComparators[(isAscending ? 1 : 0)][propertyHash]; + if (!comparator) { + comparator = function(lhs, rhs) { + var l = lhs[property], r = rhs[property]; + if ((l === null || r === null) && property2 !== null) + l = lhs[property2], r = rhs[property2]; + var result = l < r ? -1 : (l > r ? 1 : 0); + return isAscending ? result : -result; + }; + this.propertyComparators[(isAscending ? 1 : 0)][propertyHash] = comparator; + } + return comparator; +}; + +WebInspector.HeapSnapshotDataGridRetainerNode = function(snapshotView, baseEntry, snapshotEntry, owningTree) +{ + this.snapshotView = snapshotView; + + if (!snapshotEntry) + snapshotEntry = { cons: baseEntry.cons, count: 0, clusters: {} }; + this.constructorName = snapshotEntry.cons; + this.count = snapshotEntry.count; + this.retainers = this._calculateRetainers(this.snapshotView.profile, snapshotEntry.clusters); + + if (!baseEntry) + baseEntry = { count: 0, clusters: {} }; + this.baseCount = baseEntry.count; + this.countDelta = this.count - this.baseCount; + this.baseRetainers = this._calculateRetainers(this.snapshotView.baseSnapshot, baseEntry.clusters); + + this.size = null; + this.sizeDelta = null; + + WebInspector.HeapSnapshotDataGridNodeWithRetainers.call(this, owningTree); +} + +WebInspector.HeapSnapshotDataGridRetainerNode.prototype = { + get sizePercent() + { + return null; + }, + + get sizeDeltaPercent() + { + return null; + }, + + _calculateRetainers: function(snapshot, clusters) { + var retainers = {}; + if (this.isEmptySet(clusters)) { + if (this.constructorName in snapshot.entries) + return snapshot.entries[this.constructorName].retainers; + } else { + // In case when an entry is retained by clusters, we need to gather up the list + // of retainers by merging retainers of every cluster. + // E.g. having such a tree: + // A + // Object:1 10 + // X 3 + // Y 4 + // Object:2 5 + // X 6 + // + // will result in a following retainers list: X 9, Y 4. + for (var clusterName in clusters) { + if (clusterName in snapshot.clusters) { + var clusterRetainers = snapshot.clusters[clusterName].retainers; + for (var clusterRetainer in clusterRetainers) { + var clusterRetainerEntry = clusterRetainers[clusterRetainer]; + if (!(clusterRetainer in retainers)) + retainers[clusterRetainer] = { cons: clusterRetainerEntry.cons, count: 0, clusters: {} }; + retainers[clusterRetainer].count += clusterRetainerEntry.count; + for (var clusterRetainerCluster in clusterRetainerEntry.clusters) + retainers[clusterRetainer].clusters[clusterRetainerCluster] = true; + } + } + } + } + return retainers; + } +}; + +WebInspector.HeapSnapshotDataGridRetainerNode.prototype.__proto__ = WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype; + + +WebInspector.HeapSnapshotProfileType = function() +{ + WebInspector.ProfileType.call(this, WebInspector.HeapSnapshotProfileType.TypeId, WebInspector.UIString("HEAP SNAPSHOTS")); +} + +WebInspector.HeapSnapshotProfileType.TypeId = "HEAP"; + +WebInspector.HeapSnapshotProfileType.snapshots = []; + +WebInspector.HeapSnapshotProfileType.prototype = { + get buttonTooltip() + { + return WebInspector.UIString("Take heap snapshot."); + }, + + get buttonStyle() + { + return "heap-snapshot-status-bar-item status-bar-item"; + }, + + buttonClicked: function() + { + InspectorBackend.takeHeapSnapshot(); + }, + + get welcomeMessage() + { + return WebInspector.UIString("Get a heap snapshot by pressing<br>the %s button on the status bar."); + }, + + createSidebarTreeElementForProfile: function(profile) + { + var element = new WebInspector.HeapSnapshotSidebarTreeElement(profile); + element.small = false; + return element; + }, + + createView: function(profile) + { + return new WebInspector.HeapSnapshotView(WebInspector.panels.profiles, profile); + } +} + +WebInspector.HeapSnapshotProfileType.prototype.__proto__ = WebInspector.ProfileType.prototype; + + +(function() { + var originalCreatePanels = WebInspector._createPanels; + WebInspector._createPanels = function() { + originalCreatePanels.apply(this, arguments); + if (WebInspector.panels.profiles) + WebInspector.panels.profiles.registerProfileType(new WebInspector.HeapSnapshotProfileType()); + } +})(); diff --git a/WebKit/chromium/src/js/Images/segmentChromium.png b/WebKit/chromium/src/js/Images/segmentChromium.png Binary files differnew file mode 100755 index 0000000..607559b --- /dev/null +++ b/WebKit/chromium/src/js/Images/segmentChromium.png diff --git a/WebKit/chromium/src/js/Images/segmentHoverChromium.png b/WebKit/chromium/src/js/Images/segmentHoverChromium.png Binary files differnew file mode 100755 index 0000000..0a743d9 --- /dev/null +++ b/WebKit/chromium/src/js/Images/segmentHoverChromium.png diff --git a/WebKit/chromium/src/js/Images/segmentHoverEndChromium.png b/WebKit/chromium/src/js/Images/segmentHoverEndChromium.png Binary files differnew file mode 100755 index 0000000..cf62072 --- /dev/null +++ b/WebKit/chromium/src/js/Images/segmentHoverEndChromium.png diff --git a/WebKit/chromium/src/js/Images/segmentSelectedChromium.png b/WebKit/chromium/src/js/Images/segmentSelectedChromium.png Binary files differnew file mode 100755 index 0000000..a1f7251 --- /dev/null +++ b/WebKit/chromium/src/js/Images/segmentSelectedChromium.png diff --git a/WebKit/chromium/src/js/Images/segmentSelectedEndChromium.png b/WebKit/chromium/src/js/Images/segmentSelectedEndChromium.png Binary files differnew file mode 100755 index 0000000..07641db --- /dev/null +++ b/WebKit/chromium/src/js/Images/segmentSelectedEndChromium.png diff --git a/WebKit/chromium/src/js/Images/statusbarBackgroundChromium.png b/WebKit/chromium/src/js/Images/statusbarBackgroundChromium.png Binary files differnew file mode 100755 index 0000000..9d326ac --- /dev/null +++ b/WebKit/chromium/src/js/Images/statusbarBackgroundChromium.png diff --git a/WebKit/chromium/src/js/Images/statusbarBottomBackgroundChromium.png b/WebKit/chromium/src/js/Images/statusbarBottomBackgroundChromium.png Binary files differnew file mode 100755 index 0000000..7c7db0a --- /dev/null +++ b/WebKit/chromium/src/js/Images/statusbarBottomBackgroundChromium.png diff --git a/WebKit/chromium/src/js/Images/statusbarButtonsChromium.png b/WebKit/chromium/src/js/Images/statusbarButtonsChromium.png Binary files differnew file mode 100755 index 0000000..0c6635d --- /dev/null +++ b/WebKit/chromium/src/js/Images/statusbarButtonsChromium.png diff --git a/WebKit/chromium/src/js/Images/statusbarMenuButtonChromium.png b/WebKit/chromium/src/js/Images/statusbarMenuButtonChromium.png Binary files differnew file mode 100755 index 0000000..bf26684 --- /dev/null +++ b/WebKit/chromium/src/js/Images/statusbarMenuButtonChromium.png diff --git a/WebKit/chromium/src/js/Images/statusbarMenuButtonSelectedChromium.png b/WebKit/chromium/src/js/Images/statusbarMenuButtonSelectedChromium.png Binary files differnew file mode 100755 index 0000000..3c0aeec --- /dev/null +++ b/WebKit/chromium/src/js/Images/statusbarMenuButtonSelectedChromium.png diff --git a/WebKit/chromium/src/js/InjectDispatch.js b/WebKit/chromium/src/js/InjectDispatch.js new file mode 100644 index 0000000..e070c42 --- /dev/null +++ b/WebKit/chromium/src/js/InjectDispatch.js @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2010 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 + * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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. + */ + +/** + * @fileoverview Injects "injected" object into the inspectable page. + */ + + +var InspectorControllerDispatcher = {}; + +/** + * Main dispatch method, all calls from the host to InspectorController go + * through this one. + * @param {string} functionName Function to call + * @param {string} json_args JSON-serialized call parameters. + * @return {string} JSON-serialized result of the dispatched call. + */ +InspectorControllerDispatcher.dispatch = function(functionName, json_args) +{ + var params = JSON.parse(json_args); + InspectorBackend[functionName].apply(InspectorBackend, params); +}; + +/** + * Special controller object for APU related messages. Outgoing messages + * are sent to this object if the ApuAgentDispatcher is enabled. + **/ +var ApuAgentDispatcher = { enabled : false }; + +/** + * Dispatches messages to APU. This filters and transforms + * outgoing messages that are used by APU. + * @param {string} method name of the dispatch method. + **/ +ApuAgentDispatcher.dispatchToApu = function(method, args) +{ + if (method !== "addRecordToTimeline" && method !== "updateResource" && method !== "addResource") + return; + // TODO(knorton): Transform args so they can be used + // by APU. + DevToolsAgentHost.dispatchToApu(JSON.stringify(args)); +}; + +/** + * This is called by the InspectorFrontend for serialization. + * We serialize the call and send it to the client over the IPC + * using dispatchOut bound method. + */ +function dispatch(method, var_args) { + // Handle all messages with non-primitieve arguments here. + var args = Array.prototype.slice.call(arguments); + + if (method === "inspectedWindowCleared" || method === "reset" || method === "setAttachedWindow") { + // Filter out messages we don't need here. + // We do it on the sender side since they may have non-serializable + // parameters. + return; + } + + // Sniff some inspector controller state changes in order to support + // cross-navigation instrumentation. Keep names in sync with + // webdevtoolsagent_impl. + if (method === "timelineProfilerWasStarted") + DevToolsAgentHost.runtimeFeatureStateChanged("timeline-profiler", true); + else if (method === "timelineProfilerWasStopped") + DevToolsAgentHost.runtimeFeatureStateChanged("timeline-profiler", false); + else if (method === "resourceTrackingWasEnabled") + DevToolsAgentHost.runtimeFeatureStateChanged("resource-tracking", true); + else if (method === "resourceTrackingWasDisabled") + DevToolsAgentHost.runtimeFeatureStateChanged("resource-tracking", false); + + if (ApuAgentDispatcher.enabled) { + ApuAgentDispatcher.dispatchToApu(method, args); + return; + } + + var call = JSON.stringify(args); + DevToolsAgentHost.dispatch(call); +}; diff --git a/WebKit/chromium/src/js/InspectorControllerImpl.js b/WebKit/chromium/src/js/InspectorControllerImpl.js new file mode 100644 index 0000000..c92a94c --- /dev/null +++ b/WebKit/chromium/src/js/InspectorControllerImpl.js @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2010 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 + * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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. + */ + +/** + * @fileoverview DevTools' implementation of the InspectorController API. + */ + +if (!this.devtools) + devtools = {}; + +devtools.InspectorBackendImpl = function() +{ + WebInspector.InspectorBackendStub.call(this); + this.installInspectorControllerDelegate_("clearMessages"); + this.installInspectorControllerDelegate_("copyNode"); + this.installInspectorControllerDelegate_("deleteCookie"); + this.installInspectorControllerDelegate_("didEvaluateForTestInFrontend"); + this.installInspectorControllerDelegate_("disableResourceTracking"); + this.installInspectorControllerDelegate_("disableTimeline"); + this.installInspectorControllerDelegate_("enableResourceTracking"); + this.installInspectorControllerDelegate_("enableTimeline"); + this.installInspectorControllerDelegate_("getChildNodes"); + this.installInspectorControllerDelegate_("getCookies"); + this.installInspectorControllerDelegate_("getDatabaseTableNames"); + this.installInspectorControllerDelegate_("getDOMStorageEntries"); + this.installInspectorControllerDelegate_("getEventListenersForNode"); + this.installInspectorControllerDelegate_("getResourceContent"); + this.installInspectorControllerDelegate_("highlightDOMNode"); + this.installInspectorControllerDelegate_("hideDOMNodeHighlight"); + this.installInspectorControllerDelegate_("releaseWrapperObjectGroup"); + this.installInspectorControllerDelegate_("removeAttribute"); + this.installInspectorControllerDelegate_("removeDOMStorageItem"); + this.installInspectorControllerDelegate_("removeNode"); + this.installInspectorControllerDelegate_("saveFrontendSettings"); + this.installInspectorControllerDelegate_("setAttribute"); + this.installInspectorControllerDelegate_("setDOMStorageItem"); + this.installInspectorControllerDelegate_("setInjectedScriptSource"); + this.installInspectorControllerDelegate_("setTextNodeValue"); + this.installInspectorControllerDelegate_("startTimelineProfiler"); + this.installInspectorControllerDelegate_("stopTimelineProfiler"); + this.installInspectorControllerDelegate_("storeLastActivePanel"); +}; +devtools.InspectorBackendImpl.prototype.__proto__ = WebInspector.InspectorBackendStub.prototype; + + +/** + * {@inheritDoc}. + */ +devtools.InspectorBackendImpl.prototype.toggleNodeSearch = function() +{ + WebInspector.InspectorBackendStub.prototype.toggleNodeSearch.call(this); + this.callInspectorController_.call(this, "toggleNodeSearch"); + if (!this.searchingForNode()) { + // This is called from ElementsPanel treeOutline's focusNodeChanged(). + DevToolsHost.activateWindow(); + } +}; + + +/** + * @override + */ +devtools.InspectorBackendImpl.prototype.debuggerEnabled = function() +{ + return true; +}; + + +/** + * @override + */ +devtools.InspectorBackendImpl.prototype.profilerEnabled = function() +{ + return true; +}; + + +devtools.InspectorBackendImpl.prototype.addBreakpoint = function(sourceID, line, condition) +{ + devtools.tools.getDebuggerAgent().addBreakpoint(sourceID, line, condition); +}; + + +devtools.InspectorBackendImpl.prototype.removeBreakpoint = function(sourceID, line) +{ + devtools.tools.getDebuggerAgent().removeBreakpoint(sourceID, line); +}; + +devtools.InspectorBackendImpl.prototype.updateBreakpoint = function(sourceID, line, condition) +{ + devtools.tools.getDebuggerAgent().updateBreakpoint(sourceID, line, condition); +}; + +devtools.InspectorBackendImpl.prototype.pauseInDebugger = function() +{ + devtools.tools.getDebuggerAgent().pauseExecution(); +}; + + +devtools.InspectorBackendImpl.prototype.resumeDebugger = function() +{ + devtools.tools.getDebuggerAgent().resumeExecution(); +}; + + +devtools.InspectorBackendImpl.prototype.stepIntoStatementInDebugger = function() +{ + devtools.tools.getDebuggerAgent().stepIntoStatement(); +}; + + +devtools.InspectorBackendImpl.prototype.stepOutOfFunctionInDebugger = function() +{ + devtools.tools.getDebuggerAgent().stepOutOfFunction(); +}; + + +devtools.InspectorBackendImpl.prototype.stepOverStatementInDebugger = function() +{ + devtools.tools.getDebuggerAgent().stepOverStatement(); +}; + +/** + * @override + */ +devtools.InspectorBackendImpl.prototype.setPauseOnExceptionsState = function(state) +{ + this._setPauseOnExceptionsState = state; + // TODO(yurys): support all three states. See http://crbug.com/32877 + var enabled = (state !== WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions); + return devtools.tools.getDebuggerAgent().setPauseOnExceptions(enabled); +}; + +/** + * @override + */ +devtools.InspectorBackendImpl.prototype.pauseOnExceptionsState = function() +{ + return (this._setPauseOnExceptionsState || WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions); +}; + +/** + * @override + */ +devtools.InspectorBackendImpl.prototype.pauseOnExceptions = function() +{ + return devtools.tools.getDebuggerAgent().pauseOnExceptions(); +}; + + +/** + * @override + */ +devtools.InspectorBackendImpl.prototype.setPauseOnExceptions = function(value) +{ + return devtools.tools.getDebuggerAgent().setPauseOnExceptions(value); +}; + + +/** + * @override + */ +devtools.InspectorBackendImpl.prototype.startProfiling = function() +{ + devtools.tools.getProfilerAgent().startProfiling(devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_CPU); +}; + + +/** + * @override + */ +devtools.InspectorBackendImpl.prototype.stopProfiling = function() +{ + devtools.tools.getProfilerAgent().stopProfiling( devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_CPU); +}; + + +/** + * @override + */ +devtools.InspectorBackendImpl.prototype.getProfileHeaders = function(callId) +{ + WebInspector.didGetProfileHeaders(callId, []); +}; + + +/** + * Emulate WebKit InspectorController behavior. It stores profiles on renderer side, + * and is able to retrieve them by uid using "getProfile". + */ +devtools.InspectorBackendImpl.prototype.addFullProfile = function(profile) +{ + WebInspector.__fullProfiles = WebInspector.__fullProfiles || {}; + WebInspector.__fullProfiles[profile.uid] = profile; +}; + + +/** + * @override + */ +devtools.InspectorBackendImpl.prototype.getProfile = function(callId, uid) +{ + if (WebInspector.__fullProfiles && (uid in WebInspector.__fullProfiles)) + WebInspector.didGetProfile(callId, WebInspector.__fullProfiles[uid]); +}; + + +/** + * @override + */ +devtools.InspectorBackendImpl.prototype.takeHeapSnapshot = function() +{ + devtools.tools.getProfilerAgent().startProfiling(devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_HEAP_SNAPSHOT + | devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_HEAP_STATS + | devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_JS_CONSTRUCTORS); +}; + + +/** + * @override + */ +devtools.InspectorBackendImpl.prototype.dispatchOnInjectedScript = function(callId, injectedScriptId, methodName, argsString, async) +{ + // Encode injectedScriptId into callId + if (typeof injectedScriptId !== "number") + injectedScriptId = 0; + RemoteToolsAgent.dispatchOnInjectedScript(callId, injectedScriptId, methodName, argsString, async); +}; + + +/** + * Installs delegating handler into the inspector controller. + * @param {string} methodName Method to install delegating handler for. + */ +devtools.InspectorBackendImpl.prototype.installInspectorControllerDelegate_ = function(methodName) +{ + this[methodName] = this.callInspectorController_.bind(this, methodName); +}; + + +/** + * Bound function with the installInjectedScriptDelegate_ actual + * implementation. + */ +devtools.InspectorBackendImpl.prototype.callInspectorController_ = function(methodName, var_arg) +{ + var args = Array.prototype.slice.call(arguments, 1); + RemoteToolsAgent.dispatchOnInspectorController(WebInspector.Callback.wrap(function(){}), methodName, JSON.stringify(args)); +}; + + +InspectorBackend = new devtools.InspectorBackendImpl(); diff --git a/WebKit/chromium/src/js/ProfilerAgent.js b/WebKit/chromium/src/js/ProfilerAgent.js new file mode 100644 index 0000000..e08c5d2 --- /dev/null +++ b/WebKit/chromium/src/js/ProfilerAgent.js @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2010 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 + * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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. + */ + +/** + * @fileoverview Provides communication interface to remote v8 profiler. + */ + +/** + * @constructor + */ +devtools.ProfilerAgent = function() +{ + RemoteProfilerAgent.didGetActiveProfilerModules = this._didGetActiveProfilerModules.bind(this); + RemoteProfilerAgent.didGetLogLines = this._didGetLogLines.bind(this); + + /** + * Active profiler modules flags. + * @type {number} + */ + this._activeProfilerModules = devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_NONE; + + /** + * Interval for polling profiler state. + * @type {number} + */ + this._getActiveProfilerModulesInterval = null; + + /** + * Profiler log position. + * @type {number} + */ + this._logPosition = 0; + + /** + * Last requested log position. + * @type {number} + */ + this._lastRequestedLogPosition = -1; + + /** + * Whether log contents retrieval must be forced next time. + * @type {boolean} + */ + this._forceGetLogLines = false; + + /** + * Profiler processor instance. + * @type {devtools.profiler.Processor} + */ + this._profilerProcessor = new devtools.profiler.Processor(); +}; + + +/** + * A copy of enum from include/v8.h + * @enum {number} + */ +devtools.ProfilerAgent.ProfilerModules = { + PROFILER_MODULE_NONE: 0, + PROFILER_MODULE_CPU: 1, + PROFILER_MODULE_HEAP_STATS: 1 << 1, + PROFILER_MODULE_JS_CONSTRUCTORS: 1 << 2, + PROFILER_MODULE_HEAP_SNAPSHOT: 1 << 16 +}; + + +/** + * Sets up callbacks that deal with profiles processing. + */ +devtools.ProfilerAgent.prototype.setupProfilerProcessorCallbacks = function() +{ + // A temporary icon indicating that the profile is being processed. + var processingIcon = new WebInspector.SidebarTreeElement( + "profile-sidebar-tree-item", + WebInspector.UIString("Processing..."), + '', null, false); + var profilesSidebar = WebInspector.panels.profiles.getProfileType(WebInspector.CPUProfileType.TypeId).treeElement; + + this._profilerProcessor.setCallbacks( + function onProfileProcessingStarted() { + // Set visually empty string. Subtitle hiding is done via styles + // manipulation which doesn't play well with dynamic append / removal. + processingIcon.subtitle = " "; + profilesSidebar.appendChild(processingIcon); + }, + function onProfileProcessingStatus(ticksCount) { + processingIcon.subtitle = WebInspector.UIString("%d ticks processed", ticksCount); + }, + function onProfileProcessingFinished(profile) { + profilesSidebar.removeChild(processingIcon); + profile.typeId = WebInspector.CPUProfileType.TypeId; + InspectorBackend.addFullProfile(profile); + WebInspector.addProfileHeader(profile); + // If no profile is currently shown, show the new one. + var profilesPanel = WebInspector.panels.profiles; + if (!profilesPanel.visibleView) { + profilesPanel.showProfile(profile); + } + } + ); +}; + + +/** + * Initializes profiling state. + */ +devtools.ProfilerAgent.prototype.initializeProfiling = function() +{ + this.setupProfilerProcessorCallbacks(); + this._forceGetLogLines = true; + this._getActiveProfilerModulesInterval = setInterval(function() { RemoteProfilerAgent.getActiveProfilerModules(); }, 1000); +}; + + +/** + * Requests the next chunk of log lines. + * @param {boolean} immediately Do not postpone the request. + * @private + */ +devtools.ProfilerAgent.prototype._getNextLogLines = function(immediately) +{ + if (this._lastRequestedLogPosition == this._logPosition) + return; + var pos = this._lastRequestedLogPosition = this._logPosition; + if (immediately) + RemoteProfilerAgent.getLogLines(pos); + else + setTimeout(function() { RemoteProfilerAgent.getLogLines(pos); }, 500); +}; + + +/** + * Starts profiling. + * @param {number} modules List of modules to enable. + */ +devtools.ProfilerAgent.prototype.startProfiling = function(modules) +{ + var cmd = new devtools.DebugCommand("profile", { + "modules": modules, + "command": "resume"}); + devtools.DebuggerAgent.sendCommand_(cmd); + RemoteDebuggerAgent.processDebugCommands(); + if (modules & devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_HEAP_SNAPSHOT) { + // Active modules will not change, instead, a snapshot will be logged. + this._getNextLogLines(); + } +}; + + +/** + * Stops profiling. + */ +devtools.ProfilerAgent.prototype.stopProfiling = function(modules) +{ + var cmd = new devtools.DebugCommand("profile", { + "modules": modules, + "command": "pause"}); + devtools.DebuggerAgent.sendCommand_(cmd); + RemoteDebuggerAgent.processDebugCommands(); +}; + + +/** + * Handles current profiler status. + * @param {number} modules List of active (started) modules. + */ +devtools.ProfilerAgent.prototype._didGetActiveProfilerModules = function(modules) +{ + var profModules = devtools.ProfilerAgent.ProfilerModules; + var profModuleNone = profModules.PROFILER_MODULE_NONE; + if (this._forceGetLogLines || (modules !== profModuleNone && this._activeProfilerModules === profModuleNone)) { + this._forceGetLogLines = false; + // Start to query log data. + this._getNextLogLines(true); + } + this._activeProfilerModules = modules; + // Update buttons. + WebInspector.setRecordingProfile(modules & profModules.PROFILER_MODULE_CPU); +}; + + +/** + * Handles a portion of a profiler log retrieved by getLogLines call. + * @param {number} pos Current position in log. + * @param {string} log A portion of profiler log. + */ +devtools.ProfilerAgent.prototype._didGetLogLines = function(pos, log) +{ + this._logPosition = pos; + if (log.length > 0) + this._profilerProcessor.processLogChunk(log); + else { + // Allow re-reading from the last position. + this._lastRequestedLogPosition = this._logPosition - 1; + if (this._activeProfilerModules === devtools.ProfilerAgent.ProfilerModules.PROFILER_MODULE_NONE) + // No new data and profiling is stopped---suspend log reading. + return; + } + this._getNextLogLines(); +}; diff --git a/WebKit/chromium/src/js/ProfilerProcessor.js b/WebKit/chromium/src/js/ProfilerProcessor.js new file mode 100644 index 0000000..f678d2c --- /dev/null +++ b/WebKit/chromium/src/js/ProfilerProcessor.js @@ -0,0 +1,543 @@ +/* + * Copyright (C) 2010 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 + * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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. + */ + +/** + * @fileoverview Profiler processor is used to process log file produced + * by V8 and produce an internal profile representation which is used + * for building profile views in "Profiles" tab. + */ + + +/** + * Creates a Profile View builder object compatible with WebKit Profiler UI. + * + * @param {number} samplingRate Number of ms between profiler ticks. + * @constructor + */ +devtools.profiler.WebKitViewBuilder = function(samplingRate) +{ + devtools.profiler.ViewBuilder.call(this, samplingRate); +}; +devtools.profiler.WebKitViewBuilder.prototype.__proto__ = devtools.profiler.ViewBuilder.prototype; + + +/** + * @override + */ +devtools.profiler.WebKitViewBuilder.prototype.createViewNode = function(funcName, totalTime, selfTime, head) +{ + return new devtools.profiler.WebKitViewNode(funcName, totalTime, selfTime, head); +}; + + +/** + * Constructs a Profile View node object for displaying in WebKit Profiler UI. + * + * @param {string} internalFuncName A fully qualified function name. + * @param {number} totalTime Amount of time that application spent in the + * corresponding function and its descendants (not that depending on + * profile they can be either callees or callers.) + * @param {number} selfTime Amount of time that application spent in the + * corresponding function only. + * @param {devtools.profiler.ProfileView.Node} head Profile view head. + * @constructor + */ +devtools.profiler.WebKitViewNode = function(internalFuncName, totalTime, selfTime, head) +{ + devtools.profiler.ProfileView.Node.call(this, internalFuncName, totalTime, selfTime, head); + this.initFuncInfo_(); + this.callUID = internalFuncName; +}; +devtools.profiler.WebKitViewNode.prototype.__proto__ = devtools.profiler.ProfileView.Node.prototype; + + +/** + * RegEx for stripping V8's prefixes of compiled functions. + */ +devtools.profiler.WebKitViewNode.FUNC_NAME_STRIP_RE = /^(?:LazyCompile|Function|Callback): (.*)$/; + + +/** + * RegEx for extracting script source URL and line number. + */ +devtools.profiler.WebKitViewNode.FUNC_NAME_PARSE_RE = /^((?:get | set )?[^ ]+) (.*):(\d+)( \{\d+\})?$/; + + +/** + * Inits "functionName", "url", and "lineNumber" fields using "internalFuncName" + * field. + * @private + */ +devtools.profiler.WebKitViewNode.prototype.initFuncInfo_ = function() +{ + var nodeAlias = devtools.profiler.WebKitViewNode; + this.functionName = this.internalFuncName; + + var strippedName = nodeAlias.FUNC_NAME_STRIP_RE.exec(this.functionName); + if (strippedName) + this.functionName = strippedName[1]; + + var parsedName = nodeAlias.FUNC_NAME_PARSE_RE.exec(this.functionName); + if (parsedName) { + this.functionName = parsedName[1]; + if (parsedName[4]) + this.functionName += parsedName[4]; + this.url = parsedName[2]; + this.lineNumber = parsedName[3]; + } else { + this.url = ''; + this.lineNumber = 0; + } +}; + + +/** + * Ancestor of a profile object that leaves out only JS-related functions. + * @constructor + */ +devtools.profiler.JsProfile = function() +{ + devtools.profiler.Profile.call(this); +}; +devtools.profiler.JsProfile.prototype.__proto__ = devtools.profiler.Profile.prototype; + + +/** + * RegExp that leaves only non-native JS functions. + * @type {RegExp} + */ +devtools.profiler.JsProfile.JS_NON_NATIVE_RE = new RegExp( + "^" + + "(?:Callback:)|" + + "(?:Script: (?!native))|" + + "(?:(?:LazyCompile|Function): [^ ]*(?: (?!native )[^ ]+:\\d+)?$)"); + + +/** + * @override + */ +devtools.profiler.JsProfile.prototype.skipThisFunction = function(name) +{ + return !devtools.profiler.JsProfile.JS_NON_NATIVE_RE.test(name); +}; + + +/** + * Profiler processor. Consumes profiler log and builds profile views. + * FIXME: change field naming style to use trailing underscore. + * + * @param {function(devtools.profiler.ProfileView)} newProfileCallback Callback + * that receives a new processed profile. + * @constructor + */ +devtools.profiler.Processor = function() +{ + var dispatches = { + "code-creation": { + parsers: [null, this.createAddressParser("code"), parseInt, null], + processor: this.processCodeCreation_, backrefs: true, + needsProfile: true }, + "code-move": { parsers: [this.createAddressParser("code"), + this.createAddressParser("code-move-to")], + processor: this.processCodeMove_, backrefs: true, + needsProfile: true }, + "code-delete": { parsers: [this.createAddressParser("code")], + processor: this.processCodeDelete_, backrefs: true, + needsProfile: true }, + "function-creation": { parsers: [this.createAddressParser("code"), + this.createAddressParser("function-obj")], + processor: this.processFunctionCreation_, backrefs: true }, + "function-move": { parsers: [this.createAddressParser("code"), + this.createAddressParser("code-move-to")], + processor: this.processFunctionMove_, backrefs: true }, + "function-delete": { parsers: [this.createAddressParser("code")], + processor: this.processFunctionDelete_, backrefs: true }, + "tick": { parsers: [this.createAddressParser("code"), + this.createAddressParser("stack"), parseInt, "var-args"], + processor: this.processTick_, backrefs: true, needProfile: true }, + "profiler": { parsers: [null, "var-args"], + processor: this.processProfiler_, needsProfile: false }, + "heap-sample-begin": { parsers: [null, null, parseInt], + processor: this.processHeapSampleBegin_ }, + "heap-sample-stats": { parsers: [null, null, parseInt, parseInt], + processor: this.processHeapSampleStats_ }, + "heap-sample-item": { parsers: [null, parseInt, parseInt], + processor: this.processHeapSampleItem_ }, + "heap-js-cons-item": { parsers: [null, parseInt, parseInt], + processor: this.processHeapJsConsItem_ }, + "heap-js-ret-item": { parsers: [null, "var-args"], + processor: this.processHeapJsRetItem_ }, + "heap-sample-end": { parsers: [null, null], + processor: this.processHeapSampleEnd_ }, + // Not used in DevTools Profiler. + "shared-library": null, + // Obsolete row types. + "code-allocate": null, + "begin-code-region": null, + "end-code-region": null}; + + if (devtools.profiler.Profile.VERSION === 2) { + dispatches["tick"] = { parsers: [this.createAddressParser("code"), + this.createAddressParser("stack"), + this.createAddressParser("func"), parseInt, "var-args"], + processor: this.processTickV2_, backrefs: true }; + } + + devtools.profiler.LogReader.call(this, dispatches); + + /** + * Callback that is called when a new profile is encountered in the log. + * @type {function()} + */ + this.startedProfileProcessing_ = null; + + /** + * Callback that is called periodically to display processing status. + * @type {function()} + */ + this.profileProcessingStatus_ = null; + + /** + * Callback that is called when a profile has been processed and is ready + * to be shown. + * @type {function(devtools.profiler.ProfileView)} + */ + this.finishedProfileProcessing_ = null; + + /** + * The current profile. + * @type {devtools.profiler.JsProfile} + */ + this.currentProfile_ = null; + + /** + * Builder of profile views. Created during "profiler,begin" event processing. + * @type {devtools.profiler.WebKitViewBuilder} + */ + this.viewBuilder_ = null; + + /** + * Next profile id. + * @type {number} + */ + this.profileId_ = 1; + + /** + * Counter for processed ticks. + * @type {number} + */ + this.ticksCount_ = 0; + + /** + * Interval id for updating processing status. + * @type {number} + */ + this.processingInterval_ = null; + + /** + * The current heap snapshot. + * @type {string} + */ + this.currentHeapSnapshot_ = null; + + /** + * Next heap snapshot id. + * @type {number} + */ + this.heapSnapshotId_ = 1; +}; +devtools.profiler.Processor.prototype.__proto__ = devtools.profiler.LogReader.prototype; + + +/** + * @override + */ +devtools.profiler.Processor.prototype.printError = function(str) +{ + debugPrint(str); +}; + + +/** + * @override + */ +devtools.profiler.Processor.prototype.skipDispatch = function(dispatch) +{ + return dispatch.needsProfile && this.currentProfile_ === null; +}; + + +/** + * Sets profile processing callbacks. + * + * @param {function()} started Started processing callback. + * @param {function(devtools.profiler.ProfileView)} finished Finished + * processing callback. + */ +devtools.profiler.Processor.prototype.setCallbacks = function(started, processing, finished) +{ + this.startedProfileProcessing_ = started; + this.profileProcessingStatus_ = processing; + this.finishedProfileProcessing_ = finished; +}; + + +/** + * An address for the fake "(program)" entry. WebKit's visualisation + * has assumptions on how the top of the call tree should look like, + * and we need to add a fake entry as the topmost function. This + * address is chosen because it's the end address of the first memory + * page, which is never used for code or data, but only as a guard + * page for catching AV errors. + * + * @type {number} + */ +devtools.profiler.Processor.PROGRAM_ENTRY = 0xffff; +/** + * @type {string} + */ +devtools.profiler.Processor.PROGRAM_ENTRY_STR = "0xffff"; + + +/** + * Sets new profile callback. + * @param {function(devtools.profiler.ProfileView)} callback Callback function. + */ +devtools.profiler.Processor.prototype.setNewProfileCallback = function(callback) +{ + this.newProfileCallback_ = callback; +}; + + +devtools.profiler.Processor.prototype.processProfiler_ = function(state, params) +{ + switch (state) { + case "resume": + if (this.currentProfile_ === null) { + this.currentProfile_ = new devtools.profiler.JsProfile(); + // see the comment for devtools.profiler.Processor.PROGRAM_ENTRY + this.currentProfile_.addCode("Function", "(program)", devtools.profiler.Processor.PROGRAM_ENTRY, 1); + if (this.startedProfileProcessing_) + this.startedProfileProcessing_(); + this.ticksCount_ = 0; + var self = this; + if (this.profileProcessingStatus_) { + this.processingInterval_ = window.setInterval( + function() { self.profileProcessingStatus_(self.ticksCount_); }, + 1000); + } + } + break; + case "pause": + if (this.currentProfile_ !== null) { + window.clearInterval(this.processingInterval_); + this.processingInterval_ = null; + if (this.finishedProfileProcessing_) + this.finishedProfileProcessing_(this.createProfileForView()); + this.currentProfile_ = null; + } + break; + case "begin": + var samplingRate = NaN; + if (params.length > 0) + samplingRate = parseInt(params[0]); + if (isNaN(samplingRate)) + samplingRate = 1; + this.viewBuilder_ = new devtools.profiler.WebKitViewBuilder(samplingRate); + break; + // These events are valid but aren't used. + case "compression": + case "end": break; + default: + throw new Error("unknown profiler state: " + state); + } +}; + + +devtools.profiler.Processor.prototype.processCodeCreation_ = function(type, start, size, name) +{ + this.currentProfile_.addCode(this.expandAlias(type), name, start, size); +}; + + +devtools.profiler.Processor.prototype.processCodeMove_ = function(from, to) +{ + this.currentProfile_.moveCode(from, to); +}; + + +devtools.profiler.Processor.prototype.processCodeDelete_ = function(start) +{ + this.currentProfile_.deleteCode(start); +}; + + +devtools.profiler.Processor.prototype.processFunctionCreation_ = function(functionAddr, codeAddr) +{ + this.currentProfile_.addCodeAlias(functionAddr, codeAddr); +}; + + +devtools.profiler.Processor.prototype.processFunctionMove_ = function(from, to) +{ + this.currentProfile_.safeMoveDynamicCode(from, to); +}; + + +devtools.profiler.Processor.prototype.processFunctionDelete_ = function(start) +{ + this.currentProfile_.safeDeleteDynamicCode(start); +}; + + +// TODO(mnaganov): Remove after next V8 roll. +devtools.profiler.Processor.prototype.processTick_ = function(pc, sp, vmState, stack) +{ + // see the comment for devtools.profiler.Processor.PROGRAM_ENTRY + stack.push(devtools.profiler.Processor.PROGRAM_ENTRY_STR); + this.currentProfile_.recordTick(this.processStack(pc, stack)); + this.ticksCount_++; +}; + + +devtools.profiler.Processor.prototype.processTickV2_ = function(pc, sp, func, vmState, stack) +{ + // see the comment for devtools.profiler.Processor.PROGRAM_ENTRY + stack.push(devtools.profiler.Processor.PROGRAM_ENTRY_STR); + + + if (func) { + var funcEntry = this.currentProfile_.findEntry(func); + if (!funcEntry || !funcEntry.isJSFunction || !funcEntry.isJSFunction()) + func = 0; + else { + var currEntry = this.currentProfile_.findEntry(pc); + if (!currEntry || !currEntry.isJSFunction || currEntry.isJSFunction()) { + func = 0; + } + } + } + + this.currentProfile_.recordTick(this.processStack(pc, func, stack)); + this.ticksCount_++; +}; + + +devtools.profiler.Processor.prototype.processHeapSampleBegin_ = function(space, state, ticks) +{ + if (space !== "Heap") return; + this.currentHeapSnapshot_ = { + number: this.heapSnapshotId_++, + entries: {}, + clusters: {}, + lowlevels: {}, + ticks: ticks + }; +}; + + +devtools.profiler.Processor.prototype.processHeapSampleStats_ = function(space, state, capacity, used) +{ + if (space !== "Heap") return; +}; + + +devtools.profiler.Processor.prototype.processHeapSampleItem_ = function(item, number, size) +{ + if (!this.currentHeapSnapshot_) return; + this.currentHeapSnapshot_.lowlevels[item] = { + type: item, count: number, size: size + }; +}; + + +devtools.profiler.Processor.prototype.processHeapJsConsItem_ = function(item, number, size) +{ + if (!this.currentHeapSnapshot_) return; + this.currentHeapSnapshot_.entries[item] = { + cons: item, count: number, size: size, retainers: {} + }; +}; + + +devtools.profiler.Processor.prototype.processHeapJsRetItem_ = function(item, retainersArray) +{ + if (!this.currentHeapSnapshot_) return; + var rawRetainers = {}; + for (var i = 0, n = retainersArray.length; i < n; ++i) { + var entry = retainersArray[i].split(";"); + rawRetainers[entry[0]] = parseInt(entry[1], 10); + } + + function mergeRetainers(entry) { + for (var rawRetainer in rawRetainers) { + var consName = rawRetainer.indexOf(":") !== -1 ? rawRetainer.split(":")[0] : rawRetainer; + if (!(consName in entry.retainers)) + entry.retainers[consName] = { cons: consName, count: 0, clusters: {} }; + var retainer = entry.retainers[consName]; + retainer.count += rawRetainers[rawRetainer]; + if (consName !== rawRetainer) + retainer.clusters[rawRetainer] = true; + } + } + + if (item.indexOf(":") !== -1) { + // Array, Function, or Object instances cluster case. + if (!(item in this.currentHeapSnapshot_.clusters)) { + this.currentHeapSnapshot_.clusters[item] = { + cons: item, retainers: {} + }; + } + mergeRetainers(this.currentHeapSnapshot_.clusters[item]); + item = item.split(":")[0]; + } + mergeRetainers(this.currentHeapSnapshot_.entries[item]); +}; + + +devtools.profiler.Processor.prototype.processHeapSampleEnd_ = function(space, state) +{ + if (space !== "Heap") return; + var snapshot = this.currentHeapSnapshot_; + this.currentHeapSnapshot_ = null; + WebInspector.panels.profiles.addSnapshot(snapshot); +}; + + +/** + * Creates a profile for further displaying in ProfileView. + */ +devtools.profiler.Processor.prototype.createProfileForView = function() +{ + var profile = this.viewBuilder_.buildView(this.currentProfile_.getTopDownProfile()); + profile.uid = this.profileId_++; + profile.title = UserInitiatedProfileName + "." + profile.uid; + return profile; +}; diff --git a/WebKit/chromium/src/js/Tests.js b/WebKit/chromium/src/js/Tests.js new file mode 100644 index 0000000..fa0c99f --- /dev/null +++ b/WebKit/chromium/src/js/Tests.js @@ -0,0 +1,1862 @@ +/* + * Copyright (C) 2010 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 + * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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. + */ + + +/** + * @fileoverview This file contains small testing framework along with the + * test suite for the frontend. These tests are a part of the continues build + * and are executed by the devtools_sanity_unittest.cc as a part of the + * Interactive UI Test suite. + * FIXME: change field naming style to use trailing underscore. + */ + +if (window.domAutomationController) { + +var ___interactiveUiTestsMode = true; + +/** + * Test suite for interactive UI tests. + * @constructor + */ +TestSuite = function() +{ + this.controlTaken_ = false; + this.timerId_ = -1; +}; + + +/** + * Reports test failure. + * @param {string} message Failure description. + */ +TestSuite.prototype.fail = function(message) +{ + if (this.controlTaken_) + this.reportFailure_(message); + else + throw message; +}; + + +/** + * Equals assertion tests that expected === actual. + * @param {Object} expected Expected object. + * @param {Object} actual Actual object. + * @param {string} opt_message User message to print if the test fails. + */ +TestSuite.prototype.assertEquals = function(expected, actual, opt_message) +{ + if (expected !== actual) { + var message = "Expected: '" + expected + "', but was '" + actual + "'"; + if (opt_message) + message = opt_message + "(" + message + ")"; + this.fail(message); + } +}; + + +/** + * True assertion tests that value == true. + * @param {Object} value Actual object. + * @param {string} opt_message User message to print if the test fails. + */ +TestSuite.prototype.assertTrue = function(value, opt_message) +{ + this.assertEquals(true, !!value, opt_message); +}; + + +/** + * Contains assertion tests that string contains substring. + * @param {string} string Outer. + * @param {string} substring Inner. + */ +TestSuite.prototype.assertContains = function(string, substring) +{ + if (string.indexOf(substring) === -1) + this.fail("Expected to: '" + string + "' to contain '" + substring + "'"); +}; + + +/** + * Takes control over execution. + */ +TestSuite.prototype.takeControl = function() +{ + this.controlTaken_ = true; + // Set up guard timer. + var self = this; + this.timerId_ = setTimeout(function() { + self.reportFailure_("Timeout exceeded: 20 sec"); + }, 20000); +}; + + +/** + * Releases control over execution. + */ +TestSuite.prototype.releaseControl = function() +{ + if (this.timerId_ !== -1) { + clearTimeout(this.timerId_); + this.timerId_ = -1; + } + this.reportOk_(); +}; + + +/** + * Async tests use this one to report that they are completed. + */ +TestSuite.prototype.reportOk_ = function() +{ + window.domAutomationController.send("[OK]"); +}; + + +/** + * Async tests use this one to report failures. + */ +TestSuite.prototype.reportFailure_ = function(error) +{ + if (this.timerId_ !== -1) { + clearTimeout(this.timerId_); + this.timerId_ = -1; + } + window.domAutomationController.send("[FAILED] " + error); +}; + + +/** + * Runs all global functions starting with "test" as unit tests. + */ +TestSuite.prototype.runTest = function(testName) +{ + try { + this[testName](); + if (!this.controlTaken_) + this.reportOk_(); + } catch (e) { + this.reportFailure_(e); + } +}; + + +/** + * @param {string} panelName Name of the panel to show. + */ +TestSuite.prototype.showPanel = function(panelName) +{ + // Open Scripts panel. + var toolbar = document.getElementById("toolbar"); + var button = toolbar.getElementsByClassName(panelName)[0]; + button.click(); + this.assertEquals(WebInspector.panels[panelName], WebInspector.currentPanel); +}; + + +/** + * Overrides the method with specified name until it's called first time. + * @param {Object} receiver An object whose method to override. + * @param {string} methodName Name of the method to override. + * @param {Function} override A function that should be called right after the + * overriden method returns. + * @param {boolean} opt_sticky Whether restore original method after first run + * or not. + */ +TestSuite.prototype.addSniffer = function(receiver, methodName, override, opt_sticky) +{ + var orig = receiver[methodName]; + if (typeof orig !== "function") + this.fail("Cannot find method to override: " + methodName); + var test = this; + receiver[methodName] = function(var_args) { + try { + var result = orig.apply(this, arguments); + } finally { + if (!opt_sticky) + receiver[methodName] = orig; + } + // In case of exception the override won't be called. + try { + override.apply(this, arguments); + } catch (e) { + test.fail("Exception in overriden method '" + methodName + "': " + e); + } + return result; + }; +}; + + +// UI Tests + + +/** + * Tests that the real injected host is present in the context. + */ +TestSuite.prototype.testHostIsPresent = function() +{ + this.assertTrue(typeof InspectorFrontendHost === "object" && !InspectorFrontendHost.isStub); +}; + + +/** + * Tests elements tree has an "HTML" root. + */ +TestSuite.prototype.testElementsTreeRoot = function() +{ + var doc = WebInspector.domAgent.document; + this.assertEquals("HTML", doc.documentElement.nodeName); + this.assertTrue(doc.documentElement.hasChildNodes()); +}; + + +/** + * Tests that main resource is present in the system and that it is + * the only resource. + */ +TestSuite.prototype.testMainResource = function() +{ + var tokens = []; + var resources = WebInspector.resources; + for (var id in resources) + tokens.push(resources[id].lastPathComponent); + this.assertEquals("simple_page.html", tokens.join(",")); +}; + + +/** + * Tests that resources tab is enabled when corresponding item is selected. + */ +TestSuite.prototype.testEnableResourcesTab = function() +{ + this.showPanel("resources"); + + var test = this; + this.addSniffer(WebInspector, "updateResource", + function(identifier, payload) { + test.assertEquals("simple_page.html", payload.lastPathComponent); + WebInspector.panels.resources.refresh(); + WebInspector.panels.resources.revealAndSelectItem(WebInspector.resources[identifier]); + + test.releaseControl(); + }); + + // Following call should lead to reload that we capture in the + // addResource override. + WebInspector.panels.resources._enableResourceTracking(); + + // We now have some time to report results to controller. + this.takeControl(); +}; + + +/** + * Tests that correct content length is reported for resources. + */ +TestSuite.prototype.testResourceContentLength = function() +{ + this.showPanel("resources"); + var test = this; + + var png = false; + var html = false; + this.addSniffer(WebInspector, "updateResource", + function(identifier, payload) { + if (!payload.didLengthChange) + return; + var resource = WebInspector.resources[identifier]; + if (!resource || !resource.url) + return; + if (resource.url.search("image.html$") !== -1) { + var expectedLength = 87; + test.assertTrue( + resource.contentLength <= expectedLength, + "image.html content length is greater thatn expected."); + if (expectedLength === resource.contentLength) + html = true; + } else if (resource.url.search("image.png") !== -1) { + var expectedLength = 257796; + test.assertTrue( + resource.contentLength <= expectedLength, + "image.png content length is greater than expected."); + if (expectedLength === resource.contentLength) + png = true; + } + if (html && png) { + // Wait 1 second before releasing control to check that the content + // lengths are not updated anymore. + setTimeout(function() { + test.releaseControl(); + }, 1000); + } + }, true); + + // Make sure resource tracking is on. + WebInspector.panels.resources._enableResourceTracking(); + // Reload inspected page to update all resources. + test.evaluateInConsole_( + "window.location.reload(true);", + function(resultText) { + test.assertEquals("undefined", resultText, "Unexpected result of reload()."); + }); + + // We now have some time to report results to controller. + this.takeControl(); +}; + + +/** + * Tests resource headers. + */ +TestSuite.prototype.testResourceHeaders = function() +{ + this.showPanel("resources"); + + var test = this; + + var responseOk = false; + var timingOk = false; + + this.addSniffer(WebInspector, "updateResource", + function(identifier, payload) { + var resource = this.resources[identifier]; + if (!resource || resource.mainResource) { + // We are only interested in secondary resources in this test. + return; + } + + var requestHeaders = JSON.stringify(resource.requestHeaders); + test.assertContains(requestHeaders, "Accept"); + + if (payload.didResponseChange) { + var responseHeaders = JSON.stringify(resource.responseHeaders); + test.assertContains(responseHeaders, "Content-type"); + test.assertContains(responseHeaders, "Content-Length"); + test.assertTrue(typeof resource.responseReceivedTime !== "undefined"); + responseOk = true; + } + + if (payload.didTimingChange) { + test.assertTrue(typeof resource.startTime !== "undefined"); + timingOk = true; + } + + if (payload.didCompletionChange) { + test.assertTrue(responseOk); + test.assertTrue(timingOk); + test.assertTrue(typeof resource.endTime !== "undefined"); + test.releaseControl(); + } + }, true); + + WebInspector.panels.resources._enableResourceTracking(); + this.takeControl(); +}; + + +/** + * Tests the mime type of a cached (HTTP 304) resource. + */ +TestSuite.prototype.testCachedResourceMimeType = function() +{ + this.showPanel("resources"); + + var test = this; + var hasReloaded = false; + + this.addSniffer(WebInspector, "updateResource", + function(identifier, payload) { + var resource = this.resources[identifier]; + if (!resource || resource.mainResource) { + // We are only interested in secondary resources in this test. + return; + } + + if (payload.didResponseChange) { + // Test server uses a default mime type for JavaScript files. + test.assertEquals("text/html", payload.mimeType); + if (!hasReloaded) { + hasReloaded = true; + // Reload inspected page to update all resources. + test.evaluateInConsole_("window.location.reload(true);", function() {}); + } else + test.releaseControl(); + } + + }, true); + + WebInspector.panels.resources._enableResourceTracking(); + this.takeControl(); +}; + + +/** + * Tests that profiler works. + */ +TestSuite.prototype.testProfilerTab = function() +{ + this.showPanel("profiles"); + + var test = this; + this.addSniffer(WebInspector.panels.profiles, "addProfileHeader", + function(typeOrProfile, profile) { + if (!profile) + profile = typeOrProfile; + var panel = WebInspector.panels.profiles; + panel.showProfile(profile); + var node = panel.visibleView.profileDataGridTree.children[0]; + // Iterate over displayed functions and search for a function + // that is called "fib" or "eternal_fib". If found, it will mean + // that we actually have profiled page's code. + while (node) { + if (node.functionName.indexOf("fib") !== -1) + test.releaseControl(); + node = node.traverseNextNode(true, null, true); + } + + test.fail(); + }); + var ticksCount = 0; + var tickRecord = "\nt,"; + this.addSniffer(RemoteProfilerAgent, "didGetLogLines", + function(posIgnored, log) { + var pos = 0; + while ((pos = log.indexOf(tickRecord, pos)) !== -1) { + pos += tickRecord.length; + ticksCount++; + } + if (ticksCount > 100) + InspectorBackend.stopProfiling(); + }, true); + + InspectorBackend.startProfiling(); + this.takeControl(); +}; + + +/** + * Tests that scripts tab can be open and populated with inspected scripts. + */ +TestSuite.prototype.testShowScriptsTab = function() +{ + this.showPanel("scripts"); + var test = this; + // There should be at least main page script. + this._waitUntilScriptsAreParsed(["debugger_test_page.html$"], + function() { + test.releaseControl(); + }); + // Wait until all scripts are added to the debugger. + this.takeControl(); +}; + + +/** + * Tests that scripts tab is populated with inspected scripts even if it + * hadn't been shown by the moment inspected paged refreshed. + * @see http://crbug.com/26312 + */ +TestSuite.prototype.testScriptsTabIsPopulatedOnInspectedPageRefresh = function() +{ + var test = this; + this.assertEquals(WebInspector.panels.elements, WebInspector.currentPanel, "Elements panel should be current one."); + + this.addSniffer(devtools.DebuggerAgent.prototype, "reset", waitUntilScriptIsParsed); + + // Reload inspected page. It will reset the debugger agent. + test.evaluateInConsole_( + "window.location.reload(true);", + function(resultText) { + test.assertEquals("undefined", resultText, "Unexpected result of reload()."); + }); + + function waitUntilScriptIsParsed() { + var parsed = devtools.tools.getDebuggerAgent().parsedScripts_; + for (var id in parsed) { + var url = parsed[id].getUrl(); + if (url && url.search("debugger_test_page.html$") !== -1) { + checkScriptsPanel(); + return; + } + } + test.addSniffer(devtools.DebuggerAgent.prototype, "addScriptInfo_", waitUntilScriptIsParsed); + } + + function checkScriptsPanel() { + test.showPanel("scripts"); + test.assertTrue(test._scriptsAreParsed(["debugger_test_page.html$"]), "Inspected script not found in the scripts list"); + test.releaseControl(); + } + + // Wait until all scripts are added to the debugger. + this.takeControl(); +}; + + +/** + * Tests that scripts list contains content scripts. + */ +TestSuite.prototype.testContentScriptIsPresent = function() +{ + this.showPanel("scripts"); + var test = this; + + test._waitUntilScriptsAreParsed( + ["page_with_content_script.html$", "simple_content_script.js$"], + function() { + test.releaseControl(); + }); + + // Wait until all scripts are added to the debugger. + this.takeControl(); +}; + + +/** + * Tests that scripts are not duplicaed on Scripts tab switch. + */ +TestSuite.prototype.testNoScriptDuplicatesOnPanelSwitch = function() +{ + var test = this; + + // There should be two scripts: one for the main page and another + // one which is source of console API(see + // InjectedScript._ensureCommandLineAPIInstalled). + var expectedScriptsCount = 2; + var parsedScripts = []; + + this.showPanel("scripts"); + + + function switchToElementsTab() { + test.showPanel("elements"); + setTimeout(switchToScriptsTab, 0); + } + + function switchToScriptsTab() { + test.showPanel("scripts"); + setTimeout(checkScriptsPanel, 0); + } + + function checkScriptsPanel() { + test.assertTrue(!!WebInspector.panels.scripts.visibleView, "No visible script view."); + test.assertTrue(test._scriptsAreParsed(["debugger_test_page.html$"]), "Some scripts are missing."); + checkNoDuplicates(); + test.releaseControl(); + } + + function checkNoDuplicates() { + var scriptSelect = document.getElementById("scripts-files"); + var options = scriptSelect.options; + for (var i = 0; i < options.length; i++) { + var scriptName = options[i].text; + for (var j = i + 1; j < options.length; j++) + test.assertTrue(scriptName !== options[j].text, "Found script duplicates: " + test.optionsToString_(options)); + } + } + + test._waitUntilScriptsAreParsed( + ["debugger_test_page.html$"], + function() { + checkNoDuplicates(); + setTimeout(switchToElementsTab, 0); + }); + + + // Wait until all scripts are added to the debugger. + this.takeControl(); +}; + + +/** + * Tests that a breakpoint can be set. + */ +TestSuite.prototype.testSetBreakpoint = function() +{ + var test = this; + this.showPanel("scripts"); + + var breakpointLine = 12; + + this._waitUntilScriptsAreParsed(["debugger_test_page.html"], + function() { + test.showMainPageScriptSource_( + "debugger_test_page.html", + function(view, url) { + view._addBreakpoint(breakpointLine); + // Force v8 execution. + RemoteDebuggerAgent.processDebugCommands(); + test.waitForSetBreakpointResponse_(url, breakpointLine, + function() { + test.releaseControl(); + }); + }); + }); + + this.takeControl(); +}; + + +/** + * Tests that pause on exception works. + */ +TestSuite.prototype.testPauseOnException = function() +{ + this.showPanel("scripts"); + var test = this; + + // TODO(yurys): remove else branch once the states are supported. + if (WebInspector.ScriptsPanel.PauseOnExceptionsState) { + while (WebInspector.currentPanel.pauseOnExceptionButton.state !== WebInspector.ScriptsPanel.PauseOnExceptionsState.PauseOnUncaughtExceptions) + WebInspector.currentPanel.pauseOnExceptionButton.element.click(); + } else { + // Make sure pause on exceptions is on. + if (!WebInspector.currentPanel.pauseOnExceptionButton.toggled) + WebInspector.currentPanel.pauseOnExceptionButton.element.click(); + } + + this._executeCodeWhenScriptsAreParsed("handleClick()", ["pause_on_exception.html$"]); + + this._waitForScriptPause( + { + functionsOnStack: ["throwAnException", "handleClick", "(anonymous function)"], + lineNumber: 6, + lineText: " return unknown_var;" + }, + function() { + test.releaseControl(); + }); + + this.takeControl(); +}; + + +// Tests that debugger works correctly if pause event occurs when DevTools +// frontend is being loaded. +TestSuite.prototype.testPauseWhenLoadingDevTools = function() +{ + this.showPanel("scripts"); + var test = this; + + var expectations = { + functionsOnStack: ["callDebugger"], + lineNumber: 8, + lineText: " debugger;" + }; + + + // Script execution can already be paused. + if (WebInspector.currentPanel.paused) { + var callFrame = WebInspector.currentPanel.sidebarPanes.callstack.selectedCallFrame; + this.assertEquals(expectations.functionsOnStack[0], callFrame.functionName); + var callbackInvoked = false; + this._checkSourceFrameWhenLoaded(expectations, function() { + callbackInvoked = true; + if (test.controlTaken_) + test.releaseControl(); + }); + if (!callbackInvoked) { + test.takeControl(); + } + return; + } + + this._waitForScriptPause( + { + functionsOnStack: ["callDebugger"], + lineNumber: 8, + lineText: " debugger;" + }, + function() { + test.releaseControl(); + }); + this.takeControl(); +}; + + +// Tests that pressing "Pause" will pause script execution if the script +// is already running. +TestSuite.prototype.testPauseWhenScriptIsRunning = function() +{ + this.showPanel("scripts"); + var test = this; + + test.evaluateInConsole_( + 'setTimeout("handleClick()" , 0)', + function(resultText) { + test.assertTrue(!isNaN(resultText), "Failed to get timer id: " + resultText); + testScriptPauseAfterDelay(); + }); + + // Wait for some time to make sure that inspected page is running the + // infinite loop. + function testScriptPauseAfterDelay() { + setTimeout(testScriptPause, 300); + } + + function testScriptPause() { + // The script should be in infinite loop. Click "Pause" button to + // pause it and wait for the result. + WebInspector.panels.scripts.pauseButton.click(); + + test._waitForScriptPause( + { + functionsOnStack: ["handleClick", "(anonymous function)"], + lineNumber: 5, + lineText: " while(true) {" + }, + function() { + test.releaseControl(); + }); + } + + this.takeControl(); +}; + + +/** + * Serializes options collection to string. + * @param {HTMLOptionsCollection} options + * @return {string} + */ +TestSuite.prototype.optionsToString_ = function(options) +{ + var names = []; + for (var i = 0; i < options.length; i++) + names.push('"' + options[i].text + '"'); + return names.join(","); +}; + + +/** + * Ensures that main HTML resource is selected in Scripts panel and that its + * source frame is setup. Invokes the callback when the condition is satisfied. + * @param {HTMLOptionsCollection} options + * @param {function(WebInspector.SourceView,string)} callback + */ +TestSuite.prototype.showMainPageScriptSource_ = function(scriptName, callback) +{ + var test = this; + + var scriptSelect = document.getElementById("scripts-files"); + var options = scriptSelect.options; + + test.assertTrue(options.length, "Scripts list is empty"); + + // Select page's script if it's not current option. + var scriptResource; + if (options[scriptSelect.selectedIndex].text === scriptName) + scriptResource = options[scriptSelect.selectedIndex].representedObject; + else { + var pageScriptIndex = -1; + for (var i = 0; i < options.length; i++) { + if (options[i].text === scriptName) { + pageScriptIndex = i; + break; + } + } + test.assertTrue(-1 !== pageScriptIndex, "Script with url " + scriptName + " not found among " + test.optionsToString_(options)); + scriptResource = options[pageScriptIndex].representedObject; + + // Current panel is "Scripts". + WebInspector.currentPanel._showScriptOrResource(scriptResource); + test.assertEquals(pageScriptIndex, scriptSelect.selectedIndex, "Unexpected selected option index."); + } + + test.assertTrue(scriptResource instanceof WebInspector.Resource, + "Unexpected resource class."); + test.assertTrue(!!scriptResource.url, "Resource URL is null."); + test.assertTrue(scriptResource.url.search(scriptName + "$") !== -1, "Main HTML resource should be selected."); + + var scriptsPanel = WebInspector.panels.scripts; + + var view = scriptsPanel.visibleView; + test.assertTrue(view instanceof WebInspector.SourceView); + + if (!view.sourceFrame._loaded) { + test.addSniffer(view, "_sourceFrameSetupFinished", function(event) { + callback(view, scriptResource.url); + }); + } else + callback(view, scriptResource.url); +}; + + +/* + * Evaluates the code in the console as if user typed it manually and invokes + * the callback when the result message is received and added to the console. + * @param {string} code + * @param {function(string)} callback + */ +TestSuite.prototype.evaluateInConsole_ = function(code, callback) +{ + WebInspector.console.visible = true; + WebInspector.console.prompt.text = code; + WebInspector.console.promptElement.dispatchEvent( TestSuite.createKeyEvent("Enter")); + + this.addSniffer(WebInspector.ConsoleView.prototype, "addMessage", + function(commandResult) { + callback(commandResult.toMessageElement().textContent); + }); +}; + + +/* + * Waits for "setbreakpoint" response, checks that corresponding breakpoint + * was successfully set and invokes the callback if it was. + * @param {string} scriptUrl + * @param {number} breakpointLine + * @param {function()} callback + */ +TestSuite.prototype.waitForSetBreakpointResponse_ = function(scriptUrl, breakpointLine, callback) +{ + var test = this; + test.addSniffer( + devtools.DebuggerAgent.prototype, + "handleSetBreakpointResponse_", + function(msg) { + var bps = this.urlToBreakpoints_[scriptUrl]; + test.assertTrue(!!bps, "No breakpoints for line " + breakpointLine); + var line = devtools.DebuggerAgent.webkitToV8LineNumber_(breakpointLine); + test.assertTrue(!!bps[line].getV8Id(), "Breakpoint id was not assigned."); + callback(); + }); +}; + + +/** + * Tests eval on call frame. + */ +TestSuite.prototype.testEvalOnCallFrame = function() +{ + this.showPanel("scripts"); + + var breakpointLine = 16; + + var test = this; + this.addSniffer(devtools.DebuggerAgent.prototype, "handleScriptsResponse_", + function(msg) { + test.showMainPageScriptSource_( + "debugger_test_page.html", + function(view, url) { + view._addBreakpoint(breakpointLine); + // Force v8 execution. + RemoteDebuggerAgent.processDebugCommands(); + test.waitForSetBreakpointResponse_(url, breakpointLine, setBreakpointCallback); + }); + }); + + function setBreakpointCallback() { + // Since breakpoints are ignored in evals' calculate() function is + // execute after zero-timeout so that the breakpoint is hit. + test.evaluateInConsole_( + 'setTimeout("calculate(123)" , 0)', + function(resultText) { + test.assertTrue(!isNaN(resultText), "Failed to get timer id: " + resultText); + waitForBreakpointHit(); + }); + } + + function waitForBreakpointHit() { + test.addSniffer( + devtools.DebuggerAgent.prototype, + "handleBacktraceResponse_", + function(msg) { + test.assertEquals(2, this.callFrames_.length, "Unexpected stack depth on the breakpoint. " + JSON.stringify(msg)); + test.assertEquals("calculate", this.callFrames_[0].functionName, "Unexpected top frame function."); + // Evaluate "e+1" where "e" is an argument of "calculate" function. + test.evaluateInConsole_( + "e+1", + function(resultText) { + test.assertEquals("124", resultText, 'Unexpected "e+1" value.'); + test.releaseControl(); + }); + }); + } + + this.takeControl(); +}; + + +/** + * Tests that console auto completion works when script execution is paused. + */ +TestSuite.prototype.testCompletionOnPause = function() +{ + this.showPanel("scripts"); + var test = this; + this._executeCodeWhenScriptsAreParsed("handleClick()", ["completion_on_pause.html$"]); + + this._waitForScriptPause( + { + functionsOnStack: ["innerFunction", "handleClick", "(anonymous function)"], + lineNumber: 9, + lineText: " debugger;" + }, + showConsole); + + function showConsole() { + test.addSniffer(WebInspector.console, "afterShow", testLocalsCompletion); + WebInspector.showConsole(); + } + + function testLocalsCompletion() { + checkCompletions("th", ["parameter1", "closureLocal", "p", "createClosureLocal"], testThisCompletion); + } + + function testThisCompletion() { + checkCompletions("this.", ["field1", "field2", "m"], testFieldCompletion); + } + + function testFieldCompletion() { + checkCompletions("this.field1.", ["id", "name"], function() { test.releaseControl(); }); + } + + function checkCompletions(expression, expectedProperties, callback) { + test.addSniffer(WebInspector.console, "_reportCompletions", + function(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, result, isException) { + test.assertTrue(!isException, "Exception while collecting completions"); + for (var i = 0; i < expectedProperties.length; i++) { + var name = expectedProperties[i]; + test.assertTrue(result[name], "Name " + name + " not found among the completions: " + JSON.stringify(result)); + } + setTimeout(callback, 0); + }); + WebInspector.console.prompt.text = expression; + WebInspector.console.prompt.autoCompleteSoon(); + } + + this.takeControl(); +}; + + +/** + * Tests that inspected page doesn't hang on reload if it contains a syntax + * error and DevTools window is open. + */ +TestSuite.prototype.testAutoContinueOnSyntaxError = function() +{ + this.showPanel("scripts"); + var test = this; + + function checkScriptsList() { + var scriptSelect = document.getElementById("scripts-files"); + var options = scriptSelect.options; + // There should be only console API source (see + // InjectedScript._ensureCommandLineAPIInstalled) since the page script + // contains a syntax error. + for (var i = 0 ; i < options.length; i++) { + if (options[i].text.search("script_syntax_error.html$") !== -1) + test.fail("Script with syntax error should not be in the list of parsed scripts."); + } + } + + this.addSniffer(devtools.DebuggerAgent.prototype, "handleScriptsResponse_", + function(msg) { + checkScriptsList(); + + // Reload inspected page. + test.evaluateInConsole_( + "window.location.reload(true);", + function(resultText) { + test.assertEquals("undefined", resultText, "Unexpected result of reload()."); + waitForExceptionEvent(); + }); + }); + + function waitForExceptionEvent() { + var exceptionCount = 0; + test.addSniffer( + devtools.DebuggerAgent.prototype, + "handleExceptionEvent_", + function(msg) { + exceptionCount++; + test.assertEquals(1, exceptionCount, "Too many exceptions."); + test.assertEquals(undefined, msg.getBody().script, "Unexpected exception: " + JSON.stringify(msg)); + test.releaseControl(); + }); + + // Check that the script is not paused on parse error. + test.addSniffer( + WebInspector, + "pausedScript", + function(callFrames) { + test.fail("Script execution should not pause on syntax error."); + }); + } + + this.takeControl(); +}; + + +/** + * Checks current execution line against expectations. + * @param {WebInspector.SourceFrame} sourceFrame + * @param {number} lineNumber Expected line number + * @param {string} lineContent Expected line text + */ +TestSuite.prototype._checkExecutionLine = function(sourceFrame, lineNumber, lineContent) +{ + this.assertEquals(lineNumber, sourceFrame.executionLine, "Unexpected execution line number."); + this.assertEquals(lineContent, sourceFrame._textModel.line(lineNumber - 1), "Unexpected execution line text."); +} + + +/** + * Checks that all expected scripts are present in the scripts list + * in the Scripts panel. + * @param {Array.<string>} expected Regular expressions describing + * expected script names. + * @return {boolean} Whether all the scripts are in "scripts-files" select + * box + */ +TestSuite.prototype._scriptsAreParsed = function(expected) +{ + var scriptSelect = document.getElementById("scripts-files"); + var options = scriptSelect.options; + + // Check that at least all the expected scripts are present. + var missing = expected.slice(0); + for (var i = 0 ; i < options.length; i++) { + for (var j = 0; j < missing.length; j++) { + if (options[i].text.search(missing[j]) !== -1) { + missing.splice(j, 1); + break; + } + } + } + return missing.length === 0; +}; + + +/** + * Waits for script pause, checks expectations, and invokes the callback. + * @param {Object} expectations Dictionary of expectations + * @param {function():void} callback + */ +TestSuite.prototype._waitForScriptPause = function(expectations, callback) +{ + var test = this; + // Wait until script is paused. + test.addSniffer( + WebInspector, + "pausedScript", + function(callFrames) { + var functionsOnStack = []; + for (var i = 0; i < callFrames.length; i++) + functionsOnStack.push(callFrames[i].functionName); + + test.assertEquals(expectations.functionsOnStack.join(","), functionsOnStack.join(","), "Unexpected stack."); + + // Check that execution line where the script is paused is + // expected one. + test._checkSourceFrameWhenLoaded(expectations, callback); + }); +}; + + +/** + * Waits for current source frame to load, checks expectations, and invokes + * the callback. + * @param {Object} expectations Dictionary of expectations + * @param {function():void} callback + */ +TestSuite.prototype._checkSourceFrameWhenLoaded = function(expectations, callback) +{ + var test = this; + + var frame = WebInspector.currentPanel.visibleView.sourceFrame; + if (frame._loaded) + checkExecLine(); + else { + setTimeout(function() { + test._checkSourceFrameWhenLoaded(expectations, callback); + }, 100); + } + function checkExecLine() { + test._checkExecutionLine(frame, expectations.lineNumber, expectations.lineText); + callback(); + } +}; + + +/** + * Performs sequence of steps. + * @param {Array.<Object|Function>} Array [expectations1,action1,expectations2, + * action2,...,actionN]. + */ +TestSuite.prototype._performSteps = function(actions) +{ + var test = this; + var i = 0; + function doNextAction() { + if (i > 0) + actions[i++](); + if (i < actions.length - 1) + test._waitForScriptPause(actions[i++], doNextAction); + } + doNextAction(); +}; + + +/** + * Waits until all the scripts are parsed and asynchronously executes the code + * in the inspected page. + */ +TestSuite.prototype._executeCodeWhenScriptsAreParsed = function(code, expectedScripts) +{ + var test = this; + + function executeFunctionInInspectedPage() { + // Since breakpoints are ignored in evals' calculate() function is + // execute after zero-timeout so that the breakpoint is hit. + test.evaluateInConsole_( + 'setTimeout("' + code + '" , 0)', + function(resultText) { + test.assertTrue(!isNaN(resultText), "Failed to get timer id: " + resultText); + }); + } + + test._waitUntilScriptsAreParsed(expectedScripts, executeFunctionInInspectedPage); +}; + + +/** + * Waits until all the scripts are parsed and invokes the callback. + */ +TestSuite.prototype._waitUntilScriptsAreParsed = function(expectedScripts, callback) +{ + var test = this; + + function waitForAllScripts() { + if (test._scriptsAreParsed(expectedScripts)) + callback(); + else + test.addSniffer(WebInspector, "parsedScriptSource", waitForAllScripts); + } + + waitForAllScripts(); +}; + + +/** + * Waits until all debugger scripts are parsed and executes "a()" in the + * inspected page. + */ +TestSuite.prototype._executeFunctionForStepTest = function() +{ + this._executeCodeWhenScriptsAreParsed("a()", ["debugger_step.html$", "debugger_step.js$"]); +}; + + +/** + * Tests step over in the debugger. + */ +TestSuite.prototype.testStepOver = function() +{ + this.showPanel("scripts"); + var test = this; + + this._executeFunctionForStepTest(); + + this._performSteps([ + { + functionsOnStack: ["d","a","(anonymous function)"], + lineNumber: 3, + lineText: " debugger;" + }, + function() { + document.getElementById("scripts-step-over").click(); + }, + { + functionsOnStack: ["d","a","(anonymous function)"], + lineNumber: 5, + lineText: " var y = fact(10);" + }, + function() { + document.getElementById("scripts-step-over").click(); + }, + { + functionsOnStack: ["d","a","(anonymous function)"], + lineNumber: 6, + lineText: " return y;" + }, + function() { + test.releaseControl(); + } + ]); + + test.takeControl(); +}; + + +/** + * Tests step out in the debugger. + */ +TestSuite.prototype.testStepOut = function() +{ + this.showPanel("scripts"); + var test = this; + + this._executeFunctionForStepTest(); + + this._performSteps([ + { + functionsOnStack: ["d","a","(anonymous function)"], + lineNumber: 3, + lineText: " debugger;" + }, + function() { + document.getElementById("scripts-step-out").click(); + }, + { + functionsOnStack: ["a","(anonymous function)"], + lineNumber: 8, + lineText: " printResult(result);" + }, + function() { + test.releaseControl(); + } + ]); + + test.takeControl(); +}; + + +/** + * Tests step in in the debugger. + */ +TestSuite.prototype.testStepIn = function() +{ + this.showPanel("scripts"); + var test = this; + + this._executeFunctionForStepTest(); + + this._performSteps([ + { + functionsOnStack: ["d","a","(anonymous function)"], + lineNumber: 3, + lineText: " debugger;" + }, + function() { + document.getElementById("scripts-step-over").click(); + }, + { + functionsOnStack: ["d","a","(anonymous function)"], + lineNumber: 5, + lineText: " var y = fact(10);" + }, + function() { + document.getElementById("scripts-step-into").click(); + }, + { + functionsOnStack: ["fact","d","a","(anonymous function)"], + lineNumber: 15, + lineText: " return r;" + }, + function() { + test.releaseControl(); + } + ]); + + test.takeControl(); +}; + + +/** + * Gets a XPathResult matching given xpath. + * @param {string} xpath + * @param {number} resultType + * @param {Node} opt_ancestor Context node. If not specified documentElement + * will be used + * @return {XPathResult} Type of returned value is determined by "resultType" parameter + */ + +TestSuite.prototype._evaluateXpath = function(xpath, resultType, opt_ancestor) +{ + if (!opt_ancestor) + opt_ancestor = document.documentElement; + try { + return document.evaluate(xpath, opt_ancestor, null, resultType, null); + } catch(e) { + this.fail('Error in expression: "' + xpath + '".' + e); + } +}; + + +/** + * Gets first Node matching given xpath. + * @param {string} xpath + * @param {Node} opt_ancestor Context node. If not specified documentElement + * will be used + * @return {?Node} + */ +TestSuite.prototype._findNode = function(xpath, opt_ancestor) +{ + var result = this._evaluateXpath(xpath, XPathResult.FIRST_ORDERED_NODE_TYPE, opt_ancestor).singleNodeValue; + this.assertTrue(!!result, "Cannot find node on path: " + xpath); + return result; +}; + + +/** + * Gets a text matching given xpath. + * @param {string} xpath + * @param {Node} opt_ancestor Context node. If not specified documentElement + * will be used + * @return {?string} + */ +TestSuite.prototype._findText = function(xpath, opt_ancestor) +{ + var result = this._evaluateXpath(xpath, XPathResult.STRING_TYPE, opt_ancestor).stringValue; + this.assertTrue(!!result, "Cannot find text on path: " + xpath); + return result; +}; + + +/** + * Gets an iterator over nodes matching given xpath. + * @param {string} xpath + * @param {Node} opt_ancestor Context node. If not specified, documentElement + * will be used + * @return {XPathResult} Iterator over the nodes + */ +TestSuite.prototype._nodeIterator = function(xpath, opt_ancestor) +{ + return this._evaluateXpath(xpath, XPathResult.ORDERED_NODE_ITERATOR_TYPE, opt_ancestor); +}; + + +/** + * Checks the scopeSectionDiv against the expectations. + * @param {Node} scopeSectionDiv The section div + * @param {Object} expectations Expectations dictionary + */ +TestSuite.prototype._checkScopeSectionDiv = function(scopeSectionDiv, expectations) +{ + var scopeTitle = this._findText('./div[@class="header"]/div[@class="title"]/text()', scopeSectionDiv); + this.assertEquals(expectations.title, scopeTitle, "Unexpected scope section title."); + if (!expectations.properties) + return; + this.assertTrue(scopeSectionDiv.hasStyleClass("expanded"), 'Section "' + scopeTitle + '" is collapsed.'); + + var propertyIt = this._nodeIterator("./ol/li", scopeSectionDiv); + var propertyLi; + var foundProps = []; + while (propertyLi = propertyIt.iterateNext()) { + var name = this._findText('./span[@class="name"]/text()', propertyLi); + var value = this._findText('./span[@class="value"]/text()', propertyLi); + this.assertTrue(!!name, 'Invalid variable name: "' + name + '"'); + this.assertTrue(name in expectations.properties, "Unexpected property: " + name); + this.assertEquals(expectations.properties[name], value, 'Unexpected "' + name + '" property value.'); + delete expectations.properties[name]; + foundProps.push(name + " = " + value); + } + + // Check that all expected properties were found. + for (var p in expectations.properties) + this.fail('Property "' + p + '" was not found in scope "' + scopeTitle + '". Found properties: "' + foundProps.join(",") + '"'); +}; + + +/** + * Expands scope sections matching the filter and invokes the callback on + * success. + * @param {function(WebInspector.ObjectPropertiesSection, number):boolean} + * filter + * @param {Function} callback + */ +TestSuite.prototype._expandScopeSections = function(filter, callback) +{ + var sections = WebInspector.currentPanel.sidebarPanes.scopechain.sections; + + var toBeUpdatedCount = 0; + function updateListener() { + --toBeUpdatedCount; + if (toBeUpdatedCount === 0) { + // Report when all scopes are expanded and populated. + callback(); + } + } + + // Global scope is always the last one. + for (var i = 0; i < sections.length - 1; i++) { + var section = sections[i]; + if (!filter(sections, i)) + continue; + ++toBeUpdatedCount; + var populated = section.populated; + + this._hookGetPropertiesCallback(updateListener, + function() { + section.expand(); + if (populated) { + // Make sure "updateProperties" callback will be called at least once + // after it was overridden. + section.update(); + } + }); + } +}; + + +/** + * Tests that scopes can be expanded and contain expected data. + */ +TestSuite.prototype.testExpandScope = function() +{ + this.showPanel("scripts"); + var test = this; + + this._executeCodeWhenScriptsAreParsed("handleClick()", ["debugger_closure.html$"]); + + this._waitForScriptPause( + { + functionsOnStack: ["innerFunction", "handleClick", "(anonymous function)"], + lineNumber: 8, + lineText: " debugger;" + }, + expandAllSectionsExceptGlobal); + + // Expanding Global scope takes for too long so we skeep it. + function expandAllSectionsExceptGlobal() { + test._expandScopeSections(function(sections, i) { + return i < sections.length - 1; + }, + examineScopes /* When all scopes are expanded and populated check them. */); + } + + // Check scope sections contents. + function examineScopes() { + var scopeVariablesSection = test._findNode('//div[@id="scripts-sidebar"]/div[div[@class="title"]/text()="Scope Variables"]'); + var expectedScopes = [ + { + title: "Local", + properties: { + x:"2009", + innerFunctionLocalVar:"2011", + "this": "global", + } + }, + { + title: "Closure", + properties: { + n:"TextParam", + makeClosureLocalVar:"local.TextParam", + } + }, + { + title: "Global", + }, + ]; + var it = test._nodeIterator('./div[@class="body"]/div', scopeVariablesSection); + var scopeIndex = 0; + var scopeDiv; + while (scopeDiv = it.iterateNext()) { + test.assertTrue(scopeIndex < expectedScopes.length, "Too many scopes."); + test._checkScopeSectionDiv(scopeDiv, expectedScopes[scopeIndex]); + ++scopeIndex; + } + test.assertEquals(expectedScopes.length, scopeIndex, "Unexpected number of scopes."); + + test.releaseControl(); + } + + test.takeControl(); +}; + + +/** + * Returns child tree element for a property with given name. + * @param {TreeElement} parent Parent tree element. + * @param {string} childName + * @param {string} objectPath Path to the object. Will be printed in the case + * of failure. + * @return {TreeElement} + */ +TestSuite.prototype._findChildProperty = function(parent, childName, objectPath) +{ + var children = parent.children; + for (var i = 0; i < children.length; i++) { + var treeElement = children[i]; + var property = treeElement.property; + if (property.name === childName) + return treeElement; + } + this.fail('Cannot find property "' + childName + '" in ' + objectPath); +}; + + +/** + * Executes the 'code' with InjectedScriptAccess.getProperties overriden + * so that all callbacks passed to InjectedScriptAccess.getProperties are + * extended with the "hook". + * @param {Function} hook The hook function. + * @param {Function} code A code snippet to be executed. + */ +TestSuite.prototype._hookGetPropertiesCallback = function(hook, code) +{ + var accessor = InjectedScriptAccess.prototype; + var orig = accessor.getProperties; + accessor.getProperties = function(objectProxy, ignoreHasOwnProperty, abbreviate, callback) { + orig.call(this, objectProxy, ignoreHasOwnProperty, abbreviate, + function() { + callback.apply(this, arguments); + hook(); + }); + }; + try { + code(); + } finally { + accessor.getProperties = orig; + } +}; + + +/** + * Tests that all elements in prototype chain of an object have expected + * intrinic proprties(__proto__, constructor, prototype). + */ +TestSuite.prototype.testDebugIntrinsicProperties = function() +{ + this.showPanel("scripts"); + var test = this; + + this._executeCodeWhenScriptsAreParsed("handleClick()", ["debugger_intrinsic_properties.html$"]); + + this._waitForScriptPause( + { + functionsOnStack: ["callDebugger", "handleClick", "(anonymous function)"], + lineNumber: 29, + lineText: " debugger;" + }, + expandLocalScope); + + var localScopeSection = null; + function expandLocalScope() { + test._expandScopeSections(function(sections, i) { + if (i === 0) { + test.assertTrue(sections[i].object.isLocal, "Scope #0 is not Local."); + localScopeSection = sections[i]; + return true; + } + return false; + }, + examineLocalScope); + } + + function examineLocalScope() { + var scopeExpectations = [ + "a", "Object", [ + "constructor", "function Child()", [ + "constructor", "function Function()", null, + "name", "Child", null, + "prototype", "Object", [ + "childProtoField", 21, null + ] + ], + + "__proto__", "Object", [ + "__proto__", "Object", [ + "__proto__", "Object", [ + "__proto__", "null", null, + "constructor", "function Object()", null, + ], + "constructor", "function Parent()", [ + "name", "Parent", null, + "prototype", "Object", [ + "parentProtoField", 11, null, + ] + ], + "parentProtoField", 11, null, + ], + "constructor", "function Child()", null, + "childProtoField", 21, null, + ], + + "parentField", 10, null, + "childField", 20, null, + ] + ]; + + checkProperty(localScopeSection.propertiesTreeOutline, "<Local Scope>", scopeExpectations); + } + + var propQueue = []; + var index = 0; + var expectedFinalIndex = 8; + + function expandAndCheckNextProperty() { + if (index === propQueue.length) { + test.assertEquals(expectedFinalIndex, index, "Unexpected number of expanded objects."); + test.releaseControl(); + return; + } + + // Read next property data from the queue. + var treeElement = propQueue[index].treeElement; + var path = propQueue[index].path; + var expectations = propQueue[index].expectations; + index++; + + // Expand the property. + test._hookGetPropertiesCallback(function() { + checkProperty(treeElement, path, expectations); + }, + function() { + treeElement.expand(); + }); + } + + function checkProperty(treeElement, path, expectations) { + for (var i = 0; i < expectations.length; i += 3) { + var name = expectations[i]; + var description = expectations[i+1]; + var value = expectations[i+2]; + + var propertyPath = path + "." + name; + var propertyTreeElement = test._findChildProperty(treeElement, name, path); + test.assertTrue(propertyTreeElement, 'Property "' + propertyPath + '" not found.'); + test.assertEquals(description, propertyTreeElement.property.value.description, 'Unexpected "' + propertyPath + '" description.'); + if (value) { + // Schedule property content check. + propQueue.push({ + treeElement: propertyTreeElement, + path: propertyPath, + expectations: value, + }); + } + } + // Check next property in the queue. + expandAndCheckNextProperty(); + } + + test.takeControl(); +}; + + +/** + * Tests "Pause" button will pause debugger when a snippet is evaluated. + */ +TestSuite.prototype.testPauseInEval = function() +{ + this.showPanel("scripts"); + + var test = this; + + var pauseButton = document.getElementById("scripts-pause"); + pauseButton.click(); + + devtools.tools.evaluateJavaScript("fib(10)"); + + this.addSniffer(WebInspector, "pausedScript", + function() { + test.releaseControl(); + }); + + test.takeControl(); +}; + + +/** + * Key event with given key identifier. + */ +TestSuite.createKeyEvent = function(keyIdentifier) +{ + var evt = document.createEvent("KeyboardEvent"); + evt.initKeyboardEvent("keydown", true /* can bubble */, true /* can cancel */, null /* view */, keyIdentifier, ""); + return evt; +}; + + +/** + * Tests console eval. + */ +TestSuite.prototype.testConsoleEval = function() +{ + var test = this; + this.evaluateInConsole_("123", + function(resultText) { + test.assertEquals("123", resultText); + test.releaseControl(); + }); + + this.takeControl(); +}; + + +/** + * Tests console log. + */ +TestSuite.prototype.testConsoleLog = function() +{ + WebInspector.console.visible = true; + var messages = WebInspector.console.messages; + var index = 0; + + var test = this; + var assertNext = function(line, message, opt_class, opt_count, opt_substr) { + var elem = messages[index++].toMessageElement(); + var clazz = elem.getAttribute("class"); + var expectation = (opt_count || '') + 'console_test_page.html:' + line + message; + if (opt_substr) + test.assertContains(elem.textContent, expectation); + else + test.assertEquals(expectation, elem.textContent); + if (opt_class) + test.assertContains(clazz, "console-" + opt_class); + }; + + assertNext("5", "log", "log-level"); + assertNext("7", "debug", "log-level"); + assertNext("9", "info", "log-level"); + assertNext("11", "warn", "warning-level"); + assertNext("13", "error", "error-level"); + assertNext("15", "Message format number 1, 2 and 3.5"); + assertNext("17", "Message format for string"); + assertNext("19", "Object Object"); + assertNext("22", "repeated", "log-level", 5); + assertNext("26", "count: 1"); + assertNext("26", "count: 2"); + assertNext("29", "group", "group-title"); + index++; + assertNext("33", "timer:", "log-level", "", true); + assertNext("35", "1 2 3", "log-level"); + assertNext("37", "HTMLDocument", "log-level"); + assertNext("39", "<html>", "log-level", "", true); +}; + + +/** + * Tests eval of global objects. + */ +TestSuite.prototype.testEvalGlobal = function() +{ + WebInspector.console.visible = true; + + var inputs = ["foo", "foobar"]; + var expectations = ["foo", "fooValue", "foobar", "ReferenceError: foobar is not defined"]; + + // Do not change code below - simply add inputs and expectations above. + var initEval = function(input) { + WebInspector.console.prompt.text = input; + WebInspector.console.promptElement.dispatchEvent( TestSuite.createKeyEvent("Enter")); + }; + var test = this; + var messagesCount = 0; + var inputIndex = 0; + this.addSniffer(WebInspector.ConsoleView.prototype, "addMessage", + function(commandResult) { + messagesCount++; + if (messagesCount === expectations.length) { + var messages = WebInspector.console.messages; + for (var i = 0; i < expectations; ++i) { + var elem = messages[i++].toMessageElement(); + test.assertEquals(elem.textContent, expectations[i]); + } + test.releaseControl(); + } else if (messagesCount % 2 === 0) + initEval(inputs[inputIndex++]); + }, true); + + initEval(inputs[inputIndex++]); + this.takeControl(); +}; + + +/** + * Tests that Storage panel can be open and that local DOM storage is added + * to the panel. + */ +TestSuite.prototype.testShowStoragePanel = function() +{ + var test = this; + this.addSniffer(WebInspector.panels.storage, "addDOMStorage", + function(storage) { + var orig = storage.getEntries; + storage.getEntries = function(callback) { + orig.call(this, function(entries) { + callback(entries); + test.releaseControl(); + }); + }; + try { + WebInspector.currentPanel.selectDOMStorage(storage.id); + storage.getEntries = orig; + } catch (e) { + test.fail("Exception in selectDOMStorage: " + e); + } + }); + this.showPanel("storage"); + + // Access localStorage so that it's pushed to the frontend. + this.evaluateInConsole_( + 'setTimeout("localStorage.x = 10" , 0)', + function(resultText) { + test.assertTrue(!isNaN(resultText), "Failed to get timer id: " + resultText); + }); + + // Wait until DOM storage is added to the panel. + this.takeControl(); +}; + + +/** + * Test runner for the test suite. + */ +var uiTests = {}; + + +/** + * Run each test from the test suit on a fresh instance of the suite. + */ +uiTests.runAllTests = function() +{ + // For debugging purposes. + for (var name in TestSuite.prototype) { + if (name.substring(0, 4) === "test" && typeof TestSuite.prototype[name] === "function") + uiTests.runTest(name); + } +}; + + +/** + * Run specified test on a fresh instance of the test suite. + * @param {string} name Name of a test method from TestSuite class. + */ +uiTests.runTest = function(name) +{ + new TestSuite().runTest(name); +}; + + +} diff --git a/WebKit/chromium/src/js/devTools.css b/WebKit/chromium/src/js/devTools.css new file mode 100755 index 0000000..1fa935f --- /dev/null +++ b/WebKit/chromium/src/js/devTools.css @@ -0,0 +1,223 @@ +#scripts-files option.injected { + color: rgb(70, 134, 240); +} + +.data-grid table { + line-height: 120%; +} + +body.attached #toolbar { + height: 34px; + border-top: 1px solid rgb(100, 100, 100); + cursor: default; /* overriden */ + padding-left: 0; +} + + +/* Chrome theme overrides */ +body.platform-windows #toolbar { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(242, 247, 253)), to(rgb(223, 234, 248))); +} + +body.platform-windows.inactive #toolbar { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(248, 248, 248)), to(rgb(237, 237, 237))); +} + + +/* Heap Profiler Styles */ + +.heap-snapshot-status-bar-item .glyph { + -webkit-mask-image: url(Images/focusButtonGlyph.png); +} + +.heap-snapshot-sidebar-tree-item .icon { + content: url(Images/profileIcon.png); +} + +.heap-snapshot-sidebar-tree-item.small .icon { + content: url(Images/profileSmallIcon.png); +} + +.heap-snapshot-view { + display: none; + overflow: hidden; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +.heap-snapshot-view.visible { + display: block; +} + +.heap-snapshot-view .data-grid { + border: none; + max-height: 100%; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 93px; +} + +.heap-snapshot-view .data-grid th.count-column { + text-align: center; +} + +.heap-snapshot-view .data-grid td.count-column { + text-align: right; +} + +.heap-snapshot-view .data-grid th.size-column { + text-align: center; +} + +.heap-snapshot-view .data-grid td.size-column { + text-align: right; +} + +.heap-snapshot-view .data-grid th.countDelta-column { + text-align: center; +} + +.heap-snapshot-view .data-grid td.countDelta-column { + text-align: right; +} + +.heap-snapshot-view .data-grid th.sizeDelta-column { + text-align: center; +} + +.heap-snapshot-view .data-grid td.sizeDelta-column { + text-align: right; +} + +#heap-snapshot-summary-container { + position: absolute; + padding-top: 20px; + bottom: 0; + left: 0; + right: 0; + height: 93px; + margin-left: -1px; + border-left: 1px solid rgb(102, 102, 102); + background-color: rgb(101, 111, 130); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0))); + background-repeat: repeat-x; + background-position: top; + text-align: center; + text-shadow: black 0 1px 1px; + white-space: nowrap; + color: white; + -webkit-background-size: 1px 6px; + -webkit-background-origin: padding; + -webkit-background-clip: padding; +} + +.heap-snapshot-summary { + display: inline-block; + width: 50%; + min-width: 300px; + position: relative; +} + +.heap-snapshot-summary canvas.summary-graph { + width: 225px; +} + +.heap-snapshot-summary-label { + font-size: 12px; + font-weight: bold; + position: absolute; + top: 1px; + width: 50%; + left: 25%; +} + +body.platform-windows .section > .header { + border: 1px solid rgb(92, 116, 157); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(105, 133, 180)), to(rgb(92, 116, 157))); +} + +body.platform-windows .console-group-messages .section > .header { + padding: 0 8px 0 0; + background-image: none; + border: none; + min-height: 0; +} + +body.platform-windows #resources-filter { + background: -webkit-gradient(linear, left top, left bottom, from(rgb(233, 233, 233)), to(rgb(233, 233, 233))); +} + +body.platform-windows .crumbs .crumb { + -webkit-border-image: url(Images/segmentChromium.png) 0 12 0 2; +} + +body.platform-windows .crumbs .crumb.end { + -webkit-border-image: url(Images/segmentEndChromium.png) 0 2 0 2; +} + +body.platform-windows .crumbs .crumb.selected { + -webkit-border-image: url(Images/segmentSelectedChromium.png) 0 12 0 2; + color: white; + text-shadow: rgba(255, 255, 255, 0.5) 0 0px 0; +} + +body.platform-windows .crumbs .crumb.selected:hover { + -webkit-border-image: url(Images/segmentSelectedChromium.png) 0 12 0 2; +} + +body.platform-windows .crumbs .crumb.selected.end, .crumbs .crumb.selected.end:hover { + -webkit-border-image: url(Images/segmentSelectedEndChromium.png) 0 2 0 2; +} + +body.platform-windows .crumbs .crumb:hover { + -webkit-border-image: url(Images/segmentHoverChromium.png) 0 12 0 2; +} + +body.platform-windows .crumbs .crumb.dimmed:hover { + -webkit-border-image: url(Images/segmentHoverChromium.png) 0 12 0 2; +} + +body.platform-windows .crumbs .crumb.end:hover { + -webkit-border-image: url(Images/segmentHoverEndChromium.png) 0 2 0 2; +} + +body.platform-windows body.drawer-visible #main-status-bar { + background-image: url(Images/statusbarResizerVertical.png), url(Images/statusbarBackgroundChromium.png); +} + +body.platform-windows .status-bar { + background-image: url(Images/statusbarBackgroundChromium.png); +} + +body.platform-windows button.status-bar-item { + background-image: url(Images/statusbarButtonsChromium.png); +} + +body.platform-windows select.status-bar-item:active { + -webkit-border-image: url(Images/statusbarMenuButtonSelectedChromium.png) 0 17 0 2; +} + +body.platform-windows #drawer { + background-image: url(Images/statusbarBottomBackgroundChromium.png); +} + +body.platform-windows select.status-bar-item { + -webkit-border-image: url(Images/statusbarMenuButtonChromium.png) 0 17 0 2; +} + +.scope-bar li.selected { + -webkit-box-shadow: 0px 0px 0px rgba(0, 0, 0, 0.0); +} + +.scope-bar li:active { + -webkit-box-shadow: 0px 0px 0px rgba(0, 0, 0, 0.0); +} + +.timeline-category-tree-item input { + vertical-align: middle; +} diff --git a/WebKit/chromium/tests/TransparencyWinTest.cpp b/WebKit/chromium/tests/TransparencyWinTest.cpp new file mode 100644 index 0000000..b83c2a9 --- /dev/null +++ b/WebKit/chromium/tests/TransparencyWinTest.cpp @@ -0,0 +1,693 @@ +/* + * Copyright (C) 2010 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 + * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 "TransparencyWin.h" + +#include "AffineTransform.h" +#include "ImageBuffer.h" + +#include <gtest/gtest.h> +#include <windows.h> + +namespace WebCore { + +static FloatRect RECTToFloatRect(const RECT* rect) +{ + return FloatRect(static_cast<float>(rect->left), + static_cast<float>(rect->top), + static_cast<float>(rect->right - rect->left), + static_cast<float>(rect->bottom - rect->top)); +} + +static void drawNativeRect(GraphicsContext* context, + int x, int y, int w, int h) +{ + skia::PlatformCanvas* canvas = context->platformContext()->canvas(); + HDC dc = canvas->beginPlatformPaint(); + + RECT innerRc; + innerRc.left = x; + innerRc.top = y; + innerRc.right = x + w; + innerRc.bottom = y + h; + FillRect(dc, &innerRc, + reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH))); + + canvas->endPlatformPaint(); +} + +static Color getPixelAt(GraphicsContext* context, int x, int y) +{ + const SkBitmap& bitmap = context->platformContext()->canvas()-> + getTopPlatformDevice().accessBitmap(false); + return Color(*reinterpret_cast<const RGBA32*>(bitmap.getAddr32(x, y))); +} + +// Resets the top layer's alpha channel to 0 for each pixel. This simulates +// Windows messing it up. +static void clearTopLayerAlphaChannel(GraphicsContext* context) +{ + SkBitmap& bitmap = const_cast<SkBitmap&>(context->platformContext()-> + canvas()->getTopPlatformDevice().accessBitmap(false)); + for (int y = 0; y < bitmap.height(); y++) { + uint32_t* row = bitmap.getAddr32(0, y); + for (int x = 0; x < bitmap.width(); x++) + row[x] &= 0x00FFFFFF; + } +} + +// Clears the alpha channel on the specified pixel. +static void clearTopLayerAlphaPixel(GraphicsContext* context, int x, int y) +{ + SkBitmap& bitmap = const_cast<SkBitmap&>(context->platformContext()-> + canvas()->getTopPlatformDevice().accessBitmap(false)); + *bitmap.getAddr32(x, y) &= 0x00FFFFFF; +} + +static std::ostream& operator<<(std::ostream& out, const Color& c) +{ + std::ios_base::fmtflags oldFlags = out.flags(std::ios_base::hex | + std::ios_base::showbase); + out << c.rgb(); + out.flags(oldFlags); + return out; +} + +TEST(TransparencyWin, NoLayer) +{ + OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(17, 16), DeviceRGB)); + + // KeepTransform + { + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::NoLayer, + TransparencyWin::KeepTransform, + IntRect(1, 1, 14, 12)); + + EXPECT_TRUE(src->context() == helper.context()); + EXPECT_TRUE(IntSize(14, 12) == helper.m_layerSize); + EXPECT_TRUE(IntRect(1, 1, 14, 12) == helper.drawRect()); + } + + // Untransform is not allowed for NoLayer. + + // ScaleTransform + src->context()->save(); + src->context()->scale(FloatSize(2.0, 0.5)); + { + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::NoLayer, + TransparencyWin::ScaleTransform, + IntRect(2, 2, 6, 6)); + helper.composite(); + + // The coordinate system should be based in the upper left of our box. + // It should be post-transformed. + EXPECT_TRUE(src->context() == helper.context()); + EXPECT_TRUE(IntSize(12, 3) == helper.m_layerSize); + EXPECT_TRUE(IntRect(4, 1, 12, 3) == helper.drawRect()); + } + src->context()->restore(); +} + +TEST(TransparencyWin, WhiteLayer) +{ + OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16), DeviceRGB)); + + // KeepTransform + { + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::WhiteLayer, + TransparencyWin::KeepTransform, + IntRect(1, 1, 14, 12)); + helper.composite(); + + EXPECT_TRUE(src->context() != helper.context()); + EXPECT_TRUE(IntSize(14, 12) == helper.m_layerSize); + EXPECT_TRUE(IntRect(1, 1, 14, 12) == helper.drawRect()); + } + + // Untransform + { + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::WhiteLayer, + TransparencyWin::Untransform, + IntRect(1, 1, 14, 12)); + helper.composite(); + + EXPECT_TRUE(src->context() != helper.context()); + EXPECT_TRUE(IntSize(14, 12) == helper.m_layerSize); + EXPECT_TRUE(IntRect(0, 0, 14, 12) == helper.drawRect()); + } + + // ScaleTransform + src->context()->save(); + src->context()->scale(FloatSize(2.0, 0.5)); + { + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::WhiteLayer, + TransparencyWin::ScaleTransform, + IntRect(2, 2, 6, 6)); + helper.composite(); + + // The coordinate system should be based in the upper left of our box. + // It should be post-transformed. + EXPECT_TRUE(src->context() != helper.context()); + EXPECT_TRUE(IntSize(12, 3) == helper.m_layerSize); + EXPECT_TRUE(IntRect(0, 0, 12, 3) == helper.drawRect()); + } + src->context()->restore(); +} + +TEST(TransparencyWin, TextComposite) +{ + OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16), DeviceRGB)); + + // KeepTransform is the only valid transform mode for TextComposite. + { + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::TextComposite, + TransparencyWin::KeepTransform, + IntRect(1, 1, 14, 12)); + helper.composite(); + + EXPECT_TRUE(src->context() != helper.context()); + EXPECT_TRUE(IntSize(14, 12) == helper.m_layerSize); + EXPECT_TRUE(IntRect(1, 1, 14, 12) == helper.drawRect()); + } +} + +TEST(TransparencyWin, OpaqueCompositeLayer) +{ + OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16), DeviceRGB)); + + // KeepTransform + { + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::OpaqueCompositeLayer, + TransparencyWin::KeepTransform, + IntRect(1, 1, 14, 12)); + helper.composite(); + + EXPECT_TRUE(src->context() != helper.context()); + EXPECT_TRUE(IntSize(14, 12) == helper.m_layerSize); + EXPECT_TRUE(IntRect(1, 1, 14, 12) == helper.drawRect()); + } + + // KeepTransform with scroll applied. + src->context()->save(); + src->context()->translate(0, -1); + { + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::OpaqueCompositeLayer, + TransparencyWin::KeepTransform, + IntRect(1, 1, 14, 14)); + helper.composite(); + + EXPECT_TRUE(src->context() != helper.context()); + EXPECT_TRUE(IntSize(14, 14) == helper.m_layerSize); + EXPECT_TRUE(IntRect(1, 1, 14, 14) == helper.drawRect()); + } + src->context()->restore(); + + // Untransform + { + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::OpaqueCompositeLayer, + TransparencyWin::Untransform, + IntRect(1, 1, 14, 12)); + helper.composite(); + + EXPECT_TRUE(src->context() != helper.context()); + EXPECT_TRUE(IntSize(14, 12) == helper.m_layerSize); + EXPECT_TRUE(IntRect(0, 0, 14, 12) == helper.drawRect()); + } + + // ScaleTransform + src->context()->save(); + src->context()->scale(FloatSize(2.0, 0.5)); + { + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::OpaqueCompositeLayer, + TransparencyWin::ScaleTransform, + IntRect(2, 2, 6, 6)); + helper.composite(); + + // The coordinate system should be based in the upper left of our box. + // It should be post-transformed. + EXPECT_TRUE(src->context() != helper.context()); + EXPECT_TRUE(IntSize(12, 3) == helper.m_layerSize); + EXPECT_TRUE(IntRect(0, 0, 12, 3) == helper.drawRect()); + } + src->context()->restore(); +} + +TEST(TransparencyWin, WhiteLayerPixelTest) +{ + // Make a total transparent buffer, and draw the white layer inset by 1 px. + OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16), DeviceRGB)); + + { + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::WhiteLayer, + TransparencyWin::KeepTransform, + IntRect(1, 1, 14, 14)); + + // Coordinates should be in the original space, not the layer. + drawNativeRect(helper.context(), 3, 3, 1, 1); + clearTopLayerAlphaChannel(helper.context()); + helper.composite(); + } + + // The final image should be transparent around the edges for 1 px, white + // in the middle, with (3,3) (what we drew above) being opaque black. + EXPECT_EQ(Color(Color::transparent), getPixelAt(src->context(), 0, 0)); + EXPECT_EQ(Color(Color::white), getPixelAt(src->context(), 2, 2)); + EXPECT_EQ(Color(Color::black), getPixelAt(src->context(), 3, 3)); + EXPECT_EQ(Color(Color::white), getPixelAt(src->context(), 4, 4)); +} + +TEST(TransparencyWin, OpaqueCompositeLayerPixel) +{ + Color red(0xFFFF0000), darkRed(0xFFBF0000); + Color green(0xFF00FF00); + + // Make a red bottom layer, followed by a half green next layer @ 50%. + OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16), DeviceRGB)); + + FloatRect fullRect(0, 0, 16, 16); + src->context()->fillRect(fullRect, red, DeviceColorSpace); + src->context()->beginTransparencyLayer(0.5); + FloatRect rightHalf(8, 0, 8, 16); + src->context()->fillRect(rightHalf, green, DeviceColorSpace); + + // Make a transparency layer inset by one pixel, and fill it inset by + // another pixel with 50% black. + { + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::OpaqueCompositeLayer, + TransparencyWin::KeepTransform, + IntRect(1, 1, 14, 14)); + + FloatRect inner(2, 2, 12, 12); + helper.context()->fillRect(inner, Color(0x7f000000), DeviceColorSpace); + // These coordinates are relative to the layer, whish is inset by 1x1 + // pixels from the top left. So we're actually clearing (2, 2) and + // (13,13), which are the extreme corners of the black area (and which + // we check below). + clearTopLayerAlphaPixel(helper.context(), 1, 1); + clearTopLayerAlphaPixel(helper.context(), 12, 12); + helper.composite(); + } + + // Finish the compositing. + src->context()->endTransparencyLayer(); + + // Check that we got the right values, it should be like the rectangle was + // drawn with half opacity even though the alpha channel got messed up. + EXPECT_EQ(red, getPixelAt(src->context(), 0, 0)); + EXPECT_EQ(red, getPixelAt(src->context(), 1, 1)); + EXPECT_EQ(darkRed, getPixelAt(src->context(), 2, 2)); + + // The dark result is: + // (black @ 50% atop green) @ 50% atop red = 0xFF804000 + // which is 0xFFA02000 (Skia computes 0xFFA11F00 due to rounding). + Color darkGreenRed(0xFF803f00); + EXPECT_EQ(darkGreenRed, getPixelAt(src->context(), 13, 13)); + + // 50% green on top of red = FF808000 (rounded to what Skia will produce). + Color greenRed(0xFF807F00); + EXPECT_EQ(greenRed, getPixelAt(src->context(), 14, 14)); + EXPECT_EQ(greenRed, getPixelAt(src->context(), 15, 15)); +} + +// Tests that translations are properly handled when using KeepTransform. +TEST(TransparencyWin, TranslateOpaqueCompositeLayer) +{ + // Fill with white. + OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16), DeviceRGB)); + Color white(0xFFFFFFFF); + FloatRect fullRect(0, 0, 16, 16); + src->context()->fillRect(fullRect, white, DeviceColorSpace); + + // Scroll down by 8 (coordinate system goes up). + src->context()->save(); + src->context()->translate(0, -8); + + Color red(0xFFFF0000); + Color green(0xFF00FF00); + { + // Make the transparency layer after translation will be @ (0, -8) with + // size 16x16. + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::OpaqueCompositeLayer, + TransparencyWin::KeepTransform, + IntRect(0, 0, 16, 16)); + + // Draw a red pixel at (15, 15). This should be the at (15, 7) after + // the transform. + FloatRect bottomRight(15, 15, 1, 1); + helper.context()->fillRect(bottomRight, green, DeviceColorSpace); + helper.composite(); + } + + src->context()->restore(); + + // Check the pixel we wrote. + EXPECT_EQ(green, getPixelAt(src->context(), 15, 7)); +} + +// Same as OpaqueCompositeLayer, but the canvas has a rotation applied. This +// tests that the propert transform is applied to the copied layer. +TEST(TransparencyWin, RotateOpaqueCompositeLayer) +{ + OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16), DeviceRGB)); + + // The background is white. + Color white(0xFFFFFFFF); + FloatRect fullRect(0, 0, 16, 16); + src->context()->fillRect(fullRect, white, DeviceColorSpace); + + // Rotate the image by 90 degrees. This matrix is the same as + // cw90.rotate(90); but avoids rounding errors. Rounding errors can cause + // Skia to think that !rectStaysRect() and it will fall through to path + // drawing mode, which in turn gives us antialiasing. We want no + // antialiasing or other rounding problems since we're testing exact pixel + // values. + src->context()->save(); + AffineTransform cw90(0, 1, -1, 0, 0, 0); + src->context()->concatCTM(cw90); + + // Make a transparency layer consisting of a horizontal line of 50% black. + // Since the rotation is applied, this will actually be a vertical line + // down the middle of the image. + src->context()->beginTransparencyLayer(0.5); + FloatRect blackRect(0, -9, 16, 2); + Color black(0xFF000000); + src->context()->fillRect(blackRect, black, DeviceColorSpace); + + // Now draw 50% red square. + { + // Create a transparency helper inset one pixel in the buffer. The + // coordinates are before transforming into this space, and maps to + // IntRect(1, 1, 14, 14). + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::OpaqueCompositeLayer, + TransparencyWin::Untransform, + IntRect(1, -15, 14, 14)); + + // Fill with red. + helper.context()->fillRect(helper.drawRect(), Color(0x7f7f0000), DeviceColorSpace); + clearTopLayerAlphaChannel(helper.context()); + helper.composite(); + } + + // Finish the compositing. + src->context()->endTransparencyLayer(); + + // Top corner should be the original background. + EXPECT_EQ(white, getPixelAt(src->context(), 0, 0)); + + // Check the stripe down the middle, first at the top... + Color gray(0xFF808080); + EXPECT_EQ(white, getPixelAt(src->context(), 6, 0)); + EXPECT_EQ(gray, getPixelAt(src->context(), 7, 0)); + EXPECT_EQ(gray, getPixelAt(src->context(), 8, 0)); + EXPECT_EQ(white, getPixelAt(src->context(), 9, 0)); + + // ...now at the bottom. + EXPECT_EQ(white, getPixelAt(src->context(), 6, 15)); + EXPECT_EQ(gray, getPixelAt(src->context(), 7, 15)); + EXPECT_EQ(gray, getPixelAt(src->context(), 8, 15)); + EXPECT_EQ(white, getPixelAt(src->context(), 9, 15)); + + // Our red square should be 25% red over the top of those two. + Color redwhite(0xFFdfbfbf); + Color redgray(0xFF9f8080); + EXPECT_EQ(white, getPixelAt(src->context(), 0, 1)); + EXPECT_EQ(redwhite, getPixelAt(src->context(), 1, 1)); + EXPECT_EQ(redwhite, getPixelAt(src->context(), 6, 1)); + EXPECT_EQ(redgray, getPixelAt(src->context(), 7, 1)); + EXPECT_EQ(redgray, getPixelAt(src->context(), 8, 1)); + EXPECT_EQ(redwhite, getPixelAt(src->context(), 9, 1)); + EXPECT_EQ(redwhite, getPixelAt(src->context(), 14, 1)); + EXPECT_EQ(white, getPixelAt(src->context(), 15, 1)); + + // Complete the 50% transparent layer. + src->context()->restore(); +} + +TEST(TransparencyWin, TranslateScaleOpaqueCompositeLayer) +{ + OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16), DeviceRGB)); + + // The background is white on top with red on bottom. + Color white(0xFFFFFFFF); + FloatRect topRect(0, 0, 16, 8); + src->context()->fillRect(topRect, white, DeviceColorSpace); + Color red(0xFFFF0000); + FloatRect bottomRect(0, 8, 16, 8); + src->context()->fillRect(bottomRect, red, DeviceColorSpace); + + src->context()->save(); + + // Translate left by one pixel. + AffineTransform left; + left.translate(-1, 0); + + // Scale by 2x. + AffineTransform scale; + scale.scale(2.0); + src->context()->concatCTM(scale); + + // Then translate up by one pixel (which will actually be 2 due to scaling). + AffineTransform up; + up.translate(0, -1); + src->context()->concatCTM(up); + + // Now draw 50% red square. + { + // Create a transparency helper inset one pixel in the buffer. The + // coordinates are before transforming into this space, and maps to + // IntRect(1, 1, 14, 14). + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::OpaqueCompositeLayer, + TransparencyWin::KeepTransform, + IntRect(1, -15, 14, 14)); + + // Fill with red. + helper.context()->fillRect(helper.drawRect(), Color(0x7f7f0000), DeviceColorSpace); + clearTopLayerAlphaChannel(helper.context()); + helper.composite(); + } +} + +// Tests scale mode with no additional copy. +TEST(TransparencyWin, Scale) +{ + // Create an opaque white buffer. + OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16), DeviceRGB)); + FloatRect fullBuffer(0, 0, 16, 16); + src->context()->fillRect(fullBuffer, Color::white, DeviceColorSpace); + + // Scale by 2x. + src->context()->save(); + AffineTransform scale; + scale.scale(2.0); + src->context()->concatCTM(scale); + + // Start drawing a rectangle from 1->4. This should get scaled to 2->8. + { + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::NoLayer, + TransparencyWin::ScaleTransform, + IntRect(1, 1, 3, 3)); + + // The context should now have the identity transform and the returned + // rect should be scaled. + EXPECT_TRUE(helper.context()->getCTM().isIdentity()); + EXPECT_EQ(2, helper.drawRect().x()); + EXPECT_EQ(2, helper.drawRect().y()); + EXPECT_EQ(8, helper.drawRect().right()); + EXPECT_EQ(8, helper.drawRect().bottom()); + + // Set the pixel at (2, 2) to be transparent. This should be fixed when + // the helper goes out of scope. We don't want to call + // clearTopLayerAlphaChannel because that will actually clear the whole + // canvas (since we have no extra layer!). + SkBitmap& bitmap = const_cast<SkBitmap&>(helper.context()-> + platformContext()->canvas()->getTopPlatformDevice(). + accessBitmap(false)); + *bitmap.getAddr32(2, 2) &= 0x00FFFFFF; + helper.composite(); + } + + src->context()->restore(); + + // Check the pixel we previously made transparent, it should have gotten + // fixed back up to white. + + // The current version doesn't fixup transparency when there is no layer. + // This seems not to be necessary, so we don't bother, but if it becomes + // necessary, this line should be uncommented. + // EXPECT_EQ(Color(Color::white), getPixelAt(src->context(), 2, 2)); +} + +// Tests scale mode with an additional copy for transparency. This will happen +// if we have a scaled textbox, for example. WebKit will create a new +// transparency layer, draw the text field, then draw the text into it, then +// composite this down with an opacity. +TEST(TransparencyWin, ScaleTransparency) +{ + // Create an opaque white buffer. + OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16), DeviceRGB)); + FloatRect fullBuffer(0, 0, 16, 16); + src->context()->fillRect(fullBuffer, Color::white, DeviceColorSpace); + + // Make another layer (which duplicates how WebKit will make this). We fill + // the top half with red, and have the layer be 50% opaque. + src->context()->beginTransparencyLayer(0.5); + FloatRect topHalf(0, 0, 16, 8); + src->context()->fillRect(topHalf, Color(0xFFFF0000), DeviceColorSpace); + + // Scale by 2x. + src->context()->save(); + AffineTransform scale; + scale.scale(2.0); + src->context()->concatCTM(scale); + + // Make a layer inset two pixels (because of scaling, this is 2->14). And + // will it with 50% black. + { + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::OpaqueCompositeLayer, + TransparencyWin::ScaleTransform, + IntRect(1, 1, 6, 6)); + + helper.context()->fillRect(helper.drawRect(), Color(0x7f000000), DeviceColorSpace); + clearTopLayerAlphaChannel(helper.context()); + helper.composite(); + } + + // Finish the layer. + src->context()->restore(); + src->context()->endTransparencyLayer(); + + Color redBackground(0xFFFF8080); // 50% red composited on white. + EXPECT_EQ(redBackground, getPixelAt(src->context(), 0, 0)); + EXPECT_EQ(redBackground, getPixelAt(src->context(), 1, 1)); + + // Top half (minus two pixel border) should be 50% gray atop opaque + // red = 0xFF804141. Then that's composited with 50% transparency on solid + // white = 0xFFC0A1A1. + Color darkRed(0xFFBF8080); + EXPECT_EQ(darkRed, getPixelAt(src->context(), 2, 2)); + EXPECT_EQ(darkRed, getPixelAt(src->context(), 7, 7)); + + // Bottom half (minus a two pixel border) should be a layer with 5% gray + // with another 50% opacity composited atop white. + Color darkWhite(0xFFBFBFBF); + EXPECT_EQ(darkWhite, getPixelAt(src->context(), 8, 8)); + EXPECT_EQ(darkWhite, getPixelAt(src->context(), 13, 13)); + + Color white(0xFFFFFFFF); // Background in the lower-right. + EXPECT_EQ(white, getPixelAt(src->context(), 14, 14)); + EXPECT_EQ(white, getPixelAt(src->context(), 15, 15)); +} + +TEST(TransparencyWin, Text) +{ + OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16), DeviceRGB)); + + // Our text should end up 50% transparent blue-green. + Color fullResult(0x80008080); + + { + TransparencyWin helper; + helper.init(src->context(), + TransparencyWin::TextComposite, + TransparencyWin::KeepTransform, + IntRect(0, 0, 16, 16)); + helper.setTextCompositeColor(fullResult); + + // Write several different squares to simulate ClearType. These should + // all reduce to 2/3 coverage. + FloatRect pixel(0, 0, 1, 1); + helper.context()->fillRect(pixel, 0xFFFF0000, DeviceColorSpace); + pixel.move(1.0f, 0.0f); + helper.context()->fillRect(pixel, 0xFF00FF00, DeviceColorSpace); + pixel.move(1.0f, 0.0f); + helper.context()->fillRect(pixel, 0xFF0000FF, DeviceColorSpace); + pixel.move(1.0f, 0.0f); + helper.context()->fillRect(pixel, 0xFF008080, DeviceColorSpace); + pixel.move(1.0f, 0.0f); + helper.context()->fillRect(pixel, 0xFF800080, DeviceColorSpace); + pixel.move(1.0f, 0.0f); + helper.context()->fillRect(pixel, 0xFF808000, DeviceColorSpace); + + // Try one with 100% coverage (opaque black). + pixel.move(1.0f, 0.0f); + helper.context()->fillRect(pixel, 0xFF000000, DeviceColorSpace); + + // Now mess with the alpha channel. + clearTopLayerAlphaChannel(helper.context()); + helper.composite(); + } + + Color oneThirdResult(0x55005555); // = fullResult * 2 / 3 + EXPECT_EQ(oneThirdResult, getPixelAt(src->context(), 0, 0)); + EXPECT_EQ(oneThirdResult, getPixelAt(src->context(), 1, 0)); + EXPECT_EQ(oneThirdResult, getPixelAt(src->context(), 2, 0)); + EXPECT_EQ(oneThirdResult, getPixelAt(src->context(), 3, 0)); + EXPECT_EQ(oneThirdResult, getPixelAt(src->context(), 4, 0)); + EXPECT_EQ(oneThirdResult, getPixelAt(src->context(), 5, 0)); + EXPECT_EQ(fullResult, getPixelAt(src->context(), 6, 0)); + EXPECT_EQ(Color::transparent, getPixelAt(src->context(), 7, 0)); +} + +} // namespace WebCore diff --git a/WebKit/chromium/tests/UniscribeHelperTest.cpp b/WebKit/chromium/tests/UniscribeHelperTest.cpp new file mode 100644 index 0000000..8aaed11 --- /dev/null +++ b/WebKit/chromium/tests/UniscribeHelperTest.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2010 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 + * 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. + * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT + * OWNER 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 <gtest/gtest.h> + +#include "PlatformString.h" +#include "UniscribeHelper.h" + +using namespace WebCore; + +namespace { + +class UniscribeTest : public testing::Test { +public: + UniscribeTest() + { + } + + // Returns an HFONT with the given name. The caller does not have to free + // this, it will be automatically freed at the end of the test. Returns 0 + // on failure. On success, the + HFONT MakeFont(const wchar_t* fontName, SCRIPT_CACHE** cache) + { + LOGFONT lf; + memset(&lf, 0, sizeof(LOGFONT)); + lf.lfHeight = 20; + wcscpy_s(lf.lfFaceName, fontName); + + HFONT hfont = CreateFontIndirect(&lf); + if (!hfont) + return 0; + + *cache = new SCRIPT_CACHE; + **cache = 0; + createdFonts.append(std::make_pair(hfont, *cache)); + return hfont; + } + +protected: + // Default font properties structure for tests to use. + SCRIPT_FONTPROPERTIES properties; + +private: + virtual void SetUp() + { + memset(&properties, 0, sizeof(SCRIPT_FONTPROPERTIES)); + properties.cBytes = sizeof(SCRIPT_FONTPROPERTIES); + properties.wgBlank = ' '; + properties.wgDefault = '?'; // Used when the char is not in the font. + properties.wgInvalid = '#'; // Used for invalid characters. + } + + virtual void TearDown() + { + // Free any allocated fonts. + for (size_t i = 0; i < createdFonts.size(); i++) { + DeleteObject(createdFonts[i].first); + ScriptFreeCache(createdFonts[i].second); + delete createdFonts[i].second; + } + createdFonts.clear(); + } + + // Tracks allocated fonts so we can delete them at the end of the test. + // The script cache pointer is heap allocated and must be freed. + Vector< std::pair<HFONT, SCRIPT_CACHE*> > createdFonts; +}; + +} // namespace + +// This test tests giving Uniscribe a very large buffer, which will cause a +// failure. +TEST_F(UniscribeTest, TooBig) +{ + // Make a large string with an e with a zillion combining accents. + String input(L"e"); + for (int i = 0; i < 100000; i++) + input.append(static_cast<UChar>(0x301)); // Combining acute accent. + + SCRIPT_CACHE* scriptCache; + HFONT hfont = MakeFont(L"Times New Roman", &scriptCache); + ASSERT_TRUE(hfont); + + // Test a long string without the normal length protection we have. This + // will cause shaping to fail. + { + UniscribeHelper uniscribe( + input.characters(), static_cast<int>(input.length()), + false, hfont, scriptCache, &properties); + uniscribe.initWithOptionalLengthProtection(false); + + // There should be one shaping entry, with nothing in it. + ASSERT_EQ(1, uniscribe.m_shapes.size()); + EXPECT_EQ(0, uniscribe.m_shapes[0].m_glyphs.size()); + EXPECT_EQ(0, uniscribe.m_shapes[0].m_logs.size()); + EXPECT_EQ(0, uniscribe.m_shapes[0].m_visualAttributes.size()); + EXPECT_EQ(0, uniscribe.m_shapes[0].m_advance.size()); + EXPECT_EQ(0, uniscribe.m_shapes[0].m_offsets.size()); + EXPECT_EQ(0, uniscribe.m_shapes[0].m_justify.size()); + EXPECT_EQ(0, uniscribe.m_shapes[0].m_abc.abcA); + EXPECT_EQ(0, uniscribe.m_shapes[0].m_abc.abcB); + EXPECT_EQ(0, uniscribe.m_shapes[0].m_abc.abcC); + + // The sizes of the other stuff should match the shaping entry. + EXPECT_EQ(1, uniscribe.m_runs.size()); + EXPECT_EQ(1, uniscribe.m_screenOrder.size()); + + // Check that the various querying functions handle the empty case + // properly. + EXPECT_EQ(0, uniscribe.width()); + EXPECT_EQ(0, uniscribe.firstGlyphForCharacter(0)); + EXPECT_EQ(0, uniscribe.firstGlyphForCharacter(1000)); + EXPECT_EQ(0, uniscribe.xToCharacter(0)); + EXPECT_EQ(0, uniscribe.xToCharacter(1000)); + } + + // Now test the very large string and make sure it is handled properly by + // the length protection. + { + UniscribeHelper uniscribe( + input.characters(), static_cast<int>(input.length()), + false, hfont, scriptCache, &properties); + uniscribe.initWithOptionalLengthProtection(true); + + // There should be 0 runs and shapes. + EXPECT_EQ(0, uniscribe.m_runs.size()); + EXPECT_EQ(0, uniscribe.m_shapes.size()); + EXPECT_EQ(0, uniscribe.m_screenOrder.size()); + + EXPECT_EQ(0, uniscribe.width()); + EXPECT_EQ(0, uniscribe.firstGlyphForCharacter(0)); + EXPECT_EQ(0, uniscribe.firstGlyphForCharacter(1000)); + EXPECT_EQ(0, uniscribe.xToCharacter(0)); + EXPECT_EQ(0, uniscribe.xToCharacter(1000)); + } +} diff --git a/WebKit/gtk/ChangeLog b/WebKit/gtk/ChangeLog index 92de7e4..7a44884 100644 --- a/WebKit/gtk/ChangeLog +++ b/WebKit/gtk/ChangeLog @@ -1,3 +1,97 @@ +2010-02-09 Gustavo Noronha Silva <gns@gnome.org> + + Reviewed by Xan Lopez. + + [GTK] Hits assertion on history back, with page cache enabled, in specific conditions + https://bugs.webkit.org/show_bug.cgi?id=34773 + + Make sure cached frames have their scrollbars disconnected from + the WebView's adjustments. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::savePlatformDataToCachedFrame): + +2010-02-09 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Reviewed by Xan Lopez. + + [GTK] Set GtkAdjustments on our FrameView when loading a page in the PageCache + https://bugs.webkit.org/show_bug.cgi?id=34754 + + Test that lower, and upper bounds are kept when goibg back with + page cache enabled, and disabled. Page cache behaviour is still a + bit broken (see FIXME). + + * tests/testwebview.c: + (server_callback): + (map_event_cb): + (do_test_webkit_web_view_adjustments): + (test_webkit_web_view_adjustments): + (main): + +2010-02-09 Xan Lopez <xlopez@igalia.com> + + Reviewed by Gustavo Noronha. + + [GTK] Set GtkAdjustments on our FrameView when loading a page in the PageCache + https://bugs.webkit.org/show_bug.cgi?id=34754 + + Set the Gtk Adjustments of the FrameViews when they are restored + from the PageCache too. Right we only do it for the newly created + FrameViews in transitionToCommittedForNewPage, but we it also + needs to be done in the equilavent transition method for cached + pages. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::postCommitFrameViewSetup): + (WebKit::FrameLoaderClient::transitionToCommittedFromCachedFrame): + (WebKit::FrameLoaderClient::transitionToCommittedForNewPage): + +2010-02-08 Xan Lopez <xlopez@igalia.com> + + Reviewed by Gustavo Noronha. + + [GTK] Implement FrameLoaderClient::hasWebView + https://bugs.webkit.org/show_bug.cgi?id=34682 + + Used for sanity-check ASSERTS in the FrameLoader code. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::hasWebView): + +2010-02-08 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Reviewed by Xan Lopez. + + News about 1.1.21. + + * NEWS: + +2010-02-05 Shinichiro Hamaji <hamaji@chromium.org> + + Reviewed by Gustavo Noronha Silva. + + [Gtk] Implement layoutTestController.pageNumberForElementById + https://bugs.webkit.org/show_bug.cgi?id=34572 + + * webkit/webkitprivate.h: + * webkit/webkitwebframe.cpp: + (webkit_web_frame_page_number_for_element_by_id): + +2010-02-04 Christian Dywan <christian@twotoasts.de> + + Reviewed by Gustavo Noronha Silva. + + [GTK] Add and cleanup return values of signals in view and frame + https://bugs.webkit.org/show_bug.cgi?id=33484 + + Add missing and cleanup return values of web frame and web view signals. + + * webkit/webkitwebframe.cpp: + (webkit_web_frame_class_init): + * webkit/webkitwebview.cpp: + (DNDContentsRequest::webkit_web_view_class_init): + 2010-02-02 Gustavo Noronha Silva <gns@gnome.org> Reviewed by Xan Lopez. diff --git a/WebKit/gtk/NEWS b/WebKit/gtk/NEWS index 807fca4..4e5bc2c 100644 --- a/WebKit/gtk/NEWS +++ b/WebKit/gtk/NEWS @@ -1,4 +1,18 @@ ================= +WebKitGTK+ 1.1.21 +================= + +What's new in WebKitGTK+ 1.1.21? + + - New custom-made GStreamer source element that uses the WebCore + network layer to download media data; this makes sure any headers + and cookies will automatically get added when making requests. + - WebKit will now let libsoup know who the first party for a given + message is, making it possible to implement accept/deny policies in + Soup. + - The usual stream of fixes, and improvements + +================= WebKitGTK+ 1.1.20 ================= diff --git a/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp b/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp index 8f1bec2..1ccc8a1 100644 --- a/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp +++ b/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp @@ -3,7 +3,7 @@ * Copyright (C) 2007, 2008, 2009 Holger Hans Peter Freyther * Copyright (C) 2007 Christian Dywan <christian@twotoasts.de> * Copyright (C) 2008, 2009 Collabora Ltd. All rights reserved. - * Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org> + * Copyright (C) 2009, 2010 Gustavo Noronha Silva <gns@gnome.org> * Copyright (C) Research In Motion Limited 2009. All rights reserved. * * This library is free software; you can redistribute it and/or @@ -25,6 +25,7 @@ #include "FrameLoaderClientGtk.h" #include "ArchiveResource.h" +#include "CachedFrame.h" #include "Color.h" #include "DocumentLoader.h" #include "DocumentLoaderGtk.h" @@ -563,8 +564,7 @@ void FrameLoaderClient::setMainFrameDocumentReady(bool) bool FrameLoaderClient::hasWebView() const { - notImplemented(); - return true; + return getViewFromFrame(m_frame); } void FrameLoaderClient::dispatchDidFinishLoad() @@ -646,9 +646,7 @@ void FrameLoaderClient::setCopiesOnScroll() void FrameLoaderClient::detachedFromParent2() { - FrameView *view = core(m_frame)->view(); - if (view) - view->setGtkAdjustments(0, 0); + notImplemented(); } void FrameLoaderClient::detachedFromParent3() @@ -1116,12 +1114,40 @@ void FrameLoaderClient::updateGlobalHistoryRedirectLinks() notImplemented(); } -void FrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame*) +void FrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame) +{ + // We need to do this here in order to disconnect the scrollbars + // that are being used by the frame that is being cached from the + // adjustments, otherwise they will react to changes in the + // adjustments, and bad things will happen. + if (cachedFrame->view()) + cachedFrame->view()->setGtkAdjustments(0, 0); +} + +static void postCommitFrameViewSetup(WebKitWebFrame *frame, FrameView *view, bool resetValues) { + WebKitWebView* containingWindow = getViewFromFrame(frame); + WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(containingWindow); + view->setGtkAdjustments(priv->horizontalAdjustment, priv->verticalAdjustment, resetValues); + + if (priv->currentMenu) { + GtkMenu* menu = priv->currentMenu; + priv->currentMenu = 0; + + gtk_menu_popdown(menu); + g_object_unref(menu); + } } -void FrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame*) +void FrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame* cachedFrame) { + ASSERT(cachedFrame->view()); + + Frame* frame = core(m_frame); + if (frame != frame->page()->mainFrame()) + return; + + postCommitFrameViewSetup(m_frame, cachedFrame->view(), false); } void FrameLoaderClient::transitionToCommittedForNewPage() @@ -1140,16 +1166,7 @@ void FrameLoaderClient::transitionToCommittedForNewPage() if (frame != frame->page()->mainFrame()) return; - WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(containingWindow); - frame->view()->setGtkAdjustments(priv->horizontalAdjustment, priv->verticalAdjustment); - - if (priv->currentMenu) { - GtkMenu* menu = priv->currentMenu; - priv->currentMenu = NULL; - - gtk_menu_popdown(menu); - g_object_unref(menu); - } + postCommitFrameViewSetup(m_frame, frame->view(), true); } } diff --git a/WebKit/gtk/tests/testwebview.c b/WebKit/gtk/tests/testwebview.c index 7482747..c028a36 100644 --- a/WebKit/gtk/tests/testwebview.c +++ b/WebKit/gtk/tests/testwebview.c @@ -55,6 +55,12 @@ server_callback(SoupServer* server, SoupMessage* msg, g_assert(!error); soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, length); + } else if (g_str_equal(path, "/bigdiv.html")) { + char* contents = g_strdup("<html><body><div style=\"background-color: green; height: 1200px;\"></div></body></html>"); + soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, strlen(contents)); + } else if (g_str_equal(path, "/iframe.html")) { + char* contents = g_strdup("<html><body><div style=\"background-color: green; height: 50px;\"></div><iframe src=\"bigdiv.html\"></iframe></body></html>"); + soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, strlen(contents)); } else { char* contents = g_strdup("<html><body>test</body></html>"); soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, strlen(contents)); @@ -121,6 +127,103 @@ static void test_webkit_web_view_icon_uri() g_object_unref(view); } +static gboolean map_event_cb(GtkWidget *widget, GdkEvent* event, gpointer data) +{ + GMainLoop* loop = (GMainLoop*)data; + g_main_loop_quit(loop); + + return FALSE; +} + +static void do_test_webkit_web_view_adjustments(gboolean with_page_cache) +{ + char* effective_uri = g_strconcat(base_uri, "bigdiv.html", NULL); + char* second_uri = g_strconcat(base_uri, "iframe.html", NULL); + GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + GtkWidget* scrolled_window = gtk_scrolled_window_new(NULL, NULL); + WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new()); + GtkAdjustment* adjustment; + double lower; + double upper; + + if (with_page_cache) { + WebKitWebSettings* settings = webkit_web_view_get_settings(view); + g_object_set(settings, "enable-page-cache", TRUE, NULL); + } + + gtk_window_set_default_size(GTK_WINDOW(window), 400, 200); + + gtk_container_add(GTK_CONTAINER(window), scrolled_window); + gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(view)); + + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + loop = g_main_loop_new(NULL, TRUE); + + g_object_connect(G_OBJECT(view), + "signal::notify::progress", idle_quit_loop_cb, NULL, + NULL); + + /* Wait for window to show up */ + gtk_widget_show_all(window); + g_signal_connect(window, "map-event", + G_CALLBACK(map_event_cb), loop); + g_main_loop_run(loop); + + /* Load a page with a big div that will cause scrollbars to appear */ + webkit_web_view_load_uri(view, effective_uri); + g_main_loop_run(loop); + + adjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrolled_window)); + g_assert_cmpfloat(gtk_adjustment_get_value(adjustment), ==, 0.0); + + lower = gtk_adjustment_get_lower(adjustment); + upper = gtk_adjustment_get_upper(adjustment); + + /* Scroll the view using JavaScript */ + webkit_web_view_execute_script(view, "window.scrollBy(0, 100)"); + + /* Make sure the ScrolledWindow noticed the scroll */ + g_assert_cmpfloat(gtk_adjustment_get_value(adjustment), ==, 100.0); + + /* Load a second URI */ + webkit_web_view_load_uri(view, second_uri); + g_main_loop_run(loop); + + /* Make sure the scrollbar has been reset */ + g_assert_cmpfloat(gtk_adjustment_get_value(adjustment), ==, 0.0); + + /* Go back */ + webkit_web_view_go_back(view); + + /* When using page cache, go_back will return syncronously */ + if (!with_page_cache) + g_main_loop_run(loop); + + /* Make sure GTK+ has time to process the changes in size, for the adjusments */ + while (gtk_events_pending()) + gtk_main_iteration(); + + /* Make sure upper and lower bounds have been restored correctly */ + g_assert_cmpfloat(lower, ==, gtk_adjustment_get_lower(adjustment)); + g_assert_cmpfloat(upper, ==, gtk_adjustment_get_upper(adjustment)); + + g_assert_cmpfloat(gtk_adjustment_get_value(adjustment), ==, 100.0); + + g_free(effective_uri); + g_free(second_uri); + + gtk_widget_destroy(window); +} + +static void test_webkit_web_view_adjustments() +{ + /* Test this with page cache disabled, and enabled. */ + do_test_webkit_web_view_adjustments(FALSE); + do_test_webkit_web_view_adjustments(TRUE); +} + int main(int argc, char** argv) { SoupServer* server; @@ -153,6 +256,7 @@ int main(int argc, char** argv) g_test_bug_base("https://bugs.webkit.org/"); g_test_add_func("/webkit/webview/icon-uri", test_webkit_web_view_icon_uri); + g_test_add_func("/webkit/webview/adjustments", test_webkit_web_view_adjustments); return g_test_run (); } diff --git a/WebKit/gtk/webkit/webkitprivate.h b/WebKit/gtk/webkit/webkitprivate.h index e9d61a6..44b4d0c 100644 --- a/WebKit/gtk/webkit/webkitprivate.h +++ b/WebKit/gtk/webkit/webkitprivate.h @@ -298,6 +298,9 @@ extern "C" { WEBKIT_API gchar* webkit_web_frame_counter_value_for_element_by_id (WebKitWebFrame* frame, const gchar* id); + WEBKIT_API int + webkit_web_frame_page_number_for_element_by_id(WebKitWebFrame* frame, const gchar* id, float pageWidth, float pageHeight); + WEBKIT_API guint webkit_web_frame_get_pending_unload_event_count(WebKitWebFrame* frame); diff --git a/WebKit/gtk/webkit/webkitwebframe.cpp b/WebKit/gtk/webkit/webkitwebframe.cpp index 35d9524..fbd246d 100644 --- a/WebKit/gtk/webkit/webkitwebframe.cpp +++ b/WebKit/gtk/webkit/webkitwebframe.cpp @@ -269,6 +269,9 @@ static void webkit_web_frame_class_init(WebKitWebFrameClass* frameClass) * WebKitWebFrame:horizontal-scrollbar-policy and * WebKitWebFrame:vertical-scrollbar-policy properties. * + * Return value: %TRUE to stop other handlers from being invoked for the + * event. %FALSE to propagate the event further. + * * Since: 1.1.14 */ webkit_web_frame_signals[SCROLLBARS_POLICY_CHANGED] = g_signal_new("scrollbars-policy-changed", @@ -841,6 +844,29 @@ gchar* webkit_web_frame_counter_value_for_element_by_id(WebKitWebFrame* frame, c } /** + * webkit_web_frame_page_number_for_element_by_id + * @frame: a #WebKitWebFrame + * @id: an element ID string + * @pageWidth: width of a page + * @pageHeight: height of a page + * + * Return value: The number of page where the specified element will be put + */ +int webkit_web_frame_page_number_for_element_by_id(WebKitWebFrame* frame, const gchar* id, float pageWidth, float pageHeight) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_FRAME(frame), NULL); + + Frame* coreFrame = core(frame); + if (!coreFrame) + return -1; + + Element* coreElement = coreFrame->document()->getElementById(AtomicString(id)); + if (!coreElement) + return -1; + return PrintContext::pageNumberForElement(coreElement, FloatSize(pageWidth, pageHeight)); +} + +/** * webkit_web_frame_get_pending_unload_event_count: * @frame: a #WebKitWebFrame * diff --git a/WebKit/gtk/webkit/webkitwebview.cpp b/WebKit/gtk/webkit/webkitwebview.cpp index ad13895..8c5b802 100644 --- a/WebKit/gtk/webkit/webkitwebview.cpp +++ b/WebKit/gtk/webkit/webkitwebview.cpp @@ -1325,7 +1325,6 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * WebKitWebView::create-web-view: * @web_view: the object on which the signal is emitted * @frame: the #WebKitWebFrame - * @return: a newly allocated #WebKitWebView or %NULL * * Emitted when the creation of a new window is requested. * If this signal is handled the signal handler should return the @@ -1338,6 +1337,8 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * the new #WebKitWebView. The widget to which the widget is added will * handle that. * + * Return value: a newly allocated #WebKitWebView, or %NULL + * * Since: 1.0.3 */ webkit_web_view_signals[CREATE_WEB_VIEW] = g_signal_new("create-web-view", @@ -1353,8 +1354,6 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) /** * WebKitWebView::web-view-ready: * @web_view: the object on which the signal is emitted - * @return: %TRUE to stop other handlers from being invoked for - * the event, %FALSE to propagate the event further * * Emitted after #WebKitWebView::create-web-view when the new #WebKitWebView * should be displayed to the user. When this signal is emitted @@ -1367,6 +1366,9 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * time of the window, so you may want to connect to the ::notify * signal of the #WebKitWebWindowFeatures object to handle those. * + * Return value: %TRUE to stop handlers from being invoked for the event or + * %FALSE to propagate the event furter + * * Since: 1.0.3 */ webkit_web_view_signals[WEB_VIEW_READY] = g_signal_new("web-view-ready", @@ -1381,14 +1383,15 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) /** * WebKitWebView::close-web-view: * @web_view: the object on which the signal is emitted - * @return: %TRUE to stop handlers from being invoked for the event or - * %FALSE to propagate the event furter * * Emitted when closing a #WebKitWebView is requested. This occurs when a * call is made from JavaScript's window.close function. The default * signal handler does not do anything. It is the owner's responsibility * to hide or delete the web view, if necessary. * + * Return value: %TRUE to stop handlers from being invoked for the event or + * %FALSE to propagate the event furter + * * Since: 1.1.11 */ webkit_web_view_signals[CLOSE_WEB_VIEW] = g_signal_new("close-web-view", @@ -1405,10 +1408,11 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * @web_view: the object on which the signal is emitted * @frame: the #WebKitWebFrame that required the navigation * @request: a #WebKitNetworkRequest - * @return: a WebKitNavigationResponse * * Emitted when @frame requests a navigation to another page. * + * Return value: a #WebKitNavigationResponse + * * Deprecated: Use WebKitWebView::navigation-policy-decision-requested * instead */ @@ -1430,8 +1434,6 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * @request: a #WebKitNetworkRequest * @navigation_action: a #WebKitWebNavigation * @policy_decision: a #WebKitWebPolicyDecision - * @return: TRUE if a decision was made, 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 @@ -1453,6 +1455,9 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * webkit_web_policy_decision_download() on the @policy_decision * object. * + * Return value: %TRUE if a decision was made, %FALSE to have the + * default behavior apply + * * Since: 1.1.4 */ webkit_web_view_signals[NEW_WINDOW_POLICY_DECISION_REQUESTED] = @@ -1476,8 +1481,6 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * @request: a #WebKitNetworkRequest * @navigation_action: a #WebKitWebNavigation * @policy_decision: a #WebKitWebPolicyDecision - * @return: TRUE if a decision was made, FALSE to have the - * default behavior apply * * Emitted when @frame requests a navigation to another page. * If this signal is not handled, the default behavior is to allow the @@ -1490,6 +1493,9 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * webkit_web_policy_decision_download() on the @policy_decision * object. * + * Return value: %TRUE if a decision was made, %FALSE to have the + * default behavior apply + * * Since: 1.0.3 */ webkit_web_view_signals[NAVIGATION_POLICY_DECISION_REQUESTED] = g_signal_new("navigation-policy-decision-requested", @@ -1512,8 +1518,6 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * @request: a WebKitNetworkRequest * @mimetype: the MIME type attempted to load * @policy_decision: a #WebKitWebPolicyDecision - * @return: TRUE if a decision was made, FALSE to have the - * default behavior apply * * Decide whether or not to display the given MIME type. If this * signal is not handled, the default behavior is to show the @@ -1531,6 +1535,9 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * webkit_web_policy_decision_download() on the @policy_decision * object. * + * Return value: %TRUE if a decision was made, %FALSE to have the + * default behavior apply + * * Since: 1.0.3 */ webkit_web_view_signals[MIME_TYPE_POLICY_DECISION_REQUESTED] = g_signal_new("mime-type-policy-decision-requested", @@ -1578,7 +1585,6 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * @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. If you handle the download @@ -1601,6 +1607,9 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * is to download anything that WebKit can't handle, which you can * figure out by using webkit_web_view_can_show_mime_type()). * + * Return value: TRUE if the download should be performed, %FALSE to + * cancel it + * * Since: 1.1.2 */ webkit_web_view_signals[DOWNLOAD_REQUESTED] = g_signal_new("download-requested", @@ -1681,6 +1690,9 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * handle the signal if you want to provide your own error page. * * Since: 1.1.6 + * + * Return value: %TRUE to stop other handlers from being invoked for the + * event. %FALSE to propagate the event further. */ webkit_web_view_signals[LOAD_ERROR] = g_signal_new("load-error", G_TYPE_FROM_CLASS(webViewClass), @@ -1774,8 +1786,6 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * WebKitWebView::print-requested * @web_view: the object in which the signal is emitted * @web_frame: the frame that is requesting to be printed - * @return: %TRUE if the print request has been handled, %FALSE if - * the default handler should run * * Emitted when printing is requested by the frame, usually * because of a javascript call. When handling this signal you @@ -1787,6 +1797,9 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * ignore a print request you must connect to this signal, and * return %TRUE. * + * Return value: %TRUE if the print request has been handled, %FALSE if + * the default handler should run + * * Since: 1.1.5 */ webkit_web_view_signals[PRINT_REQUESTED] = g_signal_new("print-requested", @@ -1843,9 +1856,11 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * @message: the message text * @line: the line where the error occured * @source_id: the source id - * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further. * * A JavaScript console message was created. + * + * Return value: %TRUE to stop other handlers from being invoked for the + * event. %FALSE to propagate the event further. */ webkit_web_view_signals[CONSOLE_MESSAGE] = g_signal_new("console-message", G_TYPE_FROM_CLASS(webViewClass), @@ -1862,9 +1877,11 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * @web_view: the object on which the signal is emitted * @frame: the relevant frame * @message: the message text - * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further. * * A JavaScript alert dialog was created. + * + * Return value: %TRUE to stop other handlers from being invoked for the + * event. %FALSE to propagate the event further. */ webkit_web_view_signals[SCRIPT_ALERT] = g_signal_new("script-alert", G_TYPE_FROM_CLASS(webViewClass), @@ -1882,9 +1899,11 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * @frame: the relevant frame * @message: the message text * @confirmed: whether the dialog has been confirmed - * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further. * * A JavaScript confirm dialog was created, providing Yes and No buttons. + * + * Return value: %TRUE to stop other handlers from being invoked for the + * event. %FALSE to propagate the event further. */ webkit_web_view_signals[SCRIPT_CONFIRM] = g_signal_new("script-confirm", G_TYPE_FROM_CLASS(webViewClass), @@ -1903,9 +1922,11 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * @message: the message text * @default: the default value * @text: To be filled with the return value or NULL if the dialog was cancelled. - * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further. * * A JavaScript prompt dialog was created, providing an entry to input text. + * + * Return value: %TRUE to stop other handlers from being invoked for the + * event. %FALSE to propagate the event further. */ webkit_web_view_signals[SCRIPT_PROMPT] = g_signal_new("script-prompt", G_TYPE_FROM_CLASS(webViewClass), @@ -2032,6 +2053,8 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * * The #WebKitWebView::move-cursor will be emitted to apply the * cursor movement described by its parameters to the @view. + * + * Return value: %TRUE or %FALSE * * Since: 1.1.4 */ @@ -2059,6 +2082,8 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) * to set the property value of "webkit-widget-is-selected". This can * be used to draw a visual indicator of the selection. * + * Return value: a new #GtkWidget, or %NULL + * * Since: 1.1.8 */ webkit_web_view_signals[PLUGIN_WIDGET] = g_signal_new("create-plugin-widget", diff --git a/WebKit/mac/ChangeLog b/WebKit/mac/ChangeLog index 8bbd4de..b545a40 100644 --- a/WebKit/mac/ChangeLog +++ b/WebKit/mac/ChangeLog @@ -1,3 +1,189 @@ +2010-02-12 Dan Bernstein <mitz@apple.com> + + Reviewed by Darin Adler. + + <rdar://problem/7615234> REGRESSION (r48586): Loading an HTML page causes + PDFKit to be loaded + + * WebView/WebPDFDocumentExtras.h: Removed the category declaration and + addWebPDFDocumentExtras(). Declare allScriptsInPDFDocument(). + * WebView/WebPDFDocumentExtras.mm: + (allScriptsInPDFDocument): Changed the -_web_allScripts method into this function. + * WebView/WebPDFRepresentation.mm: Removed +initialize. + (-[WebPDFRepresentation finishedLoadingWithDataSource:]): Use + allScriptsInPDFDocument() instead of -_web_allScripts. + +2010-02-10 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Exported some new JavaScript heap introspection. + + * Misc/WebCoreStatistics.h: + * Misc/WebCoreStatistics.mm: + (+[WebCoreStatistics javaScriptObjectTypeCounts]): Just like + javaScriptProtectedObjectTypeCounts, except this function enumerates all + live objects, not just protected objects. + +2010-02-08 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Cameron Zwarich. + + Restore ENABLE_RUBY flag so vendors can ship with Ruby disabled if they choose. + https://bugs.webkit.org/show_bug.cgi?id=34698 + + * Configurations/FeatureDefines.xcconfig: + +2010-02-09 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Geoffrey Garen. + + https://bugs.webkit.org/show_bug.cgi?id=34490 + WebCore::ImageEventSender::dispatchPendingEvents() crashes in certain conditions + + * ForwardingHeaders/wtf/ValueCheck.h: Added. + +2010-02-10 Jesus Sanchez-Palencia <jesus.palencia@openbossa.org> + + Reviewed by Kenneth Rohde Christiansen. + + Support frameset flattening + https://bugs.webkit.org/show_bug.cgi?id=32717 + + Add support for enabling/disabling FrameSet Flattening on the Mac port. + + * WebView/WebPreferenceKeysPrivate.h: + * WebView/WebPreferences.mm: + (+[WebPreferences initialize]): + (-[WebPreferences isFrameSetFlatteningEnabled]): + (-[WebPreferences setFrameSetFlatteningEnabled:]): + * WebView/WebPreferencesPrivate.h: + * WebView/WebView.mm: + (-[WebView _preferencesChangedNotification:]): + +2010-02-09 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Anders Carlsson. + + https://bugs.webkit.org/show_bug.cgi?id=34771 + A stray mouse moved event is sent to plug-ins after mouse exit + + * WebCoreSupport/WebFrameLoaderClient.mm: (NetscapePluginWidget::handleEvent): A mouseout + DOM event is dispatched while handling NSMouseMoved - but we shouldn't be sending a + mouse moved event to plug-ins at this point. + +2010-02-09 Shinichiro Hamaji <hamaji@chromium.org> + + Reviewed by Darin Adler. + + Provide a way to get total number of pages to be printed + https://bugs.webkit.org/show_bug.cgi?id=34699 + + * Misc/WebCoreStatistics.h: + * Misc/WebCoreStatistics.mm: + (-[WebFrame numberOfPages:pageWidthInPixels:]): + +2010-02-08 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=34727 + Assertion crashes and freezes when plug-in property access results in an exception + + * Plugins/Hosted/WebKitPluginClient.defs: Made PCSetProperty and PCRemoveProperty async. + A plug-in can call back whil processing this call (e.g. for NPN_SetException), so we need + to listen for messages while waiting for reply. + + * Plugins/Hosted/NetscapePluginHostProxy.mm: + (WKPCEvaluate): If there is no instance proxy, return KERN_FAILURE. This improves consistency + between method implementations, and leaves us with one less IPC call to make in failure case + (returning false with KERN_SUCCESS and returning KERN_FAILURE looks the same from plugin + host code). + (WKPCInvoke): Ditto. + (WKPCInvokeDefault): Ditto. + (WKPCGetProperty): Ditto. + (WKPCSetProperty): Send a reply once done. + (WKPCRemoveProperty): Ditto. + (WKPCHasProperty): If there is no instance proxy, return KERN_FAILURE. + (WKPCHasMethod): Ditto. + (WKPCEnumerate): Ditto. + +2010-02-08 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Anders Carlsson. + + <rdar://problem/6530010> OOP: Support NPN_SetException + + Tested by plugins/netscape-throw-exception.html (removed it from skipped list). + + * Plugins/Hosted/NetscapePluginHostProxy.mm: + (WKPCSetException): + * Plugins/Hosted/NetscapePluginInstanceProxy.h: + * Plugins/Hosted/NetscapePluginInstanceProxy.mm: + (WebKit::globalExceptionString): + (WebKit::NetscapePluginInstanceProxy::setGlobalException): + (WebKit::NetscapePluginInstanceProxy::moveGlobalExceptionToExecState): + * Plugins/Hosted/ProxyInstance.mm: + (WebKit::ProxyInstance::invoke): + (WebKit::ProxyInstance::getPropertyNames): + (WebKit::ProxyInstance::fieldValue): + (WebKit::ProxyInstance::setFieldValue): + * Plugins/Hosted/WebKitPluginClient.defs: + Route exception string to a global that's checked after calling into plug-in (just like in + in-process case). + +2010-02-05 Kevin Decker <kdecker@apple.com> + + Reviewed by Mark Rowe. + + https://bugs.webkit.org/show_bug.cgi?id=34661 + <rdar://problem/7614067> REGRESSION (Safari 4.0-> Safari 4.0.4): NPP_SetWindow no longer sets a clipRect of (0,0,0,0) when it becomes hidden + + * Plugins/Hosted/WebHostedNetscapePluginView.mm: + (-[WebHostedNetscapePluginView updateAndSetWindow]): When clipping out NPDrawingModelCoreAnimation plug-ins, provide a zero'd out clipRect. + * Plugins/WebBaseNetscapePluginView.h: Moved superviewsHaveSuperviews to the base class. + * Plugins/WebBaseNetscapePluginView.mm: + (-[WebBaseNetscapePluginView superviewsHaveSuperviews]): Added to the base class; extracted from WebNetscapePluginView. + (-[WebBaseNetscapePluginView shouldClipOutPlugin]): Added new method with code extracted from WebNetscapePluginView. + * Plugins/WebNetscapePluginView.mm: + (-[WebNetscapePluginView saveAndSetNewPortStateForUpdate:]): When clipping out NPDrawingModelCoreAnimation plug-ins, provide a zero'd out clipRect. + +2010-02-04 Mark Rowe <mrowe@apple.com> + + Rubber-stamped by Dan Bernstein. + + Fix the ability to #include <WebKit/DOMFile.h>. + + * MigrateHeaders.make: Mark DOMBlob.h as a public header since the already-public DOMFile.h depends on it. + +2010-02-04 John Sullivan <sullivan@apple.com> + + https://bugs.webkit.org/show_bug.cgi?id=34611 + WebLocalizedString() could use an assertion that it is being called on the main thread + + Reviewed by Tim Hatcher. + + * Misc/WebLocalizableStrings.m: Removed. + * Misc/WebLocalizableStrings.mm: Copied from mac/Misc/WebLocalizableStrings.m. + Renamed to use .mm extension so it can include a C++ header. + (WebLocalizedString): + Added an assertion that this is being called on the main thread. + +2010-02-04 Dan Bernstein <mitz@apple.com> + + Reviewed by Simon Fraser. + + REGRESSION (r53718): When scrolling a tall window by page, the overlap between pages is too big + https://bugs.webkit.org/show_bug.cgi?id=34371 + + * WebView/WebFrameView.mm: + (-[WebFrameView _verticalPageScrollDistance]): Use Scrollbar methods instead of + constants, and cap the scroll distance. + (-[WebFrameView initWithFrame:]): Use Scrollbar::pixelsPerLineStep() instead of + cScrollbarPixelsPerLineStep. + (-[WebFrameView _horizontalPageScrollDistance]):Use Scrollbar methods instead of + constants, and cap the scroll distance. + 2010-02-01 Shinichiro Hamaji <hamaji@chromium.org> Reviewed by Eric Seidel. diff --git a/WebKit/mac/Configurations/FeatureDefines.xcconfig b/WebKit/mac/Configurations/FeatureDefines.xcconfig index 24589c7..8343ce7 100644 --- a/WebKit/mac/Configurations/FeatureDefines.xcconfig +++ b/WebKit/mac/Configurations/FeatureDefines.xcconfig @@ -56,6 +56,7 @@ ENABLE_JAVASCRIPT_DEBUGGER = ENABLE_JAVASCRIPT_DEBUGGER; ENABLE_MATHML = ; ENABLE_NOTIFICATIONS = ; ENABLE_OFFLINE_WEB_APPLICATIONS = ENABLE_OFFLINE_WEB_APPLICATIONS; +ENABLE_RUBY = ENABLE_RUBY; ENABLE_SHARED_WORKERS = ENABLE_SHARED_WORKERS; ENABLE_SVG = ENABLE_SVG; ENABLE_SVG_ANIMATION = ENABLE_SVG_ANIMATION; @@ -72,4 +73,4 @@ ENABLE_XHTMLMP = ; ENABLE_XPATH = ENABLE_XPATH; ENABLE_XSLT = ENABLE_XSLT; -FEATURE_DEFINES = $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT); +FEATURE_DEFINES = $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_RUBY) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT); diff --git a/WebKit/mac/Configurations/Version.xcconfig b/WebKit/mac/Configurations/Version.xcconfig index 75f9bd4..0e289b1 100644 --- a/WebKit/mac/Configurations/Version.xcconfig +++ b/WebKit/mac/Configurations/Version.xcconfig @@ -21,8 +21,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -MAJOR_VERSION = 532; -MINOR_VERSION = 9; +MAJOR_VERSION = 533; +MINOR_VERSION = 1; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/WebKit/mac/ForwardingHeaders/wtf/ValueCheck.h b/WebKit/mac/ForwardingHeaders/wtf/ValueCheck.h new file mode 100644 index 0000000..7a067ff --- /dev/null +++ b/WebKit/mac/ForwardingHeaders/wtf/ValueCheck.h @@ -0,0 +1 @@ +#import <JavaScriptCore/ValueCheck.h> diff --git a/WebKit/mac/MigrateHeaders.make b/WebKit/mac/MigrateHeaders.make index 7d01c99..f4bf744 100644 --- a/WebKit/mac/MigrateHeaders.make +++ b/WebKit/mac/MigrateHeaders.make @@ -36,7 +36,7 @@ all : \ $(PUBLIC_HEADERS_DIR)/DOM.h \ $(PUBLIC_HEADERS_DIR)/DOMAbstractView.h \ $(PUBLIC_HEADERS_DIR)/DOMAttr.h \ - $(PRIVATE_HEADERS_DIR)/DOMBlob.h \ + $(PUBLIC_HEADERS_DIR)/DOMBlob.h \ $(INTERNAL_HEADERS_DIR)/DOMBlobInternal.h \ $(PUBLIC_HEADERS_DIR)/DOMCDATASection.h \ $(PUBLIC_HEADERS_DIR)/DOMCSS.h \ diff --git a/WebKit/mac/Misc/WebCoreStatistics.h b/WebKit/mac/Misc/WebCoreStatistics.h index 6c45fb9..d205083 100644 --- a/WebKit/mac/Misc/WebCoreStatistics.h +++ b/WebKit/mac/Misc/WebCoreStatistics.h @@ -43,6 +43,7 @@ + (size_t)javaScriptProtectedObjectsCount; + (size_t)javaScriptProtectedGlobalObjectsCount; + (NSCountedSet *)javaScriptProtectedObjectTypeCounts; ++ (NSCountedSet *)javaScriptObjectTypeCounts; + (void)garbageCollectJavaScriptObjects; + (void)garbageCollectJavaScriptObjectsOnAlternateThreadForDebugging:(BOOL)waitUntilDone; @@ -85,4 +86,5 @@ - (NSString *)renderTreeAsExternalRepresentation; - (NSString *)counterValueForElement:(DOMElement*)element; - (int)pageNumberForElement:(DOMElement*)element:(float)pageWidthInPixels:(float)pageHeightInPixels; +- (int)numberOfPages:(float)pageWidthInPixels:(float)pageHeightInPixels; @end diff --git a/WebKit/mac/Misc/WebCoreStatistics.mm b/WebKit/mac/Misc/WebCoreStatistics.mm index b18ee29..9e8ae05 100644 --- a/WebKit/mac/Misc/WebCoreStatistics.mm +++ b/WebKit/mac/Misc/WebCoreStatistics.mm @@ -93,6 +93,21 @@ using namespace WebCore; return result; } ++ (NSCountedSet *)javaScriptObjectTypeCounts +{ + JSLock lock(SilenceAssertionsOnly); + + NSCountedSet *result = [NSCountedSet set]; + + OwnPtr<HashCountedSet<const char*> > counts(JSDOMWindow::commonJSGlobalData()->heap.objectTypeCounts()); + HashCountedSet<const char*>::iterator end = counts->end(); + for (HashCountedSet<const char*>::iterator it = counts->begin(); it != end; ++it) + for (unsigned i = 0; i < it->second; ++i) + [result addObject:[NSString stringWithUTF8String:it->first]]; + + return result; +} + + (void)garbageCollectJavaScriptObjects { gcController().garbageCollectNow(); @@ -256,4 +271,9 @@ using namespace WebCore; return PrintContext::pageNumberForElement(core(element), FloatSize(pageWidthInPixels, pageHeightInPixels)); } +- (int)numberOfPages:(float)pageWidthInPixels:(float)pageHeightInPixels +{ + return PrintContext::numberOfPages(_private->coreFrame, FloatSize(pageWidthInPixels, pageHeightInPixels)); +} + @end diff --git a/WebKit/mac/Misc/WebLocalizableStrings.m b/WebKit/mac/Misc/WebLocalizableStrings.mm index 0babfbc..4006bb7 100644 --- a/WebKit/mac/Misc/WebLocalizableStrings.m +++ b/WebKit/mac/Misc/WebLocalizableStrings.mm @@ -29,11 +29,18 @@ #import <WebKit/WebLocalizableStrings.h> #import <wtf/Assertions.h> +#import <wtf/Threading.h> WebLocalizableStringsBundle WebKitLocalizableStringsBundle = { "com.apple.WebKit", 0 }; NSString *WebLocalizedString(WebLocalizableStringsBundle *stringsBundle, const char *key) { + // This function is not thread-safe due at least to its unguarded use of the mainBundle static variable + // and its use of [NSBundle localizedStringForKey:::], which is not guaranteed to be thread-safe. If + // we decide we need to use this on background threads, we'll need to add locking here and make sure + // it doesn't affect performance. + ASSERT(isMainThread()); + NSBundle *bundle; if (stringsBundle == NULL) { static NSBundle *mainBundle; diff --git a/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm b/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm index 0e6c9a3..c5beb07 100644 --- a/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm +++ b/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm @@ -39,6 +39,7 @@ #import <WebCore/Frame.h> #import <WebCore/IdentifierRep.h> #import <WebCore/ScriptController.h> +#import <string> extern "C" { #import "WebKitPluginHost.h" @@ -568,10 +569,8 @@ kern_return_t WKPCEvaluate(mach_port_t clientPort, uint32_t pluginID, uint32_t r return KERN_FAILURE; NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); - if (!instanceProxy) { - _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0); - return KERN_SUCCESS; - } + if (!instanceProxy) + return KERN_FAILURE; PluginDestroyDeferrer deferrer(instanceProxy); @@ -625,18 +624,14 @@ kern_return_t WKPCInvoke(mach_port_t clientPort, uint32_t pluginID, uint32_t req return KERN_FAILURE; NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); - if (!instanceProxy) { - _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0); - return KERN_SUCCESS; - } + 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; - } + if (!IdentifierRep::isValid(identifier)) + return KERN_FAILURE; Identifier methodNameIdentifier = identifierFromIdentifierRep(identifier); @@ -661,10 +656,8 @@ kern_return_t WKPCInvokeDefault(mach_port_t clientPort, uint32_t pluginID, uint3 return KERN_FAILURE; NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); - if (!instanceProxy) { - _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0); - return KERN_SUCCESS; - } + if (!instanceProxy) + return KERN_FAILURE; PluginDestroyDeferrer deferrer(instanceProxy); @@ -707,16 +700,12 @@ kern_return_t WKPCGetProperty(mach_port_t clientPort, uint32_t pluginID, uint32_ return KERN_FAILURE; NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); - if (!instanceProxy) { - _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0); - return KERN_SUCCESS; - } + if (!instanceProxy) + return KERN_FAILURE; IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier); - if (!IdentifierRep::isValid(identifier)) { - _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0); - return KERN_SUCCESS; - } + if (!IdentifierRep::isValid(identifier)) + return KERN_FAILURE; PluginDestroyDeferrer deferrer(instanceProxy); @@ -737,7 +726,7 @@ kern_return_t WKPCGetProperty(mach_port_t clientPort, uint32_t pluginID, uint32_ 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) +kern_return_t WKPCSetProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier, data_t valueData, mach_msg_type_number_t valueLength) { DataDeallocator deallocator(valueData, valueLength); @@ -753,18 +742,21 @@ kern_return_t WKPCSetProperty(mach_port_t clientPort, uint32_t pluginID, uint32_ IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier); if (!IdentifierRep::isValid(identifier)) - *returnValue = false; - + return KERN_FAILURE; + + bool result; if (identifier->isString()) { Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier); - *returnValue = instanceProxy->setProperty(objectID, propertyNameIdentifier, valueData, valueLength); + result = instanceProxy->setProperty(objectID, propertyNameIdentifier, valueData, valueLength); } else - *returnValue = instanceProxy->setProperty(objectID, identifier->number(), valueData, valueLength); - + result = instanceProxy->setProperty(objectID, identifier->number(), valueData, valueLength); + + _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, result); + return KERN_SUCCESS; } -kern_return_t WKPCRemoveProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t objectID, uint64_t serverIdentifier, boolean_t* returnValue) +kern_return_t WKPCRemoveProperty(mach_port_t clientPort, uint32_t pluginID, uint32_t requestID, uint32_t objectID, uint64_t serverIdentifier) { NetscapePluginHostProxy* hostProxy = pluginProxyMap().get(clientPort); if (!hostProxy) @@ -779,13 +771,16 @@ kern_return_t WKPCRemoveProperty(mach_port_t clientPort, uint32_t pluginID, uint IdentifierRep* identifier = reinterpret_cast<IdentifierRep*>(serverIdentifier); if (!IdentifierRep::isValid(identifier)) return KERN_FAILURE; - + + bool result; if (identifier->isString()) { Identifier propertyNameIdentifier = identifierFromIdentifierRep(identifier); - *returnValue = instanceProxy->removeProperty(objectID, propertyNameIdentifier); + result = instanceProxy->removeProperty(objectID, propertyNameIdentifier); } else - *returnValue = instanceProxy->removeProperty(objectID, identifier->number()); - + result = instanceProxy->removeProperty(objectID, identifier->number()); + + _WKPHBooleanReply(hostProxy->port(), instanceProxy->pluginID(), requestID, result); + return KERN_SUCCESS; } @@ -796,18 +791,14 @@ kern_return_t WKPCHasProperty(mach_port_t clientPort, uint32_t pluginID, uint32_ return KERN_FAILURE; NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); - if (!instanceProxy) { - _WKPHBooleanReply(hostProxy->port(), pluginID, requestID, false); - return KERN_SUCCESS; - } + 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; - } + if (!IdentifierRep::isValid(identifier)) + return KERN_FAILURE; boolean_t returnValue; if (identifier->isString()) { @@ -828,18 +819,14 @@ kern_return_t WKPCHasMethod(mach_port_t clientPort, uint32_t pluginID, uint32_t return KERN_FAILURE; NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); - if (!instanceProxy) { - _WKPHBooleanReply(hostProxy->port(), pluginID, requestID, false); - return KERN_SUCCESS; - } + 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; - } + if (!IdentifierRep::isValid(identifier)) + return KERN_FAILURE; Identifier methodNameIdentifier = identifierFromIdentifierRep(identifier); boolean_t returnValue = instanceProxy->hasMethod(objectID, methodNameIdentifier); @@ -880,10 +867,8 @@ kern_return_t WKPCEnumerate(mach_port_t clientPort, uint32_t pluginID, uint32_t return KERN_FAILURE; NetscapePluginInstanceProxy* instanceProxy = hostProxy->pluginInstance(pluginID); - if (!instanceProxy) { - _WKPHBooleanAndDataReply(hostProxy->port(), pluginID, requestID, false, 0, 0); - return KERN_SUCCESS; - } + if (!instanceProxy) + return KERN_FAILURE; data_t resultData = 0; mach_msg_type_number_t resultLength = 0; @@ -1149,4 +1134,14 @@ kern_return_t WKPCRunSyncOpenPanel(mach_port_t clientPort, data_t panelData, mac } #endif // !defined(BUILDING_ON_SNOW_LEOPARD) +kern_return_t WKPCSetException(mach_port_t clientPort, data_t message, mach_msg_type_number_t messageCnt) +{ + DataDeallocator deallocator(message, messageCnt); + + string str(message, messageCnt); + NetscapePluginInstanceProxy::setGlobalException(str.c_str()); + + return KERN_SUCCESS; +} + #endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h b/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h index 2ef6b02..76981a4 100644 --- a/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h +++ b/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.h @@ -140,7 +140,7 @@ public: data_t& usernameData, mach_msg_type_number_t& usernameLength, data_t& passwordData, mach_msg_type_number_t& passwordLength); bool convertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double& destX, double& destY, NPCoordinateSpace destSpace); - + PassRefPtr<JSC::Bindings::Instance> createBindingsInstance(PassRefPtr<JSC::Bindings::RootObject>); RetainPtr<NSData *> marshalValues(JSC::ExecState*, const JSC::ArgList& args); void marshalValue(JSC::ExecState*, JSC::JSValue value, data_t& resultData, mach_msg_type_number_t& resultLength); @@ -167,6 +167,9 @@ public: void didDraw(); void privateBrowsingModeDidChange(bool isPrivateBrowsingEnabled); + static void setGlobalException(const WebCore::String&); + static void moveGlobalExceptionToExecState(JSC::ExecState*); + // Reply structs struct Reply { enum Type { diff --git a/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm b/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm index e4fe1d2..c09e3ea 100644 --- a/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm +++ b/WebKit/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm @@ -40,6 +40,7 @@ #import "WebUIDelegate.h" #import "WebUIDelegatePrivate.h" #import "WebViewInternal.h" +#import <JavaScriptCore/Error.h> #import <JavaScriptCore/JSLock.h> #import <JavaScriptCore/PropertyNameArray.h> #import <WebCore/CString.h> @@ -1492,6 +1493,30 @@ void NetscapePluginInstanceProxy::privateBrowsingModeDidChange(bool isPrivateBro _WKPHPluginInstancePrivateBrowsingModeDidChange(m_pluginHostProxy->port(), m_pluginID, isPrivateBrowsingEnabled); } +static String& globalExceptionString() +{ + DEFINE_STATIC_LOCAL(String, exceptionString, ()); + return exceptionString; +} + +void NetscapePluginInstanceProxy::setGlobalException(const String& exception) +{ + globalExceptionString() = exception; +} + +void NetscapePluginInstanceProxy::moveGlobalExceptionToExecState(ExecState* exec) +{ + if (globalExceptionString().isNull()) + return; + + { + JSLock lock(SilenceAssertionsOnly); + throwError(exec, GeneralError, globalExceptionString()); + } + + globalExceptionString() = UString(); +} + } // namespace WebKit #endif // USE(PLUGIN_HOST_PROCESS) diff --git a/WebKit/mac/Plugins/Hosted/ProxyInstance.mm b/WebKit/mac/Plugins/Hosted/ProxyInstance.mm index 1af2ef8..1587ad0 100644 --- a/WebKit/mac/Plugins/Hosted/ProxyInstance.mm +++ b/WebKit/mac/Plugins/Hosted/ProxyInstance.mm @@ -147,6 +147,7 @@ JSValue ProxyInstance::invoke(JSC::ExecState* exec, InvokeType type, uint64_t id return jsUndefined(); auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID); + NetscapePluginInstanceProxy::moveGlobalExceptionToExecState(exec); if (!reply.get() || !reply->m_returnValue) return jsUndefined(); @@ -253,7 +254,7 @@ void ProxyInstance::getPropertyNames(ExecState* exec, PropertyNameArray& nameArr return; auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID); - + NetscapePluginInstanceProxy::moveGlobalExceptionToExecState(exec); if (!reply.get() || !reply->m_returnValue) return; @@ -361,6 +362,7 @@ JSC::JSValue ProxyInstance::fieldValue(ExecState* exec, const Field* field) cons return jsUndefined(); auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID); + NetscapePluginInstanceProxy::moveGlobalExceptionToExecState(exec); if (!reply.get() || !reply->m_returnValue) return jsUndefined(); @@ -387,6 +389,7 @@ void ProxyInstance::setFieldValue(ExecState* exec, const Field* field, JSValue v return; auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID); + NetscapePluginInstanceProxy::moveGlobalExceptionToExecState(exec); } void ProxyInstance::invalidate() diff --git a/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm b/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm index 9baa328..42f0877 100644 --- a/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm +++ b/WebKit/mac/Plugins/Hosted/WebHostedNetscapePluginView.mm @@ -161,12 +161,24 @@ extern "C" { // 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]; + NSRect visibleRectInWindow; + + // Core Animation plug-ins need to be updated (with a 0,0,0,0 clipRect) when + // moved to a background tab. We don't do this for Core Graphics plug-ins as + // older versions of Flash have historical WebKit-specific code that isn't + // compatible with this behavior. + BOOL shouldClipOutPlugin = _pluginLayer && [self shouldClipOutPlugin]; + if (!shouldClipOutPlugin) + visibleRectInWindow = [self convertRect:[self visibleRect] toView:nil]; + else + visibleRectInWindow = NSZeroRect; // 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); + + if (!shouldClipOutPlugin) + visibleRectInWindow.origin.y = borderViewHeight - NSMaxY(visibleRectInWindow); BOOL sizeChanged = !NSEqualSizes(_previousSize, boundsInWindow.size); _previousSize = boundsInWindow.size; diff --git a/WebKit/mac/Plugins/Hosted/WebKitPluginClient.defs b/WebKit/mac/Plugins/Hosted/WebKitPluginClient.defs index 0cf4005..58a7996 100644 --- a/WebKit/mac/Plugins/Hosted/WebKitPluginClient.defs +++ b/WebKit/mac/Plugins/Hosted/WebKitPluginClient.defs @@ -149,18 +149,18 @@ simpleroutine PCGetProperty(clientPort :mach_port_t; objectID :uint32_t; propertyNameIdentifier :uint64_t); -routine PCSetProperty(clientPort :mach_port_t; +simpleroutine PCSetProperty(clientPort :mach_port_t; pluginID :uint32_t; + requestID :uint32_t; objectID :uint32_t; propertyNameIdentifier :uint64_t; - value :data_t; - out returnValue :boolean_t); + value :data_t); -routine PCRemoveProperty(clientPort :mach_port_t; +simpleroutine PCRemoveProperty(clientPort :mach_port_t; pluginID :uint32_t; + requestID :uint32_t; objectID :uint32_t; - propertyNameIdentifier :uint64_t; - out returnValue :boolean_t); + propertyNameIdentifier :uint64_t); simpleroutine PCHasProperty(clientPort :mach_port_t; pluginID :uint32_t; @@ -236,3 +236,6 @@ simpleroutine PCRunSyncOpenPanel(clientPort :mach_port_t; simpleroutine PCSetFullScreenWindowIsShowing(clientPort :mach_port_t; isShowing :boolean_t); + +simpleroutine PCSetException(clientPort :mach_port_t; + message :data_t); diff --git a/WebKit/mac/Plugins/WebBaseNetscapePluginView.h b/WebKit/mac/Plugins/WebBaseNetscapePluginView.h index 246fcf1..029a058 100644 --- a/WebKit/mac/Plugins/WebBaseNetscapePluginView.h +++ b/WebKit/mac/Plugins/WebBaseNetscapePluginView.h @@ -119,6 +119,7 @@ class WebHaltablePlugin; - (void)addWindowObservers; - (void)removeWindowObservers; +- (BOOL)shouldClipOutPlugin; - (BOOL)convertFromX:(double)sourceX andY:(double)sourceY space:(NPCoordinateSpace)sourceSpace toX:(double *)destX andY:(double *)destY space:(NPCoordinateSpace)destSpace; diff --git a/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm b/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm index bf8b80b..e93509a 100644 --- a/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm +++ b/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm @@ -545,6 +545,22 @@ String WebHaltablePlugin::pluginName() const return _isHalted; } +- (BOOL)superviewsHaveSuperviews +{ + NSView *contentView = [[self window] contentView]; + for (NSView *view = self; view; view = [view superview]) { + if (view == contentView) + return YES; + } + return NO; +} + +- (BOOL)shouldClipOutPlugin +{ + NSWindow *window = [self window]; + return !window || [window isMiniaturized] || [NSApp isHidden] || ![self superviewsHaveSuperviews] || [self isHiddenOrHasHiddenAncestor]; +} + - (BOOL)hasBeenHalted { return _hasBeenHalted; diff --git a/WebKit/mac/Plugins/WebNetscapePluginView.mm b/WebKit/mac/Plugins/WebNetscapePluginView.mm index 4a4a435..e96abe8 100644 --- a/WebKit/mac/Plugins/WebNetscapePluginView.mm +++ b/WebKit/mac/Plugins/WebNetscapePluginView.mm @@ -197,19 +197,6 @@ typedef struct { #pragma mark EVENTS -- (BOOL)superviewsHaveSuperviews -{ - NSView *contentView = [[self window] contentView]; - NSView *view; - for (view = self; view != nil; view = [view superview]) { - if (view == contentView) { - return YES; - } - } - return NO; -} - - // The WindowRef created by -[NSWindow windowRef] has a QuickDraw GrafPort that covers // the entire window frame (or structure region to use the Carbon term) rather then just the window content. // We can remove this when <rdar://problem/4201099> is fixed. @@ -329,12 +316,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) // 3) the window is miniaturized or the app is hidden // 4) we're inside of viewWillMoveToWindow: with a nil window. In this case, superviews may already have nil // superviews and nil windows and results from convertRect:toView: are incorrect. - NSWindow *realWindow = [self window]; - if (window.width <= 0 || window.height <= 0 || window.x < -100000 - || realWindow == nil || [realWindow isMiniaturized] - || [NSApp isHidden] - || ![self superviewsHaveSuperviews] - || [self isHiddenOrHasHiddenAncestor]) { + if (window.width <= 0 || window.height <= 0 || window.x < -100000 || [self shouldClipOutPlugin]) { // The following code tries to give plug-ins the same size they will eventually have. // The specifiedWidth and specifiedHeight variables are used to predict the size that @@ -351,6 +333,13 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr) window.clipRect.bottom = window.clipRect.top; window.clipRect.left = window.clipRect.right; + + // Core Animation plug-ins need to be updated (with a 0,0,0,0 clipRect) when + // moved to a background tab. We don't do this for Core Graphics plug-ins as + // older versions of Flash have historical WebKit-specific code that isn't + // compatible with this behavior. + if (drawingModel == NPDrawingModelCoreAnimation) + getNPRect(NSZeroRect, window.clipRect); } else { getNPRect(visibleRectInWindow, window.clipRect); } diff --git a/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm index 5934d7c..eaec807 100644 --- a/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm +++ b/WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm @@ -1484,15 +1484,15 @@ public: { } - virtual void handleEvent(Event*) + virtual void handleEvent(Event* event) { Frame* frame = Frame::frameForWidget(this); if (!frame) return; - NSEvent* event = frame->eventHandler()->currentNSEvent(); - if ([event type] == NSMouseMoved) - [(WebBaseNetscapePluginView *)platformWidget() handleMouseMoved:event]; + NSEvent* currentNSEvent = frame->eventHandler()->currentNSEvent(); + if (event->type() == eventNames().mousemoveEvent) + [(WebBaseNetscapePluginView *)platformWidget() handleMouseMoved:currentNSEvent]; } }; diff --git a/WebKit/mac/WebView/WebFrameView.mm b/WebKit/mac/WebView/WebFrameView.mm index 565e64d..b6b1941 100644 --- a/WebKit/mac/WebView/WebFrameView.mm +++ b/WebKit/mac/WebView/WebFrameView.mm @@ -201,7 +201,7 @@ enum { - (float)_verticalPageScrollDistance { float height = [[self _contentView] bounds].size.height; - return max(height * cFractionToStepWhenPaging, 1.f); + return max<float>(height * Scrollbar::minFractionToStepWhenPaging(), height - Scrollbar::maxOverlapBetweenPages()); } static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCClass, NSArray *supportTypes) @@ -342,7 +342,7 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl [scrollView setHasVerticalScroller:NO]; [scrollView setHasHorizontalScroller:NO]; [scrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - [scrollView setLineScroll:cScrollbarPixelsPerLineStep]; + [scrollView setLineScroll:Scrollbar::pixelsPerLineStep()]; [self addSubview:scrollView]; // Don't call our overridden version of setNextKeyView here; we need to make the standard NSView @@ -613,7 +613,7 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl - (float)_horizontalPageScrollDistance { float width = [[self _contentView] bounds].size.width; - return max(width * cFractionToStepWhenPaging, 1.f); + return max<float>(width * Scrollbar::minFractionToStepWhenPaging(), width - Scrollbar::maxOverlapBetweenPages()); } - (BOOL)_pageVertically:(BOOL)up diff --git a/WebKit/mac/WebView/WebPDFDocumentExtras.h b/WebKit/mac/WebView/WebPDFDocumentExtras.h index 5a33ccf..0dce43e 100644 --- a/WebKit/mac/WebView/WebPDFDocumentExtras.h +++ b/WebKit/mac/WebView/WebPDFDocumentExtras.h @@ -23,10 +23,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import <PDFKit/PDFDocument.h> +@class PDFDocument; -@interface PDFDocument (WebPDFDocumentExtras) -- (NSArray *)_web_allScripts; -@end - -void addWebPDFDocumentExtras(Class); +NSArray *allScriptsInPDFDocument(PDFDocument *); diff --git a/WebKit/mac/WebView/WebPDFDocumentExtras.mm b/WebKit/mac/WebView/WebPDFDocumentExtras.mm index ec580ec..b7043df 100644 --- a/WebKit/mac/WebView/WebPDFDocumentExtras.mm +++ b/WebKit/mac/WebView/WebPDFDocumentExtras.mm @@ -68,10 +68,10 @@ static void getAllValuesInPDFNameTree(CGPDFDictionaryRef tree, Vector<CGPDFObjec appendValuesInPDFNameSubtreeToVector(tree, allValues); } -static NSArray *web_PDFDocumentAllScripts(id self, SEL _cmd) +NSArray *allScriptsInPDFDocument(PDFDocument *document) { NSMutableArray *scripts = [NSMutableArray array]; - CGPDFDocumentRef pdfDocument = [self documentRef]; + CGPDFDocumentRef pdfDocument = [document documentRef]; if (!pdfDocument) return scripts; @@ -129,13 +129,3 @@ static NSArray *web_PDFDocumentAllScripts(id self, SEL _cmd) return scripts; } - -void addWebPDFDocumentExtras(Class pdfDocumentClass) -{ -#ifndef BUILDING_ON_TIGER - class_addMethod(pdfDocumentClass, @selector(_web_allScripts), (IMP)web_PDFDocumentAllScripts, "@@:"); -#else - static struct objc_method_list methodList = { 0, 1, { @selector(_web_allScripts), (char*)"@@:", (IMP)web_PDFDocumentAllScripts } }; - class_addMethods(pdfDocumentClass, &methodList); -#endif -} diff --git a/WebKit/mac/WebView/WebPDFRepresentation.mm b/WebKit/mac/WebView/WebPDFRepresentation.mm index 924bda8..36449f3 100644 --- a/WebKit/mac/WebView/WebPDFRepresentation.mm +++ b/WebKit/mac/WebView/WebPDFRepresentation.mm @@ -70,16 +70,6 @@ return PDFDocumentClass; } -+ (void)initialize -{ - if (self != [WebPDFRepresentation class]) - return; - - Class pdfDocumentClass = [self PDFDocumentClass]; - if (pdfDocumentClass) - addWebPDFDocumentExtras(pdfDocumentClass); -} - - (void)setDataSource:(WebDataSource *)dataSource; { } @@ -136,7 +126,7 @@ PDFDocument *doc = [[[[self class] PDFDocumentClass] alloc] initWithData:data]; [view setPDFDocument:doc]; - NSArray *scripts = [doc _web_allScripts]; + NSArray *scripts = allScriptsInPDFDocument(doc); [doc release]; doc = nil; diff --git a/WebKit/mac/WebView/WebPreferenceKeysPrivate.h b/WebKit/mac/WebView/WebPreferenceKeysPrivate.h index 7085cec..b8e912e 100644 --- a/WebKit/mac/WebView/WebPreferenceKeysPrivate.h +++ b/WebKit/mac/WebView/WebPreferenceKeysPrivate.h @@ -90,6 +90,7 @@ #define WebKitWebGLEnabledPreferenceKey @"WebKitWebGLEnabled" #define WebKitUsesProxiedOpenPanelPreferenceKey @"WebKitUsesProxiedOpenPanel" #define WebKitPluginAllowedRunTimePreferenceKey @"WebKitPluginAllowedRunTime" +#define WebKitFrameSetFlatteningEnabledPreferenceKey @"WebKitFrameSetFlatteningEnabled" // These are private both because callers should be using the cover methods and because the // cover methods themselves are private. diff --git a/WebKit/mac/WebView/WebPreferences.mm b/WebKit/mac/WebView/WebPreferences.mm index d06cc13..a1176a9 100644 --- a/WebKit/mac/WebView/WebPreferences.mm +++ b/WebKit/mac/WebView/WebPreferences.mm @@ -356,6 +356,7 @@ static WebCacheModel cacheModelForMainBundle(void) [NSNumber numberWithBool:NO], WebKitWebGLEnabledPreferenceKey, [NSNumber numberWithBool:NO], WebKitUsesProxiedOpenPanelPreferenceKey, [NSNumber numberWithUnsignedInt:4], WebKitPluginAllowedRunTimePreferenceKey, + [NSNumber numberWithBool:NO], WebKitFrameSetFlatteningEnabledPreferenceKey, nil]; // This value shouldn't ever change, which is assumed in the initialization of WebKitPDFDisplayModePreferenceKey above @@ -1204,6 +1205,16 @@ static NSString *classIBCreatorID = nil; return [self _setIntegerValue:allowedRunTime forKey:WebKitPluginAllowedRunTimePreferenceKey]; } +- (BOOL)isFrameSetFlatteningEnabled +{ + return [self _boolValueForKey:WebKitFrameSetFlatteningEnabledPreferenceKey]; +} + +- (void)setFrameSetFlatteningEnabled:(BOOL)flag +{ + [self _setBoolValue:flag forKey:WebKitFrameSetFlatteningEnabledPreferenceKey]; +} + - (void)didRemoveFromWebView { ASSERT(_private->numWebViews); diff --git a/WebKit/mac/WebView/WebPreferencesPrivate.h b/WebKit/mac/WebView/WebPreferencesPrivate.h index 20c98b2..7c84d8d 100644 --- a/WebKit/mac/WebView/WebPreferencesPrivate.h +++ b/WebKit/mac/WebView/WebPreferencesPrivate.h @@ -113,6 +113,9 @@ extern NSString *WebPreferencesRemovedNotification; - (unsigned)pluginAllowedRunTime; - (void)setPluginAllowedRunTime:(unsigned)allowedRunTime; +- (BOOL)isFrameSetFlatteningEnabled; +- (void)setFrameSetFlatteningEnabled:(BOOL)flag; + // zero means do AutoScale - (float)PDFScaleFactor; - (void)setPDFScaleFactor:(float)scale; diff --git a/WebKit/mac/WebView/WebView.mm b/WebKit/mac/WebView/WebView.mm index e583bb5..4b449de 100644 --- a/WebKit/mac/WebView/WebView.mm +++ b/WebKit/mac/WebView/WebView.mm @@ -1334,6 +1334,7 @@ static bool fastDocumentTeardownEnabled() settings->setPluginAllowedRunTime([preferences pluginAllowedRunTime]); settings->setWebGLEnabled([preferences webGLEnabled]); settings->setLoadDeferringEnabled(shouldEnableLoadDeferring()); + settings->setFrameSetFlatteningEnabled([preferences isFrameSetFlatteningEnabled]); } static inline IMP getMethod(id o, SEL s) diff --git a/WebKit/qt/Api/DerivedSources.pro b/WebKit/qt/Api/DerivedSources.pro new file mode 100644 index 0000000..8702fde --- /dev/null +++ b/WebKit/qt/Api/DerivedSources.pro @@ -0,0 +1,96 @@ +TEMPLATE = lib +TARGET = dummy + +include(headers.pri) + +CONFIG -= debug_and_release + +DESTDIR = ../../../include/QtWebKit + +QUOTE = "" +DOUBLE_ESCAPED_QUOTE = "" +ESCAPE = "" +win32-msvc*|symbian { + ESCAPE = "^" +} else:win32-g++:isEmpty(QMAKE_SH) { + # MinGW's make will run makefile commands using sh, even if make + # was run from the Windows shell, if it finds sh in the path. + ESCAPE = "^" +} else { + QUOTE = "\'" + DOUBLE_ESCAPED_QUOTE = "\\\'" +} + +qtheader_module.target = $${DESTDIR}/QtWebKit +qtheader_module.depends = $${_PRO_FILE_} +qtheader_module.commands = echo $${QUOTE}$${LITERAL_HASH}ifndef QT_QTWEBKIT_MODULE_H$${QUOTE} > $${qtheader_module.target} && +qtheader_module.commands += echo $${QUOTE}$${LITERAL_HASH}define QT_QTWEBKIT_MODULE_H$${QUOTE} >> $${qtheader_module.target} && +qtheader_module.commands += echo $${QUOTE}$${LITERAL_HASH}include $${ESCAPE}<QtNetwork/QtNetwork$${ESCAPE}>$${QUOTE} >> $${qtheader_module.target} && +WEBKIT_CLASS_HEADERS = $${LITERAL_DOLLAR}$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PWD/QtWebKit + +regex = ".*\sclass\sQWEBKIT_EXPORT\s(\w+)\s(.*)" + +for(HEADER, WEBKIT_API_HEADERS) { + qtheader_module.depends += $$HEADER + # Quotes need to be escaped once more when placed in eval() + eval(qtheader_module.commands += echo $${DOUBLE_ESCAPED_QUOTE}\$${LITERAL_HASH}include \\\"$$basename(HEADER)\\\"$${DOUBLE_ESCAPED_QUOTE} >> $${qtheader_module.target} &&) + + HEADER_NAME = $$basename(HEADER) + HEADER_TARGET = $$replace(HEADER_NAME, [^a-zA-Z0-9_], -) + HEADER_TARGET = "qtheader-$${HEADER_TARGET}" + + eval($${HEADER_TARGET}.target = $${DESTDIR}/$${HEADER_NAME}) + eval($${HEADER_TARGET}.depends = $$HEADER) + eval($${HEADER_TARGET}.commands = echo $${DOUBLE_ESCAPED_QUOTE}\$${LITERAL_HASH}include \\\"$$HEADER\\\"$${DOUBLE_ESCAPED_QUOTE} > $$eval($${HEADER_TARGET}.target)) + + QMAKE_EXTRA_TARGETS += $$HEADER_TARGET + + src_words = $$cat($$HEADER) + # Really make sure we're dealing with words + src_words = $$split(src_words, " ") + + src = $$join(src_words, $${LITERAL_WHITESPACE}) + for(ever) { + # Looking up by line is faster, so we try that first + res = $$find(src_words, "QWEBKIT_EXPORT") + isEmpty(res):break() + + # Then do a slow lookup to ensure we're dealing with an exported class + res = $$find(src, $$regex) + isEmpty(res):break() + + exp = $$replace(src, $$regex, "EXPORTED_CLASS = \1") + eval($$exp) + + CLASS_TARGET = "qtheader_$${EXPORTED_CLASS}" + + eval($${CLASS_TARGET}.target = $${DESTDIR}/$${EXPORTED_CLASS}) + eval($${CLASS_TARGET}.depends = $$eval($${HEADER_TARGET}.target)) + eval($${CLASS_TARGET}.commands = echo $${DOUBLE_ESCAPED_QUOTE}\$${LITERAL_HASH}include \\\"$$basename(HEADER)\\\"$${DOUBLE_ESCAPED_QUOTE} > $$eval($${CLASS_TARGET}.target)) + + QMAKE_EXTRA_TARGETS += $$CLASS_TARGET + WEBKIT_CLASS_HEADERS += $${LITERAL_DOLLAR}$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PWD/$${EXPORTED_CLASS} + + generated_files.depends += $$eval($${CLASS_TARGET}.target) + qtheader_pri.depends += $$eval($${CLASS_TARGET}.target) + + # Qt's QRegExp does not support inline non-greedy matching, + # so we'll have to work around it by updating the haystack + src = $$replace(src, $$regex, "\2") + src_words = $$join(src, $${LITERAL_WHITESPACE}) + } +} + +qtheader_module.commands += echo $${QUOTE}$${LITERAL_HASH}endif // QT_QTWEBKIT_MODULE_H$${QUOTE} >> $${qtheader_module.target} +QMAKE_EXTRA_TARGETS += qtheader_module + +qtheader_pri.target = $${DESTDIR}/classheaders.pri +qtheader_pri.depends = $${WEBKIT_API_HEADERS} $${_PRO_FILE_} +qtheader_pri.commands = echo $${QUOTE}WEBKIT_CLASS_HEADERS = $${WEBKIT_CLASS_HEADERS}$${QUOTE} > $${qtheader_pri.target} +QMAKE_EXTRA_TARGETS += qtheader_pri + +generated_files.depends += $${qtheader_module.target} $${qtheader_pri.target} +QMAKE_EXTRA_TARGETS += generated_files + + + diff --git a/WebKit/qt/Api/qgraphicswebview.cpp b/WebKit/qt/Api/qgraphicswebview.cpp index 8d4f3ba..b323598 100644 --- a/WebKit/qt/Api/qgraphicswebview.cpp +++ b/WebKit/qt/Api/qgraphicswebview.cpp @@ -27,6 +27,7 @@ #include "qwebpage_p.h" #include "QWebPageClient.h" #include <FrameView.h> +#include <QtCore/qmetaobject.h> #include <QtCore/qsharedpointer.h> #include <QtCore/qtimer.h> #include <QtGui/qapplication.h> @@ -78,13 +79,14 @@ public: , page(0) #if USE(ACCELERATED_COMPOSITING) , rootGraphicsLayer(0) - , shouldSync(true) + , shouldSync(false) #endif { #if USE(ACCELERATED_COMPOSITING) // the overlay and stays alive for the lifetime of // this QGraphicsWebView as the scrollbars are needed when there's no compositing q->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption); + syncMetaMethod = q->metaObject()->method(q->metaObject()->indexOfMethod("syncLayers()")); #endif } @@ -131,6 +133,9 @@ public: // compositor telling us to do so. We'll get that call from ChromeClientQt bool shouldSync; + // we have to flush quite often, so we use a meta-method instead of QTimer::singleShot for putting the event in the queue + QMetaMethod syncMetaMethod; + // we need to put the root graphics layer behind the overlay (which contains the scrollbar) enum { RootGraphicsLayerZValue, OverlayZValue }; #endif @@ -178,7 +183,7 @@ void QGraphicsWebViewPrivate::markForSync(bool scheduleSync) { shouldSync = true; if (scheduleSync) - QTimer::singleShot(0, q, SLOT(syncLayers())); + syncMetaMethod.invoke(q, Qt::QueuedConnection); } void QGraphicsWebViewPrivate::updateCompositingScrollPosition() @@ -224,6 +229,7 @@ void QGraphicsWebViewPrivate::update(const QRect & dirtyRect) #if USE(ACCELERATED_COMPOSITING) if (overlay) overlay->update(QRectF(dirtyRect)); + syncLayers(); #endif } @@ -442,7 +448,6 @@ void QGraphicsWebView::paint(QPainter* painter, const QStyleOptionGraphicsItem* { #if USE(ACCELERATED_COMPOSITING) page()->mainFrame()->render(painter, d->overlay ? QWebFrame::ContentsLayer : QWebFrame::AllLayers, option->exposedRect.toAlignedRect()); - d->syncLayers(); #else page()->mainFrame()->render(painter, QWebFrame::AllLayers, option->exposedRect.toRect()); #endif diff --git a/WebKit/qt/Api/qwebelement.cpp b/WebKit/qt/Api/qwebelement.cpp index 441bec7..9d4d0d0 100644 --- a/WebKit/qt/Api/qwebelement.cpp +++ b/WebKit/qt/Api/qwebelement.cpp @@ -38,7 +38,6 @@ #include "NodeList.h" #include "PropertyNameArray.h" #include "RenderImage.h" -#include "ScriptFunctionCall.h" #include "StaticNodeList.h" #include "qt_runtime.h" #include "qwebframe.h" diff --git a/WebKit/qt/Api/qwebframe.cpp b/WebKit/qt/Api/qwebframe.cpp index aeb7a22..4c1f318 100644 --- a/WebKit/qt/Api/qwebframe.cpp +++ b/WebKit/qt/Api/qwebframe.cpp @@ -220,6 +220,19 @@ QString QWEBKIT_EXPORT qt_drt_counterValueForElementById(QWebFrame* qFrame, cons return QString(); } +int QWEBKIT_EXPORT qt_drt_pageNumberForElementById(QWebFrame* qFrame, const QString& id, float width, float height) +{ + Frame* frame = QWebFramePrivate::core(qFrame); + if (!frame) + return -1; + + Element* element = frame->document()->getElementById(AtomicString(id)); + if (!element) + return -1; + + return PrintContext::pageNumberForElement(element, FloatSize(width, height)); +} + // Suspend active DOM objects in this frame. void QWEBKIT_EXPORT qt_suspendActiveDOMObjects(QWebFrame* qFrame) { diff --git a/WebKit/qt/Api/qwebpage.cpp b/WebKit/qt/Api/qwebpage.cpp index ea2401b..f661918 100644 --- a/WebKit/qt/Api/qwebpage.cpp +++ b/WebKit/qt/Api/qwebpage.cpp @@ -146,6 +146,11 @@ void QWEBKIT_EXPORT qt_drt_run(bool b) QWebPagePrivate::drtRun = b; } +void QWEBKIT_EXPORT qt_drt_setFrameSetFlatteningEnabled(QWebPage* page, bool enabled) +{ + QWebPagePrivate::core(page)->settings()->setFrameSetFlatteningEnabled(enabled); +} + void QWEBKIT_EXPORT qt_webpage_setGroupName(QWebPage* page, const QString& groupName) { page->handle()->page->setGroupName(groupName); @@ -444,6 +449,11 @@ QWebPagePrivate::~QWebPagePrivate() delete page; } +WebCore::Page* QWebPagePrivate::core(QWebPage* page) +{ + return page->d->page; +} + bool QWebPagePrivate::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type) { if (insideOpenCall @@ -1945,6 +1955,8 @@ bool QWebPage::shouldInterruptJavaScript() If the view associated with the web page is a QWebView object, then the default implementation forwards the request to QWebView's createWindow() function; otherwise it returns a null pointer. + If \a type is WebModalDialog, the application must call setWindowModality(Qt::ApplicationModal) on the new window. + \sa acceptNavigationRequest() */ QWebPage *QWebPage::createWindow(WebWindowType type) diff --git a/WebKit/qt/Api/qwebpage_p.h b/WebKit/qt/Api/qwebpage_p.h index dbc981e..15ddfb2 100644 --- a/WebKit/qt/Api/qwebpage_p.h +++ b/WebKit/qt/Api/qwebpage_p.h @@ -62,6 +62,9 @@ class QWebPagePrivate { public: QWebPagePrivate(QWebPage*); ~QWebPagePrivate(); + + static WebCore::Page* core(QWebPage*); + void createMainFrame(); #ifndef QT_NO_CONTEXTMENU QMenu* createContextMenu(const WebCore::ContextMenu* webcoreMenu, const QList<WebCore::ContextMenuItem>* items, QBitArray* visitedWebActions); diff --git a/WebKit/qt/Api/qwebview.cpp b/WebKit/qt/Api/qwebview.cpp index b5a5a90..79c16c7 100644 --- a/WebKit/qt/Api/qwebview.cpp +++ b/WebKit/qt/Api/qwebview.cpp @@ -60,96 +60,141 @@ void QWebViewPrivate::_q_pageDestroyed() #ifdef Q_WS_MAEMO_5 #include "qabstractkineticscroller.h" +#include "qapplication.h" -class QWebViewKineticScroller : public QAbstractKineticScroller { +// QCoreApplication::sendSpontaneousEvent() is private, hence this friend wrapper +bool qt_sendSpontaneousEvent(QObject* receiver, QEvent* ev) +{ + return QCoreApplication::sendSpontaneousEvent(receiver, ev); +} + +class QWebViewKineticScroller : public QObject, public QAbstractKineticScroller { public: - QWebViewKineticScroller() : QAbstractKineticScroller() {} - // remember the frame where the button was pressed + QWebViewKineticScroller() + : QObject() + , QAbstractKineticScroller() + , m_view(0) + , m_ignoreEvents(false) + { + } + + void setWidget(QWebView* widget) + { + if (m_view) { + m_view->removeEventFilter(this); + QWebFrame* frame = m_view->page()->mainFrame(); + frame->setScrollBarPolicy(Qt::Vertical, m_oldVerticalScrollBarPolicy); + frame->setScrollBarPolicy(Qt::Horizontal, m_oldHorizontalScrollBarPolicy); + } + + m_view = widget; + setParent(m_view); + if (m_view) { + QWebFrame* frame = m_view->page()->mainFrame(); + m_oldHorizontalScrollBarPolicy = frame->scrollBarPolicy(Qt::Horizontal); + m_oldVerticalScrollBarPolicy = frame->scrollBarPolicy(Qt::Vertical); + frame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); + frame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); + m_view->installEventFilter(this); + } + } + +protected: bool eventFilter(QObject* o, QEvent* ev) { + if (!o || m_view != o || m_ignoreEvents || !m_view->isEnabled()) + return QObject::eventFilter(o, ev); + + bool res = false; + switch (ev->type()) { case QEvent::MouseButtonPress: { + // remember the frame where the button was pressed QWebFrame* hitFrame = scrollingFrameAt(static_cast<QMouseEvent*>(ev)->pos()); if (hitFrame) m_frame = hitFrame; - break; + // fall through } + case QEvent::MouseMove: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + res = handleMouseEvent(static_cast<QMouseEvent*>(ev)); + break; default: break; } - return QAbstractKineticScroller::eventFilter(o, ev); + return res ? true : QObject::eventFilter(o, ev); } -protected: - QWebFrame* currentFrame() const + void cancelLeftMouseButtonPress(const QPoint& /* globalPressPos */) { - if (!m_frame.isNull()) - return m_frame.data(); - - QWebView* view = static_cast<QWebView*>(widget()); - QWebFrame* frame = view->page()->mainFrame(); - return frame; + QMouseEvent cmem(QEvent::MouseMove, QPoint(-INT_MAX, -INT_MAX), Qt::LeftButton, QApplication::mouseButtons() | Qt::LeftButton, QApplication::keyboardModifiers()); + sendEvent(m_view, &cmem); + QMouseEvent cmer(QEvent::MouseButtonRelease, QPoint(-INT_MAX, -INT_MAX), Qt::LeftButton, QApplication::mouseButtons() & ~Qt::LeftButton, QApplication::keyboardModifiers()); + sendEvent(m_view, &cmer); } - // Returns the innermost frame at the given position that can scroll. - QWebFrame* scrollingFrameAt(const QPoint& pos) const + QWebFrame* currentFrame() const { - QWebView* view = static_cast<QWebView*>(widget()); - QWebFrame* mainFrame = view->page()->mainFrame(); - QWebFrame* hitFrame = mainFrame->hitTestContent(pos).frame(); - QSize range = hitFrame->contentsSize() - hitFrame->geometry().size(); + if (m_frame) + return m_frame; - while (hitFrame && range.width() <= 1 && range.height() <= 1) - hitFrame = hitFrame->parentFrame(); + if (m_view) + return m_view->page()->mainFrame(); - return hitFrame; + return 0; } - void attachToWidget() + // Returns the innermost frame at the given position that can scroll. + QWebFrame* scrollingFrameAt(const QPoint& pos) const { - QWebView* view = static_cast<QWebView*>(widget()); - QWebFrame* mainFrame = view->page()->mainFrame(); - m_oldHorizontalScrollBarPolicy = mainFrame->scrollBarPolicy(Qt::Horizontal); - m_oldVerticalScrollBarPolicy = mainFrame->scrollBarPolicy(Qt::Vertical); - mainFrame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff); - mainFrame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff); - view->installEventFilter(this); - } + QWebFrame* hitFrame = 0; + if (m_view) { + QWebFrame* frame = m_view->page()->mainFrame(); + hitFrame = frame->hitTestContent(pos).frame(); + QSize range = hitFrame->contentsSize() - hitFrame->geometry().size(); - void removeFromWidget() - { - QWebView* view = static_cast<QWebView*>(widget()); - view->removeEventFilter(this); - QWebFrame* mainFrame = view->page()->mainFrame(); - mainFrame->setScrollBarPolicy(Qt::Vertical, m_oldVerticalScrollBarPolicy); - mainFrame->setScrollBarPolicy(Qt::Horizontal, m_oldHorizontalScrollBarPolicy); + while (hitFrame && range.width() <= 1 && range.height() <= 1) + hitFrame = hitFrame->parentFrame(); + + return hitFrame; + } } - QRect positionRange() const + QPoint maximumScrollPosition() const { - QRect r; QWebFrame* frame = currentFrame(); - r.setSize(frame->contentsSize() - frame->geometry().size()); - return r; + QSize s = frame ? frame->contentsSize() - frame->geometry().size() : QSize(0, 0); + return QPoint(qMax(0, s.width()), qMax(0, s.height())); } - QPoint position() const + QPoint scrollPosition() const { QWebFrame* frame = currentFrame(); - return frame->scrollPosition(); + return frame ? frame->scrollPosition() : QPoint(); } QSize viewportSize() const { - return static_cast<QWebView*>(widget())->page()->viewportSize(); + return m_view ? m_view->page()->viewportSize() : QSize(); } - void setPosition(const QPoint& point, const QPoint& /* overShootDelta */) + void setScrollPosition(const QPoint& point, const QPoint& /* overShootDelta */) { QWebFrame* frame = currentFrame(); - frame->setScrollPosition(point); + if (frame) + frame->setScrollPosition(point); + } + + void sendEvent(QWidget* w, QEvent* ev) + { + m_ignoreEvents = true; + qt_sendSpontaneousEvent(w, ev); + m_ignoreEvents = false; } + QWebView* m_view; + bool m_ignoreEvents; QPointer<QWebFrame> m_frame; Qt::ScrollBarPolicy m_oldVerticalScrollBarPolicy; Qt::ScrollBarPolicy m_oldHorizontalScrollBarPolicy; @@ -259,7 +304,7 @@ QWebView::QWebView(QWidget *parent) #endif #if defined(Q_WS_MAEMO_5) QAbstractKineticScroller* scroller = new QWebViewKineticScroller(); - scroller->setWidget(this); + static_cast<QWebViewKineticScroller*>(scroller)->setWidget(this); setProperty("kineticScroller", QVariant::fromValue(scroller)); #endif setAcceptDrops(true); diff --git a/WebKit/qt/ChangeLog b/WebKit/qt/ChangeLog index e63ee86..e0d1b28 100644 --- a/WebKit/qt/ChangeLog +++ b/WebKit/qt/ChangeLog @@ -1,3 +1,222 @@ +2010-02-12 Diego Gonzalez <diego.gonzalez@openbossa.org> + + Reviewed by Kenneth Rohde Christiansen. + + Qt DRT now dump the frame loader callbacks when LayoutTestController() + method is called. + + LayoutTests: + http/tests/security/mixedContent/data-url-script-in-iframe.html + http/tests/security/mixedContent/empty-url-plugin-in-frame.html + http/tests/security/mixedContent/insecure-css-in-iframe.html + http/tests/security/mixedContent/insecure-iframe-in-iframe.html + http/tests/security/mixedContent/insecure-image-in-iframe.html + http/tests/security/mixedContent/insecure-plugin-in-iframe.html + http/tests/security/mixedContent/insecure-script-in-iframe.html + http/tests/security/mixedContent/redirect-http-to-https-script-in-iframe.html + http/tests/security/mixedContent/redirect-https-to-http-script-in-iframe.html + + [Qt] Make possible Qt DRT dump frame load callbacks + https://bugs.webkit.org/show_bug.cgi?id=34702 + + * WebCoreSupport/FrameLoaderClientQt.cpp: + (WebCore::FrameLoaderClientQt::didDisplayInsecureContent): + (WebCore::FrameLoaderClientQt::didRunInsecureContent): + +2010-02-10 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Tor Arne Vestbø. + + [Qt] Make qtlauncher and qgvlauncher use the generated headers + path to make sure they are correctly generated. + + * tests/tests.pri: + +2010-02-10 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Tor Arne Vestbø. + + [Qt] Ensure relative paths in generated .pri files to ensure that + a source package with pre-generated derived sources can be compiled. + + - Re-add a separate headers.pri file for WEBKIT_API_HEADERS + - Rename the generated headers.pri to classheaders.pri to avoid + confusion with the one generated by synqt since they don't have the + same content. + - Remove private headers list variable from classheaders.pri + - Use $$PWD in classheaders.pri + - Remove classheaders.pri from the installed files + + * Api/DerivedSources.pro: + +2010-02-10 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Tor Arne Vestbø. + + [Qt] Minor fixes on QtWebKit headers generation. + + - Adds QtWebKit to the generated headers destination path + - Improve compatibility with MinGW + + * Api/DerivedSources.pro: + +2010-02-09 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by nobody, build fix. + + [Qt] Fix standalone build with MinGW. + + * tests/qwebelement/tst_qwebelement.cpp: + * tests/tests.pri: + +2010-02-10 Diego Gonzalez <diego.gonzalez@openbossa.org> + + Reviewed by Kenneth Rohde Christiansen. + + Implement pageNumberForElementById() method in Qt DRT LayoutTestController, + to make Qt DRT able to get page number. + + LayoutTests: + printing/page-break-always.html + printing/pageNumerForElementById.html + printing/css2.1/page-break-before-000.html + printing/css2.1/page-break-after-000.html + printing/css2.1/page-break-after-004.html + printing/css2.1/page-break-before-001.html + printing/css2.1/page-break-after-001.html + printing/css2.1/page-break-after-002.html + printing/css2.1/page-break-before-002.html + printing/css2.1/page-break-inside-000.html + + [Qt] Make possible Qt DRT get a page number for element by ID + https://bugs.webkit.org/show_bug.cgi?id=34777 + + * Api/qwebframe.cpp: + (qt_drt_pageNumberForElementById): + +2010-02-09 Yael Aharon <yael.aharon@nokia.com> + + Reviewed by Adam Barth. + + [Qt] Unit test for window.runModalDialog + https://bugs.webkit.org/show_bug.cgi?id=34755 + + * tests/qwebpage/tst_qwebpage.cpp: + (TestModalPage::TestModalPage): + (TestModalPage::createWindow): + (tst_QWebPage::showModalDialog): + +2010-02-09 Andreas Kling <andreas.kling@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Sync with API changes in Maemo 5 kinetic scrolling + + https://bugs.webkit.org/show_bug.cgi?id=34747 + + This is a forward-port of http://qt.gitorious.org/+qt-developers/qt/x11-maemo/commit/08497561 + + * Api/qwebview.cpp: + (qt_sendSpontaneousEvent): + (QWebViewKineticScroller::QWebViewKineticScroller): + (QWebViewKineticScroller::setWidget): + (QWebViewKineticScroller::eventFilter): + (QWebViewKineticScroller::cancelLeftMouseButtonPress): + (QWebViewKineticScroller::currentFrame): + (QWebViewKineticScroller::scrollingFrameAt): + (QWebViewKineticScroller::maximumScrollPosition): + (QWebViewKineticScroller::scrollPosition): + (QWebViewKineticScroller::viewportSize): + (QWebViewKineticScroller::setScrollPosition): + (QWebViewKineticScroller::sendEvent): + (QWebView::QWebView): + +2010-02-09 Yael Aharon <yael.aharon@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Webkit in Qt does not have window.showModalDialog + https://bugs.webkit.org/show_bug.cgi?id=25585 + + Create a new eventloop when runModal() is called. + Added comemnt in QWebPage::createWindow that the application is responsible + for setting the modality of the appropriate window. + + * Api/qwebpage.cpp: + * WebCoreSupport/ChromeClientQt.cpp: + (WebCore::ChromeClientQt::ChromeClientQt): + (WebCore::ChromeClientQt::~ChromeClientQt): + (WebCore::ChromeClientQt::canRunModal): + (WebCore::ChromeClientQt::runModal): + * WebCoreSupport/ChromeClientQt.h: + +2010-01-19 Kenneth Rohde Christiansen <kenneth@webkit.org> + + Reviewed by Dave Hyatt. + + Implement flattening of framesets + https://bugs.webkit.org/show_bug.cgi?id=32717 + + Privately export the setFrameSetFlatteningEnabled setting for + use with the Qt DRT. + + * Api/qwebpage.cpp: + (qt_drt_setFrameSetFlatteningEnabled): + (QWebPagePrivate::core): + * Api/qwebpage_p.h: + +2010-02-05 Tor Arne Vestbø <tor.arne.vestbo@nokia.com> + + [Qt] Fix build on Windows + + Reviewed by Kenneth Rohde Christiansen. + + DerivedSources for our API headers failed on Windows, + due to Windows not accepting ; as a command separator, + not needing quotes for echo, and needing < and > escaped. + + We now detect Windows and set these quote markers and + escape markers accordingly, as well as use && for separating + individual commands. + + * Api/DerivedSources.pro: + +2010-02-05 Yury Semikhatsky <yurys@chromium.org> + + Reviewed by Pavel Feldman. + + Remove unused inmport of ScriptFunctionCall.h + + https://bugs.webkit.org/show_bug.cgi?id=33592 + + * Api/qwebelement.cpp: + +2010-02-05 Tor Arne Vestbø <tor.arne.vestbo@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Generate convenience headers (QWebView, etc) using qmake + + In Qt this is done using syncqt, but we use a pro-file instead + that generates makefile-rules for each of the extra headers. + + These extra headers are installed alongside the normal headers. + + * Api/DerivedSources.pro: Added. List of headers + pro file magic + * Api/headers.pri: Removed, list of headers is now in the above file + +2010-02-04 No'am Rosenthal <noam.rosenthal@nokia.com> + + Reviewed by Ariya Hidayat. + + [Qt] Tuning and optimizations to GraphicsLayerQt. Mainly reduced usage + of QTimer::singleShot, and moved syncLayers() from paint() to update() + https://bugs.webkit.org/show_bug.cgi?id=34062 + + * Api/qgraphicswebview.cpp: + (QGraphicsWebViewPrivate::update): Moved the sync operation to update + (QGraphicsWebView::paint): Moved the sync operation to update + 2010-02-03 Andras Becsi <abecsi@webkit.org> Unreviewed build fix. diff --git a/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp b/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp index f1e6a86..893a1b7 100644 --- a/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp +++ b/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp @@ -44,6 +44,7 @@ #include "SecurityOrigin.h" #include <qdebug.h> +#include <qeventloop.h> #include <qtextdocument.h> #include <qtooltip.h> @@ -62,13 +63,15 @@ namespace WebCore { ChromeClientQt::ChromeClientQt(QWebPage* webPage) : m_webPage(webPage) + , m_eventLoop(0) { toolBarsVisible = statusBarVisible = menuBarVisible = true; } ChromeClientQt::~ChromeClientQt() { - + if (m_eventLoop) + m_eventLoop->exit(); } void ChromeClientQt::setWindowRect(const FloatRect& rect) @@ -173,14 +176,16 @@ void ChromeClientQt::show() bool ChromeClientQt::canRunModal() { - notImplemented(); - return false; + return true; } void ChromeClientQt::runModal() { - notImplemented(); + m_eventLoop = new QEventLoop(); + QEventLoop* eventLoop = m_eventLoop; + m_eventLoop->exec(); + delete eventLoop; } diff --git a/WebKit/qt/WebCoreSupport/ChromeClientQt.h b/WebKit/qt/WebCoreSupport/ChromeClientQt.h index 7699349..6b3017d 100644 --- a/WebKit/qt/WebCoreSupport/ChromeClientQt.h +++ b/WebKit/qt/WebCoreSupport/ChromeClientQt.h @@ -34,6 +34,7 @@ #include "KURL.h" #include "PlatformString.h" +class QEventLoop; class QWebPage; namespace WebCore { @@ -158,6 +159,7 @@ namespace WebCore { bool toolBarsVisible; bool statusBarVisible; bool menuBarVisible; + QEventLoop* m_eventLoop; }; } diff --git a/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp b/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp index 760e37e..16a6faa 100644 --- a/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp +++ b/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp @@ -672,11 +672,17 @@ void FrameLoaderClientQt::dispatchDidChangeBackForwardIndex() const void FrameLoaderClientQt::didDisplayInsecureContent() { + if (dumpFrameLoaderCallbacks) + printf("didDisplayInsecureContent\n"); + notImplemented(); } void FrameLoaderClientQt::didRunInsecureContent(WebCore::SecurityOrigin*) { + if (dumpFrameLoaderCallbacks) + printf("didRunInsecureContent\n"); + notImplemented(); } diff --git a/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp b/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp index dde65cf..8db0ec3 100644 --- a/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp +++ b/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp @@ -18,13 +18,13 @@ */ -#include <../util.h> #include <QtTest/QtTest> #include <qwebpage.h> #include <qwidget.h> #include <qwebview.h> #include <qwebframe.h> #include <qwebelement.h> +#include <util.h> //TESTED_CLASS= //TESTED_FILES= diff --git a/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp b/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp index f48fb73..ba7a87e 100644 --- a/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp +++ b/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp @@ -110,6 +110,7 @@ private slots: void originatingObjectInNetworkRequests(); void testJSPrompt(); + void showModalDialog(); private: QWebView* m_view; @@ -1828,5 +1829,26 @@ void tst_QWebPage::testJSPrompt() QVERIFY(res); } +class TestModalPage : public QWebPage +{ + Q_OBJECT +public: + TestModalPage(QObject* parent = 0) : QWebPage(parent) { + } + virtual QWebPage* createWindow(WebWindowType) { + QWebPage* page = new TestModalPage(); + connect(page, SIGNAL(windowCloseRequested()), page, SLOT(deleteLater())); + return page; + } +}; + +void tst_QWebPage::showModalDialog() +{ + TestModalPage page; + page.mainFrame()->setHtml(QString("<html></html>")); + QString res = page.mainFrame()->evaluateJavaScript("window.showModalDialog('javascript:window.returnValue=dialogArguments; window.close();', 'This is a test');").toString(); + QCOMPARE(res, QString("This is a test")); +} + QTEST_MAIN(tst_QWebPage) #include "tst_qwebpage.moc" diff --git a/WebKit/qt/tests/tests.pri b/WebKit/qt/tests/tests.pri index c3d7755..187950a 100644 --- a/WebKit/qt/tests/tests.pri +++ b/WebKit/qt/tests/tests.pri @@ -3,6 +3,9 @@ CONFIG -= app_bundle TARGET = tst_$$TARGET SOURCES += $$_PRO_FILE_PWD_/$${TARGET}.cpp +INCLUDEPATH += \ + $$PWD \ + $$PWD/../Api exists($$_PRO_FILE_PWD_/$${TARGET}.qrc):RESOURCES += $$_PRO_FILE_PWD_/$${TARGET}.qrc diff --git a/WebKit/win/AccessibleBase.cpp b/WebKit/win/AccessibleBase.cpp index 0704771..3e8306f 100644 --- a/WebKit/win/AccessibleBase.cpp +++ b/WebKit/win/AccessibleBase.cpp @@ -382,10 +382,10 @@ HRESULT STDMETHODCALLTYPE AccessibleBase::get_accKeyboardShortcut(VARIANT vChild HRESULT STDMETHODCALLTYPE AccessibleBase::accSelect(long selectionFlags, VARIANT vChild) { // According to MSDN, these combinations are invalid. - if (((selectionFlags & (SELFLAG_ADDSELECTION | SELFLAG_REMOVESELECTION)) == (SELFLAG_ADDSELECTION | SELFLAG_REMOVESELECTION)) || - ((selectionFlags & (SELFLAG_ADDSELECTION | SELFLAG_TAKESELECTION)) == (SELFLAG_ADDSELECTION | SELFLAG_TAKESELECTION)) || - ((selectionFlags & (SELFLAG_REMOVESELECTION | SELFLAG_TAKESELECTION)) == (SELFLAG_REMOVESELECTION | SELFLAG_TAKESELECTION)) || - ((selectionFlags & (SELFLAG_EXTENDSELECTION | SELFLAG_TAKESELECTION)) == (SELFLAG_REMOVESELECTION | SELFLAG_TAKESELECTION))) + if (((selectionFlags & (SELFLAG_ADDSELECTION | SELFLAG_REMOVESELECTION)) == (SELFLAG_ADDSELECTION | SELFLAG_REMOVESELECTION)) + || ((selectionFlags & (SELFLAG_ADDSELECTION | SELFLAG_TAKESELECTION)) == (SELFLAG_ADDSELECTION | SELFLAG_TAKESELECTION)) + || ((selectionFlags & (SELFLAG_REMOVESELECTION | SELFLAG_TAKESELECTION)) == (SELFLAG_REMOVESELECTION | SELFLAG_TAKESELECTION)) + || ((selectionFlags & (SELFLAG_EXTENDSELECTION | SELFLAG_TAKESELECTION)) == (SELFLAG_EXTENDSELECTION | SELFLAG_TAKESELECTION))) return E_INVALIDARG; AccessibilityObject* childObject; @@ -406,15 +406,19 @@ HRESULT STDMETHODCALLTYPE AccessibleBase::accSelect(long selectionFlags, VARIANT Vector<RefPtr<AccessibilityObject> > selectedChildren(1); selectedChildren[0] = childObject; static_cast<AccessibilityListBox*>(parentObject)->setSelectedChildren(selectedChildren); - } else if (parentObject->isMenuListPopup()) + } else { // any element may be selectable by virtue of it having the aria-selected property + ASSERT(!parentObject->isMultiSelectable()); childObject->setSelected(true); - else - return E_INVALIDARG; + } } - // MSDN says that ADD, REMOVE, and EXTENDSELECTION are invalid for + // MSDN says that ADD, REMOVE, and EXTENDSELECTION with no other flags are invalid for // single-select. - if (!parentObject->isMultiSelectable()) + const long allSELFLAGs = SELFLAG_TAKEFOCUS | SELFLAG_TAKESELECTION | SELFLAG_EXTENDSELECTION | SELFLAG_ADDSELECTION | SELFLAG_REMOVESELECTION; + if (!parentObject->isMultiSelectable() + && (((selectionFlags & allSELFLAGs) == SELFLAG_ADDSELECTION) + || ((selectionFlags & allSELFLAGs) == SELFLAG_REMOVESELECTION) + || ((selectionFlags & allSELFLAGs) == SELFLAG_EXTENDSELECTION))) return E_INVALIDARG; if (selectionFlags & SELFLAG_ADDSELECTION) diff --git a/WebKit/win/ChangeLog b/WebKit/win/ChangeLog index 36d3144..feb22a1 100644 --- a/WebKit/win/ChangeLog +++ b/WebKit/win/ChangeLog @@ -1,3 +1,113 @@ +2010-02-10 Jesus Sanchez-Palencia <jesus.palencia@openbossa.org> + + Reviewed by Kenneth Rohde Christiansen. + + Support frameset flattening + https://bugs.webkit.org/show_bug.cgi?id=32717 + + Add support for enabling/disabling FrameSet Flattening on the Windows port. + + * Interfaces/IWebPreferencesPrivate.idl: + * WebPreferenceKeysPrivate.h: + * WebPreferences.cpp: + (WebPreferences::initializeDefaultSettings): + (WebPreferences::isFrameSetFlatteningEnabled): + (WebPreferences::setFrameSetFlatteningEnabled): + * WebPreferences.h: + * WebView.cpp: + (WebView::notifyPreferencesChanged): + +2010-02-10 Adam Roben <aroben@apple.com> + + Remove unnecessary #include of shfolder.h + + shfolder.h has been deprecated in newer versions of the Windows SDK. + + Fixes <http://webkit.org/b/34803> WebPreferences.cpp fails to compile + under VS2010 RC due to #include of shfolder.h. + + Reviewed by Darin Adler. + + * WebPreferences.cpp: Removed #include. + +2010-02-08 Charlie Reis <creis@chromium.org> + + Reviewed by Darin Adler. + + onbeforeunload not called at window close + frame or iframe focused + https://bugs.webkit.org/show_bug.cgi?id=27481 + + Chromium and WebKit on Windows will now fire beforeunload handlers + even if an inner frame is focused. + + Layout tests aren't able to test this bug, since it requires closing + the actual browser window, not calling window.close(). Instead, + test with WebCore/manual-tests/onbeforeunload-focused-iframe.html. + + * WebView.cpp: + (WebView::shouldClose): + +2010-02-08 Brent Fulgham <bfulgham@webkit.org> + + Reviewed by Adam Roben. + + Include header position in World Transform used for plugin positioning. + https://bugs.webkit.org/show_bug.cgi?id=34709 + + * WebFrame.cpp: + (WebFrame::spoolPage): Correct WinCairo plugin print positioning to + account for header size. Existing code ignored this, causing + plugins to overlay other elements. + +2010-02-04 Alice Liu <alice.liu@apple.com> + + Reviewed by Jon Honeycutt. + + https://bugs.webkit.org/show_bug.cgi?id=34612 " MSAA: accSelect returns error + codes for most elements that arent listbox or menupopup related" + <rdar://problem/7436861> + + * AccessibleBase.cpp: + (AccessibleBase::accSelect): + - Stop sending E_INVALIDARG for elements that request TAKE_SELECTION that + aren't beneath listboxes or menupopups. This was too restrictive since + any element can be selectable. + - Correct the misinterpretation of MSDN's stipulation of situations involving + adding, removing, and extending selection on single-select elements + +2010-02-04 Brent Fulgham <bfulgham@webkit.org> + + Reviewed by Adam Roben. + + Properly handle margin settings when printing Plugins in WinCairo. + https://bugs.webkit.org/show_bug.cgi?id=34613 + + * WebFrame.cpp: + (WebFrame::spoolPage): Adjust the GraphicsContext passed to the + paintContents method so that the World Transform is properly + positioned to account for margin settings at the time that + PluginViewWin.cpp processes the drawing operations. + +2010-02-04 Brent Fulgham <bfulgham@webkit.org> + + Reviewed by Adam Roben. + + Properly handle margin settings in WinCairo. + https://bugs.webkit.org/show_bug.cgi?id=34545 + + * WebFrame.cpp: + (scaleFactor): Require the margin information as an input + parameter, and use them when computing the scaling factor. + (WebFrame::drawHeader): Pass margin size to scaleFactor. + (WebFrame::drawFooter): Pass margin size to scaleFactor. + (WebFrame::spoolPage): + 1. Pass margin size to scaleFactor. + 2. Recognize that the return value of printerMarginRect is + already in device units, and therefore scale it so that + the Cairo drawing is correct. + 3. Remove scaling call for margins in GDI code, as it is + already in scaled units. + 2010-02-03 Brian Weinstein <bweinstein@apple.com> Reviewed by Steve Falkenburg. diff --git a/WebKit/win/Interfaces/IWebPreferencesPrivate.idl b/WebKit/win/Interfaces/IWebPreferencesPrivate.idl index 1293fb8..613a53d 100644 --- a/WebKit/win/Interfaces/IWebPreferencesPrivate.idl +++ b/WebKit/win/Interfaces/IWebPreferencesPrivate.idl @@ -79,6 +79,9 @@ interface IWebPreferencesPrivate : IUnknown HRESULT isXSSAuditorEnabled([out, retval] BOOL *enabled); HRESULT setXSSAuditorEnabled([in] BOOL enabled); + HRESULT isFrameSetFlatteningEnabled([out, retval] BOOL *enabled); + HRESULT setFrameSetFlatteningEnabled([in] BOOL enabled); + HRESULT experimentalNotificationsEnabled([out, retval] BOOL *enabled); HRESULT setExperimentalNotificationsEnabled([in] BOOL enabled); diff --git a/WebKit/win/Interfaces/WebKit.idl b/WebKit/win/Interfaces/WebKit.idl index 94dc697..3cd748c 100644 --- a/WebKit/win/Interfaces/WebKit.idl +++ b/WebKit/win/Interfaces/WebKit.idl @@ -294,4 +294,3 @@ library WebKit [default] interface IWebGeolocationPosition; } } - diff --git a/WebKit/win/WebFrame.cpp b/WebKit/win/WebFrame.cpp index c0c1601..b7ad014 100644 --- a/WebKit/win/WebFrame.cpp +++ b/WebKit/win/WebFrame.cpp @@ -2018,11 +2018,17 @@ void WebFrame::spoolPage(PlatformGraphicsContext* pctx, GraphicsContext* spoolCt CGContextRestoreGState(pctx); } #elif PLATFORM(CAIRO) -static float scaleFactor(HDC printDC, const IntRect& pageRect) +static float scaleFactor(HDC printDC, const IntRect& marginRect, const IntRect& pageRect) { const IntRect& printRect = printerRect(printDC); - float scale = static_cast<float>(printRect.width()) / static_cast<float>(pageRect.width()); + IntRect adjustedRect = IntRect( + printRect.x() + marginRect.x(), + printRect.y() + marginRect.y(), + printRect.width() - marginRect.x() - marginRect.right(), + printRect.height() - marginRect.y() - marginRect.bottom()); + + float scale = static_cast<float>(adjustedRect.width()) / static_cast<float>(pageRect.width()); if (!scale) scale = 1.0; @@ -2038,8 +2044,9 @@ static HDC hdcFromContext(PlatformGraphicsContext* pctx) void WebFrame::drawHeader(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, float headerHeight) { HDC hdc = hdcFromContext(pctx); + const IntRect& marginRect = printerMarginRect(hdc); - const float scale = scaleFactor(hdc, pageRect); + const float scale = scaleFactor(hdc, marginRect, pageRect); int x = static_cast<int>(scale * pageRect.x()); int y = 0; RECT headerRect = {x, y, x + static_cast<int>(scale * pageRect.width()), y + static_cast<int>(scale * headerHeight)}; @@ -2050,8 +2057,9 @@ void WebFrame::drawHeader(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, con void WebFrame::drawFooter(PlatformGraphicsContext* pctx, IWebUIDelegate* ui, const IntRect& pageRect, UINT page, UINT pageCount, float headerHeight, float footerHeight) { HDC hdc = hdcFromContext(pctx); + const IntRect& marginRect = printerMarginRect(hdc); - const float scale = scaleFactor(hdc, pageRect); + const float scale = scaleFactor(hdc, marginRect, pageRect); int x = static_cast<int>(scale * pageRect.x()); int y = static_cast<int>(scale * max(static_cast<int>(headerHeight) + pageRect.height(), m_pageHeight-static_cast<int>(footerHeight))); RECT footerRect = {x, y, x + static_cast<int>(scale * pageRect.width()), y + static_cast<int>(scale * footerHeight)}; @@ -2064,24 +2072,34 @@ void WebFrame::spoolPage(PlatformGraphicsContext* pctx, GraphicsContext* spoolCt Frame* coreFrame = core(this); const IntRect& pageRect = m_pageRects[page]; - IntRect marginRect = printerMarginRect(printDC); + const IntRect& marginRect = printerMarginRect(printDC); cairo_save(pctx); - float scale = scaleFactor(printDC, pageRect); + spoolCtx->save(); + float scale = scaleFactor(printDC, marginRect, pageRect); cairo_scale(pctx, scale, scale); - cairo_translate(pctx, -pageRect.x() + marginRect.x(), -pageRect.y() + marginRect.y() + headerHeight); + IntRect cairoMarginRect (marginRect); + cairoMarginRect.scale (1 / scale); + + // Modify Cairo and GDI World Transform to account for margin in the + // subsequent WebKit-controlled 'paintContents' drawing operations: + spoolCtx->translate(cairoMarginRect.x(), cairoMarginRect.y() + headerHeight); + + // Modify Cairo (only) to account for page position. + cairo_translate(pctx, -pageRect.x(), -pageRect.y()); coreFrame->view()->paintContents(spoolCtx, pageRect); - cairo_translate(pctx, pageRect.x() - marginRect.x(), pageRect.y() - marginRect.y() - headerHeight); + cairo_translate(pctx, pageRect.x(), pageRect.y()); XFORM originalWorld; ::GetWorldTransform(printDC, &originalWorld); - // Position world transform to account for margin + // Position GDI world transform to account for margin in GDI-only + // header/footer calls XFORM newWorld = originalWorld; - newWorld.eDx = scale * marginRect.x(); - newWorld.eDy = scale * marginRect.y(); + newWorld.eDx = marginRect.x(); + newWorld.eDy = marginRect.y(); ::SetWorldTransform(printDC, &newWorld); @@ -2095,6 +2113,7 @@ void WebFrame::spoolPage(PlatformGraphicsContext* pctx, GraphicsContext* spoolCt cairo_show_page(pctx); ASSERT(!cairo_status(pctx)); + spoolCtx->restore(); cairo_restore(pctx); } #endif diff --git a/WebKit/win/WebPreferenceKeysPrivate.h b/WebKit/win/WebPreferenceKeysPrivate.h index 3b4197c..9f768f2 100644 --- a/WebKit/win/WebPreferenceKeysPrivate.h +++ b/WebKit/win/WebPreferenceKeysPrivate.h @@ -130,6 +130,8 @@ #define WebKitPluginAllowedRunTimePreferenceKey "WebKitPluginAllowedRunTime" +#define WebKitFrameSetFlatteningEnabledPreferenceKey "WebKitFrameSetFlatteningEnabled" + #define WebKitAcceleratedCompositingEnabledPreferenceKey "WebKitAcceleratedCompositingEnabled" #define WebKitCustomDragCursorsEnabledPreferenceKey "WebKitCustomDragCursorsEnabled" diff --git a/WebKit/win/WebPreferences.cpp b/WebKit/win/WebPreferences.cpp index c23f236..13c2ac4 100644 --- a/WebKit/win/WebPreferences.cpp +++ b/WebKit/win/WebPreferences.cpp @@ -43,7 +43,6 @@ #include <CoreFoundation/CoreFoundation.h> #include <limits> #include <shlobj.h> -#include <shfolder.h> #include <tchar.h> #include <wtf/HashMap.h> #include <wtf/OwnArrayPtr.h> @@ -207,6 +206,7 @@ void WebPreferences::initializeDefaultSettings() CFDictionaryAddValue(defaults, CFSTR(WebKitWebSecurityEnabledPreferenceKey), kCFBooleanTrue); CFDictionaryAddValue(defaults, CFSTR(WebKitAllowUniversalAccessFromFileURLsPreferenceKey), kCFBooleanFalse); CFDictionaryAddValue(defaults, CFSTR(WebKitXSSAuditorEnabledPreferenceKey), kCFBooleanTrue); + CFDictionaryAddValue(defaults, CFSTR(WebKitFrameSetFlatteningEnabledPreferenceKey), kCFBooleanFalse); CFDictionaryAddValue(defaults, CFSTR(WebKitJavaScriptCanOpenWindowsAutomaticallyPreferenceKey), kCFBooleanTrue); CFDictionaryAddValue(defaults, CFSTR(WebKitPluginsEnabledPreferenceKey), kCFBooleanTrue); CFDictionaryAddValue(defaults, CFSTR(WebKitDatabasesEnabledPreferenceKey), kCFBooleanTrue); @@ -806,6 +806,20 @@ HRESULT STDMETHODCALLTYPE WebPreferences::setXSSAuditorEnabled( return S_OK; } +HRESULT STDMETHODCALLTYPE WebPreferences::isFrameSetFlatteningEnabled( + /* [retval][out] */ BOOL* enabled) +{ + *enabled = boolValueForKey(CFSTR(WebKitFrameSetFlatteningEnabledPreferenceKey)); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE WebPreferences::setFrameSetFlatteningEnabled( + /* [in] */ BOOL enabled) +{ + setBoolValue(CFSTR(WebKitFrameSetFlatteningEnabledPreferenceKey), enabled); + return S_OK; +} + HRESULT STDMETHODCALLTYPE WebPreferences::javaScriptCanOpenWindowsAutomatically( /* [retval][out] */ BOOL* enabled) { diff --git a/WebKit/win/WebPreferences.h b/WebKit/win/WebPreferences.h index 1631e78..9209b7d 100644 --- a/WebKit/win/WebPreferences.h +++ b/WebKit/win/WebPreferences.h @@ -380,6 +380,12 @@ public: virtual HRESULT STDMETHODCALLTYPE pluginAllowedRunTime( /* [retval][out] */ UINT* allowedRunTime); + virtual HRESULT STDMETHODCALLTYPE isFrameSetFlatteningEnabled( + /* [retval][out] */ BOOL* enabled); + + virtual HRESULT STDMETHODCALLTYPE setFrameSetFlatteningEnabled( + /* [in] */ BOOL enabled); + virtual HRESULT STDMETHODCALLTYPE setPreferenceForTest( /* [in] */ BSTR key, /* [in] */ BSTR value); diff --git a/WebKit/win/WebView.cpp b/WebKit/win/WebView.cpp index 6144532..880c75f 100644 --- a/WebKit/win/WebView.cpp +++ b/WebKit/win/WebView.cpp @@ -4645,6 +4645,11 @@ HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification) return hr; settings->setPluginAllowedRunTime(runTime); + hr = prefsPrivate->isFrameSetFlatteningEnabled(&enabled); + if (FAILED(hr)) + return hr; + settings->setFrameSetFlatteningEnabled(enabled); + #if USE(ACCELERATED_COMPOSITING) hr = prefsPrivate->acceleratedCompositingEnabled(&enabled); if (FAILED(hr)) @@ -4653,7 +4658,7 @@ HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification) #endif #if ENABLE(3D_CANVAS) - settings->setExperimentalWebGLEnabled(true); + settings->setWebGLEnabled(true); #endif // ENABLE(3D_CANVAS) if (!m_closeWindowTimer.isActive()) @@ -5060,7 +5065,7 @@ HRESULT STDMETHODCALLTYPE WebView::shouldClose( } *result = TRUE; - if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) + if (Frame* frame = m_page->mainFrame()) *result = frame->shouldClose() ? TRUE : FALSE; return S_OK; } diff --git a/WebKit/wx/ChangeLog b/WebKit/wx/ChangeLog index 26d14d6..05efbd2 100644 --- a/WebKit/wx/ChangeLog +++ b/WebKit/wx/ChangeLog @@ -1,3 +1,20 @@ +2010-02-04 Kevin Ollivier <kevino@theolliviers.com> + + Build fix after changes in r54345. + + * WebView.cpp: + (wxWebView::OnKeyEvents): + +2010-02-04 Dan Bernstein <mitz@apple.com> + + Reviewed by Simon Fraser. + + REGRESSION (r53718): When scrolling a tall window by page, the overlap between pages is too big + https://bugs.webkit.org/show_bug.cgi?id=34371 + + * WebView.cpp: + (wxWebView::OnKeyEvents): Use Scrollbar method instead of constant. + 2010-02-03 Kevin Watters <kevinwatters@gmail.com> Reviewed by Kevin Ollivier. diff --git a/WebKit/wx/WebView.cpp b/WebKit/wx/WebView.cpp index 5fdae83..c448bbf 100644 --- a/WebKit/wx/WebView.cpp +++ b/WebKit/wx/WebView.cpp @@ -797,19 +797,19 @@ void wxWebView::OnKeyEvents(wxKeyEvent& event) break; case WXK_LEFT: case WXK_NUMPAD_LEFT: - frame->view()->scrollBy(WebCore::IntSize(-WebCore::cScrollbarPixelsPerLineStep, 0)); + frame->view()->scrollBy(WebCore::IntSize(-WebCore::Scrollbar::pixelsPerLineStep(), 0)); return; case WXK_UP: case WXK_NUMPAD_UP: - frame->view()->scrollBy(WebCore::IntSize(0, -WebCore::cScrollbarPixelsPerLineStep)); + frame->view()->scrollBy(WebCore::IntSize(0, -WebCore::Scrollbar::pixelsPerLineStep())); return; case WXK_RIGHT: case WXK_NUMPAD_RIGHT: - frame->view()->scrollBy(WebCore::IntSize(WebCore::cScrollbarPixelsPerLineStep, 0)); + frame->view()->scrollBy(WebCore::IntSize(WebCore::Scrollbar::pixelsPerLineStep(), 0)); return; case WXK_DOWN: case WXK_NUMPAD_DOWN: - frame->view()->scrollBy(WebCore::IntSize(0, WebCore::cScrollbarPixelsPerLineStep)); + frame->view()->scrollBy(WebCore::IntSize(0, WebCore::Scrollbar::pixelsPerLineStep())); return; case WXK_END: case WXK_NUMPAD_END: @@ -821,11 +821,11 @@ void wxWebView::OnKeyEvents(wxKeyEvent& event) return; case WXK_PAGEUP: case WXK_NUMPAD_PAGEUP: - frame->view()->scrollBy(WebCore::IntSize(0, -frame->view()->visibleHeight() * WebCore::cFractionToStepWhenPaging)); + frame->view()->scrollBy(WebCore::IntSize(0, -frame->view()->visibleHeight() * WebCore::Scrollbar::minFractionToStepWhenPaging())); return; case WXK_PAGEDOWN: case WXK_NUMPAD_PAGEDOWN: - frame->view()->scrollBy(WebCore::IntSize(0, frame->view()->visibleHeight() * WebCore::cFractionToStepWhenPaging)); + frame->view()->scrollBy(WebCore::IntSize(0, frame->view()->visibleHeight() * WebCore::Scrollbar::minFractionToStepWhenPaging())); return; //These we don't want turning into char events, stuff 'em case WXK_ESCAPE: |