summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/test/page_cycler/page_cycler_test.cc14
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Info.plist180
-rwxr-xr-xchrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/MacOS/Chromiumbin0 -> 27016444 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/PkgInfo1
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/aliasCursor.pngbin0 -> 752 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/app.icnsbin0 -> 199039 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/back.pdfbin0 -> 2214 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/cellCursor.pngbin0 -> 183 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/chrome.pakbin0 -> 614790 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/close_bar.pdfbin0 -> 3726 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/close_bar_h.pdfbin0 -> 3765 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/close_bar_p.pdfbin0 -> 3765 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/contextMenuCursor.pngbin0 -> 523 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/copyCursor.pngbin0 -> 1652 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/crossHairCursor.pngbin0 -> 319 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/eastResizeCursor.pngbin0 -> 123 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/eastWestResizeCursor.pngbin0 -> 126 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/About.nibbin0 -> 7624 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/BrowserWindow.nibbin0 -> 3877 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/ClearBrowsingData.nibbin0 -> 11153 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/FindBar.nibbin0 -> 5349 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/FirstRunDialog.nibbin0 -> 10048 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/MainMenu.nibbin0 -> 25272 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/Preferences.nibbin0 -> 59583 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/SaveAccessoryView.nibbin0 -> 3596 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/TabContents.nibbin0 -> 3846 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/TabView.nibbin0 -> 5196 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/Toolbar.nibbin0 -> 6237 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/locale.pakbin0 -> 81838 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/forward.pdfbin0 -> 2214 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/go.pdfbin0 -> 2261 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/grow_box.pngbin0 -> 237 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/helpCursor.pngbin0 -> 239 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/BottomUpProfileDataGridTree.js252
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Breakpoint.js54
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/BreakpointsSidebarPane.js85
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/CallStackSidebarPane.js110
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Console.js942
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DataGrid.js885
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Database.js95
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DatabaseQueryView.js199
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DatabaseTableView.js96
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DatabasesPanel.js526
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DebuggerConsole.js173
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DebuggerIPC.js109
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DebuggerPanel.js201
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DebuggerShell.js1458
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ElementsPanel.js1206
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ElementsTreeOutline.js626
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/FontView.js104
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ImageView.js74
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/back.pngbin0 -> 4205 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/checker.pngbin0 -> 3471 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/clearConsoleButtons.pngbin0 -> 5224 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/closeButtons.pngbin0 -> 4355 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/consoleButtons.pngbin0 -> 5197 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/database.pngbin0 -> 2329 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/databaseTable.pngbin0 -> 4325 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/databasesIcon.pngbin0 -> 7148 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerContinue.pngbin0 -> 4190 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerPause.pngbin0 -> 4081 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerStepInto.pngbin0 -> 4282 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerStepOut.pngbin0 -> 4271 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerStepOver.pngbin0 -> 4366 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDown.pngbin0 -> 3919 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDownBlack.pngbin0 -> 3802 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDownWhite.pngbin0 -> 3820 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRight.pngbin0 -> 3898 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightBlack.pngbin0 -> 3807 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDown.pngbin0 -> 3953 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDownBlack.pngbin0 -> 3816 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDownWhite.pngbin0 -> 3838 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightWhite.pngbin0 -> 3818 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/dockButtons.pngbin0 -> 1274 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/elementsIcon.pngbin0 -> 6639 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/enableButtons.pngbin0 -> 5543 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/errorIcon.pngbin0 -> 4337 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/errorMediumIcon.pngbin0 -> 4059 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/excludeButtons.pngbin0 -> 4562 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/focusButtons.pngbin0 -> 4919 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/forward.pngbin0 -> 4202 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/glossyHeader.pngbin0 -> 3720 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/glossyHeaderPressed.pngbin0 -> 3721 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/glossyHeaderSelected.pngbin0 -> 3738 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/glossyHeaderSelectedPressed.pngbin0 -> 3739 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/goArrow.pngbin0 -> 3591 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/graphLabelCalloutLeft.pngbin0 -> 3790 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/graphLabelCalloutRight.pngbin0 -> 3789 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/largerResourcesButtons.pngbin0 -> 1596 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/nodeSearchButtons.pngbin0 -> 5708 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/paneBottomGrow.pngbin0 -> 3457 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/paneBottomGrowActive.pngbin0 -> 3457 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/paneGrowHandleLine.pngbin0 -> 3443 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/pauseOnExceptionButtons.pngbin0 -> 2305 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/percentButtons.pngbin0 -> 5771 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profileGroupIcon.pngbin0 -> 5126 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profileIcon.pngbin0 -> 4953 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profileSmallIcon.pngbin0 -> 579 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profilesIcon.pngbin0 -> 4158 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profilesSilhouette.pngbin0 -> 48600 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/radioDot.pngbin0 -> 235 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/recordButtons.pngbin0 -> 5716 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/reloadButtons.pngbin0 -> 4544 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourceCSSIcon.pngbin0 -> 1066 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourceDocumentIcon.pngbin0 -> 4959 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourceDocumentIconSmall.pngbin0 -> 787 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourceJSIcon.pngbin0 -> 879 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcePlainIcon.pngbin0 -> 4321 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcePlainIconSmall.pngbin0 -> 731 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcesIcon.pngbin0 -> 6431 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcesSizeGraphIcon.pngbin0 -> 5606 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcesTimeGraphIcon.pngbin0 -> 5743 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/scriptsIcon.pngbin0 -> 7428 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/scriptsSilhouette.pngbin0 -> 49028 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/searchSmallBlue.pngbin0 -> 3968 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/searchSmallBrightBlue.pngbin0 -> 3966 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/searchSmallGray.pngbin0 -> 3936 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/searchSmallWhite.pngbin0 -> 3844 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segment.pngbin0 -> 4349 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentEnd.pngbin0 -> 4070 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentHover.pngbin0 -> 4310 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentHoverEnd.pngbin0 -> 4074 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentSelected.pngbin0 -> 4302 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentSelectedEnd.pngbin0 -> 4070 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/splitviewDimple.pngbin0 -> 216 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/splitviewDividerBackground.pngbin0 -> 149 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarBackground.pngbin0 -> 4024 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarBottomBackground.pngbin0 -> 4021 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarButtons.pngbin0 -> 4175 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarMenuButton.pngbin0 -> 4293 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarMenuButtonSelected.pngbin0 -> 4291 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarResizerHorizontal.pngbin0 -> 4026 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarResizerVertical.pngbin0 -> 4036 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillBlue.pngbin0 -> 3450 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillGray.pngbin0 -> 3392 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillGreen.pngbin0 -> 3452 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillOrange.pngbin0 -> 3452 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillPurple.pngbin0 -> 3453 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillRed.pngbin0 -> 3460 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillYellow.pngbin0 -> 3444 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillBlue.pngbin0 -> 3346 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillGray.pngbin0 -> 3297 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillGreen.pngbin0 -> 3350 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillOrange.pngbin0 -> 3352 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillPurple.pngbin0 -> 3353 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillRed.pngbin0 -> 3343 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillYellow.pngbin0 -> 3336 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/tipBalloon.pngbin0 -> 3689 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/tipBalloonBottom.pngbin0 -> 3139 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/tipIcon.pngbin0 -> 1212 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/tipIconPressed.pngbin0 -> 1224 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/toolbarItemSelected.pngbin0 -> 4197 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeDownTriangleBlack.pngbin0 -> 3570 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeDownTriangleWhite.pngbin0 -> 3531 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeRightTriangleBlack.pngbin0 -> 3561 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeRightTriangleWhite.pngbin0 -> 3535 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeUpTriangleBlack.pngbin0 -> 3584 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeUpTriangleWhite.pngbin0 -> 3558 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/userInputIcon.pngbin0 -> 777 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/userInputPreviousIcon.pngbin0 -> 765 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/warningIcon.pngbin0 -> 4244 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/warningMediumIcon.pngbin0 -> 3833 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/warningsErrors.pngbin0 -> 5192 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/MetricsSidebarPane.js195
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Object.js82
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ObjectPropertiesSection.js276
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Panel.js273
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/PanelEnablerView.js97
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Placard.js106
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ProfileDataGridTree.js398
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ProfileView.js580
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ProfilesPanel.js502
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/PropertiesSection.js145
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/PropertiesSidebarPane.js54
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Resource.js625
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ResourceCategory.js68
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ResourceView.js140
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ResourcesPanel.js1706
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ScopeChainSidebarPane.js156
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Script.js37
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ScriptView.js103
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ScriptsPanel.js854
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/SidebarPane.js125
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/SidebarTreeElement.js201
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/SourceFrame.js730
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/SourceView.js308
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/StylesSidebarPane.js927
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/TextPrompt.js312
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/TopDownProfileDataGridTree.js111
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/View.js74
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/base.js1015
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/codemap.js230
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/consarray.js93
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/csvparser.js98
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/debugger.css35
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/debugger.html31
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/debugger_agent.js1185
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/devtools.html126
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/devtools.js896
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/devtools_callback.js57
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/devtools_host_stub.js341
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/dom_agent.js1032
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inject.js463
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector.css3104
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector.html97
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector.js1381
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector_controller.js430
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector_controller_impl.js203
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/profile.js605
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/profile_view.js224
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/profiler_processor.js395
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/splaytree.js322
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/tests.js210
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/treeoutline.js846
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/utilities.js1136
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/linkCursor.pngbin0 -> 341 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/missingImage.pngbin0 -> 411 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/moveCursor.pngbin0 -> 175 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/nav.pdfbin0 -> 2743 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/newtab.pdfbin0 -> 3758 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/noDropCursor.pngbin0 -> 1455 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/noneCursor.pngbin0 -> 90 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northEastResizeCursor.pngbin0 -> 209 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northEastSouthWestResizeCursor.pngbin0 -> 212 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northResizeCursor.pngbin0 -> 125 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northSouthResizeCursor.pngbin0 -> 144 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northWestResizeCursor.pngbin0 -> 174 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northWestSouthEastResizeCursor.pngbin0 -> 193 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/notAllowedCursor.pngbin0 -> 1101 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_globe.pngbin0 -> 536 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_history.pngbin0 -> 400 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_more.pngbin0 -> 320 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_search.pngbin0 -> 340 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_star.pngbin0 -> 489 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/progressCursor.pngbin0 -> 1791 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/reload.pdfbin0 -> 2223 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/renderer.sb28
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/sadtab.pngbin0 -> 275 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/southEastResizeCursor.pngbin0 -> 166 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/southResizeCursor.pngbin0 -> 128 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/southWestResizeCursor.pngbin0 -> 177 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/star.pdfbin0 -> 2513 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/starred.pdfbin0 -> 2801 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/stop.pdfbin0 -> 2219 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/theme.pakbin0 -> 339158 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/throbber.pngbin0 -> 4614 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/throbber_waiting.pngbin0 -> 16464 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/verticalTextCursor.pngbin0 -> 120 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/waitCursor.pngbin0 -> 125 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/westResizeCursor.pngbin0 -> 122 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/zoomInCursor.pngbin0 -> 199 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/zoomOutCursor.pngbin0 -> 182 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Info.plist194
-rwxr-xr-xchrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/MacOS/Google Chromebin0 -> 27055616 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/PkgInfo1
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/aliasCursor.pngbin0 -> 752 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/app.icnsbin0 -> 114493 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/back.pdfbin0 -> 2214 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/cellCursor.pngbin0 -> 183 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/chrome.pakbin0 -> 636162 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/close_bar.pdfbin0 -> 3726 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/close_bar_h.pdfbin0 -> 3765 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/close_bar_p.pdfbin0 -> 3765 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/contextMenuCursor.pngbin0 -> 523 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/copyCursor.pngbin0 -> 1652 bytes
-rwxr-xr-xchrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_inspectorbin0 -> 53044 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Info.plist32
-rwxr-xr-xchrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/MacOS/crash_report_senderbin0 -> 48108 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/PkgInfo1
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/Breakpad.nib/classes.nib57
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/Breakpad.nib/info.nib20
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/Breakpad.nib/keyedobjects.nibbin0 -> 13747 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/English.lproj/Localizable.stringsbin0 -> 1488 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/crash_report_sender.icnsbin0 -> 170816 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crossHairCursor.pngbin0 -> 319 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/eastResizeCursor.pngbin0 -> 123 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/eastWestResizeCursor.pngbin0 -> 126 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/About.nibbin0 -> 7624 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/BrowserWindow.nibbin0 -> 3877 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/ClearBrowsingData.nibbin0 -> 11153 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/FindBar.nibbin0 -> 5349 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/FirstRunDialog.nibbin0 -> 10048 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/MainMenu.nibbin0 -> 25288 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/Preferences.nibbin0 -> 59559 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/SaveAccessoryView.nibbin0 -> 3596 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/TabContents.nibbin0 -> 3846 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/TabView.nibbin0 -> 5196 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/Toolbar.nibbin0 -> 6237 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/locale.pakbin0 -> 105892 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/forward.pdfbin0 -> 2214 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/go.pdfbin0 -> 2261 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/grow_box.pngbin0 -> 237 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/helpCursor.pngbin0 -> 239 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/BottomUpProfileDataGridTree.js252
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Breakpoint.js54
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/BreakpointsSidebarPane.js85
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/CallStackSidebarPane.js110
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Console.js942
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DataGrid.js885
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Database.js95
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DatabaseQueryView.js199
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DatabaseTableView.js96
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DatabasesPanel.js526
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DebuggerConsole.js173
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DebuggerIPC.js109
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DebuggerPanel.js201
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DebuggerShell.js1458
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ElementsPanel.js1206
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ElementsTreeOutline.js626
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/FontView.js104
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ImageView.js74
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/back.pngbin0 -> 4205 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/checker.pngbin0 -> 3471 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/clearConsoleButtons.pngbin0 -> 5224 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/closeButtons.pngbin0 -> 4355 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/consoleButtons.pngbin0 -> 5197 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/database.pngbin0 -> 2329 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/databaseTable.pngbin0 -> 4325 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/databasesIcon.pngbin0 -> 7148 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerContinue.pngbin0 -> 4190 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerPause.pngbin0 -> 4081 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerStepInto.pngbin0 -> 4282 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerStepOut.pngbin0 -> 4271 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerStepOver.pngbin0 -> 4366 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDown.pngbin0 -> 3919 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDownBlack.pngbin0 -> 3802 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDownWhite.pngbin0 -> 3820 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRight.pngbin0 -> 3898 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightBlack.pngbin0 -> 3807 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDown.pngbin0 -> 3953 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDownBlack.pngbin0 -> 3816 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDownWhite.pngbin0 -> 3838 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightWhite.pngbin0 -> 3818 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/dockButtons.pngbin0 -> 1274 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/elementsIcon.pngbin0 -> 6639 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/enableButtons.pngbin0 -> 5543 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/errorIcon.pngbin0 -> 4337 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/errorMediumIcon.pngbin0 -> 4059 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/excludeButtons.pngbin0 -> 4562 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/focusButtons.pngbin0 -> 4919 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/forward.pngbin0 -> 4202 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/glossyHeader.pngbin0 -> 3720 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/glossyHeaderPressed.pngbin0 -> 3721 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/glossyHeaderSelected.pngbin0 -> 3738 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/glossyHeaderSelectedPressed.pngbin0 -> 3739 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/goArrow.pngbin0 -> 3591 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/graphLabelCalloutLeft.pngbin0 -> 3790 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/graphLabelCalloutRight.pngbin0 -> 3789 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/largerResourcesButtons.pngbin0 -> 1596 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/nodeSearchButtons.pngbin0 -> 5708 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/paneBottomGrow.pngbin0 -> 3457 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/paneBottomGrowActive.pngbin0 -> 3457 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/paneGrowHandleLine.pngbin0 -> 3443 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/pauseOnExceptionButtons.pngbin0 -> 2305 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/percentButtons.pngbin0 -> 5771 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profileGroupIcon.pngbin0 -> 5126 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profileIcon.pngbin0 -> 4953 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profileSmallIcon.pngbin0 -> 579 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profilesIcon.pngbin0 -> 4158 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profilesSilhouette.pngbin0 -> 48600 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/radioDot.pngbin0 -> 235 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/recordButtons.pngbin0 -> 5716 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/reloadButtons.pngbin0 -> 4544 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourceCSSIcon.pngbin0 -> 1066 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourceDocumentIcon.pngbin0 -> 4959 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourceDocumentIconSmall.pngbin0 -> 787 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourceJSIcon.pngbin0 -> 879 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcePlainIcon.pngbin0 -> 4321 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcePlainIconSmall.pngbin0 -> 731 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcesIcon.pngbin0 -> 6431 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcesSizeGraphIcon.pngbin0 -> 5606 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcesTimeGraphIcon.pngbin0 -> 5743 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/scriptsIcon.pngbin0 -> 7428 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/scriptsSilhouette.pngbin0 -> 49028 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/searchSmallBlue.pngbin0 -> 3968 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/searchSmallBrightBlue.pngbin0 -> 3966 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/searchSmallGray.pngbin0 -> 3936 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/searchSmallWhite.pngbin0 -> 3844 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segment.pngbin0 -> 4349 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentEnd.pngbin0 -> 4070 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentHover.pngbin0 -> 4310 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentHoverEnd.pngbin0 -> 4074 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentSelected.pngbin0 -> 4302 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentSelectedEnd.pngbin0 -> 4070 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/splitviewDimple.pngbin0 -> 216 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/splitviewDividerBackground.pngbin0 -> 149 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarBackground.pngbin0 -> 4024 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarBottomBackground.pngbin0 -> 4021 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarButtons.pngbin0 -> 4175 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarMenuButton.pngbin0 -> 4293 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarMenuButtonSelected.pngbin0 -> 4291 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarResizerHorizontal.pngbin0 -> 4026 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarResizerVertical.pngbin0 -> 4036 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillBlue.pngbin0 -> 3450 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillGray.pngbin0 -> 3392 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillGreen.pngbin0 -> 3452 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillOrange.pngbin0 -> 3452 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillPurple.pngbin0 -> 3453 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillRed.pngbin0 -> 3460 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillYellow.pngbin0 -> 3444 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillBlue.pngbin0 -> 3346 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillGray.pngbin0 -> 3297 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillGreen.pngbin0 -> 3350 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillOrange.pngbin0 -> 3352 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillPurple.pngbin0 -> 3353 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillRed.pngbin0 -> 3343 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillYellow.pngbin0 -> 3336 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/tipBalloon.pngbin0 -> 3689 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/tipBalloonBottom.pngbin0 -> 3139 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/tipIcon.pngbin0 -> 1212 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/tipIconPressed.pngbin0 -> 1224 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/toolbarItemSelected.pngbin0 -> 4197 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeDownTriangleBlack.pngbin0 -> 3570 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeDownTriangleWhite.pngbin0 -> 3531 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeRightTriangleBlack.pngbin0 -> 3561 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeRightTriangleWhite.pngbin0 -> 3535 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeUpTriangleBlack.pngbin0 -> 3584 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeUpTriangleWhite.pngbin0 -> 3558 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/userInputIcon.pngbin0 -> 777 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/userInputPreviousIcon.pngbin0 -> 765 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/warningIcon.pngbin0 -> 4244 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/warningMediumIcon.pngbin0 -> 3833 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/warningsErrors.pngbin0 -> 5192 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/MetricsSidebarPane.js195
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Object.js82
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ObjectPropertiesSection.js276
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Panel.js273
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/PanelEnablerView.js97
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Placard.js106
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ProfileDataGridTree.js398
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ProfileView.js580
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ProfilesPanel.js502
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/PropertiesSection.js145
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/PropertiesSidebarPane.js54
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Resource.js625
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ResourceCategory.js68
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ResourceView.js140
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ResourcesPanel.js1706
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ScopeChainSidebarPane.js156
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Script.js37
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ScriptView.js103
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ScriptsPanel.js854
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/SidebarPane.js125
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/SidebarTreeElement.js201
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/SourceFrame.js730
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/SourceView.js308
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/StylesSidebarPane.js927
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/TextPrompt.js312
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/TopDownProfileDataGridTree.js111
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/View.js74
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/base.js1015
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/codemap.js230
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/consarray.js93
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/csvparser.js98
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/debugger.css35
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/debugger.html31
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/debugger_agent.js1185
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/devtools.html126
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/devtools.js896
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/devtools_callback.js57
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/devtools_host_stub.js341
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/dom_agent.js1032
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inject.js463
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector.css3104
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector.html97
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector.js1381
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector_controller.js430
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector_controller_impl.js203
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/profile.js605
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/profile_view.js224
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/profiler_processor.js395
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/splaytree.js322
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/tests.js210
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/treeoutline.js846
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/utilities.js1136
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/linkCursor.pngbin0 -> 341 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/missingImage.pngbin0 -> 411 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/moveCursor.pngbin0 -> 175 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/nav.pdfbin0 -> 2743 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/newtab.pdfbin0 -> 3758 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/noDropCursor.pngbin0 -> 1455 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/noneCursor.pngbin0 -> 90 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northEastResizeCursor.pngbin0 -> 209 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northEastSouthWestResizeCursor.pngbin0 -> 212 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northResizeCursor.pngbin0 -> 125 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northSouthResizeCursor.pngbin0 -> 144 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northWestResizeCursor.pngbin0 -> 174 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northWestSouthEastResizeCursor.pngbin0 -> 193 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/notAllowedCursor.pngbin0 -> 1101 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_globe.pngbin0 -> 536 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_history.pngbin0 -> 400 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_more.pngbin0 -> 320 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_search.pngbin0 -> 340 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_star.pngbin0 -> 489 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/progressCursor.pngbin0 -> 1791 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/reload.pdfbin0 -> 2223 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/renderer.sb28
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/sadtab.pngbin0 -> 275 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/southEastResizeCursor.pngbin0 -> 166 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/southResizeCursor.pngbin0 -> 128 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/southWestResizeCursor.pngbin0 -> 177 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/star.pdfbin0 -> 2513 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/starred.pdfbin0 -> 2801 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/stop.pdfbin0 -> 2219 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/theme.pakbin0 -> 362899 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/throbber.pngbin0 -> 4614 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/throbber_waiting.pngbin0 -> 16464 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/verticalTextCursor.pngbin0 -> 120 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/waitCursor.pngbin0 -> 125 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/westResizeCursor.pngbin0 -> 122 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/zoomInCursor.pngbin0 -> 199 bytes
-rw-r--r--chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/zoomOutCursor.pngbin0 -> 182 bytes
512 files changed, 62414 insertions, 12 deletions
diff --git a/chrome/test/page_cycler/page_cycler_test.cc b/chrome/test/page_cycler/page_cycler_test.cc
index 34bafe6..9dd89221 100644
--- a/chrome/test/page_cycler/page_cycler_test.cc
+++ b/chrome/test/page_cycler/page_cycler_test.cc
@@ -264,13 +264,11 @@ TEST_F(PageCyclerTest, MozFile) {
RunTest("moz", false);
}
-// TODO(port): Enable PageCyclerReferenceTest when reference build is
-// available for non-windows
-#if !defined(OS_MACOSX)
TEST_F(PageCyclerReferenceTest, MozFile) {
RunTest("moz", false);
}
+#if !defined(OS_MACOSX)
// TODO(nirnimesh): Intl1File, Intl2File, Intl1Http, Intl2Http crash Chromium
// on Mac. Revisit later.
TEST_F(PageCyclerTest, Intl1File) {
@@ -294,32 +292,28 @@ TEST_F(PageCyclerTest, DomFile) {
RunTest("dom", false);
}
-#if !defined(OS_MACOSX)
TEST_F(PageCyclerReferenceTest, DomFile) {
RunTest("dom", false);
}
-#endif
TEST_F(PageCyclerTest, DhtmlFile) {
RunTest("dhtml", false);
}
-#if !defined(OS_MACOSX)
TEST_F(PageCyclerReferenceTest, DhtmlFile) {
RunTest("dhtml", false);
}
-#endif
// http (localhost) tests
TEST_F(PageCyclerTest, MozHttp) {
RunTest("moz", true);
}
-#if !defined(OS_MACOSX)
TEST_F(PageCyclerReferenceTest, MozHttp) {
RunTest("moz", true);
}
+#if !defined(OS_MACOSX)
TEST_F(PageCyclerTest, Intl1Http) {
RunTest("intl1", true);
}
@@ -341,20 +335,16 @@ TEST_F(PageCyclerTest, DomHttp) {
RunTest("dom", true);
}
-#if !defined(OS_MACOSX)
TEST_F(PageCyclerReferenceTest, DomHttp) {
RunTest("dom", true);
}
-#endif
TEST_F(PageCyclerTest, BloatHttp) {
RunTest("bloat", true);
}
-#if !defined(OS_MACOSX)
TEST_F(PageCyclerReferenceTest, BloatHttp) {
RunTest("bloat", true);
}
-#endif
} // namespace
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Info.plist b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Info.plist
new file mode 100644
index 0000000..1a462e5
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Info.plist
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>gif</string>
+ </array>
+ <key>CFBundleTypeMIMETypes</key>
+ <array>
+ <string>image/gif</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>GIF image</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>GIFf</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>html</string>
+ <string>htm</string>
+ </array>
+ <key>CFBundleTypeMIMETypes</key>
+ <array>
+ <string>text/html</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>HTML document</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>HTML</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>js</string>
+ </array>
+ <key>CFBundleTypeMIMETypes</key>
+ <array>
+ <string>application/x-javascript</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>JavaScript script</string>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>jpg</string>
+ <string>jpeg</string>
+ </array>
+ <key>CFBundleTypeMIMETypes</key>
+ <array>
+ <string>image/jpeg</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>JPEG image</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>JPEG</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>txt</string>
+ <string>text</string>
+ </array>
+ <key>CFBundleTypeMIMETypes</key>
+ <array>
+ <string>text/plain</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>Plain text document</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>TEXT</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>png</string>
+ </array>
+ <key>CFBundleTypeMIMETypes</key>
+ <array>
+ <string>image/png</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>PNG image</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>PNGf</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ </dict>
+ </array>
+ <key>CFBundleExecutable</key>
+ <string>Chromium</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Chromium 3.0.189.0, Copyright © 2006-2009 The Chromium Authors. All Rights Reserved.</string>
+ <key>CFBundleIconFile</key>
+ <string>app.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.chromium.Chromium</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>Chromium</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>3.0.189</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleURLTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleURLName</key>
+ <string>Web site URL</string>
+ <key>CFBundleURLSchemes</key>
+ <array>
+ <string>http</string>
+ <string>https</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleURLName</key>
+ <string>FTP site URL</string>
+ <key>CFBundleURLSchemes</key>
+ <array>
+ <string>ftp</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleURLName</key>
+ <string>Local file URL</string>
+ <key>CFBundleURLSchemes</key>
+ <array>
+ <string>file</string>
+ </array>
+ </dict>
+ </array>
+ <key>CFBundleVersion</key>
+ <string>189.0</string>
+ <key>LSFileQuarantineEnabled</key>
+ <true/>
+ <key>LSMinimumSystemVersion</key>
+ <string>10.5.0</string>
+ <key>LSUIElement</key>
+ <string>1</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright © 2006-2009 The Chromium Authors. All Rights Reserved.</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+ <key>SVNRevision</key>
+ <string>18159</string>
+</dict>
+</plist>
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/MacOS/Chromium b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/MacOS/Chromium
new file mode 100755
index 0000000..1b1d5ad
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/MacOS/Chromium
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/PkgInfo b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/PkgInfo
new file mode 100644
index 0000000..bd04210
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/PkgInfo
@@ -0,0 +1 @@
+APPL???? \ No newline at end of file
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/aliasCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/aliasCursor.png
new file mode 100644
index 0000000..d33d7e98
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/aliasCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/app.icns b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/app.icns
new file mode 100644
index 0000000..4b93e5c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/app.icns
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/back.pdf b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/back.pdf
new file mode 100644
index 0000000..a3c64b0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/back.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/cellCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/cellCursor.png
new file mode 100644
index 0000000..5c616c4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/cellCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/chrome.pak b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/chrome.pak
new file mode 100644
index 0000000..b164d23
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/chrome.pak
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/close_bar.pdf b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/close_bar.pdf
new file mode 100644
index 0000000..758a6da
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/close_bar.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/close_bar_h.pdf b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/close_bar_h.pdf
new file mode 100644
index 0000000..059ee5a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/close_bar_h.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/close_bar_p.pdf b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/close_bar_p.pdf
new file mode 100644
index 0000000..6c391a44
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/close_bar_p.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/contextMenuCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/contextMenuCursor.png
new file mode 100644
index 0000000..ae100c7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/contextMenuCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/copyCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/copyCursor.png
new file mode 100644
index 0000000..33be332
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/copyCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/crossHairCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/crossHairCursor.png
new file mode 100644
index 0000000..2823010
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/crossHairCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/eastResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/eastResizeCursor.png
new file mode 100644
index 0000000..9c1592e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/eastResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/eastWestResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/eastWestResizeCursor.png
new file mode 100644
index 0000000..f43202e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/eastWestResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/About.nib b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/About.nib
new file mode 100644
index 0000000..896707e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/About.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/BrowserWindow.nib b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/BrowserWindow.nib
new file mode 100644
index 0000000..e412b2a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/BrowserWindow.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/ClearBrowsingData.nib b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/ClearBrowsingData.nib
new file mode 100644
index 0000000..e01ba42
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/ClearBrowsingData.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/FindBar.nib b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/FindBar.nib
new file mode 100644
index 0000000..4596c0c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/FindBar.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/FirstRunDialog.nib b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/FirstRunDialog.nib
new file mode 100644
index 0000000..7466e3b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/FirstRunDialog.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/MainMenu.nib b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/MainMenu.nib
new file mode 100644
index 0000000..47c98e7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/MainMenu.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/Preferences.nib b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/Preferences.nib
new file mode 100644
index 0000000..0cefa9b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/Preferences.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/SaveAccessoryView.nib b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/SaveAccessoryView.nib
new file mode 100644
index 0000000..cbd6fc9
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/SaveAccessoryView.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/TabContents.nib b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/TabContents.nib
new file mode 100644
index 0000000..f144c52
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/TabContents.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/TabView.nib b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/TabView.nib
new file mode 100644
index 0000000..c8f2e7c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/TabView.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/Toolbar.nib b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/Toolbar.nib
new file mode 100644
index 0000000..1bcd07b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/Toolbar.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/locale.pak b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/locale.pak
new file mode 100644
index 0000000..22ec910
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/en.lproj/locale.pak
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/forward.pdf b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/forward.pdf
new file mode 100644
index 0000000..9a36de0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/forward.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/go.pdf b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/go.pdf
new file mode 100644
index 0000000..31af1f4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/go.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/grow_box.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/grow_box.png
new file mode 100644
index 0000000..8278fec
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/grow_box.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/helpCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/helpCursor.png
new file mode 100644
index 0000000..6828d6a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/helpCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/BottomUpProfileDataGridTree.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/BottomUpProfileDataGridTree.js
new file mode 100644
index 0000000..89b4ddc
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/BottomUpProfileDataGridTree.js
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2009 280 North Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Bottom Up Profiling shows the entire callstack backwards:
+// The root node is a representation of each individual function called, and each child of that node represents
+// a reverse-callstack showing how many of those calls came from it. So, unlike top-down, the statistics in
+// each child still represent the root node. We have to be particularly careful of recursion with this mode
+// because a root node can represent itself AND an ancestor.
+
+WebInspector.BottomUpProfileDataGridTree = function(/*ProfileView*/ aProfileView, /*ProfileNode*/ aProfileNode)
+{
+ WebInspector.ProfileDataGridTree.call(this, aProfileView, aProfileNode);
+
+ // Iterate each node in pre-order.
+ var profileNodeUIDs = 0;
+ var profileNodeGroups = [[], [aProfileNode]];
+ var visitedProfileNodesForCallUID = {};
+
+ this._remainingNodeInfos = [];
+
+ for (var profileNodeGroupIndex = 0; profileNodeGroupIndex < profileNodeGroups.length; ++profileNodeGroupIndex) {
+ var parentProfileNodes = profileNodeGroups[profileNodeGroupIndex];
+ var profileNodes = profileNodeGroups[++profileNodeGroupIndex];
+ var count = profileNodes.length;
+
+ for (var index = 0; index < count; ++index) {
+ var profileNode = profileNodes[index];
+
+ if (!profileNode.UID)
+ profileNode.UID = ++profileNodeUIDs;
+
+ if (profileNode.head && profileNode !== profileNode.head) {
+ // The total time of this ancestor is accounted for if we're in any form of recursive cycle.
+ var visitedNodes = visitedProfileNodesForCallUID[profileNode.callUID];
+ var totalTimeAccountedFor = false;
+
+ if (!visitedNodes) {
+ visitedNodes = {}
+ visitedProfileNodesForCallUID[profileNode.callUID] = visitedNodes;
+ } else {
+ // The total time for this node has already been accounted for iff one of it's parents has already been visited.
+ // We can do this check in this style because we are traversing the tree in pre-order.
+ var parentCount = parentProfileNodes.length;
+ for (var parentIndex = 0; parentIndex < parentCount; ++parentIndex) {
+ if (visitedNodes[parentProfileNodes[parentIndex].UID]) {
+ totalTimeAccountedFor = true;
+ break;
+ }
+ }
+ }
+
+ visitedNodes[profileNode.UID] = true;
+
+ this._remainingNodeInfos.push({ ancestor:profileNode, focusNode:profileNode, totalTimeAccountedFor:totalTimeAccountedFor });
+ }
+
+ var children = profileNode.children;
+ if (children.length) {
+ profileNodeGroups.push(parentProfileNodes.concat([profileNode]))
+ profileNodeGroups.push(children);
+ }
+ }
+ }
+
+ // Populate the top level nodes.
+ WebInspector.BottomUpProfileDataGridNode.prototype._populate.call(this);
+
+ return this;
+}
+
+WebInspector.BottomUpProfileDataGridTree.prototype = {
+ // When focusing, we keep the entire callstack up to this ancestor.
+ focus: function(/*ProfileDataGridNode*/ profileDataGridNode)
+ {
+ if (!profileDataGridNode)
+ return;
+
+ this._save();
+
+ var currentNode = profileDataGridNode;
+ var focusNode = profileDataGridNode;
+
+ while (currentNode.parent && (currentNode instanceof WebInspector.ProfileDataGridNode)) {
+ currentNode._takePropertiesFromProfileDataGridNode(profileDataGridNode);
+
+ focusNode = currentNode;
+ currentNode = currentNode.parent;
+
+ if (currentNode instanceof WebInspector.ProfileDataGridNode)
+ currentNode._keepOnlyChild(focusNode);
+ }
+
+ this.children = [focusNode];
+ this.totalTime = profileDataGridNode.totalTime;
+ },
+
+ exclude: function(/*ProfileDataGridNode*/ profileDataGridNode)
+ {
+ if (!profileDataGridNode)
+ return;
+
+ this._save();
+
+ var excludedCallUID = profileDataGridNode.callUID;
+ var excludedTopLevelChild = this.childrenByCallUID[excludedCallUID];
+
+ // If we have a top level node that is excluded, get rid of it completely (not keeping children),
+ // since bottom up data relies entirely on the root node.
+ if (excludedTopLevelChild)
+ this.children.remove(excludedTopLevelChild);
+
+ var children = this.children;
+ var count = children.length;
+
+ for (var index = 0; index < count; ++index)
+ children[index]._exclude(excludedCallUID);
+
+ if (this.lastComparator)
+ this.sort(this.lastComparator, true);
+ }
+}
+
+WebInspector.BottomUpProfileDataGridTree.prototype.__proto__ = WebInspector.ProfileDataGridTree.prototype;
+
+WebInspector.BottomUpProfileDataGridNode = function(/*ProfileView*/ profileView, /*ProfileNode*/ profileNode, /*BottomUpProfileDataGridTree*/ owningTree)
+{
+ // In bottom up mode, our parents are our children since we display an inverted tree.
+ // However, we don't want to show the very top parent since it is redundant.
+ var hasChildren = !!(profileNode.parent && profileNode.parent.parent);
+
+ WebInspector.ProfileDataGridNode.call(this, profileView, profileNode, owningTree, hasChildren);
+
+ this._remainingNodeInfos = [];
+}
+
+WebInspector.BottomUpProfileDataGridNode.prototype = {
+ _takePropertiesFromProfileDataGridNode: function(/*ProfileDataGridNode*/ profileDataGridNode)
+ {
+ this._save();
+
+ this.selfTime = profileDataGridNode.selfTime;
+ this.totalTime = profileDataGridNode.totalTime;
+ this.numberOfCalls = profileDataGridNode.numberOfCalls;
+ },
+
+ // When focusing, we keep just the members of the callstack.
+ _keepOnlyChild: function(/*ProfileDataGridNode*/ child)
+ {
+ this._save();
+
+ this.removeChildren();
+ this.appendChild(child);
+ },
+
+ _exclude: function(aCallUID)
+ {
+ if (this._remainingNodeInfos)
+ this._populate();
+
+ this._save();
+
+ var children = this.children;
+ var index = this.children.length;
+
+ while (index--)
+ children[index]._exclude(aCallUID);
+
+ var child = this.childrenByCallUID[aCallUID];
+
+ if (child)
+ this._merge(child, true);
+ },
+
+ _merge: function(/*ProfileDataGridNode*/ child, /*Boolean*/ shouldAbsorb)
+ {
+ this.selfTime -= child.selfTime;
+
+ WebInspector.ProfileDataGridNode.prototype._merge.call(this, child, shouldAbsorb);
+ },
+
+ _populate: function(event)
+ {
+ var remainingNodeInfos = this._remainingNodeInfos;
+ var count = remainingNodeInfos.length;
+
+ for (var index = 0; index < count; ++index) {
+ var nodeInfo = remainingNodeInfos[index];
+ var ancestor = nodeInfo.ancestor;
+ var focusNode = nodeInfo.focusNode;
+ var child = this.findChild(ancestor);
+
+ // If we already have this child, then merge the data together.
+ if (child) {
+ var totalTimeAccountedFor = nodeInfo.totalTimeAccountedFor;
+
+ child.selfTime += focusNode.selfTime;
+ child.numberOfCalls += focusNode.numberOfCalls;
+
+ if (!totalTimeAccountedFor)
+ child.totalTime += focusNode.totalTime;
+ } else {
+ // If not, add it as a true ancestor.
+ // In heavy mode, we take our visual identity from ancestor node...
+ var child = new WebInspector.BottomUpProfileDataGridNode(this.profileView, ancestor, this.tree);
+
+ if (ancestor !== focusNode) {
+ // but the actual statistics from the "root" node (bottom of the callstack).
+ child.selfTime = focusNode.selfTime;
+ child.totalTime = focusNode.totalTime;
+ child.numberOfCalls = focusNode.numberOfCalls;
+ }
+
+ this.appendChild(child);
+ }
+
+ var parent = ancestor.parent;
+ if (parent && parent.parent) {
+ nodeInfo.ancestor = parent;
+ child._remainingNodeInfos.push(nodeInfo);
+ }
+ }
+
+ delete this._remainingNodeInfos;
+
+ if (this.removeEventListener)
+ this.removeEventListener("populate", this._populate, this);
+ }
+}
+
+WebInspector.BottomUpProfileDataGridNode.prototype.__proto__ = WebInspector.ProfileDataGridNode.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Breakpoint.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Breakpoint.js
new file mode 100644
index 0000000..8611cf5
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Breakpoint.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Breakpoint = function(url, line, sourceID)
+{
+ this.url = url;
+ this.line = line;
+ this.sourceID = sourceID;
+ this._enabled = true;
+}
+
+WebInspector.Breakpoint.prototype = {
+ get enabled()
+ {
+ return this._enabled;
+ },
+
+ set enabled(x)
+ {
+ if (this._enabled === x)
+ return;
+
+ this._enabled = x;
+
+ if (this._enabled)
+ this.dispatchEventToListeners("enabled");
+ else
+ this.dispatchEventToListeners("disabled");
+ }
+}
+
+WebInspector.Breakpoint.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/BreakpointsSidebarPane.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/BreakpointsSidebarPane.js
new file mode 100644
index 0000000..2b8f3cd
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/BreakpointsSidebarPane.js
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.BreakpointsSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Breakpoints"));
+
+ this.breakpoints = [];
+
+ this.emptyElement = document.createElement("div");
+ this.emptyElement.className = "info";
+ this.emptyElement.textContent = WebInspector.UIString("No Breakpoints");
+
+ this.bodyElement.appendChild(this.emptyElement);
+}
+
+WebInspector.BreakpointsSidebarPane.prototype = {
+ addBreakpoint: function(breakpoint)
+ {
+ this.breakpoints.push(breakpoint);
+ breakpoint.addEventListener("enabled", this._breakpointEnableChanged, this);
+ breakpoint.addEventListener("disabled", this._breakpointEnableChanged, this);
+
+ // FIXME: add to the breakpoints UI.
+
+ if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID)
+ return;
+
+ if (breakpoint.enabled)
+ InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line);
+ },
+
+ removeBreakpoint: function(breakpoint)
+ {
+ this.breakpoints.remove(breakpoint);
+ breakpoint.removeEventListener("enabled", null, this);
+ breakpoint.removeEventListener("disabled", null, this);
+
+ // FIXME: remove from the breakpoints UI.
+
+ if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID)
+ return;
+
+ InspectorController.removeBreakpoint(breakpoint.sourceID, breakpoint.line);
+ },
+
+ _breakpointEnableChanged: function(event)
+ {
+ var breakpoint = event.target;
+
+ // FIXME: change the breakpoint checkbox state in the UI.
+
+ if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID)
+ return;
+
+ if (breakpoint.enabled)
+ InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line);
+ else
+ InspectorController.removeBreakpoint(breakpoint.sourceID, breakpoint.line);
+ }
+}
+
+WebInspector.BreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/CallStackSidebarPane.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/CallStackSidebarPane.js
new file mode 100644
index 0000000..a2c8bed
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/CallStackSidebarPane.js
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.CallStackSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Call Stack"));
+}
+
+WebInspector.CallStackSidebarPane.prototype = {
+ update: function(callFrame, sourceIDMap)
+ {
+ this.bodyElement.removeChildren();
+
+ this.placards = [];
+ delete this._selectedCallFrame;
+
+ if (!callFrame) {
+ var infoElement = document.createElement("div");
+ infoElement.className = "info";
+ infoElement.textContent = WebInspector.UIString("Not Paused");
+ this.bodyElement.appendChild(infoElement);
+ return;
+ }
+
+ var title;
+ var subtitle;
+ var scriptOrResource;
+
+ do {
+ switch (callFrame.type) {
+ case "function":
+ title = callFrame.functionName || WebInspector.UIString("(anonymous function)");
+ break;
+ case "program":
+ title = WebInspector.UIString("(program)");
+ break;
+ }
+
+ scriptOrResource = sourceIDMap[callFrame.sourceID];
+ subtitle = WebInspector.displayNameForURL(scriptOrResource.sourceURL || scriptOrResource.url);
+
+ if (callFrame.line > 0) {
+ if (subtitle)
+ subtitle += ":" + callFrame.line;
+ else
+ subtitle = WebInspector.UIString("line %d", callFrame.line);
+ }
+
+ var placard = new WebInspector.Placard(title, subtitle);
+ placard.callFrame = callFrame;
+
+ placard.element.addEventListener("click", this._placardSelected.bind(this), false);
+
+ this.placards.push(placard);
+ this.bodyElement.appendChild(placard.element);
+
+ callFrame = callFrame.caller;
+ } while (callFrame);
+ },
+
+ get selectedCallFrame()
+ {
+ return this._selectedCallFrame;
+ },
+
+ set selectedCallFrame(x)
+ {
+ if (this._selectedCallFrame === x)
+ return;
+
+ this._selectedCallFrame = x;
+
+ for (var i = 0; i < this.placards.length; ++i) {
+ var placard = this.placards[i];
+ placard.selected = (placard.callFrame === this._selectedCallFrame);
+ }
+
+ this.dispatchEventToListeners("call frame selected");
+ },
+
+ _placardSelected: function(event)
+ {
+ var placardElement = event.target.enclosingNodeOrSelfWithClass("placard");
+ this.selectedCallFrame = placardElement.placard.callFrame;
+ }
+}
+
+WebInspector.CallStackSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Console.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Console.js
new file mode 100644
index 0000000..65cc7d0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Console.js
@@ -0,0 +1,942 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Console = function()
+{
+ this.messages = [];
+
+ WebInspector.View.call(this, document.getElementById("console"));
+
+ this.messagesElement = document.getElementById("console-messages");
+ this.messagesElement.addEventListener("selectstart", this._messagesSelectStart.bind(this), false);
+ this.messagesElement.addEventListener("click", this._messagesClicked.bind(this), true);
+
+ this.promptElement = document.getElementById("console-prompt");
+ this.promptElement.handleKeyEvent = this._promptKeyDown.bind(this);
+ this.prompt = new WebInspector.TextPrompt(this.promptElement, this.completions.bind(this), " .=:[({;");
+
+ this.toggleButton = document.getElementById("console-status-bar-item");
+ this.toggleButton.title = WebInspector.UIString("Show console.");
+ this.toggleButton.addEventListener("click", this._toggleButtonClicked.bind(this), false);
+
+ this.clearButton = document.getElementById("clear-console-status-bar-item");
+ this.clearButton.title = WebInspector.UIString("Clear console log.");
+ this.clearButton.addEventListener("click", this._clearButtonClicked.bind(this), false);
+
+ this.topGroup = new WebInspector.ConsoleGroup(null, 0);
+ this.messagesElement.insertBefore(this.topGroup.element, this.promptElement);
+ this.groupLevel = 0;
+ this.currentGroup = this.topGroup;
+
+ document.getElementById("main-status-bar").addEventListener("mousedown", this._startStatusBarDragging.bind(this), true);
+}
+
+WebInspector.Console.prototype = {
+ show: function()
+ {
+ if (this._animating || this.visible)
+ return;
+
+ WebInspector.View.prototype.show.call(this);
+
+ this._animating = true;
+
+ this.toggleButton.addStyleClass("toggled-on");
+ this.toggleButton.title = WebInspector.UIString("Hide console.");
+
+ document.body.addStyleClass("console-visible");
+
+ var anchoredItems = document.getElementById("anchored-status-bar-items");
+
+ var animations = [
+ {element: document.getElementById("main"), end: {bottom: this.element.offsetHeight}},
+ {element: document.getElementById("main-status-bar"), start: {"padding-left": anchoredItems.offsetWidth - 1}, end: {"padding-left": 0}},
+ {element: document.getElementById("other-console-status-bar-items"), start: {opacity: 0}, end: {opacity: 1}}
+ ];
+
+ var consoleStatusBar = document.getElementById("console-status-bar");
+ consoleStatusBar.insertBefore(anchoredItems, consoleStatusBar.firstChild);
+
+ function animationFinished()
+ {
+ if ("updateStatusBarItems" in WebInspector.currentPanel)
+ WebInspector.currentPanel.updateStatusBarItems();
+ WebInspector.currentFocusElement = this.promptElement;
+ delete this._animating;
+ }
+
+ WebInspector.animateStyle(animations, window.event && window.event.shiftKey ? 2000 : 250, animationFinished.bind(this));
+
+ if (!this.prompt.isCaretInsidePrompt())
+ this.prompt.moveCaretToEndOfPrompt();
+ },
+
+ hide: function()
+ {
+ if (this._animating || !this.visible)
+ return;
+
+ WebInspector.View.prototype.hide.call(this);
+
+ this._animating = true;
+
+ this.toggleButton.removeStyleClass("toggled-on");
+ this.toggleButton.title = WebInspector.UIString("Show console.");
+
+ if (this.element === WebInspector.currentFocusElement || this.element.isAncestor(WebInspector.currentFocusElement))
+ WebInspector.currentFocusElement = WebInspector.previousFocusElement;
+
+ var anchoredItems = document.getElementById("anchored-status-bar-items");
+
+ // Temporally set properties and classes to mimic the post-animation values so panels
+ // like Elements in their updateStatusBarItems call will size things to fit the final location.
+ document.getElementById("main-status-bar").style.setProperty("padding-left", (anchoredItems.offsetWidth - 1) + "px");
+ document.body.removeStyleClass("console-visible");
+ if ("updateStatusBarItems" in WebInspector.currentPanel)
+ WebInspector.currentPanel.updateStatusBarItems();
+ document.body.addStyleClass("console-visible");
+
+ var animations = [
+ {element: document.getElementById("main"), end: {bottom: 0}},
+ {element: document.getElementById("main-status-bar"), start: {"padding-left": 0}, end: {"padding-left": anchoredItems.offsetWidth - 1}},
+ {element: document.getElementById("other-console-status-bar-items"), start: {opacity: 1}, end: {opacity: 0}}
+ ];
+
+ function animationFinished()
+ {
+ var mainStatusBar = document.getElementById("main-status-bar");
+ mainStatusBar.insertBefore(anchoredItems, mainStatusBar.firstChild);
+ mainStatusBar.style.removeProperty("padding-left");
+ document.body.removeStyleClass("console-visible");
+ delete this._animating;
+ }
+
+ WebInspector.animateStyle(animations, window.event && window.event.shiftKey ? 2000 : 250, animationFinished.bind(this));
+ },
+
+ addMessage: function(msg)
+ {
+ if (msg instanceof WebInspector.ConsoleMessage && !(msg instanceof WebInspector.ConsoleCommandResult)) {
+ msg.totalRepeatCount = msg.repeatCount;
+ msg.repeatDelta = msg.repeatCount;
+
+ var messageRepeated = false;
+
+ if (msg.isEqual && msg.isEqual(this.previousMessage)) {
+ // Because sometimes we get a large number of repeated messages and sometimes
+ // we get them one at a time, we need to know the difference between how many
+ // repeats we used to have and how many we have now.
+ msg.repeatDelta -= this.previousMessage.totalRepeatCount;
+
+ if (!isNaN(this.repeatCountBeforeCommand))
+ msg.repeatCount -= this.repeatCountBeforeCommand;
+
+ if (!this.commandSincePreviousMessage) {
+ // Recreate the previous message element to reset the repeat count.
+ var messagesElement = this.currentGroup.messagesElement;
+ messagesElement.removeChild(messagesElement.lastChild);
+ messagesElement.appendChild(msg.toMessageElement());
+
+ messageRepeated = true;
+ }
+ } else
+ delete this.repeatCountBeforeCommand;
+
+ // Increment the error or warning count
+ switch (msg.level) {
+ case WebInspector.ConsoleMessage.MessageLevel.Warning:
+ WebInspector.warnings += msg.repeatDelta;
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Error:
+ WebInspector.errors += msg.repeatDelta;
+ break;
+ }
+
+ // Add message to the resource panel
+ if (msg.url in WebInspector.resourceURLMap) {
+ msg.resource = WebInspector.resourceURLMap[msg.url];
+ if (WebInspector.panels.resources)
+ WebInspector.panels.resources.addMessageToResource(msg.resource, msg);
+ }
+
+ this.commandSincePreviousMessage = false;
+ this.previousMessage = msg;
+
+ if (messageRepeated)
+ return;
+ } else if (msg instanceof WebInspector.ConsoleCommand) {
+ if (this.previousMessage) {
+ this.commandSincePreviousMessage = true;
+ this.repeatCountBeforeCommand = this.previousMessage.totalRepeatCount;
+ }
+ }
+
+ this.messages.push(msg);
+
+ if (msg.level === WebInspector.ConsoleMessage.MessageLevel.EndGroup) {
+ if (this.groupLevel < 1)
+ return;
+
+ this.groupLevel--;
+
+ this.currentGroup = this.currentGroup.parentGroup;
+ } else {
+ if (msg.level === WebInspector.ConsoleMessage.MessageLevel.StartGroup) {
+ this.groupLevel++;
+
+ var group = new WebInspector.ConsoleGroup(this.currentGroup, this.groupLevel);
+ this.currentGroup.messagesElement.appendChild(group.element);
+ this.currentGroup = group;
+ }
+
+ this.currentGroup.addMessage(msg);
+ }
+
+ this.promptElement.scrollIntoView(false);
+ },
+
+ clearMessages: function(clearInspectorController)
+ {
+ if (clearInspectorController)
+ InspectorController.clearMessages();
+ if (WebInspector.panels.resources)
+ WebInspector.panels.resources.clearMessages();
+
+ this.messages = [];
+
+ this.groupLevel = 0;
+ this.currentGroup = this.topGroup;
+ this.topGroup.messagesElement.removeChildren();
+
+ WebInspector.errors = 0;
+ WebInspector.warnings = 0;
+
+ delete this.commandSincePreviousMessage;
+ delete this.repeatCountBeforeCommand;
+ delete this.previousMessage;
+ },
+
+ completions: function(wordRange, bestMatchOnly)
+ {
+ // Pass less stop characters to rangeOfWord so the range will be a more complete expression.
+ const expressionStopCharacters = " =:{;";
+ var expressionRange = wordRange.startContainer.rangeOfWord(wordRange.startOffset, expressionStopCharacters, this.promptElement, "backward");
+ var expressionString = expressionRange.toString();
+ var lastIndex = expressionString.length - 1;
+
+ var dotNotation = (expressionString[lastIndex] === ".");
+ var bracketNotation = (expressionString[lastIndex] === "[");
+
+ if (dotNotation || bracketNotation)
+ expressionString = expressionString.substr(0, lastIndex);
+
+ var prefix = wordRange.toString();
+ if (!expressionString && !prefix)
+ return;
+
+ var result;
+ if (expressionString) {
+ try {
+ result = this._evalInInspectedWindow(expressionString);
+ } catch(e) {
+ // Do nothing, the prefix will be considered a window property.
+ }
+ } else {
+ // There is no expressionString, so the completion should happen against global properties.
+ // Or if the debugger is paused, against properties in scope of the selected call frame.
+ if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused)
+ result = WebInspector.panels.scripts.variablesInScopeForSelectedCallFrame();
+ else
+ result = InspectorController.inspectedWindow();
+ }
+
+ if (bracketNotation) {
+ if (prefix.length && prefix[0] === "'")
+ var quoteUsed = "'";
+ else
+ var quoteUsed = "\"";
+ }
+
+ var results = [];
+ var properties = Object.sortedProperties(result);
+ for (var i = 0; i < properties.length; ++i) {
+ var property = properties[i];
+
+ if (dotNotation && !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(property))
+ continue;
+
+ if (bracketNotation) {
+ if (!/^[0-9]+$/.test(property))
+ property = quoteUsed + property.escapeCharacters(quoteUsed + "\\") + quoteUsed;
+ property += "]";
+ }
+
+ if (property.length < prefix.length)
+ continue;
+ if (property.indexOf(prefix) !== 0)
+ continue;
+
+ results.push(property);
+ if (bestMatchOnly)
+ break;
+ }
+
+ return results;
+ },
+
+ _toggleButtonClicked: function()
+ {
+ this.visible = !this.visible;
+ },
+
+ _clearButtonClicked: function()
+ {
+ this.clearMessages(true);
+ },
+
+ _messagesSelectStart: function(event)
+ {
+ if (this._selectionTimeout)
+ clearTimeout(this._selectionTimeout);
+
+ this.prompt.clearAutoComplete();
+
+ function moveBackIfOutside()
+ {
+ delete this._selectionTimeout;
+ if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed)
+ this.prompt.moveCaretToEndOfPrompt();
+ this.prompt.autoCompleteSoon();
+ }
+
+ this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100);
+ },
+
+ _messagesClicked: function(event)
+ {
+ var link = event.target.enclosingNodeOrSelfWithNodeName("a");
+ if (!link || !link.representedNode)
+ return;
+
+ WebInspector.updateFocusedNode(link.representedNode);
+ event.stopPropagation();
+ event.preventDefault();
+ },
+
+ _promptKeyDown: function(event)
+ {
+ switch (event.keyIdentifier) {
+ case "Enter":
+ this._enterKeyPressed(event);
+ return;
+ }
+
+ this.prompt.handleKeyEvent(event);
+ },
+
+ _startStatusBarDragging: function(event)
+ {
+ if (!this.visible || event.target !== document.getElementById("main-status-bar"))
+ return;
+
+ WebInspector.elementDragStart(document.getElementById("main-status-bar"), this._statusBarDragging.bind(this), this._endStatusBarDragging.bind(this), event, "row-resize");
+
+ this._statusBarDragOffset = event.pageY - this.element.totalOffsetTop;
+
+ event.stopPropagation();
+ },
+
+ _statusBarDragging: function(event)
+ {
+ var mainElement = document.getElementById("main");
+
+ var height = window.innerHeight - event.pageY + this._statusBarDragOffset;
+ height = Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - mainElement.totalOffsetTop - Preferences.minConsoleHeight);
+
+ mainElement.style.bottom = height + "px";
+ this.element.style.height = height + "px";
+
+ event.preventDefault();
+ event.stopPropagation();
+ },
+
+ _endStatusBarDragging: function(event)
+ {
+ WebInspector.elementDragEnd(event);
+
+ delete this._statusBarDragOffset;
+
+ event.stopPropagation();
+ },
+
+ _evalInInspectedWindow: function(expression)
+ {
+ if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused)
+ return WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression);
+
+ var inspectedWindow = InspectorController.inspectedWindow();
+ if (!inspectedWindow._inspectorCommandLineAPI) {
+ inspectedWindow.eval("window._inspectorCommandLineAPI = { \
+ $: function() { return document.getElementById.apply(document, arguments) }, \
+ $$: function() { return document.querySelectorAll.apply(document, arguments) }, \
+ $x: function(xpath, context) { \
+ var nodes = []; \
+ try { \
+ var doc = context || document; \
+ var results = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null); \
+ var node; \
+ while (node = results.iterateNext()) nodes.push(node); \
+ } catch (e) {} \
+ return nodes; \
+ }, \
+ dir: function() { return console.dir.apply(console, arguments) }, \
+ dirxml: function() { return console.dirxml.apply(console, arguments) }, \
+ keys: function(o) { var a = []; for (k in o) a.push(k); return a; }, \
+ values: function(o) { var a = []; for (k in o) a.push(o[k]); return a; }, \
+ profile: function() { return console.profile.apply(console, arguments) }, \
+ profileEnd: function() { return console.profileEnd.apply(console, arguments) } \
+ };");
+
+ inspectedWindow._inspectorCommandLineAPI.clear = InspectorController.wrapCallback(this.clearMessages.bind(this));
+ }
+
+ // Surround the expression in with statements to inject our command line API so that
+ // the window object properties still take more precedent than our API functions.
+ expression = "with (window._inspectorCommandLineAPI) { with (window) { " + expression + " } }";
+
+ return inspectedWindow.eval(expression);
+ },
+
+ _enterKeyPressed: function(event)
+ {
+ if (event.altKey)
+ return;
+
+ event.preventDefault();
+ event.stopPropagation();
+
+ this.prompt.clearAutoComplete(true);
+
+ var str = this.prompt.text;
+ if (!str.length)
+ return;
+
+ var commandMessage = new WebInspector.ConsoleCommand(str);
+ this.addMessage(commandMessage);
+
+ var result;
+ var exception = false;
+ try {
+ result = this._evalInInspectedWindow(str);
+ } catch(e) {
+ result = e;
+ exception = true;
+ }
+
+ this.prompt.history.push(str);
+ this.prompt.historyOffset = 0;
+ this.prompt.text = "";
+
+ this.addMessage(new WebInspector.ConsoleCommandResult(result, exception, commandMessage));
+ },
+
+ _format: function(output, forceObjectFormat)
+ {
+ var type = (forceObjectFormat ? "object" : Object.type(output, InspectorController.inspectedWindow()));
+
+ // We don't perform any special formatting on these types, so we just
+ // pass them through the simple _formatvalue function.
+ var undecoratedTypes = {
+ "undefined": 1,
+ "null": 1,
+ "boolean": 1,
+ "number": 1,
+ "date": 1,
+ "function": 1,
+ };
+
+ var formatter;
+ if (forceObjectFormat)
+ formatter = "_formatobject";
+ else if (type in undecoratedTypes)
+ formatter = "_formatvalue";
+ else {
+ formatter = "_format" + type;
+ if (!(formatter in this)) {
+ formatter = "_formatobject";
+ type = "object";
+ }
+ }
+
+ var span = document.createElement("span");
+ span.addStyleClass("console-formatted-" + type);
+ this[formatter](output, span);
+ return span;
+ },
+
+ _formatvalue: function(val, elem)
+ {
+ elem.appendChild(document.createTextNode(val));
+ },
+
+ _formatstring: function(str, elem)
+ {
+ elem.appendChild(document.createTextNode("\"" + str + "\""));
+ },
+
+ _formatregexp: function(re, elem)
+ {
+ var formatted = String(re).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1);
+ elem.appendChild(document.createTextNode(formatted));
+ },
+
+ _formatarray: function(arr, elem)
+ {
+ elem.appendChild(document.createTextNode("["));
+ for (var i = 0; i < arr.length; ++i) {
+ elem.appendChild(this._format(arr[i]));
+ if (i < arr.length - 1)
+ elem.appendChild(document.createTextNode(", "));
+ }
+ elem.appendChild(document.createTextNode("]"));
+ },
+
+ _formatnode: function(node, elem)
+ {
+ var treeOutline = new WebInspector.ElementsTreeOutline();
+ treeOutline.rootDOMNode = node;
+ treeOutline.element.addStyleClass("outline-disclosure");
+ if (!treeOutline.children[0].hasChildren)
+ treeOutline.element.addStyleClass("single-node");
+ elem.appendChild(treeOutline.element);
+ },
+
+ _formatobject: function(obj, elem)
+ {
+ elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, null, null, null, true).element);
+ },
+
+ _formaterror: function(obj, elem)
+ {
+ var messageElement = document.createElement("span");
+ messageElement.className = "error-message";
+ messageElement.textContent = obj.name + ": " + obj.message;
+ elem.appendChild(messageElement);
+
+ if (obj.sourceURL) {
+ var urlElement = document.createElement("a");
+ urlElement.className = "webkit-html-resource-link";
+ urlElement.href = obj.sourceURL;
+ urlElement.lineNumber = obj.line;
+ urlElement.preferredPanel = "scripts";
+
+ if (obj.line > 0)
+ urlElement.textContent = WebInspector.displayNameForURL(obj.sourceURL) + ":" + obj.line;
+ else
+ urlElement.textContent = WebInspector.displayNameForURL(obj.sourceURL);
+
+ elem.appendChild(document.createTextNode(" ("));
+ elem.appendChild(urlElement);
+ elem.appendChild(document.createTextNode(")"));
+ }
+ },
+}
+
+WebInspector.Console.prototype.__proto__ = WebInspector.View.prototype;
+
+WebInspector.ConsoleMessage = function(source, level, line, url, groupLevel, repeatCount)
+{
+ this.source = source;
+ this.level = level;
+ this.line = line;
+ this.url = url;
+ this.groupLevel = groupLevel;
+ this.repeatCount = repeatCount;
+ if (arguments.length > 6)
+ this.setMessageBody(Array.prototype.slice.call(arguments, 6));
+}
+
+WebInspector.ConsoleMessage.prototype = {
+ setMessageBody: function(args)
+ {
+ switch (this.level) {
+ case WebInspector.ConsoleMessage.MessageLevel.Trace:
+ var span = document.createElement("span");
+ span.addStyleClass("console-formatted-trace");
+ var stack = Array.prototype.slice.call(args);
+ var funcNames = stack.map(function(f) {
+ return f || WebInspector.UIString("(anonymous function)");
+ });
+ span.appendChild(document.createTextNode(funcNames.join("\n")));
+ this.formattedMessage = span;
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Object:
+ this.formattedMessage = this._format(["%O", args[0]]);
+ break;
+ default:
+ this.formattedMessage = this._format(args);
+ break;
+ }
+
+ // This is used for inline message bubbles in SourceFrames, or other plain-text representations.
+ this.message = this.formattedMessage.textContent;
+ },
+
+ isErrorOrWarning: function()
+ {
+ return (this.level === WebInspector.ConsoleMessage.MessageLevel.Warning || this.level === WebInspector.ConsoleMessage.MessageLevel.Error);
+ },
+
+ _format: function(parameters)
+ {
+ var formattedResult = document.createElement("span");
+
+ if (!parameters.length)
+ return formattedResult;
+
+ function formatForConsole(obj)
+ {
+ return WebInspector.console._format(obj);
+ }
+
+ function formatAsObjectForConsole(obj)
+ {
+ return WebInspector.console._format(obj, true);
+ }
+
+ if (Object.type(parameters[0], InspectorController.inspectedWindow()) === "string") {
+ var formatters = {}
+ for (var i in String.standardFormatters)
+ formatters[i] = String.standardFormatters[i];
+
+ // Firebug uses %o for formatting objects.
+ formatters.o = formatForConsole;
+ // Firebug allows both %i and %d for formatting integers.
+ formatters.i = formatters.d;
+ // Support %O to force object formating, instead of the type-based %o formatting.
+ formatters.O = formatAsObjectForConsole;
+
+ function append(a, b)
+ {
+ if (!(b instanceof Node))
+ a.appendChild(WebInspector.linkifyStringAsFragment(b.toString()));
+ else
+ a.appendChild(b);
+ return a;
+ }
+
+ var result = String.format(parameters[0], parameters.slice(1), formatters, formattedResult, append);
+ formattedResult = result.formattedResult;
+ parameters = result.unusedSubstitutions;
+ if (parameters.length)
+ formattedResult.appendChild(document.createTextNode(" "));
+ }
+
+ for (var i = 0; i < parameters.length; ++i) {
+ if (typeof parameters[i] === "string")
+ formattedResult.appendChild(WebInspector.linkifyStringAsFragment(parameters[i]));
+ else
+ formattedResult.appendChild(formatForConsole(parameters[i]));
+
+ if (i < parameters.length - 1)
+ formattedResult.appendChild(document.createTextNode(" "));
+ }
+
+ return formattedResult;
+ },
+
+ toMessageElement: function()
+ {
+ if (this.propertiesSection)
+ return this.propertiesSection.element;
+
+ var element = document.createElement("div");
+ element.message = this;
+ element.className = "console-message";
+
+ switch (this.source) {
+ case WebInspector.ConsoleMessage.MessageSource.HTML:
+ element.addStyleClass("console-html-source");
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.WML:
+ element.addStyleClass("console-wml-source");
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.XML:
+ element.addStyleClass("console-xml-source");
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.JS:
+ element.addStyleClass("console-js-source");
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.CSS:
+ element.addStyleClass("console-css-source");
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.Other:
+ element.addStyleClass("console-other-source");
+ break;
+ }
+
+ switch (this.level) {
+ case WebInspector.ConsoleMessage.MessageLevel.Tip:
+ element.addStyleClass("console-tip-level");
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Log:
+ element.addStyleClass("console-log-level");
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Warning:
+ element.addStyleClass("console-warning-level");
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Error:
+ element.addStyleClass("console-error-level");
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.StartGroup:
+ element.addStyleClass("console-group-title-level");
+ }
+
+ if (this.elementsTreeOutline) {
+ element.addStyleClass("outline-disclosure");
+ element.appendChild(this.elementsTreeOutline.element);
+ return element;
+ }
+
+ if (this.repeatCount > 1) {
+ var messageRepeatCountElement = document.createElement("span");
+ messageRepeatCountElement.className = "bubble";
+ messageRepeatCountElement.textContent = this.repeatCount;
+
+ element.appendChild(messageRepeatCountElement);
+ element.addStyleClass("repeated-message");
+ }
+
+ if (this.url && this.url !== "undefined") {
+ var urlElement = document.createElement("a");
+ urlElement.className = "console-message-url webkit-html-resource-link";
+ urlElement.href = this.url;
+ urlElement.lineNumber = this.line;
+
+ if (this.source === WebInspector.ConsoleMessage.MessageSource.JS)
+ urlElement.preferredPanel = "scripts";
+
+ if (this.line > 0)
+ urlElement.textContent = WebInspector.displayNameForURL(this.url) + ":" + this.line;
+ else
+ urlElement.textContent = WebInspector.displayNameForURL(this.url);
+
+ element.appendChild(urlElement);
+ }
+
+ var messageTextElement = document.createElement("span");
+ messageTextElement.className = "console-message-text";
+ messageTextElement.appendChild(this.formattedMessage);
+ element.appendChild(messageTextElement);
+
+ return element;
+ },
+
+ toString: function()
+ {
+ var sourceString;
+ switch (this.source) {
+ case WebInspector.ConsoleMessage.MessageSource.HTML:
+ sourceString = "HTML";
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.WML:
+ sourceString = "WML";
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.XML:
+ sourceString = "XML";
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.JS:
+ sourceString = "JS";
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.CSS:
+ sourceString = "CSS";
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.Other:
+ sourceString = "Other";
+ break;
+ }
+
+ var levelString;
+ switch (this.level) {
+ case WebInspector.ConsoleMessage.MessageLevel.Tip:
+ levelString = "Tip";
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Log:
+ levelString = "Log";
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Warning:
+ levelString = "Warning";
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Error:
+ levelString = "Error";
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Object:
+ levelString = "Object";
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Trace:
+ levelString = "Trace";
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.StartGroup:
+ levelString = "Start Group";
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.EndGroup:
+ levelString = "End Group";
+ break;
+ }
+
+ return sourceString + " " + levelString + ": " + this.formattedMessage.textContent + "\n" + this.url + " line " + this.line;
+ },
+
+ isEqual: function(msg, disreguardGroup)
+ {
+ if (!msg)
+ return false;
+
+ var ret = (this.source == msg.source)
+ && (this.level == msg.level)
+ && (this.line == msg.line)
+ && (this.url == msg.url)
+ && (this.message == msg.message);
+
+ return (disreguardGroup ? ret : (ret && (this.groupLevel == msg.groupLevel)));
+ }
+}
+
+// Note: Keep these constants in sync with the ones in Console.h
+WebInspector.ConsoleMessage.MessageSource = {
+ HTML: 0,
+ WML: 1,
+ XML: 2,
+ JS: 3,
+ CSS: 4,
+ Other: 5
+}
+
+WebInspector.ConsoleMessage.MessageLevel = {
+ Tip: 0,
+ Log: 1,
+ Warning: 2,
+ Error: 3,
+ Object: 4,
+ Trace: 5,
+ StartGroup: 6,
+ EndGroup: 7
+}
+
+WebInspector.ConsoleCommand = function(command)
+{
+ this.command = command;
+}
+
+WebInspector.ConsoleCommand.prototype = {
+ toMessageElement: function()
+ {
+ var element = document.createElement("div");
+ element.command = this;
+ element.className = "console-user-command";
+
+ var commandTextElement = document.createElement("span");
+ commandTextElement.className = "console-message-text";
+ commandTextElement.textContent = this.command;
+ element.appendChild(commandTextElement);
+
+ return element;
+ }
+}
+
+WebInspector.ConsoleCommandResult = function(result, exception, originatingCommand)
+{
+ var level = (exception ? WebInspector.ConsoleMessage.MessageLevel.Error : WebInspector.ConsoleMessage.MessageLevel.Log);
+ var message = (exception ? String(result) : result);
+ var line = (exception ? result.line : -1);
+ var url = (exception ? result.sourceURL : null);
+
+ WebInspector.ConsoleMessage.call(this, WebInspector.ConsoleMessage.MessageSource.JS, level, line, url, null, 1, message);
+
+ this.originatingCommand = originatingCommand;
+}
+
+WebInspector.ConsoleCommandResult.prototype = {
+ toMessageElement: function()
+ {
+ var element = WebInspector.ConsoleMessage.prototype.toMessageElement.call(this);
+ element.addStyleClass("console-user-command-result");
+ return element;
+ }
+}
+
+WebInspector.ConsoleCommandResult.prototype.__proto__ = WebInspector.ConsoleMessage.prototype;
+
+WebInspector.ConsoleGroup = function(parentGroup, level)
+{
+ this.parentGroup = parentGroup;
+ this.level = level;
+
+ var element = document.createElement("div");
+ element.className = "console-group";
+ element.group = this;
+ this.element = element;
+
+ var messagesElement = document.createElement("div");
+ messagesElement.className = "console-group-messages";
+ element.appendChild(messagesElement);
+ this.messagesElement = messagesElement;
+}
+
+WebInspector.ConsoleGroup.prototype = {
+ addMessage: function(msg)
+ {
+ var element = msg.toMessageElement();
+
+ if (msg.level === WebInspector.ConsoleMessage.MessageLevel.StartGroup) {
+ this.messagesElement.parentNode.insertBefore(element, this.messagesElement);
+ element.addEventListener("click", this._titleClicked.bind(this), true);
+ } else
+ this.messagesElement.appendChild(element);
+
+ if (element.previousSibling && msg.originatingCommand && element.previousSibling.command === msg.originatingCommand)
+ element.previousSibling.addStyleClass("console-adjacent-user-command-result");
+ },
+
+ _titleClicked: function(event)
+ {
+ var groupTitleElement = event.target.enclosingNodeOrSelfWithClass("console-group-title-level");
+ if (groupTitleElement) {
+ var groupElement = groupTitleElement.enclosingNodeOrSelfWithClass("console-group");
+ if (groupElement)
+ if (groupElement.hasStyleClass("collapsed"))
+ groupElement.removeStyleClass("collapsed");
+ else
+ groupElement.addStyleClass("collapsed");
+ groupTitleElement.scrollIntoViewIfNeeded(true);
+ }
+
+ event.stopPropagation();
+ event.preventDefault();
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DataGrid.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DataGrid.js
new file mode 100644
index 0000000..2fcb08c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DataGrid.js
@@ -0,0 +1,885 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DataGrid = function(columns)
+{
+ this.element = document.createElement("div");
+ this.element.className = "data-grid";
+ this.element.tabIndex = 0;
+ this.element.addEventListener("keydown", this._keyDown.bind(this), false);
+
+ this._headerTable = document.createElement("table");
+ this._headerTable.className = "header";
+
+ this._dataTable = document.createElement("table");
+ this._dataTable.className = "data";
+
+ this._dataTable.addEventListener("mousedown", this._mouseDownInDataTable.bind(this), true);
+ this._dataTable.addEventListener("click", this._clickInDataTable.bind(this), true);
+
+ var scrollContainer = document.createElement("div");
+ scrollContainer.className = "data-container";
+ scrollContainer.appendChild(this._dataTable);
+
+ this.element.appendChild(this._headerTable);
+ this.element.appendChild(scrollContainer);
+
+ var headerRow = document.createElement("tr");
+ var columnGroup = document.createElement("colgroup");
+ var columnCount = 0;
+
+ for (var columnIdentifier in columns) {
+ var column = columns[columnIdentifier];
+ if (column.disclosure)
+ this.disclosureColumnIdentifier = columnIdentifier;
+
+ var col = document.createElement("col");
+ if (column.width)
+ col.style.width = column.width;
+ columnGroup.appendChild(col);
+
+ var cell = document.createElement("th");
+ cell.className = columnIdentifier + "-column";
+ cell.columnIdentifier = columnIdentifier;
+
+ var div = document.createElement("div");
+ div.textContent = column.title;
+ cell.appendChild(div);
+
+ if (column.sort) {
+ cell.addStyleClass("sort-" + column.sort);
+ this._sortColumnCell = cell;
+ }
+
+ if (column.sortable) {
+ cell.addEventListener("click", this._clickInHeaderCell.bind(this), false);
+ cell.addStyleClass("sortable");
+ }
+
+ headerRow.appendChild(cell);
+
+ ++columnCount;
+ }
+
+ columnGroup.span = columnCount;
+
+ var cell = document.createElement("th");
+ cell.className = "corner";
+ headerRow.appendChild(cell);
+
+ this._headerTable.appendChild(columnGroup);
+ this.headerTableBody.appendChild(headerRow);
+
+ var fillerRow = document.createElement("tr");
+ fillerRow.className = "filler";
+
+ for (var i = 0; i < columnCount; ++i) {
+ var cell = document.createElement("td");
+ fillerRow.appendChild(cell);
+ }
+
+ this._dataTable.appendChild(columnGroup.cloneNode(true));
+ this.dataTableBody.appendChild(fillerRow);
+
+ this.columns = columns || {};
+ this.children = [];
+ this.selectedNode = null;
+ this.expandNodesWhenArrowing = false;
+ this.root = true;
+ this.hasChildren = false;
+ this.expanded = true;
+ this.revealed = true;
+ this.selected = false;
+ this.dataGrid = this;
+ this.indentWidth = 15;
+}
+
+WebInspector.DataGrid.prototype = {
+ get sortColumnIdentifier()
+ {
+ if (!this._sortColumnCell)
+ return null;
+ return this._sortColumnCell.columnIdentifier;
+ },
+
+ get sortOrder()
+ {
+ if (!this._sortColumnCell || this._sortColumnCell.hasStyleClass("sort-ascending"))
+ return "ascending";
+ if (this._sortColumnCell.hasStyleClass("sort-descending"))
+ return "descending";
+ return null;
+ },
+
+ get headerTableBody()
+ {
+ if ("_headerTableBody" in this)
+ return this._headerTableBody;
+
+ this._headerTableBody = this._headerTable.getElementsByTagName("tbody")[0];
+ if (!this._headerTableBody) {
+ this._headerTableBody = this.element.ownerDocument.createElement("tbody");
+ this._headerTable.insertBefore(this._headerTableBody, this._headerTable.tFoot);
+ }
+
+ return this._headerTableBody;
+ },
+
+ get dataTableBody()
+ {
+ if ("_dataTableBody" in this)
+ return this._dataTableBody;
+
+ this._dataTableBody = this._dataTable.getElementsByTagName("tbody")[0];
+ if (!this._dataTableBody) {
+ this._dataTableBody = this.element.ownerDocument.createElement("tbody");
+ this._dataTable.insertBefore(this._dataTableBody, this._dataTable.tFoot);
+ }
+
+ return this._dataTableBody;
+ },
+
+ appendChild: function(child)
+ {
+ this.insertChild(child, this.children.length);
+ },
+
+ insertChild: function(child, index)
+ {
+ if (!child)
+ throw("insertChild: Node can't be undefined or null.");
+ if (child.parent === this)
+ throw("insertChild: Node is already a child of this node.");
+
+ if (child.parent)
+ child.parent.removeChild(child);
+
+ this.children.splice(index, 0, child);
+ this.hasChildren = true;
+
+ child.parent = this;
+ child.dataGrid = this.dataGrid;
+ child._recalculateSiblings(index);
+
+ delete child._depth;
+ delete child._revealed;
+ delete child._attached;
+
+ var current = child.children[0];
+ while (current) {
+ current.dataGrid = this.dataGrid;
+ delete current._depth;
+ delete current._revealed;
+ delete current._attached;
+ current = current.traverseNextNode(false, child, true);
+ }
+
+ if (this.expanded)
+ child._attach();
+ },
+
+ removeChild: function(child)
+ {
+ if (!child)
+ throw("removeChild: Node can't be undefined or null.");
+ if (child.parent !== this)
+ throw("removeChild: Node is not a child of this node.");
+
+ child.deselect();
+
+ this.children.remove(child, true);
+
+ if (child.previousSibling)
+ child.previousSibling.nextSibling = child.nextSibling;
+ if (child.nextSibling)
+ child.nextSibling.previousSibling = child.previousSibling;
+
+ child.dataGrid = null;
+ child.parent = null;
+ child.nextSibling = null;
+ child.previousSibling = null;
+
+ if (this.children.length <= 0)
+ this.hasChildren = false;
+ },
+
+ removeChildren: function()
+ {
+ for (var i = 0; i < this.children.length; ++i) {
+ var child = this.children[i];
+ child.deselect();
+ child._detach();
+
+ child.dataGrid = null;
+ child.parent = null;
+ child.nextSibling = null;
+ child.previousSibling = null;
+ }
+
+ this.children = [];
+ this.hasChildren = false;
+ },
+
+ removeChildrenRecursive: function()
+ {
+ var childrenToRemove = this.children;
+
+ var child = this.children[0];
+ while (child) {
+ if (child.children.length)
+ childrenToRemove = childrenToRemove.concat(child.children);
+ child = child.traverseNextNode(false, this, true);
+ }
+
+ for (var i = 0; i < childrenToRemove.length; ++i) {
+ var child = childrenToRemove[i];
+ child.deselect();
+ child._detach();
+
+ child.children = [];
+ child.dataGrid = null;
+ child.parent = null;
+ child.nextSibling = null;
+ child.previousSibling = null;
+ }
+
+ this.children = [];
+ },
+
+ handleKeyEvent: function(event)
+ {
+ if (!this.selectedNode || event.shiftKey || event.metaKey || event.ctrlKey)
+ return false;
+
+ var handled = false;
+ var nextSelectedNode;
+ if (event.keyIdentifier === "Up" && !event.altKey) {
+ nextSelectedNode = this.selectedNode.traversePreviousNode(true);
+ while (nextSelectedNode && !nextSelectedNode.selectable)
+ nextSelectedNode = nextSelectedNode.traversePreviousNode(!this.expandTreeNodesWhenArrowing);
+ handled = nextSelectedNode ? true : false;
+ } else if (event.keyIdentifier === "Down" && !event.altKey) {
+ nextSelectedNode = this.selectedNode.traverseNextNode(true);
+ while (nextSelectedNode && !nextSelectedNode.selectable)
+ nextSelectedNode = nextSelectedNode.traverseNextNode(!this.expandTreeNodesWhenArrowing);
+ handled = nextSelectedNode ? true : false;
+ } else if (event.keyIdentifier === "Left") {
+ if (this.selectedNode.expanded) {
+ if (event.altKey)
+ this.selectedNode.collapseRecursively();
+ else
+ this.selectedNode.collapse();
+ handled = true;
+ } else if (this.selectedNode.parent && !this.selectedNode.parent.root) {
+ handled = true;
+ if (this.selectedNode.parent.selectable) {
+ nextSelectedNode = this.selectedNode.parent;
+ handled = nextSelectedNode ? true : false;
+ } else if (this.selectedNode.parent)
+ this.selectedNode.parent.collapse();
+ }
+ } else if (event.keyIdentifier === "Right") {
+ if (!this.selectedNode.revealed) {
+ this.selectedNode.reveal();
+ handled = true;
+ } else if (this.selectedNode.hasChildren) {
+ handled = true;
+ if (this.selectedNode.expanded) {
+ nextSelectedNode = this.selectedNode.children[0];
+ handled = nextSelectedNode ? true : false;
+ } else {
+ if (event.altKey)
+ this.selectedNode.expandRecursively();
+ else
+ this.selectedNode.expand();
+ }
+ }
+ }
+
+ if (nextSelectedNode) {
+ nextSelectedNode.reveal();
+ nextSelectedNode.select();
+ }
+
+ if (handled) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+
+ return handled;
+ },
+
+ expand: function()
+ {
+ // This is the root, do nothing.
+ },
+
+ collapse: function()
+ {
+ // This is the root, do nothing.
+ },
+
+ reveal: function()
+ {
+ // This is the root, do nothing.
+ },
+
+ dataGridNodeFromEvent: function(event)
+ {
+ var rowElement = event.target.enclosingNodeOrSelfWithNodeName("tr");
+ return rowElement._dataGridNode;
+ },
+
+ dataGridNodeFromPoint: function(x, y)
+ {
+ var node = this._dataTable.ownerDocument.elementFromPoint(x, y);
+ var rowElement = node.enclosingNodeOrSelfWithNodeName("tr");
+ return rowElement._dataGridNode;
+ },
+
+ _keyDown: function(event)
+ {
+ this.handleKeyEvent(event);
+ },
+
+ _clickInHeaderCell: function(event)
+ {
+ var cell = event.target.enclosingNodeOrSelfWithNodeName("th");
+ if (!cell || !cell.columnIdentifier || !cell.hasStyleClass("sortable"))
+ return;
+
+ var sortOrder = this.sortOrder;
+
+ if (this._sortColumnCell) {
+ this._sortColumnCell.removeStyleClass("sort-ascending");
+ this._sortColumnCell.removeStyleClass("sort-descending");
+ }
+
+ if (cell == this._sortColumnCell) {
+ if (sortOrder == "ascending")
+ sortOrder = "descending";
+ else
+ sortOrder = "ascending";
+ }
+
+ this._sortColumnCell = cell;
+
+ cell.addStyleClass("sort-" + sortOrder);
+
+ this.dispatchEventToListeners("sorting changed");
+ },
+
+ _mouseDownInDataTable: function(event)
+ {
+ var gridNode = this.dataGridNodeFromEvent(event);
+ if (!gridNode || !gridNode.selectable)
+ return;
+
+ if (gridNode.isEventWithinDisclosureTriangle(event))
+ return;
+
+ if (event.metaKey) {
+ if (gridNode.selected)
+ gridNode.deselect();
+ else
+ gridNode.select();
+ } else
+ gridNode.select();
+ },
+
+ _clickInDataTable: function(event)
+ {
+ var gridNode = this.dataGridNodeFromEvent(event);
+ if (!gridNode || !gridNode.hasChildren)
+ return;
+
+ if (!gridNode.isEventWithinDisclosureTriangle(event))
+ return;
+
+ if (gridNode.expanded) {
+ if (event.altKey)
+ gridNode.collapseRecursively();
+ else
+ gridNode.collapse();
+ } else {
+ if (event.altKey)
+ gridNode.expandRecursively();
+ else
+ gridNode.expand();
+ }
+ }
+}
+
+WebInspector.DataGrid.prototype.__proto__ = WebInspector.Object.prototype;
+
+WebInspector.DataGridNode = function(data, hasChildren)
+{
+ this._expanded = false;
+ this._selected = false;
+ this._shouldRefreshChildren = true;
+ this._data = data || {};
+ this.hasChildren = hasChildren || false;
+ this.children = [];
+ this.dataGrid = null;
+ this.parent = null;
+ this.previousSibling = null;
+ this.nextSibling = null;
+ this.disclosureToggleWidth = 10;
+}
+
+WebInspector.DataGridNode.prototype = {
+ selectable: true,
+
+ get element()
+ {
+ if (this._element)
+ return this._element;
+
+ if (!this.dataGrid)
+ return null;
+
+ this._element = document.createElement("tr");
+ this._element._dataGridNode = this;
+
+ if (this.hasChildren)
+ this._element.addStyleClass("parent");
+ if (this.expanded)
+ this._element.addStyleClass("expanded");
+ if (this.selected)
+ this._element.addStyleClass("selected");
+ if (this.revealed)
+ this._element.addStyleClass("revealed");
+
+ for (var columnIdentifier in this.dataGrid.columns) {
+ var cell = this.createCell(columnIdentifier);
+ this._element.appendChild(cell);
+ }
+
+ return this._element;
+ },
+
+ get data()
+ {
+ return this._data;
+ },
+
+ set data(x)
+ {
+ this._data = x || {};
+ this.refresh();
+ },
+
+ get revealed()
+ {
+ if ("_revealed" in this)
+ return this._revealed;
+
+ var currentAncestor = this.parent;
+ while (currentAncestor && !currentAncestor.root) {
+ if (!currentAncestor.expanded) {
+ this._revealed = false;
+ return false;
+ }
+
+ currentAncestor = currentAncestor.parent;
+ }
+
+ this._revealed = true;
+ return true;
+ },
+
+ set hasChildren(x)
+ {
+ if (this._hasChildren === x)
+ return;
+
+ this._hasChildren = x;
+
+ if (!this._element)
+ return;
+
+ if (this._hasChildren)
+ {
+ this._element.addStyleClass("parent");
+ if (this.expanded)
+ this._element.addStyleClass("expanded");
+ }
+ else
+ {
+ this._element.removeStyleClass("parent");
+ this._element.removeStyleClass("expanded");
+ }
+ },
+
+ get hasChildren()
+ {
+ return this._hasChildren;
+ },
+
+ set revealed(x)
+ {
+ if (this._revealed === x)
+ return;
+
+ this._revealed = x;
+
+ if (this._element) {
+ if (this._revealed)
+ this._element.addStyleClass("revealed");
+ else
+ this._element.removeStyleClass("revealed");
+ }
+
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i].revealed = x && this.expanded;
+ },
+
+ get depth()
+ {
+ if ("_depth" in this)
+ return this._depth;
+ if (this.parent && !this.parent.root)
+ this._depth = this.parent.depth + 1;
+ else
+ this._depth = 0;
+ return this._depth;
+ },
+
+ get shouldRefreshChildren()
+ {
+ return this._shouldRefreshChildren;
+ },
+
+ set shouldRefreshChildren(x)
+ {
+ this._shouldRefreshChildren = x;
+ if (x && this.expanded)
+ this.expand();
+ },
+
+ get selected()
+ {
+ return this._selected;
+ },
+
+ set selected(x)
+ {
+ if (x)
+ this.select();
+ else
+ this.deselect();
+ },
+
+ get expanded()
+ {
+ return this._expanded;
+ },
+
+ set expanded(x)
+ {
+ if (x)
+ this.expand();
+ else
+ this.collapse();
+ },
+
+ refresh: function()
+ {
+ if (!this._element || !this.dataGrid)
+ return;
+
+ this._element.removeChildren();
+
+ for (var columnIdentifier in this.dataGrid.columns) {
+ var cell = this.createCell(columnIdentifier);
+ this._element.appendChild(cell);
+ }
+ },
+
+ createCell: function(columnIdentifier)
+ {
+ var cell = document.createElement("td");
+ cell.className = columnIdentifier + "-column";
+
+ var div = document.createElement("div");
+ div.textContent = this.data[columnIdentifier];
+ cell.appendChild(div);
+
+ if (columnIdentifier === this.dataGrid.disclosureColumnIdentifier) {
+ cell.addStyleClass("disclosure");
+ if (this.depth)
+ cell.style.setProperty("padding-left", (this.depth * this.dataGrid.indentWidth) + "px");
+ }
+
+ return cell;
+ },
+
+ // Share these functions with DataGrid. They are written to work with a DataGridNode this object.
+ appendChild: WebInspector.DataGrid.prototype.appendChild,
+ insertChild: WebInspector.DataGrid.prototype.insertChild,
+ removeChild: WebInspector.DataGrid.prototype.removeChild,
+ removeChildren: WebInspector.DataGrid.prototype.removeChildren,
+ removeChildrenRecursive: WebInspector.DataGrid.prototype.removeChildrenRecursive,
+
+ _recalculateSiblings: function(myIndex)
+ {
+ if (!this.parent)
+ return;
+
+ var previousChild = (myIndex > 0 ? this.parent.children[myIndex - 1] : null);
+
+ if (previousChild) {
+ previousChild.nextSibling = this;
+ this.previousSibling = previousChild;
+ } else
+ this.previousSibling = null;
+
+ var nextChild = this.parent.children[myIndex + 1];
+
+ if (nextChild) {
+ nextChild.previousSibling = this;
+ this.nextSibling = nextChild;
+ } else
+ this.nextSibling = null;
+ },
+
+ collapse: function()
+ {
+ if (this._element)
+ this._element.removeStyleClass("expanded");
+
+ this._expanded = false;
+
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i].revealed = false;
+
+ this.dispatchEventToListeners("collapsed");
+ },
+
+ collapseRecursively: function()
+ {
+ var item = this;
+ while (item) {
+ if (item.expanded)
+ item.collapse();
+ item = item.traverseNextNode(false, this, true);
+ }
+ },
+
+ expand: function()
+ {
+ if (!this.hasChildren || this.expanded)
+ return;
+
+ if (this.revealed && !this._shouldRefreshChildren)
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i].revealed = true;
+
+ if (this._shouldRefreshChildren) {
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i]._detach();
+
+ this.dispatchEventToListeners("populate");
+
+ if (this._attached) {
+ for (var i = 0; i < this.children.length; ++i) {
+ var child = this.children[i];
+ if (this.revealed)
+ child.revealed = true;
+ child._attach();
+ }
+ }
+
+ delete this._shouldRefreshChildren;
+ }
+
+ if (this._element)
+ this._element.addStyleClass("expanded");
+
+ this._expanded = true;
+
+ this.dispatchEventToListeners("expanded");
+ },
+
+ expandRecursively: function()
+ {
+ var item = this;
+ while (item) {
+ item.expand();
+ item = item.traverseNextNode(false, this);
+ }
+ },
+
+ reveal: function()
+ {
+ var currentAncestor = this.parent;
+ while (currentAncestor && !currentAncestor.root) {
+ if (!currentAncestor.expanded)
+ currentAncestor.expand();
+ currentAncestor = currentAncestor.parent;
+ }
+
+ this.element.scrollIntoViewIfNeeded(false);
+
+ this.dispatchEventToListeners("revealed");
+ },
+
+ select: function(supressSelectedEvent)
+ {
+ if (!this.dataGrid || !this.selectable || this.selected)
+ return;
+
+ if (this.dataGrid.selectedNode)
+ this.dataGrid.selectedNode.deselect();
+
+ this._selected = true;
+ this.dataGrid.selectedNode = this;
+
+ if (this._element)
+ this._element.addStyleClass("selected");
+
+ if (!supressSelectedEvent)
+ this.dispatchEventToListeners("selected");
+ },
+
+ deselect: function(supressDeselectedEvent)
+ {
+ if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected)
+ return;
+
+ this._selected = false;
+ this.dataGrid.selectedNode = null;
+
+ if (this._element)
+ this._element.removeStyleClass("selected");
+
+ if (!supressDeselectedEvent)
+ this.dispatchEventToListeners("deselected");
+ },
+
+ traverseNextNode: function(skipHidden, stayWithin, dontPopulate, info)
+ {
+ if (!dontPopulate && this.hasChildren)
+ this.dispatchEventToListeners("populate");
+
+ if (info)
+ info.depthChange = 0;
+
+ var node = (!skipHidden || this.revealed) ? this.children[0] : null;
+ if (node && (!skipHidden || this.expanded)) {
+ if (info)
+ info.depthChange = 1;
+ return node;
+ }
+
+ if (this === stayWithin)
+ return null;
+
+ node = (!skipHidden || this.revealed) ? this.nextSibling : null;
+ if (node)
+ return node;
+
+ node = this;
+ while (node && !node.root && !((!skipHidden || node.revealed) ? node.nextSibling : null) && node.parent !== stayWithin) {
+ if (info)
+ info.depthChange -= 1;
+ node = node.parent;
+ }
+
+ if (!node)
+ return null;
+
+ return (!skipHidden || node.revealed) ? node.nextSibling : null;
+ },
+
+ traversePreviousNode: function(skipHidden, dontPopulate)
+ {
+ var node = (!skipHidden || this.revealed) ? this.previousSibling : null;
+ if (!dontPopulate && node && node.hasChildren)
+ node.dispatchEventToListeners("populate");
+
+ while (node && ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null)) {
+ if (!dontPopulate && node.hasChildren)
+ node.dispatchEventToListeners("populate");
+ node = ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null);
+ }
+
+ if (node)
+ return node;
+
+ if (!this.parent || this.parent.root)
+ return null;
+
+ return this.parent;
+ },
+
+ isEventWithinDisclosureTriangle: function(event)
+ {
+ if (!this.hasChildren)
+ return false;
+ var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
+ if (!cell.hasStyleClass("disclosure"))
+ return false;
+ var computedLeftPadding = window.getComputedStyle(cell).getPropertyCSSValue("padding-left").getFloatValue(CSSPrimitiveValue.CSS_PX);
+ var left = cell.totalOffsetLeft + computedLeftPadding;
+ return event.pageX >= left && event.pageX <= left + this.disclosureToggleWidth;
+ },
+
+ _attach: function()
+ {
+ if (!this.dataGrid || this._attached)
+ return;
+
+ this._attached = true;
+
+ var nextNode = null;
+ var previousNode = this.traversePreviousNode(true, true);
+ if (previousNode && previousNode.element.parentNode && previousNode.element.nextSibling)
+ var nextNode = previousNode.element.nextSibling;
+ if (!nextNode)
+ nextNode = this.dataGrid.dataTableBody.lastChild;
+ this.dataGrid.dataTableBody.insertBefore(this.element, nextNode);
+
+ if (this.expanded)
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i]._attach();
+ },
+
+ _detach: function()
+ {
+ if (!this._attached)
+ return;
+
+ this._attached = false;
+
+ if (this._element && this._element.parentNode)
+ this._element.parentNode.removeChild(this._element);
+
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i]._detach();
+ }
+}
+
+WebInspector.DataGridNode.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Database.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Database.js
new file mode 100644
index 0000000..ef42e15
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Database.js
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Database = function(database, domain, name, version)
+{
+ this.database = database;
+ this.domain = domain;
+ this.name = name;
+ this.version = version;
+}
+
+WebInspector.Database.prototype = {
+ get database()
+ {
+ return this._database;
+ },
+
+ set database(x)
+ {
+ if (this._database === x)
+ return;
+ this._database = x;
+ },
+
+ get name()
+ {
+ return this._name;
+ },
+
+ set name(x)
+ {
+ if (this._name === x)
+ return;
+ this._name = x;
+ },
+
+ get version()
+ {
+ return this._version;
+ },
+
+ set version(x)
+ {
+ if (this._version === x)
+ return;
+ this._version = x;
+ },
+
+ get domain()
+ {
+ return this._domain;
+ },
+
+ set domain(x)
+ {
+ if (this._domain === x)
+ return;
+ this._domain = x;
+ },
+
+ get displayDomain()
+ {
+ return WebInspector.Resource.prototype.__lookupGetter__("displayDomain").call(this);
+ },
+
+ get tableNames()
+ {
+ return InspectorController.databaseTableNames(this.database).sort();
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DatabaseQueryView.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DatabaseQueryView.js
new file mode 100644
index 0000000..122707f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DatabaseQueryView.js
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DatabaseQueryView = function(database)
+{
+ WebInspector.View.call(this);
+
+ this.database = database;
+
+ this.element.addStyleClass("storage-view");
+ this.element.addStyleClass("query");
+ this.element.tabIndex = 0;
+
+ this.element.addEventListener("selectstart", this._selectStart.bind(this), false);
+
+ this.promptElement = document.createElement("div");
+ this.promptElement.className = "database-query-prompt";
+ this.promptElement.appendChild(document.createElement("br"));
+ this.promptElement.handleKeyEvent = this._promptKeyDown.bind(this);
+ this.element.appendChild(this.promptElement);
+
+ this.prompt = new WebInspector.TextPrompt(this.promptElement, this.completions.bind(this), " ");
+}
+
+WebInspector.DatabaseQueryView.prototype = {
+ show: function(parentElement)
+ {
+ WebInspector.View.prototype.show.call(this, parentElement);
+
+ function moveBackIfOutside()
+ {
+ if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed)
+ this.prompt.moveCaretToEndOfPrompt();
+ }
+
+ setTimeout(moveBackIfOutside.bind(this), 0);
+ },
+
+ completions: function(wordRange, bestMatchOnly)
+ {
+ var prefix = wordRange.toString().toLowerCase();
+ if (!prefix.length)
+ return;
+
+ var results = [];
+
+ function accumulateMatches(textArray)
+ {
+ if (bestMatchOnly && results.length)
+ return;
+ for (var i = 0; i < textArray.length; ++i) {
+ var text = textArray[i].toLowerCase();
+ if (text.length < prefix.length)
+ continue;
+ if (text.indexOf(prefix) !== 0)
+ continue;
+ results.push(textArray[i]);
+ if (bestMatchOnly)
+ return;
+ }
+ }
+
+ accumulateMatches(this.database.tableNames.map(function(name) { return name + " " }));
+ accumulateMatches(["SELECT ", "FROM ", "WHERE ", "LIMIT ", "DELETE FROM ", "CREATE ", "DROP ", "TABLE ", "INDEX ", "UPDATE ", "INSERT INTO ", "VALUES ("]);
+
+ return results;
+ },
+
+ _promptKeyDown: function(event)
+ {
+ switch (event.keyIdentifier) {
+ case "Enter":
+ this._enterKeyPressed(event);
+ return;
+ }
+
+ this.prompt.handleKeyEvent(event);
+ },
+
+ _selectStart: function(event)
+ {
+ if (this._selectionTimeout)
+ clearTimeout(this._selectionTimeout);
+
+ this.prompt.clearAutoComplete();
+
+ function moveBackIfOutside()
+ {
+ delete this._selectionTimeout;
+ if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed)
+ this.prompt.moveCaretToEndOfPrompt();
+ this.prompt.autoCompleteSoon();
+ }
+
+ this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100);
+ },
+
+ _enterKeyPressed: function(event)
+ {
+ event.preventDefault();
+ event.stopPropagation();
+
+ this.prompt.clearAutoComplete(true);
+
+ var query = this.prompt.text;
+ if (!query.length)
+ return;
+
+ this.prompt.history.push(query);
+ this.prompt.historyOffset = 0;
+ this.prompt.text = "";
+
+ function queryTransaction(tx)
+ {
+ tx.executeSql(query, null, InspectorController.wrapCallback(this._queryFinished.bind(this, query)), InspectorController.wrapCallback(this._executeSqlError.bind(this, query)));
+ }
+
+ this.database.database.transaction(InspectorController.wrapCallback(queryTransaction.bind(this)), InspectorController.wrapCallback(this._queryError.bind(this, query)));
+ },
+
+ _queryFinished: function(query, tx, result)
+ {
+ var dataGrid = WebInspector.panels.databases.dataGridForResult(result);
+ dataGrid.element.addStyleClass("inline");
+ this._appendQueryResult(query, dataGrid.element);
+
+ if (query.match(/^create /i) || query.match(/^drop table /i))
+ WebInspector.panels.databases.updateDatabaseTables(this.database);
+ },
+
+ _queryError: function(query, error)
+ {
+ if (error.code == 1)
+ var message = error.message;
+ else if (error.code == 2)
+ var message = WebInspector.UIString("Database no longer has expected version.");
+ else
+ var message = WebInspector.UIString("An unexpected error %s occured.", error.code);
+
+ this._appendQueryResult(query, message, "error");
+ },
+
+ _executeSqlError: function(query, tx, error)
+ {
+ this._queryError(query, error);
+ },
+
+ _appendQueryResult: function(query, result, resultClassName)
+ {
+ var element = document.createElement("div");
+ element.className = "database-user-query";
+
+ var commandTextElement = document.createElement("span");
+ commandTextElement.className = "database-query-text";
+ commandTextElement.textContent = query;
+ element.appendChild(commandTextElement);
+
+ var resultElement = document.createElement("div");
+ resultElement.className = "database-query-result";
+
+ if (resultClassName)
+ resultElement.addStyleClass(resultClassName);
+
+ if (typeof result === "string" || result instanceof String)
+ resultElement.textContent = result;
+ else if (result && result.nodeName)
+ resultElement.appendChild(result);
+
+ if (resultElement.childNodes.length)
+ element.appendChild(resultElement);
+
+ this.element.insertBefore(element, this.promptElement);
+ this.promptElement.scrollIntoView(false);
+ }
+}
+
+WebInspector.DatabaseQueryView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DatabaseTableView.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DatabaseTableView.js
new file mode 100644
index 0000000..bbca9d0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DatabaseTableView.js
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DatabaseTableView = function(database, tableName)
+{
+ WebInspector.View.call(this);
+
+ this.database = database;
+ this.tableName = tableName;
+
+ this.element.addStyleClass("storage-view");
+ this.element.addStyleClass("table");
+
+ this.refreshButton = document.createElement("button");
+ this.refreshButton.title = WebInspector.UIString("Refresh");
+ this.refreshButton.className = "refresh-storage-status-bar-item status-bar-item";
+ this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
+}
+
+WebInspector.DatabaseTableView.prototype = {
+ show: function(parentElement)
+ {
+ WebInspector.View.prototype.show.call(this, parentElement);
+ this.update();
+ },
+
+ get statusBarItems()
+ {
+ return [this.refreshButton];
+ },
+
+ update: function()
+ {
+ function queryTransaction(tx)
+ {
+ tx.executeSql("SELECT * FROM " + this.tableName, null, InspectorController.wrapCallback(this._queryFinished.bind(this)), InspectorController.wrapCallback(this._queryError.bind(this)));
+ }
+
+ this.database.database.transaction(InspectorController.wrapCallback(queryTransaction.bind(this)), InspectorController.wrapCallback(this._queryError.bind(this)));
+ },
+
+ _queryFinished: function(tx, result)
+ {
+ this.element.removeChildren();
+
+ var dataGrid = WebInspector.panels.databases.dataGridForResult(result);
+ if (!dataGrid) {
+ var emptyMsgElement = document.createElement("div");
+ emptyMsgElement.className = "storage-table-empty";
+ emptyMsgElement.textContent = WebInspector.UIString("The “%s”\ntable is empty.", this.tableName);
+ this.element.appendChild(emptyMsgElement);
+ return;
+ }
+
+ this.element.appendChild(dataGrid.element);
+ },
+
+ _queryError: function(tx, error)
+ {
+ this.element.removeChildren();
+
+ var errorMsgElement = document.createElement("div");
+ errorMsgElement.className = "storage-table-error";
+ errorMsgElement.textContent = WebInspector.UIString("An error occurred trying to\nread the “%s” table.", this.tableName);
+ this.element.appendChild(errorMsgElement);
+ },
+
+ _refreshButtonClicked: function(event)
+ {
+ this.update();
+ }
+}
+
+WebInspector.DatabaseTableView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DatabasesPanel.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DatabasesPanel.js
new file mode 100644
index 0000000..4644b3b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DatabasesPanel.js
@@ -0,0 +1,526 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DatabasesPanel = function(database)
+{
+ WebInspector.Panel.call(this);
+
+ this.sidebarElement = document.createElement("div");
+ this.sidebarElement.id = "databases-sidebar";
+ this.sidebarElement.className = "sidebar";
+ this.element.appendChild(this.sidebarElement);
+
+ this.sidebarResizeElement = document.createElement("div");
+ this.sidebarResizeElement.className = "sidebar-resizer-vertical";
+ this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarDragging.bind(this), false);
+ this.element.appendChild(this.sidebarResizeElement);
+
+ this.sidebarTreeElement = document.createElement("ol");
+ this.sidebarTreeElement.className = "sidebar-tree";
+ this.sidebarElement.appendChild(this.sidebarTreeElement);
+
+ this.sidebarTree = new TreeOutline(this.sidebarTreeElement);
+
+ this.databasesListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("DATABASES"), {}, true);
+ this.sidebarTree.appendChild(this.databasesListTreeElement);
+ this.databasesListTreeElement.expand();
+
+ this.localStorageListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("LOCAL STORAGE"), {}, true);
+ this.sidebarTree.appendChild(this.localStorageListTreeElement);
+ this.localStorageListTreeElement.expand();
+
+ this.sessionStorageListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("SESSION STORAGE"), {}, true);
+ this.sidebarTree.appendChild(this.sessionStorageListTreeElement);
+ this.sessionStorageListTreeElement.expand();
+
+ this.storageViews = document.createElement("div");
+ this.storageViews.id = "storage-views";
+ this.element.appendChild(this.storageViews);
+
+ this.storageViewStatusBarItemsContainer = document.createElement("div");
+ this.storageViewStatusBarItemsContainer.id = "storage-view-status-bar-items";
+
+ this.reset();
+}
+
+WebInspector.DatabasesPanel.prototype = {
+ toolbarItemClass: "databases",
+
+ get toolbarItemLabel()
+ {
+ return WebInspector.UIString("Databases");
+ },
+
+ get statusBarItems()
+ {
+ return [this.storageViewStatusBarItemsContainer];
+ },
+
+ show: function()
+ {
+ WebInspector.Panel.prototype.show.call(this);
+ this._updateSidebarWidth();
+ },
+
+ reset: function()
+ {
+ if (this._databases) {
+ var databasesLength = this._databases.length;
+ for (var i = 0; i < databasesLength; ++i) {
+ var database = this._databases[i];
+
+ delete database._tableViews;
+ delete database._queryView;
+ }
+ }
+
+ this._databases = [];
+
+ if (this._domStorage) {
+ var domStorageLength = this._domStorage.length;
+ for (var i = 0; i < domStorageLength; ++i) {
+ var domStorage = this._domStorage[i];
+
+ delete domStorage._domStorageView;
+ }
+ }
+
+ this._domStorage = [];
+
+ this.databasesListTreeElement.removeChildren();
+ this.localStorageListTreeElement.removeChildren();
+ this.sessionStorageListTreeElement.removeChildren();
+ this.storageViews.removeChildren();
+
+ this.storageViewStatusBarItemsContainer.removeChildren();
+ },
+
+ handleKeyEvent: function(event)
+ {
+ this.sidebarTree.handleKeyEvent(event);
+ },
+
+ addDatabase: function(database)
+ {
+ this._databases.push(database);
+
+ var databaseTreeElement = new WebInspector.DatabaseSidebarTreeElement(database);
+ database._databasesTreeElement = databaseTreeElement;
+ this.databasesListTreeElement.appendChild(databaseTreeElement);
+ },
+
+ addDOMStorage: function(domStorage)
+ {
+ this._domStorage.push(domStorage);
+ var domStorageTreeElement = new WebInspector.DOMStorageSidebarTreeElement(domStorage);
+ domStorage._domStorageTreeElement = domStorageTreeElement;
+ if (domStorage.isLocalStorage)
+ this.localStorageListTreeElement.appendChild(domStorageTreeElement);
+ else
+ this.sessionStorageListTreeElement.appendChild(domStorageTreeElement);
+ },
+
+ showDatabase: function(database, tableName)
+ {
+ if (!database)
+ return;
+
+ if (this.visibleView)
+ this.visibleView.hide();
+
+ var view;
+ if (tableName) {
+ if (!("_tableViews" in database))
+ database._tableViews = {};
+ view = database._tableViews[tableName];
+ if (!view) {
+ view = new WebInspector.DatabaseTableView(database, tableName);
+ database._tableViews[tableName] = view;
+ }
+ } else {
+ view = database._queryView;
+ if (!view) {
+ view = new WebInspector.DatabaseQueryView(database);
+ database._queryView = view;
+ }
+ }
+
+ view.show(this.storageViews);
+
+ this.visibleView = view;
+
+ this.storageViewStatusBarItemsContainer.removeChildren();
+ var statusBarItems = view.statusBarItems;
+ for (var i = 0; i < statusBarItems.length; ++i)
+ this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
+ },
+
+ showDOMStorage: function(domStorage)
+ {
+ if (!domStorage)
+ return;
+
+ if (this.visibleView)
+ this.visibleView.hide();
+
+ var view;
+ view = domStorage._domStorageView;
+ if (!view) {
+ view = new WebInspector.DOMStorageItemsView(domStorage);
+ domStorage._domStorageView = view;
+ }
+
+ view.show(this.storageViews);
+
+ this.visibleView = view;
+
+ this.storageViewStatusBarItemsContainer.removeChildren();
+ var statusBarItems = view.statusBarItems;
+ for (var i = 0; i < statusBarItems.length; ++i)
+ this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
+ },
+
+ closeVisibleView: function()
+ {
+ if (this.visibleView)
+ this.visibleView.hide();
+ delete this.visibleView;
+ },
+
+ updateDatabaseTables: function(database)
+ {
+ if (!database || !database._databasesTreeElement)
+ return;
+
+ database._databasesTreeElement.shouldRefreshChildren = true;
+
+ if (!("_tableViews" in database))
+ return;
+
+ var tableNamesHash = {};
+ var tableNames = database.tableNames;
+ var tableNamesLength = tableNames.length;
+ for (var i = 0; i < tableNamesLength; ++i)
+ tableNamesHash[tableNames[i]] = true;
+
+ for (var tableName in database._tableViews) {
+ if (!(tableName in tableNamesHash)) {
+ if (this.visibleView === database._tableViews[tableName])
+ this.closeVisibleView();
+ delete database._tableViews[tableName];
+ }
+ }
+ },
+
+ dataGridForResult: function(result)
+ {
+ if (!result.rows.length)
+ return null;
+
+ var columns = {};
+
+ var rows = result.rows;
+ for (var columnIdentifier in rows.item(0)) {
+ var column = {};
+ column.width = columnIdentifier.length;
+ column.title = columnIdentifier;
+
+ columns[columnIdentifier] = column;
+ }
+
+ var nodes = [];
+ var length = rows.length;
+ for (var i = 0; i < length; ++i) {
+ var data = {};
+
+ var row = rows.item(i);
+ for (var columnIdentifier in row) {
+ // FIXME: (Bug 19439) We should specially format SQL NULL here
+ // (which is represented by JavaScript null here, and turned
+ // into the string "null" by the String() function).
+ var text = String(row[columnIdentifier]);
+ data[columnIdentifier] = text;
+ if (text.length > columns[columnIdentifier].width)
+ columns[columnIdentifier].width = text.length;
+ }
+
+ var node = new WebInspector.DataGridNode(data, false);
+ node.selectable = false;
+ nodes.push(node);
+ }
+
+ var totalColumnWidths = 0;
+ for (var columnIdentifier in columns)
+ totalColumnWidths += columns[columnIdentifier].width;
+
+ // Calculate the percentage width for the columns.
+ const minimumPrecent = 5;
+ var recoupPercent = 0;
+ for (var columnIdentifier in columns) {
+ var width = columns[columnIdentifier].width;
+ width = Math.round((width / totalColumnWidths) * 100);
+ if (width < minimumPrecent) {
+ recoupPercent += (minimumPrecent - width);
+ width = minimumPrecent;
+ }
+
+ columns[columnIdentifier].width = width;
+ }
+
+ // Enforce the minimum percentage width.
+ while (recoupPercent > 0) {
+ for (var columnIdentifier in columns) {
+ if (columns[columnIdentifier].width > minimumPrecent) {
+ --columns[columnIdentifier].width;
+ --recoupPercent;
+ if (!recoupPercent)
+ break;
+ }
+ }
+ }
+
+ // Change the width property to a string suitable for a style width.
+ for (var columnIdentifier in columns)
+ columns[columnIdentifier].width += "%";
+
+ var dataGrid = new WebInspector.DataGrid(columns);
+ var length = nodes.length;
+ for (var i = 0; i < length; ++i)
+ dataGrid.appendChild(nodes[i]);
+
+ return dataGrid;
+ },
+
+ dataGridForDOMStorage: function(domStorage)
+ {
+ if (!domStorage.length)
+ return null;
+
+ var columns = {};
+ columns[0] = {};
+ columns[1] = {};
+ columns[0].title = WebInspector.UIString("Key");
+ columns[0].width = columns[0].title.length;
+ columns[1].title = WebInspector.UIString("Value");
+ columns[1].width = columns[0].title.length;
+
+ var nodes = [];
+
+ var length = domStorage.length;
+ for (index = 0; index < domStorage.length; index++) {
+ var data = {};
+
+ var key = String(domStorage.key(index));
+ data[0] = key;
+ if (key.length > columns[0].width)
+ columns[0].width = key.length;
+
+ var value = String(domStorage.getItem(key));
+ data[1] = value;
+ if (value.length > columns[1].width)
+ columns[1].width = value.length;
+ var node = new WebInspector.DataGridNode(data, false);
+ node.selectable = true;
+ nodes.push(node);
+ }
+
+ var totalColumnWidths = columns[0].width + columns[1].width;
+ width = Math.round((columns[0].width * 100) / totalColumnWidths);
+ const minimumPrecent = 10;
+ if (width < minimumPrecent)
+ width = minimumPrecent;
+ if (width > 100 - minimumPrecent)
+ width = 100 - minimumPrecent;
+ columns[0].width = width;
+ columns[1].width = 100 - width;
+ columns[0].width += "%";
+ columns[1].width += "%";
+
+ var dataGrid = new WebInspector.DOMStorageDataGrid(columns);
+ var length = nodes.length;
+ for (var i = 0; i < length; ++i)
+ dataGrid.appendChild(nodes[i]);
+ if (length > 0)
+ nodes[0].selected = true;
+ return dataGrid;
+ },
+
+ _startSidebarDragging: function(event)
+ {
+ WebInspector.elementDragStart(this.sidebarResizeElement, this._sidebarDragging.bind(this), this._endSidebarDragging.bind(this), event, "col-resize");
+ },
+
+ _sidebarDragging: function(event)
+ {
+ this._updateSidebarWidth(event.pageX);
+
+ event.preventDefault();
+ },
+
+ _endSidebarDragging: function(event)
+ {
+ WebInspector.elementDragEnd(event);
+ },
+
+ _updateSidebarWidth: function(width)
+ {
+ if (this.sidebarElement.offsetWidth <= 0) {
+ // The stylesheet hasn't loaded yet or the window is closed,
+ // so we can't calculate what is need. Return early.
+ return;
+ }
+
+ if (!("_currentSidebarWidth" in this))
+ this._currentSidebarWidth = this.sidebarElement.offsetWidth;
+
+ if (typeof width === "undefined")
+ width = this._currentSidebarWidth;
+
+ width = Number.constrain(width, Preferences.minSidebarWidth, window.innerWidth / 2);
+
+ this._currentSidebarWidth = width;
+
+ this.sidebarElement.style.width = width + "px";
+ this.storageViews.style.left = width + "px";
+ this.storageViewStatusBarItemsContainer.style.left = width + "px";
+ this.sidebarResizeElement.style.left = (width - 3) + "px";
+ }
+}
+
+WebInspector.DatabasesPanel.prototype.__proto__ = WebInspector.Panel.prototype;
+
+WebInspector.DatabaseSidebarTreeElement = function(database)
+{
+ this.database = database;
+
+ WebInspector.SidebarTreeElement.call(this, "database-sidebar-tree-item", "", "", database, true);
+
+ this.refreshTitles();
+}
+
+WebInspector.DatabaseSidebarTreeElement.prototype = {
+ onselect: function()
+ {
+ WebInspector.panels.databases.showDatabase(this.database);
+ },
+
+ oncollapse: function()
+ {
+ // Request a refresh after every collapse so the next
+ // expand will have an updated table list.
+ this.shouldRefreshChildren = true;
+ },
+
+ onpopulate: function()
+ {
+ this.removeChildren();
+
+ var tableNames = this.database.tableNames;
+ var tableNamesLength = tableNames.length;
+ for (var i = 0; i < tableNamesLength; ++i)
+ this.appendChild(new WebInspector.SidebarDatabaseTableTreeElement(this.database, tableNames[i]));
+ },
+
+ get mainTitle()
+ {
+ return this.database.name;
+ },
+
+ set mainTitle(x)
+ {
+ // Do nothing.
+ },
+
+ get subtitle()
+ {
+ return this.database.displayDomain;
+ },
+
+ set subtitle(x)
+ {
+ // Do nothing.
+ }
+}
+
+WebInspector.DatabaseSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
+
+WebInspector.SidebarDatabaseTableTreeElement = function(database, tableName)
+{
+ this.database = database;
+ this.tableName = tableName;
+
+ WebInspector.SidebarTreeElement.call(this, "database-table-sidebar-tree-item small", tableName, "", null, false);
+}
+
+WebInspector.SidebarDatabaseTableTreeElement.prototype = {
+ onselect: function()
+ {
+ WebInspector.panels.databases.showDatabase(this.database, this.tableName);
+ }
+}
+
+WebInspector.SidebarDatabaseTableTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
+
+WebInspector.DOMStorageSidebarTreeElement = function(domStorage)
+{
+
+ this.domStorage = domStorage;
+
+ WebInspector.SidebarTreeElement.call(this, "domstorage-sidebar-tree-item", domStorage, "", null, false);
+
+ this.refreshTitles();
+}
+
+WebInspector.DOMStorageSidebarTreeElement.prototype = {
+ onselect: function()
+ {
+ WebInspector.panels.databases.showDOMStorage(this.domStorage);
+ },
+
+ get mainTitle()
+ {
+ return this.domStorage.domain;
+ },
+
+ set mainTitle(x)
+ {
+ // Do nothing.
+ },
+
+ get subtitle()
+ {
+ return ""; //this.database.displayDomain;
+ },
+
+ set subtitle(x)
+ {
+ // Do nothing.
+ }
+}
+
+WebInspector.DOMStorageSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DebuggerConsole.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DebuggerConsole.js
new file mode 100644
index 0000000..0ba3b28
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DebuggerConsole.js
@@ -0,0 +1,173 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Helper functions and objects for the JS debugger UI.
+ * @see debugger.html
+ */
+
+/**
+ * Document load listener.
+ */
+function onLoad() {
+ var debuggerConsole = new DebuggerConsole();
+ DebuggerIPC.init(debuggerConsole);
+ DebugShell.initDebugShell(debuggerConsole);
+ debuggerConsole.focusOnCommandLine();
+}
+
+/**
+ * @constructor
+ */
+function DebuggerConsole()
+{
+ this._output = document.getElementById("output");
+
+ var input = document.getElementById("command-line-text");
+ var self = this;
+ input.addEventListener(
+ 'keydown',
+ function(e) {
+ return self._onInputKeyDown(e);
+ },
+ true);
+ input.addEventListener(
+ 'keypress',
+ function(e) {
+ return self._onInputKeyPress(e);
+ },
+ true);
+ this._commandLineInput = input;
+
+ // command object stores command-line history state.
+ this._command = {
+ history: [],
+ history_index: 0,
+ pending: null
+ };
+};
+
+DebuggerConsole.prototype = {
+ /**
+ * Sets focus to command-line-text element.
+ */
+ focusOnCommandLine: function() {
+ this._commandLineInput.focus();
+ },
+
+ /**
+ * Called by chrome code when there's output to display.
+ * @param {string} txt
+ */
+ appendText: function(txt)
+ {
+ this._output.appendChild(document.createTextNode(txt));
+ this._output.appendChild(document.createElement('br'));
+ document.body.scrollTop = document.body.scrollHeight;
+ },
+
+ /**
+ * Called by chrome code to set the current state as to whether the debugger
+ * is stopped at a breakpoint or is running.
+ * @param {boolean} isBroken
+ */
+ setDebuggerBreak: function(isBroken)
+ {
+ var out = this._output;
+ if (isBroken) {
+ out.style.color = "black";
+ this.focusOnCommandLine();
+ } else {
+ out.style.color = "gray";
+ }
+ },
+
+ /**
+ * Execute a debugger command, add it to the command history and display it in
+ * the output window.
+ * @param {string} str
+ */
+ executeCommand: function(str) {
+ this.appendText("$ " + str);
+ // Sends message to DebuggerContents.HandleCommand.
+ if (DebugShell.singleton) {
+ DebugShell.singleton.command(str);
+ } else {
+ this.appendText("FAILED to send the command as DebugShell is null");
+ }
+
+ this._command.history.push(str);
+ this._command.history_index = this._command.history.length;
+ this._command.pending = null;
+ },
+
+
+ /**
+ * Display the previous history item in the given text field.
+ * @param {HTMLInputElement} field
+ */
+ selectPreviousCommand_: function(field) {
+ var command = this._command;
+ if (command.history_index > 0) {
+ // Remember the current field value as a pending command if we're at the
+ // end (it's something the user typed in).
+ if (command.history_index == command.history.length)
+ command.pending = field.value;
+ command.history_index--;
+ field.value = command.history[command.history_index];
+ field.select();
+ }
+ },
+
+ /**
+ * Display the next history item in the given text field.
+ * @param {HTMLInputElement} field
+ */
+ selectNextCommand_: function(field) {
+ var command = this._command;
+ if (command.history_index < command.history.length) {
+ command.history_index++;
+ if (command.history_index == command.history.length) {
+ field.value = command.pending || "";
+ } else {
+ field.value = command.history[command.history_index];
+ }
+ field.select();
+ }
+ },
+
+ /**
+ * command-line-text's onkeydown handler.
+ * @param {KeyboardEvent} e
+ * @return {boolean}
+ */
+ _onInputKeyDown: function (e) {
+ var field = e.target;
+ var key = e.keyCode;
+ if (key == 38) { // up arrow
+ this.selectPreviousCommand_(field);
+ return false;
+ } else if (key == 40) { // down arrow
+ this.selectNextCommand_(field);
+ return false;
+ }
+ return true;
+ },
+
+ /**
+ * command-line-text's onkeypress handler.
+ * @param {KeyboardEvent} e
+ * @return {boolean}
+ */
+ _onInputKeyPress: function (e) {
+ var field = e.target;
+ var key = e.keyCode;
+ if (key == 13) { // enter
+ this.executeCommand(field.value);
+ field.value = "";
+ return false;
+ }
+ return true;
+ }
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DebuggerIPC.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DebuggerIPC.js
new file mode 100644
index 0000000..15835fc
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DebuggerIPC.js
@@ -0,0 +1,109 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Implementation of debugger inter-process communication.
+ * Debugger UI can send messages to the DebuggerHost object living in
+ * Chrome browser process. The messages are either processed by DebuggerHost
+ * itself or trigger IPC message(such as break, evaluate script etc) from
+ * browser process to the renderer where the v8 instance being debugged
+ * will process them.
+ */
+
+var DebuggerIPC = {};
+
+/**
+ * Set up default debugger UI.
+ * @param {DebuggerPanel|DebuggerConsole} debuggerUI
+ */
+DebuggerIPC.init = function(debuggerUI) {
+ DebuggerIPC.debuggerUI = debuggerUI;
+}
+
+/**
+ * Sends JSON message to DebuggerHost.
+ * @param {Array.<Object>} nameAndArguments
+ */
+DebuggerIPC.sendMessage = function(nameAndArguments) {
+ //alert("DebuggerIPC.sendMessage " + nameAndArguments);
+ dprint("DebuggerIPC.callMethod([" + nameAndArguments + "])");
+ // convert all arguments to strings
+ // TODO(yurys): extend chrome.send to accept array of any value
+ // objects not only strings
+ for (var i = 0; i < nameAndArguments.length; i++) {
+ if (typeof nameAndArguments[i] != "string") {
+ nameAndArguments[i] = "" + nameAndArguments[i];
+ }
+ }
+
+ chrome.send("DebuggerHostMessage", nameAndArguments);
+};
+
+/**
+ * Handles messages from DebuggerHost.
+ * @param {Object} msg An object representing the message.
+ */
+DebuggerIPC.onMessageReceived = function(msg) {
+ //alert("DebuggerIPC.onMessageReceived " + msg.event);
+ var ui = DebuggerIPC.debuggerUI;
+ dprint("onMessageReceived: " + (msg && msg.event));
+ if (msg.type == "event") {
+ if (msg.event == "setDebuggerBreak") {
+ var val = msg.body.argument;
+ ui.setDebuggerBreak(val);
+ } else if (msg.event == "appendText") {
+ var text = msg.body.text;
+ ui.appendText(text);
+ } else if (msg.event == "focusOnCommandLine") {
+ dprint("focusOnCommandLine event received");
+ // messages to DebugShell
+ } else if (msg.event == "initDebugShell") {
+ // DebugShell.initDebugShell();
+ dprint(msg.event + " done");
+ } else if (msg.event == "on_attach") {
+ if (DebugShell.singleton) {
+ var args = msg.body.arguments;
+ if (!args || args.length != 1) {
+ dprint(msg.event + " failed: invalid arguments");
+ return;
+ }
+ var title = args[0];
+ DebugShell.singleton.on_attach(title);
+ dprint(msg.event + " done");
+ } else {
+ dprint(msg.event + " failed: DebugShell.singleton == null");
+ }
+ } else if (msg.event == "on_disconnect") {
+ if (DebugShell.singleton) {
+ DebugShell.singleton.on_disconnect();
+ dprint(msg.event + " done");
+ } else {
+ dprint(msg.event + " failed: DebugShell.singleton == null");
+ }
+ } else if (msg.event == "exit") {
+ if (DebugShell.singleton) {
+ DebugShell.singleton.exit();
+ dprint(msg.event + " done");
+ } else {
+ dprint(msg.event + " failed: DebugShell.singleton == null");
+ }
+ } else if (msg.event == "response") {
+ if (DebugShell.singleton) {
+ var args = msg.body.arguments;
+ if (!args || args.length != 1) {
+ dprint(msg.event + " failed: invalid argument");
+ return;
+ }
+ DebugShell.singleton.response(args[0]);
+ dprint(msg.event + " done");
+ } else {
+ ui.appendText(msg.event + " failed: DebugShell.singleton == null");
+ }
+ } else {
+ ui.appendText("Unknown event: " + msg.event);
+ }
+ } else {
+ ui.appendText("Unknown message type: " + msg.type);
+ }
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DebuggerPanel.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DebuggerPanel.js
new file mode 100644
index 0000000..bb059ac
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DebuggerPanel.js
@@ -0,0 +1,201 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview WebInspector panel representing command line debugger.
+ */
+
+/**
+ * Command line debugger panel.
+ * @constructor
+ * @extends {WebInspector.Panel}
+ */
+WebInspector.DebuggerPanel = function()
+{
+ WebInspector.Panel.call(this);
+
+ this.contentElement = document.createElement("div");
+ this.contentElement.id = "debugger-content";
+
+ var table = document.createElement("table");
+ table.id = 'outer';
+ var tr = document.createElement("tr");
+ this._output = document.createElement("td");
+ this._output.id = "output";
+ this._output.valign = "bottom";
+ this.appendText("Chrome JavaScript Debugger");
+ this.appendText("Type 'help' for a list of commands.");
+
+ tr.appendChild(this._output);
+ table.appendChild(tr);
+ this.contentElement.appendChild(table);
+
+
+ var commandLine = document.createElement("div");
+ commandLine.id = "command-line";
+ var input = document.createElement("input");
+ input.id = "command-line-text";
+ input.addEventListener('keydown', this._onInputKeyDown.bind(this), true);
+ input.addEventListener('keypress', this._onInputKeyPress.bind(this), true);
+ input.type = "text";
+ this.commandLineInput_ = input;
+
+ commandLine.appendChild(input);
+ this.contentElement.appendChild(commandLine);
+
+ // command object stores command-line history state.
+ this._command = {
+ history: [],
+ history_index: 0,
+ pending: null
+ };
+
+ this.element.appendChild(this.contentElement);
+ p('DebuggerPanel created');
+};
+
+WebInspector.DebuggerPanel.prototype = {
+ toolbarItemClass: "debugger",
+
+ get toolbarItemLabel()
+ {
+ return "Debugger"; //WebInspector.UIString("Debugger");
+ },
+
+ show: function()
+ {
+ WebInspector.Panel.prototype.show.call(this);
+ this.focusOnCommandLine();
+ },
+
+ /**
+ * Sets focus to command-line-text element.
+ */
+ focusOnCommandLine: function()
+ {
+ if (this.visible) {
+ this.commandLineInput_.focus();
+ }
+ },
+
+ /**
+ * Called by chrome code when there's output to display.
+ * @param {string} txt
+ */
+ appendText: function(txt)
+ {
+ this._output.appendChild(document.createTextNode(txt));
+ this._output.appendChild(document.createElement('br'));
+ },
+
+ /**
+ * Called by chrome code to set the current state as to whether the debugger
+ * is stopped at a breakpoint or is running.
+ * @param {boolean} isBroken
+ */
+ setDebuggerBreak: function(isBroken)
+ {
+ var out = this._output;
+ if (isBroken) {
+ out.style.color = "black";
+ this.focusOnCommandLine();
+ } else {
+ out.style.color = "gray";
+ }
+ },
+
+ /**
+ * Execute a debugger command, add it to the command history and display
+ * it in the output window.
+ * @param {string} str
+ */
+ executeCommand: function(str)
+ {
+ this.appendText("$ " + str);
+ // Sends message to DebuggerContents.HandleCommand.
+ if (DebugShell.singleton) {
+ DebugShell.singleton.command(str);
+ } else {
+ this.appendText("FAILED to send the command as DebugShell is null");
+ }
+
+ this._command.history.push(str);
+ this._command.history_index = this._command.history.length;
+ this._command.pending = null;
+ },
+
+ /**
+ * Display the previous history item in the given text field.
+ * @param {HTMLInputElement} field
+ */
+ _selectPreviousCommand: function(field)
+ {
+ var command = this._command;
+ if (command.history_index > 0) {
+ // Remember the current field value as a pending command if we're at the
+ // end (it's something the user typed in).
+ if (command.history_index == command.history.length)
+ command.pending = field.value;
+ command.history_index--;
+ field.value = command.history[command.history_index];
+ field.select();
+ }
+ },
+
+ /**
+ * Display the next history item in the given text field.
+ * @param {HTMLInputElement} field
+ */
+ _selectNextCommand: function(field)
+ {
+ var command = this._command;
+ if (command.history_index < command.history.length) {
+ command.history_index++;
+ if (command.history_index == command.history.length) {
+ field.value = command.pending || "";
+ } else {
+ field.value = command.history[command.history_index];
+ }
+ field.select();
+ }
+ },
+
+ /**
+ * command-line-text's onkeydown handler.
+ * @param {KeyboardEvent} e
+ * @return {boolean}
+ */
+ _onInputKeyDown: function (e)
+ {
+ var field = e.target;
+ var key = e.keyCode;
+ if (key == 38) { // up arrow
+ this._selectPreviousCommand(field);
+ return false;
+ } else if (key == 40) { // down arrow
+ this._selectNextCommand(field);
+ return false;
+ }
+ return true;
+ },
+
+ /**
+ * command-line-text's onkeypress handler.
+ * @param {KeyboardEvent} e
+ * @return {boolean}
+ */
+ _onInputKeyPress: function (e)
+ {
+ var field = e.target;
+ var key = e.keyCode;
+ if (key == 13) { // enter
+ this.executeCommand(field.value);
+ field.value = "";
+ return false;
+ }
+ return true;
+ }
+};
+
+WebInspector.DebuggerPanel.prototype.__proto__ = WebInspector.Panel.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DebuggerShell.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DebuggerShell.js
new file mode 100644
index 0000000..907dce7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/DebuggerShell.js
@@ -0,0 +1,1458 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Shell objects and global helper functions for Chrome
+ * automation shell / debugger. This file is loaded into the global namespace
+ * of the interactive shell, so users can simply call global functions
+ * directly.
+ */
+
+// TODO(erikkay): look into how this can be split up into multiple files
+// It's currently loaded explicitly by Chrome, so maybe I need an "include"
+// or "source" builtin to allow a core source file to reference multiple
+// sub-files.
+
+/**
+ * Sequence number of the DebugCommand.
+ */
+DebugCommand.next_seq_ = 0;
+
+/**
+ * Command messages to be sent to the debugger.
+ * @constructor
+ */
+function DebugCommand(str) {
+ this.command = undefined;
+ // first, strip off of the leading word as the command
+ var argv = str.split(' ');
+ this.user_command = argv.shift();
+ // the rest of the string is argv to the command
+ str = argv.join(' ');
+ if (DebugCommand.aliases[this.user_command])
+ this.user_command = DebugCommand.aliases[this.user_command];
+ if (this.parseArgs_(str) == 1)
+ this.type = "request";
+ if (this.command == undefined)
+ this.command = this.user_command;
+};
+
+// Mapping of some control characters to avoid the \uXXXX syntax for most
+// commonly used control cahracters.
+const ctrlCharMap_ = {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+};
+
+// Regular expression matching ", \ and control characters (0x00 - 0x1F)
+// globally.
+const ctrlCharMatch_ = /["\\\\\x00-\x1F]/g;
+
+/**
+ * Convert a String to its JSON representation.
+ * @param {String} value - String to be converted
+ * @return {String} JSON formatted String
+ */
+DebugCommand.stringToJSON = function(value) {
+ // Check for" , \ and control characters (0x00 - 0x1F).
+ if (ctrlCharMatch_.test(value)) {
+ // Replace ", \ and control characters (0x00 - 0x1F).
+ return '"' + value.replace(ctrlCharMatch_, function (char) {
+ // Use charmap if possible.
+ var mapped = ctrlCharMap_[char];
+ if (mapped) return mapped;
+ mapped = char.charCodeAt();
+ // Convert control character to unicode escape sequence.
+ var dig1 = (Math.floor(mapped / 16));
+ var dig2 = (mapped % 16)
+ return '\\u00' + dig1.toString(16) + dig2.toString(16);
+ })
+ + '"';
+ }
+
+ // Simple string with no special characters.
+ return '"' + value + '"';
+};
+
+/**
+ * @return {bool} True if x is an integer.
+ */
+DebugCommand.isInt = function(x) {
+ var y = parseInt(x);
+ if (isNaN(y))
+ return false;
+ return x == y && x.toString() == y.toString();
+};
+
+/**
+ * @return {float} log base 10 of num
+ */
+DebugCommand.log10 = function(num) {
+ return Math.log(num)/Math.log(10);
+};
+
+/**
+ * Take an object and encode it (non-recursively) as a JSON dict.
+ * @param {Object} obj - object to encode
+ */
+DebugCommand.toJSON = function(obj) {
+ // TODO(erikkay): use a real JSON library
+ var json = '{';
+ for (var key in obj) {
+ if (json.length > 1)
+ json += ",";
+ var val = obj[key];
+ if (!DebugCommand.isInt(val)) {
+ val = DebugCommand.stringToJSON(val.toString());
+ }
+ json += '"' + key + '":' + val;
+ }
+ json += '}';
+ return json;
+};
+
+/**
+ * Encode the DebugCommand object into the V8 debugger JSON protocol format.
+ */
+DebugCommand.prototype.toJSONProtocol = function() {
+ // TODO(erikkay): use a real JSON library
+ var json = '{';
+ json += '"seq":"' + this.seq;
+ json += '","type":"' + this.type;
+ json += '","command":"' + this.command + '"';
+ if (this.arguments) {
+ json += ',"arguments":' + DebugCommand.toJSON(this.arguments);
+ }
+ json += '}'
+ return json;
+}
+
+/**
+ * Encode the contents of this message and send it to the debugger.
+ * @param {Object} tab - tab being debugged. This is an internal
+ * Chrome object.
+ */
+DebugCommand.prototype.sendToDebugger = function(tab) {
+ this.seq = DebugCommand.next_seq_++;
+ str = this.toJSONProtocol();
+ dprint("sending: " + str);
+ tab.sendToDebugger(str);
+};
+
+DebugCommand.trim = function(str) {
+ return str.replace(/^\s*/, '').replace(/\s*$/, '');
+};
+
+/**
+ * Strip off a trailing parameter after a ':'. As the identifier for the
+ * source can contain ':' characters (e.g. 'http://www....) something after
+ * a ':' is only considered a parameter if it is numeric.
+ * @return {Array} two element array, the trimmed string and the parameter,
+ * or -1 if no parameter
+ */
+DebugCommand.stripTrailingParameter = function(str, opt_separator) {
+ var sep = opt_separator || ':';
+ var index = str.lastIndexOf(sep);
+ // If a separator character if found strip if numeric.
+ if (index != -1) {
+ var value = parseInt(str.substring(index + 1, str.length), 10);
+ if (isNaN(value) || value < 0) {
+ return [str, -1];
+ }
+ str = str.substring(0, index);
+ return [str, value];
+ }
+ return [str, -1];
+};
+
+/**
+ * Format source and location strings based on source location input data.
+ * @param {Object} script - script information object
+ * @param {String} source - source code for the current location
+ * @param {int} line - line number (0-based)
+ * @param {String} func - function name
+ * @return {array} [location(string), source line(string), line number(int)]
+ */
+DebugCommand.getSourceLocation = function(script, source, line, func) {
+ // source line is 0-based, we present as 1-based
+ line++;
+
+ // TODO(erikkay): take column into account as well
+ if (source)
+ source = "" + line + ": " + source;
+ var location = '';
+ if (func) {
+ location = func + ", ";
+ }
+ location += script ? script.name : '[no source]';
+ return [location, source, line];
+};
+
+/**
+ * Aliases for debugger commands.
+ */
+DebugCommand.aliases = {
+ 'b': 'break',
+ 'bi': 'break_info',
+ 'br': 'break',
+ 'bt': 'backtrace',
+ 'c': 'continue',
+ 'f': 'frame',
+ 'h': 'help',
+ '?': 'help',
+ 'ls': 'source',
+ 'n': 'next',
+ 'p': 'print',
+ 's': 'step',
+ 'so': 'stepout',
+};
+
+/**
+ * Parses arguments to "args" and "locals" command, and initializes
+ * the underlying DebugCommand (which is a frame request).
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseArgsAndLocals_ = function(str) {
+ this.command = "frame";
+ return str.length ? -1 : 1;
+};
+
+/**
+ * Parses arguments to "break_info" command, and executes it.
+ * "break_info" has an optional argument, which is the breakpoint
+ * identifier.
+ * @see DebugCommand.commands
+ * @param {string} str - The arguments to be parsed.
+ * @return -1 for usage error, 0 for success
+ */
+DebugCommand.prototype.parseBreakInfo_ = function(str) {
+ this.type = "shell";
+
+ // Array of breakpoints to be printed by this command
+ // (default to all breakpoints)
+ var breakpointsToPrint = shell_.breakpoints;
+
+ if (str.length > 0) {
+ // User specified an invalid breakpoint (not a number)
+ if (!str.match(/^\s*\d+\s*$/))
+ return -1; // invalid usage
+
+ // Check that the specified breakpoint identifier exists
+ var id = parseInt(str);
+ var info = shell_.breakpoints[id];
+ if (!info) {
+ print("Error: Invalid breakpoint");
+ return 0; // success (of sorts)
+ }
+ breakpointsToPrint = [info];
+ } else {
+ // breakpointsToPrint.length isn't accurate, because of
+ // deletions
+ var num_breakpoints = 0;
+ for (var i in breakpointsToPrint) num_breakpoints++;
+
+ print("Num breakpoints: " + num_breakpoints);
+ }
+
+ DebugShell.printBreakpoints_(breakpointsToPrint);
+
+ return 0; // success
+}
+
+/**
+ * Parses arguments to "step" command.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseStep_ = function(str, opt_stepaction) {
+ this.command = "continue";
+ action = opt_stepaction || "in";
+ this.arguments = {"stepaction" : action}
+ if (str.length) {
+ count = parseInt(str);
+ if (count > 0) {
+ this.arguments["stepcount"] = count;
+ } else {
+ return -1;
+ }
+ }
+ return 1;
+};
+
+/**
+ * Parses arguments to "step" command.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseStepOut_ = function(str) {
+ return this.parseStep_(str, "out");
+};
+
+/**
+ * Parses arguments to "next" command.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseNext_ = function(str) {
+ return this.parseStep_(str, "next");
+};
+
+/**
+ * Parse the arguments to "print" command.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return 1 - always succeeds
+ */
+DebugCommand.prototype.parsePrint_ = function(str) {
+ this.command = "evaluate";
+ this.arguments = { "expression" : str };
+ // If the page is in the running state, then we force the expression to
+ // evaluate in the global context to avoid evaluating in a random context.
+ if (shell_.running)
+ this.arguments["global"] = true;
+ return 1;
+};
+
+/**
+ * Handle the response to a "print" command and display output to user.
+ * @param {ProtocolPacket} evaluate_response - the V8 debugger response object
+ */
+DebugCommand.responsePrint_ = function(evaluate_response) {
+ body = evaluate_response.body();
+ if (body['text'] != undefined) {
+ print(body['text']);
+ } else {
+ // TODO(erikkay): is "text" ever not set?
+ print("can't print response");
+ }
+};
+
+/**
+ * Parse the arguments to "dir" command.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return 1 - always succeeds
+ */
+DebugCommand.prototype.parseDir_ = function(str) {
+ this.command = "evaluate";
+ this.arguments = { "expression" : str };
+ // If the page is in the running state, then we force the expression to
+ // evaluate in the global context to avoid evaluating in a random context.
+ if (shell_.running)
+ this.arguments["global"] = true;
+ return 1;
+};
+
+/**
+ * Handle the response to a "dir" command and display output to user.
+ * @see http://wiki/Main/V8Debugger
+ * @param {ProtocolPacket} evaluate_response - the V8 debugger response object
+ */
+DebugCommand.responseDir_ = function(evaluate_response) {
+ var body = evaluate_response.body();
+ if (body.properties) {
+ print(body.properties.length + ' properties');
+ for (var n in body.properties) {
+ var property_info = body.properties[n].name;
+ property_info += ': ';
+ var value = evaluate_response.lookup(body.properties[n].ref);
+ if (value && value.type) {
+ property_info += value.type;
+ } else {
+ property_info += '<no type>';
+ }
+ property_info += ' (#';
+ property_info += body.properties[n].ref;
+ property_info += '#)';
+ print(property_info);
+ }
+ }
+};
+
+/**
+ * Parses arguments to "break" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success, 0 for handled internally
+ */
+DebugCommand.prototype.parseBreak_ = function(str) {
+ function stripTrailingParameter() {
+ var ret = DebugCommand.stripTrailingParameter(str, ':');
+ str = ret[0];
+ return ret[1];
+ }
+
+ if (str.length == 0) {
+ this.command = "break";
+ return 1;
+ } else {
+ var parts = str.split(/\s+/);
+ var condition = null;
+ if (parts.length > 1) {
+ str = parts.shift();
+ condition = parts.join(" ");
+ }
+
+ this.command = "setbreakpoint";
+
+ // Locate ...[:line[:column]] if present.
+ var line = -1;
+ var column = -1;
+ line = stripTrailingParameter();
+ if (line != -1) {
+ line -= 1;
+ var l = stripTrailingParameter();
+ if (l != -1) {
+ column = line;
+ line = l - 1;
+ }
+ }
+
+ if (line == -1 && column == -1) {
+ this.arguments = { 'type' : 'function',
+ 'target' : str };
+ } else {
+ var script = shell_.matchScript(str, line);
+ if (script) {
+ this.arguments = { 'type' : 'script',
+ 'target' : script.name };
+ } else {
+ this.arguments = { 'type' : 'function',
+ 'target' : str };
+ }
+ this.arguments.line = line;
+ if (column != -1)
+ this.arguments.position = column;
+ }
+ if (condition)
+ this.arguments.condition = condition;
+ }
+ return 1;
+};
+
+/**
+ * Handle the response to a "break" command and display output to user.
+ * @param {ResponsePacket} setbreakpoint_response - the V8 debugger response
+ * object
+ */
+DebugCommand.responseBreak_ = function(setbreakpoint_response) {
+ var body = setbreakpoint_response.body();
+ var info = new BreakpointInfo(
+ parseInt(body.breakpoint),
+ setbreakpoint_response.command.arguments.type,
+ setbreakpoint_response.command.arguments.target,
+ setbreakpoint_response.command.arguments.line,
+ setbreakpoint_response.command.arguments.position,
+ setbreakpoint_response.command.arguments.condition);
+ shell_.addedBreakpoint(info);
+};
+
+/**
+ * Parses arguments to "backtrace" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+ DebugCommand.prototype.parseBacktrace_ = function(str) {
+ if (str.length > 0) {
+ var parts = str.split(/\s+/);
+ var non_empty_parts = parts.filter(function(s) { return s.length > 0; });
+ // We need exactly two arguments.
+ if (non_empty_parts.length != 2) {
+ return -1;
+ }
+ var from = parseInt(non_empty_parts[0], 10);
+ var to = parseInt(non_empty_parts[1], 10);
+ // The two arguments have to be integers.
+ if (from != non_empty_parts[0] || to != non_empty_parts[1]) {
+ return -1;
+ }
+ this.arguments = { 'fromFrame': from, 'toFrame': to + 1 };
+ } else {
+ // Default to fetching the first 10 frames.
+ this.arguments = { 'fromFrame': 0, 'toFrame': 10 };
+ }
+ return 1;
+};
+
+/**
+ * Handle the response to a "backtrace" command and display output to user.
+ * @param {ResponsePacket} backtrace_response - the V8 debugger response object
+ */
+DebugCommand.responseBacktrace_ = function(backtrace_response) {
+ body = backtrace_response.body();
+ if (body && body.totalFrames) {
+ print('Frames #' + body.fromFrame + ' to #' + (body.toFrame - 1) +
+ ' of ' + body.totalFrames + ":");
+ for (var i = 0; i < body.frames.length; i++) {
+ print(body.frames[i].text);
+ }
+ } else {
+ print("unimplemented (sorry)");
+ }
+};
+
+
+/**
+ * Parses arguments to "clear" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseClearCommand_ = function(str) {
+ this.command = "clearbreakpoint";
+ if (str.length > 0) {
+ var i = parseInt(str, 10);
+ if (i != str) {
+ return -1;
+ }
+ this.arguments = { 'breakpoint': i };
+ }
+ return 1;
+}
+
+/**
+ * Handle the response to a "clear" command and display output to user.
+ * @param {ResponsePacket} clearbreakpoint_response - the V8 debugger response
+ * object
+ */
+DebugCommand.responseClear_ = function(clearbreakpoint_response) {
+ var body = clearbreakpoint_response.body();
+ shell_.clearedBreakpoint(parseInt(msg.command.arguments.breakpoint));
+}
+
+
+/**
+ * Parses arguments to "continue" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseContinueCommand_ = function(str) {
+ this.command = "continue";
+ if (str.length > 0) {
+ return -1;
+ }
+ return 1;
+}
+
+/**
+ * Parses arguments to "frame" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseFrame_ = function(str) {
+ if (str.length > 0) {
+ var i = parseInt(str, 10);
+ if (i != str) {
+ return -1;
+ }
+ this.arguments = { 'number': i };
+ }
+ return 1;
+};
+
+/**
+ * Handle the response to a "frame" command and display output to user.
+ * @param {ResponsePacket} frame_response - the V8 debugger response object
+ */
+DebugCommand.responseFrame_ = function(frame_response) {
+ var body = frame_response.body();
+ var func = frame_response.lookup(body.func.ref);
+ loc = DebugCommand.getSourceLocation(func.script,
+ body.sourceLineText, body.line, func.name);
+ print("#" + (body.index <= 9 ? '0' : '') + body.index + " " + loc[0]);
+ print(loc[1]);
+ shell_.current_frame = body.index;
+ shell_.current_line = loc[2];
+ shell_.current_script = func.script;
+};
+
+/**
+ * Handle the response to a "args" command and display output to user.
+ * @param {ProtocolPacket} frame_response - the V8 debugger response object (for
+ * "frame" command)
+ */
+DebugCommand.responseArgs_ = function(frame_response) {
+ var body = frame_response.body();
+ DebugCommand.printVariables_(body.arguments, frame_response);
+}
+
+/**
+ * Handle the response to a "locals" command and display output to user.
+ * @param {Object} msg - the V8 debugger response object (for "frame" command)
+ */
+DebugCommand.responseLocals_ = function(frame_response) {
+ var body = frame_response.body();
+ DebugCommand.printVariables_(body.locals, frame_response);
+}
+
+DebugCommand.printVariables_ = function(variables, protocol_packet) {
+ for (var i = 0; i < variables.length; i++) {
+ print(variables[i].name + " = " +
+ DebugCommand.toPreviewString_(protocol_packet.lookup(variables[i].value.ref)));
+ }
+}
+
+DebugCommand.toPreviewString_ = function(value) {
+ // TODO(ericroman): pretty print arrays and objects, recursively.
+ // TODO(ericroman): truncate length of preview if too long?
+ if (value.type == "string") {
+ // Wrap the string in quote marks and JS-escape
+ return DebugCommand.stringToJSON(value.text);
+ }
+ return value.text;
+}
+
+/**
+ * Parses arguments to "scripts" command.
+ * @see DebugCommand.commands
+ * @param {string} str - The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseScripts_ = function(str) {
+ return 1
+};
+
+/**
+ * Handle the response to a "scripts" command and display output to user.
+ * @param {ResponsePacket} scripts_response - the V8 debugger response object
+ */
+DebugCommand.responseScripts_ = function(scripts_response) {
+ scripts = scripts_response.body();
+ shell_.scripts = [];
+ for (var i in scripts) {
+ var script = scripts[i];
+
+ // Add this script to the internal list of scripts.
+ shell_.scripts.push(script);
+
+ // Print result if this response was the result of a user command.
+ if (scripts_response.command.from_user) {
+ var name = script.name;
+ if (name) {
+ if (script.lineOffset > 0) {
+ print(name + " (lines " + script.lineOffset + "-" +
+ (script.lineOffset + script.lineCount - 1) + ")");
+ } else {
+ print(name + " (lines " + script.lineCount + ")");
+ }
+ } else {
+ // For unnamed scripts (typically eval) display some source.
+ var sourceStart = script.sourceStart;
+ if (sourceStart.length > 40)
+ sourceStart = sourceStart.substring(0, 37) + '...';
+ print("[unnamed] (source:\"" + sourceStart + "\")");
+ }
+ }
+ }
+};
+
+/**
+ * Parses arguments to "source" command.
+ * @see DebugCommand.commands
+ * @param {string} str - The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseSource_ = function(str) {
+ this.arguments = {};
+ if (this.current_frame > 0)
+ this.arguments.frame = this.current_frame;
+ if (str.length) {
+ var args = str.split(" ");
+ if (args.length == 1) {
+ // with 1 argument n, we print 10 lines starting at n
+ var num = parseInt(args[0]);
+ if (num > 0) {
+ this.arguments.fromLine = num - 1;
+ this.arguments.toLine = this.arguments.fromLine + 10;
+ } else {
+ return -1;
+ }
+ } else if (args.length == 2) {
+ // with 2 arguments x and y, we print from line x to line x + y
+ var from = parseInt(args[0]);
+ var len = parseInt(args[1]);
+ if (from > 0 && len > 0) {
+ this.arguments.fromLine = from - 1;
+ this.arguments.toLine = this.arguments.fromLine + len;
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ if (this.arguments.fromLine < 0)
+ return -1;
+ if (this.arguments.toLine <= this.arguments.fromLine)
+ return -1;
+ } else if (shell_.current_line > 0) {
+ // with no arguments, we print 11 lines with the current line as the center
+ this.arguments.fromLine =
+ Math.max(0, shell_.current_line - 6);
+ this.arguments.toLine = this.arguments.fromLine + 11;
+ }
+ return 1;
+};
+
+/**
+ * Handle the response to a "source" command and display output to user.
+ * @param {ProtocolPacket} source_response - the V8 debugger response object
+ */
+DebugCommand.responseSource_ = function(source_response) {
+ var body = source_response.body();
+ var from_line = parseInt(body.fromLine) + 1;
+ var source = body.source;
+ var lines = source.split('\n');
+ var maxdigits = 1 + Math.floor(DebugCommand.log10(from_line + lines.length))
+ for (var num in lines) {
+ // there's an extra newline at the end
+ if (num >= (lines.length - 1) && lines[num].length == 0)
+ break;
+ spacer = maxdigits - (1 + Math.floor(DebugCommand.log10(from_line)))
+ var line = "";
+ if (from_line == shell_.current_line) {
+ for (var i = 0; i < (maxdigits + 2); i++)
+ line += ">";
+ } else {
+ for (var i = 0; i < spacer; i++)
+ line += " ";
+ line += from_line + ": ";
+ }
+ line += lines[num];
+ print(line);
+ from_line++;
+ }
+};
+
+/**
+ * Parses arguments to "help" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return 0 for handled internally
+ */
+DebugCommand.parseHelp_ = function(str) {
+ DebugCommand.help(str);
+ return 0;
+};
+
+/**
+ * Takes argument and evaluates it in the context of the shell to allow commands
+ * to be escaped to the outer shell. Used primarily for development purposes.
+ * @see DebugCommand.commands
+ * @param {string} str The expression to be evaluated
+ * @return 0 for handled internally
+ */
+DebugCommand.parseShell_ = function(str) {
+ print(eval(str));
+ return 0;
+}
+
+DebugCommand.parseShellDebug_ = function(str) {
+ shell_.debug = !shell_.debug;
+ if (shell_.debug) {
+ print("shell debugging enabled");
+ } else {
+ print("shell debugging disabled");
+ }
+ return 0;
+}
+
+/**
+ * Parses a user-entered command string.
+ * @param {string} str The arguments to be parsed.
+ */
+DebugCommand.prototype.parseArgs_ = function(str) {
+ if (str.length)
+ str = DebugCommand.trim(str);
+ var cmd = DebugCommand.commands[this.user_command];
+ if (cmd) {
+ var parse = cmd['parse'];
+ if (parse == undefined) {
+ print('>>>can\'t find parse func for ' + this.user_command);
+ this.type = "error";
+ } else {
+ var ret = parse.call(this, str);
+ if (ret > 0) {
+ // Command gererated a debugger request.
+ this.type = "request";
+ } else if (ret == 0) {
+ // Command handeled internally.
+ this.type = "handled";
+ } else if (ret < 0) {
+ // Command error.
+ this.type = "handled";
+ DebugCommand.help(this.user_command);
+ }
+ }
+ } else {
+ this.type = "handled";
+ print('unknown command: ' + this.user_command);
+ DebugCommand.help();
+ }
+};
+
+/**
+ * Displays command help or all help.
+ * @param {string} opt_str Which command to print help for.
+ */
+DebugCommand.help = function(opt_str) {
+ if (opt_str) {
+ var cmd = DebugCommand.commands[opt_str];
+ var usage = cmd.usage;
+ print('usage: ' + usage);
+ // Print additional details for the command.
+ if (cmd.help) {
+ print(cmd.help);
+ }
+ } else {
+ if (shell_.running) {
+ print('Status: page is running');
+ } else {
+ print('Status: page is paused');
+ }
+ print('Available commands:');
+ for (var key in DebugCommand.commands) {
+ var cmd = DebugCommand.commands[key];
+ if (!cmd['hidden'] && (!shell_.running || cmd['while_running'])) {
+ var usage = cmd.usage;
+ print(' ' + usage);
+ }
+ }
+ }
+};
+
+/**
+ * Valid commands, their argument parser and their associated usage text.
+ */
+DebugCommand.commands = {
+ 'args': { 'parse': DebugCommand.prototype.parseArgsAndLocals_,
+ 'usage': 'args',
+ 'help': 'summarize the arguments to the current function.',
+ 'response': DebugCommand.responseArgs_ },
+ 'break': { 'parse': DebugCommand.prototype.parseBreak_,
+ 'response': DebugCommand.responseBreak_,
+ 'usage': 'break [location] <condition>',
+ 'help': 'location is one of <function> | <script:function> | <script:line> | <script:line:pos>',
+ 'while_running': true },
+ 'break_info': { 'parse': DebugCommand.prototype.parseBreakInfo_,
+ 'usage': 'break_info [breakpoint #]',
+ 'help': 'list the current breakpoints, or the details on a single one',
+ 'while_running': true },
+ 'backtrace': { 'parse': DebugCommand.prototype.parseBacktrace_,
+ 'response': DebugCommand.responseBacktrace_,
+ 'usage': 'backtrace [from frame #] [to frame #]' },
+ 'clear': { 'parse': DebugCommand.prototype.parseClearCommand_,
+ 'response': DebugCommand.responseClear_,
+ 'usage': 'clear <breakpoint #>',
+ 'while_running': true },
+ 'continue': { 'parse': DebugCommand.prototype.parseContinueCommand_,
+ 'usage': 'continue' },
+ 'dir': { 'parse': DebugCommand.prototype.parseDir_,
+ 'response': DebugCommand.responseDir_,
+ 'usage': 'dir <expression>',
+ 'while_running': true },
+ 'frame': { 'parse': DebugCommand.prototype.parseFrame_,
+ 'response': DebugCommand.responseFrame_,
+ 'usage': 'frame <frame #>' },
+ 'help': { 'parse': DebugCommand.parseHelp_,
+ 'usage': 'help [command]',
+ 'while_running': true },
+ 'locals': { 'parse': DebugCommand.prototype.parseArgsAndLocals_,
+ 'usage': 'locals',
+ 'help': 'summarize the local variables for current frame',
+ 'response': DebugCommand.responseLocals_ },
+ 'next': { 'parse': DebugCommand.prototype.parseNext_,
+ 'usage': 'next' } ,
+ 'print': { 'parse': DebugCommand.prototype.parsePrint_,
+ 'response': DebugCommand.responsePrint_,
+ 'usage': 'print <expression>',
+ 'while_running': true },
+ 'scripts': { 'parse': DebugCommand.prototype.parseScripts_,
+ 'response': DebugCommand.responseScripts_,
+ 'usage': 'scripts',
+ 'while_running': true },
+ 'source': { 'parse': DebugCommand.prototype.parseSource_,
+ 'response': DebugCommand.responseSource_,
+ 'usage': 'source [from line] | [<from line> <num lines>]' },
+ 'step': { 'parse': DebugCommand.prototype.parseStep_,
+ 'usage': 'step' },
+ 'stepout': { 'parse': DebugCommand.prototype.parseStepOut_,
+ 'usage': 'stepout' },
+ // local eval for debugging - remove this later
+ 'shell': { 'parse': DebugCommand.parseShell_,
+ 'usage': 'shell <expression>',
+ 'while_running': true,
+ 'hidden': true },
+ 'shelldebug': { 'parse': DebugCommand.parseShellDebug_,
+ 'usage': 'shelldebug',
+ 'while_running': true,
+ 'hidden': true },
+};
+
+
+/**
+ * Debug shell using the new JSON protocol
+ * @param {Object} tab - which tab is to be debugged. This is an internal
+ * Chrome object.
+ * @constructor
+ */
+function DebugShell(tab) {
+ this.tab = tab;
+ this.tab.attach();
+ this.ready = true;
+ this.running = true;
+ this.current_command = undefined;
+ this.pending_commands = [];
+ // The auto continue flag is used to indicate whether the JavaScript execution
+ // should automatically continue after a break event and the processing of
+ // pending commands. This is used to make it possible for the user to issue
+ // commands, e.g. setting break points, without making an explicit break. In
+ // this case the debugger will silently issue a forced break issue the command
+ // and silently continue afterwards.
+ this.auto_continue = false;
+ this.debug = false;
+ this.current_line = -1;
+ this.current_pos = -1;
+ this.current_frame = 0;
+ this.current_script = undefined;
+ this.scripts = [];
+
+ // Mapping of breakpoints id --> info.
+ // Must use numeric keys.
+ this.breakpoints = [];
+};
+
+DebugShell.prototype.set_ready = function(ready) {
+ if (ready != this.ready) {
+ this.ready = ready;
+ ChromeNode.setDebuggerReady(this.ready);
+ }
+};
+
+DebugShell.prototype.set_running = function(running) {
+ if (running != this.running) {
+ this.running = running;
+ ChromeNode.setDebuggerBreak(!this.running);
+ }
+};
+
+/**
+ * Execute a constructed DebugCommand object if possible, otherwise pend.
+ * @param cmd {DebugCommand} - command to execute
+ */
+DebugShell.prototype.process_command = function(cmd) {
+ dprint("Running: " + (this.running ? "yes" : "no"));
+
+ // The "break" commands needs to be handled seperatly
+ if (cmd.command == "break") {
+ if (this.running) {
+ // Schedule a break.
+ print("Stopping JavaScript execution...");
+ this.tab.debugBreak(false);
+ } else {
+ print("JavaScript execution already stopped.");
+ }
+ return;
+ }
+
+ // If page is running an break needs to be issued.
+ if (this.running) {
+ // Some requests are not valid when the page is running.
+ var cmd_info = DebugCommand.commands[cmd.user_command];
+ if (!cmd_info['while_running']) {
+ print(cmd.user_command + " can only be run while paused");
+ return;
+ }
+
+ // Add the command as pending before scheduling a break.
+ this.pending_commands.push(cmd);
+ dprint("pending command: " + cmd.toJSONProtocol());
+
+ // Schedule a forced break and enable auto continue.
+ this.tab.debugBreak(true);
+ this.auto_continue = true;
+ this.set_ready(false);
+ return;
+ }
+
+ // If waiting for a response add command as pending otherwise send the
+ // command.
+ if (this.current_command) {
+ this.pending_commands.push(cmd);
+ dprint("pending command: " + cmd.toJSONProtocol());
+ } else {
+ this.current_command = cmd;
+ cmd.sendToDebugger(this.tab);
+ this.set_ready(false);
+ }
+};
+
+/**
+ * Handle a break event from the debugger.
+ * @param msg {ResponsePacket} - break_event protocol message to handle
+ */
+DebugShell.prototype.event_break = function(break_event) {
+ this.current_frame = 0;
+ this.set_running(false);
+ var body = break_event.body();
+ if (body) {
+ this.current_script = body.script;
+ var loc = DebugCommand.getSourceLocation(body.script,
+ body.sourceLineText, body.sourceLine, body.invocationText);
+ var location = loc[0];
+ var source = loc[1];
+ this.current_line = loc[2];
+ if (body.breakpoints) {
+ // Always disable auto continue if a real break point is hit.
+ this.auto_continue = false;
+ var breakpoints = body.breakpoints;
+ print("paused at breakpoint " + breakpoints.join(",") + ": " +
+ location);
+ for (var i = 0; i < breakpoints.length; i++)
+ this.didHitBreakpoint(parseInt(breakpoints[i]));
+ } else if (body.scriptData == "") {
+ print("paused");
+ } else {
+ // step, stepout, next, "break" and a "debugger" line in the code
+ // are all treated the same (they're not really distinguishable anyway)
+ if (location != this.last_break_location) {
+ // We only print the location (function + script) when it changes,
+ // so as we step, you only see the source line when you transition
+ // to a new script and/or function. Also if auto continue is enables
+ // don't print the break location.
+ if (!this.auto_continue)
+ print(location);
+ }
+ }
+ // Print th current source line unless auto continue is enabled.
+ if (source && !this.auto_continue)
+ print(source);
+ this.last_break_location = location;
+ }
+ if (!this.auto_continue)
+ this.set_ready(true);
+};
+
+/**
+ * Handle an exception event from the debugger.
+ * @param msg {ResponsePacket} - exception_event protocol message to handle
+ */
+DebugShell.prototype.event_exception = function(exception_event) {
+ this.set_running(false);
+ this.set_ready(true);
+ var body = exception_event.body();
+ if (body) {
+ if (body["uncaught"]) {
+ print("uncaught exception " + body["exception"].text);
+ } else {
+ print("paused at exception " + body["exception"].text);
+ }
+ }
+};
+
+DebugShell.prototype.matchScript = function(script_match, line) {
+ var script = null;
+ // In the v8 debugger, all scripts have a name, line offset and line count
+ // Script names are usually URLs which are a pain to have to type again and
+ // again, so we match the tail end of the script name. This makes it easy
+ // to type break foo.js:23 rather than
+ // http://www.foo.com/bar/baz/quux/test/foo.js:23. In addition to the tail
+ // of the name we also look at the lines the script cover. If there are
+ // several scripts with the same tail including the requested line we match
+ // the first one encountered.
+ // TODO(sgjesse) Find how to handle several matching scripts.
+ var candidate_scripts = [];
+ for (var i in this.scripts) {
+ if (this.scripts[i].name &&
+ this.scripts[i].name.indexOf(script_match) >= 0) {
+ candidate_scripts.push(this.scripts[i]);
+ }
+ }
+ for (var i in candidate_scripts) {
+ var s = candidate_scripts[i];
+ var from = s.lineOffset;
+ var to = from + s.lineCount;
+ if (from <= line && line < to) {
+ script = s;
+ break;
+ }
+ }
+ if (script)
+ return script;
+ else
+ return null;
+}
+
+// The Chrome Subshell interface requires:
+// prompt(), command(), response(), exit() and on_disconnect()
+
+/**
+ * Called by Chrome Shell to get a prompt string to display.
+ */
+DebugShell.prototype.prompt = function() {
+ if (this.current_command)
+ return '';
+ if (!this.running)
+ return 'v8(paused)> ';
+ else
+ return 'v8(running)> ';
+};
+
+/**
+ * Called by Chrome Shell when command input has been received from the user.
+ */
+DebugShell.prototype.command = function(str) {
+ if (this.tab) {
+ str = DebugCommand.trim(str);
+ if (str.length) {
+ var cmd = new DebugCommand(str);
+ cmd.from_user = true;
+ if (cmd.type == "request")
+ this.process_command(cmd);
+ }
+ } else {
+ print(">>not connected to a tab");
+ }
+};
+
+/**
+ * Called by Chrome Shell when a response to a previous command has been
+ * received.
+ * @param {Object} msg Message object.
+ */
+DebugShell.prototype.response = function(msg) {
+ dprint("received: " + (msg && msg.type));
+ var response;
+ try {
+ response = new ProtocolPackage(msg);
+ } catch (error) {
+ print(error.toString(), str);
+ return;
+ }
+ if (response.type() == "event") {
+ ev = response.event();
+ if (ev == "break") {
+ this.event_break(response);
+ } else if (ev == "exception") {
+ this.event_exception(response);
+ }
+ } else if (response.type() == "response") {
+ if (response.requestSeq() != undefined) {
+ if (!this.current_command || this.current_command.seq != response.requestSeq()){
+ throw("received response to unknown command " + str);
+ }
+ } else {
+ // TODO(erikkay): should we reject these when they happen?
+ print(">>no request_seq in response " + str);
+ }
+ var cmd = DebugCommand.commands[this.current_command.user_command]
+ response.command = this.current_command;
+ this.current_command = null
+ this.set_running(response.running());
+ if (!response.success()) {
+ print(response.message());
+ } else {
+ var handler = cmd['response'];
+ if (handler != undefined) {
+ handler.call(this, response);
+ }
+ }
+ this.set_ready(true);
+ }
+
+ // Process next pending command if any.
+ if (this.pending_commands.length) {
+ this.process_command(this.pending_commands.shift());
+ } else if (this.auto_continue) {
+ // If no more pending commands and auto continue is active issue a continue command.
+ this.auto_continue = false;
+ this.process_command(new DebugCommand("continue"));
+ }
+};
+
+/**
+ * Called when a breakpoint has been set.
+ * @param {BreakpointInfo} info - details of breakpoint set.
+ */
+DebugShell.prototype.addedBreakpoint = function(info) {
+ print("set breakpoint #" + info.id);
+ this.breakpoints[info.id] = info;
+}
+
+/**
+ * Called when a breakpoint has been cleared.
+ * @param {int} id - the breakpoint number that was cleared.
+ */
+DebugShell.prototype.clearedBreakpoint = function(id) {
+ assertIsNumberType(id, "clearedBreakpoint called with invalid id");
+
+ print("cleared breakpoint #" + id);
+ delete this.breakpoints[id];
+}
+
+/**
+ * Called when a breakpoint has been reached.
+ * @param {int} id - the breakpoint number that was hit.
+ */
+DebugShell.prototype.didHitBreakpoint = function(id) {
+ assertIsNumberType(id, "didHitBreakpoint called with invalid id");
+
+ var info = this.breakpoints[id];
+ if (!info)
+ throw "Could not find breakpoint #" + id;
+
+ info.hit_count ++;
+}
+
+/**
+ * Print a summary of the specified breakpoints.
+ *
+ * @param {Array<BreakpointInfo>} breakpointsToPrint - List of breakpoints. The
+ * index is unused (id is determined from the info).
+ */
+DebugShell.printBreakpoints_ = function(breakpoints) {
+ // TODO(ericroman): this would look much nicer if we could output as an HTML
+ // table. I tried outputting as formatted text table, but this looks aweful
+ // once it triggers wrapping (which is very likely if the target is a script)
+
+ // Output as a comma separated list of key=value
+ for (var i in breakpoints) {
+ var b = breakpoints[i];
+ var props = ["id", "hit_count", "type", "target", "line", "position",
+ "condition"];
+ var propertyList = [];
+ for (var i = 0; i < props.length; i++) {
+ var prop = props[i];
+ var val = b[prop];
+ if (val != undefined)
+ propertyList.push(prop + "=" + val);
+ }
+ print(propertyList.join(", "));
+ }
+}
+
+/**
+ * Called by Chrome Shell when the outer shell is detaching from debugging
+ * this tab.
+ */
+DebugShell.prototype.exit = function() {
+ if (this.tab) {
+ this.tab.detach();
+ this.tab = null;
+ }
+};
+
+/**
+ * Called by the Chrome Shell when the tab that the shell is debugging
+ * have attached.
+ */
+DebugShell.prototype.on_attach = function(title) {
+ if (!title)
+ title = "Untitled";
+ print('attached to ' + title);
+ // on attach, we update our current script list
+ var cmd = new DebugCommand("scripts");
+ cmd.from_user = false;
+ this.process_command(cmd);
+};
+
+
+/**
+ * Called by the Chrome Shell when the tab that the shell is debugging
+ * went away.
+ */
+DebugShell.prototype.on_disconnect = function() {
+ print(">>lost connection to tab");
+ this.tab = null;
+};
+
+
+/**
+ * Protocol packages send from the debugger.
+ * @param {string} json - raw protocol packet as JSON string.
+ * @constructor
+ */
+function ProtocolPackage(msg) {
+ this.packet_ = 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];
+ }
+ }
+}
+
+
+/**
+ * Get the packet type.
+ * @return {String} the packet type
+ */
+ProtocolPackage.prototype.type = function() {
+ return this.packet_.type;
+}
+
+
+/**
+ * Get the packet event.
+ * @return {Object} the packet event
+ */
+ProtocolPackage.prototype.event = function() {
+ return this.packet_.event;
+}
+
+
+/**
+ * Get the packet request sequence.
+ * @return {number} the packet request sequence
+ */
+ProtocolPackage.prototype.requestSeq = function() {
+ return this.packet_.request_seq;
+}
+
+
+/**
+ * Get the packet request sequence.
+ * @return {number} the packet request sequence
+ */
+ProtocolPackage.prototype.running = function() {
+ return this.packet_.running ? true : false;
+}
+
+
+ProtocolPackage.prototype.success = function() {
+ return this.packet_.success ? true : false;
+}
+
+
+ProtocolPackage.prototype.message = function() {
+ return this.packet_.message;
+}
+
+
+ProtocolPackage.prototype.body = function() {
+ return this.packet_.body;
+}
+
+
+ProtocolPackage.prototype.lookup = function(handle) {
+ return this.refs_[handle];
+}
+
+
+/**
+ * Structure that holds the details about a breakpoint.
+ * @constructor
+ *
+ * @param {int} id - breakpoint number
+ * @param {string} type - "script" or "function"
+ * @param {string} target - either a function name, or script url
+ * @param {int} line - line number in the script, or undefined
+ * @param {int} position - column in the script, or undefined
+ * @param {string} condition - boolean expression, or undefined
+ */
+function BreakpointInfo(id, type, target, line, position, condition) {
+ this.id = id;
+ this.type = type;
+ this.target = target;
+
+ if (line != undefined)
+ this.line = line;
+ if (position != undefined)
+ this.position = position;
+ if (condition != undefined)
+ this.condition = condition;
+
+ this.hit_count = 0;
+
+ // Check that the id is numeric, otherwise will run into problems later
+ assertIsNumberType(this.id, "id is not a number");
+}
+
+var shell_ = null;
+DebugShell.initDebugShell = function(debuggerUI) {
+ if (!DebugShell.singleton) {
+ DebugShell.ui = debuggerUI;
+ DebugShell.singleton = new DebugShell(TabNode);
+ shell_ = DebugShell.singleton;
+
+ // enable debug output
+ //shell_.debug = true;
+ }
+};
+
+/**
+ * Print debugging message when DebugShell's debug flag is true.
+ */
+function dprint(str) {
+ if (shell_ && shell_.debug) {
+ print(str);
+ }
+};
+
+/**
+ * Helper that throws error if x is not a number
+ * @param x {object} - object to test type of
+ * @param error_message {string} - error to throw on failure
+ */
+function assertIsNumberType(x, error_message) {
+ if (typeof x != "number")
+ throw error_message;
+}
+
+////////////////////// migration staff //////////////////////////
+// This file was copied from chrome\browser\debugger\resources\debugger_shell.js
+
+function print(txt) {
+ var ui = DebugShell.ui;
+ if (ui) {
+ ui.appendText(txt);
+ }
+}
+
+var TabNode = {
+ debugBreak: function(force) {
+ DebuggerIPC.sendMessage(["debugBreak", force]);
+ },
+ attach: function() {
+ DebuggerIPC.sendMessage(["attach"]);
+ },
+ detach: function() {
+ // TODO(yurys): send this from DebugHandler when it's being destroyed?
+ DebuggerIPC.sendMessage(["detach"]);
+ },
+ sendToDebugger: function(str) {
+ DebuggerIPC.sendMessage(["sendToDebugger", str]);
+ }
+};
+
+var ChromeNode = {
+ setDebuggerReady: function(isReady) {
+ DebuggerIPC.sendMessage(["setDebuggerReady", isReady]);
+ },
+ setDebuggerBreak: function(isBreak) {
+ var ui = DebugShell.ui;
+ if (ui) {
+ ui.setDebuggerBreak(isBreak);
+ }
+ DebuggerIPC.sendMessage(["setDebuggerBreak", isBreak]);
+ }
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ElementsPanel.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ElementsPanel.js
new file mode 100644
index 0000000..3c9be54
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ElementsPanel.js
@@ -0,0 +1,1206 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ElementsPanel = function()
+{
+ WebInspector.Panel.call(this);
+
+ this.element.addStyleClass("elements");
+
+ this.contentElement = document.createElement("div");
+ this.contentElement.id = "elements-content";
+ this.contentElement.className = "outline-disclosure";
+
+ this.treeOutline = new WebInspector.ElementsTreeOutline();
+ this.treeOutline.panel = this;
+ this.treeOutline.includeRootDOMNode = false;
+ this.treeOutline.selectEnabled = true;
+
+ this.treeOutline.focusedNodeChanged = function(forceUpdate)
+ {
+ if (this.panel.visible && WebInspector.currentFocusElement !== document.getElementById("search"))
+ WebInspector.currentFocusElement = document.getElementById("main-panels");
+
+ this.panel.updateBreadcrumb(forceUpdate);
+
+ for (var pane in this.panel.sidebarPanes)
+ this.panel.sidebarPanes[pane].needsUpdate = true;
+
+ this.panel.updateStyles(true);
+ this.panel.updateMetrics();
+ this.panel.updateProperties();
+
+ if (InspectorController.searchingForNode()) {
+ InspectorController.toggleNodeSearch();
+ this.panel.nodeSearchButton.removeStyleClass("toggled-on");
+ }
+ };
+
+ this.contentElement.appendChild(this.treeOutline.element);
+
+ this.crumbsElement = document.createElement("div");
+ this.crumbsElement.className = "crumbs";
+ this.crumbsElement.addEventListener("mousemove", this._mouseMovedInCrumbs.bind(this), false);
+ this.crumbsElement.addEventListener("mouseout", this._mouseMovedOutOfCrumbs.bind(this), false);
+
+ this.sidebarPanes = {};
+ this.sidebarPanes.styles = new WebInspector.StylesSidebarPane();
+ this.sidebarPanes.metrics = new WebInspector.MetricsSidebarPane();
+ this.sidebarPanes.properties = new WebInspector.PropertiesSidebarPane();
+
+ this.sidebarPanes.styles.onexpand = this.updateStyles.bind(this);
+ this.sidebarPanes.metrics.onexpand = this.updateMetrics.bind(this);
+ this.sidebarPanes.properties.onexpand = this.updateProperties.bind(this);
+
+ this.sidebarPanes.styles.expanded = true;
+
+ this.sidebarPanes.styles.addEventListener("style edited", this._stylesPaneEdited, this);
+ this.sidebarPanes.styles.addEventListener("style property toggled", this._stylesPaneEdited, this);
+ this.sidebarPanes.metrics.addEventListener("metrics edited", this._metricsPaneEdited, this);
+
+ this.sidebarElement = document.createElement("div");
+ this.sidebarElement.id = "elements-sidebar";
+
+ this.sidebarElement.appendChild(this.sidebarPanes.styles.element);
+ this.sidebarElement.appendChild(this.sidebarPanes.metrics.element);
+ this.sidebarElement.appendChild(this.sidebarPanes.properties.element);
+
+ this.sidebarResizeElement = document.createElement("div");
+ this.sidebarResizeElement.className = "sidebar-resizer-vertical";
+ this.sidebarResizeElement.addEventListener("mousedown", this.rightSidebarResizerDragStart.bind(this), false);
+
+ this.nodeSearchButton = document.createElement("button");
+ this.nodeSearchButton.title = WebInspector.UIString("Select an element in the page to inspect it.");
+ this.nodeSearchButton.id = "node-search-status-bar-item";
+ this.nodeSearchButton.className = "status-bar-item";
+ this.nodeSearchButton.addEventListener("click", this._nodeSearchButtonClicked.bind(this), false);
+
+ this.searchingForNode = false;
+
+ this.element.appendChild(this.contentElement);
+ this.element.appendChild(this.sidebarElement);
+ this.element.appendChild(this.sidebarResizeElement);
+
+ this._mutationMonitoredWindows = [];
+ this._nodeInsertedEventListener = InspectorController.wrapCallback(this._nodeInserted.bind(this));
+ this._nodeRemovedEventListener = InspectorController.wrapCallback(this._nodeRemoved.bind(this));
+ this._contentLoadedEventListener = InspectorController.wrapCallback(this._contentLoaded.bind(this));
+
+ this.reset();
+}
+
+WebInspector.ElementsPanel.prototype = {
+ toolbarItemClass: "elements",
+
+ get toolbarItemLabel()
+ {
+ return WebInspector.UIString("Elements");
+ },
+
+ get statusBarItems()
+ {
+ return [this.nodeSearchButton, this.crumbsElement];
+ },
+
+ updateStatusBarItems: function()
+ {
+ this.updateBreadcrumbSizes();
+ },
+
+ show: function()
+ {
+ WebInspector.Panel.prototype.show.call(this);
+ this.sidebarResizeElement.style.right = (this.sidebarElement.offsetWidth - 3) + "px";
+ this.updateBreadcrumb();
+ this.treeOutline.updateSelection();
+ if (this.recentlyModifiedNodes.length)
+ this._updateModifiedNodes();
+ },
+
+ hide: function()
+ {
+ WebInspector.Panel.prototype.hide.call(this);
+
+ WebInspector.hoveredDOMNode = null;
+
+ if (InspectorController.searchingForNode()) {
+ InspectorController.toggleNodeSearch();
+ this.nodeSearchButton.removeStyleClass("toggled-on");
+ }
+ },
+
+ resize: function()
+ {
+ this.treeOutline.updateSelection();
+ this.updateBreadcrumbSizes();
+ },
+
+ reset: function()
+ {
+ this.rootDOMNode = null;
+ this.focusedDOMNode = null;
+
+ WebInspector.hoveredDOMNode = null;
+
+ if (InspectorController.searchingForNode()) {
+ InspectorController.toggleNodeSearch();
+ this.nodeSearchButton.removeStyleClass("toggled-on");
+ }
+
+ this.recentlyModifiedNodes = [];
+ this.unregisterAllMutationEventListeners();
+
+ delete this.currentQuery;
+ this.searchCanceled();
+
+ var inspectedWindow = InspectorController.inspectedWindow();
+ if (!inspectedWindow || !inspectedWindow.document)
+ return;
+
+ if (!inspectedWindow.document.firstChild) {
+ function contentLoaded()
+ {
+ inspectedWindow.document.removeEventListener("DOMContentLoaded", contentLoadedCallback, false);
+
+ this.reset();
+ }
+
+ var contentLoadedCallback = InspectorController.wrapCallback(contentLoaded.bind(this));
+ inspectedWindow.document.addEventListener("DOMContentLoaded", contentLoadedCallback, false);
+ return;
+ }
+
+ // If the window isn't visible, return early so the DOM tree isn't built
+ // and mutation event listeners are not added.
+ if (!InspectorController.isWindowVisible())
+ return;
+
+ this.registerMutationEventListeners(inspectedWindow);
+
+ var inspectedRootDocument = inspectedWindow.document;
+ this.rootDOMNode = inspectedRootDocument;
+
+ var canidateFocusNode = inspectedRootDocument.body || inspectedRootDocument.documentElement;
+ if (canidateFocusNode) {
+ this.treeOutline.suppressSelectHighlight = true;
+ this.focusedDOMNode = canidateFocusNode;
+ this.treeOutline.suppressSelectHighlight = false;
+
+ if (this.treeOutline.selectedTreeElement)
+ this.treeOutline.selectedTreeElement.expand();
+ }
+ },
+
+ includedInSearchResultsPropertyName: "__includedInInspectorSearchResults",
+
+ searchCanceled: function()
+ {
+ if (this._searchResults) {
+ const searchResultsProperty = this.includedInSearchResultsPropertyName;
+ for (var i = 0; i < this._searchResults.length; ++i) {
+ var node = this._searchResults[i];
+
+ // Remove the searchResultsProperty since there might be an unfinished search.
+ delete node[searchResultsProperty];
+
+ var treeElement = this.treeOutline.findTreeElement(node);
+ if (treeElement)
+ treeElement.highlighted = false;
+ }
+ }
+
+ WebInspector.updateSearchMatchesCount(0, this);
+
+ if (this._currentSearchChunkIntervalIdentifier) {
+ clearInterval(this._currentSearchChunkIntervalIdentifier);
+ delete this._currentSearchChunkIntervalIdentifier;
+ }
+
+ this._currentSearchResultIndex = 0;
+ this._searchResults = [];
+ },
+
+ performSearch: function(query)
+ {
+ // Call searchCanceled since it will reset everything we need before doing a new search.
+ this.searchCanceled();
+
+ const whitespaceTrimmedQuery = query.trimWhitespace();
+ if (!whitespaceTrimmedQuery.length)
+ return;
+
+ var tagNameQuery = whitespaceTrimmedQuery;
+ var attributeNameQuery = whitespaceTrimmedQuery;
+ var startTagFound = (tagNameQuery.indexOf("<") === 0);
+ var endTagFound = (tagNameQuery.lastIndexOf(">") === (tagNameQuery.length - 1));
+
+ if (startTagFound || endTagFound) {
+ var tagNameQueryLength = tagNameQuery.length;
+ tagNameQuery = tagNameQuery.substring((startTagFound ? 1 : 0), (endTagFound ? (tagNameQueryLength - 1) : tagNameQueryLength));
+ }
+
+ // Check the tagNameQuery is it is a possibly valid tag name.
+ if (!/^[a-zA-Z0-9\-_:]+$/.test(tagNameQuery))
+ tagNameQuery = null;
+
+ // Check the attributeNameQuery is it is a possibly valid tag name.
+ if (!/^[a-zA-Z0-9\-_:]+$/.test(attributeNameQuery))
+ attributeNameQuery = null;
+
+ const escapedQuery = query.escapeCharacters("'");
+ const escapedTagNameQuery = (tagNameQuery ? tagNameQuery.escapeCharacters("'") : null);
+ const escapedWhitespaceTrimmedQuery = whitespaceTrimmedQuery.escapeCharacters("'");
+ const searchResultsProperty = this.includedInSearchResultsPropertyName;
+
+ var updatedMatchCountOnce = false;
+ var matchesCountUpdateTimeout = null;
+
+ function updateMatchesCount()
+ {
+ WebInspector.updateSearchMatchesCount(this._searchResults.length, this);
+ matchesCountUpdateTimeout = null;
+ updatedMatchCountOnce = true;
+ }
+
+ function updateMatchesCountSoon()
+ {
+ if (!updatedMatchCountOnce)
+ return updateMatchesCount.call(this);
+ if (matchesCountUpdateTimeout)
+ return;
+ // Update the matches count every half-second so it doesn't feel twitchy.
+ matchesCountUpdateTimeout = setTimeout(updateMatchesCount.bind(this), 500);
+ }
+
+ function addNodesToResults(nodes, length, getItem)
+ {
+ if (!length)
+ return;
+
+ for (var i = 0; i < length; ++i) {
+ var node = getItem.call(nodes, i);
+ // Skip this node if it already has the property.
+ if (searchResultsProperty in node)
+ continue;
+
+ if (!this._searchResults.length) {
+ this._currentSearchResultIndex = 0;
+ this.focusedDOMNode = node;
+ }
+
+ node[searchResultsProperty] = true;
+ this._searchResults.push(node);
+
+ // Highlight the tree element to show it matched the search.
+ // FIXME: highlight the substrings in text nodes and attributes.
+ var treeElement = this.treeOutline.findTreeElement(node);
+ if (treeElement)
+ treeElement.highlighted = true;
+ }
+
+ updateMatchesCountSoon.call(this);
+ }
+
+ function matchExactItems(doc)
+ {
+ matchExactId.call(this, doc);
+ matchExactClassNames.call(this, doc);
+ matchExactTagNames.call(this, doc);
+ matchExactAttributeNames.call(this, doc);
+ }
+
+ function matchExactId(doc)
+ {
+ const result = doc.__proto__.getElementById.call(doc, whitespaceTrimmedQuery);
+ addNodesToResults.call(this, result, (result ? 1 : 0), function() { return this });
+ }
+
+ function matchExactClassNames(doc)
+ {
+ const result = doc.__proto__.getElementsByClassName.call(doc, whitespaceTrimmedQuery);
+ addNodesToResults.call(this, result, result.length, result.item);
+ }
+
+ function matchExactTagNames(doc)
+ {
+ if (!tagNameQuery)
+ return;
+ const result = doc.__proto__.getElementsByTagName.call(doc, tagNameQuery);
+ addNodesToResults.call(this, result, result.length, result.item);
+ }
+
+ function matchExactAttributeNames(doc)
+ {
+ if (!attributeNameQuery)
+ return;
+ const result = doc.__proto__.querySelectorAll.call(doc, "[" + attributeNameQuery + "]");
+ addNodesToResults.call(this, result, result.length, result.item);
+ }
+
+ function matchPartialTagNames(doc)
+ {
+ if (!tagNameQuery)
+ return;
+ const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function matchStartOfTagNames(doc)
+ {
+ if (!tagNameQuery)
+ return;
+ const result = doc.__proto__.evaluate.call(doc, "//*[starts-with(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function matchPartialTagNamesAndAttributeValues(doc)
+ {
+ if (!tagNameQuery) {
+ matchPartialAttributeValues.call(this, doc);
+ return;
+ }
+
+ const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "') or contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function matchPartialAttributeValues(doc)
+ {
+ const result = doc.__proto__.evaluate.call(doc, "//*[contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function matchStyleSelector(doc)
+ {
+ const result = doc.__proto__.querySelectorAll.call(doc, whitespaceTrimmedQuery);
+ addNodesToResults.call(this, result, result.length, result.item);
+ }
+
+ function matchPlainText(doc)
+ {
+ const result = doc.__proto__.evaluate.call(doc, "//text()[contains(., '" + escapedQuery + "')] | //comment()[contains(., '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function matchXPathQuery(doc)
+ {
+ const result = doc.__proto__.evaluate.call(doc, whitespaceTrimmedQuery, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function finishedSearching()
+ {
+ // Remove the searchResultsProperty now that the search is finished.
+ for (var i = 0; i < this._searchResults.length; ++i)
+ delete this._searchResults[i][searchResultsProperty];
+ }
+
+ const mainFrameDocument = InspectorController.inspectedWindow().document;
+ const searchDocuments = [mainFrameDocument];
+
+ if (tagNameQuery && startTagFound && endTagFound)
+ const searchFunctions = [matchExactTagNames, matchPlainText];
+ else if (tagNameQuery && startTagFound)
+ const searchFunctions = [matchStartOfTagNames, matchPlainText];
+ else if (tagNameQuery && endTagFound) {
+ // FIXME: we should have a matchEndOfTagNames search function if endTagFound is true but not startTagFound.
+ // This requires ends-with() support in XPath, WebKit only supports starts-with() and contains().
+ const searchFunctions = [matchPartialTagNames, matchPlainText];
+ } else if (whitespaceTrimmedQuery === "//*" || whitespaceTrimmedQuery === "*") {
+ // These queries will match every node. Matching everything isn't useful and can be slow for large pages,
+ // so limit the search functions list to plain text and attribute matching.
+ const searchFunctions = [matchPartialAttributeValues, matchPlainText];
+ } else
+ const searchFunctions = [matchExactItems, matchStyleSelector, matchPartialTagNamesAndAttributeValues, matchPlainText, matchXPathQuery];
+
+ // Find all frames, iframes and object elements to search their documents.
+ const querySelectorAllFunction = InspectorController.inspectedWindow().Document.prototype.querySelectorAll;
+ const subdocumentResult = querySelectorAllFunction.call(mainFrameDocument, "iframe, frame, object");
+
+ for (var i = 0; i < subdocumentResult.length; ++i) {
+ var element = subdocumentResult.item(i);
+ if (element.contentDocument)
+ searchDocuments.push(element.contentDocument);
+ }
+
+ const panel = this;
+ var documentIndex = 0;
+ var searchFunctionIndex = 0;
+ var chunkIntervalIdentifier = null;
+
+ // Split up the work into chunks so we don't block the UI thread while processing.
+
+ function processChunk()
+ {
+ var searchDocument = searchDocuments[documentIndex];
+ var searchFunction = searchFunctions[searchFunctionIndex];
+
+ if (++searchFunctionIndex > searchFunctions.length) {
+ searchFunction = searchFunctions[0];
+ searchFunctionIndex = 0;
+
+ if (++documentIndex > searchDocuments.length) {
+ if (panel._currentSearchChunkIntervalIdentifier === chunkIntervalIdentifier)
+ delete panel._currentSearchChunkIntervalIdentifier;
+ clearInterval(chunkIntervalIdentifier);
+ finishedSearching.call(panel);
+ return;
+ }
+
+ searchDocument = searchDocuments[documentIndex];
+ }
+
+ if (!searchDocument || !searchFunction)
+ return;
+
+ try {
+ searchFunction.call(panel, searchDocument);
+ } catch(err) {
+ // ignore any exceptions. the query might be malformed, but we allow that.
+ }
+ }
+
+ processChunk();
+
+ chunkIntervalIdentifier = setInterval(processChunk, 25);
+ this._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier;
+ },
+
+ jumpToNextSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ if (++this._currentSearchResultIndex >= this._searchResults.length)
+ this._currentSearchResultIndex = 0;
+ this.focusedDOMNode = this._searchResults[this._currentSearchResultIndex];
+ },
+
+ jumpToPreviousSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ if (--this._currentSearchResultIndex < 0)
+ this._currentSearchResultIndex = (this._searchResults.length - 1);
+ this.focusedDOMNode = this._searchResults[this._currentSearchResultIndex];
+ },
+
+ inspectedWindowCleared: function(window)
+ {
+ if (InspectorController.isWindowVisible())
+ this.updateMutationEventListeners(window);
+ },
+
+ _addMutationEventListeners: function(monitoredWindow)
+ {
+ monitoredWindow.document.addEventListener("DOMNodeInserted", this._nodeInsertedEventListener, true);
+ monitoredWindow.document.addEventListener("DOMNodeRemoved", this._nodeRemovedEventListener, true);
+ if (monitoredWindow.frameElement)
+ monitoredWindow.addEventListener("DOMContentLoaded", this._contentLoadedEventListener, true);
+ },
+
+ _removeMutationEventListeners: function(monitoredWindow)
+ {
+ if (monitoredWindow.frameElement)
+ monitoredWindow.removeEventListener("DOMContentLoaded", this._contentLoadedEventListener, true);
+ if (!monitoredWindow.document)
+ return;
+ monitoredWindow.document.removeEventListener("DOMNodeInserted", this._nodeInsertedEventListener, true);
+ monitoredWindow.document.removeEventListener("DOMNodeRemoved", this._nodeRemovedEventListener, true);
+ },
+
+ updateMutationEventListeners: function(monitoredWindow)
+ {
+ this._addMutationEventListeners(monitoredWindow);
+ },
+
+ registerMutationEventListeners: function(monitoredWindow)
+ {
+ if (!monitoredWindow || this._mutationMonitoredWindows.indexOf(monitoredWindow) !== -1)
+ return;
+ this._mutationMonitoredWindows.push(monitoredWindow);
+ if (InspectorController.isWindowVisible())
+ this._addMutationEventListeners(monitoredWindow);
+ },
+
+ unregisterMutationEventListeners: function(monitoredWindow)
+ {
+ if (!monitoredWindow || this._mutationMonitoredWindows.indexOf(monitoredWindow) === -1)
+ return;
+ this._mutationMonitoredWindows.remove(monitoredWindow);
+ this._removeMutationEventListeners(monitoredWindow);
+ },
+
+ unregisterAllMutationEventListeners: function()
+ {
+ for (var i = 0; i < this._mutationMonitoredWindows.length; ++i)
+ this._removeMutationEventListeners(this._mutationMonitoredWindows[i]);
+ this._mutationMonitoredWindows = [];
+ },
+
+ get rootDOMNode()
+ {
+ return this.treeOutline.rootDOMNode;
+ },
+
+ set rootDOMNode(x)
+ {
+ this.treeOutline.rootDOMNode = x;
+ },
+
+ get focusedDOMNode()
+ {
+ return this.treeOutline.focusedDOMNode;
+ },
+
+ set focusedDOMNode(x)
+ {
+ this.treeOutline.focusedDOMNode = x;
+ },
+
+ _contentLoaded: function(event)
+ {
+ this.recentlyModifiedNodes.push({node: event.target, parent: event.target.defaultView.frameElement, replaced: true});
+ if (this.visible)
+ this._updateModifiedNodesSoon();
+ },
+
+ _nodeInserted: function(event)
+ {
+ this.recentlyModifiedNodes.push({node: event.target, parent: event.relatedNode, inserted: true});
+ if (this.visible)
+ this._updateModifiedNodesSoon();
+ },
+
+ _nodeRemoved: function(event)
+ {
+ this.recentlyModifiedNodes.push({node: event.target, parent: event.relatedNode, removed: true});
+ if (this.visible)
+ this._updateModifiedNodesSoon();
+ },
+
+ _updateModifiedNodesSoon: function()
+ {
+ if ("_updateModifiedNodesTimeout" in this)
+ return;
+ this._updateModifiedNodesTimeout = setTimeout(this._updateModifiedNodes.bind(this), 0);
+ },
+
+ _updateModifiedNodes: function()
+ {
+ if ("_updateModifiedNodesTimeout" in this) {
+ clearTimeout(this._updateModifiedNodesTimeout);
+ delete this._updateModifiedNodesTimeout;
+ }
+
+ var updatedParentTreeElements = [];
+ var updateBreadcrumbs = false;
+
+ for (var i = 0; i < this.recentlyModifiedNodes.length; ++i) {
+ var replaced = this.recentlyModifiedNodes[i].replaced;
+ var parent = this.recentlyModifiedNodes[i].parent;
+ if (!parent)
+ continue;
+
+ var parentNodeItem = this.treeOutline.findTreeElement(parent, null, null, objectsAreSame);
+ if (parentNodeItem && !parentNodeItem.alreadyUpdatedChildren) {
+ parentNodeItem.updateChildren(replaced);
+ parentNodeItem.alreadyUpdatedChildren = true;
+ updatedParentTreeElements.push(parentNodeItem);
+ }
+
+ if (!updateBreadcrumbs && (objectsAreSame(this.focusedDOMNode, parent) || isAncestorIncludingParentFrames(this.focusedDOMNode, parent)))
+ updateBreadcrumbs = true;
+ }
+
+ for (var i = 0; i < updatedParentTreeElements.length; ++i)
+ delete updatedParentTreeElements[i].alreadyUpdatedChildren;
+
+ this.recentlyModifiedNodes = [];
+
+ if (updateBreadcrumbs)
+ this.updateBreadcrumb(true);
+ },
+
+ _stylesPaneEdited: function()
+ {
+ this.sidebarPanes.metrics.needsUpdate = true;
+ this.updateMetrics();
+ },
+
+ _metricsPaneEdited: function()
+ {
+ this.sidebarPanes.styles.needsUpdate = true;
+ this.updateStyles(true);
+ },
+
+ _mouseMovedInCrumbs: function(event)
+ {
+ var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
+ var crumbElement = nodeUnderMouse.enclosingNodeOrSelfWithClass("crumb");
+
+ WebInspector.hoveredDOMNode = (crumbElement ? crumbElement.representedObject : null);
+
+ if ("_mouseOutOfCrumbsTimeout" in this) {
+ clearTimeout(this._mouseOutOfCrumbsTimeout);
+ delete this._mouseOutOfCrumbsTimeout;
+ }
+ },
+
+ _mouseMovedOutOfCrumbs: function(event)
+ {
+ var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
+ if (nodeUnderMouse.isDescendant(this.crumbsElement))
+ return;
+
+ WebInspector.hoveredDOMNode = null;
+
+ this._mouseOutOfCrumbsTimeout = setTimeout(this.updateBreadcrumbSizes.bind(this), 1000);
+ },
+
+ updateBreadcrumb: function(forceUpdate)
+ {
+ if (!this.visible)
+ return;
+
+ var crumbs = this.crumbsElement;
+
+ var handled = false;
+ var foundRoot = false;
+ var crumb = crumbs.firstChild;
+ while (crumb) {
+ if (objectsAreSame(crumb.representedObject, this.rootDOMNode))
+ foundRoot = true;
+
+ if (foundRoot)
+ crumb.addStyleClass("dimmed");
+ else
+ crumb.removeStyleClass("dimmed");
+
+ if (objectsAreSame(crumb.representedObject, this.focusedDOMNode)) {
+ crumb.addStyleClass("selected");
+ handled = true;
+ } else {
+ crumb.removeStyleClass("selected");
+ }
+
+ crumb = crumb.nextSibling;
+ }
+
+ if (handled && !forceUpdate) {
+ // We don't need to rebuild the crumbs, but we need to adjust sizes
+ // to reflect the new focused or root node.
+ this.updateBreadcrumbSizes();
+ return;
+ }
+
+ crumbs.removeChildren();
+
+ var panel = this;
+
+ function selectCrumbFunction(event)
+ {
+ var crumb = event.currentTarget;
+ if (crumb.hasStyleClass("collapsed")) {
+ // Clicking a collapsed crumb will expose the hidden crumbs.
+ if (crumb === panel.crumbsElement.firstChild) {
+ // If the focused crumb is the first child, pick the farthest crumb
+ // that is still hidden. This allows the user to expose every crumb.
+ var currentCrumb = crumb;
+ while (currentCrumb) {
+ var hidden = currentCrumb.hasStyleClass("hidden");
+ var collapsed = currentCrumb.hasStyleClass("collapsed");
+ if (!hidden && !collapsed)
+ break;
+ crumb = currentCrumb;
+ currentCrumb = currentCrumb.nextSibling;
+ }
+ }
+
+ panel.updateBreadcrumbSizes(crumb);
+ } else {
+ // Clicking a dimmed crumb or double clicking (event.detail >= 2)
+ // will change the root node in addition to the focused node.
+ if (event.detail >= 2 || crumb.hasStyleClass("dimmed"))
+ panel.rootDOMNode = crumb.representedObject.parentNode;
+ panel.focusedDOMNode = crumb.representedObject;
+ }
+
+ event.preventDefault();
+ }
+
+ foundRoot = false;
+ for (var current = this.focusedDOMNode; current; current = parentNodeOrFrameElement(current)) {
+ if (current.nodeType === Node.DOCUMENT_NODE)
+ continue;
+
+ if (objectsAreSame(current, this.rootDOMNode))
+ foundRoot = true;
+
+ var crumb = document.createElement("span");
+ crumb.className = "crumb";
+ crumb.representedObject = current;
+ crumb.addEventListener("mousedown", selectCrumbFunction, false);
+
+ var crumbTitle;
+ switch (current.nodeType) {
+ case Node.ELEMENT_NODE:
+ crumbTitle = current.nodeName.toLowerCase();
+
+ var nameElement = document.createElement("span");
+ nameElement.textContent = crumbTitle;
+ crumb.appendChild(nameElement);
+
+ var idAttribute = current.getAttribute("id");
+ if (idAttribute) {
+ var idElement = document.createElement("span");
+ crumb.appendChild(idElement);
+
+ var part = "#" + idAttribute;
+ crumbTitle += part;
+ idElement.appendChild(document.createTextNode(part));
+
+ // Mark the name as extra, since the ID is more important.
+ nameElement.className = "extra";
+ }
+
+ var classAttribute = current.getAttribute("class");
+ if (classAttribute) {
+ var classes = classAttribute.split(/\s+/);
+ var foundClasses = {};
+
+ if (classes.length) {
+ var classesElement = document.createElement("span");
+ classesElement.className = "extra";
+ crumb.appendChild(classesElement);
+
+ for (var i = 0; i < classes.length; ++i) {
+ var className = classes[i];
+ if (className && !(className in foundClasses)) {
+ var part = "." + className;
+ crumbTitle += part;
+ classesElement.appendChild(document.createTextNode(part));
+ foundClasses[className] = true;
+ }
+ }
+ }
+ }
+
+ break;
+
+ case Node.TEXT_NODE:
+ if (isNodeWhitespace.call(current))
+ crumbTitle = WebInspector.UIString("(whitespace)");
+ else
+ crumbTitle = WebInspector.UIString("(text)");
+ break
+
+ case Node.COMMENT_NODE:
+ crumbTitle = "<!-->";
+ break;
+
+ case Node.DOCUMENT_TYPE_NODE:
+ crumbTitle = "<!DOCTYPE>";
+ break;
+
+ default:
+ crumbTitle = current.nodeName.toLowerCase();
+ }
+
+ if (!crumb.childNodes.length) {
+ var nameElement = document.createElement("span");
+ nameElement.textContent = crumbTitle;
+ crumb.appendChild(nameElement);
+ }
+
+ crumb.title = crumbTitle;
+
+ if (foundRoot)
+ crumb.addStyleClass("dimmed");
+ if (objectsAreSame(current, this.focusedDOMNode))
+ crumb.addStyleClass("selected");
+ if (!crumbs.childNodes.length)
+ crumb.addStyleClass("end");
+
+ crumbs.appendChild(crumb);
+ }
+
+ if (crumbs.hasChildNodes())
+ crumbs.lastChild.addStyleClass("start");
+
+ this.updateBreadcrumbSizes();
+ },
+
+ updateBreadcrumbSizes: function(focusedCrumb)
+ {
+ if (!this.visible)
+ return;
+
+ if (document.body.offsetWidth <= 0) {
+ // The stylesheet hasn't loaded yet or the window is closed,
+ // so we can't calculate what is need. Return early.
+ return;
+ }
+
+ var crumbs = this.crumbsElement;
+ if (!crumbs.childNodes.length || crumbs.offsetWidth <= 0)
+ return; // No crumbs, do nothing.
+
+ // A Zero index is the right most child crumb in the breadcrumb.
+ var selectedIndex = 0;
+ var focusedIndex = 0;
+ var selectedCrumb;
+
+ var i = 0;
+ var crumb = crumbs.firstChild;
+ while (crumb) {
+ // Find the selected crumb and index.
+ if (!selectedCrumb && crumb.hasStyleClass("selected")) {
+ selectedCrumb = crumb;
+ selectedIndex = i;
+ }
+
+ // Find the focused crumb index.
+ if (crumb === focusedCrumb)
+ focusedIndex = i;
+
+ // Remove any styles that affect size before
+ // deciding to shorten any crumbs.
+ if (crumb !== crumbs.lastChild)
+ crumb.removeStyleClass("start");
+ if (crumb !== crumbs.firstChild)
+ crumb.removeStyleClass("end");
+
+ crumb.removeStyleClass("compact");
+ crumb.removeStyleClass("collapsed");
+ crumb.removeStyleClass("hidden");
+
+ crumb = crumb.nextSibling;
+ ++i;
+ }
+
+ // Restore the start and end crumb classes in case they got removed in coalesceCollapsedCrumbs().
+ // The order of the crumbs in the document is opposite of the visual order.
+ crumbs.firstChild.addStyleClass("end");
+ crumbs.lastChild.addStyleClass("start");
+
+ function crumbsAreSmallerThanContainer()
+ {
+ var rightPadding = 20;
+ var errorWarningElement = document.getElementById("error-warning-count");
+ if (!WebInspector.console.visible && errorWarningElement)
+ rightPadding += errorWarningElement.offsetWidth;
+ return ((crumbs.totalOffsetLeft + crumbs.offsetWidth + rightPadding) < window.innerWidth);
+ }
+
+ if (crumbsAreSmallerThanContainer())
+ return; // No need to compact the crumbs, they all fit at full size.
+
+ var BothSides = 0;
+ var AncestorSide = -1;
+ var ChildSide = 1;
+
+ function makeCrumbsSmaller(shrinkingFunction, direction, significantCrumb)
+ {
+ if (!significantCrumb)
+ significantCrumb = (focusedCrumb || selectedCrumb);
+
+ if (significantCrumb === selectedCrumb)
+ var significantIndex = selectedIndex;
+ else if (significantCrumb === focusedCrumb)
+ var significantIndex = focusedIndex;
+ else {
+ var significantIndex = 0;
+ for (var i = 0; i < crumbs.childNodes.length; ++i) {
+ if (crumbs.childNodes[i] === significantCrumb) {
+ significantIndex = i;
+ break;
+ }
+ }
+ }
+
+ function shrinkCrumbAtIndex(index)
+ {
+ var shrinkCrumb = crumbs.childNodes[index];
+ if (shrinkCrumb && shrinkCrumb !== significantCrumb)
+ shrinkingFunction(shrinkCrumb);
+ if (crumbsAreSmallerThanContainer())
+ return true; // No need to compact the crumbs more.
+ return false;
+ }
+
+ // Shrink crumbs one at a time by applying the shrinkingFunction until the crumbs
+ // fit in the container or we run out of crumbs to shrink.
+ if (direction) {
+ // Crumbs are shrunk on only one side (based on direction) of the signifcant crumb.
+ var index = (direction > 0 ? 0 : crumbs.childNodes.length - 1);
+ while (index !== significantIndex) {
+ if (shrinkCrumbAtIndex(index))
+ return true;
+ index += (direction > 0 ? 1 : -1);
+ }
+ } else {
+ // Crumbs are shrunk in order of descending distance from the signifcant crumb,
+ // with a tie going to child crumbs.
+ var startIndex = 0;
+ var endIndex = crumbs.childNodes.length - 1;
+ while (startIndex != significantIndex || endIndex != significantIndex) {
+ var startDistance = significantIndex - startIndex;
+ var endDistance = endIndex - significantIndex;
+ if (startDistance >= endDistance)
+ var index = startIndex++;
+ else
+ var index = endIndex--;
+ if (shrinkCrumbAtIndex(index))
+ return true;
+ }
+ }
+
+ // We are not small enough yet, return false so the caller knows.
+ return false;
+ }
+
+ function coalesceCollapsedCrumbs()
+ {
+ var crumb = crumbs.firstChild;
+ var collapsedRun = false;
+ var newStartNeeded = false;
+ var newEndNeeded = false;
+ while (crumb) {
+ var hidden = crumb.hasStyleClass("hidden");
+ if (!hidden) {
+ var collapsed = crumb.hasStyleClass("collapsed");
+ if (collapsedRun && collapsed) {
+ crumb.addStyleClass("hidden");
+ crumb.removeStyleClass("compact");
+ crumb.removeStyleClass("collapsed");
+
+ if (crumb.hasStyleClass("start")) {
+ crumb.removeStyleClass("start");
+ newStartNeeded = true;
+ }
+
+ if (crumb.hasStyleClass("end")) {
+ crumb.removeStyleClass("end");
+ newEndNeeded = true;
+ }
+
+ continue;
+ }
+
+ collapsedRun = collapsed;
+
+ if (newEndNeeded) {
+ newEndNeeded = false;
+ crumb.addStyleClass("end");
+ }
+ } else
+ collapsedRun = true;
+ crumb = crumb.nextSibling;
+ }
+
+ if (newStartNeeded) {
+ crumb = crumbs.lastChild;
+ while (crumb) {
+ if (!crumb.hasStyleClass("hidden")) {
+ crumb.addStyleClass("start");
+ break;
+ }
+ crumb = crumb.previousSibling;
+ }
+ }
+ }
+
+ function compact(crumb)
+ {
+ if (crumb.hasStyleClass("hidden"))
+ return;
+ crumb.addStyleClass("compact");
+ }
+
+ function collapse(crumb, dontCoalesce)
+ {
+ if (crumb.hasStyleClass("hidden"))
+ return;
+ crumb.addStyleClass("collapsed");
+ crumb.removeStyleClass("compact");
+ if (!dontCoalesce)
+ coalesceCollapsedCrumbs();
+ }
+
+ function compactDimmed(crumb)
+ {
+ if (crumb.hasStyleClass("dimmed"))
+ compact(crumb);
+ }
+
+ function collapseDimmed(crumb)
+ {
+ if (crumb.hasStyleClass("dimmed"))
+ collapse(crumb);
+ }
+
+ if (!focusedCrumb) {
+ // When not focused on a crumb we can be biased and collapse less important
+ // crumbs that the user might not care much about.
+
+ // Compact child crumbs.
+ if (makeCrumbsSmaller(compact, ChildSide))
+ return;
+
+ // Collapse child crumbs.
+ if (makeCrumbsSmaller(collapse, ChildSide))
+ return;
+
+ // Compact dimmed ancestor crumbs.
+ if (makeCrumbsSmaller(compactDimmed, AncestorSide))
+ return;
+
+ // Collapse dimmed ancestor crumbs.
+ if (makeCrumbsSmaller(collapseDimmed, AncestorSide))
+ return;
+ }
+
+ // Compact ancestor crumbs, or from both sides if focused.
+ if (makeCrumbsSmaller(compact, (focusedCrumb ? BothSides : AncestorSide)))
+ return;
+
+ // Collapse ancestor crumbs, or from both sides if focused.
+ if (makeCrumbsSmaller(collapse, (focusedCrumb ? BothSides : AncestorSide)))
+ return;
+
+ if (!selectedCrumb)
+ return;
+
+ // Compact the selected crumb.
+ compact(selectedCrumb);
+ if (crumbsAreSmallerThanContainer())
+ return;
+
+ // Collapse the selected crumb as a last resort. Pass true to prevent coalescing.
+ collapse(selectedCrumb, true);
+ },
+
+ updateStyles: function(forceUpdate)
+ {
+ var stylesSidebarPane = this.sidebarPanes.styles;
+ if (!stylesSidebarPane.expanded || !stylesSidebarPane.needsUpdate)
+ return;
+
+ stylesSidebarPane.update(this.focusedDOMNode, null, forceUpdate);
+ stylesSidebarPane.needsUpdate = false;
+ },
+
+ updateMetrics: function()
+ {
+ var metricsSidebarPane = this.sidebarPanes.metrics;
+ if (!metricsSidebarPane.expanded || !metricsSidebarPane.needsUpdate)
+ return;
+
+ metricsSidebarPane.update(this.focusedDOMNode);
+ metricsSidebarPane.needsUpdate = false;
+ },
+
+ updateProperties: function()
+ {
+ var propertiesSidebarPane = this.sidebarPanes.properties;
+ if (!propertiesSidebarPane.expanded || !propertiesSidebarPane.needsUpdate)
+ return;
+
+ propertiesSidebarPane.update(this.focusedDOMNode);
+ propertiesSidebarPane.needsUpdate = false;
+ },
+
+ handleKeyEvent: function(event)
+ {
+ this.treeOutline.handleKeyEvent(event);
+ },
+
+ handleCopyEvent: function(event)
+ {
+ // Don't prevent the normal copy if the user has a selection.
+ if (!window.getSelection().isCollapsed)
+ return;
+
+ switch (this.focusedDOMNode.nodeType) {
+ case Node.ELEMENT_NODE:
+ var data = this.focusedDOMNode.outerHTML;
+ break;
+
+ case Node.COMMENT_NODE:
+ var data = "<!--" + this.focusedDOMNode.nodeValue + "-->";
+ break;
+
+ default:
+ case Node.TEXT_NODE:
+ var data = this.focusedDOMNode.nodeValue;
+ }
+
+ event.clipboardData.clearData();
+ event.preventDefault();
+
+ if (data)
+ event.clipboardData.setData("text/plain", data);
+ },
+
+ rightSidebarResizerDragStart: function(event)
+ {
+ WebInspector.elementDragStart(this.sidebarElement, this.rightSidebarResizerDrag.bind(this), this.rightSidebarResizerDragEnd.bind(this), event, "col-resize");
+ },
+
+ rightSidebarResizerDragEnd: function(event)
+ {
+ WebInspector.elementDragEnd(event);
+ },
+
+ rightSidebarResizerDrag: function(event)
+ {
+ var x = event.pageX;
+ var newWidth = Number.constrain(window.innerWidth - x, Preferences.minElementsSidebarWidth, window.innerWidth * 0.66);
+
+ this.sidebarElement.style.width = newWidth + "px";
+ this.contentElement.style.right = newWidth + "px";
+ this.sidebarResizeElement.style.right = (newWidth - 3) + "px";
+
+ this.treeOutline.updateSelection();
+
+ event.preventDefault();
+ },
+
+ _nodeSearchButtonClicked: function(event)
+ {
+ InspectorController.toggleNodeSearch();
+
+ if (InspectorController.searchingForNode())
+ this.nodeSearchButton.addStyleClass("toggled-on");
+ else
+ this.nodeSearchButton.removeStyleClass("toggled-on");
+ }
+}
+
+WebInspector.ElementsPanel.prototype.__proto__ = WebInspector.Panel.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ElementsTreeOutline.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ElementsTreeOutline.js
new file mode 100644
index 0000000..2da2f10
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ElementsTreeOutline.js
@@ -0,0 +1,626 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ElementsTreeOutline = function() {
+ this.element = document.createElement("ol");
+ this.element.addEventListener("mousedown", this._onmousedown.bind(this), false);
+ this.element.addEventListener("dblclick", this._ondblclick.bind(this), false);
+ this.element.addEventListener("mousemove", this._onmousemove.bind(this), false);
+ this.element.addEventListener("mouseout", this._onmouseout.bind(this), false);
+
+ TreeOutline.call(this, this.element);
+
+ this.includeRootDOMNode = true;
+ this.selectEnabled = false;
+ this.rootDOMNode = null;
+ this.focusedDOMNode = null;
+}
+
+WebInspector.ElementsTreeOutline.prototype = {
+ get rootDOMNode()
+ {
+ return this._rootDOMNode;
+ },
+
+ set rootDOMNode(x)
+ {
+ if (objectsAreSame(this._rootDOMNode, x))
+ return;
+
+ this._rootDOMNode = x;
+
+ this.update();
+ },
+
+ get focusedDOMNode()
+ {
+ return this._focusedDOMNode;
+ },
+
+ set focusedDOMNode(x)
+ {
+ if (objectsAreSame(this._focusedDOMNode, x)) {
+ this.revealAndSelectNode(x);
+ return;
+ }
+
+ this._focusedDOMNode = x;
+
+ this.revealAndSelectNode(x);
+
+ // The revealAndSelectNode() method might find a different element if there is inlined text,
+ // and the select() call would change the focusedDOMNode and reenter this setter. So to
+ // avoid calling focusedNodeChanged() twice, first check if _focusedDOMNode is the same
+ // node as the one passed in.
+ if (objectsAreSame(this._focusedDOMNode, x)) {
+ this.focusedNodeChanged();
+
+ if (x && !this.suppressSelectHighlight) {
+ InspectorController.highlightDOMNode(x);
+
+ if ("_restorePreviousHighlightNodeTimeout" in this)
+ clearTimeout(this._restorePreviousHighlightNodeTimeout);
+
+ function restoreHighlightToHoveredNode()
+ {
+ var hoveredNode = WebInspector.hoveredDOMNode;
+ if (hoveredNode)
+ InspectorController.highlightDOMNode(hoveredNode);
+ else
+ InspectorController.hideDOMNodeHighlight();
+ }
+
+ this._restorePreviousHighlightNodeTimeout = setTimeout(restoreHighlightToHoveredNode, 2000);
+ }
+ }
+ },
+
+ update: function()
+ {
+ this.removeChildren();
+
+ if (!this.rootDOMNode)
+ return;
+
+ var treeElement;
+ if (this.includeRootDOMNode) {
+ treeElement = new WebInspector.ElementsTreeElement(this.rootDOMNode);
+ treeElement.selectable = this.selectEnabled;
+ this.appendChild(treeElement);
+ } else {
+ // FIXME: this could use findTreeElement to reuse a tree element if it already exists
+ var node = (Preferences.ignoreWhitespace ? firstChildSkippingWhitespace.call(this.rootDOMNode) : this.rootDOMNode.firstChild);
+ while (node) {
+ treeElement = new WebInspector.ElementsTreeElement(node);
+ treeElement.selectable = this.selectEnabled;
+ this.appendChild(treeElement);
+ node = Preferences.ignoreWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling;
+ }
+ }
+
+ this.updateSelection();
+ },
+
+ updateSelection: function()
+ {
+ if (!this.selectedTreeElement)
+ return;
+ var element = this.treeOutline.selectedTreeElement;
+ element.updateSelection();
+ },
+
+ focusedNodeChanged: function(forceUpdate) {},
+
+ findTreeElement: function(node, isAncestor, getParent, equal)
+ {
+ if (typeof isAncestor === "undefined")
+ isAncestor = isAncestorIncludingParentFrames;
+ if (typeof getParent === "undefined")
+ getParent = parentNodeOrFrameElement;
+ if (typeof equal === "undefined")
+ equal = objectsAreSame;
+
+ var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestor, getParent, equal);
+ if (!treeElement && node.nodeType === Node.TEXT_NODE) {
+ // The text node might have been inlined if it was short, so try to find the parent element.
+ treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestor, getParent, equal);
+ }
+
+ return treeElement;
+ },
+
+ revealAndSelectNode: function(node)
+ {
+ if (!node)
+ return;
+
+ var treeElement = this.findTreeElement(node);
+ if (!treeElement)
+ return;
+
+ treeElement.reveal();
+ treeElement.select();
+ },
+
+ _treeElementFromEvent: function(event)
+ {
+ var root = this.element;
+
+ // We choose this X coordinate based on the knowledge that our list
+ // items extend nearly to the right edge of the outer <ol>.
+ var x = root.totalOffsetLeft + root.offsetWidth - 20;
+
+ var y = event.pageY;
+
+ // Our list items have 1-pixel cracks between them vertically. We avoid
+ // the cracks by checking slightly above and slightly below the mouse
+ // and seeing if we hit the same element each time.
+ var elementUnderMouse = this.treeElementFromPoint(x, y);
+ var elementAboveMouse = this.treeElementFromPoint(x, y - 2);
+ var element;
+ if (elementUnderMouse === elementAboveMouse)
+ element = elementUnderMouse;
+ else
+ element = this.treeElementFromPoint(x, y + 2);
+
+ return element;
+ },
+
+ _ondblclick: function(event)
+ {
+ var element = this._treeElementFromEvent(event);
+
+ if (!element || !element.ondblclick)
+ return;
+
+ element.ondblclick(element, event);
+ },
+
+ _onmousedown: function(event)
+ {
+ var element = this._treeElementFromEvent(event);
+
+ if (!element || element.isEventWithinDisclosureTriangle(event))
+ return;
+
+ element.select();
+ },
+
+ _onmousemove: function(event)
+ {
+ if (this._previousHoveredElement) {
+ this._previousHoveredElement.hovered = false;
+ delete this._previousHoveredElement;
+ }
+
+ var element = this._treeElementFromEvent(event);
+ if (element && !element.elementCloseTag) {
+ element.hovered = true;
+ this._previousHoveredElement = element;
+ }
+
+ WebInspector.hoveredDOMNode = (element && !element.elementCloseTag ? element.representedObject : null);
+ },
+
+ _onmouseout: function(event)
+ {
+ var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
+ if (nodeUnderMouse.isDescendant(this.element))
+ return;
+
+ if (this._previousHoveredElement) {
+ this._previousHoveredElement.hovered = false;
+ delete this._previousHoveredElement;
+ }
+
+ WebInspector.hoveredDOMNode = null;
+ }
+}
+
+WebInspector.ElementsTreeOutline.prototype.__proto__ = TreeOutline.prototype;
+
+WebInspector.ElementsTreeElement = function(node)
+{
+ var hasChildren = node.contentDocument || (Preferences.ignoreWhitespace ? (firstChildSkippingWhitespace.call(node) ? true : false) : node.hasChildNodes());
+ var titleInfo = nodeTitleInfo.call(node, hasChildren, WebInspector.linkifyURL);
+
+ if (titleInfo.hasChildren)
+ this.whitespaceIgnored = Preferences.ignoreWhitespace;
+
+ // The title will be updated in onattach.
+ TreeElement.call(this, "", node, titleInfo.hasChildren);
+}
+
+WebInspector.ElementsTreeElement.prototype = {
+ get highlighted()
+ {
+ return this._highlighted;
+ },
+
+ set highlighted(x)
+ {
+ if (this._highlighted === x)
+ return;
+
+ this._highlighted = x;
+
+ if (this.listItemElement) {
+ if (x)
+ this.listItemElement.addStyleClass("highlighted");
+ else
+ this.listItemElement.removeStyleClass("highlighted");
+ }
+ },
+
+ get hovered()
+ {
+ return this._hovered;
+ },
+
+ set hovered(x)
+ {
+ if (this._hovered === x)
+ return;
+
+ this._hovered = x;
+
+ if (this.listItemElement) {
+ if (x) {
+ this.updateSelection();
+ this.listItemElement.addStyleClass("hovered");
+ } else
+ this.listItemElement.removeStyleClass("hovered");
+ }
+ },
+
+ updateSelection: function()
+ {
+ var listItemElement = this.listItemElement;
+ if (!listItemElement)
+ return;
+
+ if (document.body.offsetWidth <= 0) {
+ // The stylesheet hasn't loaded yet or the window is closed,
+ // so we can't calculate what is need. Return early.
+ return;
+ }
+
+ if (!this.selectionElement) {
+ this.selectionElement = document.createElement("div");
+ this.selectionElement.className = "selection selected";
+ listItemElement.insertBefore(this.selectionElement, listItemElement.firstChild);
+ }
+
+ this.selectionElement.style.height = listItemElement.offsetHeight + "px";
+ },
+
+ onattach: function()
+ {
+ this.listItemElement.addEventListener("mousedown", this.onmousedown.bind(this), false);
+
+ if (this._highlighted)
+ this.listItemElement.addStyleClass("highlighted");
+
+ if (this._hovered) {
+ this.updateSelection();
+ this.listItemElement.addStyleClass("hovered");
+ }
+
+ this._updateTitle();
+
+ this._preventFollowingLinksOnDoubleClick();
+ },
+
+ _preventFollowingLinksOnDoubleClick: function()
+ {
+ var links = this.listItemElement.querySelectorAll("li > .webkit-html-tag > .webkit-html-attribute > .webkit-html-external-link, li > .webkit-html-tag > .webkit-html-attribute > .webkit-html-resource-link");
+ if (!links)
+ return;
+
+ for (var i = 0; i < links.length; ++i)
+ links[i].preventFollowOnDoubleClick = true;
+ },
+
+ onpopulate: function()
+ {
+ if (this.children.length || this.whitespaceIgnored !== Preferences.ignoreWhitespace)
+ return;
+
+ this.whitespaceIgnored = Preferences.ignoreWhitespace;
+
+ this.updateChildren();
+ },
+
+ updateChildren: function(fullRefresh)
+ {
+ if (fullRefresh) {
+ var selectedTreeElement = this.treeOutline.selectedTreeElement;
+ if (selectedTreeElement && selectedTreeElement.hasAncestor(this))
+ this.select();
+ this.removeChildren();
+ }
+
+ var treeElement = this;
+ var treeChildIndex = 0;
+
+ function updateChildrenOfNode(node)
+ {
+ var treeOutline = treeElement.treeOutline;
+ var child = (Preferences.ignoreWhitespace ? firstChildSkippingWhitespace.call(node) : node.firstChild);
+ while (child) {
+ var currentTreeElement = treeElement.children[treeChildIndex];
+ if (!currentTreeElement || !objectsAreSame(currentTreeElement.representedObject, child)) {
+ // Find any existing element that is later in the children list.
+ var existingTreeElement = null;
+ for (var i = (treeChildIndex + 1); i < treeElement.children.length; ++i) {
+ if (objectsAreSame(treeElement.children[i].representedObject, child)) {
+ existingTreeElement = treeElement.children[i];
+ break;
+ }
+ }
+
+ if (existingTreeElement && existingTreeElement.parent === treeElement) {
+ // If an existing element was found and it has the same parent, just move it.
+ var wasSelected = existingTreeElement.selected;
+ treeElement.removeChild(existingTreeElement);
+ treeElement.insertChild(existingTreeElement, treeChildIndex);
+ if (wasSelected)
+ existingTreeElement.select();
+ } else {
+ // No existing element found, insert a new element.
+ var newElement = new WebInspector.ElementsTreeElement(child);
+ newElement.selectable = treeOutline.selectEnabled;
+ treeElement.insertChild(newElement, treeChildIndex);
+ }
+ }
+
+ child = Preferences.ignoreWhitespace ? nextSiblingSkippingWhitespace.call(child) : child.nextSibling;
+ ++treeChildIndex;
+ }
+ }
+
+ // Remove any tree elements that no longer have this node (or this node's contentDocument) as their parent.
+ for (var i = (this.children.length - 1); i >= 0; --i) {
+ if ("elementCloseTag" in this.children[i])
+ continue;
+
+ var currentChild = this.children[i];
+ var currentNode = currentChild.representedObject;
+ var currentParentNode = currentNode.parentNode;
+
+ if (objectsAreSame(currentParentNode, this.representedObject))
+ continue;
+ if (this.representedObject.contentDocument && objectsAreSame(currentParentNode, this.representedObject.contentDocument))
+ continue;
+
+ var selectedTreeElement = this.treeOutline.selectedTreeElement;
+ if (selectedTreeElement && (selectedTreeElement === currentChild || selectedTreeElement.hasAncestor(currentChild)))
+ this.select();
+
+ this.removeChildAtIndex(i);
+
+ if (this.treeOutline.panel && currentNode.contentDocument)
+ this.treeOutline.panel.unregisterMutationEventListeners(currentNode.contentDocument.defaultView);
+ }
+
+ if (this.representedObject.contentDocument)
+ updateChildrenOfNode(this.representedObject.contentDocument);
+ updateChildrenOfNode(this.representedObject);
+
+ var lastChild = this.children[this.children.length - 1];
+ if (this.representedObject.nodeType == Node.ELEMENT_NODE && (!lastChild || !lastChild.elementCloseTag)) {
+ var title = "<span class=\"webkit-html-tag close\">&lt;/" + this.representedObject.nodeName.toLowerCase().escapeHTML() + "&gt;</span>";
+ var item = new TreeElement(title, null, false);
+ item.selectable = false;
+ item.elementCloseTag = true;
+ this.appendChild(item);
+ }
+ },
+
+ onexpand: function()
+ {
+ this.treeOutline.updateSelection();
+
+ if (this.treeOutline.panel && this.representedObject.contentDocument)
+ this.treeOutline.panel.registerMutationEventListeners(this.representedObject.contentDocument.defaultView);
+ },
+
+ oncollapse: function()
+ {
+ this.treeOutline.updateSelection();
+ },
+
+ onreveal: function()
+ {
+ if (this.listItemElement)
+ this.listItemElement.scrollIntoViewIfNeeded(false);
+ },
+
+ onselect: function()
+ {
+ this.treeOutline.focusedDOMNode = this.representedObject;
+ this.updateSelection();
+ },
+
+ onmousedown: function(event)
+ {
+ if (this._editing)
+ return;
+
+ // Prevent selecting the nearest word on double click.
+ if (event.detail >= 2)
+ event.preventDefault();
+ },
+
+ ondblclick: function(treeElement, event)
+ {
+ if (this._editing)
+ return;
+
+ if (this._startEditing(event))
+ return;
+
+ if (this.treeOutline.panel) {
+ this.treeOutline.rootDOMNode = this.representedObject.parentNode;
+ this.treeOutline.focusedDOMNode = this.representedObject;
+ }
+
+ if (this.hasChildren && !this.expanded)
+ this.expand();
+ },
+
+ _startEditing: function(event)
+ {
+ if (this.treeOutline.focusedDOMNode != this.representedObject)
+ return;
+
+ if (this.representedObject.nodeType != Node.ELEMENT_NODE && this.representedObject.nodeType != Node.TEXT_NODE)
+ return false;
+
+ var textNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-text-node");
+ if (textNode)
+ return this._startEditingTextNode(textNode);
+
+ var attribute = event.target.enclosingNodeOrSelfWithClass("webkit-html-attribute");
+ if (attribute)
+ return this._startEditingAttribute(attribute, event);
+
+ return false;
+ },
+
+ _startEditingAttribute: function(attribute, event)
+ {
+ if (WebInspector.isBeingEdited(attribute))
+ return true;
+
+ var attributeNameElement = attribute.getElementsByClassName("webkit-html-attribute-name")[0];
+ if (!attributeNameElement)
+ return false;
+
+ var attributeName = attributeNameElement.innerText;
+
+ function removeZeroWidthSpaceRecursive(node)
+ {
+ if (node.nodeType === Node.TEXT_NODE) {
+ node.nodeValue = node.nodeValue.replace(/\u200B/g, "");
+ return;
+ }
+
+ if (node.nodeType !== Node.ELEMENT_NODE)
+ return;
+
+ for (var child = node.firstChild; child; child = child.nextSibling)
+ removeZeroWidthSpaceRecursive(child);
+ }
+
+ // Remove zero-width spaces that were added by nodeTitleInfo.
+ removeZeroWidthSpaceRecursive(attribute);
+
+ this._editing = true;
+
+ WebInspector.startEditing(attribute, this._attributeEditingCommitted.bind(this), this._editingCancelled.bind(this), attributeName);
+ window.getSelection().setBaseAndExtent(event.target, 0, event.target, 1);
+
+ return true;
+ },
+
+ _startEditingTextNode: function(textNode)
+ {
+ if (WebInspector.isBeingEdited(textNode))
+ return true;
+
+ this._editing = true;
+
+ WebInspector.startEditing(textNode, this._textNodeEditingCommitted.bind(this), this._editingCancelled.bind(this));
+ window.getSelection().setBaseAndExtent(textNode, 0, textNode, 1);
+
+ return true;
+ },
+
+ _attributeEditingCommitted: function(element, newText, oldText, attributeName)
+ {
+ delete this._editing;
+
+ var parseContainerElement = document.createElement("span");
+ parseContainerElement.innerHTML = "<span " + newText + "></span>";
+ var parseElement = parseContainerElement.firstChild;
+ if (!parseElement || !parseElement.hasAttributes()) {
+ this._editingCancelled(element, context);
+ return;
+ }
+
+ var foundOriginalAttribute = false;
+ for (var i = 0; i < parseElement.attributes.length; ++i) {
+ var attr = parseElement.attributes[i];
+ foundOriginalAttribute = foundOriginalAttribute || attr.name === attributeName;
+ InspectorController.inspectedWindow().Element.prototype.setAttribute.call(this.representedObject, attr.name, attr.value);
+ }
+
+ if (!foundOriginalAttribute)
+ InspectorController.inspectedWindow().Element.prototype.removeAttribute.call(this.representedObject, attributeName);
+
+ this._updateTitle();
+
+ this.treeOutline.focusedNodeChanged(true);
+ },
+
+ _textNodeEditingCommitted: function(element, newText)
+ {
+ delete this._editing;
+
+ var textNode;
+ if (this.representedObject.nodeType == Node.ELEMENT_NODE) {
+ // We only show text nodes inline in elements if the element only
+ // has a single child, and that child is a text node.
+ textNode = this.representedObject.firstChild;
+ } else if (this.representedObject.nodeType == Node.TEXT_NODE)
+ textNode = this.representedObject;
+
+ textNode.nodeValue = newText;
+ this._updateTitle();
+ },
+
+ _editingCancelled: function(element, context)
+ {
+ delete this._editing;
+
+ this._updateTitle();
+ },
+
+ _updateTitle: function()
+ {
+ var title = nodeTitleInfo.call(this.representedObject, this.hasChildren, WebInspector.linkifyURL).title;
+ this.title = "<span class=\"highlight\">" + title + "</span>";
+ delete this.selectionElement;
+ this.updateSelection();
+ this._preventFollowingLinksOnDoubleClick();
+ },
+}
+
+WebInspector.ElementsTreeElement.prototype.__proto__ = TreeElement.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/FontView.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/FontView.js
new file mode 100644
index 0000000..4e1c931
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/FontView.js
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.FontView = function(resource)
+{
+ WebInspector.ResourceView.call(this, resource);
+
+ this.element.addStyleClass("font");
+
+ var uniqueFontName = "WebInspectorFontPreview" + this.resource.identifier;
+
+ this.fontStyleElement = document.createElement("style");
+ this.fontStyleElement.textContent = "@font-face { font-family: \"" + uniqueFontName + "\"; src: url(" + this.resource.url + "); }";
+ document.getElementsByTagName("head").item(0).appendChild(this.fontStyleElement);
+
+ this.fontPreviewElement = document.createElement("div");
+ this.fontPreviewElement.className = "preview";
+ this.contentElement.appendChild(this.fontPreviewElement);
+
+ this.fontPreviewElement.style.setProperty("font-family", uniqueFontName, null);
+ this.fontPreviewElement.innerHTML = "ABCDEFGHIJKLM<br>NOPQRSTUVWXYZ<br>abcdefghijklm<br>nopqrstuvwxyz<br>1234567890";
+
+ this.updateFontPreviewSize();
+}
+
+WebInspector.FontView.prototype = {
+ show: function(parentElement)
+ {
+ WebInspector.ResourceView.prototype.show.call(this, parentElement);
+ this.updateFontPreviewSize();
+ },
+
+ resize: function()
+ {
+ this.updateFontPreviewSize();
+ },
+
+ updateFontPreviewSize: function ()
+ {
+ if (!this.fontPreviewElement || !this.visible)
+ return;
+
+ this.fontPreviewElement.removeStyleClass("preview");
+
+ var measureFontSize = 50;
+ this.fontPreviewElement.style.setProperty("position", "absolute", null);
+ this.fontPreviewElement.style.setProperty("font-size", measureFontSize + "px", null);
+ this.fontPreviewElement.style.removeProperty("height");
+
+ var height = this.fontPreviewElement.offsetHeight;
+ var width = this.fontPreviewElement.offsetWidth;
+
+ var containerWidth = this.contentElement.offsetWidth;
+
+ // Subtract some padding. This should match the padding in the CSS plus room for the scrollbar.
+ containerWidth -= 40;
+
+ if (!height || !width || !containerWidth) {
+ this.fontPreviewElement.style.removeProperty("font-size");
+ this.fontPreviewElement.style.removeProperty("position");
+ this.fontPreviewElement.addStyleClass("preview");
+ return;
+ }
+
+ var lineCount = this.fontPreviewElement.getElementsByTagName("br").length + 1;
+ var realLineHeight = Math.floor(height / lineCount);
+ var fontSizeLineRatio = measureFontSize / realLineHeight;
+ var widthRatio = containerWidth / width;
+ var finalFontSize = Math.floor(realLineHeight * widthRatio * fontSizeLineRatio) - 1;
+
+ this.fontPreviewElement.style.setProperty("font-size", finalFontSize + "px", null);
+ this.fontPreviewElement.style.setProperty("height", this.fontPreviewElement.offsetHeight + "px", null);
+ this.fontPreviewElement.style.removeProperty("position");
+
+ this.fontPreviewElement.addStyleClass("preview");
+ }
+}
+
+WebInspector.FontView.prototype.__proto__ = WebInspector.ResourceView.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ImageView.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ImageView.js
new file mode 100644
index 0000000..001ffdd
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ImageView.js
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ImageView = function(resource)
+{
+ WebInspector.ResourceView.call(this, resource);
+
+ this.element.addStyleClass("image");
+
+ var container = document.createElement("div");
+ container.className = "image";
+ this.contentElement.appendChild(container);
+
+ this.imagePreviewElement = document.createElement("img");
+ this.imagePreviewElement.setAttribute("src", this.resource.url);
+
+ container.appendChild(this.imagePreviewElement);
+
+ container = document.createElement("div");
+ container.className = "info";
+ this.contentElement.appendChild(container);
+
+ var imageNameElement = document.createElement("h1");
+ imageNameElement.className = "title";
+ imageNameElement.textContent = this.resource.displayName;
+ container.appendChild(imageNameElement);
+
+ var infoListElement = document.createElement("dl");
+ infoListElement.className = "infoList";
+
+ var imageProperties = [
+ { name: WebInspector.UIString("Dimensions"), value: WebInspector.UIString("%d × %d", this.imagePreviewElement.naturalWidth, this.imagePreviewElement.height) },
+ { name: WebInspector.UIString("File size"), value: Number.bytesToString(this.resource.contentLength, WebInspector.UIString.bind(WebInspector)) },
+ { name: WebInspector.UIString("MIME type"), value: this.resource.mimeType }
+ ];
+
+ var listHTML = '';
+ for (var i = 0; i < imageProperties.length; ++i)
+ listHTML += "<dt>" + imageProperties[i].name + "</dt><dd>" + imageProperties[i].value + "</dd>";
+
+ infoListElement.innerHTML = listHTML;
+ container.appendChild(infoListElement);
+}
+
+WebInspector.ImageView.prototype = {
+
+}
+
+WebInspector.ImageView.prototype.__proto__ = WebInspector.ResourceView.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/back.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/back.png
new file mode 100644
index 0000000..9363960
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/back.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/checker.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/checker.png
new file mode 100644
index 0000000..8349908
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/checker.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/clearConsoleButtons.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/clearConsoleButtons.png
new file mode 100644
index 0000000..140a4fb
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/clearConsoleButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/closeButtons.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/closeButtons.png
new file mode 100644
index 0000000..28158a4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/closeButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/consoleButtons.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/consoleButtons.png
new file mode 100644
index 0000000..fb5f0897
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/consoleButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/database.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/database.png
new file mode 100644
index 0000000..339efa6
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/database.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/databaseTable.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/databaseTable.png
new file mode 100644
index 0000000..3718708
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/databaseTable.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/databasesIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/databasesIcon.png
new file mode 100644
index 0000000..79c7bb3
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/databasesIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerContinue.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerContinue.png
new file mode 100644
index 0000000..d90a855
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerContinue.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerPause.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerPause.png
new file mode 100644
index 0000000..97f958a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerPause.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerStepInto.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerStepInto.png
new file mode 100644
index 0000000..277f126
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerStepInto.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerStepOut.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerStepOut.png
new file mode 100644
index 0000000..3032e32
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerStepOut.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerStepOver.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerStepOver.png
new file mode 100644
index 0000000..7d47245
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/debuggerStepOver.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDown.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDown.png
new file mode 100644
index 0000000..cffc835
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDown.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDownBlack.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDownBlack.png
new file mode 100644
index 0000000..4b49c13
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDownBlack.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDownWhite.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDownWhite.png
new file mode 100644
index 0000000..aebae12
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDownWhite.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRight.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRight.png
new file mode 100644
index 0000000..a3102ea
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRight.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightBlack.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightBlack.png
new file mode 100644
index 0000000..2c45859
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightBlack.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDown.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDown.png
new file mode 100644
index 0000000..035c069
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDown.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDownBlack.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDownBlack.png
new file mode 100644
index 0000000..86f67bd
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDownBlack.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDownWhite.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDownWhite.png
new file mode 100644
index 0000000..972d794
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDownWhite.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightWhite.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightWhite.png
new file mode 100644
index 0000000..a10168f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightWhite.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/dockButtons.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/dockButtons.png
new file mode 100644
index 0000000..4b01d66
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/dockButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/elementsIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/elementsIcon.png
new file mode 100644
index 0000000..fde3db9
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/elementsIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/enableButtons.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/enableButtons.png
new file mode 100644
index 0000000..facee60
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/enableButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/errorIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/errorIcon.png
new file mode 100644
index 0000000..c697263
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/errorIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/errorMediumIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/errorMediumIcon.png
new file mode 100644
index 0000000..6ca32bb
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/errorMediumIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/excludeButtons.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/excludeButtons.png
new file mode 100644
index 0000000..f1c53a9
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/excludeButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/focusButtons.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/focusButtons.png
new file mode 100644
index 0000000..47eaa04
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/focusButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/forward.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/forward.png
new file mode 100644
index 0000000..ad70f3e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/forward.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/glossyHeader.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/glossyHeader.png
new file mode 100644
index 0000000..6cbefb7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/glossyHeader.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/glossyHeaderPressed.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/glossyHeaderPressed.png
new file mode 100644
index 0000000..1153506
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/glossyHeaderPressed.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/glossyHeaderSelected.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/glossyHeaderSelected.png
new file mode 100644
index 0000000..71d5af6
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/glossyHeaderSelected.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/glossyHeaderSelectedPressed.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/glossyHeaderSelectedPressed.png
new file mode 100644
index 0000000..7047dbe
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/glossyHeaderSelectedPressed.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/goArrow.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/goArrow.png
new file mode 100644
index 0000000..f318a56
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/goArrow.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/graphLabelCalloutLeft.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/graphLabelCalloutLeft.png
new file mode 100644
index 0000000..6426dbd
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/graphLabelCalloutLeft.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/graphLabelCalloutRight.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/graphLabelCalloutRight.png
new file mode 100644
index 0000000..8c87eae
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/graphLabelCalloutRight.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/largerResourcesButtons.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/largerResourcesButtons.png
new file mode 100644
index 0000000..caf3f14
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/largerResourcesButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/nodeSearchButtons.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/nodeSearchButtons.png
new file mode 100644
index 0000000..0599bd4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/nodeSearchButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/paneBottomGrow.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/paneBottomGrow.png
new file mode 100644
index 0000000..d55b865
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/paneBottomGrow.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/paneBottomGrowActive.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/paneBottomGrowActive.png
new file mode 100644
index 0000000..ef3f259
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/paneBottomGrowActive.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/paneGrowHandleLine.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/paneGrowHandleLine.png
new file mode 100644
index 0000000..4eaf61b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/paneGrowHandleLine.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/pauseOnExceptionButtons.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/pauseOnExceptionButtons.png
new file mode 100644
index 0000000..a4dd33a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/pauseOnExceptionButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/percentButtons.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/percentButtons.png
new file mode 100644
index 0000000..2635b24
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/percentButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profileGroupIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profileGroupIcon.png
new file mode 100644
index 0000000..44616d4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profileGroupIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profileIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profileIcon.png
new file mode 100644
index 0000000..8008f9b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profileIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profileSmallIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profileSmallIcon.png
new file mode 100644
index 0000000..7935520
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profileSmallIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profilesIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profilesIcon.png
new file mode 100644
index 0000000..ecd5b04
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profilesIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profilesSilhouette.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profilesSilhouette.png
new file mode 100644
index 0000000..42bb966
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/profilesSilhouette.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/radioDot.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/radioDot.png
new file mode 100644
index 0000000..609878f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/radioDot.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/recordButtons.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/recordButtons.png
new file mode 100644
index 0000000..3676154
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/recordButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/reloadButtons.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/reloadButtons.png
new file mode 100644
index 0000000..1e45671
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/reloadButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourceCSSIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourceCSSIcon.png
new file mode 100644
index 0000000..aead6a7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourceCSSIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourceDocumentIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourceDocumentIcon.png
new file mode 100644
index 0000000..1683a09
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourceDocumentIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourceDocumentIconSmall.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourceDocumentIconSmall.png
new file mode 100644
index 0000000..468ced9
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourceDocumentIconSmall.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourceJSIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourceJSIcon.png
new file mode 100644
index 0000000..9ef6ed0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourceJSIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcePlainIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcePlainIcon.png
new file mode 100644
index 0000000..0ed37b6
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcePlainIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcePlainIconSmall.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcePlainIconSmall.png
new file mode 100644
index 0000000..0fa967d
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcePlainIconSmall.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcesIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcesIcon.png
new file mode 100644
index 0000000..982424d
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcesIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcesSizeGraphIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcesSizeGraphIcon.png
new file mode 100644
index 0000000..e60dbe5
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcesSizeGraphIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcesTimeGraphIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcesTimeGraphIcon.png
new file mode 100644
index 0000000..c6953e9
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/resourcesTimeGraphIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/scriptsIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/scriptsIcon.png
new file mode 100644
index 0000000..213b31e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/scriptsIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/scriptsSilhouette.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/scriptsSilhouette.png
new file mode 100644
index 0000000..206396f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/scriptsSilhouette.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/searchSmallBlue.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/searchSmallBlue.png
new file mode 100644
index 0000000..9c990f4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/searchSmallBlue.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/searchSmallBrightBlue.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/searchSmallBrightBlue.png
new file mode 100644
index 0000000..b1d8055
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/searchSmallBrightBlue.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/searchSmallGray.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/searchSmallGray.png
new file mode 100644
index 0000000..4f3c068
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/searchSmallGray.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/searchSmallWhite.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/searchSmallWhite.png
new file mode 100644
index 0000000..85f430d
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/searchSmallWhite.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segment.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segment.png
new file mode 100644
index 0000000..759266e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segment.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentEnd.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentEnd.png
new file mode 100644
index 0000000..72672ff
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentEnd.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentHover.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentHover.png
new file mode 100644
index 0000000..c5017f4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentHover.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentHoverEnd.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentHoverEnd.png
new file mode 100644
index 0000000..d51363d
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentHoverEnd.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentSelected.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentSelected.png
new file mode 100644
index 0000000..c92f584
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentSelected.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentSelectedEnd.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentSelectedEnd.png
new file mode 100644
index 0000000..be5e0852
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/segmentSelectedEnd.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/splitviewDimple.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/splitviewDimple.png
new file mode 100644
index 0000000..584ffd4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/splitviewDimple.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/splitviewDividerBackground.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/splitviewDividerBackground.png
new file mode 100644
index 0000000..1120a7f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/splitviewDividerBackground.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarBackground.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarBackground.png
new file mode 100644
index 0000000..b466a49
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarBackground.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarBottomBackground.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarBottomBackground.png
new file mode 100644
index 0000000..fb5c9e4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarBottomBackground.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarButtons.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarButtons.png
new file mode 100644
index 0000000..e8090cb
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarMenuButton.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarMenuButton.png
new file mode 100644
index 0000000..9b3abdd
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarMenuButton.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarMenuButtonSelected.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarMenuButtonSelected.png
new file mode 100644
index 0000000..8189c43
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarMenuButtonSelected.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarResizerHorizontal.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarResizerHorizontal.png
new file mode 100644
index 0000000..56deeab
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarResizerHorizontal.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarResizerVertical.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarResizerVertical.png
new file mode 100644
index 0000000..7fc145277
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/statusbarResizerVertical.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillBlue.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillBlue.png
new file mode 100644
index 0000000..c7c273b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillBlue.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillGray.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillGray.png
new file mode 100644
index 0000000..9ff37ef
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillGray.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillGreen.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillGreen.png
new file mode 100644
index 0000000..cc5a8f3
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillGreen.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillOrange.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillOrange.png
new file mode 100644
index 0000000..08a81e4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillOrange.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillPurple.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillPurple.png
new file mode 100644
index 0000000..565a05c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillPurple.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillRed.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillRed.png
new file mode 100644
index 0000000..c3a1b9b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillRed.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillYellow.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillYellow.png
new file mode 100644
index 0000000..780045b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelineHollowPillYellow.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillBlue.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillBlue.png
new file mode 100644
index 0000000..c897faa
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillBlue.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillGray.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillGray.png
new file mode 100644
index 0000000..2128896
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillGray.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillGreen.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillGreen.png
new file mode 100644
index 0000000..9b66125
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillGreen.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillOrange.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillOrange.png
new file mode 100644
index 0000000..dd944fb
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillOrange.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillPurple.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillPurple.png
new file mode 100644
index 0000000..21b96f7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillPurple.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillRed.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillRed.png
new file mode 100644
index 0000000..f5e213b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillRed.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillYellow.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillYellow.png
new file mode 100644
index 0000000..ae2a5a23
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/timelinePillYellow.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/tipBalloon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/tipBalloon.png
new file mode 100644
index 0000000..4cdf738
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/tipBalloon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/tipBalloonBottom.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/tipBalloonBottom.png
new file mode 100644
index 0000000..3317a5a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/tipBalloonBottom.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/tipIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/tipIcon.png
new file mode 100644
index 0000000..8ca6124
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/tipIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/tipIconPressed.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/tipIconPressed.png
new file mode 100644
index 0000000..443e410
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/tipIconPressed.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/toolbarItemSelected.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/toolbarItemSelected.png
new file mode 100644
index 0000000..bd681f18
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/toolbarItemSelected.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeDownTriangleBlack.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeDownTriangleBlack.png
new file mode 100644
index 0000000..0821112
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeDownTriangleBlack.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeDownTriangleWhite.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeDownTriangleWhite.png
new file mode 100644
index 0000000..1667b51
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeDownTriangleWhite.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeRightTriangleBlack.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeRightTriangleBlack.png
new file mode 100644
index 0000000..90de820
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeRightTriangleBlack.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeRightTriangleWhite.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeRightTriangleWhite.png
new file mode 100644
index 0000000..2b6a82f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeRightTriangleWhite.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeUpTriangleBlack.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeUpTriangleBlack.png
new file mode 100644
index 0000000..ef69dbc
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeUpTriangleBlack.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeUpTriangleWhite.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeUpTriangleWhite.png
new file mode 100644
index 0000000..43ce4be
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/treeUpTriangleWhite.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/userInputIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/userInputIcon.png
new file mode 100644
index 0000000..325023f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/userInputIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/userInputPreviousIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/userInputPreviousIcon.png
new file mode 100644
index 0000000..068d572
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/userInputPreviousIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/warningIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/warningIcon.png
new file mode 100644
index 0000000..d5e4c82
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/warningIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/warningMediumIcon.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/warningMediumIcon.png
new file mode 100644
index 0000000..291e111
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/warningMediumIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/warningsErrors.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/warningsErrors.png
new file mode 100644
index 0000000..878b593
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Images/warningsErrors.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/MetricsSidebarPane.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/MetricsSidebarPane.js
new file mode 100644
index 0000000..a22a000
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/MetricsSidebarPane.js
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.MetricsSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Metrics"));
+}
+
+WebInspector.MetricsSidebarPane.prototype = {
+ update: function(node)
+ {
+ var body = this.bodyElement;
+
+ body.removeChildren();
+
+ if (node)
+ this.node = node;
+ else
+ node = this.node;
+
+ if (!node || !node.ownerDocument.defaultView)
+ return;
+
+ var style;
+ if (node.nodeType === Node.ELEMENT_NODE)
+ style = node.ownerDocument.defaultView.getComputedStyle(node);
+ if (!style)
+ return;
+
+ var metricsElement = document.createElement("div");
+ metricsElement.className = "metrics";
+
+ function createBoxPartElement(style, name, side, suffix)
+ {
+ var propertyName = (name !== "position" ? name + "-" : "") + side + suffix;
+ var value = style.getPropertyValue(propertyName);
+ if (value === "" || (name !== "position" && value === "0px"))
+ value = "\u2012";
+ else if (name === "position" && value === "auto")
+ value = "\u2012";
+ value = value.replace(/px$/, "");
+
+ var element = document.createElement("div");
+ element.className = side;
+ element.textContent = value;
+ element.addEventListener("dblclick", this.startEditing.bind(this, element, name, propertyName), false);
+ return element;
+ }
+
+ // Display types for which margin is ignored.
+ var noMarginDisplayType = {
+ "table-cell": true,
+ "table-column": true,
+ "table-column-group": true,
+ "table-footer-group": true,
+ "table-header-group": true,
+ "table-row": true,
+ "table-row-group": true
+ };
+
+ // Display types for which padding is ignored.
+ var noPaddingDisplayType = {
+ "table-column": true,
+ "table-column-group": true,
+ "table-footer-group": true,
+ "table-header-group": true,
+ "table-row": true,
+ "table-row-group": true
+ };
+
+ // Position types for which top, left, bottom and right are ignored.
+ var noPositionType = {
+ "static": true
+ };
+
+ var boxes = ["content", "padding", "border", "margin", "position"];
+ var boxLabels = [WebInspector.UIString("content"), WebInspector.UIString("padding"), WebInspector.UIString("border"), WebInspector.UIString("margin"), WebInspector.UIString("position")];
+ var previousBox;
+ for (var i = 0; i < boxes.length; ++i) {
+ var name = boxes[i];
+
+ if (name === "margin" && noMarginDisplayType[style.display])
+ continue;
+ if (name === "padding" && noPaddingDisplayType[style.display])
+ continue;
+ if (name === "position" && noPositionType[style.position])
+ continue;
+
+ var boxElement = document.createElement("div");
+ boxElement.className = name;
+
+ if (name === "content") {
+ var width = style.width.replace(/px$/, "");
+ var widthElement = document.createElement("span");
+ widthElement.textContent = width;
+ widthElement.addEventListener("dblclick", this.startEditing.bind(this, widthElement, "width", "width"), false);
+
+ var height = style.height.replace(/px$/, "");
+ var heightElement = document.createElement("span");
+ heightElement.textContent = height;
+ heightElement.addEventListener("dblclick", this.startEditing.bind(this, heightElement, "height", "height"), false);
+
+ boxElement.appendChild(widthElement);
+ boxElement.appendChild(document.createTextNode(" \u00D7 "));
+ boxElement.appendChild(heightElement);
+ } else {
+ var suffix = (name === "border" ? "-width" : "");
+
+ var labelElement = document.createElement("div");
+ labelElement.className = "label";
+ labelElement.textContent = boxLabels[i];
+ boxElement.appendChild(labelElement);
+
+ boxElement.appendChild(createBoxPartElement.call(this, style, name, "top", suffix));
+ boxElement.appendChild(document.createElement("br"));
+ boxElement.appendChild(createBoxPartElement.call(this, style, name, "left", suffix));
+
+ if (previousBox)
+ boxElement.appendChild(previousBox);
+
+ boxElement.appendChild(createBoxPartElement.call(this, style, name, "right", suffix));
+ boxElement.appendChild(document.createElement("br"));
+ boxElement.appendChild(createBoxPartElement.call(this, style, name, "bottom", suffix));
+ }
+
+ previousBox = boxElement;
+ }
+
+ metricsElement.appendChild(previousBox);
+ body.appendChild(metricsElement);
+ },
+
+ startEditing: function(targetElement, box, styleProperty)
+ {
+ if (WebInspector.isBeingEdited(targetElement))
+ return;
+
+ var context = { box: box, styleProperty: styleProperty };
+
+ WebInspector.startEditing(targetElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
+ },
+
+ editingCancelled: function(element, context)
+ {
+ this.update();
+ },
+
+ editingCommitted: function(element, userInput, previousContent, context)
+ {
+ if (userInput === previousContent)
+ return this.editingCancelled(element, context); // nothing changed, so cancel
+
+ if (context.box !== "position" && (!userInput || userInput === "\u2012"))
+ userInput = "0px";
+ else if (context.box === "position" && (!userInput || userInput === "\u2012"))
+ userInput = "auto";
+
+ // Append a "px" unit if the user input was just a number.
+ if (/^\d+$/.test(userInput))
+ userInput += "px";
+
+ this.node.style.setProperty(context.styleProperty, userInput, "");
+
+ this.dispatchEventToListeners("metrics edited");
+
+ this.update();
+ }
+}
+
+WebInspector.MetricsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Object.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Object.js
new file mode 100644
index 0000000..80202b0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Object.js
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Object = function() {
+}
+
+WebInspector.Object.prototype = {
+ addEventListener: function(eventType, listener, thisObject) {
+ if (!("_listeners" in this))
+ this._listeners = {};
+ if (!(eventType in this._listeners))
+ this._listeners[eventType] = [];
+ this._listeners[eventType].push({ thisObject: thisObject, listener: listener });
+ },
+
+ removeEventListener: function(eventType, listener, thisObject) {
+ if (!("_listeners" in this) || !(eventType in this._listeners))
+ return;
+ var listeners = this._listeners[eventType];
+ for (var i = 0; i < listeners.length; ++i) {
+ if (listener && listeners[i].listener === listener && listeners[i].thisObject === thisObject)
+ listeners.splice(i, 1);
+ else if (!listener && thisObject && listeners[i].thisObject === thisObject)
+ listeners.splice(i, 1);
+ }
+
+ if (!listeners.length)
+ delete this._listeners[eventType];
+ },
+
+ dispatchEventToListeners: function(eventType) {
+ if (!("_listeners" in this) || !(eventType in this._listeners))
+ return;
+
+ var stoppedPropagation = false;
+
+ function stopPropagation()
+ {
+ stoppedPropagation = true;
+ }
+
+ function preventDefault()
+ {
+ this.defaultPrevented = true;
+ }
+
+ var event = {target: this, type: eventType, defaultPrevented: false};
+ event.stopPropagation = stopPropagation.bind(event);
+ event.preventDefault = preventDefault.bind(event);
+
+ var listeners = this._listeners[eventType];
+ for (var i = 0; i < listeners.length; ++i) {
+ listeners[i].listener.call(listeners[i].thisObject, event);
+ if (stoppedPropagation)
+ break;
+ }
+
+ return event.defaultPrevented;
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ObjectPropertiesSection.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ObjectPropertiesSection.js
new file mode 100644
index 0000000..ab6ac55
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ObjectPropertiesSection.js
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ObjectPropertiesSection = function(object, title, subtitle, emptyPlaceholder, ignoreHasOwnProperty, extraProperties, treeElementConstructor)
+{
+ if (!title) {
+ title = Object.describe(object);
+ if (title.match(/Prototype$/)) {
+ title = title.replace(/Prototype$/, "");
+ if (!subtitle)
+ subtitle = WebInspector.UIString("Prototype");
+ }
+ }
+
+ this.emptyPlaceholder = (emptyPlaceholder || WebInspector.UIString("No Properties"));
+ this.object = object;
+ this.ignoreHasOwnProperty = ignoreHasOwnProperty;
+ this.extraProperties = extraProperties;
+ this.treeElementConstructor = treeElementConstructor || WebInspector.ObjectPropertyTreeElement;
+ this.editable = true;
+
+ WebInspector.PropertiesSection.call(this, title, subtitle);
+}
+
+WebInspector.ObjectPropertiesSection.prototype = {
+ onpopulate: function()
+ {
+ this.update();
+ },
+
+ update: function()
+ {
+ var properties = [];
+ for (var prop in this.object)
+ properties.push(prop);
+ if (this.extraProperties)
+ for (var prop in this.extraProperties)
+ properties.push(prop);
+ properties.sort();
+
+ this.propertiesTreeOutline.removeChildren();
+
+ for (var i = 0; i < properties.length; ++i) {
+ var object = this.object;
+ var propertyName = properties[i];
+ if (this.extraProperties && propertyName in this.extraProperties)
+ object = this.extraProperties;
+ if (propertyName === "__treeElementIdentifier")
+ continue;
+ if (!this.ignoreHasOwnProperty && "hasOwnProperty" in object && !object.hasOwnProperty(propertyName))
+ continue;
+ this.propertiesTreeOutline.appendChild(new this.treeElementConstructor(object, propertyName));
+ }
+
+ if (!this.propertiesTreeOutline.children.length) {
+ var title = "<div class=\"info\">" + this.emptyPlaceholder + "</div>";
+ var infoElement = new TreeElement(title, null, false);
+ this.propertiesTreeOutline.appendChild(infoElement);
+ }
+ }
+}
+
+WebInspector.ObjectPropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
+
+WebInspector.ObjectPropertyTreeElement = function(parentObject, propertyName)
+{
+ this.parentObject = parentObject;
+ this.propertyName = propertyName;
+
+ // Pass an empty title, the title gets made later in onattach.
+ TreeElement.call(this, "", null, false);
+}
+
+WebInspector.ObjectPropertyTreeElement.prototype = {
+ safePropertyValue: function(object, propertyName)
+ {
+ if (object["__lookupGetter__"] && object.__lookupGetter__(propertyName))
+ return;
+ return object[propertyName];
+ },
+
+ onpopulate: function()
+ {
+ if (this.children.length && !this.shouldRefreshChildren)
+ return;
+
+ this.removeChildren();
+
+ var childObject = this.safePropertyValue(this.parentObject, this.propertyName);
+ var properties = Object.sortedProperties(childObject);
+ for (var i = 0; i < properties.length; ++i) {
+ var propertyName = properties[i];
+ if (propertyName === "__treeElementIdentifier")
+ continue;
+ this.appendChild(new this.treeOutline.section.treeElementConstructor(childObject, propertyName));
+ }
+ },
+
+ ondblclick: function(element, event)
+ {
+ this.startEditing();
+ },
+
+ onattach: function()
+ {
+ this.update();
+ },
+
+ update: function()
+ {
+ var childObject = this.safePropertyValue(this.parentObject, this.propertyName);
+ var isGetter = ("__lookupGetter__" in this.parentObject && this.parentObject.__lookupGetter__(this.propertyName));
+
+ var nameElement = document.createElement("span");
+ nameElement.className = "name";
+ nameElement.textContent = this.propertyName;
+
+ this.valueElement = document.createElement("span");
+ this.valueElement.className = "value";
+ if (!isGetter) {
+ this.valueElement.textContent = Object.describe(childObject, true);
+ } else {
+ // FIXME: this should show something like "getter" (bug 16734).
+ this.valueElement.textContent = "\u2014"; // em dash
+ this.valueElement.addStyleClass("dimmed");
+ }
+
+ this.listItemElement.removeChildren();
+
+ this.listItemElement.appendChild(nameElement);
+ this.listItemElement.appendChild(document.createTextNode(": "));
+ this.listItemElement.appendChild(this.valueElement);
+
+ var hasSubProperties = false;
+ var type = typeof childObject;
+ if (childObject && (type === "object" || type === "function")) {
+ for (subPropertyName in childObject) {
+ if (subPropertyName === "__treeElementIdentifier")
+ continue;
+ hasSubProperties = true;
+ break;
+ }
+ }
+
+ this.hasChildren = hasSubProperties;
+ },
+
+ updateSiblings: function()
+ {
+ if (this.parent.root)
+ this.treeOutline.section.update();
+ else
+ this.parent.shouldRefreshChildren = true;
+ },
+
+ startEditing: function()
+ {
+ if (WebInspector.isBeingEdited(this.valueElement) || !this.treeOutline.section.editable)
+ return;
+
+ var context = { expanded: this.expanded };
+
+ // Lie about our children to prevent expanding on double click and to collapse subproperties.
+ this.hasChildren = false;
+
+ this.listItemElement.addStyleClass("editing-sub-part");
+
+ WebInspector.startEditing(this.valueElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
+ },
+
+ editingEnded: function(context)
+ {
+ this.listItemElement.scrollLeft = 0;
+ this.listItemElement.removeStyleClass("editing-sub-part");
+ if (context.expanded)
+ this.expand();
+ },
+
+ editingCancelled: function(element, context)
+ {
+ this.update();
+ this.editingEnded(context);
+ },
+
+ editingCommitted: function(element, userInput, previousContent, context)
+ {
+ if (userInput === previousContent)
+ return this.editingCancelled(element, context); // nothing changed, so cancel
+
+ this.applyExpression(userInput, true);
+
+ this.editingEnded(context);
+ },
+
+ evaluateExpression: function(expression)
+ {
+ // Evaluate in the currently selected call frame if the debugger is paused.
+ // Otherwise evaluate in against the inspected window.
+ if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused && this.treeOutline.section.editInSelectedCallFrameWhenPaused)
+ return WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false);
+ return InspectorController.inspectedWindow().eval(expression);
+ },
+
+ applyExpression: function(expression, updateInterface)
+ {
+ var expressionLength = expression.trimWhitespace().length;
+
+ if (!expressionLength) {
+ // The user deleted everything, so try to delete the property.
+ delete this.parentObject[this.propertyName];
+
+ if (updateInterface) {
+ if (this.propertyName in this.parentObject) {
+ // The property was not deleted, so update.
+ this.update();
+ } else {
+ // The property was deleted, so remove this tree element.
+ this.parent.removeChild(this);
+ }
+ }
+
+ return;
+ }
+
+ try {
+ // Surround the expression in parenthesis so the result of the eval is the result
+ // of the whole expression not the last potential sub-expression.
+ var result = this.evaluateExpression("(" + expression + ")");
+
+ // Store the result in the property.
+ this.parentObject[this.propertyName] = result;
+ } catch(e) {
+ try {
+ // Try to update as a string
+ var result = this.evaluateExpression("\"" + expression.escapeCharacters("\"") + "\"");
+
+ // Store the result in the property.
+ this.parentObject[this.propertyName] = result;
+ } catch(e) {
+ // The expression failed so don't change the value. So just update and return.
+ if (updateInterface)
+ this.update();
+ return;
+ }
+ }
+
+ if (updateInterface) {
+ // Call updateSiblings since their value might be based on the value that just changed.
+ this.updateSiblings();
+ }
+ }
+}
+
+WebInspector.ObjectPropertyTreeElement.prototype.__proto__ = TreeElement.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Panel.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Panel.js
new file mode 100644
index 0000000..5046f6b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Panel.js
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Panel = function()
+{
+ WebInspector.View.call(this);
+
+ this.element.addStyleClass("panel");
+}
+
+WebInspector.Panel.prototype = {
+ get toolbarItem()
+ {
+ if (this._toolbarItem)
+ return this._toolbarItem;
+
+ // Sample toolbar item as markup:
+ // <button class="toolbar-item resources toggleable">
+ // <div class="toolbar-icon"></div>
+ // <div class="toolbar-label">Resources</div>
+ // </button>
+
+ this._toolbarItem = document.createElement("button");
+ this._toolbarItem.className = "toolbar-item toggleable";
+ this._toolbarItem.panel = this;
+
+ if ("toolbarItemClass" in this)
+ this._toolbarItem.addStyleClass(this.toolbarItemClass);
+
+ var iconElement = document.createElement("div");
+ iconElement.className = "toolbar-icon";
+ this._toolbarItem.appendChild(iconElement);
+
+ if ("toolbarItemLabel" in this) {
+ var labelElement = document.createElement("div");
+ labelElement.className = "toolbar-label";
+ labelElement.textContent = this.toolbarItemLabel;
+ this._toolbarItem.appendChild(labelElement);
+ }
+
+ return this._toolbarItem;
+ },
+
+ show: function()
+ {
+ WebInspector.View.prototype.show.call(this);
+
+ var statusBarItems = this.statusBarItems;
+ if (statusBarItems) {
+ this._statusBarItemContainer = document.createElement("div");
+ for (var i = 0; i < statusBarItems.length; ++i)
+ this._statusBarItemContainer.appendChild(statusBarItems[i]);
+ document.getElementById("main-status-bar").appendChild(this._statusBarItemContainer);
+ }
+
+ if ("_toolbarItem" in this)
+ this._toolbarItem.addStyleClass("toggled-on");
+
+ WebInspector.currentFocusElement = document.getElementById("main-panels");
+ },
+
+ hide: function()
+ {
+ WebInspector.View.prototype.hide.call(this);
+
+ if (this._statusBarItemContainer && this._statusBarItemContainer.parentNode)
+ this._statusBarItemContainer.parentNode.removeChild(this._statusBarItemContainer);
+ delete this._statusBarItemContainer;
+ if ("_toolbarItem" in this)
+ this._toolbarItem.removeStyleClass("toggled-on");
+ },
+
+ attach: function()
+ {
+ if (!this.element.parentNode)
+ document.getElementById("main-panels").appendChild(this.element);
+ },
+
+ searchCanceled: function(startingNewSearch)
+ {
+ if (this._searchResults) {
+ for (var i = 0; i < this._searchResults.length; ++i) {
+ var view = this._searchResults[i];
+ if (view.searchCanceled)
+ view.searchCanceled();
+ delete view.currentQuery;
+ }
+ }
+
+ WebInspector.updateSearchMatchesCount(0, this);
+
+ if (this._currentSearchChunkIntervalIdentifier) {
+ clearInterval(this._currentSearchChunkIntervalIdentifier);
+ delete this._currentSearchChunkIntervalIdentifier;
+ }
+
+ this._totalSearchMatches = 0;
+ this._currentSearchResultIndex = 0;
+ this._searchResults = [];
+ },
+
+ performSearch: function(query)
+ {
+ // Call searchCanceled since it will reset everything we need before doing a new search.
+ this.searchCanceled(true);
+
+ var searchableViews = this.searchableViews;
+ if (!searchableViews || !searchableViews.length)
+ return;
+
+ var parentElement = this.viewsContainerElement;
+ var visibleView = this.visibleView;
+ var sortFuction = this.searchResultsSortFunction;
+
+ var matchesCountUpdateTimeout = null;
+
+ function updateMatchesCount()
+ {
+ WebInspector.updateSearchMatchesCount(this._totalSearchMatches, this);
+ matchesCountUpdateTimeout = null;
+ }
+
+ function updateMatchesCountSoon()
+ {
+ if (matchesCountUpdateTimeout)
+ return;
+ // Update the matches count every half-second so it doesn't feel twitchy.
+ matchesCountUpdateTimeout = setTimeout(updateMatchesCount.bind(this), 500);
+ }
+
+ function finishedCallback(view, searchMatches)
+ {
+ if (!searchMatches)
+ return;
+
+ this._totalSearchMatches += searchMatches;
+ this._searchResults.push(view);
+
+ if (sortFuction)
+ this._searchResults.sort(sortFuction);
+
+ if (this.searchMatchFound)
+ this.searchMatchFound(view, searchMatches);
+
+ updateMatchesCountSoon.call(this);
+
+ if (view === visibleView)
+ view.jumpToFirstSearchResult();
+ }
+
+ var i = 0;
+ var panel = this;
+ var boundFinishedCallback = finishedCallback.bind(this);
+ var chunkIntervalIdentifier = null;
+
+ // Split up the work into chunks so we don't block the
+ // UI thread while processing.
+
+ function processChunk()
+ {
+ var view = searchableViews[i];
+
+ if (++i >= searchableViews.length) {
+ if (panel._currentSearchChunkIntervalIdentifier === chunkIntervalIdentifier)
+ delete panel._currentSearchChunkIntervalIdentifier;
+ clearInterval(chunkIntervalIdentifier);
+ }
+
+ if (!view)
+ return;
+
+ if (view.element.parentNode !== parentElement && view.element.parentNode && parentElement)
+ view.detach();
+
+ view.currentQuery = query;
+ view.performSearch(query, boundFinishedCallback);
+ }
+
+ processChunk();
+
+ chunkIntervalIdentifier = setInterval(processChunk, 25);
+ this._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier;
+ },
+
+ jumpToNextSearchResult: function()
+ {
+ if (!this.showView || !this._searchResults || !this._searchResults.length)
+ return;
+
+ var showFirstResult = false;
+
+ this._currentSearchResultIndex = this._searchResults.indexOf(this.visibleView);
+ if (this._currentSearchResultIndex === -1) {
+ this._currentSearchResultIndex = 0;
+ showFirstResult = true;
+ }
+
+ var currentView = this._searchResults[this._currentSearchResultIndex];
+
+ if (currentView.showingLastSearchResult()) {
+ if (++this._currentSearchResultIndex >= this._searchResults.length)
+ this._currentSearchResultIndex = 0;
+ currentView = this._searchResults[this._currentSearchResultIndex];
+ showFirstResult = true;
+ }
+
+ if (currentView !== this.visibleView)
+ this.showView(currentView);
+
+ if (showFirstResult)
+ currentView.jumpToFirstSearchResult();
+ else
+ currentView.jumpToNextSearchResult();
+ },
+
+ jumpToPreviousSearchResult: function()
+ {
+ if (!this.showView || !this._searchResults || !this._searchResults.length)
+ return;
+
+ var showLastResult = false;
+
+ this._currentSearchResultIndex = this._searchResults.indexOf(this.visibleView);
+ if (this._currentSearchResultIndex === -1) {
+ this._currentSearchResultIndex = 0;
+ showLastResult = true;
+ }
+
+ var currentView = this._searchResults[this._currentSearchResultIndex];
+
+ if (currentView.showingFirstSearchResult()) {
+ if (--this._currentSearchResultIndex < 0)
+ this._currentSearchResultIndex = (this._searchResults.length - 1);
+ currentView = this._searchResults[this._currentSearchResultIndex];
+ showLastResult = true;
+ }
+
+ if (currentView !== this.visibleView)
+ this.showView(currentView);
+
+ if (showLastResult)
+ currentView.jumpToLastSearchResult();
+ else
+ currentView.jumpToPreviousSearchResult();
+ }
+}
+
+WebInspector.Panel.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/PanelEnablerView.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/PanelEnablerView.js
new file mode 100644
index 0000000..fab6d76
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/PanelEnablerView.js
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.PanelEnablerView = function(identifier, headingText, disclaimerText, buttonTitle)
+{
+ WebInspector.View.call(this);
+
+ this.element.addStyleClass("panel-enabler-view");
+ this.element.addStyleClass(identifier);
+
+ this.contentElement = document.createElement("div");
+ this.contentElement.className = "panel-enabler-view-content";
+ this.element.appendChild(this.contentElement);
+
+ this.imageElement = document.createElement("img");
+ this.contentElement.appendChild(this.imageElement);
+
+ this.choicesForm = document.createElement("form");
+ this.contentElement.appendChild(this.choicesForm);
+
+ this.headerElement = document.createElement("h1");
+ this.headerElement.textContent = headingText;
+ this.choicesForm.appendChild(this.headerElement);
+
+ var self = this;
+ function enableOption(text, checked) {
+ var label = document.createElement("label");
+ var option = document.createElement("input");
+ option.type = "radio";
+ option.name = "enable-option";
+ if (checked)
+ option.checked = true;
+ label.appendChild(option);
+ label.appendChild(document.createTextNode(text));
+ self.choicesForm.appendChild(label);
+ return option;
+ };
+
+ this.enabledForSession = enableOption(WebInspector.UIString("Only enable for this session"), true);
+ this.enabledAlways = enableOption(WebInspector.UIString("Always enable"));
+
+ this.disclaimerElement = document.createElement("div");
+ this.disclaimerElement.className = "panel-enabler-disclaimer";
+ this.disclaimerElement.textContent = disclaimerText;
+ this.choicesForm.appendChild(this.disclaimerElement);
+
+ this.enableButton = document.createElement("button");
+ this.enableButton.setAttribute("type", "button");
+ this.enableButton.textContent = buttonTitle;
+ this.enableButton.addEventListener("click", this._enableButtonCicked.bind(this), false);
+ this.choicesForm.appendChild(this.enableButton);
+
+ window.addEventListener("resize", this._windowResized.bind(this), true);
+}
+
+WebInspector.PanelEnablerView.prototype = {
+ _enableButtonCicked: function()
+ {
+ this.dispatchEventToListeners("enable clicked");
+ },
+
+ _windowResized: function()
+ {
+ this.imageElement.removeStyleClass("hidden");
+
+ if (this.element.offsetWidth < (this.choicesForm.offsetWidth + this.imageElement.offsetWidth))
+ this.imageElement.addStyleClass("hidden");
+ },
+
+ get alwaysEnabled() {
+ return this.enabledAlways.checked;
+ }
+}
+
+WebInspector.PanelEnablerView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Placard.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Placard.js
new file mode 100644
index 0000000..69a168e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Placard.js
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Placard = function(title, subtitle)
+{
+ this.element = document.createElement("div");
+ this.element.className = "placard";
+ this.element.placard = this;
+
+ this.titleElement = document.createElement("div");
+ this.titleElement.className = "title";
+
+ this.subtitleElement = document.createElement("div");
+ this.subtitleElement.className = "subtitle";
+
+ this.element.appendChild(this.subtitleElement);
+ this.element.appendChild(this.titleElement);
+
+ this.title = title;
+ this.subtitle = subtitle;
+ this.selected = false;
+}
+
+WebInspector.Placard.prototype = {
+ get title()
+ {
+ return this._title;
+ },
+
+ set title(x)
+ {
+ if (this._title === x)
+ return;
+ this._title = x;
+ this.titleElement.textContent = x;
+ },
+
+ get subtitle()
+ {
+ return this._subtitle;
+ },
+
+ set subtitle(x)
+ {
+ if (this._subtitle === x)
+ return;
+ this._subtitle = x;
+ this.subtitleElement.innerHTML = x;
+ },
+
+ get selected()
+ {
+ return this._selected;
+ },
+
+ set selected(x)
+ {
+ if (x)
+ this.select();
+ else
+ this.deselect();
+ },
+
+ select: function()
+ {
+ if (this._selected)
+ return;
+ this._selected = true;
+ this.element.addStyleClass("selected");
+ },
+
+ deselect: function()
+ {
+ if (!this._selected)
+ return;
+ this._selected = false;
+ this.element.removeStyleClass("selected");
+ },
+
+ toggleSelected: function()
+ {
+ this.selected = !this.selected;
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ProfileDataGridTree.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ProfileDataGridTree.js
new file mode 100644
index 0000000..84d9923
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ProfileDataGridTree.js
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2009 280 North Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ProfileDataGridNode = function(profileView, profileNode, owningTree, hasChildren)
+{
+ this.profileView = profileView;
+ this.profileNode = profileNode;
+
+ WebInspector.DataGridNode.call(this, null, hasChildren);
+
+ this.addEventListener("populate", this._populate, this);
+
+ this.tree = owningTree;
+
+ this.childrenByCallUID = {};
+ this.lastComparator = null;
+
+ this.callUID = profileNode.callUID;
+ this.selfTime = profileNode.selfTime;
+ this.totalTime = profileNode.totalTime;
+ this.functionName = profileNode.functionName;
+ this.numberOfCalls = profileNode.numberOfCalls;
+ this.url = profileNode.url;
+}
+
+WebInspector.ProfileDataGridNode.prototype = {
+ get data()
+ {
+ function formatMilliseconds(time)
+ {
+ return Number.secondsToString(time / 1000, WebInspector.UIString.bind(WebInspector), true);
+ }
+
+ var data = {};
+
+ data["function"] = this.functionName;
+ data["calls"] = this.numberOfCalls;
+
+ if (this.profileView.showSelfTimeAsPercent)
+ data["self"] = WebInspector.UIString("%.2f%%", this.selfPercent);
+ else
+ data["self"] = formatMilliseconds(this.selfTime);
+
+ if (this.profileView.showTotalTimeAsPercent)
+ data["total"] = WebInspector.UIString("%.2f%%", this.totalPercent);
+ else
+ data["total"] = formatMilliseconds(this.totalTime);
+
+ if (this.profileView.showAverageTimeAsPercent)
+ data["average"] = WebInspector.UIString("%.2f%%", this.averagePercent);
+ else
+ data["average"] = formatMilliseconds(this.averageTime);
+
+ return data;
+ },
+
+ createCell: function(columnIdentifier)
+ {
+ var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier);
+
+ if (columnIdentifier === "self" && this._searchMatchedSelfColumn)
+ cell.addStyleClass("highlight");
+ else if (columnIdentifier === "total" && this._searchMatchedTotalColumn)
+ cell.addStyleClass("highlight");
+ else if (columnIdentifier === "average" && this._searchMatchedAverageColumn)
+ cell.addStyleClass("highlight");
+ else if (columnIdentifier === "calls" && this._searchMatchedCallsColumn)
+ cell.addStyleClass("highlight");
+
+ if (columnIdentifier !== "function")
+ return cell;
+
+ if (this.profileNode._searchMatchedFunctionColumn)
+ cell.addStyleClass("highlight");
+
+ if (this.profileNode.url) {
+ var fileName = WebInspector.displayNameForURL(this.profileNode.url);
+
+ var urlElement = document.createElement("a");
+ urlElement.className = "profile-node-file webkit-html-resource-link";
+ urlElement.href = this.profileNode.url;
+ urlElement.lineNumber = this.profileNode.lineNumber;
+
+ if (this.profileNode.lineNumber > 0)
+ urlElement.textContent = fileName + ":" + this.profileNode.lineNumber;
+ else
+ urlElement.textContent = fileName;
+
+ cell.insertBefore(urlElement, cell.firstChild);
+ }
+
+ return cell;
+ },
+
+ select: function(supressSelectedEvent)
+ {
+ WebInspector.DataGridNode.prototype.select.call(this, supressSelectedEvent);
+ this.profileView._dataGridNodeSelected(this);
+ },
+
+ deselect: function(supressDeselectedEvent)
+ {
+ WebInspector.DataGridNode.prototype.deselect.call(this, supressDeselectedEvent);
+ this.profileView._dataGridNodeDeselected(this);
+ },
+
+ expand: function()
+ {
+ if (!this.parent) {
+ var currentComparator = this.parent.lastComparator;
+
+ if (!currentComparator || (currentComparator === this.lastComparator))
+ return;
+
+ this.sort(currentComparator);
+ }
+
+ WebInspector.DataGridNode.prototype.expand.call(this);
+ },
+
+ sort: function(/*Function*/ comparator, /*Boolean*/ force)
+ {
+ var gridNodeGroups = [[this]];
+
+ for (var gridNodeGroupIndex = 0; gridNodeGroupIndex < gridNodeGroups.length; ++gridNodeGroupIndex) {
+ var gridNodes = gridNodeGroups[gridNodeGroupIndex];
+ var count = gridNodes.length;
+
+ for (var index = 0; index < count; ++index) {
+ var gridNode = gridNodes[index];
+
+ // If the grid node is collapsed, then don't sort children (save operation for later).
+ // If the grid node has the same sorting as previously, then there is no point in sorting it again.
+ if (!force && !gridNode.expanded || gridNode.lastComparator === comparator)
+ continue;
+
+ gridNode.lastComparator = comparator;
+
+ var children = gridNode.children;
+ var childCount = children.length;
+
+ if (childCount) {
+ children.sort(comparator);
+
+ for (var childIndex = 0; childIndex < childCount; ++childIndex)
+ children[childIndex]._recalculateSiblings(childIndex);
+
+ gridNodeGroups.push(children);
+ }
+ }
+ }
+ },
+
+ insertChild: function(/*ProfileDataGridNode*/ profileDataGridNode, index)
+ {
+ WebInspector.DataGridNode.prototype.insertChild.call(this, profileDataGridNode, index);
+
+ this.childrenByCallUID[profileDataGridNode.callUID] = profileDataGridNode;
+ },
+
+ removeChild: function(/*ProfileDataGridNode*/ profileDataGridNode)
+ {
+ WebInspector.DataGridNode.prototype.removeChild.call(this, profileDataGridNode);
+
+ delete this.childrenByCallUID[profileDataGridNode.callUID];
+ },
+
+ removeChildren: function(/*ProfileDataGridNode*/ profileDataGridNode)
+ {
+ WebInspector.DataGridNode.prototype.removeChildren.call(this);
+
+ this.childrenByCallUID = {};
+ },
+
+ findChild: function(/*Node*/ node)
+ {
+ if (!node)
+ return null;
+ return this.childrenByCallUID[node.callUID];
+ },
+
+ get averageTime()
+ {
+ return this.selfTime / Math.max(1, this.numberOfCalls);
+ },
+
+ get averagePercent()
+ {
+ return this.averageTime / this.tree.totalTime * 100.0;
+ },
+
+ get selfPercent()
+ {
+ return this.selfTime / this.tree.totalTime * 100.0;
+ },
+
+ get totalPercent()
+ {
+ return this.totalTime / this.tree.totalTime * 100.0;
+ },
+
+ // When focusing and collapsing we modify lots of nodes in the tree.
+ // This allows us to restore them all to their original state when we revert.
+ _save: function()
+ {
+ if (this._savedChildren)
+ return;
+
+ this._savedSelfTime = this.selfTime;
+ this._savedTotalTime = this.totalTime;
+ this._savedNumberOfCalls = this.numberOfCalls;
+
+ this._savedChildren = this.children.slice();
+ },
+
+ // When focusing and collapsing we modify lots of nodes in the tree.
+ // This allows us to restore them all to their original state when we revert.
+ _restore: function()
+ {
+ if (!this._savedChildren)
+ return;
+
+ this.selfTime = this._savedSelfTime;
+ this.totalTime = this._savedTotalTime;
+ this.numberOfCalls = this._savedNumberOfCalls;
+
+ this.removeChildren();
+
+ var children = this._savedChildren;
+ var count = children.length;
+
+ for (var index = 0; index < count; ++index) {
+ children[index]._restore();
+ this.appendChild(children[index]);
+ }
+ },
+
+ _merge: function(child, shouldAbsorb)
+ {
+ this.selfTime += child.selfTime;
+
+ if (!shouldAbsorb) {
+ this.totalTime += child.totalTime;
+ this.numberOfCalls += child.numberOfCalls;
+ }
+
+ var children = this.children.slice();
+
+ this.removeChildren();
+
+ var count = children.length;
+
+ for (var index = 0; index < count; ++index) {
+ if (!shouldAbsorb || children[index] !== child)
+ this.appendChild(children[index]);
+ }
+
+ children = child.children.slice();
+ count = children.length;
+
+ for (var index = 0; index < count; ++index) {
+ var orphanedChild = children[index],
+ existingChild = this.childrenByCallUID[orphanedChild.callUID];
+
+ if (existingChild)
+ existingChild._merge(orphanedChild, false);
+ else
+ this.appendChild(orphanedChild);
+ }
+ }
+}
+
+WebInspector.ProfileDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
+
+WebInspector.ProfileDataGridTree = function(profileView, profileNode)
+{
+ this.tree = this;
+ this.children = [];
+
+ this.profileView = profileView;
+
+ this.totalTime = profileNode.totalTime;
+ this.lastComparator = null;
+
+ this.childrenByCallUID = {};
+}
+
+WebInspector.ProfileDataGridTree.prototype = {
+ get expanded()
+ {
+ return true;
+ },
+
+ appendChild: function(child)
+ {
+ this.insertChild(child, this.children.length);
+ },
+
+ insertChild: function(child, index)
+ {
+ this.children.splice(index, 0, child);
+ this.childrenByCallUID[child.callUID] = child;
+ },
+
+ removeChildren: function()
+ {
+ this.children = [];
+ this.childrenByCallUID = {};
+ },
+
+ findChild: WebInspector.ProfileDataGridNode.prototype.findChild,
+ sort: WebInspector.ProfileDataGridNode.prototype.sort,
+
+ _save: function()
+ {
+ if (this._savedChildren)
+ return;
+
+ this._savedTotalTime = this.totalTime;
+ this._savedChildren = this.children.slice();
+ },
+
+ restore: function()
+ {
+ if (!this._savedChildren)
+ return;
+
+ this.children = this._savedChildren;
+ this.totalTime = this._savedTotalTime;
+
+ var children = this.children;
+ var count = children.length;
+
+ for (var index = 0; index < count; ++index)
+ children[index]._restore();
+
+ this._savedChildren = null;
+ }
+}
+
+WebInspector.ProfileDataGridTree.propertyComparators = [{}, {}];
+
+WebInspector.ProfileDataGridTree.propertyComparator = function(/*String*/ property, /*Boolean*/ isAscending)
+{
+ var comparator = this.propertyComparators[(isAscending ? 1 : 0)][property];
+
+ if (!comparator) {
+ if (isAscending) {
+ comparator = function(lhs, rhs)
+ {
+ if (lhs[property] < rhs[property])
+ return -1;
+
+ if (lhs[property] > rhs[property])
+ return 1;
+
+ return 0;
+ }
+ } else {
+ comparator = function(lhs, rhs)
+ {
+ if (lhs[property] > rhs[property])
+ return -1;
+
+ if (lhs[property] < rhs[property])
+ return 1;
+
+ return 0;
+ }
+ }
+
+ this.propertyComparators[(isAscending ? 1 : 0)][property] = comparator;
+ }
+
+ return comparator;
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ProfileView.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ProfileView.js
new file mode 100644
index 0000000..d00733c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ProfileView.js
@@ -0,0 +1,580 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ProfileView = function(profile)
+{
+ WebInspector.View.call(this);
+
+ this.element.addStyleClass("profile-view");
+
+ this.showSelfTimeAsPercent = true;
+ this.showTotalTimeAsPercent = true;
+ this.showAverageTimeAsPercent = true;
+
+ var columns = { "self": { title: WebInspector.UIString("Self"), width: "72px", sort: "descending", sortable: true },
+ "total": { title: WebInspector.UIString("Total"), width: "72px", sortable: true },
+ "average": { title: WebInspector.UIString("Average"), width: "72px", sortable: true },
+ "calls": { title: WebInspector.UIString("Calls"), width: "54px", sortable: true },
+ "function": { title: WebInspector.UIString("Function"), disclosure: true, 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.viewSelectElement = document.createElement("select");
+ this.viewSelectElement.className = "status-bar-item";
+ this.viewSelectElement.addEventListener("change", this._changeView.bind(this), false);
+ this.view = "Heavy";
+
+ var heavyViewOption = document.createElement("option");
+ heavyViewOption.label = WebInspector.UIString("Heavy (Bottom Up)");
+ var treeViewOption = document.createElement("option");
+ treeViewOption.label = WebInspector.UIString("Tree (Top Down)");
+ this.viewSelectElement.appendChild(heavyViewOption);
+ this.viewSelectElement.appendChild(treeViewOption);
+
+ this.percentButton = document.createElement("button");
+ this.percentButton.className = "percent-time-status-bar-item status-bar-item";
+ this.percentButton.addEventListener("click", this._percentClicked.bind(this), false);
+
+ this.focusButton = document.createElement("button");
+ this.focusButton.title = WebInspector.UIString("Focus selected function.");
+ this.focusButton.className = "focus-profile-node-status-bar-item status-bar-item";
+ this.focusButton.disabled = true;
+ this.focusButton.addEventListener("click", this._focusClicked.bind(this), false);
+
+ this.excludeButton = document.createElement("button");
+ this.excludeButton.title = WebInspector.UIString("Exclude selected function.");
+ this.excludeButton.className = "exclude-profile-node-status-bar-item status-bar-item";
+ this.excludeButton.disabled = true;
+ this.excludeButton.addEventListener("click", this._excludeClicked.bind(this), false);
+
+ this.resetButton = document.createElement("button");
+ this.resetButton.title = WebInspector.UIString("Restore all functions.");
+ this.resetButton.className = "reset-profile-status-bar-item status-bar-item hidden";
+ this.resetButton.addEventListener("click", this._resetClicked.bind(this), false);
+
+ this.profile = profile;
+
+ this.profileDataGridTree = this.bottomUpProfileDataGridTree;
+ this.profileDataGridTree.sort(WebInspector.ProfileDataGridTree.propertyComparator("selfTime", false));
+
+ this.refresh();
+
+ this._updatePercentButton();
+}
+
+WebInspector.ProfileView.prototype = {
+ get statusBarItems()
+ {
+ return [this.viewSelectElement, this.percentButton, this.focusButton, this.excludeButton, this.resetButton];
+ },
+
+ get profile()
+ {
+ return this._profile;
+ },
+
+ set profile(profile)
+ {
+ this._profile = profile;
+ },
+
+ get bottomUpProfileDataGridTree()
+ {
+ if (!this._bottomUpProfileDataGridTree)
+ this._bottomUpProfileDataGridTree = new WebInspector.BottomUpProfileDataGridTree(this, this.profile.head);
+ return this._bottomUpProfileDataGridTree;
+ },
+
+ get topDownProfileDataGridTree()
+ {
+ if (!this._topDownProfileDataGridTree)
+ this._topDownProfileDataGridTree = new WebInspector.TopDownProfileDataGridTree(this, this.profile.head);
+ return this._topDownProfileDataGridTree;
+ },
+
+ get currentTree()
+ {
+ return this._currentTree;
+ },
+
+ set currentTree(tree)
+ {
+ this._currentTree = tree;
+ this.refresh();
+ },
+
+ get topDownTree()
+ {
+ if (!this._topDownTree) {
+ this._topDownTree = WebInspector.TopDownTreeFactory.create(this.profile.head);
+ this._sortProfile(this._topDownTree);
+ }
+
+ return this._topDownTree;
+ },
+
+ get bottomUpTree()
+ {
+ if (!this._bottomUpTree) {
+ this._bottomUpTree = WebInspector.BottomUpTreeFactory.create(this.profile.head);
+ this._sortProfile(this._bottomUpTree);
+ }
+
+ return this._bottomUpTree;
+ },
+
+ hide: function()
+ {
+ WebInspector.View.prototype.hide.call(this);
+ this._currentSearchResultIndex = -1;
+ },
+
+ refresh: function()
+ {
+ var selectedProfileNode = this.dataGrid.selectedNode ? this.dataGrid.selectedNode.profileNode : null;
+
+ this.dataGrid.removeChildren();
+
+ var children = this.profileDataGridTree.children;
+ var count = children.length;
+
+ for (var index = 0; index < count; ++index)
+ this.dataGrid.appendChild(children[index]);
+
+ if (selectedProfileNode && selectedProfileNode._dataGridNode)
+ selectedProfileNode._dataGridNode.selected = true;
+ },
+
+ refreshVisibleData: function()
+ {
+ var child = this.dataGrid.children[0];
+ while (child) {
+ child.refresh();
+ child = child.traverseNextNode(false, null, true);
+ }
+ },
+
+ refreshShowAsPercents: function()
+ {
+ this._updatePercentButton();
+ this.refreshVisibleData();
+ },
+
+ searchCanceled: function()
+ {
+ if (this._searchResults) {
+ for (var i = 0; i < this._searchResults.length; ++i) {
+ var profileNode = this._searchResults[i].profileNode;
+
+ delete profileNode._searchMatchedSelfColumn;
+ delete profileNode._searchMatchedTotalColumn;
+ delete profileNode._searchMatchedCallsColumn;
+ delete profileNode._searchMatchedFunctionColumn;
+
+ if (profileNode._dataGridNode)
+ profileNode._dataGridNode.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 greaterThan = (query.indexOf(">") === 0);
+ var lessThan = (query.indexOf("<") === 0);
+ var equalTo = (query.indexOf("=") === 0 || ((greaterThan || lessThan) && query.indexOf("=") === 1));
+ var percentUnits = (query.lastIndexOf("%") === (query.length - 1));
+ var millisecondsUnits = (query.length > 2 && query.lastIndexOf("ms") === (query.length - 2));
+ var secondsUnits = (!millisecondsUnits && query.lastIndexOf("s") === (query.length - 1));
+
+ var queryNumber = parseFloat(query);
+ if (greaterThan || lessThan || equalTo) {
+ if (equalTo && (greaterThan || lessThan))
+ queryNumber = parseFloat(query.substring(2));
+ else
+ queryNumber = parseFloat(query.substring(1));
+ }
+
+ var queryNumberMilliseconds = (secondsUnits ? (queryNumber * 1000) : queryNumber);
+
+ // Make equalTo implicitly true if it wasn't specified there is no other operator.
+ if (!isNaN(queryNumber) && !(greaterThan || lessThan))
+ equalTo = true;
+
+ function matchesQuery(/*ProfileDataGridNode*/ profileDataGridNode)
+ {
+ delete profileDataGridNode._searchMatchedSelfColumn;
+ delete profileDataGridNode._searchMatchedTotalColumn;
+ delete profileDataGridNode._searchMatchedAverageColumn;
+ delete profileDataGridNode._searchMatchedCallsColumn;
+ delete profileDataGridNode._searchMatchedFunctionColumn;
+
+ if (percentUnits) {
+ if (lessThan) {
+ if (profileDataGridNode.selfPercent < queryNumber)
+ profileDataGridNode._searchMatchedSelfColumn = true;
+ if (profileDataGridNode.totalPercent < queryNumber)
+ profileDataGridNode._searchMatchedTotalColumn = true;
+ if (profileDataGridNode.averagePercent < queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedAverageColumn = true;
+ } else if (greaterThan) {
+ if (profileDataGridNode.selfPercent > queryNumber)
+ profileDataGridNode._searchMatchedSelfColumn = true;
+ if (profileDataGridNode.totalPercent > queryNumber)
+ profileDataGridNode._searchMatchedTotalColumn = true;
+ if (profileDataGridNode.averagePercent < queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedAverageColumn = true;
+ }
+
+ if (equalTo) {
+ if (profileDataGridNode.selfPercent == queryNumber)
+ profileDataGridNode._searchMatchedSelfColumn = true;
+ if (profileDataGridNode.totalPercent == queryNumber)
+ profileDataGridNode._searchMatchedTotalColumn = true;
+ if (profileDataGridNode.averagePercent < queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedAverageColumn = true;
+ }
+ } else if (millisecondsUnits || secondsUnits) {
+ if (lessThan) {
+ if (profileDataGridNode.selfTime < queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedSelfColumn = true;
+ if (profileDataGridNode.totalTime < queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedTotalColumn = true;
+ if (profileDataGridNode.averageTime < queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedAverageColumn = true;
+ } else if (greaterThan) {
+ if (profileDataGridNode.selfTime > queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedSelfColumn = true;
+ if (profileDataGridNode.totalTime > queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedTotalColumn = true;
+ if (profileDataGridNode.averageTime > queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedAverageColumn = true;
+ }
+
+ if (equalTo) {
+ if (profileDataGridNode.selfTime == queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedSelfColumn = true;
+ if (profileDataGridNode.totalTime == queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedTotalColumn = true;
+ if (profileDataGridNode.averageTime == queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedAverageColumn = true;
+ }
+ } else {
+ if (equalTo && profileDataGridNode.numberOfCalls == queryNumber)
+ profileDataGridNode._searchMatchedCallsColumn = true;
+ if (greaterThan && profileDataGridNode.numberOfCalls > queryNumber)
+ profileDataGridNode._searchMatchedCallsColumn = true;
+ if (lessThan && profileDataGridNode.numberOfCalls < queryNumber)
+ profileDataGridNode._searchMatchedCallsColumn = true;
+ }
+
+ if (profileDataGridNode.functionName.hasSubstring(query, true) || profileDataGridNode.url.hasSubstring(query, true))
+ profileDataGridNode._searchMatchedFunctionColumn = true;
+
+ if (profileDataGridNode._searchMatchedSelfColumn ||
+ profileDataGridNode._searchMatchedTotalColumn ||
+ profileDataGridNode._searchMatchedAverageColumn ||
+ profileDataGridNode._searchMatchedCallsColumn ||
+ profileDataGridNode._searchMatchedFunctionColumn);
+ {
+ profileDataGridNode.refresh();
+ return true;
+ }
+
+ return false;
+ }
+
+ var current = this.dataGrid;
+ var ancestors = [];
+ var nextIndexes = [];
+ var startIndex = 0;
+
+ while (current) {
+ var children = current.children;
+ var childrenLength = children.length;
+
+ if (startIndex >= childrenLength) {
+ current = ancestors.pop();
+ startIndex = nextIndexes.pop();
+ continue;
+ }
+
+ for (var i = startIndex; i < childrenLength; ++i) {
+ var child = children[i];
+
+ if (matchesQuery(child)) {
+ if (child._dataGridNode) {
+ // The child has a data grid node already, no need to remember the ancestors.
+ this._searchResults.push({ profileNode: child });
+ } else {
+ var ancestorsCopy = [].concat(ancestors);
+ ancestorsCopy.push(current);
+ this._searchResults.push({ profileNode: child, ancestors: ancestorsCopy });
+ }
+ }
+
+ if (child.children.length) {
+ ancestors.push(current);
+ nextIndexes.push(i + 1);
+ current = child;
+ startIndex = 0;
+ break;
+ }
+
+ if (i === (childrenLength - 1)) {
+ current = ancestors.pop();
+ startIndex = nextIndexes.pop();
+ }
+ }
+ }
+
+ finishedCallback(this, this._searchResults.length);
+ },
+
+ jumpToFirstSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ this._currentSearchResultIndex = 0;
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToLastSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ this._currentSearchResultIndex = (this._searchResults.length - 1);
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToNextSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ if (++this._currentSearchResultIndex >= this._searchResults.length)
+ this._currentSearchResultIndex = 0;
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToPreviousSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ if (--this._currentSearchResultIndex < 0)
+ this._currentSearchResultIndex = (this._searchResults.length - 1);
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ showingFirstSearchResult: function()
+ {
+ return (this._currentSearchResultIndex === 0);
+ },
+
+ showingLastSearchResult: function()
+ {
+ return (this._searchResults && this._currentSearchResultIndex === (this._searchResults.length - 1));
+ },
+
+ _jumpToSearchResult: function(index)
+ {
+ var searchResult = this._searchResults[index];
+ if (!searchResult)
+ return;
+
+ var profileNode = this._searchResults[index].profileNode;
+ if (!profileNode._dataGridNode && searchResult.ancestors) {
+ var ancestors = searchResult.ancestors;
+ for (var i = 0; i < ancestors.length; ++i) {
+ var ancestorProfileNode = ancestors[i];
+ var gridNode = ancestorProfileNode._dataGridNode;
+ if (gridNode)
+ gridNode.expand();
+ }
+
+ // No need to keep the ancestors around.
+ delete searchResult.ancestors;
+ }
+
+ gridNode = profileNode._dataGridNode;
+ if (!gridNode)
+ return;
+
+ gridNode.reveal();
+ gridNode.select();
+ },
+
+ _changeView: function(event)
+ {
+ if (!event || !this.profile)
+ return;
+
+ if (event.target.selectedIndex == 1 && this.view == "Heavy") {
+ this.profileDataGridTree = this.topDownProfileDataGridTree;
+ this._sortProfile();
+ this.view = "Tree";
+ } else if (event.target.selectedIndex == 0 && this.view == "Tree") {
+ this.profileDataGridTree = this.bottomUpProfileDataGridTree;
+ this._sortProfile();
+ this.view = "Heavy";
+ }
+
+ 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 the with same query and callback.
+ this._searchFinishedCallback(this, -this._searchResults.length);
+ this.performSearch(this.currentQuery, this._searchFinishedCallback);
+ },
+
+ _percentClicked: function(event)
+ {
+ var currentState = this.showSelfTimeAsPercent && this.showTotalTimeAsPercent && this.showAverageTimeAsPercent;
+ this.showSelfTimeAsPercent = !currentState;
+ this.showTotalTimeAsPercent = !currentState;
+ this.showAverageTimeAsPercent = !currentState;
+ this.refreshShowAsPercents();
+ },
+
+ _updatePercentButton: function()
+ {
+ if (this.showSelfTimeAsPercent && this.showTotalTimeAsPercent && this.showAverageTimeAsPercent) {
+ this.percentButton.title = WebInspector.UIString("Show absolute total and self times.");
+ this.percentButton.addStyleClass("toggled-on");
+ } else {
+ this.percentButton.title = WebInspector.UIString("Show total and self times as percentages.");
+ this.percentButton.removeStyleClass("toggled-on");
+ }
+ },
+
+ _focusClicked: function(event)
+ {
+ if (!this.dataGrid.selectedNode)
+ return;
+
+ this.resetButton.removeStyleClass("hidden");
+ this.profileDataGridTree.focus(this.dataGrid.selectedNode);
+ this.refresh();
+ this.refreshVisibleData();
+ },
+
+ _excludeClicked: function(event)
+ {
+ var selectedNode = this.dataGrid.selectedNode
+
+ if (!selectedNode)
+ return;
+
+ selectedNode.deselect();
+
+ this.resetButton.removeStyleClass("hidden");
+ this.profileDataGridTree.exclude(selectedNode);
+ this.refresh();
+ this.refreshVisibleData();
+ },
+
+ _resetClicked: function(event)
+ {
+ this.resetButton.addStyleClass("hidden");
+ this.profileDataGridTree.restore();
+ this.refresh();
+ this.refreshVisibleData();
+ },
+
+ _dataGridNodeSelected: function(node)
+ {
+ this.focusButton.disabled = false;
+ this.excludeButton.disabled = false;
+ },
+
+ _dataGridNodeDeselected: function(node)
+ {
+ this.focusButton.disabled = true;
+ this.excludeButton.disabled = true;
+ },
+
+ _sortData: function(event)
+ {
+ this._sortProfile(this.profile);
+ },
+
+ _sortProfile: function()
+ {
+ var sortAscending = this.dataGrid.sortOrder === "ascending";
+ var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
+ var sortProperty = {
+ "average": "averageTime",
+ "self": "selfTime",
+ "total": "totalTime",
+ "calls": "numberOfCalls",
+ "function": "functionName"
+ }[sortColumnIdentifier];
+
+ this.profileDataGridTree.sort(WebInspector.ProfileDataGridTree.propertyComparator(sortProperty, sortAscending));
+
+ this.refresh();
+ },
+
+ _mouseDownInDataGrid: function(event)
+ {
+ if (event.detail < 2)
+ return;
+
+ var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
+ if (!cell || (!cell.hasStyleClass("total-column") && !cell.hasStyleClass("self-column") && !cell.hasStyleClass("average-column")))
+ return;
+
+ if (cell.hasStyleClass("total-column"))
+ this.showTotalTimeAsPercent = !this.showTotalTimeAsPercent;
+ else if (cell.hasStyleClass("self-column"))
+ this.showSelfTimeAsPercent = !this.showSelfTimeAsPercent;
+ else if (cell.hasStyleClass("average-column"))
+ this.showAverageTimeAsPercent = !this.showAverageTimeAsPercent;
+
+ this.refreshShowAsPercents();
+
+ event.preventDefault();
+ event.stopPropagation();
+ }
+}
+
+WebInspector.ProfileView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ProfilesPanel.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ProfilesPanel.js
new file mode 100644
index 0000000..aafc306
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ProfilesPanel.js
@@ -0,0 +1,502 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+const UserInitiatedProfileName = "org.webkit.profiles.user-initiated";
+
+WebInspector.ProfilesPanel = function()
+{
+ WebInspector.Panel.call(this);
+
+ this.element.addStyleClass("profiles");
+
+ var panelEnablerHeading = WebInspector.UIString("You need to enable profiling before you can use the Profiles panel.");
+ var panelEnablerDisclaimer = WebInspector.UIString("Enabling profiling will make scripts run slower.");
+ var panelEnablerButton = WebInspector.UIString("Enable Profiling");
+ this.panelEnablerView = new WebInspector.PanelEnablerView("profiles", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
+ this.panelEnablerView.addEventListener("enable clicked", this._enableProfiling, this);
+
+ this.element.appendChild(this.panelEnablerView.element);
+
+ this.sidebarElement = document.createElement("div");
+ this.sidebarElement.id = "profiles-sidebar";
+ this.sidebarElement.className = "sidebar";
+ this.element.appendChild(this.sidebarElement);
+
+ this.sidebarResizeElement = document.createElement("div");
+ this.sidebarResizeElement.className = "sidebar-resizer-vertical";
+ this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarDragging.bind(this), false);
+ this.element.appendChild(this.sidebarResizeElement);
+
+ this.sidebarTreeElement = document.createElement("ol");
+ this.sidebarTreeElement.className = "sidebar-tree";
+ this.sidebarElement.appendChild(this.sidebarTreeElement);
+
+ this.sidebarTree = new TreeOutline(this.sidebarTreeElement);
+
+ this.profileViews = document.createElement("div");
+ this.profileViews.id = "profile-views";
+ this.element.appendChild(this.profileViews);
+
+ this.enableToggleButton = document.createElement("button");
+ this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item";
+ this.enableToggleButton.addEventListener("click", this._toggleProfiling.bind(this), false);
+
+ this.recordButton = document.createElement("button");
+ this.recordButton.title = WebInspector.UIString("Start profiling.");
+ this.recordButton.id = "record-profile-status-bar-item";
+ this.recordButton.className = "status-bar-item";
+ this.recordButton.addEventListener("click", this._recordClicked.bind(this), false);
+
+ this.recording = false;
+
+ this.profileViewStatusBarItemsContainer = document.createElement("div");
+ this.profileViewStatusBarItemsContainer.id = "profile-view-status-bar-items";
+
+ this.reset();
+}
+
+WebInspector.ProfilesPanel.prototype = {
+ toolbarItemClass: "profiles",
+
+ get toolbarItemLabel()
+ {
+ return WebInspector.UIString("Profiles");
+ },
+
+ get statusBarItems()
+ {
+ return [this.enableToggleButton, this.recordButton, this.profileViewStatusBarItemsContainer];
+ },
+
+ show: function()
+ {
+ WebInspector.Panel.prototype.show.call(this);
+ this._updateSidebarWidth();
+ if (this._shouldPopulateProfiles)
+ this._populateProfiles();
+ },
+
+ populateInterface: function()
+ {
+ if (this.visible)
+ this._populateProfiles();
+ else
+ this._shouldPopulateProfiles = true;
+ },
+
+ profilerWasEnabled: function()
+ {
+ this.reset();
+ this.populateInterface();
+ },
+
+ profilerWasDisabled: function()
+ {
+ this.reset();
+ },
+
+ reset: function()
+ {
+ if (this._profiles) {
+ var profiledLength = this._profiles.length;
+ for (var i = 0; i < profiledLength; ++i) {
+ var profile = this._profiles[i];
+ delete profile._profileView;
+ }
+ }
+
+ delete this.currentQuery;
+ this.searchCanceled();
+
+ this._profiles = [];
+ this._profilesIdMap = {};
+ this._profileGroups = {};
+ this._profileGroupsForLinks = {}
+
+ this.sidebarTreeElement.removeStyleClass("some-expandable");
+
+ this.sidebarTree.removeChildren();
+ this.profileViews.removeChildren();
+
+ this.profileViewStatusBarItemsContainer.removeChildren();
+
+ this._updateInterface();
+ },
+
+ handleKeyEvent: function(event)
+ {
+ this.sidebarTree.handleKeyEvent(event);
+ },
+
+ addProfile: function(profile)
+ {
+ this._profiles.push(profile);
+ this._profilesIdMap[profile.uid] = profile;
+
+ var sidebarParent = this.sidebarTree;
+ var small = false;
+ var alternateTitle;
+
+ if (profile.title.indexOf(UserInitiatedProfileName) !== 0) {
+ if (!(profile.title in this._profileGroups))
+ this._profileGroups[profile.title] = [];
+
+ var group = this._profileGroups[profile.title];
+ group.push(profile);
+
+ if (group.length === 2) {
+ // Make a group TreeElement now that there are 2 profiles.
+ group._profilesTreeElement = new WebInspector.ProfileGroupSidebarTreeElement(profile.title);
+
+ // Insert at the same index for the first profile of the group.
+ var index = this.sidebarTree.children.indexOf(group[0]._profilesTreeElement);
+ this.sidebarTree.insertChild(group._profilesTreeElement, index);
+
+ // Move the first profile to the group.
+ var selected = group[0]._profilesTreeElement.selected;
+ this.sidebarTree.removeChild(group[0]._profilesTreeElement);
+ group._profilesTreeElement.appendChild(group[0]._profilesTreeElement);
+ if (selected) {
+ group[0]._profilesTreeElement.select();
+ group[0]._profilesTreeElement.reveal();
+ }
+
+ group[0]._profilesTreeElement.small = true;
+ group[0]._profilesTreeElement.mainTitle = WebInspector.UIString("Run %d", 1);
+
+ this.sidebarTreeElement.addStyleClass("some-expandable");
+ }
+
+ if (group.length >= 2) {
+ sidebarParent = group._profilesTreeElement;
+ alternateTitle = WebInspector.UIString("Run %d", group.length);
+ small = true;
+ }
+ }
+
+ var profileTreeElement = new WebInspector.ProfileSidebarTreeElement(profile);
+ profileTreeElement.small = small;
+ if (alternateTitle)
+ profileTreeElement.mainTitle = alternateTitle;
+ profile._profilesTreeElement = profileTreeElement;
+
+ sidebarParent.appendChild(profileTreeElement);
+ },
+
+ showProfile: function(profile)
+ {
+ if (!profile)
+ return;
+
+ if (this.visibleView)
+ this.visibleView.hide();
+
+ var view = this.profileViewForProfile(profile);
+
+ view.show(this.profileViews);
+
+ profile._profilesTreeElement.select(true);
+ profile._profilesTreeElement.reveal();
+
+ this.visibleView = view;
+
+ this.profileViewStatusBarItemsContainer.removeChildren();
+
+ var statusBarItems = view.statusBarItems;
+ for (var i = 0; i < statusBarItems.length; ++i)
+ this.profileViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
+ },
+
+ showView: function(view)
+ {
+ this.showProfile(view.profile);
+ },
+
+ profileViewForProfile: function(profile)
+ {
+ if (!profile)
+ return null;
+ if (!profile._profileView)
+ profile._profileView = new WebInspector.ProfileView(profile);
+ return profile._profileView;
+ },
+
+ showProfileById: function(uid)
+ {
+ this.showProfile(this._profilesIdMap[uid]);
+ },
+
+ closeVisibleView: function()
+ {
+ if (this.visibleView)
+ this.visibleView.hide();
+ delete this.visibleView;
+ },
+
+ displayTitleForProfileLink: function(title)
+ {
+ title = unescape(title);
+ if (title.indexOf(UserInitiatedProfileName) === 0) {
+ title = WebInspector.UIString("Profile %d", title.substring(UserInitiatedProfileName.length + 1));
+ } else {
+ if (!(title in this._profileGroupsForLinks))
+ this._profileGroupsForLinks[title] = 0;
+
+ groupNumber = ++this._profileGroupsForLinks[title];
+
+ if (groupNumber >= 2)
+ title += " " + WebInspector.UIString("Run %d", groupNumber);
+ }
+
+ return title;
+ },
+
+ get searchableViews()
+ {
+ var views = [];
+
+ const visibleView = this.visibleView;
+ if (visibleView && visibleView.performSearch)
+ views.push(visibleView);
+
+ var profilesLength = this._profiles.length;
+ for (var i = 0; i < profilesLength; ++i) {
+ var view = this.profileViewForProfile(this._profiles[i]);
+ if (!view.performSearch || view === visibleView)
+ continue;
+ views.push(view);
+ }
+
+ return views;
+ },
+
+ searchMatchFound: function(view, matches)
+ {
+ view.profile._profilesTreeElement.searchMatches = matches;
+ },
+
+ searchCanceled: function(startingNewSearch)
+ {
+ WebInspector.Panel.prototype.searchCanceled.call(this, startingNewSearch);
+
+ if (!this._profiles)
+ return;
+
+ for (var i = 0; i < this._profiles.length; ++i) {
+ var profile = this._profiles[i];
+ profile._profilesTreeElement.searchMatches = 0;
+ }
+ },
+
+ setRecordingProfile: function(isProfiling)
+ {
+ this.recording = isProfiling;
+
+ if (isProfiling) {
+ this.recordButton.addStyleClass("toggled-on");
+ this.recordButton.title = WebInspector.UIString("Stop profiling.");
+ } else {
+ this.recordButton.removeStyleClass("toggled-on");
+ this.recordButton.title = WebInspector.UIString("Start profiling.");
+ }
+ },
+
+ _updateInterface: function()
+ {
+ if (InspectorController.profilerEnabled()) {
+ this.enableToggleButton.title = WebInspector.UIString("Profiling enabled. Click to disable.");
+ this.enableToggleButton.addStyleClass("toggled-on");
+ this.recordButton.removeStyleClass("hidden");
+ this.profileViewStatusBarItemsContainer.removeStyleClass("hidden");
+ this.panelEnablerView.visible = false;
+ } else {
+ this.enableToggleButton.title = WebInspector.UIString("Profiling disabled. Click to enable.");
+ this.enableToggleButton.removeStyleClass("toggled-on");
+ this.recordButton.addStyleClass("hidden");
+ this.profileViewStatusBarItemsContainer.addStyleClass("hidden");
+ this.panelEnablerView.visible = true;
+ }
+ },
+
+ _recordClicked: function()
+ {
+ this.recording = !this.recording;
+
+ if (this.recording)
+ InspectorController.startProfiling();
+ else
+ InspectorController.stopProfiling();
+ },
+
+ _enableProfiling: function()
+ {
+ if (InspectorController.profilerEnabled())
+ return;
+ this._toggleProfiling(this.panelEnablerView.alwaysEnabled);
+ },
+
+ _toggleProfiling: function(optionalAlways)
+ {
+ if (InspectorController.profilerEnabled())
+ InspectorController.disableProfiler(true);
+ else
+ InspectorController.enableProfiler(!!optionalAlways);
+ },
+
+ _populateProfiles: function()
+ {
+ if (this.sidebarTree.children.length)
+ return;
+
+ var profiles = InspectorController.profiles();
+ var profilesLength = profiles.length;
+ for (var i = 0; i < profilesLength; ++i) {
+ var profile = profiles[i];
+ this.addProfile(profile);
+ }
+
+ if (this.sidebarTree.children[0])
+ this.sidebarTree.children[0].select();
+
+ delete this._shouldPopulateProfiles;
+ },
+
+ _startSidebarDragging: function(event)
+ {
+ WebInspector.elementDragStart(this.sidebarResizeElement, this._sidebarDragging.bind(this), this._endSidebarDragging.bind(this), event, "col-resize");
+ },
+
+ _sidebarDragging: function(event)
+ {
+ this._updateSidebarWidth(event.pageX);
+
+ event.preventDefault();
+ },
+
+ _endSidebarDragging: function(event)
+ {
+ WebInspector.elementDragEnd(event);
+ },
+
+ _updateSidebarWidth: function(width)
+ {
+ if (this.sidebarElement.offsetWidth <= 0) {
+ // The stylesheet hasn't loaded yet or the window is closed,
+ // so we can't calculate what is need. Return early.
+ return;
+ }
+
+ if (!("_currentSidebarWidth" in this))
+ this._currentSidebarWidth = this.sidebarElement.offsetWidth;
+
+ if (typeof width === "undefined")
+ width = this._currentSidebarWidth;
+
+ width = Number.constrain(width, Preferences.minSidebarWidth, window.innerWidth / 2);
+
+ this._currentSidebarWidth = width;
+
+ this.sidebarElement.style.width = width + "px";
+ this.profileViews.style.left = width + "px";
+ this.profileViewStatusBarItemsContainer.style.left = width + "px";
+ this.sidebarResizeElement.style.left = (width - 3) + "px";
+ }
+}
+
+WebInspector.ProfilesPanel.prototype.__proto__ = WebInspector.Panel.prototype;
+
+WebInspector.ProfileSidebarTreeElement = function(profile)
+{
+ this.profile = profile;
+
+ if (this.profile.title.indexOf(UserInitiatedProfileName) === 0)
+ this._profileNumber = this.profile.title.substring(UserInitiatedProfileName.length + 1);
+
+ WebInspector.SidebarTreeElement.call(this, "profile-sidebar-tree-item", "", "", profile, false);
+
+ this.refreshTitles();
+}
+
+WebInspector.ProfileSidebarTreeElement.prototype = {
+ onselect: function()
+ {
+ WebInspector.panels.profiles.showProfile(this.profile);
+ },
+
+ get mainTitle()
+ {
+ if (this._mainTitle)
+ return this._mainTitle;
+ if (this.profile.title.indexOf(UserInitiatedProfileName) === 0)
+ return WebInspector.UIString("Profile %d", this._profileNumber);
+ return this.profile.title;
+ },
+
+ set mainTitle(x)
+ {
+ this._mainTitle = x;
+ this.refreshTitles();
+ },
+
+ get subtitle()
+ {
+ // There is no subtitle.
+ },
+
+ set subtitle(x)
+ {
+ // Can't change subtitle.
+ },
+
+ set searchMatches(matches)
+ {
+ if (!matches) {
+ if (!this.bubbleElement)
+ return;
+ this.bubbleElement.removeStyleClass("search-matches");
+ this.bubbleText = "";
+ return;
+ }
+
+ this.bubbleText = matches;
+ this.bubbleElement.addStyleClass("search-matches");
+ }
+}
+
+WebInspector.ProfileSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
+
+WebInspector.ProfileGroupSidebarTreeElement = function(title, subtitle)
+{
+ WebInspector.SidebarTreeElement.call(this, "profile-group-sidebar-tree-item", title, subtitle, null, true);
+}
+
+WebInspector.ProfileGroupSidebarTreeElement.prototype = {
+ onselect: function()
+ {
+ WebInspector.panels.profiles.showProfile(this.children[this.children.length - 1].profile);
+ }
+}
+
+WebInspector.ProfileGroupSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/PropertiesSection.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/PropertiesSection.js
new file mode 100644
index 0000000..a4b2fba
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/PropertiesSection.js
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.PropertiesSection = function(title, subtitle)
+{
+ this.element = document.createElement("div");
+ this.element.className = "section";
+
+ this.headerElement = document.createElement("div");
+ this.headerElement.className = "header";
+
+ this.titleElement = document.createElement("div");
+ this.titleElement.className = "title";
+
+ this.subtitleElement = document.createElement("div");
+ this.subtitleElement.className = "subtitle";
+
+ this.headerElement.appendChild(this.subtitleElement);
+ this.headerElement.appendChild(this.titleElement);
+
+ this.headerElement.addEventListener("click", this.toggleExpanded.bind(this), false);
+
+ this.propertiesElement = document.createElement("ol");
+ this.propertiesElement.className = "properties";
+ this.propertiesTreeOutline = new TreeOutline(this.propertiesElement);
+ this.propertiesTreeOutline.section = this;
+
+ this.element.appendChild(this.headerElement);
+ this.element.appendChild(this.propertiesElement);
+
+ this.title = title;
+ this.subtitle = subtitle;
+ this._expanded = false;
+}
+
+WebInspector.PropertiesSection.prototype = {
+ get title()
+ {
+ return this._title;
+ },
+
+ set title(x)
+ {
+ if (this._title === x)
+ return;
+ this._title = x;
+
+ if (x instanceof Node) {
+ this.titleElement.removeChildren();
+ this.titleElement.appendChild(x);
+ } else
+ this.titleElement.textContent = x;
+ },
+
+ get subtitle()
+ {
+ return this._subtitle;
+ },
+
+ set subtitle(x)
+ {
+ if (this._subtitle === x)
+ return;
+ this._subtitle = x;
+ this.subtitleElement.innerHTML = x;
+ },
+
+ get expanded()
+ {
+ return this._expanded;
+ },
+
+ set expanded(x)
+ {
+ if (x)
+ this.expand();
+ else
+ this.collapse();
+ },
+
+ get populated()
+ {
+ return this._populated;
+ },
+
+ set populated(x)
+ {
+ this._populated = x;
+ if (!x && this.onpopulate && this._expanded) {
+ this.onpopulate(this);
+ this._populated = true;
+ }
+ },
+
+ expand: function()
+ {
+ if (this._expanded)
+ return;
+ this._expanded = true;
+ this.element.addStyleClass("expanded");
+
+ if (!this._populated && this.onpopulate) {
+ this.onpopulate(this);
+ this._populated = true;
+ }
+ },
+
+ collapse: function()
+ {
+ if (!this._expanded)
+ return;
+ this._expanded = false;
+ this.element.removeStyleClass("expanded");
+ },
+
+ toggleExpanded: function()
+ {
+ this.expanded = !this.expanded;
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/PropertiesSidebarPane.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/PropertiesSidebarPane.js
new file mode 100644
index 0000000..70db805
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/PropertiesSidebarPane.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.PropertiesSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Properties"));
+}
+
+WebInspector.PropertiesSidebarPane.prototype = {
+ update: function(object)
+ {
+ var body = this.bodyElement;
+
+ body.removeChildren();
+
+ this.sections = [];
+
+ if (!object)
+ return;
+
+ for (var prototype = object; prototype; prototype = prototype.__proto__) {
+ var section = new WebInspector.ObjectPropertiesSection(prototype);
+ this.sections.push(section);
+ body.appendChild(section.element);
+ }
+ }
+}
+
+WebInspector.PropertiesSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Resource.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Resource.js
new file mode 100644
index 0000000..058f232
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Resource.js
@@ -0,0 +1,625 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Resource = function(requestHeaders, url, domain, path, lastPathComponent, identifier, mainResource, cached)
+{
+ this.identifier = identifier;
+
+ this.startTime = -1;
+ this.endTime = -1;
+ this.mainResource = mainResource;
+ this.requestHeaders = requestHeaders;
+ this.url = url;
+ this.domain = domain;
+ this.path = path;
+ this.lastPathComponent = lastPathComponent;
+ this.cached = cached;
+
+ this.category = WebInspector.resourceCategories.other;
+}
+
+// Keep these in sync with WebCore::InspectorResource::Type
+WebInspector.Resource.Type = {
+ Document: 0,
+ Stylesheet: 1,
+ Image: 2,
+ Font: 3,
+ Script: 4,
+ XHR: 5,
+ Other: 6,
+
+ isTextType: function(type)
+ {
+ return (type === this.Document) || (type === this.Stylesheet) || (type === this.Script) || (type === this.XHR);
+ },
+
+ toString: function(type)
+ {
+ switch (type) {
+ case this.Document:
+ return WebInspector.UIString("document");
+ case this.Stylesheet:
+ return WebInspector.UIString("stylesheet");
+ case this.Image:
+ return WebInspector.UIString("image");
+ case this.Font:
+ return WebInspector.UIString("font");
+ case this.Script:
+ return WebInspector.UIString("script");
+ case this.XHR:
+ return WebInspector.UIString("XHR");
+ case this.Other:
+ default:
+ return WebInspector.UIString("other");
+ }
+ }
+}
+
+WebInspector.Resource.prototype = {
+ get url()
+ {
+ return this._url;
+ },
+
+ set url(x)
+ {
+ if (this._url === x)
+ return;
+
+ var oldURL = this._url;
+ this._url = x;
+
+ // FIXME: We should make the WebInspector object listen for the "url changed" event.
+ // Then resourceURLChanged can be removed.
+ WebInspector.resourceURLChanged(this, oldURL);
+
+ this.dispatchEventToListeners("url changed");
+ },
+
+ get domain()
+ {
+ return this._domain;
+ },
+
+ set domain(x)
+ {
+ if (this._domain === x)
+ return;
+ this._domain = x;
+ },
+
+ get lastPathComponent()
+ {
+ return this._lastPathComponent;
+ },
+
+ set lastPathComponent(x)
+ {
+ if (this._lastPathComponent === x)
+ return;
+ this._lastPathComponent = x;
+ this._lastPathComponentLowerCase = x ? x.toLowerCase() : null;
+ },
+
+ get displayName()
+ {
+ var title = this.lastPathComponent;
+ if (!title)
+ title = this.displayDomain;
+ if (!title && this.url)
+ title = this.url.trimURL(WebInspector.mainResource ? WebInspector.mainResource.domain : "");
+ if (title === "/")
+ title = this.url;
+ return title;
+ },
+
+ get displayDomain()
+ {
+ // WebInspector.Database calls this, so don't access more than this.domain.
+ if (this.domain && (!WebInspector.mainResource || (WebInspector.mainResource && this.domain !== WebInspector.mainResource.domain)))
+ return this.domain;
+ return "";
+ },
+
+ get startTime()
+ {
+ return this._startTime || -1;
+ },
+
+ set startTime(x)
+ {
+ if (this._startTime === x)
+ return;
+
+ this._startTime = x;
+
+ if (WebInspector.panels.resources)
+ WebInspector.panels.resources.refreshResource(this);
+ },
+
+ get responseReceivedTime()
+ {
+ return this._responseReceivedTime || -1;
+ },
+
+ set responseReceivedTime(x)
+ {
+ if (this._responseReceivedTime === x)
+ return;
+
+ this._responseReceivedTime = x;
+
+ if (WebInspector.panels.resources)
+ WebInspector.panels.resources.refreshResource(this);
+ },
+
+ get endTime()
+ {
+ return this._endTime || -1;
+ },
+
+ set endTime(x)
+ {
+ if (this._endTime === x)
+ return;
+
+ this._endTime = x;
+
+ if (WebInspector.panels.resources)
+ WebInspector.panels.resources.refreshResource(this);
+ },
+
+ get duration()
+ {
+ if (this._endTime === -1 || this._startTime === -1)
+ return -1;
+ return this._endTime - this._startTime;
+ },
+
+ get latency()
+ {
+ if (this._responseReceivedTime === -1 || this._startTime === -1)
+ return -1;
+ return this._responseReceivedTime - this._startTime;
+ },
+
+ get contentLength()
+ {
+ return this._contentLength || 0;
+ },
+
+ set contentLength(x)
+ {
+ if (this._contentLength === x)
+ return;
+
+ this._contentLength = x;
+
+ if (WebInspector.panels.resources)
+ WebInspector.panels.resources.refreshResource(this);
+ },
+
+ get expectedContentLength()
+ {
+ return this._expectedContentLength || 0;
+ },
+
+ set expectedContentLength(x)
+ {
+ if (this._expectedContentLength === x)
+ return;
+ this._expectedContentLength = x;
+ },
+
+ get finished()
+ {
+ return this._finished;
+ },
+
+ set finished(x)
+ {
+ if (this._finished === x)
+ return;
+
+ this._finished = x;
+
+ if (x) {
+ this._checkTips();
+ this._checkWarnings();
+ this.dispatchEventToListeners("finished");
+ }
+ },
+
+ get failed()
+ {
+ return this._failed;
+ },
+
+ set failed(x)
+ {
+ this._failed = x;
+ },
+
+ get category()
+ {
+ return this._category;
+ },
+
+ set category(x)
+ {
+ if (this._category === x)
+ return;
+
+ var oldCategory = this._category;
+ if (oldCategory)
+ oldCategory.removeResource(this);
+
+ this._category = x;
+
+ if (this._category)
+ this._category.addResource(this);
+
+ if (WebInspector.panels.resources) {
+ WebInspector.panels.resources.refreshResource(this);
+ WebInspector.panels.resources.recreateViewForResourceIfNeeded(this);
+ }
+ },
+
+ get mimeType()
+ {
+ return this._mimeType;
+ },
+
+ set mimeType(x)
+ {
+ if (this._mimeType === x)
+ return;
+
+ this._mimeType = x;
+ },
+
+ get type()
+ {
+ return this._type;
+ },
+
+ set type(x)
+ {
+ if (this._type === x)
+ return;
+
+ this._type = x;
+
+ switch (x) {
+ case WebInspector.Resource.Type.Document:
+ this.category = WebInspector.resourceCategories.documents;
+ break;
+ case WebInspector.Resource.Type.Stylesheet:
+ this.category = WebInspector.resourceCategories.stylesheets;
+ break;
+ case WebInspector.Resource.Type.Script:
+ this.category = WebInspector.resourceCategories.scripts;
+ break;
+ case WebInspector.Resource.Type.Image:
+ this.category = WebInspector.resourceCategories.images;
+ break;
+ case WebInspector.Resource.Type.Font:
+ this.category = WebInspector.resourceCategories.fonts;
+ break;
+ case WebInspector.Resource.Type.XHR:
+ this.category = WebInspector.resourceCategories.xhr;
+ break;
+ case WebInspector.Resource.Type.Other:
+ default:
+ this.category = WebInspector.resourceCategories.other;
+ break;
+ }
+ },
+
+ get documentNode() {
+ if ("identifier" in this)
+ return InspectorController.getResourceDocumentNode(this.identifier);
+ return null;
+ },
+
+ get requestHeaders()
+ {
+ if (this._requestHeaders === undefined)
+ this._requestHeaders = {};
+ return this._requestHeaders;
+ },
+
+ set requestHeaders(x)
+ {
+ if (this._requestHeaders === x)
+ return;
+
+ this._requestHeaders = x;
+ delete this._sortedRequestHeaders;
+
+ this.dispatchEventToListeners("requestHeaders changed");
+ },
+
+ get sortedRequestHeaders()
+ {
+ if (this._sortedRequestHeaders !== undefined)
+ return this._sortedRequestHeaders;
+
+ this._sortedRequestHeaders = [];
+ for (var key in this.requestHeaders)
+ this._sortedRequestHeaders.push({header: key, value: this.requestHeaders[key]});
+ this._sortedRequestHeaders.sort(function(a,b) { return a.header.localeCompare(b.header) });
+
+ return this._sortedRequestHeaders;
+ },
+
+ get responseHeaders()
+ {
+ if (this._responseHeaders === undefined)
+ this._responseHeaders = {};
+ return this._responseHeaders;
+ },
+
+ set responseHeaders(x)
+ {
+ if (this._responseHeaders === x)
+ return;
+
+ this._responseHeaders = x;
+ delete this._sortedResponseHeaders;
+
+ this.dispatchEventToListeners("responseHeaders changed");
+ },
+
+ get sortedResponseHeaders()
+ {
+ if (this._sortedResponseHeaders !== undefined)
+ return this._sortedResponseHeaders;
+
+ this._sortedResponseHeaders = [];
+ for (var key in this.responseHeaders)
+ this._sortedResponseHeaders.push({header: key, value: this.responseHeaders[key]});
+ this._sortedResponseHeaders.sort(function(a,b) { return a.header.localeCompare(b.header) });
+
+ return this._sortedResponseHeaders;
+ },
+
+ get scripts()
+ {
+ if (!("_scripts" in this))
+ this._scripts = [];
+ return this._scripts;
+ },
+
+ addScript: function(script)
+ {
+ if (!script)
+ return;
+ this.scripts.unshift(script);
+ script.resource = this;
+ },
+
+ removeAllScripts: function()
+ {
+ if (!this._scripts)
+ return;
+
+ for (var i = 0; i < this._scripts.length; ++i) {
+ if (this._scripts[i].resource === this)
+ delete this._scripts[i].resource;
+ }
+
+ delete this._scripts;
+ },
+
+ removeScript: function(script)
+ {
+ if (!script)
+ return;
+
+ if (script.resource === this)
+ delete script.resource;
+
+ if (!this._scripts)
+ return;
+
+ this._scripts.remove(script);
+ },
+
+ get errors()
+ {
+ return this._errors || 0;
+ },
+
+ set errors(x)
+ {
+ this._errors = x;
+ },
+
+ get warnings()
+ {
+ return this._warnings || 0;
+ },
+
+ set warnings(x)
+ {
+ this._warnings = x;
+ },
+
+ get tips()
+ {
+ if (!("_tips" in this))
+ this._tips = {};
+ return this._tips;
+ },
+
+ _addTip: function(tip)
+ {
+ if (tip.id in this.tips)
+ return;
+
+ this.tips[tip.id] = tip;
+
+ // FIXME: Re-enable this code once we have a scope bar in the Console.
+ // Otherwise, we flood the Console with too many tips.
+ /*
+ var msg = new WebInspector.ConsoleMessage(WebInspector.ConsoleMessage.MessageSource.Other,
+ WebInspector.ConsoleMessage.MessageLevel.Tip, -1, this.url, null, 1, tip.message);
+ WebInspector.console.addMessage(msg);
+ */
+ },
+
+ _checkTips: function()
+ {
+ for (var tip in WebInspector.Tips)
+ this._checkTip(WebInspector.Tips[tip]);
+ },
+
+ _checkTip: function(tip)
+ {
+ var addTip = false;
+ switch (tip.id) {
+ case WebInspector.Tips.ResourceNotCompressed.id:
+ addTip = this._shouldCompress();
+ break;
+ }
+
+ if (addTip)
+ this._addTip(tip);
+ },
+
+ _shouldCompress: function()
+ {
+ return WebInspector.Resource.Type.isTextType(this.type)
+ && this.domain
+ && !("Content-Encoding" in this.responseHeaders)
+ && this.contentLength !== undefined
+ && this.contentLength >= 512;
+ },
+
+ _mimeTypeIsConsistentWithType: function()
+ {
+ if (typeof this.type === "undefined"
+ || this.type === WebInspector.Resource.Type.Other
+ || this.type === WebInspector.Resource.Type.XHR)
+ return true;
+
+ if (this.mimeType in WebInspector.MIMETypes)
+ return this.type in WebInspector.MIMETypes[this.mimeType];
+
+ return true;
+ },
+
+ _checkWarnings: function()
+ {
+ for (var warning in WebInspector.Warnings)
+ this._checkWarning(WebInspector.Warnings[warning]);
+ },
+
+ _checkWarning: function(warning)
+ {
+ var addWarning = false;
+ var msg;
+ switch (warning.id) {
+ case WebInspector.Warnings.IncorrectMIMEType.id:
+ if (!this._mimeTypeIsConsistentWithType())
+ msg = new WebInspector.ConsoleMessage(WebInspector.ConsoleMessage.MessageSource.Other,
+ WebInspector.ConsoleMessage.MessageLevel.Warning, -1, this.url, null, 1,
+ String.sprintf(WebInspector.Warnings.IncorrectMIMEType.message,
+ WebInspector.Resource.Type.toString(this.type), this.mimeType));
+ break;
+ }
+
+ if (msg)
+ WebInspector.console.addMessage(msg);
+ }
+}
+
+WebInspector.Resource.prototype.__proto__ = WebInspector.Object.prototype;
+
+WebInspector.Resource.CompareByStartTime = function(a, b)
+{
+ if (a.startTime < b.startTime)
+ return -1;
+ if (a.startTime > b.startTime)
+ return 1;
+ return 0;
+}
+
+WebInspector.Resource.CompareByResponseReceivedTime = function(a, b)
+{
+ if (a.responseReceivedTime === -1 && b.responseReceivedTime !== -1)
+ return 1;
+ if (a.responseReceivedTime !== -1 && b.responseReceivedTime === -1)
+ return -1;
+ if (a.responseReceivedTime < b.responseReceivedTime)
+ return -1;
+ if (a.responseReceivedTime > b.responseReceivedTime)
+ return 1;
+ return 0;
+}
+
+WebInspector.Resource.CompareByEndTime = function(a, b)
+{
+ if (a.endTime === -1 && b.endTime !== -1)
+ return 1;
+ if (a.endTime !== -1 && b.endTime === -1)
+ return -1;
+ if (a.endTime < b.endTime)
+ return -1;
+ if (a.endTime > b.endTime)
+ return 1;
+ return 0;
+}
+
+WebInspector.Resource.CompareByDuration = function(a, b)
+{
+ if (a.duration < b.duration)
+ return -1;
+ if (a.duration > b.duration)
+ return 1;
+ return 0;
+}
+
+WebInspector.Resource.CompareByLatency = function(a, b)
+{
+ if (a.latency < b.latency)
+ return -1;
+ if (a.latency > b.latency)
+ return 1;
+ return 0;
+}
+
+WebInspector.Resource.CompareBySize = function(a, b)
+{
+ if (a.contentLength < b.contentLength)
+ return -1;
+ if (a.contentLength > b.contentLength)
+ return 1;
+ return 0;
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ResourceCategory.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ResourceCategory.js
new file mode 100644
index 0000000..fc508d0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ResourceCategory.js
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ResourceCategory = function(title, name)
+{
+ this.name = name;
+ this.title = title;
+ this.resources = [];
+}
+
+WebInspector.ResourceCategory.prototype = {
+ toString: function()
+ {
+ return this.title;
+ },
+
+ addResource: function(resource)
+ {
+ var a = resource;
+ var resourcesLength = this.resources.length;
+ for (var i = 0; i < resourcesLength; ++i) {
+ var b = this.resources[i];
+ if (a._lastPathComponentLowerCase && b._lastPathComponentLowerCase)
+ if (a._lastPathComponentLowerCase < b._lastPathComponentLowerCase)
+ break;
+ else if (a.name && b.name)
+ if (a.name < b.name)
+ break;
+ }
+
+ this.resources.splice(i, 0, resource);
+ },
+
+ removeResource: function(resource)
+ {
+ this.resources.remove(resource, true);
+ },
+
+ removeAllResources: function(resource)
+ {
+ this.resources = [];
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ResourceView.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ResourceView.js
new file mode 100644
index 0000000..b480362
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ResourceView.js
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ResourceView = function(resource)
+{
+ WebInspector.View.call(this);
+
+ this.element.addStyleClass("resource-view");
+
+ this.resource = resource;
+
+ this.headersElement = document.createElement("div");
+ this.headersElement.className = "resource-view-headers";
+ this.element.appendChild(this.headersElement);
+
+ this.contentElement = document.createElement("div");
+ this.contentElement.className = "resource-view-content";
+ this.element.appendChild(this.contentElement);
+
+ this.headersListElement = document.createElement("ol");
+ this.headersListElement.className = "outline-disclosure";
+ this.headersElement.appendChild(this.headersListElement);
+
+ this.headersTreeOutline = new TreeOutline(this.headersListElement);
+ this.headersTreeOutline.expandTreeElementsWhenArrowing = true;
+
+ this.urlTreeElement = new TreeElement("", null, false);
+ this.urlTreeElement.selectable = false;
+ this.headersTreeOutline.appendChild(this.urlTreeElement);
+
+ this.requestHeadersTreeElement = new TreeElement("", null, true);
+ this.requestHeadersTreeElement.expanded = false;
+ this.requestHeadersTreeElement.selectable = false;
+ this.headersTreeOutline.appendChild(this.requestHeadersTreeElement);
+
+ this.responseHeadersTreeElement = new TreeElement("", null, true);
+ this.responseHeadersTreeElement.expanded = false;
+ this.responseHeadersTreeElement.selectable = false;
+ this.headersTreeOutline.appendChild(this.responseHeadersTreeElement);
+
+ this.headersVisible = true;
+
+ resource.addEventListener("url changed", this._refreshURL, this);
+ resource.addEventListener("requestHeaders changed", this._refreshRequestHeaders, this);
+ resource.addEventListener("responseHeaders changed", this._refreshResponseHeaders, this);
+
+ this._refreshURL();
+ this._refreshRequestHeaders();
+ this._refreshResponseHeaders();
+}
+
+WebInspector.ResourceView.prototype = {
+ get headersVisible()
+ {
+ return this._headersVisible;
+ },
+
+ set headersVisible(x)
+ {
+ if (x === this._headersVisible)
+ return;
+
+ this._headersVisible = x;
+
+ if (x)
+ this.element.addStyleClass("headers-visible");
+ else
+ this.element.removeStyleClass("headers-visible");
+ },
+
+ attach: function()
+ {
+ if (!this.element.parentNode) {
+ var parentElement = (document.getElementById("resource-views") || document.getElementById("script-resource-views"));
+ if (parentElement)
+ parentElement.appendChild(this.element);
+ }
+ },
+
+ _refreshURL: function()
+ {
+ this.urlTreeElement.title = this.resource.url.escapeHTML();
+ },
+
+ _refreshRequestHeaders: function()
+ {
+ this._refreshHeaders(WebInspector.UIString("Request Headers"), this.resource.sortedRequestHeaders, this.requestHeadersTreeElement);
+ },
+
+ _refreshResponseHeaders: function()
+ {
+ this._refreshHeaders(WebInspector.UIString("Response Headers"), this.resource.sortedResponseHeaders, this.responseHeadersTreeElement);
+ },
+
+ _refreshHeaders: function(title, headers, headersTreeElement)
+ {
+ headersTreeElement.removeChildren();
+
+ var length = headers.length;
+ headersTreeElement.title = title.escapeHTML() + "<span class=\"header-count\">" + WebInspector.UIString(" (%d)", length) + "</span>";
+ headersTreeElement.hidden = !length;
+
+ var length = headers.length;
+ for (var i = 0; i < length; ++i) {
+ var title = "<div class=\"header-name\">" + headers[i].header.escapeHTML() + ":</div>";
+ title += "<div class=\"header-value\">" + headers[i].value.escapeHTML() + "</div>"
+
+ var headerTreeElement = new TreeElement(title, null, false);
+ headerTreeElement.selectable = false;
+ headersTreeElement.appendChild(headerTreeElement);
+ }
+ }
+}
+
+WebInspector.ResourceView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ResourcesPanel.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ResourcesPanel.js
new file mode 100644
index 0000000..04d998e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ResourcesPanel.js
@@ -0,0 +1,1706 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Anthony Ricaud (rik24d@gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ResourcesPanel = function()
+{
+ WebInspector.Panel.call(this);
+
+ this.element.addStyleClass("resources");
+
+ this.viewsContainerElement = document.createElement("div");
+ this.viewsContainerElement.id = "resource-views";
+ this.element.appendChild(this.viewsContainerElement);
+
+ this.containerElement = document.createElement("div");
+ this.containerElement.id = "resources-container";
+ this.containerElement.addEventListener("scroll", this._updateDividersLabelBarPosition.bind(this), false);
+ this.element.appendChild(this.containerElement);
+
+ this.sidebarElement = document.createElement("div");
+ this.sidebarElement.id = "resources-sidebar";
+ this.sidebarElement.className = "sidebar";
+ this.containerElement.appendChild(this.sidebarElement);
+
+ this.sidebarResizeElement = document.createElement("div");
+ this.sidebarResizeElement.className = "sidebar-resizer-vertical";
+ this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarDragging.bind(this), false);
+ this.element.appendChild(this.sidebarResizeElement);
+
+ this.containerContentElement = document.createElement("div");
+ this.containerContentElement.id = "resources-container-content";
+ this.containerElement.appendChild(this.containerContentElement);
+
+ this.summaryElement = document.createElement("div");
+ this.summaryElement.id = "resources-summary";
+ this.containerContentElement.appendChild(this.summaryElement);
+
+ this.resourcesGraphsElement = document.createElement("div");
+ this.resourcesGraphsElement.id = "resources-graphs";
+ this.containerContentElement.appendChild(this.resourcesGraphsElement);
+
+ this.dividersElement = document.createElement("div");
+ this.dividersElement.id = "resources-dividers";
+ this.containerContentElement.appendChild(this.dividersElement);
+
+ this.dividersLabelBarElement = document.createElement("div");
+ this.dividersLabelBarElement.id = "resources-dividers-label-bar";
+ this.containerContentElement.appendChild(this.dividersLabelBarElement);
+
+ this.summaryGraphElement = document.createElement("canvas");
+ this.summaryGraphElement.setAttribute("width", "450");
+ this.summaryGraphElement.setAttribute("height", "38");
+ this.summaryGraphElement.id = "resources-summary-graph";
+ this.summaryElement.appendChild(this.summaryGraphElement);
+
+ this.legendElement = document.createElement("div");
+ this.legendElement.id = "resources-graph-legend";
+ this.summaryElement.appendChild(this.legendElement);
+
+ this.sidebarTreeElement = document.createElement("ol");
+ this.sidebarTreeElement.className = "sidebar-tree";
+ this.sidebarElement.appendChild(this.sidebarTreeElement);
+
+ this.sidebarTree = new TreeOutline(this.sidebarTreeElement);
+
+ var timeGraphItem = new WebInspector.SidebarTreeElement("resources-time-graph-sidebar-item", WebInspector.UIString("Time"));
+ timeGraphItem.onselect = this._graphSelected.bind(this);
+
+ var transferTimeCalculator = new WebInspector.ResourceTransferTimeCalculator();
+ var transferDurationCalculator = new WebInspector.ResourceTransferDurationCalculator();
+
+ timeGraphItem.sortingOptions = [
+ { name: WebInspector.UIString("Sort by Start Time"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByAscendingStartTime, calculator: transferTimeCalculator },
+ { name: WebInspector.UIString("Sort by Response Time"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByAscendingResponseReceivedTime, calculator: transferTimeCalculator },
+ { name: WebInspector.UIString("Sort by End Time"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByAscendingEndTime, calculator: transferTimeCalculator },
+ { name: WebInspector.UIString("Sort by Duration"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByDescendingDuration, calculator: transferDurationCalculator },
+ { name: WebInspector.UIString("Sort by Latency"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByDescendingLatency, calculator: transferDurationCalculator },
+ ];
+
+ timeGraphItem.selectedSortingOptionIndex = 1;
+
+ var sizeGraphItem = new WebInspector.SidebarTreeElement("resources-size-graph-sidebar-item", WebInspector.UIString("Size"));
+ sizeGraphItem.onselect = this._graphSelected.bind(this);
+
+ var transferSizeCalculator = new WebInspector.ResourceTransferSizeCalculator();
+ sizeGraphItem.sortingOptions = [
+ { name: WebInspector.UIString("Sort by Size"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByDescendingSize, calculator: transferSizeCalculator },
+ ];
+
+ sizeGraphItem.selectedSortingOptionIndex = 0;
+
+ this.graphsTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("GRAPHS"), {}, true);
+ this.sidebarTree.appendChild(this.graphsTreeElement);
+
+ this.graphsTreeElement.appendChild(timeGraphItem);
+ this.graphsTreeElement.appendChild(sizeGraphItem);
+ this.graphsTreeElement.expand();
+
+ this.resourcesTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("RESOURCES"), {}, true);
+ this.sidebarTree.appendChild(this.resourcesTreeElement);
+
+ this.resourcesTreeElement.expand();
+
+ var panelEnablerHeading = WebInspector.UIString("You need to enable resource tracking to use the this panel.");
+ var panelEnablerDisclaimer = WebInspector.UIString("Enabling resource tracking will reload the page and make page loading slower.");
+ var panelEnablerButton = WebInspector.UIString("Enable resource tracking");
+
+ this.panelEnablerView = new WebInspector.PanelEnablerView("resources", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
+ this.panelEnablerView.addEventListener("enable clicked", this._enableResourceTracking, this);
+
+ this.element.appendChild(this.panelEnablerView.element);
+
+ this.enableToggleButton = document.createElement("button");
+ this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item";
+ this.enableToggleButton.addEventListener("click", this._toggleResourceTracking.bind(this), false);
+
+ this.largerResourcesButton = document.createElement("button");
+ this.largerResourcesButton.id = "resources-larger-resources-status-bar-item";
+ this.largerResourcesButton.className = "status-bar-item toggled-on";
+ this.largerResourcesButton.title = WebInspector.UIString("Use small resource rows.");
+ this.largerResourcesButton.addEventListener("click", this._toggleLargerResources.bind(this), false);
+
+ this.sortingSelectElement = document.createElement("select");
+ this.sortingSelectElement.className = "status-bar-item";
+ this.sortingSelectElement.addEventListener("change", this._changeSortingFunction.bind(this), false);
+
+ this.reset();
+
+ timeGraphItem.select();
+}
+
+WebInspector.ResourcesPanel.prototype = {
+ toolbarItemClass: "resources",
+
+ get toolbarItemLabel()
+ {
+ return WebInspector.UIString("Resources");
+ },
+
+ get statusBarItems()
+ {
+ return [this.enableToggleButton, this.largerResourcesButton, this.sortingSelectElement];
+ },
+
+ show: function()
+ {
+ WebInspector.Panel.prototype.show.call(this);
+
+ this._updateDividersLabelBarPosition();
+ this._updateSidebarWidth();
+ this.refreshIfNeeded();
+
+ var visibleView = this.visibleView;
+ if (visibleView) {
+ visibleView.headersVisible = true;
+ visibleView.show(this.viewsContainerElement);
+ }
+
+ // Hide any views that are visible that are not this panel's current visible view.
+ // This can happen when a ResourceView is visible in the Scripts panel then switched
+ // to the this panel.
+ var resourcesLength = this._resources.length;
+ for (var i = 0; i < resourcesLength; ++i) {
+ var resource = this._resources[i];
+ var view = resource._resourcesView;
+ if (!view || view === visibleView)
+ continue;
+ view.visible = false;
+ }
+ },
+
+ resize: function()
+ {
+ this._updateGraphDividersIfNeeded();
+
+ var visibleView = this.visibleView;
+ if (visibleView && "resize" in visibleView)
+ visibleView.resize();
+ },
+
+ get searchableViews()
+ {
+ var views = [];
+
+ const visibleView = this.visibleView;
+ if (visibleView && visibleView.performSearch)
+ views.push(visibleView);
+
+ var resourcesLength = this._resources.length;
+ for (var i = 0; i < resourcesLength; ++i) {
+ var resource = this._resources[i];
+ if (!resource._resourcesTreeElement)
+ continue;
+ var resourceView = this.resourceViewForResource(resource);
+ if (!resourceView.performSearch || resourceView === visibleView)
+ continue;
+ views.push(resourceView);
+ }
+
+ return views;
+ },
+
+ get searchResultsSortFunction()
+ {
+ const resourceTreeElementSortFunction = this.sortingFunction;
+
+ function sortFuction(a, b)
+ {
+ return resourceTreeElementSortFunction(a.resource._resourcesTreeElement, b.resource._resourcesTreeElement);
+ }
+
+ return sortFuction;
+ },
+
+ searchMatchFound: function(view, matches)
+ {
+ view.resource._resourcesTreeElement.searchMatches = matches;
+ },
+
+ searchCanceled: function(startingNewSearch)
+ {
+ WebInspector.Panel.prototype.searchCanceled.call(this, startingNewSearch);
+
+ if (startingNewSearch || !this._resources)
+ return;
+
+ for (var i = 0; i < this._resources.length; ++i) {
+ var resource = this._resources[i];
+ if (resource._resourcesTreeElement)
+ resource._resourcesTreeElement.updateErrorsAndWarnings();
+ }
+ },
+
+ performSearch: function(query)
+ {
+ for (var i = 0; i < this._resources.length; ++i) {
+ var resource = this._resources[i];
+ if (resource._resourcesTreeElement)
+ resource._resourcesTreeElement.resetBubble();
+ }
+
+ WebInspector.Panel.prototype.performSearch.call(this, query);
+ },
+
+ get visibleView()
+ {
+ if (this.visibleResource)
+ return this.visibleResource._resourcesView;
+ return null;
+ },
+
+ get calculator()
+ {
+ return this._calculator;
+ },
+
+ set calculator(x)
+ {
+ if (!x || this._calculator === x)
+ return;
+
+ this._calculator = x;
+ this._calculator.reset();
+
+ this._staleResources = this._resources;
+ this.refresh();
+ },
+
+ get sortingFunction()
+ {
+ return this._sortingFunction;
+ },
+
+ set sortingFunction(x)
+ {
+ this._sortingFunction = x;
+ this._sortResourcesIfNeeded();
+ },
+
+ get needsRefresh()
+ {
+ return this._needsRefresh;
+ },
+
+ set needsRefresh(x)
+ {
+ if (this._needsRefresh === x)
+ return;
+
+ this._needsRefresh = x;
+
+ if (x) {
+ if (this.visible && !("_refreshTimeout" in this))
+ this._refreshTimeout = setTimeout(this.refresh.bind(this), 500);
+ } else {
+ if ("_refreshTimeout" in this) {
+ clearTimeout(this._refreshTimeout);
+ delete this._refreshTimeout;
+ }
+ }
+ },
+
+ refreshIfNeeded: function()
+ {
+ if (this.needsRefresh)
+ this.refresh();
+ },
+
+ refresh: function()
+ {
+ this.needsRefresh = false;
+
+ var staleResourcesLength = this._staleResources.length;
+ var boundariesChanged = false;
+
+ for (var i = 0; i < staleResourcesLength; ++i) {
+ var resource = this._staleResources[i];
+ if (!resource._resourcesTreeElement) {
+ // Create the resource tree element and graph.
+ resource._resourcesTreeElement = new WebInspector.ResourceSidebarTreeElement(resource);
+ resource._resourcesTreeElement._resourceGraph = new WebInspector.ResourceGraph(resource);
+
+ this.resourcesTreeElement.appendChild(resource._resourcesTreeElement);
+ this.resourcesGraphsElement.appendChild(resource._resourcesTreeElement._resourceGraph.graphElement);
+ }
+
+ resource._resourcesTreeElement.refresh();
+
+ if (this.calculator.updateBoundaries(resource))
+ boundariesChanged = true;
+ }
+
+ if (boundariesChanged) {
+ // The boundaries changed, so all resource graphs are stale.
+ this._staleResources = this._resources;
+ staleResourcesLength = this._staleResources.length;
+ }
+
+ for (var i = 0; i < staleResourcesLength; ++i)
+ this._staleResources[i]._resourcesTreeElement._resourceGraph.refresh(this.calculator);
+
+ this._staleResources = [];
+
+ this._updateGraphDividersIfNeeded();
+ this._sortResourcesIfNeeded();
+ this._updateSummaryGraph();
+ },
+
+ resourceTrackingWasEnabled: function()
+ {
+ this.reset();
+ },
+
+ resourceTrackingWasDisabled: function()
+ {
+ this.reset();
+ },
+
+ reset: function()
+ {
+ this.closeVisibleResource();
+
+ this.containerElement.scrollTop = 0;
+
+ delete this.currentQuery;
+ this.searchCanceled();
+
+ if (this._calculator)
+ this._calculator.reset();
+
+ if (this._resources) {
+ var resourcesLength = this._resources.length;
+ for (var i = 0; i < resourcesLength; ++i) {
+ var resource = this._resources[i];
+
+ resource.warnings = 0;
+ resource.errors = 0;
+
+ delete resource._resourcesTreeElement;
+ delete resource._resourcesView;
+ }
+ }
+
+ this._resources = [];
+ this._staleResources = [];
+
+ this.resourcesTreeElement.removeChildren();
+ this.viewsContainerElement.removeChildren();
+ this.resourcesGraphsElement.removeChildren();
+ this.legendElement.removeChildren();
+
+ this._updateGraphDividersIfNeeded(true);
+
+ this._drawSummaryGraph(); // draws an empty graph
+
+ if (InspectorController.resourceTrackingEnabled()) {
+ this.enableToggleButton.title = WebInspector.UIString("Resource tracking enabled. Click to disable.");
+ this.enableToggleButton.addStyleClass("toggled-on");
+ this.largerResourcesButton.removeStyleClass("hidden");
+ this.sortingSelectElement.removeStyleClass("hidden");
+ this.panelEnablerView.visible = false;
+ } else {
+ this.enableToggleButton.title = WebInspector.UIString("Resource tracking disabled. Click to enable.");
+ this.enableToggleButton.removeStyleClass("toggled-on");
+ this.largerResourcesButton.addStyleClass("hidden");
+ this.sortingSelectElement.addStyleClass("hidden");
+ this.panelEnablerView.visible = true;
+ }
+ },
+
+ addResource: function(resource)
+ {
+ this._resources.push(resource);
+ this.refreshResource(resource);
+ },
+
+ removeResource: function(resource)
+ {
+ if (this.visibleView === resource._resourcesView)
+ this.closeVisibleResource();
+
+ this._resources.remove(resource, true);
+
+ if (resource._resourcesTreeElement) {
+ this.resourcesTreeElement.removeChild(resource._resourcesTreeElement);
+ this.resourcesGraphsElement.removeChild(resource._resourcesTreeElement._resourceGraph.graphElement);
+ }
+
+ resource.warnings = 0;
+ resource.errors = 0;
+
+ delete resource._resourcesTreeElement;
+ delete resource._resourcesView;
+
+ this._adjustScrollPosition();
+ },
+
+ addMessageToResource: function(resource, msg)
+ {
+ if (!resource)
+ return;
+
+ switch (msg.level) {
+ case WebInspector.ConsoleMessage.MessageLevel.Warning:
+ resource.warnings += msg.repeatDelta;
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Error:
+ resource.errors += msg.repeatDelta;
+ break;
+ }
+
+ if (!this.currentQuery && resource._resourcesTreeElement)
+ resource._resourcesTreeElement.updateErrorsAndWarnings();
+
+ var view = this.resourceViewForResource(resource);
+ if (view.addMessage)
+ view.addMessage(msg);
+ },
+
+ clearMessages: function()
+ {
+ var resourcesLength = this._resources.length;
+ for (var i = 0; i < resourcesLength; ++i) {
+ var resource = this._resources[i];
+ resource.warnings = 0;
+ resource.errors = 0;
+
+ if (!this.currentQuery && resource._resourcesTreeElement)
+ resource._resourcesTreeElement.updateErrorsAndWarnings();
+
+ var view = resource._resourcesView;
+ if (!view || !view.clearMessages)
+ continue;
+ view.clearMessages();
+ }
+ },
+
+ refreshResource: function(resource)
+ {
+ this._staleResources.push(resource);
+ this.needsRefresh = true;
+ },
+
+ recreateViewForResourceIfNeeded: function(resource)
+ {
+ if (!resource || !resource._resourcesView)
+ return;
+
+ var newView = this._createResourceView(resource);
+ if (newView.prototype === resource._resourcesView.prototype)
+ return;
+
+ resource.warnings = 0;
+ resource.errors = 0;
+
+ if (!this.currentQuery && resource._resourcesTreeElement)
+ resource._resourcesTreeElement.updateErrorsAndWarnings();
+
+ var oldView = resource._resourcesView;
+
+ resource._resourcesView.detach();
+ delete resource._resourcesView;
+
+ resource._resourcesView = newView;
+
+ newView.headersVisible = oldView.headersVisible;
+
+ if (oldView.visible && oldView.element.parentNode)
+ newView.show(oldView.element.parentNode);
+ },
+
+ showResource: function(resource, line)
+ {
+ if (!resource)
+ return;
+
+ this.containerElement.addStyleClass("viewing-resource");
+
+ if (this.visibleResource && this.visibleResource._resourcesView)
+ this.visibleResource._resourcesView.hide();
+
+ var view = this.resourceViewForResource(resource);
+ view.headersVisible = true;
+ view.show(this.viewsContainerElement);
+
+ if (line) {
+ if (view.revealLine)
+ view.revealLine(line);
+ if (view.highlightLine)
+ view.highlightLine(line);
+ }
+
+ if (resource._resourcesTreeElement) {
+ resource._resourcesTreeElement.reveal();
+ resource._resourcesTreeElement.select(true);
+ }
+
+ this.visibleResource = resource;
+
+ this._updateSidebarWidth();
+ },
+
+ showView: function(view)
+ {
+ if (!view)
+ return;
+ this.showResource(view.resource);
+ },
+
+ closeVisibleResource: function()
+ {
+ this.containerElement.removeStyleClass("viewing-resource");
+ this._updateDividersLabelBarPosition();
+
+ if (this.visibleResource && this.visibleResource._resourcesView)
+ this.visibleResource._resourcesView.hide();
+ delete this.visibleResource;
+
+ if (this._lastSelectedGraphTreeElement)
+ this._lastSelectedGraphTreeElement.select(true);
+
+ this._updateSidebarWidth();
+ },
+
+ resourceViewForResource: function(resource)
+ {
+ if (!resource)
+ return null;
+ if (!resource._resourcesView)
+ resource._resourcesView = this._createResourceView(resource);
+ return resource._resourcesView;
+ },
+
+ sourceFrameForResource: function(resource)
+ {
+ var view = this.resourceViewForResource(resource);
+ if (!view)
+ return null;
+
+ if (!view.setupSourceFrameIfNeeded)
+ return null;
+
+ // Setting up the source frame requires that we be attached.
+ if (!this.element.parentNode)
+ this.attach();
+
+ view.setupSourceFrameIfNeeded();
+ return view.sourceFrame;
+ },
+
+ handleKeyEvent: function(event)
+ {
+ this.sidebarTree.handleKeyEvent(event);
+ },
+
+ _makeLegendElement: function(label, value, color)
+ {
+ var legendElement = document.createElement("label");
+ legendElement.className = "resources-graph-legend-item";
+
+ if (color) {
+ var swatch = document.createElement("canvas");
+ swatch.className = "resources-graph-legend-swatch";
+ swatch.setAttribute("width", "13");
+ swatch.setAttribute("height", "24");
+
+ legendElement.appendChild(swatch);
+
+ this._drawSwatch(swatch, color);
+ }
+
+ var labelElement = document.createElement("div");
+ labelElement.className = "resources-graph-legend-label";
+ legendElement.appendChild(labelElement);
+
+ var headerElement = document.createElement("div");
+ var headerElement = document.createElement("div");
+ headerElement.className = "resources-graph-legend-header";
+ headerElement.textContent = label;
+ labelElement.appendChild(headerElement);
+
+ var valueElement = document.createElement("div");
+ valueElement.className = "resources-graph-legend-value";
+ valueElement.textContent = value;
+ labelElement.appendChild(valueElement);
+
+ return legendElement;
+ },
+
+ _sortResourcesIfNeeded: function()
+ {
+ var sortedElements = [].concat(this.resourcesTreeElement.children);
+ sortedElements.sort(this.sortingFunction);
+
+ var sortedElementsLength = sortedElements.length;
+ for (var i = 0; i < sortedElementsLength; ++i) {
+ var treeElement = sortedElements[i];
+ if (treeElement === this.resourcesTreeElement.children[i])
+ continue;
+
+ var wasSelected = treeElement.selected;
+ this.resourcesTreeElement.removeChild(treeElement);
+ this.resourcesTreeElement.insertChild(treeElement, i);
+ if (wasSelected)
+ treeElement.select(true);
+
+ var graphElement = treeElement._resourceGraph.graphElement;
+ this.resourcesGraphsElement.insertBefore(graphElement, this.resourcesGraphsElement.children[i]);
+ }
+ },
+
+ _updateGraphDividersIfNeeded: function(force)
+ {
+ if (!this.visible) {
+ this.needsRefresh = true;
+ return;
+ }
+
+ if (document.body.offsetWidth <= 0) {
+ // The stylesheet hasn't loaded yet or the window is closed,
+ // so we can't calculate what is need. Return early.
+ return;
+ }
+
+ var dividerCount = Math.round(this.dividersElement.offsetWidth / 64);
+ var slice = this.calculator.boundarySpan / dividerCount;
+ if (!force && this._currentDividerSlice === slice)
+ return;
+
+ this._currentDividerSlice = slice;
+
+ this.dividersElement.removeChildren();
+ this.dividersLabelBarElement.removeChildren();
+
+ for (var i = 1; i <= dividerCount; ++i) {
+ var divider = document.createElement("div");
+ divider.className = "resources-divider";
+ if (i === dividerCount)
+ divider.addStyleClass("last");
+ divider.style.left = ((i / dividerCount) * 100) + "%";
+
+ this.dividersElement.appendChild(divider.cloneNode());
+
+ var label = document.createElement("div");
+ label.className = "resources-divider-label";
+ if (!isNaN(slice))
+ label.textContent = this.calculator.formatValue(slice * i);
+ divider.appendChild(label);
+
+ this.dividersLabelBarElement.appendChild(divider);
+ }
+ },
+
+ _fadeOutRect: function(ctx, x, y, w, h, a1, a2)
+ {
+ ctx.save();
+
+ var gradient = ctx.createLinearGradient(x, y, x, y + h);
+ gradient.addColorStop(0.0, "rgba(0, 0, 0, " + (1.0 - a1) + ")");
+ gradient.addColorStop(0.8, "rgba(0, 0, 0, " + (1.0 - a2) + ")");
+ gradient.addColorStop(1.0, "rgba(0, 0, 0, 1.0)");
+
+ ctx.globalCompositeOperation = "destination-out";
+
+ ctx.fillStyle = gradient;
+ ctx.fillRect(x, y, w, h);
+
+ ctx.restore();
+ },
+
+ _drawSwatch: function(canvas, color)
+ {
+ var ctx = canvas.getContext("2d");
+
+ function drawSwatchSquare() {
+ ctx.fillStyle = color;
+ ctx.fillRect(0, 0, 13, 13);
+
+ var gradient = ctx.createLinearGradient(0, 0, 13, 13);
+ gradient.addColorStop(0.0, "rgba(255, 255, 255, 0.2)");
+ gradient.addColorStop(1.0, "rgba(255, 255, 255, 0.0)");
+
+ ctx.fillStyle = gradient;
+ ctx.fillRect(0, 0, 13, 13);
+
+ gradient = ctx.createLinearGradient(13, 13, 0, 0);
+ gradient.addColorStop(0.0, "rgba(0, 0, 0, 0.2)");
+ gradient.addColorStop(1.0, "rgba(0, 0, 0, 0.0)");
+
+ ctx.fillStyle = gradient;
+ ctx.fillRect(0, 0, 13, 13);
+
+ ctx.strokeStyle = "rgba(0, 0, 0, 0.6)";
+ ctx.strokeRect(0.5, 0.5, 12, 12);
+ }
+
+ ctx.clearRect(0, 0, 13, 24);
+
+ drawSwatchSquare();
+
+ ctx.save();
+
+ ctx.translate(0, 25);
+ ctx.scale(1, -1);
+
+ drawSwatchSquare();
+
+ ctx.restore();
+
+ this._fadeOutRect(ctx, 0, 13, 13, 13, 0.5, 0.0);
+ },
+
+ _drawSummaryGraph: function(segments)
+ {
+ if (!this.summaryGraphElement)
+ return;
+
+ if (!segments || !segments.length) {
+ segments = [{color: "white", value: 1}];
+ this._showingEmptySummaryGraph = true;
+ } else
+ delete this._showingEmptySummaryGraph;
+
+ // Calculate the total of all segments.
+ var total = 0;
+ for (var i = 0; i < segments.length; ++i)
+ total += segments[i].value;
+
+ // Calculate the percentage of each segment, rounded to the nearest percent.
+ var percents = segments.map(function(s) { return Math.max(Math.round(100 * s.value / total), 1) });
+
+ // Calculate the total percentage.
+ var percentTotal = 0;
+ for (var i = 0; i < percents.length; ++i)
+ percentTotal += percents[i];
+
+ // Make sure our percentage total is not greater-than 100, it can be greater
+ // if we rounded up for a few segments.
+ while (percentTotal > 100) {
+ for (var i = 0; i < percents.length && percentTotal > 100; ++i) {
+ if (percents[i] > 1) {
+ --percents[i];
+ --percentTotal;
+ }
+ }
+ }
+
+ // Make sure our percentage total is not less-than 100, it can be less
+ // if we rounded down for a few segments.
+ while (percentTotal < 100) {
+ for (var i = 0; i < percents.length && percentTotal < 100; ++i) {
+ ++percents[i];
+ ++percentTotal;
+ }
+ }
+
+ var ctx = this.summaryGraphElement.getContext("2d");
+
+ var x = 0;
+ var y = 0;
+ var w = 450;
+ var h = 19;
+ var r = (h / 2);
+
+ function drawPillShadow()
+ {
+ // This draws a line with a shadow that is offset away from the line. The line is stroked
+ // twice with different X shadow offsets to give more feathered edges. Later we erase the
+ // line with destination-out 100% transparent black, leaving only the shadow. This only
+ // works if nothing has been drawn into the canvas yet.
+
+ ctx.beginPath();
+ ctx.moveTo(x + 4, y + h - 3 - 0.5);
+ ctx.lineTo(x + w - 4, y + h - 3 - 0.5);
+ ctx.closePath();
+
+ ctx.save();
+
+ ctx.shadowBlur = 2;
+ ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
+ ctx.shadowOffsetX = 3;
+ ctx.shadowOffsetY = 5;
+
+ ctx.strokeStyle = "white";
+ ctx.lineWidth = 1;
+
+ ctx.stroke();
+
+ ctx.shadowOffsetX = -3;
+
+ ctx.stroke();
+
+ ctx.restore();
+
+ ctx.save();
+
+ ctx.globalCompositeOperation = "destination-out";
+ ctx.strokeStyle = "rgba(0, 0, 0, 1)";
+ ctx.lineWidth = 1;
+
+ ctx.stroke();
+
+ ctx.restore();
+ }
+
+ function drawPill()
+ {
+ // Make a rounded rect path.
+ ctx.beginPath();
+ ctx.moveTo(x, y + r);
+ ctx.lineTo(x, y + h - r);
+ ctx.quadraticCurveTo(x, y + h, x + r, y + h);
+ ctx.lineTo(x + w - r, y + h);
+ ctx.quadraticCurveTo(x + w, y + h, x + w, y + h - r);
+ ctx.lineTo(x + w, y + r);
+ ctx.quadraticCurveTo(x + w, y, x + w - r, y);
+ ctx.lineTo(x + r, y);
+ ctx.quadraticCurveTo(x, y, x, y + r);
+ ctx.closePath();
+
+ // Clip to the rounded rect path.
+ ctx.save();
+ ctx.clip();
+
+ // Fill the segments with the associated color.
+ var previousSegmentsWidth = 0;
+ for (var i = 0; i < segments.length; ++i) {
+ var segmentWidth = Math.round(w * percents[i] / 100);
+ ctx.fillStyle = segments[i].color;
+ ctx.fillRect(x + previousSegmentsWidth, y, segmentWidth, h);
+ previousSegmentsWidth += segmentWidth;
+ }
+
+ // Draw the segment divider lines.
+ ctx.lineWidth = 1;
+ for (var i = 1; i < 20; ++i) {
+ ctx.beginPath();
+ ctx.moveTo(x + (i * Math.round(w / 20)) + 0.5, y);
+ ctx.lineTo(x + (i * Math.round(w / 20)) + 0.5, y + h);
+ ctx.closePath();
+
+ ctx.strokeStyle = "rgba(0, 0, 0, 0.2)";
+ ctx.stroke();
+
+ ctx.beginPath();
+ ctx.moveTo(x + (i * Math.round(w / 20)) + 1.5, y);
+ ctx.lineTo(x + (i * Math.round(w / 20)) + 1.5, y + h);
+ ctx.closePath();
+
+ ctx.strokeStyle = "rgba(255, 255, 255, 0.2)";
+ ctx.stroke();
+ }
+
+ // Draw the pill shading.
+ var lightGradient = ctx.createLinearGradient(x, y, x, y + (h / 1.5));
+ lightGradient.addColorStop(0.0, "rgba(220, 220, 220, 0.6)");
+ lightGradient.addColorStop(0.4, "rgba(220, 220, 220, 0.2)");
+ lightGradient.addColorStop(1.0, "rgba(255, 255, 255, 0.0)");
+
+ var darkGradient = ctx.createLinearGradient(x, y + (h / 3), x, y + h);
+ darkGradient.addColorStop(0.0, "rgba(0, 0, 0, 0.0)");
+ darkGradient.addColorStop(0.8, "rgba(0, 0, 0, 0.2)");
+ darkGradient.addColorStop(1.0, "rgba(0, 0, 0, 0.5)");
+
+ ctx.fillStyle = darkGradient;
+ ctx.fillRect(x, y, w, h);
+
+ ctx.fillStyle = lightGradient;
+ ctx.fillRect(x, y, w, h);
+
+ ctx.restore();
+ }
+
+ ctx.clearRect(x, y, w, (h * 2));
+
+ drawPillShadow();
+ drawPill();
+
+ ctx.save();
+
+ ctx.translate(0, (h * 2) + 1);
+ ctx.scale(1, -1);
+
+ drawPill();
+
+ ctx.restore();
+
+ this._fadeOutRect(ctx, x, y + h + 1, w, h, 0.5, 0.0);
+ },
+
+ _updateSummaryGraph: function()
+ {
+ var graphInfo = this.calculator.computeSummaryValues(this._resources);
+
+ var categoryOrder = ["documents", "stylesheets", "images", "scripts", "xhr", "fonts", "other"];
+ var categoryColors = {documents: {r: 47, g: 102, b: 236}, stylesheets: {r: 157, g: 231, b: 119}, images: {r: 164, g: 60, b: 255}, scripts: {r: 255, g: 121, b: 0}, xhr: {r: 231, g: 231, b: 10}, fonts: {r: 255, g: 82, b: 62}, other: {r: 186, g: 186, b: 186}};
+ var fillSegments = [];
+
+ this.legendElement.removeChildren();
+
+ for (var i = 0; i < categoryOrder.length; ++i) {
+ var category = categoryOrder[i];
+ var size = graphInfo.categoryValues[category];
+ if (!size)
+ continue;
+
+ var color = categoryColors[category];
+ var colorString = "rgb(" + color.r + ", " + color.g + ", " + color.b + ")";
+
+ var fillSegment = {color: colorString, value: size};
+ fillSegments.push(fillSegment);
+
+ var legendLabel = this._makeLegendElement(WebInspector.resourceCategories[category].title, this.calculator.formatValue(size), colorString);
+ this.legendElement.appendChild(legendLabel);
+ }
+
+ if (graphInfo.total) {
+ var totalLegendLabel = this._makeLegendElement(WebInspector.UIString("Total"), this.calculator.formatValue(graphInfo.total));
+ totalLegendLabel.addStyleClass("total");
+ this.legendElement.appendChild(totalLegendLabel);
+ }
+
+ this._drawSummaryGraph(fillSegments);
+ },
+
+ _updateDividersLabelBarPosition: function()
+ {
+ var scrollTop = this.containerElement.scrollTop;
+ var dividersTop = (scrollTop < this.summaryElement.offsetHeight ? this.summaryElement.offsetHeight : scrollTop);
+ this.dividersElement.style.top = scrollTop + "px";
+ this.dividersLabelBarElement.style.top = dividersTop + "px";
+ },
+
+ _graphSelected: function(treeElement)
+ {
+ if (this._lastSelectedGraphTreeElement)
+ this._lastSelectedGraphTreeElement.selectedSortingOptionIndex = this.sortingSelectElement.selectedIndex;
+
+ this._lastSelectedGraphTreeElement = treeElement;
+
+ this.sortingSelectElement.removeChildren();
+ for (var i = 0; i < treeElement.sortingOptions.length; ++i) {
+ var sortingOption = treeElement.sortingOptions[i];
+ var option = document.createElement("option");
+ option.label = sortingOption.name;
+ option.sortingFunction = sortingOption.sortingFunction;
+ option.calculator = sortingOption.calculator;
+ this.sortingSelectElement.appendChild(option);
+ }
+
+ this.sortingSelectElement.selectedIndex = treeElement.selectedSortingOptionIndex;
+ this._changeSortingFunction();
+
+ this.closeVisibleResource();
+ this.containerElement.scrollTop = 0;
+ },
+
+ _toggleLargerResources: function()
+ {
+ if (!this.resourcesTreeElement._childrenListNode)
+ return;
+
+ this.resourcesTreeElement.smallChildren = !this.resourcesTreeElement.smallChildren;
+
+ if (this.resourcesTreeElement.smallChildren) {
+ this.resourcesGraphsElement.addStyleClass("small");
+ this.largerResourcesButton.title = WebInspector.UIString("Use large resource rows.");
+ this.largerResourcesButton.removeStyleClass("toggled-on");
+ this._adjustScrollPosition();
+ } else {
+ this.resourcesGraphsElement.removeStyleClass("small");
+ this.largerResourcesButton.title = WebInspector.UIString("Use small resource rows.");
+ this.largerResourcesButton.addStyleClass("toggled-on");
+ }
+ },
+
+ _adjustScrollPosition: function()
+ {
+ // Prevent the container from being scrolled off the end.
+ if ((this.containerElement.scrollTop + this.containerElement.offsetHeight) > this.sidebarElement.offsetHeight)
+ this.containerElement.scrollTop = (this.sidebarElement.offsetHeight - this.containerElement.offsetHeight);
+ },
+
+ _changeSortingFunction: function()
+ {
+ var selectedOption = this.sortingSelectElement[this.sortingSelectElement.selectedIndex];
+ this.sortingFunction = selectedOption.sortingFunction;
+ this.calculator = selectedOption.calculator;
+ },
+
+ _createResourceView: function(resource)
+ {
+ switch (resource.category) {
+ case WebInspector.resourceCategories.documents:
+ case WebInspector.resourceCategories.stylesheets:
+ case WebInspector.resourceCategories.scripts:
+ case WebInspector.resourceCategories.xhr:
+ return new WebInspector.SourceView(resource);
+ case WebInspector.resourceCategories.images:
+ return new WebInspector.ImageView(resource);
+ case WebInspector.resourceCategories.fonts:
+ return new WebInspector.FontView(resource);
+ default:
+ return new WebInspector.ResourceView(resource);
+ }
+ },
+
+ _startSidebarDragging: function(event)
+ {
+ WebInspector.elementDragStart(this.sidebarResizeElement, this._sidebarDragging.bind(this), this._endSidebarDragging.bind(this), event, "col-resize");
+ },
+
+ _sidebarDragging: function(event)
+ {
+ this._updateSidebarWidth(event.pageX);
+
+ event.preventDefault();
+ },
+
+ _endSidebarDragging: function(event)
+ {
+ WebInspector.elementDragEnd(event);
+ },
+
+ _updateSidebarWidth: function(width)
+ {
+ if (this.sidebarElement.offsetWidth <= 0) {
+ // The stylesheet hasn't loaded yet or the window is closed,
+ // so we can't calculate what is need. Return early.
+ return;
+ }
+
+ if (!("_currentSidebarWidth" in this))
+ this._currentSidebarWidth = this.sidebarElement.offsetWidth;
+
+ if (typeof width === "undefined")
+ width = this._currentSidebarWidth;
+
+ width = Number.constrain(width, Preferences.minSidebarWidth, window.innerWidth / 2);
+
+ this._currentSidebarWidth = width;
+
+ if (this.visibleResource) {
+ this.containerElement.style.width = width + "px";
+ this.sidebarElement.style.removeProperty("width");
+ } else {
+ this.sidebarElement.style.width = width + "px";
+ this.containerElement.style.removeProperty("width");
+ }
+
+ this.containerContentElement.style.left = width + "px";
+ this.viewsContainerElement.style.left = width + "px";
+ this.sidebarResizeElement.style.left = (width - 3) + "px";
+
+ this._updateGraphDividersIfNeeded();
+
+ var visibleView = this.visibleView;
+ if (visibleView && "resize" in visibleView)
+ visibleView.resize();
+ },
+
+ _enableResourceTracking: function()
+ {
+ if (InspectorController.resourceTrackingEnabled())
+ return;
+ this._toggleResourceTracking(this.panelEnablerView.alwaysEnabled);
+ },
+
+ _toggleResourceTracking: function(optionalAlways)
+ {
+ if (InspectorController.resourceTrackingEnabled()) {
+ this.largerResourcesButton.visible = false;
+ this.sortingSelectElement.visible = false;
+ InspectorController.disableResourceTracking(true);
+ } else {
+ this.largerResourcesButton.visible = true;
+ this.sortingSelectElement.visible = true;
+ InspectorController.enableResourceTracking(!!optionalAlways);
+ }
+ }
+}
+
+WebInspector.ResourcesPanel.prototype.__proto__ = WebInspector.Panel.prototype;
+
+WebInspector.ResourceCalculator = function()
+{
+}
+
+WebInspector.ResourceCalculator.prototype = {
+ computeSummaryValues: function(resources)
+ {
+ var total = 0;
+ var categoryValues = {};
+
+ var resourcesLength = resources.length;
+ for (var i = 0; i < resourcesLength; ++i) {
+ var resource = resources[i];
+ var value = this._value(resource);
+ if (typeof value === "undefined")
+ continue;
+ if (!(resource.category.name in categoryValues))
+ categoryValues[resource.category.name] = 0;
+ categoryValues[resource.category.name] += value;
+ total += value;
+ }
+
+ return {categoryValues: categoryValues, total: total};
+ },
+
+ computeBarGraphPercentages: function(resource)
+ {
+ return {start: 0, middle: 0, end: (this._value(resource) / this.boundarySpan) * 100};
+ },
+
+ computeBarGraphLabels: function(resource)
+ {
+ const label = this.formatValue(this._value(resource));
+ var tooltip = label;
+ if (resource.cached)
+ tooltip = WebInspector.UIString("%s (from cache)", tooltip);
+ return {left: label, right: label, tooltip: tooltip};
+ },
+
+ get boundarySpan()
+ {
+ return this.maximumBoundary - this.minimumBoundary;
+ },
+
+ updateBoundaries: function(resource)
+ {
+ this.minimumBoundary = 0;
+
+ var value = this._value(resource);
+ if (typeof this.maximumBoundary === "undefined" || value > this.maximumBoundary) {
+ this.maximumBoundary = value;
+ return true;
+ }
+
+ return false;
+ },
+
+ reset: function()
+ {
+ delete this.minimumBoundary;
+ delete this.maximumBoundary;
+ },
+
+ _value: function(resource)
+ {
+ return 0;
+ },
+
+ formatValue: function(value)
+ {
+ return value.toString();
+ }
+}
+
+WebInspector.ResourceTimeCalculator = function(startAtZero)
+{
+ WebInspector.ResourceCalculator.call(this);
+ this.startAtZero = startAtZero;
+}
+
+WebInspector.ResourceTimeCalculator.prototype = {
+ computeSummaryValues: function(resources)
+ {
+ var resourcesByCategory = {};
+ var resourcesLength = resources.length;
+ for (var i = 0; i < resourcesLength; ++i) {
+ var resource = resources[i];
+ if (!(resource.category.name in resourcesByCategory))
+ resourcesByCategory[resource.category.name] = [];
+ resourcesByCategory[resource.category.name].push(resource);
+ }
+
+ var earliestStart;
+ var latestEnd;
+ var categoryValues = {};
+ for (var category in resourcesByCategory) {
+ resourcesByCategory[category].sort(WebInspector.Resource.CompareByTime);
+ categoryValues[category] = 0;
+
+ var segment = {start: -1, end: -1};
+
+ var categoryResources = resourcesByCategory[category];
+ var resourcesLength = categoryResources.length;
+ for (var i = 0; i < resourcesLength; ++i) {
+ var resource = categoryResources[i];
+ if (resource.startTime === -1 || resource.endTime === -1)
+ continue;
+
+ if (typeof earliestStart === "undefined")
+ earliestStart = resource.startTime;
+ else
+ earliestStart = Math.min(earliestStart, resource.startTime);
+
+ if (typeof latestEnd === "undefined")
+ latestEnd = resource.endTime;
+ else
+ latestEnd = Math.max(latestEnd, resource.endTime);
+
+ if (resource.startTime <= segment.end) {
+ segment.end = Math.max(segment.end, resource.endTime);
+ continue;
+ }
+
+ categoryValues[category] += segment.end - segment.start;
+
+ segment.start = resource.startTime;
+ segment.end = resource.endTime;
+ }
+
+ // Add the last segment
+ categoryValues[category] += segment.end - segment.start;
+ }
+
+ return {categoryValues: categoryValues, total: latestEnd - earliestStart};
+ },
+
+ computeBarGraphPercentages: function(resource)
+ {
+ if (resource.startTime !== -1)
+ var start = ((resource.startTime - this.minimumBoundary) / this.boundarySpan) * 100;
+ else
+ var start = 0;
+
+ if (resource.responseReceivedTime !== -1)
+ var middle = ((resource.responseReceivedTime - this.minimumBoundary) / this.boundarySpan) * 100;
+ else
+ var middle = (this.startAtZero ? start : 100);
+
+ if (resource.endTime !== -1)
+ var end = ((resource.endTime - this.minimumBoundary) / this.boundarySpan) * 100;
+ else
+ var end = (this.startAtZero ? middle : 100);
+
+ if (this.startAtZero) {
+ end -= start;
+ middle -= start;
+ start = 0;
+ }
+
+ return {start: start, middle: middle, end: end};
+ },
+
+ computeBarGraphLabels: function(resource)
+ {
+ var leftLabel = "";
+ if (resource.latency > 0)
+ leftLabel = this.formatValue(resource.latency);
+
+ var rightLabel = "";
+ if (resource.responseReceivedTime !== -1 && resource.endTime !== -1)
+ rightLabel = this.formatValue(resource.endTime - resource.responseReceivedTime);
+
+ if (leftLabel && rightLabel) {
+ var total = this.formatValue(resource.duration);
+ var tooltip = WebInspector.UIString("%s latency, %s download (%s total)", leftLabel, rightLabel, total);
+ } else if (leftLabel)
+ var tooltip = WebInspector.UIString("%s latency", leftLabel);
+ else if (rightLabel)
+ var tooltip = WebInspector.UIString("%s download", rightLabel);
+
+ if (resource.cached)
+ tooltip = WebInspector.UIString("%s (from cache)", tooltip);
+
+ return {left: leftLabel, right: rightLabel, tooltip: tooltip};
+ },
+
+ updateBoundaries: function(resource)
+ {
+ var didChange = false;
+
+ var lowerBound;
+ if (this.startAtZero)
+ lowerBound = 0;
+ else
+ lowerBound = this._lowerBound(resource);
+
+ if (lowerBound !== -1 && (typeof this.minimumBoundary === "undefined" || lowerBound < this.minimumBoundary)) {
+ this.minimumBoundary = lowerBound;
+ didChange = true;
+ }
+
+ var upperBound = this._upperBound(resource);
+ if (upperBound !== -1 && (typeof this.maximumBoundary === "undefined" || upperBound > this.maximumBoundary)) {
+ this.maximumBoundary = upperBound;
+ didChange = true;
+ }
+
+ return didChange;
+ },
+
+ formatValue: function(value)
+ {
+ return Number.secondsToString(value, WebInspector.UIString.bind(WebInspector));
+ },
+
+ _lowerBound: function(resource)
+ {
+ return 0;
+ },
+
+ _upperBound: function(resource)
+ {
+ return 0;
+ },
+}
+
+WebInspector.ResourceTimeCalculator.prototype.__proto__ = WebInspector.ResourceCalculator.prototype;
+
+WebInspector.ResourceTransferTimeCalculator = function()
+{
+ WebInspector.ResourceTimeCalculator.call(this, false);
+}
+
+WebInspector.ResourceTransferTimeCalculator.prototype = {
+ formatValue: function(value)
+ {
+ return Number.secondsToString(value, WebInspector.UIString.bind(WebInspector));
+ },
+
+ _lowerBound: function(resource)
+ {
+ return resource.startTime;
+ },
+
+ _upperBound: function(resource)
+ {
+ return resource.endTime;
+ }
+}
+
+WebInspector.ResourceTransferTimeCalculator.prototype.__proto__ = WebInspector.ResourceTimeCalculator.prototype;
+
+WebInspector.ResourceTransferDurationCalculator = function()
+{
+ WebInspector.ResourceTimeCalculator.call(this, true);
+}
+
+WebInspector.ResourceTransferDurationCalculator.prototype = {
+ formatValue: function(value)
+ {
+ return Number.secondsToString(value, WebInspector.UIString.bind(WebInspector));
+ },
+
+ _upperBound: function(resource)
+ {
+ return resource.duration;
+ }
+}
+
+WebInspector.ResourceTransferDurationCalculator.prototype.__proto__ = WebInspector.ResourceTimeCalculator.prototype;
+
+WebInspector.ResourceTransferSizeCalculator = function()
+{
+ WebInspector.ResourceCalculator.call(this);
+}
+
+WebInspector.ResourceTransferSizeCalculator.prototype = {
+ _value: function(resource)
+ {
+ return resource.contentLength;
+ },
+
+ formatValue: function(value)
+ {
+ return Number.bytesToString(value, WebInspector.UIString.bind(WebInspector));
+ }
+}
+
+WebInspector.ResourceTransferSizeCalculator.prototype.__proto__ = WebInspector.ResourceCalculator.prototype;
+
+WebInspector.ResourceSidebarTreeElement = function(resource)
+{
+ this.resource = resource;
+
+ this.createIconElement();
+
+ WebInspector.SidebarTreeElement.call(this, "resource-sidebar-tree-item", "", "", resource);
+
+ this.refreshTitles();
+}
+
+WebInspector.ResourceSidebarTreeElement.prototype = {
+ onattach: function()
+ {
+ WebInspector.SidebarTreeElement.prototype.onattach.call(this);
+
+ this._listItemNode.addStyleClass("resources-category-" + this.resource.category.name);
+ },
+
+ onselect: function()
+ {
+ WebInspector.panels.resources.showResource(this.resource);
+ },
+
+ get mainTitle()
+ {
+ return this.resource.displayName;
+ },
+
+ set mainTitle(x)
+ {
+ // Do nothing.
+ },
+
+ get subtitle()
+ {
+ var subtitle = this.resource.displayDomain;
+
+ if (this.resource.path && this.resource.lastPathComponent) {
+ var lastPathComponentIndex = this.resource.path.lastIndexOf("/" + this.resource.lastPathComponent);
+ if (lastPathComponentIndex != -1)
+ subtitle += this.resource.path.substring(0, lastPathComponentIndex);
+ }
+
+ return subtitle;
+ },
+
+ set subtitle(x)
+ {
+ // Do nothing.
+ },
+
+ createIconElement: function()
+ {
+ var previousIconElement = this.iconElement;
+
+ if (this.resource.category === WebInspector.resourceCategories.images) {
+ var previewImage = document.createElement("img");
+ previewImage.className = "image-resource-icon-preview";
+ previewImage.src = this.resource.url;
+
+ this.iconElement = document.createElement("div");
+ this.iconElement.className = "icon";
+ this.iconElement.appendChild(previewImage);
+ } else {
+ this.iconElement = document.createElement("img");
+ this.iconElement.className = "icon";
+ }
+
+ if (previousIconElement)
+ previousIconElement.parentNode.replaceChild(this.iconElement, previousIconElement);
+ },
+
+ refresh: function()
+ {
+ this.refreshTitles();
+
+ if (!this._listItemNode.hasStyleClass("resources-category-" + this.resource.category.name)) {
+ this._listItemNode.removeMatchingStyleClasses("resources-category-\\w+");
+ this._listItemNode.addStyleClass("resources-category-" + this.resource.category.name);
+
+ this.createIconElement();
+ }
+ },
+
+ resetBubble: function()
+ {
+ this.bubbleText = "";
+ this.bubbleElement.removeStyleClass("search-matches");
+ this.bubbleElement.removeStyleClass("warning");
+ this.bubbleElement.removeStyleClass("error");
+ },
+
+ set searchMatches(matches)
+ {
+ this.resetBubble();
+
+ if (!matches)
+ return;
+
+ this.bubbleText = matches;
+ this.bubbleElement.addStyleClass("search-matches");
+ },
+
+ updateErrorsAndWarnings: function()
+ {
+ this.resetBubble();
+
+ if (this.resource.warnings || this.resource.errors)
+ this.bubbleText = (this.resource.warnings + this.resource.errors);
+
+ if (this.resource.warnings)
+ this.bubbleElement.addStyleClass("warning");
+
+ if (this.resource.errors)
+ this.bubbleElement.addStyleClass("error");
+ }
+}
+
+WebInspector.ResourceSidebarTreeElement.CompareByAscendingStartTime = function(a, b)
+{
+ return WebInspector.Resource.CompareByStartTime(a.resource, b.resource)
+ || WebInspector.Resource.CompareByEndTime(a.resource, b.resource)
+ || WebInspector.Resource.CompareByResponseReceivedTime(a.resource, b.resource);
+}
+
+WebInspector.ResourceSidebarTreeElement.CompareByAscendingResponseReceivedTime = function(a, b)
+{
+ return WebInspector.Resource.CompareByResponseReceivedTime(a.resource, b.resource)
+ || WebInspector.Resource.CompareByStartTime(a.resource, b.resource)
+ || WebInspector.Resource.CompareByEndTime(a.resource, b.resource);
+}
+
+WebInspector.ResourceSidebarTreeElement.CompareByAscendingEndTime = function(a, b)
+{
+ return WebInspector.Resource.CompareByEndTime(a.resource, b.resource)
+ || WebInspector.Resource.CompareByStartTime(a.resource, b.resource)
+ || WebInspector.Resource.CompareByResponseReceivedTime(a.resource, b.resource);
+}
+
+WebInspector.ResourceSidebarTreeElement.CompareByDescendingDuration = function(a, b)
+{
+ return -1 * WebInspector.Resource.CompareByDuration(a.resource, b.resource);
+}
+
+WebInspector.ResourceSidebarTreeElement.CompareByDescendingLatency = function(a, b)
+{
+ return -1 * WebInspector.Resource.CompareByLatency(a.resource, b.resource);
+}
+
+WebInspector.ResourceSidebarTreeElement.CompareByDescendingSize = function(a, b)
+{
+ return -1 * WebInspector.Resource.CompareBySize(a.resource, b.resource);
+}
+
+WebInspector.ResourceSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
+
+WebInspector.ResourceGraph = function(resource)
+{
+ this.resource = resource;
+
+ this._graphElement = document.createElement("div");
+ this._graphElement.className = "resources-graph-side";
+ this._graphElement.addEventListener("mouseover", this.refreshLabelPositions.bind(this), false);
+
+ if (resource.cached)
+ this._graphElement.addStyleClass("resource-cached");
+
+ this._barAreaElement = document.createElement("div");
+ this._barAreaElement.className = "resources-graph-bar-area hidden";
+ this._graphElement.appendChild(this._barAreaElement);
+
+ this._barLeftElement = document.createElement("div");
+ this._barLeftElement.className = "resources-graph-bar waiting";
+ this._barAreaElement.appendChild(this._barLeftElement);
+
+ this._barRightElement = document.createElement("div");
+ this._barRightElement.className = "resources-graph-bar";
+ this._barAreaElement.appendChild(this._barRightElement);
+
+ this._labelLeftElement = document.createElement("div");
+ this._labelLeftElement.className = "resources-graph-label waiting";
+ this._barAreaElement.appendChild(this._labelLeftElement);
+
+ this._labelRightElement = document.createElement("div");
+ this._labelRightElement.className = "resources-graph-label";
+ this._barAreaElement.appendChild(this._labelRightElement);
+
+ this._graphElement.addStyleClass("resources-category-" + resource.category.name);
+}
+
+WebInspector.ResourceGraph.prototype = {
+ get graphElement()
+ {
+ return this._graphElement;
+ },
+
+ refreshLabelPositions: function()
+ {
+ this._labelLeftElement.style.removeProperty("left");
+ this._labelLeftElement.style.removeProperty("right");
+ this._labelLeftElement.removeStyleClass("before");
+ this._labelLeftElement.removeStyleClass("hidden");
+
+ this._labelRightElement.style.removeProperty("left");
+ this._labelRightElement.style.removeProperty("right");
+ this._labelRightElement.removeStyleClass("after");
+ this._labelRightElement.removeStyleClass("hidden");
+
+ const labelPadding = 10;
+ const rightBarWidth = (this._barRightElement.offsetWidth - labelPadding);
+ const leftBarWidth = ((this._barLeftElement.offsetWidth - this._barRightElement.offsetWidth) - labelPadding);
+
+ var labelBefore = (this._labelLeftElement.offsetWidth > leftBarWidth);
+ var labelAfter = (this._labelRightElement.offsetWidth > rightBarWidth);
+
+ if (labelBefore) {
+ if ((this._graphElement.offsetWidth * (this._percentages.start / 100)) < (this._labelLeftElement.offsetWidth + 10))
+ this._labelLeftElement.addStyleClass("hidden");
+ this._labelLeftElement.style.setProperty("right", (100 - this._percentages.start) + "%");
+ this._labelLeftElement.addStyleClass("before");
+ } else {
+ this._labelLeftElement.style.setProperty("left", this._percentages.start + "%");
+ this._labelLeftElement.style.setProperty("right", (100 - this._percentages.middle) + "%");
+ }
+
+ if (labelAfter) {
+ if ((this._graphElement.offsetWidth * ((100 - this._percentages.end) / 100)) < (this._labelRightElement.offsetWidth + 10))
+ this._labelRightElement.addStyleClass("hidden");
+ this._labelRightElement.style.setProperty("left", this._percentages.end + "%");
+ this._labelRightElement.addStyleClass("after");
+ } else {
+ this._labelRightElement.style.setProperty("left", this._percentages.middle + "%");
+ this._labelRightElement.style.setProperty("right", (100 - this._percentages.end) + "%");
+ }
+ },
+
+ refresh: function(calculator)
+ {
+ var percentages = calculator.computeBarGraphPercentages(this.resource);
+ var labels = calculator.computeBarGraphLabels(this.resource);
+
+ this._percentages = percentages;
+
+ this._barAreaElement.removeStyleClass("hidden");
+
+ if (!this._graphElement.hasStyleClass("resources-category-" + this.resource.category.name)) {
+ this._graphElement.removeMatchingStyleClasses("resources-category-\\w+");
+ this._graphElement.addStyleClass("resources-category-" + this.resource.category.name);
+ }
+
+ this._barLeftElement.style.setProperty("left", percentages.start + "%");
+ this._barLeftElement.style.setProperty("right", (100 - percentages.end) + "%");
+
+ this._barRightElement.style.setProperty("left", percentages.middle + "%");
+ this._barRightElement.style.setProperty("right", (100 - percentages.end) + "%");
+
+ this._labelLeftElement.textContent = labels.left;
+ this._labelRightElement.textContent = labels.right;
+
+ var tooltip = (labels.tooltip || "");
+ this._barLeftElement.title = tooltip;
+ this._labelLeftElement.title = tooltip;
+ this._labelRightElement.title = tooltip;
+ this._barRightElement.title = tooltip;
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ScopeChainSidebarPane.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ScopeChainSidebarPane.js
new file mode 100644
index 0000000..157cee9
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ScopeChainSidebarPane.js
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ScopeChainSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Scope Variables"));
+}
+
+WebInspector.ScopeChainSidebarPane.prototype = {
+ update: function(callFrame)
+ {
+ this.bodyElement.removeChildren();
+
+ this.sections = [];
+ this.callFrame = callFrame;
+
+ if (!callFrame) {
+ var infoElement = document.createElement("div");
+ infoElement.className = "info";
+ infoElement.textContent = WebInspector.UIString("Not Paused");
+ this.bodyElement.appendChild(infoElement);
+ return;
+ }
+
+ if (!callFrame._expandedProperties) {
+ // FIXME: fix this when https://bugs.webkit.org/show_bug.cgi?id=19410 is fixed.
+ // The callFrame is a JSInspectedObjectWrapper, so we are not allowed to assign
+ // an object created in the Inspector's context to that object. So create an
+ // Object from the inspectedWindow.
+ var inspectedWindow = InspectorController.inspectedWindow();
+ callFrame._expandedProperties = new inspectedWindow.Object;
+ }
+
+ var foundLocalScope = false;
+ var scopeChain = callFrame.scopeChain;
+ for (var i = 0; i < scopeChain.length; ++i) {
+ var scopeObject = scopeChain[i];
+ var title = null;
+ var subtitle = Object.describe(scopeObject, true);
+ var emptyPlaceholder = null;
+ var localScope = false;
+ var extraProperties = null;
+
+ if (Object.prototype.toString.call(scopeObject) === "[object JSActivation]") {
+ if (!foundLocalScope) {
+ extraProperties = { "this": callFrame.thisObject };
+ title = WebInspector.UIString("Local");
+ } else
+ title = WebInspector.UIString("Closure");
+ emptyPlaceholder = WebInspector.UIString("No Variables");
+ subtitle = null;
+ foundLocalScope = true;
+ localScope = true;
+ } else if (i === (scopeChain.length - 1))
+ title = WebInspector.UIString("Global");
+ else if (foundLocalScope && scopeObject instanceof InspectorController.inspectedWindow().Element)
+ title = WebInspector.UIString("Event Target");
+ else if (foundLocalScope && scopeObject instanceof InspectorController.inspectedWindow().Document)
+ title = WebInspector.UIString("Event Document");
+ else if (!foundLocalScope && !localScope)
+ title = WebInspector.UIString("With Block");
+
+ if (!title || title === subtitle)
+ subtitle = null;
+
+ var section = new WebInspector.ObjectPropertiesSection(scopeObject, title, subtitle, emptyPlaceholder, true, extraProperties, WebInspector.ScopeVariableTreeElement);
+ section.editInSelectedCallFrameWhenPaused = true;
+ section.pane = this;
+
+ if (!foundLocalScope || localScope)
+ section.expanded = true;
+
+ this.sections.push(section);
+ this.bodyElement.appendChild(section.element);
+ }
+ }
+}
+
+WebInspector.ScopeChainSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
+
+WebInspector.ScopeVariableTreeElement = function(parentObject, propertyName)
+{
+ WebInspector.ObjectPropertyTreeElement.call(this, parentObject, propertyName);
+}
+
+WebInspector.ScopeVariableTreeElement.prototype = {
+ onattach: function()
+ {
+ WebInspector.ObjectPropertyTreeElement.prototype.onattach.call(this);
+ if (this.hasChildren && this.propertyIdentifier in this.treeOutline.section.pane.callFrame._expandedProperties)
+ this.expand();
+ },
+
+ onexpand: function()
+ {
+ this.treeOutline.section.pane.callFrame._expandedProperties[this.propertyIdentifier] = true;
+ },
+
+ oncollapse: function()
+ {
+ delete this.treeOutline.section.pane.callFrame._expandedProperties[this.propertyIdentifier];
+ },
+
+ get propertyIdentifier()
+ {
+ if ("_propertyIdentifier" in this)
+ return this._propertyIdentifier;
+ var section = this.treeOutline.section;
+ this._propertyIdentifier = section.title + ":" + (section.subtitle ? section.subtitle + ":" : "") + this.propertyPath;
+ return this._propertyIdentifier;
+ },
+
+ get propertyPath()
+ {
+ if ("_propertyPath" in this)
+ return this._propertyPath;
+
+ var current = this;
+ var result;
+
+ do {
+ if (result)
+ result = current.propertyName + "." + result;
+ else
+ result = current.propertyName;
+ current = current.parent;
+ } while (current && !current.root);
+
+ this._propertyPath = result;
+ return result;
+ }
+}
+
+WebInspector.ScopeVariableTreeElement.prototype.__proto__ = WebInspector.ObjectPropertyTreeElement.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Script.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Script.js
new file mode 100644
index 0000000..46502a6
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/Script.js
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Script = function(sourceID, sourceURL, source, startingLine, errorLine, errorMessage)
+{
+ this.sourceID = sourceID;
+ this.sourceURL = sourceURL;
+ this.source = source;
+ this.startingLine = startingLine;
+ this.errorLine = errorLine;
+ this.errorMessage = errorMessage;
+}
+
+WebInspector.Script.prototype = {
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ScriptView.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ScriptView.js
new file mode 100644
index 0000000..124190c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ScriptView.js
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ScriptView = function(script)
+{
+ WebInspector.View.call(this);
+
+ this.element.addStyleClass("script-view");
+
+ this.script = script;
+
+ this._frameNeedsSetup = true;
+ this._sourceFrameSetup = false;
+
+ this.sourceFrame = new WebInspector.SourceFrame(null, this._addBreakpoint.bind(this));
+
+ this.element.appendChild(this.sourceFrame.element);
+}
+
+WebInspector.ScriptView.prototype = {
+ show: function(parentElement)
+ {
+ WebInspector.View.prototype.show.call(this, parentElement);
+ this.setupSourceFrameIfNeeded();
+ },
+
+ hide: function()
+ {
+ WebInspector.View.prototype.hide.call(this);
+ this._currentSearchResultIndex = -1;
+ },
+
+ setupSourceFrameIfNeeded: function()
+ {
+ if (!this._frameNeedsSetup)
+ return;
+
+ this.attach();
+
+ if (!InspectorController.addSourceToFrame("text/javascript", this.script.source, this.sourceFrame.element))
+ return;
+
+ delete this._frameNeedsSetup;
+
+ this.sourceFrame.addEventListener("syntax highlighting complete", this._syntaxHighlightingComplete, this);
+ this.sourceFrame.syntaxHighlightJavascript();
+ },
+
+ attach: function()
+ {
+ if (!this.element.parentNode)
+ document.getElementById("script-resource-views").appendChild(this.element);
+ },
+
+ _addBreakpoint: function(line)
+ {
+ var breakpoint = new WebInspector.Breakpoint(this.script.sourceURL, line, this.script.sourceID);
+ WebInspector.panels.scripts.addBreakpoint(breakpoint);
+ },
+
+ // The follow methods are pulled from SourceView, since they are
+ // generic and work with ScriptView just fine.
+
+ revealLine: WebInspector.SourceView.prototype.revealLine,
+ highlightLine: WebInspector.SourceView.prototype.highlightLine,
+ addMessage: WebInspector.SourceView.prototype.addMessage,
+ clearMessages: WebInspector.SourceView.prototype.clearMessages,
+ searchCanceled: WebInspector.SourceView.prototype.searchCanceled,
+ performSearch: WebInspector.SourceView.prototype.performSearch,
+ jumpToFirstSearchResult: WebInspector.SourceView.prototype.jumpToFirstSearchResult,
+ jumpToLastSearchResult: WebInspector.SourceView.prototype.jumpToLastSearchResult,
+ jumpToNextSearchResult: WebInspector.SourceView.prototype.jumpToNextSearchResult,
+ jumpToPreviousSearchResult: WebInspector.SourceView.prototype.jumpToPreviousSearchResult,
+ showingFirstSearchResult: WebInspector.SourceView.prototype.showingFirstSearchResult,
+ showingLastSearchResult: WebInspector.SourceView.prototype.showingLastSearchResult,
+ _jumpToSearchResult: WebInspector.SourceView.prototype._jumpToSearchResult,
+ _sourceFrameSetupFinished: WebInspector.SourceView.prototype._sourceFrameSetupFinished,
+ _syntaxHighlightingComplete: WebInspector.SourceView.prototype._syntaxHighlightingComplete
+}
+
+WebInspector.ScriptView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ScriptsPanel.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ScriptsPanel.js
new file mode 100644
index 0000000..7af9292
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/ScriptsPanel.js
@@ -0,0 +1,854 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ScriptsPanel = function()
+{
+ WebInspector.Panel.call(this);
+
+ this.element.addStyleClass("scripts");
+
+ this.topStatusBar = document.createElement("div");
+ this.topStatusBar.className = "status-bar";
+ this.topStatusBar.id = "scripts-status-bar";
+ this.element.appendChild(this.topStatusBar);
+
+ this.backButton = document.createElement("button");
+ this.backButton.className = "status-bar-item";
+ this.backButton.id = "scripts-back";
+ this.backButton.title = WebInspector.UIString("Show the previous script resource.");
+ this.backButton.disabled = true;
+ this.backButton.appendChild(document.createElement("img"));
+ this.backButton.addEventListener("click", this._goBack.bind(this), false);
+ this.topStatusBar.appendChild(this.backButton);
+
+ this.forwardButton = document.createElement("button");
+ this.forwardButton.className = "status-bar-item";
+ this.forwardButton.id = "scripts-forward";
+ this.forwardButton.title = WebInspector.UIString("Show the next script resource.");
+ this.forwardButton.disabled = true;
+ this.forwardButton.appendChild(document.createElement("img"));
+ this.forwardButton.addEventListener("click", this._goForward.bind(this), false);
+ this.topStatusBar.appendChild(this.forwardButton);
+
+ this.filesSelectElement = document.createElement("select");
+ this.filesSelectElement.className = "status-bar-item";
+ this.filesSelectElement.id = "scripts-files";
+ this.filesSelectElement.addEventListener("change", this._changeVisibleFile.bind(this), false);
+ this.topStatusBar.appendChild(this.filesSelectElement);
+
+ this.functionsSelectElement = document.createElement("select");
+ this.functionsSelectElement.className = "status-bar-item";
+ this.functionsSelectElement.id = "scripts-functions";
+
+ // FIXME: append the functions select element to the top status bar when it is implemented.
+ // this.topStatusBar.appendChild(this.functionsSelectElement);
+
+ this.sidebarButtonsElement = document.createElement("div");
+ this.sidebarButtonsElement.id = "scripts-sidebar-buttons";
+ this.topStatusBar.appendChild(this.sidebarButtonsElement);
+
+ this.pauseButton = document.createElement("button");
+ this.pauseButton.className = "status-bar-item";
+ this.pauseButton.id = "scripts-pause";
+ this.pauseButton.title = WebInspector.UIString("Pause script execution.");
+ this.pauseButton.disabled = true;
+ this.pauseButton.appendChild(document.createElement("img"));
+ this.pauseButton.addEventListener("click", this._togglePause.bind(this), false);
+ this.sidebarButtonsElement.appendChild(this.pauseButton);
+
+ this.stepOverButton = document.createElement("button");
+ this.stepOverButton.className = "status-bar-item";
+ this.stepOverButton.id = "scripts-step-over";
+ this.stepOverButton.title = WebInspector.UIString("Step over next function call.");
+ this.stepOverButton.disabled = true;
+ this.stepOverButton.addEventListener("click", this._stepOverClicked.bind(this), false);
+ this.stepOverButton.appendChild(document.createElement("img"));
+ this.sidebarButtonsElement.appendChild(this.stepOverButton);
+
+ this.stepIntoButton = document.createElement("button");
+ this.stepIntoButton.className = "status-bar-item";
+ this.stepIntoButton.id = "scripts-step-into";
+ this.stepIntoButton.title = WebInspector.UIString("Step into next function call.");
+ this.stepIntoButton.disabled = true;
+ this.stepIntoButton.addEventListener("click", this._stepIntoClicked.bind(this), false);
+ this.stepIntoButton.appendChild(document.createElement("img"));
+ this.sidebarButtonsElement.appendChild(this.stepIntoButton);
+
+ this.stepOutButton = document.createElement("button");
+ this.stepOutButton.className = "status-bar-item";
+ this.stepOutButton.id = "scripts-step-out";
+ this.stepOutButton.title = WebInspector.UIString("Step out of current function.");
+ this.stepOutButton.disabled = true;
+ this.stepOutButton.addEventListener("click", this._stepOutClicked.bind(this), false);
+ this.stepOutButton.appendChild(document.createElement("img"));
+ this.sidebarButtonsElement.appendChild(this.stepOutButton);
+
+ this.debuggerStatusElement = document.createElement("div");
+ this.debuggerStatusElement.id = "scripts-debugger-status";
+ this.sidebarButtonsElement.appendChild(this.debuggerStatusElement);
+
+ this.viewsContainerElement = document.createElement("div");
+ this.viewsContainerElement.id = "script-resource-views";
+
+ this.sidebarElement = document.createElement("div");
+ this.sidebarElement.id = "scripts-sidebar";
+
+ this.sidebarResizeElement = document.createElement("div");
+ this.sidebarResizeElement.className = "sidebar-resizer-vertical";
+ this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
+
+ this.sidebarResizeWidgetElement = document.createElement("div");
+ this.sidebarResizeWidgetElement.id = "scripts-sidebar-resizer-widget";
+ this.sidebarResizeWidgetElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
+ this.topStatusBar.appendChild(this.sidebarResizeWidgetElement);
+
+ this.sidebarPanes = {};
+ this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
+ this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
+ this.sidebarPanes.breakpoints = new WebInspector.BreakpointsSidebarPane();
+
+ for (var pane in this.sidebarPanes)
+ this.sidebarElement.appendChild(this.sidebarPanes[pane].element);
+
+ // FIXME: remove the following line of code when the Breakpoints pane has content.
+ this.sidebarElement.removeChild(this.sidebarPanes.breakpoints.element);
+
+ this.sidebarPanes.callstack.expanded = true;
+ this.sidebarPanes.callstack.addEventListener("call frame selected", this._callFrameSelected, this);
+
+ this.sidebarPanes.scopechain.expanded = true;
+
+ var panelEnablerHeading = WebInspector.UIString("You need to enable debugging before you can use the Scripts panel.");
+ var panelEnablerDisclaimer = WebInspector.UIString("Enabling debugging will make scripts run slower.");
+ var panelEnablerButton = WebInspector.UIString("Enable Debugging");
+
+ this.panelEnablerView = new WebInspector.PanelEnablerView("scripts", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
+ this.panelEnablerView.addEventListener("enable clicked", this._enableDebugging, this);
+
+ this.element.appendChild(this.panelEnablerView.element);
+ this.element.appendChild(this.viewsContainerElement);
+ this.element.appendChild(this.sidebarElement);
+ this.element.appendChild(this.sidebarResizeElement);
+
+ this.enableToggleButton = document.createElement("button");
+ this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item";
+ this.enableToggleButton.addEventListener("click", this._toggleDebugging.bind(this), false);
+
+ this.pauseOnExceptionButton = document.createElement("button");
+ this.pauseOnExceptionButton.id = "scripts-pause-on-exceptions-status-bar-item";
+ this.pauseOnExceptionButton.className = "status-bar-item";
+ this.pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions.bind(this), false);
+
+ this._breakpointsURLMap = {};
+
+ this.reset();
+}
+
+WebInspector.ScriptsPanel.prototype = {
+ toolbarItemClass: "scripts",
+
+ get toolbarItemLabel()
+ {
+ return WebInspector.UIString("Scripts");
+ },
+
+ get statusBarItems()
+ {
+ return [this.enableToggleButton, this.pauseOnExceptionButton];
+ },
+
+ get paused()
+ {
+ return this._paused;
+ },
+
+ show: function()
+ {
+ WebInspector.Panel.prototype.show.call(this);
+ this.sidebarResizeElement.style.right = (this.sidebarElement.offsetWidth - 3) + "px";
+
+ if (this.visibleView) {
+ if (this.visibleView instanceof WebInspector.ResourceView)
+ this.visibleView.headersVisible = false;
+ this.visibleView.show(this.viewsContainerElement);
+ }
+
+ // Hide any views that are visible that are not this panel's current visible view.
+ // This can happen when a ResourceView is visible in the Resources panel then switched
+ // to the this panel.
+ for (var sourceID in this._sourceIDMap) {
+ var scriptOrResource = this._sourceIDMap[sourceID];
+ var view = this._sourceViewForScriptOrResource(scriptOrResource);
+ if (!view || view === this.visibleView)
+ continue;
+ view.visible = false;
+ }
+ if (this._attachDebuggerWhenShown) {
+ InspectorController.enableDebuggerFromFrontend(false);
+ delete this._attachDebuggerWhenShown;
+ }
+ },
+
+ get searchableViews()
+ {
+ var views = [];
+
+ const visibleView = this.visibleView;
+ if (visibleView && visibleView.performSearch) {
+ visibleView.alreadySearching = true;
+ views.push(visibleView);
+ }
+
+ for (var sourceID in this._sourceIDMap) {
+ var scriptOrResource = this._sourceIDMap[sourceID];
+ var view = this._sourceViewForScriptOrResource(scriptOrResource);
+ if (!view || !view.performSearch || view.alreadySearching)
+ continue;
+
+ view.alreadySearching = true;
+ views.push(view);
+ }
+
+ for (var i = 0; i < views.length; ++i)
+ delete views[i].alreadySearching;
+
+ return views;
+ },
+
+ addScript: function(sourceID, sourceURL, source, startingLine, errorLine, errorMessage)
+ {
+ var script = new WebInspector.Script(sourceID, sourceURL, source, startingLine, errorLine, errorMessage);
+
+ if (sourceURL in WebInspector.resourceURLMap) {
+ var resource = WebInspector.resourceURLMap[sourceURL];
+ resource.addScript(script);
+ }
+
+ if (sourceURL in this._breakpointsURLMap && sourceID) {
+ var breakpoints = this._breakpointsURLMap[sourceURL];
+ var breakpointsLength = breakpoints.length;
+ for (var i = 0; i < breakpointsLength; ++i) {
+ var breakpoint = breakpoints[i];
+ if (startingLine <= breakpoint.line) {
+ breakpoint.sourceID = sourceID;
+ if (breakpoint.enabled)
+ InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line);
+ }
+ }
+ }
+
+ if (sourceID)
+ this._sourceIDMap[sourceID] = (resource || script);
+
+ this._addScriptToFilesMenu(script);
+ },
+
+ addBreakpoint: function(breakpoint)
+ {
+ this.sidebarPanes.breakpoints.addBreakpoint(breakpoint);
+
+ var sourceFrame;
+ if (breakpoint.url) {
+ if (!(breakpoint.url in this._breakpointsURLMap))
+ this._breakpointsURLMap[breakpoint.url] = [];
+ this._breakpointsURLMap[breakpoint.url].unshift(breakpoint);
+
+ if (breakpoint.url in WebInspector.resourceURLMap) {
+ var resource = WebInspector.resourceURLMap[breakpoint.url];
+ sourceFrame = this._sourceFrameForScriptOrResource(resource);
+ }
+ }
+
+ if (breakpoint.sourceID && !sourceFrame) {
+ var object = this._sourceIDMap[breakpoint.sourceID]
+ sourceFrame = this._sourceFrameForScriptOrResource(object);
+ }
+
+ if (sourceFrame)
+ sourceFrame.addBreakpoint(breakpoint);
+ },
+
+ removeBreakpoint: function(breakpoint)
+ {
+ this.sidebarPanes.breakpoints.removeBreakpoint(breakpoint);
+
+ var sourceFrame;
+ if (breakpoint.url && breakpoint.url in this._breakpointsURLMap) {
+ var breakpoints = this._breakpointsURLMap[breakpoint.url];
+ breakpoints.remove(breakpoint);
+ if (!breakpoints.length)
+ delete this._breakpointsURLMap[breakpoint.url];
+
+ if (breakpoint.url in WebInspector.resourceURLMap) {
+ var resource = WebInspector.resourceURLMap[breakpoint.url];
+ sourceFrame = this._sourceFrameForScriptOrResource(resource);
+ }
+ }
+
+ if (breakpoint.sourceID && !sourceFrame) {
+ var object = this._sourceIDMap[breakpoint.sourceID]
+ sourceFrame = this._sourceFrameForScriptOrResource(object);
+ }
+
+ if (sourceFrame)
+ sourceFrame.removeBreakpoint(breakpoint);
+ },
+
+ evaluateInSelectedCallFrame: function(code, updateInterface)
+ {
+ var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
+ if (!this._paused || !selectedCallFrame)
+ return;
+ if (typeof updateInterface === "undefined")
+ updateInterface = true;
+ var result = selectedCallFrame.evaluate(code);
+ if (updateInterface)
+ this.sidebarPanes.scopechain.update(selectedCallFrame);
+ return result;
+ },
+
+ variablesInScopeForSelectedCallFrame: function()
+ {
+ var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
+ if (!this._paused || !selectedCallFrame)
+ return {};
+
+ var result = {};
+ var scopeChain = selectedCallFrame.scopeChain;
+ for (var i = 0; i < scopeChain.length; ++i) {
+ var scopeObject = scopeChain[i];
+ for (var property in scopeObject)
+ result[property] = true;
+ }
+
+ return result;
+ },
+
+ debuggerPaused: function()
+ {
+ this._paused = true;
+ this._waitingToPause = false;
+ this._stepping = false;
+
+ this._updateDebuggerButtons();
+
+ var callStackPane = this.sidebarPanes.callstack;
+ var currentFrame = InspectorController.currentCallFrame();
+ callStackPane.update(currentFrame, this._sourceIDMap);
+ callStackPane.selectedCallFrame = currentFrame;
+
+ WebInspector.currentPanel = this;
+ window.focus();
+ },
+
+ debuggerResumed: function()
+ {
+ this._paused = false;
+ this._waitingToPause = false;
+ this._stepping = false;
+
+ this._clearInterface();
+ },
+
+ attachDebuggerWhenShown: function()
+ {
+ if (this.element.parentElement) {
+ InspectorController.enableDebuggerFromFrontend(false);
+ } else {
+ this._attachDebuggerWhenShown = true;
+ }
+ },
+
+ debuggerWasEnabled: function()
+ {
+ this.reset();
+ },
+
+ debuggerWasDisabled: function()
+ {
+ this.reset();
+ },
+
+ reset: function()
+ {
+ this.visibleView = null;
+
+ delete this.currentQuery;
+ this.searchCanceled();
+
+ if (!InspectorController.debuggerEnabled()) {
+ this._paused = false;
+ this._waitingToPause = false;
+ this._stepping = false;
+ }
+
+ this._clearInterface();
+
+ this._backForwardList = [];
+ this._currentBackForwardIndex = -1;
+ this._updateBackAndForwardButtons();
+
+ this._scriptsForURLsInFilesSelect = {};
+ this.filesSelectElement.removeChildren();
+ this.functionsSelectElement.removeChildren();
+ this.viewsContainerElement.removeChildren();
+
+ if (this._sourceIDMap) {
+ for (var sourceID in this._sourceIDMap) {
+ var object = this._sourceIDMap[sourceID];
+ if (object instanceof WebInspector.Resource)
+ object.removeAllScripts();
+ }
+ }
+
+ this._sourceIDMap = {};
+ },
+
+ get visibleView()
+ {
+ return this._visibleView;
+ },
+
+ set visibleView(x)
+ {
+ if (this._visibleView === x)
+ return;
+
+ if (this._visibleView)
+ this._visibleView.hide();
+
+ this._visibleView = x;
+
+ if (x)
+ x.show(this.viewsContainerElement);
+ },
+
+ canShowResource: function(resource)
+ {
+ return resource && resource.scripts.length && InspectorController.debuggerEnabled();
+ },
+
+ showScript: function(script, line)
+ {
+ this._showScriptOrResource(script, line, true);
+ },
+
+ showResource: function(resource, line)
+ {
+ this._showScriptOrResource(resource, line, true);
+ },
+
+ showView: function(view)
+ {
+ if (!view)
+ return;
+ this._showScriptOrResource((view.resource || view.script));
+ },
+
+ scriptViewForScript: function(script)
+ {
+ if (!script)
+ return null;
+ if (!script._scriptView)
+ script._scriptView = new WebInspector.ScriptView(script);
+ return script._scriptView;
+ },
+
+ sourceFrameForScript: function(script)
+ {
+ var view = this.scriptViewForScript(script);
+ if (!view)
+ return null;
+
+ // Setting up the source frame requires that we be attached.
+ if (!this.element.parentNode)
+ this.attach();
+
+ view.setupSourceFrameIfNeeded();
+ return view.sourceFrame;
+ },
+
+ _sourceViewForScriptOrResource: function(scriptOrResource)
+ {
+ if (scriptOrResource instanceof WebInspector.Resource) {
+ if (!WebInspector.panels.resources)
+ return null;
+ return WebInspector.panels.resources.resourceViewForResource(scriptOrResource);
+ }
+ if (scriptOrResource instanceof WebInspector.Script)
+ return this.scriptViewForScript(scriptOrResource);
+ },
+
+ _sourceFrameForScriptOrResource: function(scriptOrResource)
+ {
+ if (scriptOrResource instanceof WebInspector.Resource) {
+ if (!WebInspector.panels.resources)
+ return null;
+ return WebInspector.panels.resources.sourceFrameForResource(scriptOrResource);
+ }
+ if (scriptOrResource instanceof WebInspector.Script)
+ return this.sourceFrameForScript(scriptOrResource);
+ },
+
+ _showScriptOrResource: function(scriptOrResource, line, shouldHighlightLine, fromBackForwardAction)
+ {
+ if (!scriptOrResource)
+ return;
+
+ var view;
+ if (scriptOrResource instanceof WebInspector.Resource) {
+ if (!WebInspector.panels.resources)
+ return null;
+ view = WebInspector.panels.resources.resourceViewForResource(scriptOrResource);
+ view.headersVisible = false;
+
+ if (scriptOrResource.url in this._breakpointsURLMap) {
+ var sourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource);
+ if (sourceFrame && !sourceFrame.breakpoints.length) {
+ var breakpoints = this._breakpointsURLMap[scriptOrResource.url];
+ var breakpointsLength = breakpoints.length;
+ for (var i = 0; i < breakpointsLength; ++i)
+ sourceFrame.addBreakpoint(breakpoints[i]);
+ }
+ }
+ } else if (scriptOrResource instanceof WebInspector.Script)
+ view = this.scriptViewForScript(scriptOrResource);
+
+ if (!view)
+ return;
+
+ if (!fromBackForwardAction) {
+ var oldIndex = this._currentBackForwardIndex;
+ if (oldIndex >= 0)
+ this._backForwardList.splice(oldIndex + 1, this._backForwardList.length - oldIndex);
+
+ // Check for a previous entry of the same object in _backForwardList.
+ // If one is found, remove it and update _currentBackForwardIndex to match.
+ var previousEntryIndex = this._backForwardList.indexOf(scriptOrResource);
+ if (previousEntryIndex !== -1) {
+ this._backForwardList.splice(previousEntryIndex, 1);
+ --this._currentBackForwardIndex;
+ }
+
+ this._backForwardList.push(scriptOrResource);
+ ++this._currentBackForwardIndex;
+
+ this._updateBackAndForwardButtons();
+ }
+
+ this.visibleView = view;
+
+ if (line) {
+ if (view.revealLine)
+ view.revealLine(line);
+ if (view.highlightLine && shouldHighlightLine)
+ view.highlightLine(line);
+ }
+
+ var option;
+ if (scriptOrResource instanceof WebInspector.Script) {
+ option = scriptOrResource.filesSelectOption;
+ console.assert(option);
+ } else {
+ var url = scriptOrResource.url;
+ var script = this._scriptsForURLsInFilesSelect[url];
+ if (script)
+ option = script.filesSelectOption;
+ }
+
+ if (option)
+ this.filesSelectElement.selectedIndex = option.index;
+ },
+
+ _addScriptToFilesMenu: function(script)
+ {
+ if (script.resource && this._scriptsForURLsInFilesSelect[script.sourceURL])
+ return;
+
+ this._scriptsForURLsInFilesSelect[script.sourceURL] = script;
+
+ var select = this.filesSelectElement;
+
+ var option = document.createElement("option");
+ option.representedObject = (script.resource || script);
+ option.text = (script.sourceURL ? WebInspector.displayNameForURL(script.sourceURL) : WebInspector.UIString("(program)"));
+
+ function optionCompare(a, b)
+ {
+ var aTitle = a.text.toLowerCase();
+ var bTitle = b.text.toLowerCase();
+ if (aTitle < bTitle)
+ return -1;
+ else if (aTitle > bTitle)
+ return 1;
+
+ var aSourceID = a.representedObject.sourceID;
+ var bSourceID = b.representedObject.sourceID;
+ if (aSourceID < bSourceID)
+ return -1;
+ else if (aSourceID > bSourceID)
+ return 1;
+ return 0;
+ }
+
+ var insertionIndex = insertionIndexForObjectInListSortedByFunction(option, select.childNodes, optionCompare);
+ if (insertionIndex < 0)
+ select.appendChild(option);
+ else
+ select.insertBefore(option, select.childNodes.item(insertionIndex));
+
+ script.filesSelectOption = option;
+
+ // Call _showScriptOrResource if the option we just appended ended up being selected.
+ // This will happen for the first item added to the menu.
+ if (select.options[select.selectedIndex] === option)
+ this._showScriptOrResource(option.representedObject);
+ },
+
+ _clearCurrentExecutionLine: function()
+ {
+ if (this._executionSourceFrame)
+ this._executionSourceFrame.executionLine = 0;
+ delete this._executionSourceFrame;
+ },
+
+ _callFrameSelected: function()
+ {
+ this._clearCurrentExecutionLine();
+
+ var callStackPane = this.sidebarPanes.callstack;
+ var currentFrame = callStackPane.selectedCallFrame;
+ if (!currentFrame)
+ return;
+
+ this.sidebarPanes.scopechain.update(currentFrame);
+
+ var scriptOrResource = this._sourceIDMap[currentFrame.sourceID];
+ this._showScriptOrResource(scriptOrResource, currentFrame.line);
+
+ this._executionSourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource);
+ if (this._executionSourceFrame)
+ this._executionSourceFrame.executionLine = currentFrame.line;
+ },
+
+ _changeVisibleFile: function(event)
+ {
+ var select = this.filesSelectElement;
+ this._showScriptOrResource(select.options[select.selectedIndex].representedObject);
+ },
+
+ _startSidebarResizeDrag: function(event)
+ {
+ WebInspector.elementDragStart(this.sidebarElement, this._sidebarResizeDrag.bind(this), this._endSidebarResizeDrag.bind(this), event, "col-resize");
+
+ if (event.target === this.sidebarResizeWidgetElement)
+ this._dragOffset = (event.target.offsetWidth - (event.pageX - event.target.totalOffsetLeft));
+ else
+ this._dragOffset = 0;
+ },
+
+ _endSidebarResizeDrag: function(event)
+ {
+ WebInspector.elementDragEnd(event);
+
+ delete this._dragOffset;
+ },
+
+ _sidebarResizeDrag: function(event)
+ {
+ var x = event.pageX + this._dragOffset;
+ var newWidth = Number.constrain(window.innerWidth - x, Preferences.minScriptsSidebarWidth, window.innerWidth * 0.66);
+
+ this.sidebarElement.style.width = newWidth + "px";
+ this.sidebarButtonsElement.style.width = newWidth + "px";
+ this.viewsContainerElement.style.right = newWidth + "px";
+ this.sidebarResizeWidgetElement.style.right = newWidth + "px";
+ this.sidebarResizeElement.style.right = (newWidth - 3) + "px";
+
+ event.preventDefault();
+ },
+
+ _updatePauseOnExceptionsButton: function()
+ {
+ if (InspectorController.pauseOnExceptions()) {
+ this.pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions.");
+ this.pauseOnExceptionButton.addStyleClass("toggled-on");
+ } else {
+ this.pauseOnExceptionButton.title = WebInspector.UIString("Pause on exceptions.");
+ this.pauseOnExceptionButton.removeStyleClass("toggled-on");
+ }
+ },
+
+ _updateDebuggerButtons: function()
+ {
+ if (InspectorController.debuggerEnabled()) {
+ this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable.");
+ this.enableToggleButton.addStyleClass("toggled-on");
+ this.pauseOnExceptionButton.removeStyleClass("hidden");
+ this.panelEnablerView.visible = false;
+ } else {
+ this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable.");
+ this.enableToggleButton.removeStyleClass("toggled-on");
+ this.pauseOnExceptionButton.addStyleClass("hidden");
+ this.panelEnablerView.visible = true;
+ }
+
+ this._updatePauseOnExceptionsButton();
+
+ if (this._paused) {
+ this.pauseButton.addStyleClass("paused");
+
+ this.pauseButton.disabled = false;
+ this.stepOverButton.disabled = false;
+ this.stepIntoButton.disabled = false;
+ this.stepOutButton.disabled = false;
+
+ this.debuggerStatusElement.textContent = WebInspector.UIString("Paused");
+ } else {
+ this.pauseButton.removeStyleClass("paused");
+
+ this.pauseButton.disabled = this._waitingToPause;
+ this.stepOverButton.disabled = true;
+ this.stepIntoButton.disabled = true;
+ this.stepOutButton.disabled = true;
+
+ if (this._waitingToPause)
+ this.debuggerStatusElement.textContent = WebInspector.UIString("Pausing");
+ else if (this._stepping)
+ this.debuggerStatusElement.textContent = WebInspector.UIString("Stepping");
+ else
+ this.debuggerStatusElement.textContent = "";
+ }
+ },
+
+ _updateBackAndForwardButtons: function()
+ {
+ this.backButton.disabled = this._currentBackForwardIndex <= 0;
+ this.forwardButton.disabled = this._currentBackForwardIndex >= (this._backForwardList.length - 1);
+ },
+
+ _clearInterface: function()
+ {
+ this.sidebarPanes.callstack.update(null);
+ this.sidebarPanes.scopechain.update(null);
+
+ this._clearCurrentExecutionLine();
+ this._updateDebuggerButtons();
+ },
+
+ _goBack: function()
+ {
+ if (this._currentBackForwardIndex <= 0) {
+ console.error("Can't go back from index " + this._currentBackForwardIndex);
+ return;
+ }
+
+ this._showScriptOrResource(this._backForwardList[--this._currentBackForwardIndex], null, false, true);
+ this._updateBackAndForwardButtons();
+ },
+
+ _goForward: function()
+ {
+ if (this._currentBackForwardIndex >= this._backForwardList.length - 1) {
+ console.error("Can't go forward from index " + this._currentBackForwardIndex);
+ return;
+ }
+
+ this._showScriptOrResource(this._backForwardList[++this._currentBackForwardIndex], null, false, true);
+ this._updateBackAndForwardButtons();
+ },
+
+ _enableDebugging: function()
+ {
+ if (InspectorController.debuggerEnabled())
+ return;
+ this._toggleDebugging(this.panelEnablerView.alwaysEnabled);
+ },
+
+ _toggleDebugging: function(optionalAlways)
+ {
+ this._paused = false;
+ this._waitingToPause = false;
+ this._stepping = false;
+
+ if (InspectorController.debuggerEnabled())
+ InspectorController.disableDebugger(true);
+ else
+ InspectorController.enableDebuggerFromFrontend(!!optionalAlways);
+ },
+
+ _togglePauseOnExceptions: function()
+ {
+ InspectorController.setPauseOnExceptions(!InspectorController.pauseOnExceptions());
+ this._updatePauseOnExceptionsButton();
+ },
+
+ _togglePause: function()
+ {
+ if (this._paused) {
+ this._paused = false;
+ this._waitingToPause = false;
+ InspectorController.resumeDebugger();
+ } else {
+ this._stepping = false;
+ this._waitingToPause = true;
+ InspectorController.pauseInDebugger();
+ }
+
+ this._clearInterface();
+ },
+
+ _stepOverClicked: function()
+ {
+ this._paused = false;
+ this._stepping = true;
+
+ this._clearInterface();
+
+ InspectorController.stepOverStatementInDebugger();
+ },
+
+ _stepIntoClicked: function()
+ {
+ this._paused = false;
+ this._stepping = true;
+
+ this._clearInterface();
+
+ InspectorController.stepIntoStatementInDebugger();
+ },
+
+ _stepOutClicked: function()
+ {
+ this._paused = false;
+ this._stepping = true;
+
+ this._clearInterface();
+
+ InspectorController.stepOutOfFunctionInDebugger();
+ }
+}
+
+WebInspector.ScriptsPanel.prototype.__proto__ = WebInspector.Panel.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/SidebarPane.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/SidebarPane.js
new file mode 100644
index 0000000..af9e5f9
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/SidebarPane.js
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SidebarPane = function(title)
+{
+ this.element = document.createElement("div");
+ this.element.className = "pane";
+
+ this.titleElement = document.createElement("div");
+ this.titleElement.className = "title";
+ this.titleElement.addEventListener("click", this.toggleExpanded.bind(this), false);
+
+ this.bodyElement = document.createElement("div");
+ this.bodyElement.className = "body";
+
+ this.element.appendChild(this.titleElement);
+ this.element.appendChild(this.bodyElement);
+
+ this.title = title;
+ this.growbarVisible = false;
+ this.expanded = false;
+}
+
+WebInspector.SidebarPane.prototype = {
+ get title()
+ {
+ return this._title;
+ },
+
+ set title(x)
+ {
+ if (this._title === x)
+ return;
+ this._title = x;
+ this.titleElement.textContent = x;
+ },
+
+ get growbarVisible()
+ {
+ return this._growbarVisible;
+ },
+
+ set growbarVisible(x)
+ {
+ if (this._growbarVisible === x)
+ return;
+
+ this._growbarVisible = x;
+
+ if (x && !this._growbarElement) {
+ this._growbarElement = document.createElement("div");
+ this._growbarElement.className = "growbar";
+ this.element.appendChild(this._growbarElement);
+ } else if (!x && this._growbarElement) {
+ if (this._growbarElement.parentNode)
+ this._growbarElement.parentNode(this._growbarElement);
+ delete this._growbarElement;
+ }
+ },
+
+ get expanded()
+ {
+ return this._expanded;
+ },
+
+ set expanded(x)
+ {
+ if (x)
+ this.expand();
+ else
+ this.collapse();
+ },
+
+ expand: function()
+ {
+ if (this._expanded)
+ return;
+ this._expanded = true;
+ this.element.addStyleClass("expanded");
+ if (this.onexpand)
+ this.onexpand(this);
+ },
+
+ collapse: function()
+ {
+ if (!this._expanded)
+ return;
+ this._expanded = false;
+ this.element.removeStyleClass("expanded");
+ if (this.oncollapse)
+ this.oncollapse(this);
+ },
+
+ toggleExpanded: function()
+ {
+ this.expanded = !this.expanded;
+ }
+}
+
+WebInspector.SidebarPane.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/SidebarTreeElement.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/SidebarTreeElement.js
new file mode 100644
index 0000000..c08b0ef
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/SidebarTreeElement.js
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SidebarSectionTreeElement = function(title, representedObject, hasChildren)
+{
+ TreeElement.call(this, title.escapeHTML(), representedObject || {}, hasChildren);
+}
+
+WebInspector.SidebarSectionTreeElement.prototype = {
+ selectable: false,
+
+ get smallChildren()
+ {
+ return this._smallChildren;
+ },
+
+ set smallChildren(x)
+ {
+ if (this._smallChildren === x)
+ return;
+
+ this._smallChildren = x;
+
+ if (this._smallChildren)
+ this._childrenListNode.addStyleClass("small");
+ else
+ this._childrenListNode.removeStyleClass("small");
+ },
+
+ onattach: function()
+ {
+ this._listItemNode.addStyleClass("sidebar-tree-section");
+ },
+
+ onreveal: function()
+ {
+ if (this.listItemElement)
+ this.listItemElement.scrollIntoViewIfNeeded(false);
+ }
+}
+
+WebInspector.SidebarSectionTreeElement.prototype.__proto__ = TreeElement.prototype;
+
+WebInspector.SidebarTreeElement = function(className, title, subtitle, representedObject, hasChildren)
+{
+ TreeElement.call(this, "", representedObject || {}, hasChildren);
+
+ if (hasChildren) {
+ this.disclosureButton = document.createElement("button");
+ this.disclosureButton.className = "disclosure-button";
+ }
+
+ if (!this.iconElement) {
+ this.iconElement = document.createElement("img");
+ this.iconElement.className = "icon";
+ }
+
+ this.statusElement = document.createElement("div");
+ this.statusElement.className = "status";
+
+ this.titlesElement = document.createElement("div");
+ this.titlesElement.className = "titles";
+
+ this.titleElement = document.createElement("span");
+ this.titleElement.className = "title";
+ this.titlesElement.appendChild(this.titleElement);
+
+ this.subtitleElement = document.createElement("span");
+ this.subtitleElement.className = "subtitle";
+ this.titlesElement.appendChild(this.subtitleElement);
+
+ this.className = className;
+ this.mainTitle = title;
+ this.subtitle = subtitle;
+}
+
+WebInspector.SidebarTreeElement.prototype = {
+ get small()
+ {
+ return this._small;
+ },
+
+ set small(x)
+ {
+ this._small = x;
+
+ if (this._listItemNode) {
+ if (this._small)
+ this._listItemNode.addStyleClass("small");
+ else
+ this._listItemNode.removeStyleClass("small");
+ }
+ },
+
+ get mainTitle()
+ {
+ return this._mainTitle;
+ },
+
+ set mainTitle(x)
+ {
+ this._mainTitle = x;
+ this.refreshTitles();
+ },
+
+ get subtitle()
+ {
+ return this._subtitle;
+ },
+
+ set subtitle(x)
+ {
+ this._subtitle = x;
+ this.refreshTitles();
+ },
+
+ get bubbleText()
+ {
+ return this._bubbleText;
+ },
+
+ set bubbleText(x)
+ {
+ if (!this.bubbleElement) {
+ this.bubbleElement = document.createElement("div");
+ this.bubbleElement.className = "bubble";
+ this.statusElement.appendChild(this.bubbleElement);
+ }
+
+ this._bubbleText = x;
+ this.bubbleElement.textContent = x;
+ },
+
+ refreshTitles: function()
+ {
+ var mainTitle = this.mainTitle;
+ if (this.titleElement.textContent !== mainTitle)
+ this.titleElement.textContent = mainTitle;
+
+ var subtitle = this.subtitle;
+ if (subtitle) {
+ if (this.subtitleElement.textContent !== subtitle)
+ this.subtitleElement.textContent = subtitle;
+ this.titlesElement.removeStyleClass("no-subtitle");
+ } else
+ this.titlesElement.addStyleClass("no-subtitle");
+ },
+
+ isEventWithinDisclosureTriangle: function(event)
+ {
+ return event.target === this.disclosureButton;
+ },
+
+ onattach: function()
+ {
+ this._listItemNode.addStyleClass("sidebar-tree-item");
+
+ if (this.className)
+ this._listItemNode.addStyleClass(this.className);
+
+ if (this.small)
+ this._listItemNode.addStyleClass("small");
+
+ if (this.hasChildren && this.disclosureButton)
+ this._listItemNode.appendChild(this.disclosureButton);
+
+ this._listItemNode.appendChild(this.iconElement);
+ this._listItemNode.appendChild(this.statusElement);
+ this._listItemNode.appendChild(this.titlesElement);
+ },
+
+ onreveal: function()
+ {
+ if (this._listItemNode)
+ this._listItemNode.scrollIntoViewIfNeeded(false);
+ }
+}
+
+WebInspector.SidebarTreeElement.prototype.__proto__ = TreeElement.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/SourceFrame.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/SourceFrame.js
new file mode 100644
index 0000000..18d9073
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/SourceFrame.js
@@ -0,0 +1,730 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SourceFrame = function(element, addBreakpointDelegate)
+{
+ this.messages = [];
+ this.breakpoints = [];
+
+ this.addBreakpointDelegate = addBreakpointDelegate;
+
+ this.element = element || document.createElement("iframe");
+ this.element.addStyleClass("source-view-frame");
+ this.element.setAttribute("viewsource", "true");
+
+ this.element.addEventListener("load", this._loaded.bind(this), false);
+}
+
+WebInspector.SourceFrame.prototype = {
+ get executionLine()
+ {
+ return this._executionLine;
+ },
+
+ set executionLine(x)
+ {
+ if (this._executionLine === x)
+ return;
+
+ var previousLine = this._executionLine;
+ this._executionLine = x;
+
+ this._updateExecutionLine(previousLine);
+ },
+
+ get autoSizesToFitContentHeight()
+ {
+ return this._autoSizesToFitContentHeight;
+ },
+
+ set autoSizesToFitContentHeight(x)
+ {
+ if (this._autoSizesToFitContentHeight === x)
+ return;
+
+ this._autoSizesToFitContentHeight = x;
+
+ if (this._autoSizesToFitContentHeight) {
+ this._windowResizeListener = this._windowResized.bind(this);
+ window.addEventListener("resize", this._windowResizeListener, false);
+ this.sizeToFitContentHeight();
+ } else {
+ this.element.style.removeProperty("height");
+ if (this.element.contentDocument)
+ this.element.contentDocument.body.removeStyleClass("webkit-height-sized-to-fit");
+ window.removeEventListener("resize", this._windowResizeListener, false);
+ delete this._windowResizeListener;
+ }
+ },
+
+ sourceRow: function(lineNumber)
+ {
+ if (!lineNumber || !this.element.contentDocument)
+ return;
+
+ var table = this.element.contentDocument.getElementsByTagName("table")[0];
+ if (!table)
+ return;
+
+ var rows = table.rows;
+
+ // Line numbers are a 1-based index, but the rows collection is 0-based.
+ --lineNumber;
+
+ return rows[lineNumber];
+ },
+
+ lineNumberForSourceRow: function(sourceRow)
+ {
+ // Line numbers are a 1-based index, but the rows collection is 0-based.
+ var lineNumber = 0;
+ while (sourceRow) {
+ ++lineNumber;
+ sourceRow = sourceRow.previousSibling;
+ }
+
+ return lineNumber;
+ },
+
+ revealLine: function(lineNumber)
+ {
+ if (!this._isContentLoaded()) {
+ this._lineNumberToReveal = lineNumber;
+ return;
+ }
+
+ var row = this.sourceRow(lineNumber);
+ if (row)
+ row.scrollIntoViewIfNeeded(true);
+ },
+
+ addBreakpoint: function(breakpoint)
+ {
+ this.breakpoints.push(breakpoint);
+ breakpoint.addEventListener("enabled", this._breakpointEnableChanged, this);
+ breakpoint.addEventListener("disabled", this._breakpointEnableChanged, this);
+ this._addBreakpointToSource(breakpoint);
+ },
+
+ removeBreakpoint: function(breakpoint)
+ {
+ this.breakpoints.remove(breakpoint);
+ breakpoint.removeEventListener("enabled", null, this);
+ breakpoint.removeEventListener("disabled", null, this);
+ this._removeBreakpointFromSource(breakpoint);
+ },
+
+ addMessage: function(msg)
+ {
+ // Don't add the message if there is no message or valid line or if the msg isn't an error or warning.
+ if (!msg.message || msg.line <= 0 || !msg.isErrorOrWarning())
+ return;
+ this.messages.push(msg);
+ this._addMessageToSource(msg);
+ },
+
+ clearMessages: function()
+ {
+ this.messages = [];
+
+ if (!this.element.contentDocument)
+ return;
+
+ var bubbles = this.element.contentDocument.querySelectorAll(".webkit-html-message-bubble");
+ if (!bubbles)
+ return;
+
+ for (var i = 0; i < bubbles.length; ++i) {
+ var bubble = bubbles[i];
+ bubble.parentNode.removeChild(bubble);
+ }
+ },
+
+ sizeToFitContentHeight: function()
+ {
+ if (this.element.contentDocument) {
+ this.element.style.setProperty("height", this.element.contentDocument.body.offsetHeight + "px");
+ this.element.contentDocument.body.addStyleClass("webkit-height-sized-to-fit");
+ }
+ },
+
+ _highlightLineEnds: function(event)
+ {
+ event.target.parentNode.removeStyleClass("webkit-highlighted-line");
+ },
+
+ highlightLine: function(lineNumber)
+ {
+ if (!this._isContentLoaded()) {
+ this._lineNumberToHighlight = lineNumber;
+ return;
+ }
+
+ var sourceRow = this.sourceRow(lineNumber);
+ if (!sourceRow)
+ return;
+ var line = sourceRow.getElementsByClassName('webkit-line-content')[0];
+ // Trick to reset the animation if the user clicks on the same link
+ // Using a timeout to avoid coalesced style updates
+ line.style.setProperty("-webkit-animation-name", "none");
+ setTimeout(function () {
+ line.style.removeProperty("-webkit-animation-name");
+ sourceRow.addStyleClass("webkit-highlighted-line");
+ }, 0);
+ },
+
+ _loaded: function()
+ {
+ WebInspector.addMainEventListeners(this.element.contentDocument);
+ this.element.contentDocument.addEventListener("mousedown", this._documentMouseDown.bind(this), true);
+ this.element.contentDocument.addEventListener("webkitAnimationEnd", this._highlightLineEnds.bind(this), false);
+
+ var headElement = this.element.contentDocument.getElementsByTagName("head")[0];
+ if (!headElement) {
+ headElement = this.element.contentDocument.createElement("head");
+ this.element.contentDocument.documentElement.insertBefore(headElement, this.element.contentDocument.documentElement.firstChild);
+ }
+
+ var styleElement = this.element.contentDocument.createElement("style");
+ headElement.appendChild(styleElement);
+
+ // Add these style rules here since they are specific to the Inspector. They also behave oddly and not
+ // all properties apply if added to view-source.css (becuase it is a user agent sheet.)
+ var styleText = ".webkit-line-number { background-repeat: no-repeat; background-position: right 1px; }\n";
+ styleText += ".webkit-breakpoint .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint); }\n";
+ styleText += ".webkit-breakpoint-disabled .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint-disabled); }\n";
+ styleText += ".webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(program-counter); }\n";
+ styleText += ".webkit-breakpoint.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-program-counter); }\n";
+ styleText += ".webkit-breakpoint-disabled.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-disabled-program-counter); }\n";
+ styleText += ".webkit-execution-line .webkit-line-content { background-color: rgb(171, 191, 254); outline: 1px solid rgb(64, 115, 244); }\n";
+ styleText += ".webkit-height-sized-to-fit { overflow-y: hidden }\n";
+ styleText += ".webkit-line-content { background-color: white; }\n";
+ styleText += "@-webkit-keyframes fadeout {from {background-color: rgb(255, 255, 120);} to { background-color: white;}}\n";
+ styleText += ".webkit-highlighted-line .webkit-line-content { background-color: rgb(255, 255, 120); -webkit-animation: 'fadeout' 2s 500ms}\n";
+ styleText += ".webkit-javascript-comment { color: rgb(0, 116, 0); }\n";
+ styleText += ".webkit-javascript-keyword { color: rgb(170, 13, 145); }\n";
+ styleText += ".webkit-javascript-number { color: rgb(28, 0, 207); }\n";
+ styleText += ".webkit-javascript-string, .webkit-javascript-regexp { color: rgb(196, 26, 22); }\n";
+
+ styleElement.textContent = styleText;
+
+ this._needsProgramCounterImage = true;
+ this._needsBreakpointImages = true;
+
+ this.element.contentWindow.Element.prototype.addStyleClass = Element.prototype.addStyleClass;
+ this.element.contentWindow.Element.prototype.removeStyleClass = Element.prototype.removeStyleClass;
+ this.element.contentWindow.Element.prototype.removeMatchingStyleClasses = Element.prototype.removeMatchingStyleClasses;
+ this.element.contentWindow.Element.prototype.hasStyleClass = Element.prototype.hasStyleClass;
+ this.element.contentWindow.Node.prototype.enclosingNodeOrSelfWithNodeName = Node.prototype.enclosingNodeOrSelfWithNodeName;
+ this.element.contentWindow.Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = Node.prototype.enclosingNodeOrSelfWithNodeNameInArray;
+
+ this._addExistingMessagesToSource();
+ this._addExistingBreakpointsToSource();
+ this._updateExecutionLine();
+ if (this._executionLine)
+ this.revealLine(this._executionLine);
+
+ if (this.autoSizesToFitContentHeight)
+ this.sizeToFitContentHeight();
+
+ if (this._lineNumberToReveal) {
+ this.revealLine(this._lineNumberToReveal);
+ delete this._lineNumberToReveal;
+ }
+
+ if (this._lineNumberToHighlight) {
+ this.highlightLine(this._lineNumberToHighlight);
+ delete this._lineNumberToHighlight;
+ }
+
+ this.dispatchEventToListeners("content loaded");
+ },
+
+ _isContentLoaded: function() {
+ var doc = this.element.contentDocument;
+ return doc && doc.getElementsByTagName("table")[0];
+ },
+
+ _windowResized: function(event)
+ {
+ if (!this._autoSizesToFitContentHeight)
+ return;
+ this.sizeToFitContentHeight();
+ },
+
+ _documentMouseDown: function(event)
+ {
+ if (!event.target.hasStyleClass("webkit-line-number"))
+ return;
+
+ var sourceRow = event.target.enclosingNodeOrSelfWithNodeName("tr");
+ if (sourceRow._breakpointObject)
+ sourceRow._breakpointObject.enabled = !sourceRow._breakpointObject.enabled;
+ else if (this.addBreakpointDelegate)
+ this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow));
+ },
+
+ _breakpointEnableChanged: function(event)
+ {
+ var breakpoint = event.target;
+ var sourceRow = this.sourceRow(breakpoint.line);
+ if (!sourceRow)
+ return;
+
+ sourceRow.addStyleClass("webkit-breakpoint");
+
+ if (breakpoint.enabled)
+ sourceRow.removeStyleClass("webkit-breakpoint-disabled");
+ else
+ sourceRow.addStyleClass("webkit-breakpoint-disabled");
+ },
+
+ _updateExecutionLine: function(previousLine)
+ {
+ if (previousLine) {
+ var sourceRow = this.sourceRow(previousLine);
+ if (sourceRow)
+ sourceRow.removeStyleClass("webkit-execution-line");
+ }
+
+ if (!this._executionLine)
+ return;
+
+ this._drawProgramCounterImageIfNeeded();
+
+ var sourceRow = this.sourceRow(this._executionLine);
+ if (sourceRow)
+ sourceRow.addStyleClass("webkit-execution-line");
+ },
+
+ _addExistingBreakpointsToSource: function()
+ {
+ var length = this.breakpoints.length;
+ for (var i = 0; i < length; ++i)
+ this._addBreakpointToSource(this.breakpoints[i]);
+ },
+
+ _addBreakpointToSource: function(breakpoint)
+ {
+ var sourceRow = this.sourceRow(breakpoint.line);
+ if (!sourceRow)
+ return;
+
+ this._drawBreakpointImagesIfNeeded();
+
+ sourceRow._breakpointObject = breakpoint;
+
+ sourceRow.addStyleClass("webkit-breakpoint");
+ if (!breakpoint.enabled)
+ sourceRow.addStyleClass("webkit-breakpoint-disabled");
+ },
+
+ _removeBreakpointFromSource: function(breakpoint)
+ {
+ var sourceRow = this.sourceRow(breakpoint.line);
+ if (!sourceRow)
+ return;
+
+ delete sourceRow._breakpointObject;
+
+ sourceRow.removeStyleClass("webkit-breakpoint");
+ sourceRow.removeStyleClass("webkit-breakpoint-disabled");
+ },
+
+ _incrementMessageRepeatCount: function(msg, repeatDelta)
+ {
+ if (!msg._resourceMessageLineElement)
+ return;
+
+ if (!msg._resourceMessageRepeatCountElement) {
+ var repeatedElement = document.createElement("span");
+ msg._resourceMessageLineElement.appendChild(repeatedElement);
+ msg._resourceMessageRepeatCountElement = repeatedElement;
+ }
+
+ msg.repeatCount += repeatDelta;
+ msg._resourceMessageRepeatCountElement.textContent = WebInspector.UIString(" (repeated %d times)", msg.repeatCount);
+ },
+
+ _addExistingMessagesToSource: function()
+ {
+ var length = this.messages.length;
+ for (var i = 0; i < length; ++i)
+ this._addMessageToSource(this.messages[i]);
+ },
+
+ _addMessageToSource: function(msg)
+ {
+ var row = this.sourceRow(msg.line);
+ if (!row)
+ return;
+
+ var cell = row.cells[1];
+ if (!cell)
+ return;
+
+ var messageBubbleElement = cell.lastChild;
+ if (!messageBubbleElement || messageBubbleElement.nodeType !== Node.ELEMENT_NODE || !messageBubbleElement.hasStyleClass("webkit-html-message-bubble")) {
+ messageBubbleElement = this.element.contentDocument.createElement("div");
+ messageBubbleElement.className = "webkit-html-message-bubble";
+ cell.appendChild(messageBubbleElement);
+ }
+
+ if (!row.messages)
+ row.messages = [];
+
+ for (var i = 0; i < row.messages.length; ++i) {
+ if (row.messages[i].isEqual(msg, true)) {
+ this._incrementMessageRepeatCount(row.messages[i], msg.repeatDelta);
+ return;
+ }
+ }
+
+ row.messages.push(msg);
+
+ var imageURL;
+ switch (msg.level) {
+ case WebInspector.ConsoleMessage.MessageLevel.Error:
+ messageBubbleElement.addStyleClass("webkit-html-error-message");
+ imageURL = "Images/errorIcon.png";
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Warning:
+ messageBubbleElement.addStyleClass("webkit-html-warning-message");
+ imageURL = "Images/warningIcon.png";
+ break;
+ }
+
+ var messageLineElement = this.element.contentDocument.createElement("div");
+ messageLineElement.className = "webkit-html-message-line";
+ messageBubbleElement.appendChild(messageLineElement);
+
+ // Create the image element in the Inspector's document so we can use relative image URLs.
+ var image = document.createElement("img");
+ image.src = imageURL;
+ image.className = "webkit-html-message-icon";
+
+ // Adopt the image element since it wasn't created in element's contentDocument.
+ image = this.element.contentDocument.adoptNode(image);
+ messageLineElement.appendChild(image);
+ messageLineElement.appendChild(this.element.contentDocument.createTextNode(msg.message));
+
+ msg._resourceMessageLineElement = messageLineElement;
+ },
+
+ _drawProgramCounterInContext: function(ctx, glow)
+ {
+ if (glow)
+ ctx.save();
+
+ ctx.beginPath();
+ ctx.moveTo(17, 2);
+ ctx.lineTo(19, 2);
+ ctx.lineTo(19, 0);
+ ctx.lineTo(21, 0);
+ ctx.lineTo(26, 5.5);
+ ctx.lineTo(21, 11);
+ ctx.lineTo(19, 11);
+ ctx.lineTo(19, 9);
+ ctx.lineTo(17, 9);
+ ctx.closePath();
+ ctx.fillStyle = "rgb(142, 5, 4)";
+
+ if (glow) {
+ ctx.shadowBlur = 4;
+ ctx.shadowColor = "rgb(255, 255, 255)";
+ ctx.shadowOffsetX = -1;
+ ctx.shadowOffsetY = 0;
+ }
+
+ ctx.fill();
+ ctx.fill(); // Fill twice to get a good shadow and darker anti-aliased pixels.
+
+ if (glow)
+ ctx.restore();
+ },
+
+ _drawProgramCounterImageIfNeeded: function()
+ {
+ if (!this._needsProgramCounterImage || !this.element.contentDocument)
+ return;
+
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "program-counter", 26, 11);
+ ctx.clearRect(0, 0, 26, 11);
+ this._drawProgramCounterInContext(ctx, true);
+
+ delete this._needsProgramCounterImage;
+ },
+
+ _drawBreakpointImagesIfNeeded: function()
+ {
+ if (!this._needsBreakpointImages || !this.element.contentDocument)
+ return;
+
+ function drawBreakpoint(ctx, disabled)
+ {
+ ctx.beginPath();
+ ctx.moveTo(0, 2);
+ ctx.lineTo(2, 0);
+ ctx.lineTo(21, 0);
+ ctx.lineTo(26, 5.5);
+ ctx.lineTo(21, 11);
+ ctx.lineTo(2, 11);
+ ctx.lineTo(0, 9);
+ ctx.closePath();
+ ctx.fillStyle = "rgb(1, 142, 217)";
+ ctx.strokeStyle = "rgb(0, 103, 205)";
+ ctx.lineWidth = 3;
+ ctx.fill();
+ ctx.save();
+ ctx.clip();
+ ctx.stroke();
+ ctx.restore();
+
+ if (!disabled)
+ return;
+
+ ctx.save();
+ ctx.globalCompositeOperation = "destination-out";
+ ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
+ ctx.fillRect(0, 0, 26, 11);
+ ctx.restore();
+ }
+
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint", 26, 11);
+ ctx.clearRect(0, 0, 26, 11);
+ drawBreakpoint(ctx);
+
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-program-counter", 26, 11);
+ ctx.clearRect(0, 0, 26, 11);
+ drawBreakpoint(ctx);
+ ctx.clearRect(20, 0, 6, 11);
+ this._drawProgramCounterInContext(ctx, true);
+
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-disabled", 26, 11);
+ ctx.clearRect(0, 0, 26, 11);
+ drawBreakpoint(ctx, true);
+
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-disabled-program-counter", 26, 11);
+ ctx.clearRect(0, 0, 26, 11);
+ drawBreakpoint(ctx, true);
+ ctx.clearRect(20, 0, 6, 11);
+ this._drawProgramCounterInContext(ctx, true);
+
+ delete this._needsBreakpointImages;
+ },
+
+ syntaxHighlightJavascript: function()
+ {
+ var table = this.element.contentDocument.getElementsByTagName("table")[0];
+ if (!table)
+ return;
+
+ function deleteContinueFlags(cell)
+ {
+ if (!cell)
+ return;
+ delete cell._commentContinues;
+ delete cell._singleQuoteStringContinues;
+ delete cell._doubleQuoteStringContinues;
+ delete cell._regexpContinues;
+ }
+
+ function createSpan(content, className)
+ {
+ var span = document.createElement("span");
+ span.className = className;
+ span.appendChild(document.createTextNode(content));
+ return span;
+ }
+
+ function generateFinder(regex, matchNumber, className)
+ {
+ return function(str) {
+ var match = regex.exec(str);
+ if (!match)
+ return null;
+ previousMatchLength = match[matchNumber].length;
+ return createSpan(match[matchNumber], className);
+ };
+ }
+
+ var findNumber = generateFinder(/^(-?(\d+\.?\d*([eE][+-]\d+)?|0[xX]\h+|Infinity)|NaN)(?:\W|$)/, 1, "webkit-javascript-number");
+ var findKeyword = generateFinder(/^(null|true|false|break|case|catch|const|default|finally|for|instanceof|new|var|continue|function|return|void|delete|if|this|do|while|else|in|switch|throw|try|typeof|with|debugger|class|enum|export|extends|import|super|get|set)(?:\W|$)/, 1, "webkit-javascript-keyword");
+ var findSingleLineString = generateFinder(/^"(?:[^"\\]|\\.)*"|^'([^'\\]|\\.)*'/, 0, "webkit-javascript-string"); // " this quote keeps Xcode happy
+ var findMultilineCommentStart = generateFinder(/^\/\*.*$/, 0, "webkit-javascript-comment");
+ var findMultilineCommentEnd = generateFinder(/^.*?\*\//, 0, "webkit-javascript-comment");
+ var findMultilineSingleQuoteStringStart = generateFinder(/^'(?:[^'\\]|\\.)*\\$/, 0, "webkit-javascript-string");
+ var findMultilineSingleQuoteStringEnd = generateFinder(/^(?:[^'\\]|\\.)*?'/, 0, "webkit-javascript-string");
+ var findMultilineDoubleQuoteStringStart = generateFinder(/^"(?:[^"\\]|\\.)*\\$/, 0, "webkit-javascript-string");
+ var findMultilineDoubleQuoteStringEnd = generateFinder(/^(?:[^"\\]|\\.)*?"/, 0, "webkit-javascript-string");
+ var findMultilineRegExpEnd = generateFinder(/^(?:[^\/\\]|\\.)*?\/([gim]{0,3})/, 0, "webkit-javascript-regexp");
+ var findSingleLineComment = generateFinder(/^\/\/.*|^\/\*.*?\*\//, 0, "webkit-javascript-comment");
+
+ function findMultilineRegExpStart(str)
+ {
+ var match = /^\/(?:[^\/\\]|\\.)*\\$/.exec(str);
+ if (!match || !/\\|\$|\.[\?\*\+]|[^\|]\|[^\|]/.test(match[0]))
+ return null;
+ var node = createSpan(match[0], "webkit-javascript-regexp");
+ previousMatchLength = match[0].length;
+ return node;
+ }
+
+ function findSingleLineRegExp(str)
+ {
+ var match = /^(\/(?:[^\/\\]|\\.)*\/([gim]{0,3}))(.?)/.exec(str);
+ if (!match || !(match[2].length > 0 || /\\|\$|\.[\?\*\+]|[^\|]\|[^\|]/.test(match[1]) || /\.|;|,/.test(match[3])))
+ return null;
+ var node = createSpan(match[1], "webkit-javascript-regexp");
+ previousMatchLength = match[1].length;
+ return node;
+ }
+
+ function syntaxHighlightJavascriptLine(line, prevLine)
+ {
+ var messageBubble = line.lastChild;
+ if (messageBubble && messageBubble.nodeType === Node.ELEMENT_NODE && messageBubble.hasStyleClass("webkit-html-message-bubble"))
+ line.removeChild(messageBubble);
+ else
+ messageBubble = null;
+
+ var code = line.textContent;
+
+ while (line.firstChild)
+ line.removeChild(line.firstChild);
+
+ var token;
+ var tmp = 0;
+ var i = 0;
+ previousMatchLength = 0;
+
+ if (prevLine) {
+ if (prevLine._commentContinues) {
+ if (!(token = findMultilineCommentEnd(code))) {
+ token = createSpan(code, "webkit-javascript-comment");
+ line._commentContinues = true;
+ }
+ } else if (prevLine._singleQuoteStringContinues) {
+ if (!(token = findMultilineSingleQuoteStringEnd(code))) {
+ token = createSpan(code, "webkit-javascript-string");
+ line._singleQuoteStringContinues = true;
+ }
+ } else if (prevLine._doubleQuoteStringContinues) {
+ if (!(token = findMultilineDoubleQuoteStringEnd(code))) {
+ token = createSpan(code, "webkit-javascript-string");
+ line._doubleQuoteStringContinues = true;
+ }
+ } else if (prevLine._regexpContinues) {
+ if (!(token = findMultilineRegExpEnd(code))) {
+ token = createSpan(code, "webkit-javascript-regexp");
+ line._regexpContinues = true;
+ }
+ }
+ if (token) {
+ i += previousMatchLength ? previousMatchLength : code.length;
+ tmp = i;
+ line.appendChild(token);
+ }
+ }
+
+ for ( ; i < code.length; ++i) {
+ var codeFragment = code.substr(i);
+ var prevChar = code[i - 1];
+ token = findSingleLineComment(codeFragment);
+ if (!token) {
+ if ((token = findMultilineCommentStart(codeFragment)))
+ line._commentContinues = true;
+ else if (!prevChar || /^\W/.test(prevChar)) {
+ token = findNumber(codeFragment, code[i - 1]) ||
+ findKeyword(codeFragment, code[i - 1]) ||
+ findSingleLineString(codeFragment) ||
+ findSingleLineRegExp(codeFragment);
+ if (!token) {
+ if (token = findMultilineSingleQuoteStringStart(codeFragment))
+ line._singleQuoteStringContinues = true;
+ else if (token = findMultilineDoubleQuoteStringStart(codeFragment))
+ line._doubleQuoteStringContinues = true;
+ else if (token = findMultilineRegExpStart(codeFragment))
+ line._regexpContinues = true;
+ }
+ }
+ }
+
+ if (token) {
+ if (tmp !== i)
+ line.appendChild(document.createTextNode(code.substring(tmp, i)));
+ line.appendChild(token);
+ i += previousMatchLength - 1;
+ tmp = i + 1;
+ }
+ }
+
+ if (tmp < code.length)
+ line.appendChild(document.createTextNode(code.substring(tmp, i)));
+
+ if (messageBubble)
+ line.appendChild(messageBubble);
+ }
+
+ var i = 0;
+ var rows = table.rows;
+ var rowsLength = rows.length;
+ var previousCell = null;
+ var previousMatchLength = 0;
+ var sourceFrame = this;
+
+ // Split up the work into chunks so we don't block the
+ // UI thread while processing.
+
+ function processChunk()
+ {
+ for (var end = Math.min(i + 10, rowsLength); i < end; ++i) {
+ var row = rows[i];
+ if (!row)
+ continue;
+ var cell = row.cells[1];
+ if (!cell)
+ continue;
+ syntaxHighlightJavascriptLine(cell, previousCell);
+ if (i < (end - 1))
+ deleteContinueFlags(previousCell);
+ previousCell = cell;
+ }
+
+ if (i >= rowsLength && processChunkInterval) {
+ deleteContinueFlags(previousCell);
+ clearInterval(processChunkInterval);
+
+ sourceFrame.dispatchEventToListeners("syntax highlighting complete");
+ }
+ }
+
+ processChunk();
+
+ var processChunkInterval = setInterval(processChunk, 25);
+ }
+}
+
+WebInspector.SourceFrame.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/SourceView.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/SourceView.js
new file mode 100644
index 0000000..7510c8c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/SourceView.js
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SourceView = function(resource)
+{
+ // Set the sourceFrame first since WebInspector.ResourceView will set headersVisible
+ // and our override of headersVisible needs the sourceFrame.
+ this.sourceFrame = new WebInspector.SourceFrame(null, this._addBreakpoint.bind(this));
+
+ WebInspector.ResourceView.call(this, resource);
+
+ resource.addEventListener("finished", this._resourceLoadingFinished, this);
+
+ this.element.addStyleClass("source");
+
+ this._frameNeedsSetup = true;
+
+ this.contentElement.appendChild(this.sourceFrame.element);
+
+ var gutterElement = document.createElement("div");
+ gutterElement.className = "webkit-line-gutter-backdrop";
+ this.element.appendChild(gutterElement);
+}
+
+WebInspector.SourceView.prototype = {
+ set headersVisible(x)
+ {
+ if (x === this._headersVisible)
+ return;
+
+ var superSetter = WebInspector.ResourceView.prototype.__lookupSetter__("headersVisible");
+ if (superSetter)
+ superSetter.call(this, x);
+
+ this.sourceFrame.autoSizesToFitContentHeight = x;
+ },
+
+ show: function(parentElement)
+ {
+ WebInspector.ResourceView.prototype.show.call(this, parentElement);
+ this.setupSourceFrameIfNeeded();
+ },
+
+ hide: function()
+ {
+ WebInspector.View.prototype.hide.call(this);
+ this._currentSearchResultIndex = -1;
+ },
+
+ resize: function()
+ {
+ if (this.sourceFrame.autoSizesToFitContentHeight)
+ this.sourceFrame.sizeToFitContentHeight();
+ },
+
+ detach: function()
+ {
+ WebInspector.ResourceView.prototype.detach.call(this);
+
+ // FIXME: We need to mark the frame for setup on detach because the frame DOM is cleared
+ // when it is removed from the document. Is this a bug?
+ this._frameNeedsSetup = true;
+ this._sourceFrameSetup = false;
+ },
+
+ setupSourceFrameIfNeeded: function()
+ {
+ if (!this._frameNeedsSetup)
+ return;
+
+ this.attach();
+
+ delete this._frameNeedsSetup;
+ this.sourceFrame.addEventListener("content loaded", this._contentLoaded, this);
+ InspectorController.addResourceSourceToFrame(this.resource.identifier, this.sourceFrame.element);
+ },
+
+ _contentLoaded: function()
+ {
+ delete this._frameNeedsSetup;
+ this.sourceFrame.removeEventListener("content loaded", this._contentLoaded, this);
+
+ if (this.resource.type === WebInspector.Resource.Type.Script) {
+ this.sourceFrame.addEventListener("syntax highlighting complete", this._syntaxHighlightingComplete, this);
+ this.sourceFrame.syntaxHighlightJavascript();
+ } else
+ this._sourceFrameSetupFinished();
+ },
+
+ _resourceLoadingFinished: function(event)
+ {
+ this._frameNeedsSetup = true;
+ this._sourceFrameSetup = false;
+ if (this.visible)
+ this.setupSourceFrameIfNeeded();
+ this.resource.removeEventListener("finished", this._resourceLoadingFinished, this);
+ },
+
+ _addBreakpoint: function(line)
+ {
+ var sourceID = null;
+ var closestStartingLine = 0;
+ var scripts = this.resource.scripts;
+ for (var i = 0; i < scripts.length; ++i) {
+ var script = scripts[i];
+ if (script.startingLine <= line && script.startingLine >= closestStartingLine) {
+ closestStartingLine = script.startingLine;
+ sourceID = script.sourceID;
+ }
+ }
+
+ if (WebInspector.panels.scripts) {
+ var breakpoint = new WebInspector.Breakpoint(this.resource.url, line, sourceID);
+ WebInspector.panels.scripts.addBreakpoint(breakpoint);
+ }
+ },
+
+ // The rest of the methods in this prototype need to be generic enough to work with a ScriptView.
+ // The ScriptView prototype pulls these methods into it's prototype to avoid duplicate code.
+
+ searchCanceled: function()
+ {
+ this._currentSearchResultIndex = -1;
+ this._searchResults = [];
+ delete this._delayedFindSearchMatches;
+ },
+
+ performSearch: function(query, finishedCallback)
+ {
+ // Call searchCanceled since it will reset everything we need before doing a new search.
+ this.searchCanceled();
+
+ var lineQueryRegex = /(^|\s)(?:#|line:\s*)(\d+)(\s|$)/i;
+ var lineQueryMatch = query.match(lineQueryRegex);
+ if (lineQueryMatch) {
+ var lineToSearch = parseInt(lineQueryMatch[2]);
+
+ // If there was a space before and after the line query part, replace with a space.
+ // Otherwise replace with an empty string to eat the prefix or postfix space.
+ var lineQueryReplacement = (lineQueryMatch[1] && lineQueryMatch[3] ? " " : "");
+ var filterlessQuery = query.replace(lineQueryRegex, lineQueryReplacement);
+ }
+
+ this._searchFinishedCallback = finishedCallback;
+
+ function findSearchMatches(query, finishedCallback)
+ {
+ if (isNaN(lineToSearch)) {
+ // Search the whole document since there was no line to search.
+ this._searchResults = (InspectorController.search(this.sourceFrame.element.contentDocument, query) || []);
+ } else {
+ var sourceRow = this.sourceFrame.sourceRow(lineToSearch);
+ if (sourceRow) {
+ if (filterlessQuery) {
+ // There is still a query string, so search for that string in the line.
+ this._searchResults = (InspectorController.search(sourceRow, filterlessQuery) || []);
+ } else {
+ // Match the whole line, since there was no remaining query string to match.
+ var rowRange = this.sourceFrame.element.contentDocument.createRange();
+ rowRange.selectNodeContents(sourceRow);
+ this._searchResults = [rowRange];
+ }
+ }
+
+ // Attempt to search for the whole query, just incase it matches a color like "#333".
+ var wholeQueryMatches = InspectorController.search(this.sourceFrame.element.contentDocument, query);
+ if (wholeQueryMatches)
+ this._searchResults = this._searchResults.concat(wholeQueryMatches);
+ }
+
+ if (this._searchResults)
+ finishedCallback(this, this._searchResults.length);
+ }
+
+ if (!this._sourceFrameSetup) {
+ // The search is performed in _sourceFrameSetupFinished by calling _delayedFindSearchMatches.
+ this._delayedFindSearchMatches = findSearchMatches.bind(this, query, finishedCallback);
+ this.setupSourceFrameIfNeeded();
+ return;
+ }
+
+ findSearchMatches.call(this, query, finishedCallback);
+ },
+
+ jumpToFirstSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ this._currentSearchResultIndex = 0;
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToLastSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ this._currentSearchResultIndex = (this._searchResults.length - 1);
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToNextSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ if (++this._currentSearchResultIndex >= this._searchResults.length)
+ this._currentSearchResultIndex = 0;
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToPreviousSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ if (--this._currentSearchResultIndex < 0)
+ this._currentSearchResultIndex = (this._searchResults.length - 1);
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ showingFirstSearchResult: function()
+ {
+ return (this._currentSearchResultIndex === 0);
+ },
+
+ showingLastSearchResult: function()
+ {
+ return (this._searchResults && this._currentSearchResultIndex === (this._searchResults.length - 1));
+ },
+
+ revealLine: function(lineNumber)
+ {
+ this.setupSourceFrameIfNeeded();
+ this.sourceFrame.revealLine(lineNumber);
+ },
+
+ highlightLine: function(lineNumber)
+ {
+ this.setupSourceFrameIfNeeded();
+ this.sourceFrame.highlightLine(lineNumber);
+ },
+
+ addMessage: function(msg)
+ {
+ this.sourceFrame.addMessage(msg);
+ },
+
+ clearMessages: function()
+ {
+ this.sourceFrame.clearMessages();
+ },
+
+ _jumpToSearchResult: function(index)
+ {
+ var foundRange = this._searchResults[index];
+ if (!foundRange)
+ return;
+
+ var selection = this.sourceFrame.element.contentWindow.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(foundRange);
+
+ if (foundRange.startContainer.scrollIntoViewIfNeeded)
+ foundRange.startContainer.scrollIntoViewIfNeeded(true);
+ else if (foundRange.startContainer.parentNode)
+ foundRange.startContainer.parentNode.scrollIntoViewIfNeeded(true);
+ },
+
+ _sourceFrameSetupFinished: function()
+ {
+ this._sourceFrameSetup = true;
+ if (this._delayedFindSearchMatches) {
+ this._delayedFindSearchMatches();
+ delete this._delayedFindSearchMatches;
+ }
+ },
+
+ _syntaxHighlightingComplete: function(event)
+ {
+ this._sourceFrameSetupFinished();
+ this.sourceFrame.removeEventListener("syntax highlighting complete", null, this);
+ }
+}
+
+WebInspector.SourceView.prototype.__proto__ = WebInspector.ResourceView.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/StylesSidebarPane.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/StylesSidebarPane.js
new file mode 100644
index 0000000..c30444b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/StylesSidebarPane.js
@@ -0,0 +1,927 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.StylesSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Styles"));
+}
+
+WebInspector.StylesSidebarPane.prototype = {
+ update: function(node, editedSection, forceUpdate)
+ {
+ var refresh = false;
+
+ if (forceUpdate)
+ delete this.node;
+
+ if (!forceUpdate && (!node || node === this.node))
+ refresh = true;
+
+ if (node && node.nodeType === Node.TEXT_NODE && node.parentNode)
+ node = node.parentNode;
+
+ if (node && node.nodeType !== Node.ELEMENT_NODE)
+ node = null;
+
+ if (node)
+ this.node = node;
+ else
+ node = this.node;
+
+ var body = this.bodyElement;
+ if (!refresh || !node) {
+ body.removeChildren();
+ this.sections = [];
+ }
+
+ if (!node)
+ return;
+
+ var styleRules = [];
+
+ if (refresh) {
+ for (var i = 0; i < this.sections.length; ++i) {
+ var section = this.sections[i];
+ if (section.computedStyle)
+ section.styleRule.style = node.ownerDocument.defaultView.getComputedStyle(node);
+ var styleRule = { section: section, style: section.styleRule.style, computedStyle: section.computedStyle };
+ styleRules.push(styleRule);
+ }
+ } else {
+ var computedStyle = node.ownerDocument.defaultView.getComputedStyle(node);
+ styleRules.push({ computedStyle: true, selectorText: WebInspector.UIString("Computed Style"), style: computedStyle, editable: false });
+
+ var nodeName = node.nodeName.toLowerCase();
+ for (var i = 0; i < node.attributes.length; ++i) {
+ var attr = node.attributes[i];
+ if (attr.style) {
+ var attrStyle = { style: attr.style, editable: false };
+ attrStyle.subtitle = WebInspector.UIString("element’s “%s” attribute", attr.name);
+ attrStyle.selectorText = nodeName + "[" + attr.name;
+ if (attr.value.length)
+ attrStyle.selectorText += "=" + attr.value;
+ attrStyle.selectorText += "]";
+ styleRules.push(attrStyle);
+ }
+ }
+
+ if (node.style && (node.style.length || Object.hasProperties(node.style.__disabledProperties))) {
+ var inlineStyle = { selectorText: WebInspector.UIString("Inline Style Attribute"), style: node.style };
+ inlineStyle.subtitle = WebInspector.UIString("element’s “%s” attribute", "style");
+ styleRules.push(inlineStyle);
+ }
+
+ var matchedStyleRules = node.ownerDocument.defaultView.getMatchedCSSRules(node, "", !Preferences.showUserAgentStyles);
+ if (matchedStyleRules) {
+ // Add rules in reverse order to match the cascade order.
+ for (var i = (matchedStyleRules.length - 1); i >= 0; --i) {
+ var rule = matchedStyleRules[i];
+ styleRules.push({ style: rule.style, selectorText: rule.selectorText, parentStyleSheet: rule.parentStyleSheet });
+ }
+ }
+ }
+
+ function deleteDisabledProperty(style, name)
+ {
+ if (!style || !name)
+ return;
+ if (style.__disabledPropertyValues)
+ delete style.__disabledPropertyValues[name];
+ if (style.__disabledPropertyPriorities)
+ delete style.__disabledPropertyPriorities[name];
+ if (style.__disabledProperties)
+ delete style.__disabledProperties[name];
+ }
+
+ var usedProperties = {};
+ var disabledComputedProperties = {};
+ var priorityUsed = false;
+
+ // Walk the style rules and make a list of all used and overloaded properties.
+ for (var i = 0; i < styleRules.length; ++i) {
+ var styleRule = styleRules[i];
+ if (styleRule.computedStyle)
+ continue;
+
+ styleRule.usedProperties = {};
+
+ var style = styleRule.style;
+ for (var j = 0; j < style.length; ++j) {
+ var name = style[j];
+
+ if (!priorityUsed && style.getPropertyPriority(name).length)
+ priorityUsed = true;
+
+ // If the property name is already used by another rule then this rule's
+ // property is overloaded, so don't add it to the rule's usedProperties.
+ if (!(name in usedProperties))
+ styleRule.usedProperties[name] = true;
+
+ if (name === "font") {
+ // The font property is not reported as a shorthand. Report finding the individual
+ // properties so they are visible in computed style.
+ // FIXME: remove this when http://bugs.webkit.org/show_bug.cgi?id=15598 is fixed.
+ styleRule.usedProperties["font-family"] = true;
+ styleRule.usedProperties["font-size"] = true;
+ styleRule.usedProperties["font-style"] = true;
+ styleRule.usedProperties["font-variant"] = true;
+ styleRule.usedProperties["font-weight"] = true;
+ styleRule.usedProperties["line-height"] = true;
+ }
+
+ // Delete any disabled properties, since the property does exist.
+ // This prevents it from showing twice.
+ deleteDisabledProperty(style, name);
+ deleteDisabledProperty(style, style.getPropertyShorthand(name));
+ }
+
+ // Add all the properties found in this style to the used properties list.
+ // Do this here so only future rules are affect by properties used in this rule.
+ for (var name in styleRules[i].usedProperties)
+ usedProperties[name] = true;
+
+ // Remember all disabled properties so they show up in computed style.
+ if (style.__disabledProperties)
+ for (var name in style.__disabledProperties)
+ disabledComputedProperties[name] = true;
+ }
+
+ if (priorityUsed) {
+ // Walk the properties again and account for !important.
+ var foundPriorityProperties = [];
+
+ // Walk in reverse to match the order !important overrides.
+ for (var i = (styleRules.length - 1); i >= 0; --i) {
+ if (styleRules[i].computedStyle)
+ continue;
+
+ var style = styleRules[i].style;
+ var uniqueProperties = getUniqueStyleProperties(style);
+ for (var j = 0; j < uniqueProperties.length; ++j) {
+ var name = uniqueProperties[j];
+ if (style.getPropertyPriority(name).length) {
+ if (!(name in foundPriorityProperties))
+ styleRules[i].usedProperties[name] = true;
+ else
+ delete styleRules[i].usedProperties[name];
+ foundPriorityProperties[name] = true;
+ } else if (name in foundPriorityProperties)
+ delete styleRules[i].usedProperties[name];
+ }
+ }
+ }
+
+ if (refresh) {
+ // Walk the style rules and update the sections with new overloaded and used properties.
+ for (var i = 0; i < styleRules.length; ++i) {
+ var styleRule = styleRules[i];
+ var section = styleRule.section;
+ if (styleRule.computedStyle)
+ section.disabledComputedProperties = disabledComputedProperties;
+ section._usedProperties = (styleRule.usedProperties || usedProperties);
+ section.update((section === editedSection) || styleRule.computedStyle);
+ }
+ } else {
+ // Make a property section for each style rule.
+ for (var i = 0; i < styleRules.length; ++i) {
+ var styleRule = styleRules[i];
+ var subtitle = styleRule.subtitle;
+ delete styleRule.subtitle;
+
+ var computedStyle = styleRule.computedStyle;
+ delete styleRule.computedStyle;
+
+ var ruleUsedProperties = styleRule.usedProperties;
+ delete styleRule.usedProperties;
+
+ var editable = styleRule.editable;
+ delete styleRule.editable;
+
+ // Default editable to true if it was omitted.
+ if (typeof editable === "undefined")
+ editable = true;
+
+ var section = new WebInspector.StylePropertiesSection(styleRule, subtitle, computedStyle, (ruleUsedProperties || usedProperties), editable);
+ if (computedStyle)
+ section.disabledComputedProperties = disabledComputedProperties;
+ section.pane = this;
+
+ if (Preferences.styleRulesExpandedState && section.identifier in Preferences.styleRulesExpandedState)
+ section.expanded = Preferences.styleRulesExpandedState[section.identifier];
+ else if (computedStyle)
+ section.collapse(true);
+ else
+ section.expand(true);
+
+ body.appendChild(section.element);
+ this.sections.push(section);
+ }
+ }
+ }
+}
+
+WebInspector.StylesSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
+
+WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyle, usedProperties, editable)
+{
+ WebInspector.PropertiesSection.call(this, styleRule.selectorText);
+
+ this.styleRule = styleRule;
+ this.computedStyle = computedStyle;
+ this.editable = (editable && !computedStyle);
+
+ // Prevent editing the user agent and user rules.
+ var isUserAgent = this.styleRule.parentStyleSheet && !this.styleRule.parentStyleSheet.ownerNode && !this.styleRule.parentStyleSheet.href;
+ var isUser = this.styleRule.parentStyleSheet && this.styleRule.parentStyleSheet.ownerNode && this.styleRule.parentStyleSheet.ownerNode.nodeName == '#document';
+ if (isUserAgent || isUser)
+ this.editable = false;
+
+ this._usedProperties = usedProperties;
+
+ if (computedStyle) {
+ this.element.addStyleClass("computed-style");
+
+ if (Preferences.showInheritedComputedStyleProperties)
+ this.element.addStyleClass("show-inherited");
+
+ var showInheritedLabel = document.createElement("label");
+ var showInheritedInput = document.createElement("input");
+ showInheritedInput.type = "checkbox";
+ showInheritedInput.checked = Preferences.showInheritedComputedStyleProperties;
+
+ var computedStyleSection = this;
+ var showInheritedToggleFunction = function(event) {
+ Preferences.showInheritedComputedStyleProperties = showInheritedInput.checked;
+ if (Preferences.showInheritedComputedStyleProperties)
+ computedStyleSection.element.addStyleClass("show-inherited");
+ else
+ computedStyleSection.element.removeStyleClass("show-inherited");
+ event.stopPropagation();
+ };
+
+ showInheritedLabel.addEventListener("click", showInheritedToggleFunction, false);
+
+ showInheritedLabel.appendChild(showInheritedInput);
+ showInheritedLabel.appendChild(document.createTextNode(WebInspector.UIString("Show inherited")));
+ this.subtitleElement.appendChild(showInheritedLabel);
+ } else {
+ if (!subtitle) {
+ if (this.styleRule.parentStyleSheet && this.styleRule.parentStyleSheet.href) {
+ var url = this.styleRule.parentStyleSheet.href;
+ subtitle = WebInspector.linkifyURL(url, WebInspector.displayNameForURL(url));
+ this.subtitleElement.addStyleClass("file");
+ } else if (isUserAgent)
+ subtitle = WebInspector.UIString("user agent stylesheet");
+ else if (isUser)
+ subtitle = WebInspector.UIString("user stylesheet");
+ else
+ subtitle = WebInspector.UIString("inline stylesheet");
+ }
+
+ this.subtitle = subtitle;
+ }
+
+ this.identifier = styleRule.selectorText;
+ if (this.subtitle)
+ this.identifier += ":" + this.subtitleElement.textContent;
+}
+
+WebInspector.StylePropertiesSection.prototype = {
+ get usedProperties()
+ {
+ return this._usedProperties || {};
+ },
+
+ set usedProperties(x)
+ {
+ this._usedProperties = x;
+ this.update();
+ },
+
+ expand: function(dontRememberState)
+ {
+ WebInspector.PropertiesSection.prototype.expand.call(this);
+ if (dontRememberState)
+ return;
+
+ if (!Preferences.styleRulesExpandedState)
+ Preferences.styleRulesExpandedState = {};
+ Preferences.styleRulesExpandedState[this.identifier] = true;
+ },
+
+ collapse: function(dontRememberState)
+ {
+ WebInspector.PropertiesSection.prototype.collapse.call(this);
+ if (dontRememberState)
+ return;
+
+ if (!Preferences.styleRulesExpandedState)
+ Preferences.styleRulesExpandedState = {};
+ Preferences.styleRulesExpandedState[this.identifier] = false;
+ },
+
+ isPropertyInherited: function(property)
+ {
+ if (!this.computedStyle || !this._usedProperties)
+ return false;
+ // These properties should always show for Computed Style.
+ var alwaysShowComputedProperties = { "display": true, "height": true, "width": true };
+ return !(property in this.usedProperties) && !(property in alwaysShowComputedProperties) && !(property in this.disabledComputedProperties);
+ },
+
+ isPropertyOverloaded: function(property, shorthand)
+ {
+ if (this.computedStyle || !this._usedProperties)
+ return false;
+
+ var used = (property in this.usedProperties);
+ if (used || !shorthand)
+ return !used;
+
+ // Find out if any of the individual longhand properties of the shorthand
+ // are used, if none are then the shorthand is overloaded too.
+ var longhandProperties = getLonghandProperties(this.styleRule.style, property);
+ for (var j = 0; j < longhandProperties.length; ++j) {
+ var individualProperty = longhandProperties[j];
+ if (individualProperty in this.usedProperties)
+ return false;
+ }
+
+ return true;
+ },
+
+ update: function(full)
+ {
+ if (full || this.computedStyle) {
+ this.propertiesTreeOutline.removeChildren();
+ this.populated = false;
+ } else {
+ var child = this.propertiesTreeOutline.children[0];
+ while (child) {
+ child.overloaded = this.isPropertyOverloaded(child.name, child.shorthand);
+ child = child.traverseNextTreeElement(false, null, true);
+ }
+ }
+ },
+
+ onpopulate: function()
+ {
+ var style = this.styleRule.style;
+
+ var foundShorthands = {};
+ var uniqueProperties = getUniqueStyleProperties(style);
+ var disabledProperties = style.__disabledPropertyValues || {};
+
+ for (var name in disabledProperties)
+ uniqueProperties.push(name);
+
+ uniqueProperties.sort();
+
+ for (var i = 0; i < uniqueProperties.length; ++i) {
+ var name = uniqueProperties[i];
+ var disabled = name in disabledProperties;
+ if (!disabled && this.disabledComputedProperties && !(name in this.usedProperties) && name in this.disabledComputedProperties)
+ disabled = true;
+
+ var shorthand = !disabled ? style.getPropertyShorthand(name) : null;
+
+ if (shorthand && shorthand in foundShorthands)
+ continue;
+
+ if (shorthand) {
+ foundShorthands[shorthand] = true;
+ name = shorthand;
+ }
+
+ var isShorthand = (shorthand ? true : false);
+ var inherited = this.isPropertyInherited(name);
+ var overloaded = this.isPropertyOverloaded(name, isShorthand);
+
+ var item = new WebInspector.StylePropertyTreeElement(style, name, isShorthand, inherited, overloaded, disabled);
+ this.propertiesTreeOutline.appendChild(item);
+ }
+ }
+}
+
+WebInspector.StylePropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
+
+WebInspector.StylePropertyTreeElement = function(style, name, shorthand, inherited, overloaded, disabled)
+{
+ this.style = style;
+ this.name = name;
+ this.shorthand = shorthand;
+ this._inherited = inherited;
+ this._overloaded = overloaded;
+ this._disabled = disabled;
+
+ // Pass an empty title, the title gets made later in onattach.
+ TreeElement.call(this, "", null, shorthand);
+}
+
+WebInspector.StylePropertyTreeElement.prototype = {
+ get inherited()
+ {
+ return this._inherited;
+ },
+
+ set inherited(x)
+ {
+ if (x === this._inherited)
+ return;
+ this._inherited = x;
+ this.updateState();
+ },
+
+ get overloaded()
+ {
+ return this._overloaded;
+ },
+
+ set overloaded(x)
+ {
+ if (x === this._overloaded)
+ return;
+ this._overloaded = x;
+ this.updateState();
+ },
+
+ get disabled()
+ {
+ return this._disabled;
+ },
+
+ set disabled(x)
+ {
+ if (x === this._disabled)
+ return;
+ this._disabled = x;
+ this.updateState();
+ },
+
+ get priority()
+ {
+ if (this.disabled && this.style.__disabledPropertyPriorities && this.name in this.style.__disabledPropertyPriorities)
+ return this.style.__disabledPropertyPriorities[this.name];
+ return (this.shorthand ? getShorthandPriority(this.style, this.name) : this.style.getPropertyPriority(this.name));
+ },
+
+ get value()
+ {
+ if (this.disabled && this.style.__disabledPropertyValues && this.name in this.style.__disabledPropertyValues)
+ return this.style.__disabledPropertyValues[this.name];
+ return (this.shorthand ? getShorthandValue(this.style, this.name) : this.style.getPropertyValue(this.name));
+ },
+
+ onattach: function()
+ {
+ this.updateTitle();
+ },
+
+ updateTitle: function()
+ {
+ // "Nicknames" for some common values that are easier to read.
+ var valueNicknames = {
+ "rgb(0, 0, 0)": "black",
+ "#000": "black",
+ "#000000": "black",
+ "rgb(255, 255, 255)": "white",
+ "#fff": "white",
+ "#ffffff": "white",
+ "#FFF": "white",
+ "#FFFFFF": "white",
+ "rgba(0, 0, 0, 0)": "transparent",
+ "rgb(255, 0, 0)": "red",
+ "rgb(0, 255, 0)": "lime",
+ "rgb(0, 0, 255)": "blue",
+ "rgb(255, 255, 0)": "yellow",
+ "rgb(255, 0, 255)": "magenta",
+ "rgb(0, 255, 255)": "cyan"
+ };
+
+ var priority = this.priority;
+ var value = this.value;
+ var htmlValue = value;
+
+ if (priority && !priority.length)
+ delete priority;
+ if (priority)
+ priority = "!" + priority;
+
+ if (value) {
+ var urls = value.match(/url\([^)]+\)/);
+ if (urls) {
+ for (var i = 0; i < urls.length; ++i) {
+ var url = urls[i].substring(4, urls[i].length - 1);
+ htmlValue = htmlValue.replace(urls[i], "url(" + WebInspector.linkifyURL(url) + ")");
+ }
+ } else {
+ if (value in valueNicknames)
+ htmlValue = valueNicknames[value];
+ htmlValue = htmlValue.escapeHTML();
+ }
+ } else
+ htmlValue = value = "";
+
+ this.updateState();
+
+ var enabledCheckboxElement = document.createElement("input");
+ enabledCheckboxElement.className = "enabled-button";
+ enabledCheckboxElement.type = "checkbox";
+ enabledCheckboxElement.checked = !this.disabled;
+ enabledCheckboxElement.addEventListener("change", this.toggleEnabled.bind(this), false);
+
+ var nameElement = document.createElement("span");
+ nameElement.className = "name";
+ nameElement.textContent = this.name;
+
+ var valueElement = document.createElement("span");
+ valueElement.className = "value";
+ valueElement.innerHTML = htmlValue;
+
+ if (priority) {
+ var priorityElement = document.createElement("span");
+ priorityElement.className = "priority";
+ priorityElement.textContent = priority;
+ }
+
+ this.listItemElement.removeChildren();
+
+ // Append the checkbox for root elements of an editable section.
+ if (this.treeOutline.section && this.treeOutline.section.editable && this.parent.root)
+ this.listItemElement.appendChild(enabledCheckboxElement);
+ this.listItemElement.appendChild(nameElement);
+ this.listItemElement.appendChild(document.createTextNode(": "));
+ this.listItemElement.appendChild(valueElement);
+
+ if (priorityElement) {
+ this.listItemElement.appendChild(document.createTextNode(" "));
+ this.listItemElement.appendChild(priorityElement);
+ }
+
+ this.listItemElement.appendChild(document.createTextNode(";"));
+
+ if (value) {
+ // FIXME: this only covers W3C and CSS 16 valid color names
+ var colors = value.match(/((rgb|hsl)a?\([^)]+\))|(#[0-9a-fA-F]{6})|(#[0-9a-fA-F]{3})|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow/g);
+ if (colors) {
+ var colorsLength = colors.length;
+ for (var i = 0; i < colorsLength; ++i) {
+ var swatchElement = document.createElement("span");
+ swatchElement.className = "swatch";
+ swatchElement.style.setProperty("background-color", colors[i]);
+ this.listItemElement.appendChild(swatchElement);
+ }
+ }
+ }
+
+ this.tooltip = this.name + ": " + (valueNicknames[value] || value) + (priority ? " " + priority : "");
+ },
+
+ updateAll: function(updateAllRules)
+ {
+ if (updateAllRules && this.treeOutline.section && this.treeOutline.section.pane)
+ this.treeOutline.section.pane.update(null, this.treeOutline.section);
+ else if (this.treeOutline.section)
+ this.treeOutline.section.update(true);
+ else
+ this.updateTitle(); // FIXME: this will not show new properties. But we don't hit his case yet.
+ },
+
+ toggleEnabled: function(event)
+ {
+ var disabled = !event.target.checked;
+
+ if (disabled) {
+ if (!this.style.__disabledPropertyValues || !this.style.__disabledPropertyPriorities) {
+ var inspectedWindow = InspectorController.inspectedWindow();
+ this.style.__disabledProperties = new inspectedWindow.Object;
+ this.style.__disabledPropertyValues = new inspectedWindow.Object;
+ this.style.__disabledPropertyPriorities = new inspectedWindow.Object;
+ }
+
+ this.style.__disabledPropertyValues[this.name] = this.value;
+ this.style.__disabledPropertyPriorities[this.name] = this.priority;
+
+ if (this.shorthand) {
+ var longhandProperties = getLonghandProperties(this.style, this.name);
+ for (var i = 0; i < longhandProperties.length; ++i) {
+ this.style.__disabledProperties[longhandProperties[i]] = true;
+ this.style.removeProperty(longhandProperties[i]);
+ }
+ } else {
+ this.style.__disabledProperties[this.name] = true;
+ this.style.removeProperty(this.name);
+ }
+ } else {
+ this.style.setProperty(this.name, this.value, this.priority);
+ delete this.style.__disabledProperties[this.name];
+ delete this.style.__disabledPropertyValues[this.name];
+ delete this.style.__disabledPropertyPriorities[this.name];
+ }
+
+ // Set the disabled property here, since the code above replies on it not changing
+ // until after the value and priority are retrieved.
+ this.disabled = disabled;
+
+ if (this.treeOutline.section && this.treeOutline.section.pane)
+ this.treeOutline.section.pane.dispatchEventToListeners("style property toggled");
+
+ this.updateAll(true);
+ },
+
+ updateState: function()
+ {
+ if (!this.listItemElement)
+ return;
+
+ if (this.style.isPropertyImplicit(this.name) || this.value === "initial")
+ this.listItemElement.addStyleClass("implicit");
+ else
+ this.listItemElement.removeStyleClass("implicit");
+
+ if (this.inherited)
+ this.listItemElement.addStyleClass("inherited");
+ else
+ this.listItemElement.removeStyleClass("inherited");
+
+ if (this.overloaded)
+ this.listItemElement.addStyleClass("overloaded");
+ else
+ this.listItemElement.removeStyleClass("overloaded");
+
+ if (this.disabled)
+ this.listItemElement.addStyleClass("disabled");
+ else
+ this.listItemElement.removeStyleClass("disabled");
+ },
+
+ onpopulate: function()
+ {
+ // Only populate once and if this property is a shorthand.
+ if (this.children.length || !this.shorthand)
+ return;
+
+ var longhandProperties = getLonghandProperties(this.style, this.name);
+ for (var i = 0; i < longhandProperties.length; ++i) {
+ var name = longhandProperties[i];
+
+ if (this.treeOutline.section) {
+ var inherited = this.treeOutline.section.isPropertyInherited(name);
+ var overloaded = this.treeOutline.section.isPropertyOverloaded(name);
+ }
+
+ var item = new WebInspector.StylePropertyTreeElement(this.style, name, false, inherited, overloaded);
+ this.appendChild(item);
+ }
+ },
+
+ ondblclick: function(element, event)
+ {
+ this.startEditing(event.target);
+ },
+
+ startEditing: function(selectElement)
+ {
+ // FIXME: we don't allow editing of longhand properties under a shorthand right now.
+ if (this.parent.shorthand)
+ return;
+
+ if (WebInspector.isBeingEdited(this.listItemElement) || (this.treeOutline.section && !this.treeOutline.section.editable))
+ return;
+
+ var context = { expanded: this.expanded, hasChildren: this.hasChildren };
+
+ // Lie about our children to prevent expanding on double click and to collapse shorthands.
+ this.hasChildren = false;
+
+ if (!selectElement)
+ selectElement = this.listItemElement;
+
+ this.listItemElement.handleKeyEvent = this.editingKeyDown.bind(this);
+
+ WebInspector.startEditing(this.listItemElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
+ window.getSelection().setBaseAndExtent(selectElement, 0, selectElement, 1);
+ },
+
+ editingKeyDown: function(event)
+ {
+ var arrowKeyPressed = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down");
+ var pageKeyPressed = (event.keyIdentifier === "PageUp" || event.keyIdentifier === "PageDown");
+ if (!arrowKeyPressed && !pageKeyPressed)
+ return;
+
+ var selection = window.getSelection();
+ if (!selection.rangeCount)
+ return;
+
+ var selectionRange = selection.getRangeAt(0);
+ if (selectionRange.commonAncestorContainer !== this.listItemElement && !selectionRange.commonAncestorContainer.isDescendant(this.listItemElement))
+ return;
+
+ const styleValueDelimeters = " \t\n\"':;,/()";
+ var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, styleValueDelimeters, this.listItemElement);
+ var wordString = wordRange.toString();
+ var replacementString = wordString;
+
+ var matches = /(.*?)(-?\d+(?:\.\d+)?)(.*)/.exec(wordString);
+ if (matches && matches.length) {
+ var prefix = matches[1];
+ var number = parseFloat(matches[2]);
+ var suffix = matches[3];
+
+ // If the number is near zero or the number is one and the direction will take it near zero.
+ var numberNearZero = (number < 1 && number > -1);
+ if (number === 1 && event.keyIdentifier === "Down")
+ numberNearZero = true;
+ else if (number === -1 && event.keyIdentifier === "Up")
+ numberNearZero = true;
+
+ if (numberNearZero && event.altKey && arrowKeyPressed) {
+ if (event.keyIdentifier === "Down")
+ number = Math.ceil(number - 1);
+ else
+ number = Math.floor(number + 1);
+ } else {
+ // Jump by 10 when shift is down or jump by 0.1 when near zero or Alt/Option is down.
+ // Also jump by 10 for page up and down, or by 100 if shift is held with a page key.
+ var changeAmount = 1;
+ if (event.shiftKey && pageKeyPressed)
+ changeAmount = 100;
+ else if (event.shiftKey || pageKeyPressed)
+ changeAmount = 10;
+ else if (event.altKey || numberNearZero)
+ changeAmount = 0.1;
+
+ if (event.keyIdentifier === "Down" || event.keyIdentifier === "PageDown")
+ changeAmount *= -1;
+
+ // Make the new number and constrain it to a precision of 6, this matches numbers the engine returns.
+ // Use the Number constructor to forget the fixed precision, so 1.100000 will print as 1.1.
+ number = Number((number + changeAmount).toFixed(6));
+ }
+
+ replacementString = prefix + number + suffix;
+ } else {
+ // FIXME: this should cycle through known keywords for the current property name.
+ return;
+ }
+
+ var replacementTextNode = document.createTextNode(replacementString);
+
+ wordRange.deleteContents();
+ wordRange.insertNode(replacementTextNode);
+
+ var finalSelectionRange = document.createRange();
+ finalSelectionRange.setStart(replacementTextNode, 0);
+ finalSelectionRange.setEnd(replacementTextNode, replacementString.length);
+
+ selection.removeAllRanges();
+ selection.addRange(finalSelectionRange);
+
+ event.preventDefault();
+ event.handled = true;
+
+ if (!this.originalCSSText) {
+ // Remember the rule's original CSS text, so it can be restored
+ // if the editing is canceled and before each apply.
+ this.originalCSSText = getStyleTextWithShorthands(this.style);
+ } else {
+ // Restore the original CSS text before applying user changes. This is needed to prevent
+ // new properties from sticking around if the user adds one, then removes it.
+ this.style.cssText = this.originalCSSText;
+ }
+
+ this.applyStyleText(this.listItemElement.textContent);
+ },
+
+ editingEnded: function(context)
+ {
+ this.hasChildren = context.hasChildren;
+ if (context.expanded)
+ this.expand();
+ delete this.listItemElement.handleKeyEvent;
+ delete this.originalCSSText;
+ },
+
+ editingCancelled: function(element, context)
+ {
+ if (this.originalCSSText) {
+ this.style.cssText = this.originalCSSText;
+
+ if (this.treeOutline.section && this.treeOutline.section.pane)
+ this.treeOutline.section.pane.dispatchEventToListeners("style edited");
+
+ this.updateAll();
+ } else
+ this.updateTitle();
+
+ this.editingEnded(context);
+ },
+
+ editingCommitted: function(element, userInput, previousContent, context)
+ {
+ this.editingEnded(context);
+
+ if (userInput === previousContent)
+ return; // nothing changed, so do nothing else
+
+ this.applyStyleText(userInput, true);
+ },
+
+ applyStyleText: function(styleText, updateInterface)
+ {
+ var styleTextLength = styleText.trimWhitespace().length;
+
+ // Create a new element to parse the user input CSS.
+ var parseElement = document.createElement("span");
+ parseElement.setAttribute("style", styleText);
+
+ var tempStyle = parseElement.style;
+ if (tempStyle.length || !styleTextLength) {
+ // The input was parsable or the user deleted everything, so remove the
+ // original property from the real style declaration. If this represents
+ // a shorthand remove all the longhand properties.
+ if (this.shorthand) {
+ var longhandProperties = getLonghandProperties(this.style, this.name);
+ for (var i = 0; i < longhandProperties.length; ++i)
+ this.style.removeProperty(longhandProperties[i]);
+ } else
+ this.style.removeProperty(this.name);
+ }
+
+ if (!styleTextLength) {
+ if (updateInterface) {
+ // The user deleted the everything, so remove the tree element and update.
+ if (this.treeOutline.section && this.treeOutline.section.pane)
+ this.treeOutline.section.pane.update();
+ this.parent.removeChild(this);
+ }
+ return;
+ }
+
+ if (!tempStyle.length) {
+ // The user typed something, but it didn't parse. Just abort and restore
+ // the original title for this property.
+ if (updateInterface)
+ this.updateTitle();
+ return;
+ }
+
+ // Iterate of the properties on the test element's style declaration and
+ // add them to the real style declaration. We take care to move shorthands.
+ var foundShorthands = {};
+ var uniqueProperties = getUniqueStyleProperties(tempStyle);
+ for (var i = 0; i < uniqueProperties.length; ++i) {
+ var name = uniqueProperties[i];
+ var shorthand = tempStyle.getPropertyShorthand(name);
+
+ if (shorthand && shorthand in foundShorthands)
+ continue;
+
+ if (shorthand) {
+ var value = getShorthandValue(tempStyle, shorthand);
+ var priority = getShorthandPriority(tempStyle, shorthand);
+ foundShorthands[shorthand] = true;
+ } else {
+ var value = tempStyle.getPropertyValue(name);
+ var priority = tempStyle.getPropertyPriority(name);
+ }
+
+ // Set the property on the real style declaration.
+ this.style.setProperty((shorthand || name), value, priority);
+ }
+
+ if (this.treeOutline.section && this.treeOutline.section.pane)
+ this.treeOutline.section.pane.dispatchEventToListeners("style edited");
+
+ if (updateInterface)
+ this.updateAll(true);
+ }
+}
+
+WebInspector.StylePropertyTreeElement.prototype.__proto__ = TreeElement.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/TextPrompt.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/TextPrompt.js
new file mode 100644
index 0000000..61e1b52db
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/TextPrompt.js
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TextPrompt = function(element, completions, stopCharacters)
+{
+ this.element = element;
+ this.completions = completions;
+ this.completionStopCharacters = stopCharacters;
+ this.history = [];
+ this.historyOffset = 0;
+}
+
+WebInspector.TextPrompt.prototype = {
+ get text()
+ {
+ return this.element.textContent;
+ },
+
+ set text(x)
+ {
+ if (!x) {
+ // Append a break element instead of setting textContent to make sure the selection is inside the prompt.
+ this.element.removeChildren();
+ this.element.appendChild(document.createElement("br"));
+ } else
+ this.element.textContent = x;
+
+ this.moveCaretToEndOfPrompt();
+ },
+
+ handleKeyEvent: function(event)
+ {
+ switch (event.keyIdentifier) {
+ case "Up":
+ this._upKeyPressed(event);
+ break;
+ case "Down":
+ this._downKeyPressed(event);
+ break;
+ case "U+0009": // Tab
+ this._tabKeyPressed(event);
+ break;
+ case "Right":
+ if (!this.acceptAutoComplete())
+ this.autoCompleteSoon();
+ break;
+ default:
+ this.clearAutoComplete();
+ this.autoCompleteSoon();
+ break;
+ }
+ },
+
+ acceptAutoComplete: function()
+ {
+ if (!this.autoCompleteElement || !this.autoCompleteElement.parentNode)
+ return false;
+
+ var text = this.autoCompleteElement.textContent;
+ var textNode = document.createTextNode(text);
+ this.autoCompleteElement.parentNode.replaceChild(textNode, this.autoCompleteElement);
+ delete this.autoCompleteElement;
+
+ var finalSelectionRange = document.createRange();
+ finalSelectionRange.setStart(textNode, text.length);
+ finalSelectionRange.setEnd(textNode, text.length);
+
+ var selection = window.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(finalSelectionRange);
+
+ return true;
+ },
+
+ clearAutoComplete: function(includeTimeout)
+ {
+ if (includeTimeout && "_completeTimeout" in this) {
+ clearTimeout(this._completeTimeout);
+ delete this._completeTimeout;
+ }
+
+ if (!this.autoCompleteElement)
+ return;
+
+ if (this.autoCompleteElement.parentNode)
+ this.autoCompleteElement.parentNode.removeChild(this.autoCompleteElement);
+ delete this.autoCompleteElement;
+
+ if (!this._userEnteredRange || !this._userEnteredText)
+ return;
+
+ this._userEnteredRange.deleteContents();
+
+ var userTextNode = document.createTextNode(this._userEnteredText);
+ this._userEnteredRange.insertNode(userTextNode);
+
+ var selectionRange = document.createRange();
+ selectionRange.setStart(userTextNode, this._userEnteredText.length);
+ selectionRange.setEnd(userTextNode, this._userEnteredText.length);
+
+ var selection = window.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(selectionRange);
+
+ delete this._userEnteredRange;
+ delete this._userEnteredText;
+ },
+
+ autoCompleteSoon: function()
+ {
+ if (!("_completeTimeout" in this))
+ this._completeTimeout = setTimeout(this.complete.bind(this, true), 250);
+ },
+
+ complete: function(auto)
+ {
+ this.clearAutoComplete(true);
+
+ var selection = window.getSelection();
+ if (!selection.rangeCount)
+ return;
+
+ var selectionRange = selection.getRangeAt(0);
+ if (!selectionRange.commonAncestorContainer.isDescendant(this.element))
+ return;
+ if (auto && !this.isCaretAtEndOfPrompt())
+ return;
+
+ var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, this.completionStopCharacters, this.element, "backward");
+ var completions = this.completions(wordPrefixRange, auto);
+
+ if (!completions || !completions.length)
+ return;
+
+ var fullWordRange = document.createRange();
+ fullWordRange.setStart(wordPrefixRange.startContainer, wordPrefixRange.startOffset);
+ fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffset);
+
+ if (completions.length === 1 || selection.isCollapsed || auto) {
+ var completionText = completions[0];
+ } else {
+ var currentText = fullWordRange.toString();
+
+ var foundIndex = null;
+ for (var i = 0; i < completions.length; ++i) {
+ if (completions[i] === currentText)
+ foundIndex = i;
+ }
+
+ if (foundIndex === null || (foundIndex + 1) >= completions.length)
+ var completionText = completions[0];
+ else
+ var completionText = completions[foundIndex + 1];
+ }
+
+ var wordPrefixLength = wordPrefixRange.toString().length;
+
+ this._userEnteredRange = fullWordRange;
+ this._userEnteredText = fullWordRange.toString();
+
+ fullWordRange.deleteContents();
+
+ var finalSelectionRange = document.createRange();
+
+ if (auto) {
+ var prefixText = completionText.substring(0, wordPrefixLength);
+ var suffixText = completionText.substring(wordPrefixLength);
+
+ var prefixTextNode = document.createTextNode(prefixText);
+ fullWordRange.insertNode(prefixTextNode);
+
+ this.autoCompleteElement = document.createElement("span");
+ this.autoCompleteElement.className = "auto-complete-text";
+ this.autoCompleteElement.textContent = suffixText;
+
+ prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, prefixTextNode.nextSibling);
+
+ finalSelectionRange.setStart(prefixTextNode, wordPrefixLength);
+ finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength);
+ } else {
+ var completionTextNode = document.createTextNode(completionText);
+ fullWordRange.insertNode(completionTextNode);
+
+ if (completions.length > 1)
+ finalSelectionRange.setStart(completionTextNode, wordPrefixLength);
+ else
+ finalSelectionRange.setStart(completionTextNode, completionText.length);
+
+ finalSelectionRange.setEnd(completionTextNode, completionText.length);
+ }
+
+ selection.removeAllRanges();
+ selection.addRange(finalSelectionRange);
+ },
+
+ isCaretInsidePrompt: function()
+ {
+ return this.element.isInsertionCaretInside();
+ },
+
+ isCaretAtEndOfPrompt: function()
+ {
+ var selection = window.getSelection();
+ if (!selection.rangeCount || !selection.isCollapsed)
+ return false;
+
+ var selectionRange = selection.getRangeAt(0);
+ var node = selectionRange.startContainer;
+ if (node !== this.element && !node.isDescendant(this.element))
+ return false;
+
+ if (node.nodeType === Node.TEXT_NODE && selectionRange.startOffset < node.nodeValue.length)
+ return false;
+
+ var foundNextText = false;
+ while (node) {
+ if (node.nodeType === Node.TEXT_NODE && node.nodeValue.length) {
+ if (foundNextText)
+ return false;
+ foundNextText = true;
+ }
+
+ node = node.traverseNextNode(false, this.element);
+ }
+
+ return true;
+ },
+
+ moveCaretToEndOfPrompt: function()
+ {
+ var selection = window.getSelection();
+ var selectionRange = document.createRange();
+
+ var offset = this.element.childNodes.length;
+ selectionRange.setStart(this.element, offset);
+ selectionRange.setEnd(this.element, offset);
+
+ selection.removeAllRanges();
+ selection.addRange(selectionRange);
+ },
+
+ _tabKeyPressed: function(event)
+ {
+ event.preventDefault();
+ event.stopPropagation();
+
+ this.complete();
+ },
+
+ _upKeyPressed: function(event)
+ {
+ event.preventDefault();
+ event.stopPropagation();
+
+ if (this.historyOffset == this.history.length)
+ return;
+
+ this.clearAutoComplete(true);
+
+ if (this.historyOffset == 0)
+ this.tempSavedCommand = this.text;
+
+ ++this.historyOffset;
+ this.text = this.history[this.history.length - this.historyOffset];
+ },
+
+ _downKeyPressed: function(event)
+ {
+ event.preventDefault();
+ event.stopPropagation();
+
+ if (this.historyOffset == 0)
+ return;
+
+ this.clearAutoComplete(true);
+
+ --this.historyOffset;
+
+ if (this.historyOffset == 0) {
+ this.text = this.tempSavedCommand;
+ delete this.tempSavedCommand;
+ return;
+ }
+
+ this.text = this.history[this.history.length - this.historyOffset];
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/TopDownProfileDataGridTree.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/TopDownProfileDataGridTree.js
new file mode 100644
index 0000000..b9d8b94
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/TopDownProfileDataGridTree.js
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2009 280 North Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TopDownProfileDataGridNode = function(/*ProfileView*/ profileView, /*ProfileNode*/ profileNode, /*TopDownProfileDataGridTree*/ owningTree)
+{
+ var hasChildren = (profileNode.children && profileNode.children.length);
+
+ WebInspector.ProfileDataGridNode.call(this, profileView, profileNode, owningTree, hasChildren);
+
+ this._remainingChildren = profileNode.children;
+}
+
+WebInspector.TopDownProfileDataGridNode.prototype = {
+ _populate: function(event)
+ {
+ var children = this._remainingChildren;
+ var childrenLength = children.length;
+
+ for (var i = 0; i < childrenLength; ++i)
+ this.appendChild(new WebInspector.TopDownProfileDataGridNode(this.profileView, children[i], this.tree));
+
+ if (this.removeEventListener)
+ this.removeEventListener("populate", this._populate, this);
+
+ this._remainingChildren = null;
+ },
+
+ _exclude: function(aCallUID)
+ {
+ if (this._remainingChildren)
+ this._populate();
+
+ this._save();
+
+ var children = this.children;
+ var index = this.children.length;
+
+ while (index--)
+ children[index]._exclude(aCallUID);
+
+ var child = this.childrenByCallUID[aCallUID];
+
+ if (child)
+ this._merge(child, true);
+ }
+}
+
+WebInspector.TopDownProfileDataGridNode.prototype.__proto__ = WebInspector.ProfileDataGridNode.prototype;
+
+WebInspector.TopDownProfileDataGridTree = function(/*ProfileView*/ profileView, /*ProfileNode*/ profileNode)
+{
+ WebInspector.ProfileDataGridTree.call(this, profileView, profileNode);
+
+ this._remainingChildren = profileNode.children;
+
+ WebInspector.TopDownProfileDataGridNode.prototype._populate.call(this);
+}
+
+WebInspector.TopDownProfileDataGridTree.prototype = {
+ focus: function(/*ProfileDataGridNode*/ profileDataGrideNode)
+ {
+ if (!profileDataGrideNode)
+ return;
+
+ this._save();
+
+ this.children = [profileDataGrideNode];
+ this.totalTime = profileDataGrideNode.totalTime;
+ },
+
+ exclude: function(/*ProfileDataGridNode*/ profileDataGrideNode)
+ {
+ if (!profileDataGrideNode)
+ return;
+
+ this._save();
+
+ var excludedCallUID = profileDataGrideNode.callUID;
+
+ WebInspector.TopDownProfileDataGridNode.prototype._exclude.call(this, excludedCallUID);
+
+ if (this.lastComparator)
+ this.sort(this.lastComparator, true);
+ },
+
+ _merge: WebInspector.TopDownProfileDataGridNode.prototype._merge
+}
+
+WebInspector.TopDownProfileDataGridTree.prototype.__proto__ = WebInspector.ProfileDataGridTree.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/View.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/View.js
new file mode 100644
index 0000000..632a61ae
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/View.js
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.View = function(element)
+{
+ this.element = element || document.createElement("div");
+ this._visible = false;
+}
+
+WebInspector.View.prototype = {
+ get visible()
+ {
+ return this._visible;
+ },
+
+ set visible(x)
+ {
+ if (this._visible === x)
+ return;
+
+ if (x)
+ this.show();
+ else
+ this.hide();
+ },
+
+ show: function(parentElement)
+ {
+ this._visible = true;
+ if (parentElement && parentElement !== this.element.parentNode) {
+ this.detach();
+ parentElement.appendChild(this.element);
+ }
+ if (!this.element.parentNode && this.attach)
+ this.attach();
+ this.element.addStyleClass("visible");
+ },
+
+ hide: function()
+ {
+ this.element.removeStyleClass("visible");
+ this._visible = false;
+ },
+
+ detach: function()
+ {
+ if (this.element.parentNode)
+ this.element.parentNode.removeChild(this.element);
+ }
+}
+
+WebInspector.View.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/base.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/base.js
new file mode 100644
index 0000000..8f029a1
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/base.js
@@ -0,0 +1,1015 @@
+// Copyright 2006 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.
+//
+// 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.
+
+// NOTE: This file has been changed from the one on doctype. The following
+// changes were made:
+// - Removed goog.globalEval because it calls eval() which is not allowed from
+// inside v8 extensions. If we ever need to use globalEval, we will need to
+// find a way to work around this problem.
+// - Remove Function.prototype.apply() emulation for the same reason. This one
+// is useless anyway because V8 supports apply() natively.
+
+/**
+ * @fileoverview Bootstrap for the Google JS Library
+ */
+
+/**
+ * @define {boolean} Overridden to true by the compiler when
+ * --mark_as_compiled is specified.
+ */
+var COMPILED = true;
+
+
+/**
+ * Base namespace for the Google JS library. Checks to see goog is
+ * already defined in the current scope before assigning to prevent
+ * clobbering if base.js is loaded more than once.
+ */
+var goog = {}; // Check to see if already defined in current scope
+
+
+/**
+ * Reference to the global context. In most cases this will be 'window'.
+ */
+goog.global = this;
+
+
+/**
+ * Indicates whether or not we can call 'eval' directly to eval code in the
+ * global scope. Set to a Boolean by the first call to goog.globalEval (which
+ * empirically tests whether eval works for globals). @see goog.globalEval
+ * @type {boolean?}
+ * @private
+ */
+goog.evalWorksForGlobals_ = null;
+
+
+/**
+ * Creates object stubs for a namespace. When present in a file, goog.provide
+ * also indicates that the file defines the indicated object.
+ * @param {string} name name of the object that this file defines.
+ */
+goog.provide = function(name) {
+ if (!COMPILED) {
+ // Ensure that the same namespace isn't provided twice. This is intended
+ // to teach new developers that 'goog.provide' is effectively a variable
+ // declaration. And when JSCompiler transforms goog.provide into a real
+ // variable declaration, the compiled JS should work the same as the raw
+ // JS--even when the raw JS uses goog.provide incorrectly.
+ if (goog.getObjectByName(name) && !goog.implicitNamespaces_[name]) {
+ throw 'Namespace "' + name + '" already declared.';
+ }
+
+ var namespace = name;
+ while ((namespace = namespace.substr(0, namespace.lastIndexOf('.')))) {
+ goog.implicitNamespaces_[namespace] = true;
+ }
+ }
+
+ goog.exportPath_(name);
+};
+
+
+if (!COMPILED) {
+ /**
+ * Namespaces implicitly defined by goog.provide. For example,
+ * goog.provide('goog.events.Event') implicitly declares
+ * that 'goog' and 'goog.events' must be namespaces.
+ *
+ * @type {Object}
+ * @private
+ */
+ goog.implicitNamespaces_ = {};
+}
+
+
+/**
+ * Builds an object structure for the provided namespace path,
+ * ensuring that names that already exist are not overwritten. For
+ * example:
+ * "a.b.c" -> a = {};a.b={};a.b.c={};
+ * Used by goog.provide and goog.exportSymbol.
+ * @param {string} name name of the object that this file defines.
+ * @param {Object} opt_object the object to expose at the end of the path.
+ * @private
+ */
+goog.exportPath_ = function(name, opt_object) {
+ var parts = name.split('.');
+ var cur = goog.global;
+ var part;
+
+ // Internet Explorer exhibits strange behavior when throwing errors from
+ // methods externed in this manner. See the testExportSymbolExceptions in
+ // base_test.html for an example.
+ if (!(parts[0] in cur) && cur.execScript) {
+ cur.execScript('var ' + parts[0]);
+ }
+
+ // Parentheses added to eliminate strict JS warning in Firefox.
+ while ((part = parts.shift())) {
+ if (!parts.length && goog.isDef(opt_object)) {
+ // last part and we have an object; use it
+ cur[part] = opt_object;
+ } else if (cur[part]) {
+ cur = cur[part];
+ } else {
+ cur = cur[part] = {};
+ }
+ }
+};
+
+
+/**
+ * Returns an object based on its fully qualified name
+ * @param {string} name The fully qualified name.
+ * @return {Object?} The object or, if not found, null.
+ */
+goog.getObjectByName = function(name) {
+ var parts = name.split('.');
+ var cur = goog.global;
+ for (var part; part = parts.shift(); ) {
+ if (cur[part]) {
+ cur = cur[part];
+ } else {
+ return null;
+ }
+ }
+ return cur;
+};
+
+
+/**
+ * Globalizes a whole namespace, such as goog or goog.lang.
+ *
+ * @param {Object} obj The namespace to globalize.
+ * @param {Object} opt_global The object to add the properties to.
+ * @deprecated Properties may be explicitly exported to the global scope, but
+ * this should no longer be done in bulk.
+ */
+goog.globalize = function(obj, opt_global) {
+ var global = opt_global || goog.global;
+ for (var x in obj) {
+ global[x] = obj[x];
+ }
+};
+
+
+/**
+ * Adds a dependency from a file to the files it requires.
+ * @param {string} relPath The path to the js file.
+ * @param {Array} provides An array of strings with the names of the objects
+ * this file provides.
+ * @param {Array} requires An array of strings with the names of the objects
+ * this file requires.
+ */
+goog.addDependency = function(relPath, provides, requires) {
+ if (!COMPILED) {
+ var provide, require;
+ var path = relPath.replace(/\\/g, '/');
+ var deps = goog.dependencies_;
+ for (var i = 0; provide = provides[i]; i++) {
+ deps.nameToPath[provide] = path;
+ if (!(path in deps.pathToNames)) {
+ deps.pathToNames[path] = {};
+ }
+ deps.pathToNames[path][provide] = true;
+ }
+ for (var j = 0; require = requires[j]; j++) {
+ if (!(path in deps.requires)) {
+ deps.requires[path] = {};
+ }
+ deps.requires[path][require] = true;
+ }
+ }
+};
+
+
+/**
+ * Implements a system for the dynamic resolution of dependencies
+ * that works in parallel with the BUILD system.
+ * @param {string} rule Rule to include, in the form goog.package.part.
+ */
+goog.require = function(rule) {
+
+ // if the object already exists we do not need do do anything
+ if (!COMPILED) {
+ if (goog.getObjectByName(rule)) {
+ return;
+ }
+ var path = goog.getPathFromDeps_(rule);
+ if (path) {
+ goog.included_[path] = true;
+ goog.writeScripts_();
+ } else {
+ // NOTE(nicksantos): We could throw an error, but this would break
+ // legacy users that depended on this failing silently. Instead, the
+ // compiler should warn us when there are invalid goog.require calls.
+ }
+ }
+};
+
+
+/**
+ * Path for included scripts
+ * @type {string}
+ */
+goog.basePath = '';
+
+
+/**
+ * Null function used for default values of callbacks, etc.
+ * @type {Function}
+ */
+goog.nullFunction = function() {};
+
+
+/**
+ * When defining a class Foo with an abstract method bar(), you can do:
+ *
+ * Foo.prototype.bar = goog.abstractMethod
+ *
+ * Now if a subclass of Foo fails to override bar(), an error
+ * will be thrown when bar() is invoked.
+ *
+ * Note: This does not take the name of the function to override as
+ * an argument because that would make it more difficult to obfuscate
+ * our JavaScript code.
+ *
+ * @throws {Error} when invoked to indicate the method should be
+ * overridden.
+ */
+goog.abstractMethod = function() {
+ throw Error('unimplemented abstract method');
+};
+
+
+if (!COMPILED) {
+ /**
+ * Object used to keep track of urls that have already been added. This
+ * record allows the prevention of circular dependencies.
+ * @type {Object}
+ * @private
+ */
+ goog.included_ = {};
+
+
+ /**
+ * This object is used to keep track of dependencies and other data that is
+ * used for loading scripts
+ * @private
+ * @type {Object}
+ */
+ goog.dependencies_ = {
+ pathToNames: {}, // 1 to many
+ nameToPath: {}, // 1 to 1
+ requires: {}, // 1 to many
+ visited: {}, // used when resolving dependencies to prevent us from
+ // visiting the file twice
+ written: {} // used to keep track of script files we have written
+ };
+
+
+ /**
+ * Tries to detect the base path of the base.js script that bootstraps
+ * Google JS Library
+ * @private
+ */
+ goog.findBasePath_ = function() {
+ var doc = goog.global.document;
+ if (typeof doc == 'undefined') {
+ return;
+ }
+ if (goog.global.GOOG_BASE_PATH) {
+ goog.basePath = goog.global.GOOG_BASE_PATH;
+ return;
+ } else {
+ goog.global.GOOG_BASE_PATH = null;
+ }
+ var scripts = doc.getElementsByTagName('script');
+ for (var script, i = 0; script = scripts[i]; i++) {
+ var src = script.src;
+ var l = src.length;
+ if (src.substr(l - 7) == 'base.js') {
+ goog.basePath = src.substr(0, l - 7);
+ return;
+ }
+ }
+ };
+
+
+ /**
+ * Writes a script tag if, and only if, that script hasn't already been added
+ * to the document. (Must be called at execution time)
+ * @param {string} src Script source.
+ * @private
+ */
+ goog.writeScriptTag_ = function(src) {
+ var doc = goog.global.document;
+ if (typeof doc != 'undefined' &&
+ !goog.dependencies_.written[src]) {
+ goog.dependencies_.written[src] = true;
+ doc.write('<script type="text/javascript" src="' +
+ src + '"></' + 'script>');
+ }
+ };
+
+
+ /**
+ * Resolves dependencies based on the dependencies added using addDependency
+ * and calls writeScriptTag_ in the correct order.
+ * @private
+ */
+ goog.writeScripts_ = function() {
+ // the scripts we need to write this time
+ var scripts = [];
+ var seenScript = {};
+ var deps = goog.dependencies_;
+
+ function visitNode(path) {
+ if (path in deps.written) {
+ return;
+ }
+
+ // we have already visited this one. We can get here if we have cyclic
+ // dependencies
+ if (path in deps.visited) {
+ if (!(path in seenScript)) {
+ seenScript[path] = true;
+ scripts.push(path);
+ }
+ return;
+ }
+
+ deps.visited[path] = true;
+
+ if (path in deps.requires) {
+ for (var requireName in deps.requires[path]) {
+ visitNode(deps.nameToPath[requireName]);
+ }
+ }
+
+ if (!(path in seenScript)) {
+ seenScript[path] = true;
+ scripts.push(path);
+ }
+ }
+
+ for (var path in goog.included_) {
+ if (!deps.written[path]) {
+ visitNode(path);
+ }
+ }
+
+ for (var i = 0; i < scripts.length; i++) {
+ if (scripts[i]) {
+ goog.writeScriptTag_(goog.basePath + scripts[i]);
+ } else {
+ throw Error('Undefined script input');
+ }
+ }
+ };
+
+
+ /**
+ * Looks at the dependency rules and tries to determine the script file that
+ * fulfills a particular rule.
+ * @param {string} rule In the form goog.namespace.Class or project.script.
+ * @return {string?} Url corresponding to the rule, or null.
+ * @private
+ */
+ goog.getPathFromDeps_ = function(rule) {
+ if (rule in goog.dependencies_.nameToPath) {
+ return goog.dependencies_.nameToPath[rule];
+ } else {
+ return null;
+ }
+ };
+
+ goog.findBasePath_();
+ goog.writeScriptTag_(goog.basePath + 'deps.js');
+}
+
+
+
+//==============================================================================
+// Language Enhancements
+//==============================================================================
+
+
+/**
+ * This is a "fixed" version of the typeof operator. It differs from the typeof
+ * operator in such a way that null returns 'null' and arrays return 'array'.
+ * @param {*} value The value to get the type of.
+ * @return {string} The name of the type.
+ */
+goog.typeOf = function(value) {
+ var s = typeof value;
+ if (s == 'object') {
+ if (value) {
+ // We cannot use constructor == Array or instanceof Array because
+ // different frames have different Array objects. In IE6, if the iframe
+ // where the array was created is destroyed, the array loses its
+ // prototype. Then dereferencing val.splice here throws an exception, so
+ // we can't use goog.isFunction. Calling typeof directly returns 'unknown'
+ // so that will work. In this case, this function will return false and
+ // most array functions will still work because the array is still
+ // array-like (supports length and []) even though it has lost its
+ // prototype. Custom object cannot have non enumerable length and
+ // NodeLists don't have a slice method.
+ if (typeof value.length == 'number' &&
+ typeof value.splice != 'undefined' &&
+ !goog.propertyIsEnumerable_(value, 'length')) {
+ return 'array';
+ }
+
+ // IE in cross-window calls does not correctly marshal the function type
+ // (it appears just as an object) so we cannot use just typeof val ==
+ // 'function'. However, if the object has a call property, it is a
+ // function.
+ if (typeof value.call != 'undefined') {
+ return 'function';
+ }
+ } else {
+ return 'null';
+ }
+
+ // In Safari typeof nodeList returns function. We would like to return
+ // object for those and we can detect an invalid function by making sure that
+ // the function object has a call method
+ } else if (s == 'function' && typeof value.call == 'undefined') {
+ return 'object';
+ }
+ return s;
+};
+
+if (Object.prototype.propertyIsEnumerable) {
+ /**
+ * Safe way to test whether a property is enumarable. It allows testing
+ * for enumarable on objects where 'propertyIsEnumerable' is overridden or
+ * does not exist (like DOM nodes in IE).
+ * @param {Object} object The object to test if the property is enumerable.
+ * @param {string} propName The property name to check for.
+ * @return {boolean} True if the property is enumarable.
+ * @private
+ */
+ goog.propertyIsEnumerable_ = function(object, propName) {
+ return Object.prototype.propertyIsEnumerable.call(object, propName);
+ };
+} else {
+ /**
+ * Safe way to test whether a property is enumarable. It allows testing
+ * for enumarable on objects where 'propertyIsEnumerable' is overridden or
+ * does not exist (like DOM nodes in IE).
+ * @param {Object} object The object to test if the property is enumerable.
+ * @param {string} propName The property name to check for.
+ * @return {boolean} True if the property is enumarable.
+ * @private
+ */
+ goog.propertyIsEnumerable_ = function(object, propName) {
+ // KJS in Safari 2 is not ECMAScript compatible and lacks crucial methods
+ // such as propertyIsEnumerable. We therefore use a workaround.
+ // Does anyone know a more efficient work around?
+ if (propName in object) {
+ for (var key in object) {
+ if (key == propName) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+}
+
+/**
+ * Returns true if the specified value is not |undefined|.
+ * WARNING: Do not use this to test if an object has a property. Use the in
+ * operator instead.
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is defined.
+ */
+goog.isDef = function(val) {
+ return typeof val != 'undefined';
+};
+
+
+/**
+ * Returns true if the specified value is |null|
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is null.
+ */
+goog.isNull = function(val) {
+ return val === null;
+};
+
+
+/**
+ * Returns true if the specified value is defined and not null
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is defined and not null.
+ */
+goog.isDefAndNotNull = function(val) {
+ return goog.isDef(val) && !goog.isNull(val);
+};
+
+
+/**
+ * Returns true if the specified value is an array
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is an array.
+ */
+goog.isArray = function(val) {
+ return goog.typeOf(val) == 'array';
+};
+
+
+/**
+ * Returns true if the object looks like an array. To qualify as array like
+ * the value needs to be either a NodeList or an object with a Number length
+ * property.
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is an array.
+ */
+goog.isArrayLike = function(val) {
+ var type = goog.typeOf(val);
+ return type == 'array' || type == 'object' && typeof val.length == 'number';
+};
+
+
+/**
+ * Returns true if the object looks like a Date. To qualify as Date-like
+ * the value needs to be an object and have a getFullYear() function.
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is a like a Date.
+ */
+goog.isDateLike = function(val) {
+ return goog.isObject(val) && typeof val.getFullYear == 'function';
+};
+
+
+/**
+ * Returns true if the specified value is a string
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is a string.
+ */
+goog.isString = function(val) {
+ return typeof val == 'string';
+};
+
+
+/**
+ * Returns true if the specified value is a boolean
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is boolean.
+ */
+goog.isBoolean = function(val) {
+ return typeof val == 'boolean';
+};
+
+
+/**
+ * Returns true if the specified value is a number
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is a number.
+ */
+goog.isNumber = function(val) {
+ return typeof val == 'number';
+};
+
+
+/**
+ * Returns true if the specified value is a function
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is a function.
+ */
+goog.isFunction = function(val) {
+ return goog.typeOf(val) == 'function';
+};
+
+
+/**
+ * Returns true if the specified value is an object. This includes arrays
+ * and functions.
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is an object.
+ */
+goog.isObject = function(val) {
+ var type = goog.typeOf(val);
+ return type == 'object' || type == 'array' || type == 'function';
+};
+
+
+/**
+ * Adds a hash code field to an object. The hash code is unique for the
+ * given object.
+ * @param {Object} obj The object to get the hash code for.
+ * @return {number} The hash code for the object.
+ */
+goog.getHashCode = function(obj) {
+ // In IE, DOM nodes do not extend Object so they do not have this method.
+ // we need to check hasOwnProperty because the proto might have this set.
+
+ if (obj.hasOwnProperty && obj.hasOwnProperty(goog.HASH_CODE_PROPERTY_)) {
+ return obj[goog.HASH_CODE_PROPERTY_];
+ }
+ if (!obj[goog.HASH_CODE_PROPERTY_]) {
+ obj[goog.HASH_CODE_PROPERTY_] = ++goog.hashCodeCounter_;
+ }
+ return obj[goog.HASH_CODE_PROPERTY_];
+};
+
+
+/**
+ * Removes the hash code field from an object.
+ * @param {Object} obj The object to remove the field from.
+ */
+goog.removeHashCode = function(obj) {
+ // DOM nodes in IE are not instance of Object and throws exception
+ // for delete. Instead we try to use removeAttribute
+ if ('removeAttribute' in obj) {
+ obj.removeAttribute(goog.HASH_CODE_PROPERTY_);
+ }
+ /** @preserveTry */
+ try {
+ delete obj[goog.HASH_CODE_PROPERTY_];
+ } catch (ex) {
+ }
+};
+
+
+/**
+ * {String} Name for hash code property
+ * @private
+ */
+goog.HASH_CODE_PROPERTY_ = 'goog_hashCode_';
+
+
+/**
+ * @type {number} Counter for hash codes.
+ * @private
+ */
+goog.hashCodeCounter_ = 0;
+
+
+/**
+ * Clone an object/array (recursively)
+ * @param {Object} proto Object to clone.
+ * @return {Object} Clone of x;.
+ */
+goog.cloneObject = function(proto) {
+ var type = goog.typeOf(proto);
+ if (type == 'object' || type == 'array') {
+ if (proto.clone) {
+ return proto.clone();
+ }
+ var clone = type == 'array' ? [] : {};
+ for (var key in proto) {
+ clone[key] = goog.cloneObject(proto[key]);
+ }
+ return clone;
+ }
+
+ return proto;
+};
+
+
+/**
+ * Partially applies this function to a particular 'this object' and zero or
+ * more arguments. The result is a new function with some arguments of the first
+ * function pre-filled and the value of |this| 'pre-specified'.<br><br>
+ *
+ * Remaining arguments specified at call-time are appended to the pre-
+ * specified ones.<br><br>
+ *
+ * Also see: {@link #partial}.<br><br>
+ *
+ * Note that bind and partial are optimized such that repeated calls to it do
+ * not create more than one function object, so there is no additional cost for
+ * something like:<br>
+ *
+ * <pre>var g = bind(f, obj);
+ * var h = partial(g, 1, 2, 3);
+ * var k = partial(h, a, b, c);</pre>
+ *
+ * Usage:
+ * <pre>var barMethBound = bind(myFunction, myObj, 'arg1', 'arg2');
+ * barMethBound('arg3', 'arg4');</pre>
+ *
+ * @param {Function} fn A function to partially apply.
+ * @param {Object} self Specifies the object which |this| should point to
+ * when the function is run. If the value is null or undefined, it will
+ * default to the global object.
+ * @param {Object} var_args Additional arguments that are partially
+ * applied to the function.
+ *
+ * @return {Function} A partially-applied form of the function bind() was
+ * invoked as a method of.
+ */
+goog.bind = function(fn, self, var_args) {
+ var boundArgs = fn.boundArgs_;
+
+ if (arguments.length > 2) {
+ var args = Array.prototype.slice.call(arguments, 2);
+ if (boundArgs) {
+ args.unshift.apply(args, boundArgs);
+ }
+ boundArgs = args;
+ }
+
+ self = fn.boundSelf_ || self;
+ fn = fn.boundFn_ || fn;
+
+ var newfn;
+ var context = self || goog.global;
+
+ if (boundArgs) {
+ newfn = function() {
+ // Combine the static args and the new args into one big array
+ var args = Array.prototype.slice.call(arguments);
+ args.unshift.apply(args, boundArgs);
+ return fn.apply(context, args);
+ }
+ } else {
+ newfn = function() {
+ return fn.apply(context, arguments);
+ }
+ }
+
+ newfn.boundArgs_ = boundArgs;
+ newfn.boundSelf_ = self;
+ newfn.boundFn_ = fn;
+
+ return newfn;
+};
+
+
+/**
+ * Like bind(), except that a 'this object' is not required. Useful when the
+ * target function is already bound.
+ *
+ * Usage:
+ * var g = partial(f, arg1, arg2);
+ * g(arg3, arg4);
+ *
+ * @param {Function} fn A function to partially apply.
+ * @param {Object} var_args Additional arguments that are partially
+ * applied to fn.
+ * @return {Function} A partially-applied form of the function bind() was
+ * invoked as a method of.
+ */
+goog.partial = function(fn, var_args) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ args.unshift(fn, null);
+ return goog.bind.apply(null, args);
+};
+
+
+/**
+ * Copies all the members of a source object to a target object.
+ * This is deprecated. Use goog.object.extend instead.
+ * @param {Object} target Target.
+ * @param {Object} source Source.
+ * @deprecated
+ */
+goog.mixin = function(target, source) {
+ for (var x in source) {
+ target[x] = source[x];
+ }
+
+ // For IE the for-in-loop does not contain any properties that are not
+ // enumerable on the prototype object (for example, isPrototypeOf from
+ // Object.prototype) but also it will not include 'replace' on objects that
+ // extend String and change 'replace' (not that it is common for anyone to
+ // extend anything except Object).
+};
+
+
+/**
+ * A simple wrapper for new Date().getTime().
+ *
+ * @return {number} An integer value representing the number of milliseconds
+ * between midnight, January 1, 1970 and the current time.
+ */
+goog.now = Date.now || (function() {
+ return new Date().getTime();
+});
+
+
+/**
+ * Abstract implementation of goog.getMsg for use with localized messages
+ * @param {string} str Translatable string, places holders in the form.{$foo}
+ * @param {Object} opt_values Map of place holder name to value.
+ */
+goog.getMsg = function(str, opt_values) {
+ var values = opt_values || {};
+ for (var key in values) {
+ str = str.replace(new RegExp('\\{\\$' + key + '\\}', 'gi'), values[key]);
+ }
+ return str;
+};
+
+
+/**
+ * Exposes an unobfuscated global namespace path for the given object.
+ * Note that fields of the exported object *will* be obfuscated,
+ * unless they are exported in turn via this function or
+ * goog.exportProperty
+ *
+ * <p>Also handy for making public items that are defined in anonymous
+ * closures.
+ *
+ * ex. goog.exportSymbol('Foo', Foo);
+ *
+ * ex. goog.exportSymbol('public.path.Foo.staticFunction',
+ * Foo.staticFunction);
+ * public.path.Foo.staticFunction();
+ *
+ * ex. goog.exportSymbol('public.path.Foo.prototype.myMethod',
+ * Foo.prototype.myMethod);
+ * new public.path.Foo().myMethod();
+ *
+ * @param {string} publicPath Unobfuscated name to export.
+ * @param {Object} object Object the name should point to.
+ */
+goog.exportSymbol = function(publicPath, object) {
+ goog.exportPath_(publicPath, object);
+};
+
+
+/**
+ * Exports a property unobfuscated into the object's namespace.
+ * ex. goog.exportProperty(Foo, 'staticFunction', Foo.staticFunction);
+ * ex. goog.exportProperty(Foo.prototype, 'myMethod', Foo.prototype.myMethod);
+ * @param {Object} object Object whose static property is being exported.
+ * @param {string} publicName Unobfuscated name to export.
+ * @param {Object} symbol Object the name should point to.
+ */
+goog.exportProperty = function(object, publicName, symbol) {
+ object[publicName] = symbol;
+};
+
+
+
+//==============================================================================
+// Extending Function
+//==============================================================================
+
+
+/**
+ * An alias to the {@link goog.bind()} global function.
+ *
+ * Usage:
+ * var g = f.bind(obj, arg1, arg2);
+ * g(arg3, arg4);
+ *
+ * @param {Object} self Specifies the object to which |this| should point
+ * when the function is run. If the value is null or undefined, it will
+ * default to the global object.
+ * @param {Object} var_args Additional arguments that are partially
+ * applied to fn.
+ * @return {Function} A partially-applied form of the Function on which bind()
+ * was invoked as a method.
+ * @deprecated
+ */
+Function.prototype.bind = function(self, var_args) {
+ if (arguments.length > 1) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ args.unshift(this, self);
+ return goog.bind.apply(null, args);
+ } else {
+ return goog.bind(this, self);
+ }
+};
+
+
+/**
+ * An alias to the {@link goog.partial()} global function.
+ *
+ * Usage:
+ * var g = f.partial(arg1, arg2);
+ * g(arg3, arg4);
+ *
+ * @param {Object} var_args Additional arguments that are partially
+ * applied to fn.
+ * @return {Function} A partially-applied form of the function partial() was
+ * invoked as a method of.
+ * @deprecated
+ */
+Function.prototype.partial = function(var_args) {
+ var args = Array.prototype.slice.call(arguments);
+ args.unshift(this, null);
+ return goog.bind.apply(null, args);
+};
+
+
+/**
+ * Inherit the prototype methods from one constructor into another.
+ *
+ * Usage:
+ * <pre>
+ * function ParentClass(a, b) { }
+ * ParentClass.prototype.foo = function(a) { }
+ *
+ * function ChildClass(a, b, c) {
+ * ParentClass.call(this, a, b);
+ * }
+ *
+ * ChildClass.inherits(ParentClass);
+ *
+ * var child = new ChildClass('a', 'b', 'see');
+ * child.foo(); // works
+ * </pre>
+ *
+ * In addition, a superclass' implementation of a method can be invoked
+ * as follows:
+ *
+ * <pre>
+ * ChildClass.prototype.foo = function(a) {
+ * ChildClass.superClass_.foo.call(this, a);
+ * // other code
+ * };
+ * </pre>
+ *
+ * @param {Function} parentCtor Parent class.
+ */
+Function.prototype.inherits = function(parentCtor) {
+ goog.inherits(this, parentCtor);
+};
+
+
+/**
+ * Static variant of Function.prototype.inherits.
+ * @param {Function} childCtor Child class.
+ * @param {Function} parentCtor Parent class.
+ */
+goog.inherits = function(childCtor, parentCtor) {
+ /** @constructor */
+ function tempCtor() {};
+ tempCtor.prototype = parentCtor.prototype;
+ childCtor.superClass_ = parentCtor.prototype;
+ childCtor.prototype = new tempCtor();
+ childCtor.prototype.constructor = childCtor;
+};
+
+
+/**
+ * Mixes in an object's properties and methods into the callee's prototype.
+ * Basically mixin based inheritance, thus providing an alternative method for
+ * adding properties and methods to a class' prototype.
+ *
+ * <pre>
+ * function X() {}
+ * X.mixin({
+ * one: 1,
+ * two: 2,
+ * three: 3,
+ * doit: function() { return this.one + this.two + this.three; }
+ * });
+ *
+ * function Y() { }
+ * Y.mixin(X.prototype);
+ * Y.prototype.four = 15;
+ * Y.prototype.doit2 = function() { return this.doit() + this.four; }
+ * });
+ *
+ * // or
+ *
+ * function Y() { }
+ * Y.inherits(X);
+ * Y.mixin({
+ * one: 10,
+ * four: 15,
+ * doit2: function() { return this.doit() + this.four; }
+ * });
+ * </pre>
+ *
+ * @param {Object} source from which to copy properties.
+ * @see goog.mixin
+ * @deprecated
+ */
+Function.prototype.mixin = function(source) {
+ goog.mixin(this.prototype, source);
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/codemap.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/codemap.js
new file mode 100644
index 0000000..3766db0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/codemap.js
@@ -0,0 +1,230 @@
+// Copyright 2009 the V8 project authors. 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.
+
+
+// Initlialize namespaces
+var devtools = devtools || {};
+devtools.profiler = devtools.profiler || {};
+
+
+/**
+ * Constructs a mapper that maps addresses into code entries.
+ *
+ * @constructor
+ */
+devtools.profiler.CodeMap = function() {
+ /**
+ * Dynamic code entries. Used for JIT compiled code.
+ */
+ this.dynamics_ = new goog.structs.SplayTree();
+
+ /**
+ * Name generator for entries having duplicate names.
+ */
+ this.dynamicsNameGen_ = new devtools.profiler.CodeMap.NameGenerator();
+
+ /**
+ * Static code entries. Used for libraries code.
+ */
+ this.statics_ = new goog.structs.SplayTree();
+
+ /**
+ * Map of memory pages occupied with static code.
+ */
+ this.pages_ = [];
+};
+
+
+/**
+ * The number of alignment bits in a page address.
+ */
+devtools.profiler.CodeMap.PAGE_ALIGNMENT = 12;
+
+
+/**
+ * Page size in bytes.
+ */
+devtools.profiler.CodeMap.PAGE_SIZE =
+ 1 << devtools.profiler.CodeMap.PAGE_ALIGNMENT;
+
+
+/**
+ * Adds a dynamic (i.e. moveable and discardable) code entry.
+ *
+ * @param {number} start The starting address.
+ * @param {devtools.profiler.CodeMap.CodeEntry} codeEntry Code entry object.
+ */
+devtools.profiler.CodeMap.prototype.addCode = function(start, codeEntry) {
+ this.dynamics_.insert(start, codeEntry);
+};
+
+
+/**
+ * Moves a dynamic code entry. Throws an exception if there is no dynamic
+ * code entry with the specified starting address.
+ *
+ * @param {number} from The starting address of the entry being moved.
+ * @param {number} to The destination address.
+ */
+devtools.profiler.CodeMap.prototype.moveCode = function(from, to) {
+ var removedNode = this.dynamics_.remove(from);
+ this.dynamics_.insert(to, removedNode.value);
+};
+
+
+/**
+ * Discards a dynamic code entry. Throws an exception if there is no dynamic
+ * code entry with the specified starting address.
+ *
+ * @param {number} start The starting address of the entry being deleted.
+ */
+devtools.profiler.CodeMap.prototype.deleteCode = function(start) {
+ var removedNode = this.dynamics_.remove(start);
+};
+
+
+/**
+ * Adds a static code entry.
+ *
+ * @param {number} start The starting address.
+ * @param {devtools.profiler.CodeMap.CodeEntry} codeEntry Code entry object.
+ */
+devtools.profiler.CodeMap.prototype.addStaticCode = function(
+ start, codeEntry) {
+ this.markPages_(start, start + codeEntry.size);
+ this.statics_.insert(start, codeEntry);
+};
+
+
+/**
+ * @private
+ */
+devtools.profiler.CodeMap.prototype.markPages_ = function(start, end) {
+ for (var addr = start; addr <= end;
+ addr += devtools.profiler.CodeMap.PAGE_SIZE) {
+ this.pages_[addr >> devtools.profiler.CodeMap.PAGE_ALIGNMENT] = 1;
+ }
+};
+
+
+/**
+ * @private
+ */
+devtools.profiler.CodeMap.prototype.isAddressBelongsTo_ = function(addr, node) {
+ return addr >= node.key && addr < (node.key + node.value.size);
+};
+
+
+/**
+ * @private
+ */
+devtools.profiler.CodeMap.prototype.findInTree_ = function(tree, addr) {
+ var node = tree.findGreatestLessThan(addr);
+ return node && this.isAddressBelongsTo_(addr, node) ? node.value : null;
+};
+
+
+/**
+ * Finds a code entry that contains the specified address. Both static and
+ * dynamic code entries are considered.
+ *
+ * @param {number} addr Address.
+ */
+devtools.profiler.CodeMap.prototype.findEntry = function(addr) {
+ var pageAddr = addr >> devtools.profiler.CodeMap.PAGE_ALIGNMENT;
+ if (pageAddr in this.pages_) {
+ return this.findInTree_(this.statics_, addr);
+ }
+ var min = this.dynamics_.findMin();
+ var max = this.dynamics_.findMax();
+ if (max != null && addr < (max.key + max.value.size) && addr >= min.key) {
+ var dynaEntry = this.findInTree_(this.dynamics_, addr);
+ if (dynaEntry == null) return null;
+ // Dedupe entry name.
+ if (!dynaEntry.nameUpdated_) {
+ dynaEntry.name = this.dynamicsNameGen_.getName(dynaEntry.name);
+ dynaEntry.nameUpdated_ = true;
+ }
+ return dynaEntry;
+ }
+ return null;
+};
+
+
+/**
+ * Returns an array of all dynamic code entries, including deleted ones.
+ */
+devtools.profiler.CodeMap.prototype.getAllDynamicEntries = function() {
+ return this.dynamics_.exportValues();
+};
+
+
+/**
+ * Returns an array of all static code entries.
+ */
+devtools.profiler.CodeMap.prototype.getAllStaticEntries = function() {
+ return this.statics_.exportValues();
+};
+
+
+/**
+ * Creates a code entry object.
+ *
+ * @param {number} size Code entry size in bytes.
+ * @param {string} opt_name Code entry name.
+ * @constructor
+ */
+devtools.profiler.CodeMap.CodeEntry = function(size, opt_name) {
+ this.size = size;
+ this.name = opt_name || '';
+ this.nameUpdated_ = false;
+};
+
+
+devtools.profiler.CodeMap.CodeEntry.prototype.getName = function() {
+ return this.name;
+};
+
+
+devtools.profiler.CodeMap.CodeEntry.prototype.toString = function() {
+ return this.name + ': ' + this.size.toString(16);
+};
+
+
+devtools.profiler.CodeMap.NameGenerator = function() {
+ this.knownNames_ = [];
+};
+
+
+devtools.profiler.CodeMap.NameGenerator.prototype.getName = function(name) {
+ if (!(name in this.knownNames_)) {
+ this.knownNames_[name] = 0;
+ return name;
+ }
+ var count = ++this.knownNames_[name];
+ return name + ' {' + count + '}';
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/consarray.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/consarray.js
new file mode 100644
index 0000000..c67abb7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/consarray.js
@@ -0,0 +1,93 @@
+// Copyright 2009 the V8 project authors. 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.
+
+
+/**
+ * Constructs a ConsArray object. It is used mainly for tree traversal.
+ * In this use case we have lots of arrays that we need to iterate
+ * sequentally. The internal Array implementation is horribly slow
+ * when concatenating on large (10K items) arrays due to memory copying.
+ * That's why we avoid copying memory and insead build a linked list
+ * of arrays to iterate through.
+ *
+ * @constructor
+ */
+function ConsArray() {
+ this.tail_ = new ConsArray.Cell(null, null);
+ this.currCell_ = this.tail_;
+ this.currCellPos_ = 0;
+};
+
+
+/**
+ * Concatenates another array for iterating. Empty arrays are ignored.
+ * This operation can be safely performed during ongoing ConsArray
+ * iteration.
+ *
+ * @param {Array} arr Array to concatenate.
+ */
+ConsArray.prototype.concat = function(arr) {
+ if (arr.length > 0) {
+ this.tail_.data = arr;
+ this.tail_ = this.tail_.next = new ConsArray.Cell(null, null);
+ }
+};
+
+
+/**
+ * Whether the end of iteration is reached.
+ */
+ConsArray.prototype.atEnd = function() {
+ return this.currCell_ === null ||
+ this.currCell_.data === null ||
+ this.currCellPos_ >= this.currCell_.data.length;
+};
+
+
+/**
+ * Returns the current item, moves to the next one.
+ */
+ConsArray.prototype.next = function() {
+ var result = this.currCell_.data[this.currCellPos_++];
+ if (this.currCellPos_ >= this.currCell_.data.length) {
+ this.currCell_ = this.currCell_.next;
+ this.currCellPos_ = 0;
+ }
+ return result;
+};
+
+
+/**
+ * A cell object used for constructing a list in ConsArray.
+ *
+ * @constructor
+ */
+ConsArray.Cell = function(data, next) {
+ this.data = data;
+ this.next = next;
+};
+
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/csvparser.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/csvparser.js
new file mode 100644
index 0000000..9e58dea
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/csvparser.js
@@ -0,0 +1,98 @@
+// Copyright 2009 the V8 project authors. 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.
+
+
+// Initlialize namespaces.
+var devtools = devtools || {};
+devtools.profiler = devtools.profiler || {};
+
+
+/**
+ * Creates a CSV lines parser.
+ */
+devtools.profiler.CsvParser = function() {
+};
+
+
+/**
+ * A regex for matching a trailing quote.
+ * @private
+ */
+devtools.profiler.CsvParser.TRAILING_QUOTE_RE_ = /\"$/;
+
+
+/**
+ * A regex for matching a double quote.
+ * @private
+ */
+devtools.profiler.CsvParser.DOUBLE_QUOTE_RE_ = /\"\"/g;
+
+
+/**
+ * Parses a line of CSV-encoded values. Returns an array of fields.
+ *
+ * @param {string} line Input line.
+ */
+devtools.profiler.CsvParser.prototype.parseLine = function(line) {
+ var insideQuotes = false;
+ var fields = [];
+ var prevPos = 0;
+ for (var i = 0, n = line.length; i < n; ++i) {
+ switch (line.charAt(i)) {
+ case ',':
+ if (!insideQuotes) {
+ fields.push(line.substring(prevPos, i));
+ prevPos = i + 1;
+ }
+ break;
+ case '"':
+ if (!insideQuotes) {
+ insideQuotes = true;
+ // Skip the leading quote.
+ prevPos++;
+ } else {
+ if (i + 1 < n && line.charAt(i + 1) != '"') {
+ insideQuotes = false;
+ } else {
+ i++;
+ }
+ }
+ break;
+ }
+ }
+ if (n > 0) {
+ fields.push(line.substring(prevPos));
+ }
+
+ for (i = 0; i < fields.length; ++i) {
+ // Eliminate trailing quotes.
+ fields[i] = fields[i].replace(devtools.profiler.CsvParser.TRAILING_QUOTE_RE_, '');
+ // Convert quoted quotes into single ones.
+ fields[i] = fields[i].replace(devtools.profiler.CsvParser.DOUBLE_QUOTE_RE_, '"');
+ }
+ return fields;
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/debugger.css b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/debugger.css
new file mode 100644
index 0000000..ed9df2f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/debugger.css
@@ -0,0 +1,35 @@
+/**
+ * Style for javascript debugger. See debugger.html.
+ */
+
+html,body {
+ margin: 0px;
+ padding: 0px;
+ height: 100%;
+}
+#output {
+ font-family: monospace;
+ background-color: #ffffff;
+ min-height: 100%;
+}
+#outer {
+ height: 100%;
+ width: 100%;
+ white-space: pre-wrap;
+ padding: 0px 0px 24px 0px;
+}
+#command-line {
+ bottom: 0px;
+ /* not quite sure why this 5px is necessary */
+ right: 5px;
+ left: 0px;
+ position: fixed;
+ padding: 0px;
+ margin: 0px;
+}
+#command-line-text {
+ height: 20px;
+ display: block;
+ width: 100%;
+ font-family: monospace;
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/debugger.html b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/debugger.html
new file mode 100644
index 0000000..f6bb917
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/debugger.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<!--
+ The UI for the javascript debugger window.
+-->
+ <head>
+ <title>JavaScript Debugger</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF8" />
+ <link rel="stylesheet" href="debugger.css" type="text/css" />
+ <script type="text/javascript" src="DebuggerConsole.js"></script>
+ <script type="text/javascript" src="DebuggerIPC.js"></script>
+ <script type="text/javascript" src="DebuggerShell.js"></script>
+ </head>
+
+ <body onload="onLoad();">
+
+ <table id='outer'>
+ <tr>
+ <td valign='bottom' id='output'>Chrome JavaScript Debugger<br />Type 'help' for a list of commands.<br /></td>
+ </tr>
+ </table>
+
+ <div id='command-line'>
+ <!-- TODO(erikkay) - use addEventListener instead -->
+ <input id='command-line-text'
+ type="text" />
+ </div>
+
+ </body>
+</html>
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/debugger_agent.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/debugger_agent.js
new file mode 100644
index 0000000..6eec36e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/debugger_agent.js
@@ -0,0 +1,1185 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Provides communication interface to remote v8 debugger. See
+ * protocol decription at http://code.google.com/p/v8/wiki/DebuggerProtocol
+ */
+goog.provide('devtools.DebuggerAgent');
+
+
+/**
+ * @constructor
+ */
+devtools.DebuggerAgent = function() {
+ RemoteDebuggerAgent.DebuggerOutput =
+ goog.bind(this.handleDebuggerOutput_, this);
+ RemoteDebuggerAgent.DidGetContextId =
+ goog.bind(this.didGetContextId_, this);
+ RemoteDebuggerAgent.DidIsProfilingStarted =
+ goog.bind(this.didIsProfilingStarted_, this);
+ RemoteDebuggerAgent.DidGetNextLogLines =
+ goog.bind(this.didGetNextLogLines_, 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 top frame.
+ * See JavaScriptCallFrame.idl.
+ * @type {?devtools.CallFrame}
+ */
+ this.currentCallFrame_ = null;
+
+ /**
+ * Whether to stop in the debugger on the exceptions.
+ * @type {boolean}
+ */
+ this.pauseOnExceptions_ = true;
+
+ /**
+ * Mapping: request sequence number->callback.
+ * @type {Object}
+ */
+ this.requestSeqToCallback_ = null;
+
+ /**
+ * Whether the scripts list has been requested.
+ * @type {boolean}
+ */
+ this.scriptsCacheInitialized_ = false;
+
+ /**
+ * Whether profiling session is started.
+ * @type {boolean}
+ */
+ this.isProfilingStarted_ = false;
+
+ /**
+ * Profiler processor instance.
+ * @type {devtools.profiler.Processor}
+ */
+ this.profilerProcessor_ = new devtools.profiler.Processor();
+};
+
+
+/**
+ * Resets debugger agent to its initial state.
+ */
+devtools.DebuggerAgent.prototype.reset = function() {
+ this.scriptsCacheInitialized_ = false;
+ this.contextId_ = null;
+ this.parsedScripts_ = {};
+ this.requestNumberToBreakpointInfo_ = {};
+ this.currentCallFrame_ = null;
+ this.requestSeqToCallback_ = {};
+
+ // Profiler isn't reset because it contains no data that is
+ // specific for a particular V8 instance. All such data is
+ // managed by an agent on the Render's side.
+};
+
+
+/**
+ * Requests scripts list if it has not been requested yet.
+ */
+devtools.DebuggerAgent.prototype.initializeScriptsCache = function() {
+ if (!this.scriptsCacheInitialized_) {
+ this.scriptsCacheInitialized_ = true;
+ this.requestScripts();
+ }
+};
+
+
+/**
+ * Asynchronously requests for all parsed script sources. Response will be
+ * processed in handleScriptsResponse_.
+ */
+devtools.DebuggerAgent.prototype.requestScripts = function() {
+ if (this.contextId_ === null) {
+ // Update context id first to filter the scripts.
+ RemoteDebuggerAgent.GetContextId();
+ return;
+ }
+ var cmd = new devtools.DebugCommand('scripts', {
+ 'includeSource': false
+ });
+ devtools.DebuggerAgent.sendCommand_(cmd);
+ // Force v8 execution so that it gets to processing the requested command.
+ devtools.tools.evaluateJavaScript('javascript:void(0)');
+};
+
+
+/**
+ * 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) {
+ 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.
+ devtools.tools.evaluateJavaScript('javascript:void(0)');
+
+ this.requestSeqToCallback_[cmd.getSequenceNumber()] = function(msg) {
+ if (msg.isSuccess()) {
+ var scriptJson = msg.getBody()[0];
+ callback(scriptJson.source);
+ } else {
+ callback(null);
+ }
+ };
+};
+
+
+/**
+ * Tells the v8 debugger to stop on as soon as possible.
+ */
+devtools.DebuggerAgent.prototype.pauseExecution = function() {
+ RemoteDebuggerAgent.DebugBreak();
+};
+
+
+/**
+ * @param {number} sourceId Id of the script fot the breakpoint.
+ * @param {number} line Number of the line for the breakpoint.
+ */
+devtools.DebuggerAgent.prototype.addBreakpoint = function(sourceId, line) {
+ var script = this.parsedScripts_[sourceId];
+ if (!script) {
+ return;
+ }
+
+ line = devtools.DebuggerAgent.webkitToV8LineNumber_(line);
+
+ var breakpointInfo = script.getBreakpointInfo(line);
+ if (breakpointInfo) {
+ return;
+ }
+
+ breakpointInfo = new devtools.BreakpointInfo(sourceId, line);
+ script.addBreakpointInfo(breakpointInfo);
+
+ var cmd = new devtools.DebugCommand('setbreakpoint', {
+ 'type': 'scriptId',
+ 'target': sourceId,
+ 'line': line
+ });
+
+ this.requestNumberToBreakpointInfo_[cmd.getSequenceNumber()] = breakpointInfo;
+
+ devtools.DebuggerAgent.sendCommand_(cmd);
+};
+
+
+/**
+ * @param {number} sourceId Id of the script fot 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 = script.getBreakpointInfo(line);
+ script.removeBreakpointInfo(breakpointInfo);
+ 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);
+ }
+};
+
+
+/**
+ * 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() {
+ var cmd = new devtools.DebugCommand('continue');
+ devtools.DebuggerAgent.sendCommand_(cmd);
+};
+
+
+/**
+ * @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;
+};
+
+
+/**
+ * Current stack top frame.
+ * @return {devtools.CallFrame}
+ */
+devtools.DebuggerAgent.prototype.getCurrentCallFrame = function() {
+ return this.currentCallFrame_;
+};
+
+
+/**
+ * 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.
+ */
+devtools.DebuggerAgent.prototype.resolveChildren = function(object, callback) {
+ if ('ref' in object) {
+ 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);
+ } else {
+ result.error = 'Failed to resolve children: ' + msg.getMessage();
+ }
+ object.resolvedValue = result;
+ callback(object);
+ });
+
+ return;
+ } else {
+ if (!object.resolvedValue) {
+ var message = 'Corrupted object: ' + JSON.stringify(object);
+ object.resolvedValue = {};
+ object.resolvedValue.error = message;
+ }
+ callback(object);
+ }
+};
+
+
+/**
+ * Sets up callbacks that deal with profiles processing.
+ */
+devtools.DebuggerAgent.prototype.setupProfilerProcessorCallbacks = function() {
+ // A temporary icon indicating that the profile is being processed.
+ var processingIcon = new WebInspector.SidebarTreeElement(
+ "profile-sidebar-tree-item", "Processing...", "", null, false);
+ var profilesSidebar = WebInspector.panels.profiles.sidebarTree;
+
+ this.profilerProcessor_.setCallbacks(
+ function onProfileProcessingStarted() {
+ profilesSidebar.appendChild(processingIcon);
+ },
+ function onProfileProcessingFinished(profile) {
+ profilesSidebar.removeChild(processingIcon);
+ WebInspector.addProfile(profile);
+ }
+ );
+};
+
+
+/**
+ * Initializes profiling state.
+ */
+devtools.DebuggerAgent.prototype.initializeProfiling = function() {
+ this.setupProfilerProcessorCallbacks();
+ RemoteDebuggerAgent.IsProfilingStarted();
+};
+
+
+/**
+ * Starts (resumes) profiling.
+ */
+devtools.DebuggerAgent.prototype.startProfiling = function() {
+ RemoteDebuggerAgent.StartProfiling();
+ RemoteDebuggerAgent.IsProfilingStarted();
+};
+
+
+/**
+ * Stops (pauses) profiling.
+ */
+devtools.DebuggerAgent.prototype.stopProfiling = function() {
+ RemoteDebuggerAgent.StopProfiling();
+};
+
+
+/**
+ * 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);
+};
+
+
+/**
+ * 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) {
+ 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;
+};
+
+
+/**
+ * Handles GetContextId response.
+ * @param {number} contextId Id of the inspected page global context.
+ */
+devtools.DebuggerAgent.prototype.didGetContextId_ = function(contextId) {
+ this.contextId_ = contextId;
+ // Update scripts.
+ this.requestScripts();
+};
+
+
+/**
+ * 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 reponse:\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.handleScriptsResponse_(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);
+ }
+ }
+};
+
+
+/**
+ * @param {devtools.DebuggerMessage} msg
+ */
+devtools.DebuggerAgent.prototype.handleBreakEvent_ = function(msg) {
+ var body = msg.getBody();
+
+ var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(body.sourceLine);
+ this.currentCallFrame_ = new devtools.CallFrame();
+ this.currentCallFrame_.sourceID = body.script.id;
+ this.currentCallFrame_.line = line;
+ this.currentCallFrame_.script = body.script;
+ this.requestBacktrace_();
+};
+
+
+/**
+ * @param {devtools.DebuggerMessage} msg
+ */
+devtools.DebuggerAgent.prototype.handleExceptionEvent_ = function(msg) {
+ var body = msg.getBody();
+ debugPrint('Uncaught exception in ' + body.script.name + ':' +
+ body.sourceLine + '\n' + body.sourceLineText);
+ if (this.pauseOnExceptions_) {
+ var body = msg.getBody();
+
+ var sourceId = -1;
+ // The exception may happen in native code in which case there is no script.
+ if (body.script) {
+ sourceId = body.script.id;
+ }
+
+ var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(body.sourceLine);
+
+ this.currentCallFrame_ = new devtools.CallFrame();
+ this.currentCallFrame_.sourceID = sourceId;
+ this.currentCallFrame_.line = line;
+ this.currentCallFrame_.script = body.script;
+ this.requestBacktrace_();
+ } else {
+ this.resumeExecution();
+ }
+};
+
+
+/**
+ * @param {devtools.DebuggerMessage} msg
+ */
+devtools.DebuggerAgent.prototype.handleScriptsResponse_ = function(msg) {
+ if (this.invokeCallbackForResponse_(msg)) {
+ return;
+ }
+
+ 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);
+ }
+};
+
+
+/**
+ * @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 (!goog.isDef(scriptContextId)) {
+ return false; // Always ignore scripts from the utility context.
+ }
+ if (this.contextId_ === null) {
+ return true;
+ }
+ return (scriptContextId == 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) {
+ var script = msg.getBody().script;
+ // Ignore scripts from other tabs.
+ if (!this.isScriptFromInspectedContext_(script, msg)) {
+ return;
+ }
+ this.addScriptInfo_(script);
+};
+
+
+/**
+ * Handles current profiler status.
+ */
+devtools.DebuggerAgent.prototype.didIsProfilingStarted_ = function(
+ is_started) {
+ if (is_started && !this.isProfilingStarted_) {
+ // Start to query log data.
+ RemoteDebuggerAgent.GetNextLogLines();
+ }
+ this.isProfilingStarted_ = is_started;
+ // Update button.
+ WebInspector.setRecordingProfile(is_started);
+ if (is_started) {
+ // Monitor profiler state. It can stop itself on buffer fill-up.
+ setTimeout(function() { RemoteDebuggerAgent.IsProfilingStarted(); }, 1000);
+ }
+};
+
+
+/**
+ * Handles a portion of a profiler log retrieved by GetNextLogLines call.
+ * @param {string} log A portion of profiler log.
+ */
+devtools.DebuggerAgent.prototype.didGetNextLogLines_ = function(log) {
+ if (log.length > 0) {
+ this.profilerProcessor_.processLogChunk(log);
+ } else if (!this.isProfilingStarted_) {
+ // No new data and profiling is stopped---suspend log reading.
+ return;
+ }
+ setTimeout(function() { RemoteDebuggerAgent.GetNextLogLines(); }, 500);
+};
+
+
+/**
+ * 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.
+ */
+devtools.DebuggerAgent.prototype.addScriptInfo_ = function(script) {
+ this.parsedScripts_[script.id] = new devtools.ScriptInfo(
+ script.id, script.lineOffset);
+ 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.currentCallFrame_) {
+ return;
+ }
+
+ var script = this.currentCallFrame_.script;
+
+ var callerFrame = null;
+ var f = null;
+ var frames = msg.getBody().frames;
+ for (var i = frames.length - 1; i>=0; i--) {
+ var nextFrame = frames[i];
+ var f = devtools.DebuggerAgent.formatCallFrame_(nextFrame, script, msg);
+ f.frameNumber = i;
+ f.caller = callerFrame;
+ callerFrame = f;
+ }
+
+ this.currentCallFrame_ = f;
+
+ WebInspector.pausedScript();
+ DevToolsHost.activateWindow();
+};
+
+
+/**
+ * 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;
+};
+
+
+devtools.DebuggerAgent.prototype.evaluateInCallFrame_ = function(expression) {
+};
+
+
+/**
+ * @param {Object} stackFrame Frame json object from 'backtrace' response.
+ * @param {Object} script Script json object from 'break' event.
+ * @param {devtools.DebuggerMessage} msg Parsed 'backtrace' response.
+ * @return {!devtools.CallFrame} Object containing information related to the
+ * call frame in the format expected by ScriptsPanel and its panes.
+ */
+devtools.DebuggerAgent.formatCallFrame_ = function(stackFrame, script, msg) {
+ var sourceId = script.id;
+
+ var func = stackFrame.func;
+ var sourceId = func.scriptId;
+ var funcName = func.name || func.inferredName || '(anonymous function)';
+
+ var scope = {};
+
+ // Add arguments.
+ devtools.DebuggerAgent.argumentsArrayToMap_(stackFrame.arguments, scope);
+
+ // Add local variables.
+ devtools.DebuggerAgent.propertiesToMap_(stackFrame.locals, scope);
+
+ var thisObject = devtools.DebuggerAgent.formatObjectReference_(
+ stackFrame.receiver);
+ // Add variable with name 'this' to the scope.
+ scope['this'] = thisObject;
+
+ var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(stackFrame.line);
+ var result = new devtools.CallFrame();
+ result.sourceID = sourceId;
+ result.line = line;
+ result.type = 'function';
+ result.functionName = funcName;
+ result.localScope = scope;
+ result.scopeChain = [scope];
+ result.thisObject = thisObject;
+ return result;
+};
+
+
+/**
+ * Collects properties for an object from the debugger response.
+ * @param {Object} object An object from the debugger protocol response.
+ * @param {Object} result A map to put the properties in.
+ */
+devtools.DebuggerAgent.formatObjectProperties_ = function(object, result) {
+ devtools.DebuggerAgent.propertiesToMap_(object.properties, result);
+ result.protoObject = devtools.DebuggerAgent.formatObjectReference_(
+ object.protoObject);
+ result.prototypeObject = devtools.DebuggerAgent.formatObjectReference_(
+ object.prototypeObject);
+ result.constructorFunction = devtools.DebuggerAgent.formatObjectReference_(
+ object.constructorFunction);
+};
+
+
+/**
+ * For each property in 'properties' puts its name and user-friendly value into
+ * 'map'.
+ * @param {Array.<Object>} properties Receiver properties or locals array from
+ * 'backtrace' response.
+ * @param {Object} map Result holder.
+ */
+devtools.DebuggerAgent.propertiesToMap_ = function(properties, map) {
+ for (var j = 0; j < properties.length; j++) {
+ var nextValue = properties[j];
+ // Skip unnamed properties. They may appear e.g. when number of actual
+ // parameters is greater the that of formal. In that case the superfluous
+ // parameters will be present in the arguments list as elements without
+ // names.
+ if (nextValue.name) {
+ map[nextValue.name] =
+ devtools.DebuggerAgent.formatObjectReference_(nextValue.value);
+ }
+ }
+};
+
+
+/**
+ * Puts arguments from the protocol arguments array to the map assigning names
+ * to the anonymous arguments.
+ * @param {Array.<Object>} array Arguments array from 'backtrace' response.
+ * @param {Object} map Result holder.
+ */
+devtools.DebuggerAgent.argumentsArrayToMap_ = function(array, map) {
+ for (var j = 0; j < array.length; j++) {
+ var nextValue = array[j];
+ // Skip unnamed properties. They may appear e.g. when number of actual
+ // parameters is greater the that of formal. In that case the superfluous
+ // parameters will be present in the arguments list as elements without
+ // names.
+ var name = nextValue.name ? nextValue.name : '<arg #' + j + '>';
+ map[name] = devtools.DebuggerAgent.formatObjectReference_(nextValue.value);
+ }
+};
+
+
+/**
+ * @param {Object} v An object reference from the debugger response.
+ * @return {*} The value representation expected by ScriptsPanel.
+ */
+devtools.DebuggerAgent.formatObjectReference_ = function(v) {
+ if (v.type == 'object') {
+ return v;
+ } else if (v.type == 'function') {
+ var f = function() {};
+ f.ref = v.ref;
+ return f;
+ } else if (goog.isDef(v.value)) {
+ return v.value;
+ } else if (v.type == 'undefined') {
+ return 'undefined';
+ } else if (v.type == 'null') {
+ return 'null';
+ } else if (v.name) {
+ return v.name;
+ } else if (v.className) {
+ return v.className;
+ } else {
+ return '<unresolved ref: ' + v.ref + ', type: ' + v.type + '>';
+ }
+};
+
+
+/**
+ * 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 {number} lineOffset First line 0-based offset in the containing
+ * document.
+ * @constructor
+ */
+devtools.ScriptInfo = function(scriptId, lineOffset) {
+ this.scriptId_ = scriptId;
+ this.lineOffset_ = lineOffset;
+
+ this.lineToBreakpointInfo_ = {};
+};
+
+
+/**
+ * @return {number}
+ */
+devtools.ScriptInfo.prototype.getLineOffset = function() {
+ return this.lineOffset_;
+};
+
+
+/**
+ * @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} scriptId Id of the owning script.
+ * @param {number} line Breakpoint 0-based line number in the containing script.
+ * @constructor
+ */
+devtools.BreakpointInfo = function(sourceId, line) {
+ this.sourceId_ = sourceId;
+ this.line_ = line;
+ this.v8id_ = -1;
+ this.removed_ = false;
+};
+
+
+/**
+ * @return {number}
+ */
+devtools.BreakpointInfo.prototype.getSourceId = function(n) {
+ return this.sourceId_;
+};
+
+
+/**
+ * @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.
+ * @construnctor
+ */
+devtools.CallFrame = function() {
+ this.sourceID = null;
+ this.line = null;
+ this.type = 'function';
+ this.functionName = null;
+ this.caller = null;
+ this.localScope = null;
+ this.scopeChain = [];
+ this.thisObject = {};
+ this.frameNumber = null;
+};
+
+
+/**
+ * This method is called by
+ * WebInspector.ScriptsPanel.evaluateInSelectedCallFrame. This method issues
+ * asynchronous evaluate request.
+ * @param {string} expression An expression to be evaluated in the context of
+ * this call frame.
+ * @return {string} User message that the expression is being evaluated.
+ */
+devtools.CallFrame.prototype.evaluate = function(expression) {
+ devtools.tools.getDebuggerAgent().requestEvaluate({
+ 'expression': expression,
+ 'frame': this.frameNumber,
+ 'global': false,
+ 'disable_break': false
+ },
+ devtools.CallFrame.handleEvaluateResponse_);
+ return 'evaluating...';
+};
+
+
+/**
+ * Handles 'evaluate' response for a call frame
+ * @param {devtools.DebuggerMessage} response
+ */
+devtools.CallFrame.handleEvaluateResponse_ = function(response) {
+ var body = response.getBody();
+ var value = devtools.DebuggerAgent.formatObjectReference_(body);
+ WebInspector.console.addMessage(new WebInspector.ConsoleCommandResult(
+ value, false /* exception */, null /* commandMessage */));
+};
+
+
+/**
+ * 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) {
+ var jsExpression = '[' + msg + '][0]';
+ this.packet_ = eval(jsExpression);
+ 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/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/devtools.html b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/devtools.html
new file mode 100644
index 0000000..018573d
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/devtools.html
@@ -0,0 +1,126 @@
+<!--
+Copyright (c) 2009 The Chromium Authors. All rights reserved.
+
+This is the Chromium version of the WebInspector. This html file serves
+as a deployment descriptor and specifies which js libraries to include into the
+app. Once the "main" frontend method that is building WebInspector
+from the js building blocks is extracted, we will be able have different
+implementations of it for Chromium and WebKit. That would allow us for
+example not to create WebKit Database tab and remove corresponding js files
+from here. Longer term we would like to employ closure + basic js compilation.
+That way js libraries would know their dependencies and js compiler would be
+able to compile them into a single file. After that this HTML file will
+include single <script src='fe-compiled.js'> and will become upstreamable.
+
+Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <link rel="stylesheet" type="text/css" href="inspector.css">
+ <script type="text/javascript" src="base.js"></script>
+ <script type="text/javascript" src="utilities.js"></script>
+ <script type="text/javascript" src="treeoutline.js"></script>
+ <script type="text/javascript" src="devtools_callback.js"></script>
+ <script type="text/javascript" src="debugger_agent.js"></script>
+ <script type="text/javascript" src="dom_agent.js"></script>
+ <script type="text/javascript" src="inspector_controller.js"></script>
+ <script type="text/javascript" src="inspector_controller_impl.js"></script>
+ <script type="text/javascript" src="inspector.js"></script>
+ <script type="text/javascript" src="codemap.js"></script>
+ <script type="text/javascript" src="consarray.js"></script>
+ <script type="text/javascript" src="csvparser.js"></script>
+ <script type="text/javascript" src="profile.js"></script>
+ <script type="text/javascript" src="profile_view.js"></script>
+ <script type="text/javascript" src="profiler_processor.js"></script>
+ <script type="text/javascript" src="splaytree.js"></script>
+ <script type="text/javascript" src="Object.js"></script>
+ <script type="text/javascript" src="TextPrompt.js"></script>
+ <script type="text/javascript" src="Placard.js"></script>
+ <script type="text/javascript" src="View.js"></script>
+ <script type="text/javascript" src="Console.js"></script>
+ <script type="text/javascript" src="Resource.js"></script>
+ <script type="text/javascript" src="ResourceCategory.js"></script>
+ <script type="text/javascript" src="Database.js"></script>
+ <script type="text/javascript" src="DOMStorage.js"></script>
+ <script type="text/javascript" src="DOMStorageItemsView.js"></script>
+ <script type="text/javascript" src="DataGrid.js"></script>
+ <script type="text/javascript" src="DOMStorageDataGrid.js"></script>
+ <script type="text/javascript" src="Script.js"></script>
+ <script type="text/javascript" src="Breakpoint.js"></script>
+ <script type="text/javascript" src="SidebarPane.js"></script>
+ <script type="text/javascript" src="ElementsTreeOutline.js"></script>
+ <script type="text/javascript" src="SidebarTreeElement.js"></script>
+ <script type="text/javascript" src="PropertiesSection.js"></script>
+ <script type="text/javascript" src="ObjectPropertiesSection.js"></script>
+ <script type="text/javascript" src="BreakpointsSidebarPane.js"></script>
+ <script type="text/javascript" src="CallStackSidebarPane.js"></script>
+ <script type="text/javascript" src="ScopeChainSidebarPane.js"></script>
+ <script type="text/javascript" src="MetricsSidebarPane.js"></script>
+ <script type="text/javascript" src="PropertiesSidebarPane.js"></script>
+ <script type="text/javascript" src="StylesSidebarPane.js"></script>
+ <script type="text/javascript" src="Panel.js"></script>
+ <script type="text/javascript" src="PanelEnablerView.js"></script>
+ <script type="text/javascript" src="ElementsPanel.js"></script>
+ <script type="text/javascript" src="ResourcesPanel.js"></script>
+ <script type="text/javascript" src="ScriptsPanel.js"></script>
+ <script type="text/javascript" src="DatabasesPanel.js"></script>
+ <script type="text/javascript" src="ProfilesPanel.js"></script>
+ <script type="text/javascript" src="ResourceView.js"></script>
+ <script type="text/javascript" src="SourceFrame.js"></script>
+ <script type="text/javascript" src="SourceView.js"></script>
+ <script type="text/javascript" src="FontView.js"></script>
+ <script type="text/javascript" src="ImageView.js"></script>
+ <script type="text/javascript" src="DatabaseTableView.js"></script>
+ <script type="text/javascript" src="DatabaseQueryView.js"></script>
+ <script type="text/javascript" src="ScriptView.js"></script>
+ <script type="text/javascript" src="ProfileView.js"></script>
+ <script type="text/javascript" src="ProfileDataGridTree.js"></script>
+ <script type="text/javascript" src="BottomUpProfileDataGridTree.js"></script>
+ <script type="text/javascript" src="TopDownProfileDataGridTree.js"></script>
+ <script type="text/javascript" src="devtools.js"></script>
+ <script type="text/javascript" src="devtools_host_stub.js"></script>
+ <script type="text/javascript" src="tests.js"></script>
+</head>
+<body class="detached">
+ <div id="toolbar">
+ <div class="toolbar-item close"><button id="close-button"></button></div>
+ <div class="toolbar-item flexable-space"></div>
+ <div class="toolbar-item hidden" id="search-results-matches"></div>
+ <div class="toolbar-item"><input id="search" type="search" incremental results="0"><div id="search-toolbar-label" class="toolbar-label"></div></div>
+ </div>
+ <div id="main">
+ <div id="main-panels" tabindex="0"></div>
+ <div id="main-status-bar" class="status-bar"><div id="anchored-status-bar-items"><button id="dock-status-bar-item" class="status-bar-item toggled"></button><button id="console-status-bar-item" class="status-bar-item"></button><div id="error-warning-count" class="hidden"></div></div></div>
+ </div>
+ <div id="console">
+ <div id="console-messages"><div id="console-prompt"><br></div></div>
+ <div id="console-status-bar" class="status-bar"><div id="other-console-status-bar-items"><button id="clear-console-status-bar-item" class="status-bar-item"></button></div></div>
+ </div>
+</body>
+</html>
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/devtools.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/devtools.js
new file mode 100644
index 0000000..ac88652
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/devtools.js
@@ -0,0 +1,896 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @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.
+ */
+goog.provide('devtools.Tools');
+
+goog.require('devtools.DebuggerAgent');
+goog.require('devtools.DomAgent');
+
+
+/**
+ * Dispatches raw message from the host.
+ * @param {string} remoteName
+ * @prama {string} methodName
+ * @param {Object} msg Message to dispatch.
+ */
+devtools.dispatch = function(remoteName, methodName, msg) {
+ 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.apply(this, msg);
+};
+
+
+devtools.ToolsAgent = function() {
+ RemoteToolsAgent.DidEvaluateJavaScript = devtools.Callback.processCallback;
+ RemoteToolsAgent.DidExecuteUtilityFunction =
+ devtools.Callback.processCallback;
+ RemoteToolsAgent.UpdateFocusedNode =
+ goog.bind(this.updateFocusedNode_, this);
+ RemoteToolsAgent.FrameNavigate =
+ goog.bind(this.frameNavigate_, this);
+ RemoteToolsAgent.AddMessageToConsole =
+ goog.bind(this.addMessageToConsole_, this);
+ RemoteToolsAgent.DispatchOnClient =
+ goog.bind(this.dispatchOnClient_, this);
+ RemoteToolsAgent.DidGetResourceContent =
+ devtools.Callback.processCallback;
+ RemoteToolsAgent.SetResourcesPanelEnabled =
+ goog.bind(this.setResourcesPanelEnabled_, this);
+ this.debuggerAgent_ = new devtools.DebuggerAgent();
+ this.domAgent_ = new devtools.DomAgent();
+};
+
+
+/**
+ * Resets tools agent to its initial state.
+ */
+devtools.ToolsAgent.prototype.reset = function() {
+ DevToolsHost.reset();
+ this.domAgent_.reset();
+ this.debuggerAgent_.reset();
+
+ this.domAgent_.getDocumentElementAsync();
+};
+
+
+/**
+ * @param {string} script Script exression to be evaluated in the context of the
+ * inspected page.
+ * @param {function(string):undefined} callback Function to call with the
+ * result.
+ */
+devtools.ToolsAgent.prototype.evaluateJavaScript = function(script, callback) {
+ var callbackId = devtools.Callback.wrap(callback);
+ RemoteToolsAgent.EvaluateJavaScript(callbackId, script);
+};
+
+
+/**
+ * @return {devtools.DebuggerAgent} Debugger agent instance.
+ */
+devtools.ToolsAgent.prototype.getDebuggerAgent = function() {
+ return this.debuggerAgent_;
+};
+
+/**
+ * DomAgent accessor.
+ * @return {devtools.DomAgent} Dom agent instance.
+ */
+devtools.ToolsAgent.prototype.getDomAgent = function() {
+ return this.domAgent_;
+};
+
+
+/**
+ * @see tools_agent.h
+ * @private
+ */
+devtools.ToolsAgent.prototype.updateFocusedNode_ = function(nodeId) {
+ var node = this.domAgent_.getNodeForId(nodeId);
+ WebInspector.updateFocusedNode(node);
+};
+
+
+/**
+ * @param {string} url Url frame navigated to.
+ * @param {bool} topLevel True iff top level navigation occurred.
+ * @see tools_agent.h
+ * @private
+ */
+devtools.ToolsAgent.prototype.frameNavigate_ = function(url, topLevel) {
+ if (topLevel) {
+ 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 {Object} message Message object to add.
+ * @see tools_agent.h
+ * @private
+ */
+devtools.ToolsAgent.prototype.addMessageToConsole_ = function(message) {
+ var console = WebInspector.console;
+ if (console) {
+ console.addMessage(new WebInspector.ConsoleMessage(
+ message.source, message.level, message.line, message.sourceId,
+ undefined, 1, message.text));
+ }
+};
+
+
+/**
+ * @param {string} message Serialized call to be dispatched on WebInspector.
+ * @private
+ */
+devtools.ToolsAgent.prototype.dispatchOnClient_ = function(message) {
+ var messageObj = JSON.parse(message);
+ WebInspector.dispatch.apply(WebInspector, messageObj);
+};
+
+
+/**
+ * Evaluates js expression.
+ * @param {string} expr
+ */
+devtools.ToolsAgent.prototype.evaluate = function(expr) {
+ RemoteToolsAgent.evaluate(expr);
+};
+
+
+/**
+ * Asynchronously queries for the resource content.
+ * @param {number} identifier Resource identifier.
+ * @param {function(string):undefined} opt_callback Callback to call when
+ * result is available.
+ */
+devtools.ToolsAgent.prototype.getResourceContentAsync = function(identifier,
+ opt_callback) {
+ var resource = WebInspector.resources[identifier];
+ if (!resource) {
+ return;
+ }
+ RemoteToolsAgent.GetResourceContent(
+ devtools.Callback.wrap(opt_callback), identifier);
+};
+
+
+/**
+ * Enables / disables resource tracking.
+ * @param {boolean} enabled Sets tracking status.
+ * @param {boolean} always Determines whether tracking status should be sticky.
+ */
+devtools.ToolsAgent.prototype.setResourceTrackingEnabled = function(enabled,
+ always) {
+ RemoteToolsAgent.SetResourceTrackingEnabled(enabled, always);
+};
+
+
+/**
+ * Enables / disables resources panel in the ui.
+ * @param {boolean} enabled New panel status.
+ */
+devtools.ToolsAgent.prototype.setResourcesPanelEnabled_ = function(enabled) {
+ InspectorController.resourceTrackingEnabled_ = enabled;
+ // TODO(pfeldman): Extract this upstream.
+ var panel = WebInspector.panels.resources;
+ if (enabled) {
+ panel.enableToggleButton.title =
+ WebInspector.UIString("Resource tracking enabled. Click to disable.");
+ panel.enableToggleButton.addStyleClass("toggled-on");
+ panel.largerResourcesButton.removeStyleClass("hidden");
+ panel.sortingSelectElement.removeStyleClass("hidden");
+ panel.panelEnablerView.visible = false;
+ } else {
+ panel.enableToggleButton.title =
+ WebInspector.UIString("Resource tracking disabled. Click to enable.");
+ panel.enableToggleButton.removeStyleClass("toggled-on");
+ panel.largerResourcesButton.addStyleClass("hidden");
+ panel.sortingSelectElement.addStyleClass("hidden");
+ panel.panelEnablerView.visible = true;
+ }
+};
+
+
+/**
+ * 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(
+ '', undefined, 1, '', 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;
+ oldLoaded.call(this);
+
+ DevToolsHost.loaded();
+};
+
+
+var webkitUpdateChildren =
+ WebInspector.ElementsTreeElement.prototype.updateChildren;
+
+
+/**
+ * @override
+ */
+WebInspector.ElementsTreeElement.prototype.updateChildren = function() {
+ var self = this;
+ devtools.tools.getDomAgent().getChildNodesAsync(this.representedObject,
+ function() {
+ webkitUpdateChildren.call(self);
+ });
+};
+
+
+/**
+ * @override
+ */
+WebInspector.ElementsPanel.prototype.performSearch = function(query) {
+ this.searchCanceled();
+ devtools.tools.getDomAgent().performSearch(query,
+ goog.bind(this.performSearchCallback_, this));
+};
+
+
+WebInspector.ElementsPanel.prototype.performSearchCallback_ = function(nodes) {
+ for (var i = 0; i < nodes.length; ++i) {
+ var treeElement = this.treeOutline.findTreeElement(nodes[i]);
+ if (treeElement)
+ treeElement.highlighted = true;
+ }
+
+ if (nodes.length) {
+ this.currentSearchResultIndex_ = 0;
+ this.focusedDOMNode = nodes[0];
+ }
+
+ this.searchResultCount_ = nodes.length;
+};
+
+
+/**
+ * @override
+ */
+WebInspector.ElementsPanel.prototype.searchCanceled = function() {
+ this.currentSearchResultIndex_ = 0;
+ this.searchResultCount_ = 0;
+ devtools.tools.getDomAgent().searchCanceled(
+ goog.bind(this.searchCanceledCallback_, this));
+};
+
+
+WebInspector.ElementsPanel.prototype.searchCanceledCallback_ = function(nodes) {
+ for (var i = 0; i < nodes.length; i++) {
+ var treeElement = this.treeOutline.findTreeElement(nodes[i]);
+ if (treeElement)
+ treeElement.highlighted = false;
+ }
+};
+
+
+/**
+ * @override
+ */
+WebInspector.ElementsPanel.prototype.jumpToNextSearchResult = function() {
+ if (!this.searchResultCount_)
+ return;
+
+ if (++this.currentSearchResultIndex_ >= this.searchResultCount_)
+ this.currentSearchResultIndex_ = 0;
+
+ this.focusedDOMNode = devtools.tools.getDomAgent().
+ getSearchResultNode(this.currentSearchResultIndex_);
+};
+
+
+/**
+ * @override
+ */
+WebInspector.ElementsPanel.prototype.jumpToPreviousSearchResult = function() {
+ if (!this.searchResultCount_)
+ return;
+
+ if (--this.currentSearchResultIndex_ < 0)
+ this.currentSearchResultIndex_ = this.searchResultCount_ - 1;
+
+ this.focusedDOMNode = devtools.tools.getDomAgent().
+ getSearchResultNode(this.currentSearchResultIndex_);
+};
+
+
+/**
+ * @override
+ */
+WebInspector.Console.prototype._evalInInspectedWindow = function(expr) {
+ return devtools.tools.evaluate(expr);
+};
+
+
+/**
+ * Disable autocompletion in the console.
+ * TODO(yurys): change WebKit implementation to allow asynchronous completion.
+ * @override
+ */
+WebInspector.Console.prototype.completions = function(
+ wordRange, bestMatchOnly) {
+ return null;
+};
+
+
+/**
+ * @override
+ */
+WebInspector.ElementsPanel.prototype.updateStyles = function(forceUpdate) {
+ var stylesSidebarPane = this.sidebarPanes.styles;
+ if (!stylesSidebarPane.expanded || !stylesSidebarPane.needsUpdate) {
+ return;
+ }
+ this.invokeWithStyleSet_(function(node) {
+ stylesSidebarPane.needsUpdate = !!node;
+ stylesSidebarPane.update(node, null, forceUpdate);
+ });
+};
+
+
+/**
+ * @override
+ */
+WebInspector.ElementsPanel.prototype.updateMetrics = function() {
+ var metricsSidebarPane = this.sidebarPanes.metrics;
+ if (!metricsSidebarPane.expanded || !metricsSidebarPane.needsUpdate) {
+ return;
+ }
+ this.invokeWithStyleSet_(function(node) {
+ metricsSidebarPane.needsUpdate = !!node;
+ metricsSidebarPane.update(node);
+ });
+};
+
+
+/**
+ * Temporarily sets style fetched from the inspectable tab to the currently
+ * focused node, invokes updateUI callback and clears the styles.
+ * @param {function(Node):undefined} updateUI Callback to call while styles are
+ * set.
+ */
+WebInspector.ElementsPanel.prototype.invokeWithStyleSet_ =
+ function(updateUI) {
+ var node = this.focusedDOMNode;
+ if (node && node.nodeType === Node.TEXT_NODE && node.parentNode)
+ node = node.parentNode;
+
+ if (node && node.nodeType == Node.ELEMENT_NODE) {
+ var callback = function(stylesStr) {
+ var styles = JSON.parse(stylesStr);
+ if (!styles.computedStyle) {
+ return;
+ }
+ node.setStyles(styles.computedStyle, styles.inlineStyle,
+ styles.styleAttributes, styles.matchedCSSRules);
+ updateUI(node);
+ node.clearStyles();
+ };
+ devtools.tools.getDomAgent().getNodeStylesAsync(
+ node,
+ !Preferences.showUserAgentStyles,
+ callback);
+ } else {
+ updateUI(null);
+ }
+};
+
+
+/**
+ * @override
+ */
+WebInspector.MetricsSidebarPane.prototype.editingCommitted =
+ function(element, userInput, previousContent, context) {
+ if (userInput === previousContent) {
+ // nothing changed, so cancel
+ return this.editingCancelled(element, context);
+ }
+
+ if (context.box !== "position" && (!userInput || userInput === "\u2012")) {
+ userInput = "0px";
+ } else if (context.box === "position" &&
+ (!userInput || userInput === "\u2012")) {
+ userInput = "auto";
+ }
+
+ // Append a "px" unit if the user input was just a number.
+ if (/^\d+$/.test(userInput)) {
+ userInput += "px";
+ }
+ devtools.tools.getDomAgent().setStylePropertyAsync(
+ this.node,
+ context.styleProperty,
+ userInput,
+ WebInspector.updateStylesAndMetrics_);
+};
+
+
+/**
+ * @override
+ */
+WebInspector.PropertiesSidebarPane.prototype.update = function(object) {
+ var body = this.bodyElement;
+ body.removeChildren();
+
+ this.sections = [];
+
+ if (!object) {
+ return;
+ }
+
+
+ var self = this;
+ devtools.tools.getDomAgent().getNodePrototypesAsync(object.id_,
+ function(json) {
+ // Get array of prototype user-friendly names.
+ var prototypes = JSON.parse(json);
+ for (var i = 0; i < prototypes.length; ++i) {
+ var prototype = {};
+ prototype.id_ = object.id_;
+ prototype.protoDepth_ = i;
+ var section = new WebInspector.SidebarObjectPropertiesSection(
+ prototype,
+ prototypes[i]);
+ self.sections.push(section);
+ body.appendChild(section.element);
+ }
+ });
+};
+
+
+/**
+ * Our implementation of ObjectPropertiesSection for Elements tab.
+ * @constructor
+ */
+WebInspector.SidebarObjectPropertiesSection = function(object, title) {
+ WebInspector.ObjectPropertiesSection.call(this, object, title,
+ null /* subtitle */, null /* emptyPlaceholder */,
+ null /* ignoreHasOwnProperty */, null /* extraProperties */,
+ WebInspector.SidebarObjectPropertyTreeElement /* treeElementConstructor */
+ );
+};
+goog.inherits(WebInspector.SidebarObjectPropertiesSection,
+ WebInspector.ObjectPropertiesSection);
+
+
+/**
+ * @override
+ */
+WebInspector.SidebarObjectPropertiesSection.prototype.onpopulate = function() {
+ var nodeId = this.object.id_;
+ var protoDepth = this.object.protoDepth_;
+ var path = [];
+ devtools.tools.getDomAgent().getNodePropertiesAsync(nodeId, path, protoDepth,
+ goog.partial(WebInspector.didGetNodePropertiesAsync_,
+ this.propertiesTreeOutline,
+ this.treeElementConstructor,
+ nodeId,
+ path));
+};
+
+
+/**
+ * Our implementation of ObjectPropertyTreeElement for Elements tab.
+ * @constructor
+ */
+WebInspector.SidebarObjectPropertyTreeElement = function(parentObject,
+ propertyName) {
+ WebInspector.ObjectPropertyTreeElement.call(this, parentObject,
+ propertyName);
+};
+goog.inherits(WebInspector.SidebarObjectPropertyTreeElement,
+ WebInspector.ObjectPropertyTreeElement);
+
+
+/**
+ * @override
+ */
+WebInspector.SidebarObjectPropertyTreeElement.prototype.onpopulate =
+ function() {
+ var nodeId = this.parentObject.devtools$$nodeId_;
+ var path = this.parentObject.devtools$$path_.slice(0);
+ path.push(this.propertyName);
+ devtools.tools.getDomAgent().getNodePropertiesAsync(nodeId, path, -1,
+ goog.partial(
+ WebInspector.didGetNodePropertiesAsync_,
+ this,
+ this.treeOutline.section.treeElementConstructor,
+ nodeId, path));
+};
+
+
+/**
+ * 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 || '<source is not available>';
+ self.didResolveScriptSource_();
+ });
+ }
+};
+
+
+/**
+ * Performs source frame setup when script source is aready resolved.
+ */
+WebInspector.ScriptView.prototype.didResolveScriptSource_ = function() {
+ if (!InspectorController.addSourceToFrame(
+ "text/javascript", this.script.source, this.sourceFrame.element)) {
+ return;
+ }
+
+ delete this._frameNeedsSetup;
+
+ this.sourceFrame.addEventListener(
+ "syntax highlighting complete", this._syntaxHighlightingComplete, this);
+ this.sourceFrame.syntaxHighlightJavascript();
+};
+
+
+/**
+ * Dummy object used during properties inspection.
+ * @see WebInspector.didGetNodePropertiesAsync_
+ */
+WebInspector.dummyObject_ = { 'foo' : 'bar' };
+
+
+/**
+ * Dummy function used during properties inspection.
+ * @see WebInspector.didGetNodePropertiesAsync_
+ */
+WebInspector.dummyFunction_ = function() {};
+
+
+/**
+ * Callback function used with the getNodeProperties.
+ */
+WebInspector.didGetNodePropertiesAsync_ = function(treeOutline, constructor,
+ nodeId, path, json) {
+ var props = JSON.parse(json);
+ var properties = [];
+ var obj = {};
+ obj.devtools$$nodeId_ = nodeId;
+ obj.devtools$$path_ = path;
+ for (var i = 0; i < props.length; i += 3) {
+ var type = props[i];
+ var name = props[i + 1];
+ var value = props[i + 2];
+ properties.push(name);
+ if (type == 'object') {
+ // fake object is going to be replaced on expand.
+ obj[name] = WebInspector.dummyObject_;
+ } else if (type == 'function') {
+ // fake function is going to be replaced on expand.
+ obj[name] = WebInspector.dummyFunction_;
+ } else {
+ obj[name] = value;
+ }
+ }
+ properties.sort();
+
+ treeOutline.removeChildren();
+
+ for (var i = 0; i < properties.length; ++i) {
+ var propertyName = properties[i];
+ treeOutline.appendChild(new constructor(obj, propertyName));
+ }
+};
+
+
+/**
+ * Replace WebKit method with our own implementation to use our call stack
+ * representation. Original method uses Object.prototype.toString.call to
+ * learn if scope object is a JSActivation which doesn't work in Chrome.
+ */
+WebInspector.ScopeChainSidebarPane.prototype.update = function(callFrame) {
+ this.bodyElement.removeChildren();
+
+ this.sections = [];
+ this.callFrame = callFrame;
+
+ if (!callFrame) {
+ var infoElement = document.createElement('div');
+ infoElement.className = 'info';
+ infoElement.textContent = WebInspector.UIString('Not Paused');
+ this.bodyElement.appendChild(infoElement);
+ return;
+ }
+
+ if (!callFrame._expandedProperties) {
+ callFrame._expandedProperties = {};
+ }
+
+ var scopeObject = callFrame.localScope;
+ var title = WebInspector.UIString('Local');
+ var subtitle = Object.describe(scopeObject, true);
+ var emptyPlaceholder = null;
+ var extraProperties = null;
+
+ var section = new WebInspector.ObjectPropertiesSection(scopeObject, title,
+ subtitle, emptyPlaceholder, true, extraProperties,
+ WebInspector.ScopeChainSidebarPane.TreeElement);
+ section.editInSelectedCallFrameWhenPaused = true;
+ section.pane = this;
+
+ section.expanded = true;
+
+ this.sections.push(section);
+ this.bodyElement.appendChild(section.element);
+};
+
+
+/**
+ * Custom implementation of TreeElement that asynchronously resolves children
+ * using the debugger agent.
+ * @constructor
+ */
+WebInspector.ScopeChainSidebarPane.TreeElement = function(parentObject,
+ propertyName) {
+ WebInspector.ScopeVariableTreeElement.call(this, parentObject, propertyName);
+}
+WebInspector.ScopeChainSidebarPane.TreeElement.inherits(
+ WebInspector.ScopeVariableTreeElement);
+
+
+/**
+ * @override
+ */
+WebInspector.ScopeChainSidebarPane.TreeElement.prototype.onpopulate =
+ function() {
+ var obj = this.parentObject[this.propertyName];
+ devtools.tools.getDebuggerAgent().resolveChildren(obj,
+ goog.bind(this.didResolveChildren_, this));
+};
+
+
+/**
+ * Callback function used with the resolveChildren.
+ */
+WebInspector.ScopeChainSidebarPane.TreeElement.prototype.didResolveChildren_ =
+ function(object) {
+ this.removeChildren();
+ var constructor = this.treeOutline.section.treeElementConstructor;
+ object = object.resolvedValue;
+ for (var name in object) {
+ this.appendChild(new constructor(object, name));
+ }
+};
+
+
+/**
+ * @override
+ */
+WebInspector.StylePropertyTreeElement.prototype.toggleEnabled =
+ function(event) {
+ var enabled = event.target.checked;
+ devtools.tools.getDomAgent().toggleNodeStyleAsync(
+ this.style,
+ enabled,
+ this.name,
+ WebInspector.updateStylesAndMetrics_);
+};
+
+
+/**
+ * @override
+ */
+WebInspector.StylePropertyTreeElement.prototype.applyStyleText = function(
+ styleText, updateInterface) {
+ devtools.tools.getDomAgent().applyStyleTextAsync(this.style, this.name,
+ styleText,
+ function() {
+ if (updateInterface) {
+ WebInspector.updateStylesAndMetrics_();
+ }
+ });
+};
+
+
+/**
+ * Forces update of styles and metrics sidebar panes.
+ */
+WebInspector.updateStylesAndMetrics_ = function() {
+ WebInspector.panels.elements.sidebarPanes.metrics.needsUpdate = true;
+ WebInspector.panels.elements.updateMetrics();
+ WebInspector.panels.elements.sidebarPanes.styles.needsUpdate = true;
+ WebInspector.panels.elements.updateStyles(true);
+};
+
+
+/**
+ * This function overrides standard searchableViews getters to perform search
+ * only in the current view (other views are loaded asynchronously, no way to
+ * search them yet).
+ */
+WebInspector.searchableViews_ = function() {
+ var views = [];
+ const visibleView = this.visibleView;
+ if (visibleView && visibleView.performSearch) {
+ views.push(visibleView);
+ }
+ return views;
+};
+
+
+/**
+ * @override
+ */
+WebInspector.ResourcesPanel.prototype.__defineGetter__(
+ 'searchableViews',
+ WebInspector.searchableViews_);
+
+
+/**
+ * @override
+ */
+WebInspector.ScriptsPanel.prototype.__defineGetter__(
+ 'searchableViews',
+ WebInspector.searchableViews_);
+
+
+/**
+ * @override
+ */
+WebInspector.Console.prototype._evalInInspectedWindow = function(expression) {
+ if (WebInspector.panels.scripts.paused)
+ return WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression);
+
+ var console = this;
+ devtools.tools.evaluateJavaScript(expression, function(response) {
+ // TODO(yurys): send exception information along with the response
+ var exception = false;
+ console.addMessage(new WebInspector.ConsoleCommandResult(
+ response, exception, null /* commandMessage */));
+ });
+ // TODO(yurys): refactor WebInspector.Console so that the result is added into
+ // the command log message.
+ return 'evaluating...';
+};
+
+
+(function() {
+ var oldShow = WebInspector.ScriptsPanel.prototype.show;
+ WebInspector.ScriptsPanel.prototype.show = function() {
+ devtools.tools.getDebuggerAgent().initializeScriptsCache();
+ oldShow.call(this);
+ };
+})();
+
+
+// As columns in data grid can't be changed after initialization,
+// we need to intercept the constructor and modify columns upon creation.
+(function InterceptDataGridForProfiler() {
+ var originalDataGrid = WebInspector.DataGrid;
+ WebInspector.DataGrid = function(columns) {
+ if (('average' in columns) && ('calls' in columns)) {
+ delete columns['average'];
+ delete columns['calls'];
+ }
+ return new originalDataGrid(columns);
+ };
+})();
+
+
+// WebKit's profiler displays milliseconds with high resolution (shows
+// three digits after the decimal point). We never have such resolution,
+// as our minimal sampling rate is 1 ms. So we are disabling high resolution
+// to avoid visual clutter caused by meaningless ".000" parts.
+(function InterceptTimeDisplayInProfiler() {
+ var originalDataGetter =
+ WebInspector.ProfileDataGridNode.prototype.__lookupGetter__('data');
+ WebInspector.ProfileDataGridNode.prototype.__defineGetter__('data',
+ function() {
+ var oldNumberSecondsToString = Number.secondsToString;
+ Number.secondsToString = function(seconds, formatterFunction) {
+ return oldNumberSecondsToString(seconds, formatterFunction, false);
+ };
+ var data = originalDataGetter.call(this);
+ Number.secondsToString = oldNumberSecondsToString;
+ return data;
+ });
+})();
+
+
+(function InterceptProfilesPanelEvents() {
+ var oldShow = WebInspector.ProfilesPanel.prototype.show;
+ WebInspector.ProfilesPanel.prototype.show = function() {
+ devtools.tools.getDebuggerAgent().initializeProfiling();
+ 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(pfeldman): Add l10n.
+ */
+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 = 'Developer Tools - ' + resource.url;
+ }
+ };
+})();
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/devtools_callback.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/devtools_callback.js
new file mode 100644
index 0000000..f252861
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/devtools_callback.js
@@ -0,0 +1,57 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Generic callback manager.
+ */
+goog.provide('devtools.Callback');
+
+
+/**
+ * Generic callback support as a singleton object.
+ * @constructor
+ */
+devtools.Callback = function() {
+ this.lastCallbackId_ = 1;
+ this.callbacks_ = {};
+};
+
+
+/**
+ * Assigns id to a callback.
+ * @param {Function} callback Callback to assign id to.
+ * @return {number} Callback id.
+ */
+devtools.Callback.prototype.wrap = function(callback) {
+ var callbackId = this.lastCallbackId_++;
+ this.callbacks_[callbackId] = callback || function() {};
+ return callbackId;
+};
+
+
+/**
+ * Executes callback with the given id.
+ * @param {callbackId} callbackId Id of a callback to call.
+ */
+devtools.Callback.prototype.processCallback = function(callbackId,
+ opt_vararg) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ var callback = this.callbacks_[callbackId];
+ callback.apply(null, args);
+ delete this.callbacks_[callbackId];
+};
+
+
+/**
+ * @type {devtools.Callback} Callback support singleton.
+ * @private
+ */
+devtools.Callback.INSTANCE_ = new devtools.Callback();
+
+devtools.Callback.wrap = goog.bind(
+ devtools.Callback.INSTANCE_.wrap,
+ devtools.Callback.INSTANCE_);
+devtools.Callback.processCallback = goog.bind(
+ devtools.Callback.INSTANCE_.processCallback,
+ devtools.Callback.INSTANCE_);
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/devtools_host_stub.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/devtools_host_stub.js
new file mode 100644
index 0000000..42a27ea
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/devtools_host_stub.js
@@ -0,0 +1,341 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview These stubs emulate backend functionality and allows
+ * DevTools frontend to function as a standalone web app.
+ */
+
+/**
+ * @constructor
+ */
+RemoteDebuggerAgentStub = function() {
+ this.isProfiling_ = false;
+ this.profileLogPos_ = 0;
+};
+
+RemoteDebuggerAgentStub.prototype.DebugBreak = function() {
+};
+
+RemoteDebuggerAgentStub.prototype.GetContextId = function() {
+ RemoteDebuggerAgent.DidGetContextId(3);
+};
+
+RemoteDebuggerAgentStub.prototype.StopProfiling = function() {
+ this.isProfiling_ = false;
+};
+
+RemoteDebuggerAgentStub.prototype.StartProfiling = function() {
+ this.isProfiling_ = true;
+};
+
+RemoteDebuggerAgentStub.prototype.IsProfilingStarted = function() {
+ var self = this;
+ setTimeout(function() {
+ RemoteDebuggerAgent.DidIsProfilingStarted(self.isProfiling_);
+ }, 100);
+};
+
+RemoteDebuggerAgentStub.prototype.GetNextLogLines = function() {
+ if (this.profileLogPos_ < RemoteDebuggerAgentStub.ProfilerLogBuffer.length) {
+ this.profileLogPos_ += RemoteDebuggerAgentStub.ProfilerLogBuffer.length;
+ setTimeout(function() {
+ RemoteDebuggerAgent.DidGetNextLogLines(
+ RemoteDebuggerAgentStub.ProfilerLogBuffer);
+ },
+ 100);
+ } else {
+ setTimeout(function() { RemoteDebuggerAgent.DidGetNextLogLines(''); }, 100);
+ }
+};
+
+/**
+ * @constructor
+ */
+RemoteDomAgentStub = function() {
+};
+
+
+RemoteDomAgentStub.sendDocumentElement_ = function() {
+ RemoteDomAgent.SetDocumentElement([
+ 1, // id
+ 1, // type = Node.ELEMENT_NODE,
+ 'HTML', // nodeName
+ '', // nodeValue
+ ['foo','bar'], // attributes
+ 2, // childNodeCount
+ ]);
+};
+
+
+RemoteDomAgentStub.sendChildNodes_ = function(id) {
+ if (id == 1) {
+ RemoteDomAgent.SetChildNodes(id,
+ [
+ [
+ 2, // id
+ 1, // type = Node.ELEMENT_NODE,
+ 'DIV', // nodeName
+ '', // nodeValue
+ ['foo','bar'], // attributes
+ 1, // childNodeCount
+ ],
+ [
+ 3, // id
+ 3, // type = Node.TEXT_NODE,
+ '', // nodeName
+ 'Text', // nodeValue
+ ]
+ ]);
+ } else if (id == 2) {
+ RemoteDomAgent.SetChildNodes(id,
+ [
+ [
+ 4, // id
+ 1, // type = Node.ELEMENT_NODE,
+ 'span', // nodeName
+ '', // nodeValue
+ ['foo','bar'], // attributes
+ 0, // childNodeCount
+ ]
+ ]);
+ }
+};
+
+
+RemoteDomAgentStub.prototype.GetDocumentElement = function(callId) {
+ setTimeout(function() {
+ RemoteDomAgentStub.sendDocumentElement_();
+ }, 0);
+};
+
+
+RemoteDomAgentStub.prototype.GetChildNodes = function(callId, id) {
+ setTimeout(function() {
+ RemoteDomAgentStub.sendChildNodes_(id);
+ RemoteDomAgent.DidGetChildNodes(callId);
+ }, 0);
+};
+
+
+RemoteDomAgentStub.prototype.SetAttribute = function(callId) {
+ setTimeout(function() {
+ RemoteDomAgent.DidApplyDomChange(callId, true);
+ }, 0);
+};
+
+
+RemoteDomAgentStub.prototype.RemoveAttribute = function(callId) {
+ setTimeout(function() {
+ RemoteDomAgent.DidApplyDomChange(callId, true);
+ }, 0);
+};
+
+
+RemoteDomAgentStub.prototype.SetTextNodeValue = function(callId) {
+ setTimeout(function() {
+ RemoteDomAgent.DidApplyDomChange(callId, true);
+ }, 0);
+};
+
+
+RemoteDomAgentStub.prototype.PerformSearch = function(callId, query) {
+ setTimeout(function() {
+ RemoteDomAgent.DidPerformSearch(callId, [1]);
+ }, 0);
+};
+
+
+RemoteDomAgentStub.prototype.DiscardBindings = function() {
+};
+
+
+/**
+ * @constructor
+ */
+RemoteToolsAgentStub = function() {
+};
+
+
+RemoteToolsAgentStub.prototype.HideDOMNodeHighlight = function() {
+};
+
+
+RemoteToolsAgentStub.prototype.HighlightDOMNode = function() {
+};
+
+
+RemoteToolsAgentStub.prototype.evaluate = function(expr) {
+ window.eval(expr);
+};
+
+RemoteToolsAgentStub.prototype.EvaluateJavaScript = function(callId, script) {
+ setTimeout(function() {
+ var result = eval(script);
+ RemoteToolsAgent.DidEvaluateJavaScript(callId, result);
+ }, 0);
+};
+
+
+RemoteToolsAgentStub.prototype.ExecuteUtilityFunction = function(callId,
+ functionName, nodeId, args) {
+ setTimeout(function() {
+ var result = [];
+ if (functionName == 'getProperties') {
+ result = [
+ 'undefined', 'undefined_key', undefined,
+ 'string', 'string_key', 'value',
+ 'function', 'func', undefined,
+ 'array', 'array_key', [10],
+ 'object', 'object_key', undefined,
+ 'boolean', 'boolean_key', true,
+ 'number', 'num_key', 911,
+ 'date', 'date_key', new Date() ];
+ } else if (functionName == 'getPrototypes') {
+ result = ['Proto1', 'Proto2', 'Proto3'];
+ } else if (functionName == 'getStyles') {
+ result = {
+ 'computedStyle' : [0, '0px', '0px', null, null, null, ['display', false, false, '', 'none']],
+ 'inlineStyle' : [1, '0px', '0px', null, null, null, ['display', false, false, '', 'none']],
+ 'styleAttributes' : {
+ attr: [2, '0px', '0px', null, null, null, ['display', false, false, '', 'none']]
+ },
+ 'matchedCSSRules' : [
+ { 'selector' : 'S',
+ 'style' : [3, '0px', '0px', null, null, null, ['display', false, false, '', 'none']],
+ 'parentStyleSheet' : { 'href' : 'http://localhost',
+ 'ownerNodeName' : 'DIV' }
+ }
+ ]
+ };
+ } else if (functionName == 'toggleNodeStyle' ||
+ functionName == 'applyStyleText' ||
+ functionName == 'setStyleProperty') {
+ alert(functionName + '(' + nodeId + ', ' + args + ')');
+ } else {
+ alert('Unexpected utility function:' + functionName);
+ }
+ RemoteToolsAgent.DidExecuteUtilityFunction(callId,
+ JSON.stringify(result), '');
+ }, 0);
+};
+
+
+RemoteToolsAgentStub.prototype.GetNodePrototypes = function(callId, nodeId) {
+ setTimeout(function() {
+ RemoteToolsAgent.DidGetNodePrototypes(callId,
+ JSON.stringify());
+ }, 0);
+};
+
+
+RemoteToolsAgentStub.prototype.ClearConsoleMessages = function() {
+};
+
+
+RemoteToolsAgentStub.prototype.SetResourceTrackingEnabled = function(enabled, always) {
+ RemoteToolsAgent.SetResourcesPanelEnabled(enabled);
+ if (enabled) {
+ WebInspector.resourceTrackingWasEnabled();
+ } else {
+ WebInspector.resourceTrackingWasDisabled();
+ }
+ addDummyResource();
+};
+
+
+RemoteDebuggerAgentStub.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';
+
+
+/**
+ * @constructor
+ */
+RemoteDebuggerCommandExecutorStub = function() {
+};
+
+
+RemoteDebuggerCommandExecutorStub.prototype.DebuggerCommand = function(cmd) {
+};
+
+
+/**
+ * @constructor
+ */
+DevToolsHostStub = function() {
+ this.isStub = true;
+ window.domAutomationController = {
+ send: function(text) {
+ debugPrint(text);
+ }
+ };
+};
+
+
+function addDummyResource() {
+ var payload = {
+ requestHeaders : {},
+ requestURL: 'http://google.com/simple_page.html',
+ host: 'google.com',
+ path: 'simple_page.html',
+ lastPathComponent: 'simple_page.html',
+ isMainResource: true,
+ cached: false,
+ mimeType: 'text/html',
+ suggestedFilename: 'simple_page.html',
+ expectedContentLength: 10000,
+ statusCode: 200,
+ contentLength: 10000,
+ responseHeaders: {},
+ type: WebInspector.Resource.Type.Document,
+ finished: true,
+ startTime: new Date(),
+
+ didResponseChange: true,
+ didCompletionChange: true,
+ didTypeChange: true
+ };
+
+ WebInspector.addResource(1, payload);
+ WebInspector.updateResource(1, payload);
+}
+
+
+DevToolsHostStub.prototype.loaded = function() {
+ RemoteDomAgentStub.sendDocumentElement_();
+ RemoteDomAgentStub.sendChildNodes_(1);
+ RemoteDomAgentStub.sendChildNodes_(2);
+ devtools.tools.updateFocusedNode_(4);
+ addDummyResource();
+
+ uiTests.runAllTests();
+};
+
+
+DevToolsHostStub.prototype.addResourceSourceToFrame = function(
+ identifier, mimeType, element) {
+};
+
+
+if (!window['DevToolsHost']) {
+ window['RemoteDebuggerAgent'] = new RemoteDebuggerAgentStub();
+ window['RemoteDebuggerCommandExecutor'] =
+ new RemoteDebuggerCommandExecutorStub();
+ window['RemoteDomAgent'] = new RemoteDomAgentStub();
+ window['RemoteToolsAgent'] = new RemoteToolsAgentStub();
+ window['DevToolsHost'] = new DevToolsHostStub();
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/dom_agent.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/dom_agent.js
new file mode 100644
index 0000000..3ab2017
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/dom_agent.js
@@ -0,0 +1,1032 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Dom and DomNode are used to represent remote DOM in the
+ * web inspector.
+ */
+goog.provide('devtools.DomAgent');
+goog.provide('devtools.DomDocument');
+goog.provide('devtools.DomNode');
+
+goog.require('devtools.Callback');
+
+
+/**
+ * Defines indexes for the node payload properties.
+ */
+devtools.PayloadIndex = {
+ ID : 0,
+ TYPE : 1,
+ NAME : 2,
+ VALUE : 3,
+ ATTRS : 4,
+ HAS_CHILDREN : 5,
+ CHILD_NODES : 6
+};
+
+
+/**
+ * Creates document node in a given document based on a given payload data.
+ * @param {devtools.Doc} doc Document to create node in.
+ * @param {Array.<Object>} payload Data to build node based upon.
+ * @constructor
+ */
+devtools.DomNode = function(doc, payload) {
+ this.ownerDocument = doc;
+
+ this.id_ = payload[devtools.PayloadIndex.ID];
+ this.nodeType = payload[devtools.PayloadIndex.TYPE];
+ this.nodeName = payload[devtools.PayloadIndex.NAME];
+ this.nodeValue_ = payload[devtools.PayloadIndex.VALUE];
+ this.textContent = this.nodeValue;
+
+ this.attributes = [];
+ this.attributesMap_ = {};
+ if (payload.length > devtools.PayloadIndex.ATTRS) {
+ this.setAttributesPayload_(payload[devtools.PayloadIndex.ATTRS]);
+ }
+
+ this.childNodesCount_ = payload[devtools.PayloadIndex.HAS_CHILDREN];
+ this.children = null;
+
+ this.nextSibling = null;
+ this.prevSibling = null;
+ this.firstChild = null;
+ this.parentNode = null;
+
+ this.disabledStyleProperties_ = {};
+
+ if (payload.length > devtools.PayloadIndex.CHILD_NODES) {
+ // Has children payloads
+ this.setChildrenPayload_(
+ payload[devtools.PayloadIndex.CHILD_NODES]);
+ }
+
+ this.computedStyle_ = null;
+ this.style = null;
+ this.matchedCSSRules_ = [];
+};
+
+
+/**
+ * Overrides for getters and setters.
+ */
+devtools.DomNode.prototype = {
+ get nodeValue() {
+ return this.nodeValue_;
+ },
+
+ set nodeValue(value) {
+ if (this.nodeType != Node.TEXT_NODE) {
+ return;
+ }
+ var self = this;
+ this.ownerDocument.domAgent_.setTextNodeValueAsync(this, value,
+ function() {
+ self.nodeValue_ = value;
+ self.textContent = value;
+ });
+ }
+};
+
+
+/**
+ * Sets attributes for a given node based on a given attrs payload.
+ * @param {Array.<string>} attrs Attribute key-value pairs to set.
+ * @private
+ */
+devtools.DomNode.prototype.setAttributesPayload_ = function(attrs) {
+ for (var i = 0; i < attrs.length; i += 2) {
+ this.addAttribute_(attrs[i], attrs[i + 1]);
+ }
+};
+
+
+/**
+ * @return True iff node has attributes.
+ */
+devtools.DomNode.prototype.hasAttributes = function() {
+ return this.attributes.length > 0;
+};
+
+
+/**
+ * @return True iff node has child nodes.
+ */
+devtools.DomNode.prototype.hasChildNodes = function() {
+ return this.childNodesCount_ > 0;
+};
+
+
+/**
+ * Inserts child node into this node after a given anchor.
+ * @param {devtools.DomNode} prev Node to insert child after.
+ * @param {Array.<Object>} payload Child node data.
+ * @private
+ */
+devtools.DomNode.prototype.insertChild_ = function(prev, payload) {
+ var node = new devtools.DomNode(this.ownerDocument, payload);
+ if (!prev) {
+ // First node
+ this.children = [ node ];
+ } else {
+ this.children.splice(this.children.indexOf(prev) + 1, 0, node);
+ }
+ this.renumber_();
+ return node;
+};
+
+
+/**
+ * Removes child node from this node.
+ * @param {devtools.DomNode} node Node to remove.
+ * @private
+ */
+devtools.DomNode.prototype.removeChild_ = function(node) {
+ this.children.splice(this.children.indexOf(node), 1);
+ node.parentNode = null;
+ this.renumber_();
+};
+
+
+/**
+ * Sets children for this node based on the given payload.
+ * @param {Array.<Object>} payload Data for children.
+ * @private
+ */
+devtools.DomNode.prototype.setChildrenPayload_ = function(payloads) {
+ this.children = [];
+ for (var i = 0; i < payloads.length; ++i) {
+ var payload = payloads[i];
+ var node = new devtools.DomNode(this.ownerDocument, payload);
+ this.children.push(node);
+ }
+ this.renumber_();
+};
+
+
+/**
+ * Normalizes prev/next/parent/firstChild links for this node's children.
+ * @private
+ */
+devtools.DomNode.prototype.renumber_ = function() {
+ this.childNodesCount_ = this.children.length;
+ if (this.childNodesCount_ == 0) {
+ this.firstChild = null;
+ return;
+ }
+ this.firstChild = this.children[0];
+ for (var i = 0; i < this.childNodesCount_; ++i) {
+ var child = this.children[i];
+ child.nextSibling = i + 1 < this.childNodesCount_ ?
+ this.children[i + 1] : null;
+ child.prevSibling = i - 1 >= 0 ? this.children[i - 1] : null;
+ child.parentNode = this;
+ }
+};
+
+
+/**
+ * Returns attribute value.
+ * @param {string} name Attribute name to get value for.
+ * @return {string} Attribute value.
+ */
+devtools.DomNode.prototype.getAttribute = function(name) {
+ var attr = this.attributesMap_[name];
+ return attr ? attr.value : undefined;
+};
+
+
+/**
+ * Sends 'set attribute' command to the remote agent.
+ * @param {string} name Attribute name to set value for.
+ * @param {string} value Attribute value to set.
+ */
+devtools.DomNode.prototype.setAttribute = function(name, value) {
+ var self = this;
+ this.ownerDocument.domAgent_.setAttributeAsync(this, name, value,
+ function() {
+ var attr = self.attributesMap_[name];
+ if (attr) {
+ attr.value = value;
+ } else {
+ attr = self.addAttribute_(name, value);
+ }
+ });
+};
+
+
+/**
+ * Creates an attribute-like object and adds it to the object.
+ * @param {string} name Attribute name to set value for.
+ * @param {string} value Attribute value to set.
+ */
+devtools.DomNode.prototype.addAttribute_ = function(name, value) {
+ var attr = {
+ 'name': name,
+ 'value': value,
+ node_: this
+ };
+
+ this.attributesMap_[name] = attr;
+ this.attributes.push(attr);
+};
+
+
+/**
+ * Sends 'remove attribute' command to the remote agent.
+ * @param {string} name Attribute name to set value for.
+ */
+devtools.DomNode.prototype.removeAttribute = function(name) {
+ var self = this;
+ this.ownerDocument.domAgent_.removeAttributeAsync(this, name, function() {
+ delete self.attributesMap_[name];
+ for (var i = 0; i < self.attributes.length; ++i) {
+ if (self.attributes[i].name == name) {
+ self.attributes.splice(i, 1);
+ break;
+ }
+ }
+ });
+};
+
+
+/**
+ * Makes available the following methods and properties:
+ * - node.style property
+ * - node.document.defaultView.getComputedStyles(node)
+ * - node.document.defaultView.getMatchedCSSRules(node, ...)
+ * - style attribute of node's attributes
+ * @param {string} computedStyle is a cssText of result of getComputedStyle().
+ * @param {string} inlineStyle is a style.cssText (defined in the STYLE
+ * attribute).
+ * @param {Object} styleAttributes represents 'style' property
+ * of attributes.
+ * @param {Array.<object>} matchedCSSRules represents result of the
+ * getMatchedCSSRules(node, '', authorOnly). Each elemet consists of:
+ * selector, rule.style.cssText[, rule.parentStyleSheet.href
+ * [, rule.parentStyleSheet.ownerNode.nodeName]].
+ */
+devtools.DomNode.prototype.setStyles = function(computedStyle, inlineStyle,
+ styleAttributes, matchedCSSRules) {
+ this.computedStyle_ = this.makeStyle_(computedStyle);
+ this.style = this.makeStyle_(inlineStyle);
+
+ for (var name in styleAttributes) {
+ if (this.attributesMap_[name]) {
+ this.attributesMap_[name].style =
+ this.makeStyle_(styleAttributes[name]);
+ }
+ }
+
+ this.matchedCSSRules_ = [];
+ for (var i = 0; i < matchedCSSRules.length; i++) {
+ var descr = matchedCSSRules[i];
+
+ var rule = {};
+ rule.selectorText = descr['selector'];
+ rule.style = this.makeStyle_(descr['style']);
+
+ if (descr['parentStyleSheet']) {
+ var parentStyleMock = {};
+ parentStyleMock.href = descr['parentStyleSheet']['href'];
+ var nodeName = descr['parentStyleSheet']['ownerNodeName'];
+ if (nodeName) {
+ parentStyleMock.ownerNode = {
+ 'nodeName': nodeName
+ };
+ }
+ rule.parentStyleSheet = parentStyleMock;
+ }
+ this.matchedCSSRules_.push(rule);
+ }
+};
+
+
+/**
+ * Creates a style declaration.
+ * @param {payload} payload
+ * @return {devtools.CSSStyleDeclaration:undefined}
+ * @see devtools.CSSStyleDeclaration
+ */
+devtools.DomNode.prototype.makeStyle_ = function(payload) {
+ var style = new devtools.CSSStyleDeclaration(payload);
+ style.nodeId_ = this.id_;
+ return style;
+};
+
+
+/**
+ * Remove references to the style information to release
+ * resources when styles are not going to be used.
+ * @see setStyles.
+ */
+devtools.DomNode.prototype.clearStyles = function() {
+ this.computedStyle = null;
+ this.style = null;
+ for (var name in this.attributesMap_) {
+ this.attributesMap_[name].style = null;
+ }
+ this.matchedCSSRules_ = null;
+};
+
+
+/**
+ * Remote Dom document abstraction.
+ * @param {devtools.DomAgent} domAgent owner agent.
+ * @param {devtools.DomWindow} defaultView owner window.
+ * @constructor.
+ */
+devtools.DomDocument = function(domAgent, defaultView) {
+ devtools.DomNode.call(this, null,
+ [
+ 0, // id
+ 9, // type = Node.DOCUMENT_NODE,
+ '', // nodeName
+ '', // nodeValue
+ [], // attributes
+ 0, // childNodeCount
+ ]);
+ this.listeners_ = {};
+ this.domAgent_ = domAgent;
+ this.defaultView = defaultView;
+};
+goog.inherits(devtools.DomDocument, devtools.DomNode);
+
+
+/**
+ * Adds event listener to the Dom.
+ * @param {string} name Event name.
+ * @param {function(Event):undefined} callback Listener callback.
+ * @param {bool} useCapture Listener's useCapture settings.
+ */
+devtools.DomDocument.prototype.addEventListener =
+ function(name, callback, useCapture) {
+ var listeners = this.listeners_[name];
+ if (!listeners) {
+ listeners = [];
+ this.listeners_[name] = listeners;
+ }
+ listeners.push(callback);
+};
+
+
+/**
+ * Removes event listener from the Dom.
+ * @param {string} name Event name.
+ * @param {function(Event):undefined} callback Listener callback.
+ * @param {bool} useCapture Listener's useCapture settings.
+ */
+devtools.DomDocument.prototype.removeEventListener =
+ function(name, callback, useCapture) {
+ var listeners = this.listeners_[name];
+ if (!listeners) {
+ return;
+ }
+ var index = listeners.indexOf(callback);
+ if (index != -1) {
+ listeners.splice(index, 1);
+ }
+};
+
+
+/**
+ * Fires Dom event to the listeners for given event type.
+ * @param {string} name Event type.
+ * @param {Event} event Event to fire.
+ * @private
+ */
+devtools.DomDocument.prototype.fireDomEvent_ = function(name, event) {
+ var listeners = this.listeners_[name];
+ if (!listeners) {
+ return;
+ }
+ for (var i = 0; i < listeners.length; ++i) {
+ listeners[i](event);
+ }
+};
+
+
+
+/**
+ * Simulation of inspected DOMWindow.
+ * @param {devtools.DomAgent} domAgent owner agent.
+ * @constructor
+ */
+devtools.DomWindow = function(domAgent) {
+ this.document = new devtools.DomDocument(domAgent, this);
+};
+
+/**
+ * Represents DOM Node class.
+ */
+devtools.DomWindow.prototype.__defineGetter__('Node', function() {
+ return devtools.DomNode;
+});
+
+/**
+ * Represents DOM Element class.
+ * @constructor
+ */
+devtools.DomWindow.prototype.__defineGetter__('Element', function() {
+ return devtools.DomNode;
+});
+
+
+/**
+ * See usages in ScopeChainSidebarPane.js where it's called as
+ * constructor.
+ */
+devtools.DomWindow.prototype.Object = function() {
+};
+
+
+/**
+ * Simulates the DOM interface for styles.
+ * @param {devtools.DomNode} node
+ * @return {CSSStyleDescription}
+ */
+devtools.DomWindow.prototype.getComputedStyle = function(node) {
+ return node.computedStyle_;
+};
+
+
+/**
+ * Simulates the DOM interface for styles.
+ * @param {devtools.DomNode} nodeStyles
+ * @param {string} pseudoElement assumed to be empty string.
+ * @param {boolean} authorOnly assumed to be equal to authorOnly argument of
+ * getNodeStylesAsync.
+ * @return {CSSStyleDescription}
+ */
+devtools.DomWindow.prototype.getMatchedCSSRules = function(node,
+ pseudoElement, authorOnly) {
+ return node.matchedCSSRules_;
+};
+
+
+/**
+ * Creates DomAgent Js representation.
+ * @constructor
+ */
+devtools.DomAgent = function() {
+ RemoteDomAgent.DidGetChildNodes =
+ devtools.Callback.processCallback;
+ RemoteDomAgent.DidPerformSearch =
+ devtools.Callback.processCallback;
+ RemoteDomAgent.DidApplyDomChange =
+ devtools.Callback.processCallback;
+ RemoteDomAgent.DidRemoveAttribute =
+ devtools.Callback.processCallback;
+ RemoteDomAgent.DidSetTextNodeValue =
+ devtools.Callback.processCallback;
+ RemoteDomAgent.AttributesUpdated =
+ goog.bind(this.attributesUpdated_, this);
+ RemoteDomAgent.SetDocumentElement =
+ goog.bind(this.setDocumentElement_, this);
+ RemoteDomAgent.SetChildNodes =
+ goog.bind(this.setChildNodes_, this);
+ RemoteDomAgent.HasChildrenUpdated =
+ goog.bind(this.hasChildrenUpdated_, this);
+ RemoteDomAgent.ChildNodeInserted =
+ goog.bind(this.childNodeInserted_, this);
+ RemoteDomAgent.ChildNodeRemoved =
+ goog.bind(this.childNodeRemoved_, this);
+
+ /**
+ * Top-level (and the only) document.
+ * @type {devtools.DomWindow}
+ * @private
+ */
+ this.window_ = null;
+
+ /**
+ * Id to node mapping.
+ * @type {Object}
+ * @private
+ */
+ this.idToDomNode_ = null;
+
+ /**
+ * @type {Array.<number>} Node ids for search results.
+ * @private
+ */
+ this.searchResults_ = null;
+};
+
+
+/**
+ * Resets dom agent to its initial state.
+ */
+devtools.DomAgent.prototype.reset = function() {
+ this.window_ = new devtools.DomWindow(this);
+ this.idToDomNode_ = { 0 : this.getDocument() };
+ this.searchResults_ = [];
+};
+
+
+/**
+ * @return {devtools.DomWindow} Window for the top level (and the only) document.
+ */
+devtools.DomAgent.prototype.getWindow = function() {
+ return this.window_;
+};
+
+
+/**
+ * @return {devtools.DomDocument} A document of the top level window.
+ */
+devtools.DomAgent.prototype.getDocument = function() {
+ return this.window_.document;
+};
+
+
+/**
+ * Requests that the document element is sent from the agent.
+ */
+devtools.DomAgent.prototype.getDocumentElementAsync = function() {
+ if (this.getDocument().documentElement) {
+ return;
+ }
+ RemoteDomAgent.GetDocumentElement();
+};
+
+
+/**
+ * Asynchronously fetches children from the element with given id.
+ * @param {devtools.DomNode} parent Element to get children for.
+ * @param {function(devtools.DomNode):undefined} opt_callback Callback with
+ * the result.
+ */
+devtools.DomAgent.prototype.getChildNodesAsync = function(parent,
+ opt_callback) {
+ var children = parent.children;
+ if (children && opt_callback) {
+ opt_callback(children);
+ return;
+ }
+ var mycallback = function() {
+ if (opt_callback) {
+ opt_callback(parent.children);
+ }
+ };
+ var callId = devtools.Callback.wrap(mycallback);
+ RemoteDomAgent.GetChildNodes(callId, parent.id_);
+};
+
+
+/**
+ * Sends 'set attribute' command to the remote agent.
+ * @param {devtools.DomNode} node Node to change.
+ * @param {string} name Attribute name to set value for.
+ * @param {string} value Attribute value to set.
+ * @param {function():undefined} opt_callback Callback on success.
+ */
+devtools.DomAgent.prototype.setAttributeAsync = function(node, name, value,
+ callback) {
+ var mycallback = goog.bind(this.didApplyDomChange_, this, node, callback);
+ RemoteDomAgent.SetAttribute(devtools.Callback.wrap(mycallback),
+ node.id_, name, value);
+};
+
+
+/**
+ * Sends 'remove attribute' command to the remote agent.
+ * @param {devtools.DomNode} node Node to change.
+ * @param {string} name Attribute name to set value for.
+ * @param {function():undefined} opt_callback Callback on success.
+ */
+devtools.DomAgent.prototype.removeAttributeAsync = function(node, name,
+ callback) {
+ var mycallback = goog.bind(this.didApplyDomChange_, this, node, callback);
+ RemoteDomAgent.RemoveAttribute(devtools.Callback.wrap(mycallback),
+ node.id_, name);
+};
+
+
+/**
+ * Sends 'set text node value' command to the remote agent.
+ * @param {devtools.DomNode} node Node to change.
+ * @param {string} text Text value to set.
+ * @param {function():undefined} opt_callback Callback on success.
+ */
+devtools.DomAgent.prototype.setTextNodeValueAsync = function(node, text,
+ callback) {
+ var mycallback = goog.bind(this.didApplyDomChange_, this, node, callback);
+ RemoteDomAgent.SetTextNodeValue(devtools.Callback.wrap(mycallback),
+ node.id_, text);
+};
+
+
+/**
+ * Universal callback wrapper for edit dom operations.
+ * @param {devtools.DomNode} node Node to apply local changes on.
+ * @param {Function} callback Post-operation call.
+ * @param {boolean} success True iff operation has completed successfully.
+ * @private
+ */
+devtools.DomAgent.prototype.didApplyDomChange_ = function(node,
+ callback, success) {
+ if (!success) {
+ return;
+ }
+ callback();
+ var elem = WebInspector.panels.elements.treeOutline.findTreeElement(node);
+ if (elem) {
+ elem._updateTitle();
+ }
+};
+
+
+/**
+ * @see DomAgentDelegate.
+ * {@inheritDoc}.
+ * @private
+ */
+devtools.DomAgent.prototype.attributesUpdated_ = function(nodeId, attrsArray) {
+ var node = this.idToDomNode_[nodeId];
+ node.setAttributesPayload_(attrsArray);
+};
+
+
+/**
+ * Returns node for id.
+ * @param {number} nodeId Id to get node for.
+ * @return {devtools.DomNode} Node with given id.
+ */
+devtools.DomAgent.prototype.getNodeForId = function(nodeId) {
+ return this.idToDomNode_[nodeId];
+};
+
+
+/**
+ * @see DomAgentDelegate.
+ * {@inheritDoc}.
+ * @private
+ */
+devtools.DomAgent.prototype.setDocumentElement_ = function(payload) {
+ var doc = this.getDocument();
+ if (doc.documentElement) {
+ this.reset();
+ doc = this.getDocument();
+ }
+ this.setChildNodes_(0, [payload]);
+ doc.documentElement = doc.firstChild;
+ doc.documentElement.ownerDocument = doc;
+ WebInspector.panels.elements.reset();
+};
+
+
+/**
+ * @see DomAgentDelegate.
+ * {@inheritDoc}.
+ * @private
+ */
+devtools.DomAgent.prototype.setChildNodes_ = function(parentId, payloads) {
+ var parent = this.idToDomNode_[parentId];
+ if (parent.children) {
+ return;
+ }
+ parent.setChildrenPayload_(payloads);
+ this.bindNodes_(parent.children);
+};
+
+
+/**
+ * Binds nodes to ids recursively.
+ * @param {Array.<devtools.DomNode>} children Nodes to bind.
+ * @private
+ */
+devtools.DomAgent.prototype.bindNodes_ = function(children) {
+ for (var i = 0; i < children.length; ++i) {
+ var child = children[i];
+ this.idToDomNode_[child.id_] = child;
+ if (child.children) {
+ this.bindNodes_(child.children);
+ }
+ }
+};
+
+
+/**
+ * @see DomAgentDelegate.
+ * {@inheritDoc}.
+ * @private
+ */
+devtools.DomAgent.prototype.hasChildrenUpdated_ = function(nodeId, newValue) {
+ var node = this.idToDomNode_[nodeId];
+ var outline = WebInspector.panels.elements.treeOutline;
+ var treeElement = outline.findTreeElement(node);
+ if (treeElement) {
+ treeElement.hasChildren = newValue;
+ treeElement.whitespaceIgnored = Preferences.ignoreWhitespace;
+ }
+};
+
+
+/**
+ * @see DomAgentDelegate.
+ * {@inheritDoc}.
+ * @private
+ */
+devtools.DomAgent.prototype.childNodeInserted_ = function(
+ parentId, prevId, payload) {
+ var parent = this.idToDomNode_[parentId];
+ var prev = this.idToDomNode_[prevId];
+ var node = parent.insertChild_(prev, payload);
+ this.idToDomNode_[node.id_] = node;
+ var event = { target : node, relatedNode : parent };
+ this.getDocument().fireDomEvent_('DOMNodeInserted', event);
+};
+
+
+/**
+ * @see DomAgentDelegate.
+ * {@inheritDoc}.
+ * @private
+ */
+devtools.DomAgent.prototype.childNodeRemoved_ = function(
+ parentId, nodeId) {
+ var parent = this.idToDomNode_[parentId];
+ var node = this.idToDomNode_[nodeId];
+ parent.removeChild_(node);
+ var event = { target : node, relatedNode : parent };
+ this.getDocument().fireDomEvent_('DOMNodeRemoved', event);
+ delete this.idToDomNode_[nodeId];
+};
+
+
+/**
+ * @see DomAgentDelegate.
+ * {@inheritDoc}.
+ */
+devtools.DomAgent.prototype.performSearch = function(query, callback) {
+ this.searchResults_ = [];
+ RemoteDomAgent.PerformSearch(
+ devtools.Callback.wrap(
+ goog.bind(this.performSearchCallback_, this, callback,
+ this.searchResults_)),
+ query);
+};
+
+
+/**
+ * Invokes callback for nodes that needs to clear highlighting.
+ * @param {function(Array.<devtools.DomNode>)} callback to accept the result.
+ */
+devtools.DomAgent.prototype.searchCanceled = function(callback) {
+ if (!this.searchResults_)
+ return;
+
+ var nodes = [];
+ for (var i = 0; i < this.searchResults_.length; ++i) {
+ var nodeId = this.searchResults_[i];
+ var node = this.idToDomNode_[nodeId];
+ nodes.push(node);
+ }
+
+ callback(nodes);
+ this.searchResults_ = null;
+};
+
+
+/**
+ * Invokes callback for each node that needs to gain highlighting.
+ * @param {function(Array.<devtools.DomNode>)} callback to accept the result.
+ * @param {Array.<number>} searchResults to be populated.
+ * @param {Array.<number>} nodeIds Ids to highlight.
+ * @private
+ */
+devtools.DomAgent.prototype.performSearchCallback_ = function(callback,
+ searchResults, nodeIds) {
+
+ if (this.searchResults_ !== searchResults)
+ return; // another search has requested and this results are obsolete
+
+ var nodes = [];
+
+ for (var i = 0; i < nodeIds.length; ++i) {
+ var node = this.idToDomNode_[nodeIds[i]];
+ searchResults.push(nodeIds[i]);
+ nodes.push(node);
+ }
+
+ callback(nodes);
+};
+
+
+/**
+ * Returns a node by index from the actual search results
+ * (last performSearch).
+ * @param {number} index in the results.
+ * @return {devtools.DomNode}
+ */
+devtools.DomAgent.prototype.getSearchResultNode = function(index) {
+ return this.idToDomNode_[this.searchResults_[index]];
+};
+
+
+/**
+ * Returns all properties of the given node.
+ * @param {number} nodeId Node to get properties for.
+ * @param {Array.<string>} path Path to the object.
+ * @param {number} protoDepth Depth to the exact proto level.
+ * @param {function(string):undefined} callback Function to call with the
+ * result.
+ */
+devtools.DomAgent.prototype.getNodePropertiesAsync = function(nodeId,
+ path, protoDepth, callback) {
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
+ RemoteToolsAgent.ExecuteUtilityFunction(callbackId,
+ 'getProperties', nodeId,
+ JSON.stringify([path, protoDepth]));
+};
+
+
+/**
+ * Returns prototype chain for a given node.
+ * @param {number} nodeId Node to get prototypes for.
+ * @param {Function} callback.
+ */
+devtools.DomAgent.prototype.getNodePrototypesAsync = function(nodeId,
+ callback) {
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
+ RemoteToolsAgent.ExecuteUtilityFunction(callbackId,
+ 'getPrototypes', nodeId, '[]');
+};
+
+
+/**
+ * Returns styles for given node.
+ * @param {devtools.DomNode} node Node to get prototypes for.
+ * @param {boolean} authorOnly Returns only author styles if true.
+ * @param {Function} callback.
+ */
+devtools.DomAgent.prototype.getNodeStylesAsync = function(node,
+ authorOnly, callback) {
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
+ RemoteToolsAgent.ExecuteUtilityFunction(callbackId,
+ 'getStyles',
+ node.id_,
+ JSON.stringify([authorOnly]));
+};
+
+
+/**
+ * Toggles style with given id on/off.
+ * @param {devtools.CSSStyleDeclaration} style Style to toggle.
+ * @param {boolean} enabled True if style should be enabled.
+ * @param {string} name Style name.
+ * @param {Function} callback.
+ */
+devtools.DomAgent.prototype.toggleNodeStyleAsync = function(
+ style, enabled, name, callback) {
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
+ RemoteToolsAgent.ExecuteUtilityFunction(callbackId,
+ 'toggleNodeStyle',
+ style.nodeId_,
+ JSON.stringify([style.id_, enabled, name]));
+};
+
+
+/**
+ * Applies new text to a style.
+ * @param {devtools.CSSStyleDeclaration} style Style to edit.
+ * @param {string} name Property name to edit.
+ * @param {string} styleText Text to set the style from.
+ * @param {Function} callback.
+ */
+devtools.DomAgent.prototype.applyStyleTextAsync = function(
+ style, name, styleText, callback) {
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
+ RemoteToolsAgent.ExecuteUtilityFunction(
+ callbackId,
+ 'applyStyleText',
+ style.nodeId_,
+ JSON.stringify([style.id_, name, styleText]));
+};
+
+
+/**
+ * Sets style property with given name to a value.
+ * @param {devtools.DomNode} node Node to edit style for.
+ * @param {string} name Property name to edit.
+ * @param {string} value New value.
+ * @param {Function} callback.
+ */
+devtools.DomAgent.prototype.setStylePropertyAsync = function(
+ node, name, value, callback) {
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
+ RemoteToolsAgent.ExecuteUtilityFunction(
+ callbackId,
+ 'setStyleProperty',
+ node.id_,
+ JSON.stringify([name, value]));
+};
+
+
+/**
+ * Dumps exception if something went wrong in ExecuteUtilityFunction.
+ * @param {Function} callback Callback to wrap.
+ * @return {number} Callback id.
+ */
+devtools.DomAgent.prototype.utilityFunctionCallbackWrapper_ =
+ function(callback) {
+ var mycallback = function(result, exception) {
+ if (exception && exception.length) {
+ debugPrint('Exception in ExecuteUtilityFunction styles:' + exception);
+ return;
+ }
+ callback(result);
+ };
+ return devtools.Callback.wrap(mycallback);
+};
+
+
+/**
+ * Represents remote CSSStyleDeclaration for using in StyleSidebarPane.
+ * @param {id, Array<Object>} payload built by inject's getStyle from the
+ * injected js.
+ * @constructor
+ */
+devtools.CSSStyleDeclaration = function(payload) {
+ this.id_ = payload[0];
+ this.width = payload[1];
+ this.height = payload[2];
+ this.__disabledProperties = payload[3];
+ this.__disabledPropertyValues = payload[4];
+ this.__disabledPropertyPriorities = payload[5];
+
+ this.length = payload.length - 6;
+ this.priority_ = {};
+ this.implicit_ = {};
+ this.shorthand_ = {};
+ this.value_ = {};
+
+ for (var i = 6; i < payload.length; ++i) {
+ var p = payload[i];
+ var name = p[0];
+
+ this.priority_[name] = p[1];
+ this.implicit_[name] = p[2];
+ this.shorthand_[name] = p[3];
+ this.value_[name] = p[4];
+
+ this[i - 6] = name;
+ }
+};
+
+
+/**
+ * @param {string} name of a CSS property.
+ * @return {string}
+ */
+devtools.CSSStyleDeclaration.prototype.getPropertyValue = function(name) {
+ return this.value_[name] || '';
+};
+
+
+/**
+ * @param {string} name of a CSS property.
+ * @return {string} 'important' | ''.
+ */
+devtools.CSSStyleDeclaration.prototype.getPropertyPriority = function(name) {
+ return this.priority_[name] || '';
+};
+
+
+/**
+ * @param {string} name of a CSS property.
+ * @return {string} shorthand name or ''
+ */
+devtools.CSSStyleDeclaration.prototype.getPropertyShorthand = function(name) {
+ return this.shorthand_[name] || '';
+};
+
+
+/**
+ * @param {string} name of a CSS property.
+ * @return {boolean}
+ */
+devtools.CSSStyleDeclaration.prototype.isPropertyImplicit = function(name) {
+ return !!this.implicit_[name];
+};
+
+
+function firstChildSkippingWhitespace() {
+ return this.firstChild;
+}
+
+
+function onlyTextChild() {
+ if (!this.children) {
+ return null;
+ } else if (this.children.length == 1 &&
+ this.children[0].nodeType == Node.TEXT_NODE) {
+ return this.children[0];
+ } else {
+ return null;
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inject.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inject.js
new file mode 100644
index 0000000..5c1050a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inject.js
@@ -0,0 +1,463 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Javascript that is being injected into the inspectable page
+ * while debugging.
+ */
+goog.provide('devtools.Injected');
+
+
+/**
+ * Main injected object.
+ * @constructor.
+ */
+devtools.Injected = function() {
+ /**
+ * Unique style id generator.
+ * @type {number}
+ * @private
+ */
+ this.lastStyleId_ = 1;
+
+ /**
+ * This array is not unused as it may seem. It stores references to the
+ * styles so that they could be found for future editing.
+ * @type {Array<CSSStyleDeclaration>}
+ * @private
+ */
+ this.styles_ = [];
+};
+
+
+/**
+ * Returns array of properties for a given node on a given path.
+ * @param {Node} node Node to get property value for.
+ * @param {Array.<string>} path Path to the nested object.
+ * @param {number} protoDepth Depth of the actual proto to inspect.
+ * @return {Array.<Object>} Array where each property is represented
+ * by the tree entries [{string} type, {string} name, {Object} value].
+ */
+devtools.Injected.prototype.getProperties = function(node, path, protoDepth) {
+ var result = [];
+ var obj = node;
+
+ // Follow the path.
+ for (var i = 0; obj && i < path.length; ++i) {
+ obj = obj[path[i]];
+ }
+
+ if (!obj) {
+ return [];
+ }
+
+ // Get to the necessary proto layer.
+ for (var i = 0; obj && i < protoDepth; ++i) {
+ obj = obj.__proto__;
+ }
+
+ if (!obj) {
+ return [];
+ }
+
+ // Go over properties, prepare results.
+ for (var name in obj) {
+ if (protoDepth != -1 && 'hasOwnProperty' in obj &&
+ !obj.hasOwnProperty(name)) {
+ continue;
+ }
+ var type = typeof obj[name];
+ result.push(type);
+ result.push(name);
+ if (type == 'string') {
+ var str = obj[name];
+ result.push(str.length > 99 ? str.substr(0, 99) + '...' : str);
+ } else if (type != 'object' && type != 'array' &&
+ type != 'function') {
+ result.push(obj[name]);
+ } else {
+ result.push(undefined);
+ }
+ }
+ return result;
+};
+
+
+/**
+ * Returns array of prototypes for a given node.
+ * @param {Node} node Node to get prorotypes for.
+ * @return {Array<string>} Array of proto names.
+ */
+devtools.Injected.prototype.getPrototypes = function(node) {
+ var result = [];
+ for (var prototype = node; prototype; prototype = prototype.__proto__) {
+ var description = Object.prototype.toString.call(prototype);
+ result.push(description.replace(/^\[object (.*)\]$/i, '$1'));
+ }
+ return result;
+};
+
+
+/**
+ * Returns style information that is used in devtools.js.
+ * @param {Node} node Node to get prorotypes for.
+ * @param {boolean} authorOnly Determines whether only author styles need to
+ * be added.
+ * @return {string} Style collection descriptor.
+ */
+devtools.Injected.prototype.getStyles = function(node, authorOnly) {
+ if (!node.nodeType == Node.ELEMENT_NODE) {
+ return {};
+ }
+ var matchedRules = window.getMatchedCSSRules(node, '', false);
+ var matchedCSSRulesObj = [];
+ for (var i = 0; matchedRules && i < matchedRules.length; ++i) {
+ var rule = matchedRules[i];
+ var parentStyleSheet = rule.parentStyleSheet;
+ var isUserAgent = parentStyleSheet && !parentStyleSheet.ownerNode &&
+ !parentStyleSheet.href;
+ var isUser = parentStyleSheet && parentStyleSheet.ownerNode &&
+ parentStyleSheet.ownerNode.nodeName == '#document';
+
+ var style = this.serializeStyle_(rule.style, !isUserAgent && !isUser);
+ var ruleValue = {
+ 'selector' : rule.selectorText,
+ 'style' : style
+ };
+ if (parentStyleSheet) {
+ ruleValue['parentStyleSheet'] = {
+ 'href' : parentStyleSheet.href,
+ 'ownerNodeName' : parentStyleSheet.ownerNode ?
+ parentStyleSheet.ownerNode.name : null
+ };
+ }
+ matchedCSSRulesObj.push(ruleValue);
+ }
+
+ var attributeStyles = {};
+ var attributes = node.attributes;
+ for (var i = 0; attributes && i < attributes.length; ++i) {
+ if (attributes[i].style) {
+ attributeStyles[attributes[i].name] =
+ this.serializeStyle_(attributes[i].style, true);
+ }
+ }
+ var result = {
+ 'inlineStyle' : this.serializeStyle_(node.style, true),
+ 'computedStyle' : this.serializeStyle_(
+ window.getComputedStyle(node, '')),
+ 'matchedCSSRules' : matchedCSSRulesObj,
+ 'styleAttributes' : attributeStyles
+ };
+ return result;
+};
+
+
+/**
+ * Returns style decoration object for given id.
+ * @param {Node} node Node to get prorotypes for.
+ * @param {number} id Style id.
+ * @return {Object} Style object.
+ * @private
+ */
+devtools.Injected.prototype.getStyleForId_ = function(node, id) {
+ var matchedRules = window.getMatchedCSSRules(node, '', false);
+ for (var i = 0; matchedRules && i < matchedRules.length; ++i) {
+ var rule = matchedRules[i];
+ if (rule.style.__id == id) {
+ return rule.style;
+ }
+ }
+ var attributes = node.attributes;
+ for (var i = 0; attributes && i < attributes.length; ++i) {
+ if (attributes[i].style && attributes[i].style.__id == id) {
+ return attributes[i].style;
+ }
+ }
+ if (node.style.__id == id) {
+ return node.style;
+ }
+ return null;
+};
+
+
+
+
+/**
+ * Converts given style into serializable object.
+ * @param {CSSStyleDeclaration} style Style to serialize.
+ * @param {boolean} opt_bind Determins whether this style should be bound.
+ * @return {Array<Object>} Serializable object.
+ * @private
+ */
+devtools.Injected.prototype.serializeStyle_ = function(style, opt_bind) {
+ if (!style) {
+ return [];
+ }
+ var id = style.__id;
+ if (opt_bind && !id) {
+ id = style.__id = this.lastStyleId_++;
+ this.styles_.push(style);
+ }
+ var result = [
+ id,
+ style.width,
+ style.height,
+ style.__disabledProperties,
+ style.__disabledPropertyValues,
+ style.__disabledPropertyPriorities
+ ];
+ for (var i = 0; i < style.length; ++i) {
+ var name = style[i];
+ result.push([
+ name,
+ style.getPropertyPriority(name),
+ style.isPropertyImplicit(name),
+ style.getPropertyShorthand(name),
+ style.getPropertyValue(name)
+ ]);
+ }
+ return result;
+};
+
+
+/**
+ * Toggles style with given id on/off.
+ * @param {Node} node Node to get prorotypes for.
+ * @param {number} styleId Id of style to toggle.
+ * @param {boolean} enabled Determines value to toggle to,
+ * @param {string} name Name of the property.
+ */
+devtools.Injected.prototype.toggleNodeStyle = function(node, styleId, enabled,
+ name) {
+ var style = this.getStyleForId_(node, styleId);
+ if (!style) {
+ return false;
+ }
+
+ if (!enabled) {
+ if (!style.__disabledPropertyValues ||
+ !style.__disabledPropertyPriorities) {
+ style.__disabledProperties = {};
+ style.__disabledPropertyValues = {};
+ style.__disabledPropertyPriorities = {};
+ }
+
+ style.__disabledPropertyValues[name] = style.getPropertyValue(name);
+ style.__disabledPropertyPriorities[name] = style.getPropertyPriority(name);
+
+ if (style.getPropertyShorthand(name)) {
+ var longhandProperties = this.getLonghandProperties_(style, name);
+ for (var i = 0; i < longhandProperties.length; ++i) {
+ style.__disabledProperties[longhandProperties[i]] = true;
+ style.removeProperty(longhandProperties[i]);
+ }
+ } else {
+ style.__disabledProperties[name] = true;
+ style.removeProperty(name);
+ }
+ } else if (style.__disabledProperties &&
+ style.__disabledProperties[name]) {
+ var value = style.__disabledPropertyValues[name];
+ var priority = style.__disabledPropertyPriorities[name];
+ style.setProperty(name, value, priority);
+
+ delete style.__disabledProperties[name];
+ delete style.__disabledPropertyValues[name];
+ delete style.__disabledPropertyPriorities[name];
+ }
+ return true;
+};
+
+
+/**
+ * Applies given text to a style.
+ * @param {Node} node Node to get prorotypes for.
+ * @param {number} styleId Id of style to toggle.
+ * @param {string} name Style element name.
+ * @param {string} styleText New style text.
+ * @return {boolean} True iff style has been edited successfully.
+ */
+devtools.Injected.prototype.applyStyleText = function(node, styleId,
+ name, styleText) {
+ var style = this.getStyleForId_(node, styleId);
+ if (!style) {
+ return false;
+ }
+
+ var styleTextLength = this.trimWhitespace_(styleText).length;
+
+ // Create a new element to parse the user input CSS.
+ var parseElement = document.createElement("span");
+ parseElement.setAttribute("style", styleText);
+
+ var tempStyle = parseElement.style;
+ if (tempStyle.length || !styleTextLength) {
+ // The input was parsable or the user deleted everything, so remove the
+ // original property from the real style declaration. If this represents
+ // a shorthand remove all the longhand properties.
+ if (style.getPropertyShorthand(name)) {
+ var longhandProperties = this.getLonghandProperties_(style, name);
+ for (var i = 0; i < longhandProperties.length; ++i) {
+ style.removeProperty(longhandProperties[i]);
+ }
+ } else {
+ style.removeProperty(name);
+ }
+ }
+ if (!tempStyle.length) {
+ // The user typed something, but it didn't parse. Just abort and restore
+ // the original title for this property.
+ return false;
+ }
+
+ // Iterate of the properties on the test element's style declaration and
+ // add them to the real style declaration. We take care to move shorthands.
+ var foundShorthands = {};
+ var uniqueProperties = this.getUniqueStyleProperties_(tempStyle);
+ for (var i = 0; i < uniqueProperties.length; ++i) {
+ var name = uniqueProperties[i];
+ var shorthand = tempStyle.getPropertyShorthand(name);
+
+ if (shorthand && shorthand in foundShorthands) {
+ continue;
+ }
+
+ if (shorthand) {
+ var value = this.getShorthandValue_(tempStyle, shorthand);
+ var priority = this.getShorthandPriority_(tempStyle, shorthand);
+ foundShorthands[shorthand] = true;
+ } else {
+ var value = tempStyle.getPropertyValue(name);
+ var priority = tempStyle.getPropertyPriority(name);
+ }
+ // Set the property on the real style declaration.
+ style.setProperty((shorthand || name), value, priority);
+ }
+ return true;
+};
+
+
+/**
+ * Sets style property with given name to a value.
+ * @param {Node} node Node to get prorotypes for.
+ * @param {string} name Style element name.
+ * @param {string} value Value.
+ * @return {boolean} True iff style has been edited successfully.
+ */
+devtools.Injected.prototype.setStyleProperty = function(node,
+ name, value) {
+ node.style.setProperty(name, value, "");
+ return true;
+};
+
+
+/**
+ * Taken from utilities.js as is for injected evaluation.
+ */
+devtools.Injected.prototype.getLonghandProperties_ = function(style,
+ shorthandProperty) {
+ var properties = [];
+ var foundProperties = {};
+
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (individualProperty in foundProperties ||
+ style.getPropertyShorthand(individualProperty) != shorthandProperty) {
+ continue;
+ }
+ foundProperties[individualProperty] = true;
+ properties.push(individualProperty);
+ }
+ return properties;
+};
+
+
+/**
+ * Taken from utilities.js as is for injected evaluation.
+ */
+devtools.Injected.prototype.getShorthandValue_ = function(style,
+ shorthandProperty) {
+ var value = style.getPropertyValue(shorthandProperty);
+ if (!value) {
+ // Some shorthands (like border) return a null value, so compute a
+ // shorthand value.
+ // FIXME: remove this when http://bugs.webkit.org/show_bug.cgi?id=15823
+ // is fixed.
+
+ var foundProperties = {};
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (individualProperty in foundProperties ||
+ style.getPropertyShorthand(individualProperty) !==
+ shorthandProperty) {
+ continue;
+ }
+
+ var individualValue = style.getPropertyValue(individualProperty);
+ if (style.isPropertyImplicit(individualProperty) ||
+ individualValue === "initial") {
+ continue;
+ }
+
+ foundProperties[individualProperty] = true;
+
+ if (!value) {
+ value = "";
+ } else if (value.length) {
+ value += " ";
+ }
+ value += individualValue;
+ }
+ }
+ return value;
+};
+
+
+/**
+ * Taken from utilities.js as is for injected evaluation.
+ */
+devtools.Injected.prototype.getShorthandPriority_ = function(style,
+ shorthandProperty) {
+ var priority = style.getPropertyPriority(shorthandProperty);
+ if (!priority) {
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (style.getPropertyShorthand(individualProperty) !==
+ shorthandProperty) {
+ continue;
+ }
+ priority = style.getPropertyPriority(individualProperty);
+ break;
+ }
+ }
+ return priority;
+};
+
+
+/**
+ * Taken from utilities.js as is for injected evaluation.
+ */
+devtools.Injected.prototype.trimWhitespace_ = function(str) {
+ return str.replace(/^[\s\xA0]+|[\s\xA0]+$/g, '');
+};
+
+
+/**
+ * Taken from utilities.js as is for injected evaluation.
+ */
+devtools.Injected.prototype.getUniqueStyleProperties_ = function(style) {
+ var properties = [];
+ var foundProperties = {};
+
+ for (var i = 0; i < style.length; ++i) {
+ var property = style[i];
+ if (property in foundProperties) {
+ continue;
+ }
+ foundProperties[property] = true;
+ properties.push(property);
+ }
+ return properties;
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector.css b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector.css
new file mode 100644
index 0000000..2653781
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector.css
@@ -0,0 +1,3104 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+body {
+ cursor: default;
+ height: 100%;
+ width: 100%;
+ overflow: hidden;
+ font-family: Lucida Grande, sans-serif;
+ font-size: 10px;
+ margin: 0;
+ -webkit-text-size-adjust: none;
+ -webkit-user-select: none;
+}
+
+* {
+ -webkit-box-sizing: border-box;
+}
+
+:focus {
+ outline: none;
+}
+
+input[type="search"]:focus, input[type="text"]:focus {
+ outline: auto 5px -webkit-focus-ring-color;
+}
+
+iframe, a img {
+ border: none;
+}
+
+img {
+ -webkit-user-drag: none;
+}
+
+.hidden {
+ display: none !important;
+}
+
+#toolbar {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 56px;
+ display: -webkit-box;
+ padding: 0 5px;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(191, 191, 191)), to(rgb(151, 151, 151)));
+ border-bottom: 1px solid rgb(80, 80, 80);
+ -webkit-box-orient: horizontal;
+ -webkit-background-origin: padding;
+ -webkit-background-clip: padding;
+}
+
+body.inactive #toolbar {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(233, 233, 233)), to(rgb(207, 207, 207)));
+ border-bottom: 1px solid rgb(64%, 64%, 64%);
+}
+
+body.detached.platform-mac-leopard #toolbar {
+ background: transparent !important;
+}
+
+body.attached #toolbar {
+ height: 34px;
+ border-top: 1px solid rgb(100, 100, 100);
+ cursor: row-resize;
+ padding-left: 0;
+}
+
+body.attached.inactive #toolbar {
+ border-top: 1px solid rgb(64%, 64%, 64%);
+}
+
+.toolbar-item {
+ display: -webkit-box;
+ padding: 4px 6px;
+ margin: 0;
+ background-color: transparent;
+ border-style: none;
+ border-color: transparent;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: center;
+ -webkit-box-pack: end;
+}
+
+.toolbar-item.toggleable.toggled-on {
+ border-width: 0 2px 0 2px;
+ padding: 4px 4px;
+ -webkit-border-image: url(Images/toolbarItemSelected.png) 0 2 0 2;
+}
+
+.toolbar-item.flexable-space {
+ -webkit-box-flex: 1;
+ visibility: hidden;
+}
+
+.toolbar-item input {
+ margin-bottom: 8px;
+}
+
+.toolbar-icon {
+ display: inline-block;
+ width: 32px;
+ height: 32px;
+ -webkit-background-size: 100% auto;
+}
+
+body.attached .toolbar-icon {
+ width: 24px;
+ height: 24px;
+ vertical-align: middle;
+}
+
+.toolbar-item:active .toolbar-icon {
+ background-position: 0 32px;
+}
+
+body.attached .toolbar-item:active .toolbar-icon {
+ background-position: 0 24px;
+}
+
+.toolbar-label {
+ font-size: 11px;
+ font-family: Lucida Grande, sans-serif;
+ text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0;
+}
+
+.toolbar-item.toggleable:active .toolbar-label {
+ text-shadow: none;
+}
+
+body.attached .toolbar-label {
+ display: inline-block;
+ vertical-align: middle;
+ margin-left: 3px;
+}
+
+body.attached #search-toolbar-label {
+ display: none;
+}
+
+#search {
+ width: 205px;
+ font-size: 16px;
+ margin-bottom: 5px;
+}
+
+body.attached #search {
+ font-size: 11px;
+ margin-bottom: 8px;
+}
+
+#search-results-matches {
+ font-size: 11px;
+ text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0;
+ margin-bottom: 22px;
+}
+
+body.attached #search-results-matches {
+ margin-bottom: 6px;
+}
+
+.toolbar-item.elements .toolbar-icon {
+ background-image: url(Images/elementsIcon.png);
+}
+
+.toolbar-item.resources .toolbar-icon {
+ background-image: url(Images/resourcesIcon.png);
+}
+
+.toolbar-item.scripts .toolbar-icon {
+ background-image: url(Images/scriptsIcon.png);
+}
+
+.toolbar-item.databases .toolbar-icon {
+ background-image: url(Images/databasesIcon.png);
+}
+
+.toolbar-item.profiles .toolbar-icon {
+ background-image: url(Images/profilesIcon.png);
+}
+
+#close-button {
+ width: 14px;
+ height: 14px;
+ background-image: url(Images/closeButtons.png);
+ background-position: 0 0;
+ background-color: transparent;
+ border: 0 none transparent;
+ margin: 5px 0;
+}
+
+#close-button:hover {
+ background-position: 14px 0;
+}
+
+#close-button:active {
+ background-position: 28px 0;
+}
+
+body.detached .toolbar-item.close {
+ display: none;
+}
+
+#main {
+ position: absolute;
+ z-index: 1;
+ top: 56px;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ overflow: hidden;
+ background-color: white;
+}
+
+body.attached #main {
+ top: 34px;
+}
+
+#main-panels {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 23px;
+ overflow: hidden;
+}
+
+#main-status-bar {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+}
+
+body.console-visible #main-status-bar {
+ height: 24px;
+ background-image: url(Images/statusbarResizerVertical.png), url(Images/statusbarBackground.png);
+ background-repeat: no-repeat, repeat-x;
+ background-position: right center, center;
+ cursor: row-resize;
+}
+
+body.console-visible #main-status-bar * {
+ cursor: default;
+}
+
+body.console-visible #main-panels {
+ bottom: 24px;
+}
+
+.status-bar {
+ background-color: rgb(235, 235, 235);
+ background-image: url(Images/statusbarBackground.png);
+ background-repeat: repeat-x;
+ white-space: nowrap;
+ height: 23px;
+ overflow: hidden;
+ z-index: 12;
+}
+
+.status-bar > div {
+ display: inline-block;
+ vertical-align: top;
+}
+
+.status-bar-item {
+ display: inline-block;
+ height: 24px;
+ padding: 0;
+ margin-left: -1px;
+ margin-right: 0;
+ vertical-align: top;
+ border: 0 transparent none;
+ background-color: transparent;
+}
+
+.status-bar-item:active {
+ position: relative;
+ z-index: 200;
+}
+
+button.status-bar-item {
+ width: 32px;
+ background-image: url(Images/statusbarButtons.png);
+ background-position: 0 0;
+}
+
+button.status-bar-item:active {
+ background-position: 32px 0;
+}
+
+button.status-bar-item:disabled {
+ opacity: 0.5;
+ background-position: 0 0 !important;
+}
+
+select.status-bar-item {
+ min-width: 48px;
+ border-width: 0 17px 0 2px;
+ padding: 0 2px 0 6px;
+ font-weight: bold;
+ color: rgb(48, 48, 48);
+ text-shadow: rgba(255, 255, 255, 0.75) 0 1px 0;
+ -webkit-border-image: url(Images/statusbarMenuButton.png) 0 17 0 2;
+ -webkit-border-radius: 0;
+ -webkit-appearance: none;
+}
+
+select.status-bar-item:active {
+ color: black;
+ -webkit-border-image: url(Images/statusbarMenuButtonSelected.png) 0 17 0 2;
+}
+
+#dock-status-bar-item {
+ background-image: url(Images/dockButtons.png);
+}
+
+body.attached #dock-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+body.detached #dock-status-bar-item {
+ background-position: 0 24px;
+}
+
+body.detached #dock-status-bar-item.toggled-on:active {
+ background-position: 32px 24px;
+}
+
+#console-status-bar-item {
+ background-image: url(Images/consoleButtons.png);
+}
+
+#console-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+#console-status-bar-item.toggled-on {
+ background-position: 0 24px;
+}
+
+#console-status-bar-item.toggled-on:active {
+ background-position: 32px 24px;
+}
+
+#clear-console-status-bar-item {
+ background-image: url(Images/clearConsoleButtons.png);
+}
+
+#clear-console-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+#error-warning-count {
+ position: absolute;
+ right: 16px;
+ top: 0;
+ cursor: pointer;
+ padding: 6px 2px;
+ font-size: 10px;
+ height: 19px;
+}
+
+#error-warning-count:hover {
+ border-bottom: 1px solid rgb(96, 96, 96);
+}
+
+#error-count::before {
+ content: url(Images/errorIcon.png);
+ width: 10px;
+ height: 10px;
+ vertical-align: -1px;
+ margin-right: 2px;
+}
+
+#error-count + #warning-count {
+ margin-left: 6px;
+}
+
+#warning-count::before {
+ content: url(Images/warningIcon.png);
+ width: 10px;
+ height: 10px;
+ vertical-align: -1px;
+ margin-right: 2px;
+}
+
+#console {
+ display: none;
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 200px;
+ background-color: white;
+ background-image: url(Images/statusbarBottomBackground.png);
+ background-repeat: repeat-x;
+ background-position: bottom;
+}
+
+body.console-visible #console {
+ display: block;
+}
+
+#console-status-bar {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: none;
+}
+
+#console-messages {
+ position: absolute;
+ z-index: 0;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 23px;
+ font-size: 10px;
+ font-family: Monaco, Lucida Console, monospace;
+ padding: 2px 0;
+ overflow-y: overlay;
+ -webkit-user-select: text;
+ -webkit-text-size-adjust: auto;
+}
+
+#console-prompt {
+ position: relative;
+ padding: 1px 22px 1px 24px;
+ min-height: 16px;
+ white-space: pre-wrap;
+ -webkit-user-modify: read-write-plaintext-only;
+}
+
+#console-prompt::before {
+ background-image: url(Images/userInputIcon.png);
+}
+
+.console-user-command-result.console-log-level::before {
+ background-image: url(Images/userInputResultIcon.png);
+}
+
+.console-message, .console-user-command {
+ position: relative;
+ border-bottom: 1px solid rgb(240, 240, 240);
+ padding: 1px 22px 1px 24px;
+ min-height: 16px;
+}
+
+.console-adjacent-user-command-result {
+ border-bottom: none;
+}
+
+.console-adjacent-user-command-result + .console-user-command-result.console-log-level::before {
+ background-image: none;
+}
+
+.console-message::before, .console-user-command::before, #console-prompt::before, .console-group-title-level::before {
+ position: absolute;
+ display: block;
+ content: "";
+ left: 7px;
+ top: 0.8em;
+ width: 10px;
+ height: 10px;
+ margin-top: -5px;
+ -webkit-user-select: none;
+}
+
+.console-message .bubble {
+ display: inline-block;
+ height: 14px;
+ background-color: rgb(128, 151, 189);
+ vertical-align: middle;
+ white-space: nowrap;
+ padding: 1px 4px;
+ margin-top: -2px;
+ margin-right: 4px;
+ text-align: left;
+ font-size: 11px;
+ font-family: Helvetia, Arial, sans-serif;
+ font-weight: bold;
+ text-shadow: none;
+ color: white;
+ -webkit-border-radius: 7px;
+}
+
+.console-message-text {
+ white-space: pre-wrap;
+}
+
+.repeated-message {
+ padding-left: 6px;
+}
+
+.repeated-message.console-error-level::before, .repeated-message.console-warning-level:before {
+ visibility: hidden;
+}
+
+.console-group .console-group > .console-group-messages {
+ margin-left: 16px;
+}
+
+.console-group-title-level {
+ font-weight: bold;
+}
+
+.console-group-title-level::before {
+ background-image: url(Images/disclosureTriangleSmallDown.png);
+ top: 0.6em;
+ width: 11px;
+ height: 12px;
+}
+
+.console-group.collapsed .console-group-title-level::before {
+ background-image: url(Images/disclosureTriangleSmallRight.png);
+}
+
+.console-group.collapsed > .console-group-messages {
+ display: none;
+}
+
+.console-error-level .console-message-text {
+ color: red;
+}
+
+.console-error-level::before {
+ background-image: url(Images/errorIcon.png);
+}
+
+.console-warning-level::before {
+ background-image: url(Images/warningIcon.png);
+}
+
+.console-user-command .console-message {
+ margin-left: -24px;
+ padding-right: 0;
+ border-bottom: none;
+}
+
+.console-user-command::before {
+ background-image: url(Images/userInputPreviousIcon.png);
+}
+
+.console-user-command > .console-message-text {
+ color: rgb(0, 128, 255);
+}
+
+#console-messages a {
+ color: rgb(33%, 33%, 33%);
+ cursor: pointer;
+}
+
+#console-messages a:hover {
+ color: rgb(15%, 15%, 15%);
+}
+
+.console-message-url {
+ float: right;
+}
+
+.console-group-messages .section {
+ margin: 0 0 0 12px !important;
+}
+
+.console-group-messages .section .header {
+ padding: 0 8px 0 0;
+ background-image: none;
+ border: none;
+ min-height: 0;
+}
+
+.console-group-messages .section .header::before {
+ position: absolute;
+ top: 1px;
+ left: 1px;
+ width: 8px;
+ height: 8px;
+ content: url(Images/treeRightTriangleBlack.png);
+}
+
+.console-group-messages .section.expanded .header::before {
+ content: url(Images/treeDownTriangleBlack.png);
+}
+
+.console-group-messages .section .header .title {
+ color: black;
+ font-weight: normal;
+}
+
+.console-group-messages .section .properties li .info {
+ padding-top: 0;
+ padding-bottom: 0;
+ color: rgb(60%, 60%, 60%);
+}
+
+.console-group-messages .outline-disclosure {
+ padding-left: 0;
+}
+
+.console-group-messages .outline-disclosure > ol {
+ padding: 0 0 0 12px !important;
+}
+
+.console-group-messages .outline-disclosure, .console-group-messages .outline-disclosure ol {
+ font-size: inherit;
+ line-height: 1em;
+}
+
+.console-group-messages .outline-disclosure.single-node li {
+ padding-left: 2px;
+}
+
+.console-group-messages .outline-disclosure li .selection {
+ margin-left: -6px;
+ margin-right: -6px;
+}
+
+.console-formatted-object, .console-formatted-node {
+ position: relative;
+ display: inline-block;
+ vertical-align: top;
+}
+
+.console-formatted-object .section, .console-formatted-node .section {
+ position: static;
+}
+
+.console-formatted-object .properties, .console-formatted-node .properties {
+ padding-left: 0 !important;
+}
+
+.error-message {
+ color: red;
+}
+
+.auto-complete-text {
+ color: rgb(128, 128, 128);
+ -webkit-user-select: none;
+ -webkit-user-modify: read-only;
+}
+
+.panel {
+ display: none;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+
+.panel.visible {
+ display: block;
+}
+
+.resource-view {
+ display: none;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ overflow: hidden;
+}
+
+.resource-view.visible {
+ display: block;
+}
+
+.resource-view.headers-visible {
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+.resource-view-headers {
+ display: none;
+ padding: 6px;
+ border-bottom: 1px solid rgb(64%, 64%, 64%);
+ background-color: white;
+ -webkit-user-select: text;
+}
+
+.resource-view-headers .outline-disclosure .parent {
+ -webkit-user-select: none;
+ font-weight: bold;
+}
+
+.resource-view.headers-visible .resource-view-headers {
+ display: block;
+}
+
+.resource-view-headers .outline-disclosure .children li {
+ white-space: nowrap;
+}
+
+.resource-view-headers .outline-disclosure li.expanded .header-count {
+ display: none;
+}
+
+.resource-view-headers .outline-disclosure .header-name {
+ color: rgb(33%, 33%, 33%);
+ display: inline-block;
+ width: 105px;
+ text-align: right;
+ margin-right: 0.5em;
+ font-weight: bold;
+ vertical-align: top;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.resource-view-headers .outline-disclosure .header-value {
+ display: inline-block;
+ white-space: normal;
+ word-break: break-word;
+ vertical-align: top;
+ margin-right: 100px;
+}
+
+.resource-view .resource-view-content {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 0;
+ bottom: 0;
+}
+
+.resource-view.headers-visible .resource-view-content {
+ position: relative;
+ top: auto;
+ right: auto;
+ left: auto;
+ bottom: auto;
+}
+
+.resource-view.headers-visible .source-view-frame {
+ height: auto;
+ vertical-align: top;
+}
+
+.webkit-line-gutter-backdrop {
+ /* Keep this in sync with view-source.css (.webkit-line-gutter-backdrop) */
+ width: 31px;
+ background-color: rgb(240, 240, 240);
+ border-right: 1px solid rgb(187, 187, 187);
+ position: absolute;
+ z-index: -1;
+ left: 0;
+ top: 0;
+ height: 100%
+}
+
+.resource-view.font .resource-view-content {
+ font-size: 60px;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+ text-align: center;
+ padding: 15px;
+}
+
+.resource-view.image .resource-view-content > .image {
+ padding: 20px 20px 10px 20px;
+ text-align: center;
+}
+
+.resource-view.image .resource-view-content > .info {
+ padding-bottom: 10px;
+ font-size: 11px;
+ -webkit-user-select: text;
+}
+
+.resource-view.image img {
+ max-width: 100%;
+ max-height: 1000px;
+ background-image: url(Images/checker.png);
+ -webkit-box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.5);
+ -webkit-user-select: text;
+ -webkit-user-drag: auto;
+}
+
+.resource-view.image .title {
+ text-align: center;
+ font-size: 13px;
+}
+
+.resource-view.image .infoList {
+ margin: 0;
+}
+
+.resource-view.image .infoList dt {
+ font-weight: bold;
+ display: inline-block;
+ width: 50%;
+ text-align: right;
+ color: rgb(76, 76, 76);
+}
+
+.resource-view.image .infoList dd {
+ display: inline-block;
+ padding-left: 8px;
+ width: 50%;
+ text-align: left;
+ margin: 0;
+}
+
+.resource-view.image .infoList dd::after {
+ white-space: pre;
+ content: "\A";
+}
+
+#elements-content {
+ display: block;
+ overflow: auto;
+ padding: 0;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 225px;
+ bottom: 0;
+}
+
+#elements-sidebar {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ width: 225px;
+ background-color: rgb(245, 245, 245);
+ border-left: 1px solid rgb(64%, 64%, 64%);
+ cursor: default;
+ overflow: auto;
+}
+
+.crumbs {
+ display: inline-block;
+ font-size: 11px;
+ line-height: 19px;
+ text-shadow: rgba(255, 255, 255, 0.75) 0 1px 0;
+ color: rgb(20, 20, 20);
+ margin-left: -1px;
+ padding-right: 12px;
+}
+
+.crumbs .crumb {
+ height: 24px;
+ border-width: 0 12px 0 2px;
+ -webkit-border-image: url(Images/segment.png) 0 12 0 2;
+ margin-right: -12px;
+ padding-left: 18px;
+ padding-right: 2px;
+ white-space: nowrap;
+ line-height: 23px;
+ float: right;
+}
+
+.crumbs .crumb.collapsed > * {
+ display: none;
+}
+
+.crumbs .crumb.collapsed::before {
+ content: "\2026";
+ font-weight: bold;
+}
+
+.crumbs .crumb.compact .extra {
+ display: none;
+}
+
+.crumbs .crumb.dimmed {
+ color: rgba(0, 0, 0, 0.45);
+}
+
+.crumbs .crumb.start {
+ padding-left: 7px;
+}
+
+.crumbs .crumb.end {
+ border-width: 0 2px 0 2px;
+ padding-right: 6px;
+ -webkit-border-image: url(Images/segmentEnd.png) 0 2 0 2;
+}
+
+.crumbs .crumb.selected {
+ -webkit-border-image: url(Images/segmentSelected.png) 0 12 0 2;
+ color: black;
+ text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0;
+}
+
+.crumbs .crumb.selected:hover {
+ -webkit-border-image: url(Images/segmentSelected.png) 0 12 0 2;
+}
+
+.crumbs .crumb.selected.end, .crumbs .crumb.selected.end:hover {
+ -webkit-border-image: url(Images/segmentSelectedEnd.png) 0 2 0 2;
+}
+
+.crumbs .crumb:hover {
+ -webkit-border-image: url(Images/segmentHover.png) 0 12 0 2;
+ color: black;
+}
+
+.crumbs .crumb.dimmed:hover {
+ -webkit-border-image: url(Images/segmentHover.png) 0 12 0 2;
+ color: rgba(0, 0, 0, 0.75);
+}
+
+.crumbs .crumb.end:hover {
+ -webkit-border-image: url(Images/segmentHoverEnd.png) 0 2 0 2;
+}
+
+.outline-disclosure li.hovered:not(.selected) .selection {
+ display: block;
+ left: 3px;
+ right: 3px;
+ background-color: rgba(56, 121, 217, 0.1);
+ -webkit-border-radius: 5px;
+}
+
+.outline-disclosure li.highlighted .highlight {
+ background-color: rgb(255, 230, 179);
+ -webkit-border-radius: 4px;
+ padding-bottom: 2px;
+ margin-bottom: -2px;
+}
+
+.outline-disclosure li.selected.highlighted .highlight {
+ background-color: transparent;
+ padding-bottom: 0;
+ margin-bottom: 0;
+}
+
+.outline-disclosure li .selection {
+ display: none;
+ position: absolute;
+ left: 0;
+ right: 0;
+ height: 15px;
+ z-index: -1;
+}
+
+.outline-disclosure li.selected .selection {
+ display: block;
+ background-color: rgb(212, 212, 212);
+}
+
+:focus .outline-disclosure li.selected .selection {
+ background-color: rgb(56, 121, 217);
+}
+
+.outline-disclosure > ol {
+ position: relative;
+ padding: 2px 6px !important;
+ margin: 0;
+ color: black;
+ cursor: default;
+ min-width: 100%;
+}
+
+.outline-disclosure, .outline-disclosure ol {
+ list-style-type: none;
+ font-size: 11px;
+ -webkit-padding-start: 12px;
+ margin: 0;
+}
+
+.outline-disclosure li {
+ padding: 0 0 2px 14px;
+ margin-top: 1px;
+ margin-bottom: 1px;
+ word-wrap: break-word;
+ text-indent: -2px
+}
+
+:focus .outline-disclosure li.selected {
+ color: white;
+}
+
+:focus .outline-disclosure li.selected * {
+ color: inherit;
+}
+
+.outline-disclosure li.parent {
+ text-indent: -12px
+}
+
+.outline-disclosure li .webkit-html-tag.close {
+ margin-left: -12px;
+}
+
+.outline-disclosure li.parent::before {
+ content: url(Images/treeRightTriangleBlack.png);
+ float: left;
+ width: 8px;
+ height: 8px;
+ margin-top: 1px;
+ padding-right: 2px;
+}
+
+.outline-disclosure li.parent::before {
+ content: url(Images/treeRightTriangleBlack.png);
+}
+
+:focus .outline-disclosure li.parent.selected::before {
+ content: url(Images/treeRightTriangleWhite.png);
+}
+
+.outline-disclosure li.parent.expanded::before {
+ content: url(Images/treeDownTriangleBlack.png);
+}
+
+:focus .outline-disclosure li.parent.expanded.selected::before {
+ content: url(Images/treeDownTriangleWhite.png);
+}
+
+.outline-disclosure ol.children {
+ display: none;
+}
+
+.outline-disclosure ol.children.expanded {
+ display: block;
+}
+
+.webkit-html-comment {
+ /* Keep this in sync with view-source.css (.webkit-html-comment) */
+ color: rgb(35, 110, 37);
+}
+
+.webkit-html-tag {
+ /* Keep this in sync with view-source.css (.webkit-html-tag) */
+ color: rgb(136, 18, 128);
+}
+
+.webkit-html-doctype {
+ /* Keep this in sync with view-source.css (.webkit-html-doctype) */
+ color: rgb(192, 192, 192);
+}
+
+.webkit-html-attribute-name {
+ /* Keep this in sync with view-source.css (.webkit-html-attribute-name) */
+ color: rgb(153, 69, 0);
+}
+
+.webkit-html-attribute-value {
+ /* Keep this in sync with view-source.css (.webkit-html-attribute-value) */
+ color: rgb(26, 26, 166);
+}
+
+.webkit-html-external-link, .webkit-html-resource-link {
+ /* Keep this in sync with view-source.css (.webkit-html-external-link, .webkit-html-resource-link) */
+ color: #00e;
+}
+
+.webkit-html-external-link {
+ /* Keep this in sync with view-source.css (.webkit-html-external-link) */
+ text-decoration: none;
+}
+
+.webkit-html-external-link:hover {
+ /* Keep this in sync with view-source.css (.webkit-html-external-link:hover) */
+ text-decoration: underline;
+}
+
+.placard {
+ position: relative;
+ margin-top: 1px;
+ padding: 3px 8px 4px 18px;
+ min-height: 18px;
+ white-space: nowrap;
+}
+
+.placard:nth-of-type(2n) {
+ background-color: rgb(234, 243, 255);
+}
+
+.placard.selected {
+ border-top: 1px solid rgb(145, 160, 192);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(162, 177, 207)), to(rgb(120, 138, 177)));
+ -webkit-background-origin: padding;
+ -webkit-background-clip: padding;
+}
+
+:focus .placard.selected {
+ border-top: 1px solid rgb(68, 128, 200);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(92, 147, 213)), to(rgb(21, 83, 170)));
+}
+
+body.inactive .placard.selected {
+ border-top: 1px solid rgb(151, 151, 151);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(180, 180, 180)), to(rgb(138, 138, 138)));
+}
+
+.placard .title {
+ color: black;
+ font-weight: normal;
+ word-wrap: break-word;
+ white-space: normal;
+}
+
+.placard.selected .title {
+ color: white;
+ font-weight: bold;
+}
+
+.placard .subtitle {
+ float: right;
+ font-size: 10px;
+ margin-left: 5px;
+ max-width: 55%;
+ color: rgba(0, 0, 0, 0.7);
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+.placard.selected .subtitle {
+ color: rgba(255, 255, 255, 0.7);
+}
+
+.placard .subtitle a {
+ color: inherit;
+}
+
+.section {
+ position: relative;
+ margin-top: 1px;
+}
+
+.section:nth-last-of-type(1) {
+ margin-bottom: 1px;
+}
+
+.section .header {
+ padding: 2px 8px 4px 18px;
+ border-top: 1px solid rgb(145, 160, 192);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(162, 177, 207)), to(rgb(120, 138, 177)));
+ min-height: 18px;
+ white-space: nowrap;
+ -webkit-background-origin: padding;
+ -webkit-background-clip: padding;
+}
+
+.section .header::before {
+ position: absolute;
+ top: 4px;
+ left: 7px;
+ width: 8px;
+ height: 8px;
+ content: url(Images/treeRightTriangleWhite.png);
+}
+
+.section.expanded .header::before {
+ content: url(Images/treeDownTriangleWhite.png);
+}
+
+.section .header .title {
+ color: white;
+ font-weight: bold;
+ word-wrap: break-word;
+ white-space: normal;
+}
+
+.section .header label {
+ display: none;
+}
+
+.section.expanded .header label {
+ display: inline;
+}
+
+.section .header input[type=checkbox] {
+ height: 10px;
+ width: 10px;
+ margin-left: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+ vertical-align: 2px;
+}
+
+.section .header .subtitle {
+ float: right;
+ font-size: 10px;
+ margin-left: 5px;
+ max-width: 55%;
+ color: rgba(255, 255, 255, 0.7);
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+.section .header .subtitle a {
+ color: inherit;
+}
+
+.section .properties {
+ display: none;
+ margin: 0;
+ padding: 2px 6px 3px;
+ list-style: none;
+ background-color: white;
+}
+
+.section.expanded .properties {
+ display: block;
+}
+
+.section .properties li {
+ margin-left: 12px;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ -webkit-user-select: text;
+ cursor: auto;
+}
+
+.section .properties li.parent {
+ margin-left: 1px;
+}
+
+.section .properties ol {
+ display: none;
+ margin: 0;
+ -webkit-padding-start: 12px;
+ list-style: none;
+}
+
+.section .properties ol.expanded {
+ display: block;
+}
+
+.section .properties li.parent::before {
+ content: url(Images/treeRightTriangleBlack.png);
+ opacity: 0.75;
+ float: left;
+ width: 8px;
+ height: 8px;
+ margin-top: 0;
+ padding-right: 3px;
+ -webkit-user-select: none;
+ cursor: default;
+}
+
+.section .properties li.parent.expanded::before {
+ content: url(Images/treeDownTriangleBlack.png);
+ margin-top: 1px;
+}
+
+.section .properties li .info {
+ padding-top: 4px;
+ padding-bottom: 3px;
+}
+
+.editing {
+ -webkit-user-select: text;
+ -webkit-box-shadow: rgba(0, 0, 0, .5) 3px 3px 4px;
+ outline: 1px solid rgb(66%, 66%, 66%) !important;
+ background-color: white;
+ -webkit-user-modify: read-write-plaintext-only;
+ text-overflow: clip;
+ padding-left: 2px;
+ margin-left: -2px;
+ padding-right: 2px;
+ margin-right: -2px;
+ margin-bottom: -1px;
+ padding-bottom: 1px;
+ opacity: 1.0 !important;
+}
+
+.editing, .editing * {
+ color: black !important;
+ text-decoration: none !important;
+}
+
+.section .properties li.editing {
+ margin-left: 10px;
+ text-overflow: clip;
+}
+
+li.editing .swatch, li.editing .enabled-button {
+ display: none !important;
+}
+
+.section .properties li.editing-sub-part {
+ padding: 3px 6px 8px 18px;
+ margin: -3px -6px -8px -6px;
+ text-overflow: clip;
+}
+
+.section .properties .overloaded, .section .properties .disabled {
+ text-decoration: line-through;
+}
+
+.section.computed-style .properties .disabled {
+ text-decoration: none;
+ opacity: 0.5;
+}
+
+.section .properties .implicit, .section .properties .inherited {
+ opacity: 0.5;
+}
+
+.section:not(.show-inherited) .properties .inherited {
+ display: none;
+}
+
+.section .properties .enabled-button {
+ display: none;
+ float: right;
+ font-size: 10px;
+ margin: 0 0 0 4px;
+ vertical-align: top;
+ position: relative;
+ z-index: 1;
+}
+
+.section:hover .properties .enabled-button {
+ display: block;
+}
+
+.section .properties .name {
+ color: rgb(136, 19, 145);
+}
+
+.section .properties .value.dimmed {
+ color: rgb(100, 100, 100);
+}
+
+.section .properties .number {
+ color: blue;
+}
+
+.section .properties .priority {
+ color: rgb(128, 0, 0);
+}
+
+.section .properties .keyword {
+ color: rgb(136, 19, 79);
+}
+
+.section .properties .color {
+ color: rgb(118, 15, 21);
+}
+
+.swatch {
+ display: inline-block;
+ vertical-align: baseline;
+ margin-left: 4px;
+ margin-bottom: -1px;
+ width: 1em;
+ height: 1em;
+ border: 1px solid rgb(180, 180, 180);
+}
+
+.pane:not(.expanded) + .pane, .pane:first-of-type {
+ margin-top: -1px;
+}
+
+.pane > .title {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(243, 243, 243)), color-stop(0.05, rgb(243, 243, 243)), color-stop(0.05, rgb(230, 230, 230)), to(rgb(209, 209, 209)));
+ height: 20px;
+ padding: 0 5px;
+ border-top: 1px solid rgb(189, 189, 189);
+ border-bottom: 1px solid rgb(189, 189, 189);
+ font-weight: bold;
+ font-size: 12px;
+ line-height: 18px;
+ color: rgb(110, 110, 110);
+ text-shadow: white 0 1px 0;
+ -webkit-background-origin: padding;
+ -webkit-background-clip: padding;
+}
+
+.pane > .title:active {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(231, 231, 231)), color-stop(0.05, rgb(231, 231, 231)), color-stop(0.05, rgb(207, 207, 207)), to(rgb(186, 186, 186)));
+ border-top: 1px solid rgb(178, 178, 178);
+ border-bottom: 1px solid rgb(178, 178, 178);
+}
+
+.pane > .title::before {
+ content: url(Images/disclosureTriangleSmallRightBlack.png);
+ float: left;
+ width: 11px;
+ height: 12px;
+ margin-right: 2px;
+ margin-top: 1px;
+}
+
+.pane.expanded > .title::before {
+ content: url(Images/disclosureTriangleSmallDownBlack.png);
+}
+
+.pane > .body {
+ position: relative;
+ display: none;
+ background-color: white;
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+.pane > .body .info {
+ text-align: center;
+ font-style: italic;
+ font-size: 10px;
+ padding: 6px;
+ color: gray;
+}
+
+.pane.expanded > .body, .pane.expanded > .growbar {
+ display: block;
+}
+
+.pane.expanded:nth-last-of-type(1) {
+ border-bottom: 1px solid rgb(189, 189, 189);
+}
+
+.pane > .growbar {
+ display: none;
+ background-image: url(Images/paneGrowHandleLine.png), url(Images/paneBottomGrow.png);
+ background-repeat: no-repeat, repeat-x;
+ background-position: center center, bottom;
+ height: 5px;
+}
+
+.metrics {
+ padding: 8px;
+ font-size: 10px;
+ text-align: center;
+ white-space: nowrap;
+}
+
+.metrics .label {
+ position: absolute;
+ margin-top: -10px;
+ font-size: 9px;
+ color: grey;
+ background-color: white;
+ margin-left: 3px;
+ padding-left: 2px;
+ padding-right: 2px;
+}
+
+.metrics .position {
+ border: 1px rgb(66%, 66%, 66%) dotted;
+ display: inline-block;
+ text-align: center;
+ padding: 3px;
+ margin: 3px;
+}
+
+.metrics .margin {
+ border: 1px dashed;
+ display: inline-block;
+ text-align: center;
+ vertical-align: middle;
+ padding: 3px;
+ margin: 3px;
+}
+
+.metrics .border {
+ border: 1px black solid;
+ display: inline-block;
+ text-align: center;
+ vertical-align: middle;
+ padding: 3px;
+ margin: 3px;
+}
+
+.metrics .padding {
+ border: 1px grey dashed;
+ display: inline-block;
+ text-align: center;
+ vertical-align: middle;
+ padding: 3px;
+ margin: 3px;
+}
+
+.metrics .content {
+ position: static;
+ border: 1px grey solid;
+ display: inline-block;
+ text-align: center;
+ vertical-align: middle;
+ padding: 3px;
+ margin: 3px;
+ min-width: 80px;
+ text-align: center;
+ overflow: visible;
+}
+
+.metrics .content span {
+ display: inline-block;
+}
+
+.metrics .editing {
+ position: relative;
+ z-index: 100;
+}
+
+.metrics .left {
+ display: inline-block;
+ vertical-align: middle;
+}
+
+.metrics .right {
+ display: inline-block;
+ vertical-align: middle;
+}
+
+.metrics .top {
+ display: inline-block;
+}
+
+.metrics .bottom {
+ display: inline-block;
+}
+
+.sidebar {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: 200px;
+ overflow-y: auto;
+ overflow-x: hidden;
+ background-color: rgb(214, 221, 229);
+ border-right: 1px solid rgb(64%, 64%, 64%);
+}
+
+body.inactive .sidebar {
+ background-color: rgb(232, 232, 232);
+}
+
+.database-sidebar-tree-item .icon {
+ content: url(Images/database.png);
+}
+
+.database-table-sidebar-tree-item .icon {
+ content: url(Images/databaseTable.png);
+}
+
+.domstorage-sidebar-tree-item .icon {
+ content: url(Images/domStorage.png);
+}
+
+#storage-views {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 200px;
+ bottom: 0;
+}
+
+.storage-view {
+ display: none;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+
+.storage-view.visible {
+ display: block;
+}
+
+.storage-view.table {
+ overflow: hidden;
+}
+
+.storage-view.table .data-grid {
+ border: none;
+ height: 100%;
+}
+
+.storage-view.table .storage-table-empty, .storage-view.table .storage-table-error {
+ position: absolute;
+ top: 0;
+ bottom: 25%;
+ left: 0;
+ right: 0;
+ font-size: 24px;
+ color: rgb(75%, 75%, 75%);
+ margin-top: auto;
+ margin-bottom: auto;
+ height: 50px;
+ line-height: 26px;
+ text-align: center;
+ font-weight: bold;
+ padding: 10px;
+ white-space: pre-wrap;
+}
+
+.storage-view.table .storage-table-error {
+ color: rgb(66%, 33%, 33%);
+}
+
+.data-grid {
+ position: relative;
+ border: 1px solid #aaa;
+}
+
+.data-grid .highlight {
+ background-color: rgb(255, 230, 179);
+}
+
+.data-grid tr.selected .highlight {
+ background-color: transparent;
+}
+
+.data-grid table {
+ table-layout: fixed;
+ border-spacing: 0;
+ border-collapse: collapse;
+ width: 100%;
+ font-size: 10px;
+ font-family: Lucida Grande, sans-serif;
+}
+
+.data-grid .data-container {
+ position: absolute;
+ top: 16px;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ padding-right: 14px;
+ overflow-x: hidden;
+ overflow-y: overlay;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(white), color-stop(0.5, white), color-stop(0.5, rgb(234, 243, 255)), to(rgb(234, 243, 255)));
+ -webkit-background-size: 1px 32px;
+}
+
+.data-grid.inline .data-container {
+ position: static;
+}
+
+.data-grid th {
+ text-align: left;
+ background-image: url(Images/glossyHeader.png);
+ background-repeat: repeat-x;
+ border-right: 1px solid rgb(179, 179, 179);
+ border-bottom: 1px solid rgb(179, 179, 179);
+ height: 15px;
+ font-weight: normal;
+ vertical-align: middle;
+ padding: 0 4px;
+ white-space: nowrap;
+}
+
+.data-grid th.corner {
+ width: 15px;
+ border-right: 0 none transparent;
+}
+
+.data-grid tr.filler {
+ display: table-row !important;
+ height: auto !important;
+}
+
+.data-grid tr.filler td {
+ height: auto !important;
+ padding: 0 !important;
+}
+
+.data-grid table.data {
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 16px;
+ bottom: 0;
+ height: 100%;
+ border-top: 0 none transparent;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(white), color-stop(0.5, white), color-stop(0.5, rgb(234, 243, 255)), to(rgb(234, 243, 255)));
+ -webkit-background-size: 1px 32px;
+}
+
+.data-grid.inline table.data {
+ position: static;
+}
+
+.data-grid table.data tr {
+ display: none;
+}
+
+.data-grid table.data tr.revealed {
+ display: table-row;
+}
+
+.data-grid td {
+ vertical-align: top;
+ height: 12px;
+ padding: 2px 4px;
+ white-space: nowrap;
+ border-right: 1px solid #aaa;
+ -webkit-user-select: text;
+}
+
+.data-grid td > div, .data-grid th > div {
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+.data-grid th.sortable div {
+ position: relative;
+}
+
+.data-grid th.sortable:active {
+ background-image: url(Images/glossyHeaderPressed.png);
+}
+
+.data-grid th.sort-ascending, .data-grid th.sort-descending {
+ border-right: 1px solid rgb(107, 140, 196);
+ border-bottom: 1px solid rgb(107, 140, 196);
+ background-image: url(Images/glossyHeaderSelected.png);
+ background-repeat: repeat-x;
+}
+
+.data-grid th.sortable.sort-ascending:active, .data-grid th.sortable.sort-descending:active {
+ background-image: url(Images/glossyHeaderSelectedPressed.png);
+}
+
+.data-grid th.sort-ascending div::after {
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 8px;
+ height: 8px;
+ content: url(Images/treeUpTriangleBlack.png);
+}
+
+.data-grid th.sort-descending div::after {
+ position: absolute;
+ top: 0;
+ right: 0;
+ margin-top: 1px;
+ width: 8px;
+ height: 8px;
+ content: url(Images/treeDownTriangleBlack.png);
+}
+
+body.inactive .data-grid th.sort-ascending, body.inactive .data-grid th.sort-descending {
+ background-image: url(Images/glossyHeader.png);
+ border-right: 1px solid rgb(179, 179, 179);
+ border-bottom: 1px solid rgb(179, 179, 179);
+}
+
+.data-grid tr.parent td.disclosure::before {
+ float: left;
+ content: url(Images/treeRightTriangleBlack.png);
+ width: 8px;
+ height: 8px;
+ margin-right: 2px;
+ -webkit-user-select: none;
+}
+
+.data-grid tr.expanded td.disclosure::before {
+ content: url(Images/treeDownTriangleBlack.png);
+ width: 8px;
+ height: 8px;
+ margin-top: 1px;
+}
+
+.data-grid tr.selected {
+ background-color: rgb(212, 212, 212);
+ color: inherit;
+}
+
+.data-grid:focus tr.selected {
+ background-color: rgb(56, 121, 217);
+ color: white;
+}
+
+.data-grid:focus tr.parent.selected td.disclosure::before {
+ content: url(Images/treeRightTriangleWhite.png);
+}
+
+.data-grid:focus tr.expanded.selected td.disclosure::before {
+ content: url(Images/treeDownTriangleWhite.png);
+}
+
+.data-grid tr:not(.parent) td.disclosure {
+ text-indent: 10px;
+}
+
+.storage-view.query {
+ font-size: 10px;
+ font-family: Monaco, Lucida Console, monospace;
+ padding: 2px 0;
+ overflow-y: overlay;
+ overflow-x: hidden;
+ -webkit-text-size-adjust: auto;
+}
+
+.database-query-prompt {
+ position: relative;
+ padding: 1px 22px 1px 24px;
+ min-height: 16px;
+ white-space: pre-wrap;
+ -webkit-user-modify: read-write-plaintext-only;
+ -webkit-user-select: text;
+}
+
+.database-user-query::before, .database-query-prompt::before, .database-query-result::before {
+ position: absolute;
+ display: block;
+ content: "";
+ left: 7px;
+ top: 0.8em;
+ width: 10px;
+ height: 10px;
+ margin-top: -5px;
+ -webkit-user-select: none;
+}
+
+.database-query-prompt::before {
+ background-image: url(Images/userInputIcon.png);
+}
+
+.database-user-query {
+ position: relative;
+ border-bottom: 1px solid rgb(245, 245, 245);
+ padding: 1px 22px 1px 24px;
+ min-height: 16px;
+}
+
+.database-user-query::before {
+ background-image: url(Images/userInputPreviousIcon.png);
+}
+
+.database-query-text {
+ color: rgb(0, 128, 255);
+ -webkit-user-select: text;
+}
+
+.database-query-result {
+ position: relative;
+ padding: 1px 22px 1px 24px;
+ min-height: 16px;
+ margin-left: -24px;
+ padding-right: 0;
+}
+
+.database-query-result.error {
+ color: red;
+ -webkit-user-select: text;
+}
+
+.database-query-result.error::before {
+ background-image: url(Images/errorIcon.png);
+}
+
+.panel-enabler-view {
+ z-index: 1000;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: white;
+ font-size: 13px;
+ text-align: center;
+ overflow-x: hidden;
+ overflow-y: overlay;
+ display: none;
+}
+
+.panel-enabler-view.visible {
+ display: block;
+}
+
+.panel-enabler-view .panel-enabler-view-content {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ max-height: 390px;
+ margin: auto;
+ white-space: nowrap;
+}
+
+.panel-enabler-view h1 {
+ color: rgb(110, 116, 128);
+ font-size: 16px;
+ line-height: 20px;
+ font-weight: normal;
+ margin-top: 0;
+}
+
+.panel-enabler-disclaimer {
+ font-size: 10px;
+ color: rgb(110, 116, 128);
+ margin-bottom: 12px;
+ margin-left: 20px;
+}
+
+.panel-enabler-disclaimer:empty {
+ display: none;
+}
+
+.panel-enabler-view img {
+ height: 100%;
+ min-height: 200px;
+ max-width: 100%;
+ top: 0;
+ bottom: 0;
+ padding: 20px 0 20px 20px;
+ margin: auto;
+ vertical-align: middle;
+}
+
+.panel-enabler-view img.hidden {
+ display: initial !important;
+ width: 0;
+}
+
+.panel-enabler-view form {
+ display: inline-block;
+ vertical-align: middle;
+ width: 330px;
+ margin: 0;
+ padding: 15px;
+ white-space: normal;
+}
+
+.panel-enabler-view label {
+ position: relative;
+ display: block;
+ text-align: left;
+ word-break: break-word;
+ margin: 0 0 5px 20px;
+}
+
+.panel-enabler-view button {
+ font-size: 13px;
+ margin: 6px 0 0 0;
+ padding: 3px 20px;
+ color: rgb(6, 6, 6);
+ height: 24px;
+ background-color: transparent;
+ border: 1px solid rgb(165, 165, 165);
+ background-color: rgb(237, 237, 237);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)));
+ -webkit-border-radius: 12px;
+ -webkit-appearance: none;
+}
+
+.panel-enabler-view button:active {
+ background-color: rgb(215, 215, 215);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(194, 194, 194)), to(rgb(239, 239, 239)));
+}
+
+body.inactive .panel-enabler-view button, .panel-enabler-view button:disabled {
+ color: rgb(130, 130, 130);
+ border-color: rgb(212, 212, 212);
+ background-color: rgb(239, 239, 239);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(250, 250, 250)), to(rgb(235, 235, 235)));
+}
+
+.panel-enabler-view input {
+ height: 17px;
+ width: 17px;
+ border: 1px solid rgb(165, 165, 165);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)));
+ -webkit-border-radius: 8px;
+ -webkit-appearance: none;
+ vertical-align: middle;
+ margin: 0 5px 5px 0;
+}
+
+.panel-enabler-view input:active {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(194, 194, 194)), to(rgb(239, 239, 239)));
+}
+
+.panel-enabler-view input:checked {
+ background: url(Images/radioDot.png) center no-repeat,
+ -webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)));
+}
+
+.panel-enabler-view.resources img {
+ content: url(Images/scriptsSilhouette.png);
+}
+
+.panel-enabler-view.scripts img {
+ content: url(Images/scriptsSilhouette.png);
+}
+
+.panel-enabler-view.profiles img {
+ content: url(Images/profilesSilhouette.png);
+}
+
+button.enable-toggle-status-bar-item {
+ background-image: url(Images/enableButtons.png);
+}
+
+button.enable-toggle-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+button.enable-toggle-status-bar-item.toggled-on {
+ background-position: 0 24px;
+}
+
+button.enable-toggle-status-bar-item.toggled-on:active {
+ background-position: 32px 24px;
+}
+
+#scripts-pause-on-exceptions-status-bar-item {
+ background-image: url(Images/pauseOnExceptionButtons.png);
+}
+
+#scripts-pause-on-exceptions-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+#scripts-pause-on-exceptions-status-bar-item.toggled-on {
+ background-position: 0 24px;
+}
+
+#scripts-pause-on-exceptions-status-bar-item.toggled-on:active {
+ background-position: 32px 24px;
+}
+
+#scripts-status-bar {
+ position: absolute;
+ top: -1px;
+ left: 0;
+ right: 0;
+ height: 24px;
+}
+
+#scripts-files {
+ max-width: 250px;
+}
+
+#scripts-functions {
+ max-width: 150px;
+}
+
+#scripts-status-bar .status-bar-item img {
+ margin-top: 2px;
+}
+
+#scripts-back img {
+ content: url(Images/back.png);
+}
+
+#scripts-forward img {
+ content: url(Images/forward.png);
+}
+
+#scripts-pause img {
+ content: url(Images/debuggerPause.png);
+}
+
+#scripts-pause.paused img {
+ content: url(Images/debuggerContinue.png);
+}
+
+#scripts-step-over img {
+ content: url(Images/debuggerStepOver.png);
+}
+
+#scripts-step-into img {
+ content: url(Images/debuggerStepInto.png);
+}
+
+#scripts-step-out img {
+ content: url(Images/debuggerStepOut.png);
+}
+
+#scripts-debugger-status {
+ position: absolute;
+ line-height: 24px;
+ top: 0;
+ right: 8px;
+}
+
+#scripts-sidebar-resizer-widget {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ right: 225px;
+ width: 16px;
+ cursor: col-resize;
+ background-image: url(Images/statusbarResizerHorizontal.png);
+ background-repeat: no-repeat;
+ background-position: center;
+}
+
+#scripts-sidebar-buttons {
+ position: absolute;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ width: 225px;
+ overflow: hidden;
+ border-left: 1px solid rgb(64%, 64%, 64%);
+}
+
+#script-resource-views {
+ display: block;
+ overflow: auto;
+ padding: 0;
+ position: absolute;
+ top: 23px;
+ left: 0;
+ right: 225px;
+ bottom: 0;
+}
+
+.script-view {
+ display: none;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+
+.script-view.visible {
+ display: block;
+}
+
+#scripts-sidebar {
+ position: absolute;
+ top: 23px;
+ right: 0;
+ bottom: 0;
+ width: 225px;
+ background-color: rgb(245, 245, 245);
+ border-left: 1px solid rgb(64%, 64%, 64%);
+ cursor: default;
+ overflow: auto;
+}
+
+#resources-larger-resources-status-bar-item {
+ background-image: url(Images/largerResourcesButtons.png);
+}
+
+#resources-larger-resources-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+#resources-larger-resources-status-bar-item.toggled-on {
+ background-position: 0 24px;
+}
+
+#resources-larger-resources-status-bar-item.toggled-on:active {
+ background-position: 32px 24px;
+}
+
+#resources-container {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ border-right: 0 none transparent;
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+#resources-container.viewing-resource {
+ right: auto;
+ width: 200px;
+ border-right: 1px solid rgb(64%, 64%, 64%);
+}
+
+#resources-container.viewing-resource #resources-sidebar {
+ width: 100%;
+ border-right: 0 none transparent;
+}
+
+#resources-sidebar {
+ min-height: 100%;
+ bottom: auto;
+ overflow: visible;
+}
+
+#resources-container-content {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 200px;
+ min-height: 100%;
+}
+
+#resources-container.viewing-resource #resources-container-content {
+ display: none;
+}
+
+#resources-summary {
+ position: absolute;
+ padding-top: 20px;
+ top: 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)), to(rgba(0, 0, 0, 0.5)));
+ background-repeat: repeat-x;
+ background-position: bottom;
+ 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;
+}
+
+#resources-graph-legend {
+ margin-top: -10px;
+ padding-left: 15px;
+}
+
+.resources-graph-legend-item {
+ display: inline-block;
+ font-weight: bold;
+ margin-right: 15px;
+ vertical-align: top;
+}
+
+.resources-graph-legend-item.total {
+ margin-left: 10px;
+}
+
+.resources-graph-legend-label {
+ display: inline-block;
+ text-align: left;
+}
+
+.resources-graph-legend-header {
+ font-size: 12px;
+}
+
+.resources-graph-legend-value {
+ font-size: 10px;
+}
+
+.resources-graph-legend-swatch {
+ vertical-align: top;
+ margin-top: 1px;
+ margin-right: 3px;
+}
+
+#resources-dividers {
+ position: absolute;
+ left: 0;
+ right: 0;
+ height: 100%;
+ top: 0;
+ z-index: -100;
+}
+
+#resources-dividers-label-bar {
+ position: absolute;
+ top: 93px;
+ left: 0px;
+ right: 0;
+ background-color: rgba(255, 255, 255, 0.8);
+ background-clip: padding;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.3);
+ height: 20px;
+ z-index: 200;
+}
+
+.resources-divider {
+ position: absolute;
+ width: 1px;
+ top: 0;
+ bottom: 0;
+ background-color: rgba(0, 0, 0, 0.1);
+}
+
+.resources-divider.last {
+ background-color: transparent;
+}
+
+.resources-divider-label {
+ position: absolute;
+ top: 4px;
+ right: 3px;
+ font-size: 9px;
+ color: rgb(50%, 50%, 50%);
+ white-space: nowrap;
+}
+
+.resources-graph-label {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ margin: auto -7px;
+ height: 13px;
+ line-height: 13px;
+ font-size: 9px;
+ color: rgba(0, 0, 0, 0.75);
+ text-shadow: rgba(255, 255, 255, 0.25) 1px 0 0, rgba(255, 255, 255, 0.25) -1px 0 0, rgba(255, 255, 255, 0.333) 0 1px 0, rgba(255, 255, 255, 0.25) 0 -1px 0;
+ z-index: 150;
+ overflow: hidden;
+ text-align: center;
+ font-weight: bold;
+ opacity: 0;
+ -webkit-transition: opacity 250ms ease-in-out;
+}
+
+.resources-graph-side:hover .resources-graph-label {
+ opacity: 1;
+}
+
+.resources-graph-label:empty {
+ display: none;
+}
+
+.resources-graph-label.waiting {
+ margin-right: 5px;
+}
+
+.resources-graph-label.before {
+ color: rgba(0, 0, 0, 0.7);
+ text-shadow: none;
+ text-align: right;
+ margin-right: 2px;
+}
+
+.resources-graph-label.before::after {
+ padding-left: 2px;
+ height: 6px;
+ content: url(Images/graphLabelCalloutLeft.png);
+}
+
+.resources-graph-label.after {
+ color: rgba(0, 0, 0, 0.7);
+ text-shadow: none;
+ text-align: left;
+ margin-left: 2px;
+}
+
+.resources-graph-label.after::before {
+ padding-right: 2px;
+ height: 6px;
+ content: url(Images/graphLabelCalloutRight.png);
+}
+
+.resources-graph-bar {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ margin: auto -7px;
+ border-width: 6px 7px;
+ height: 13px;
+ min-width: 14px;
+ opacity: 0.65;
+ -webkit-border-image: url(Images/timelinePillGray.png) 6 7 6 7;
+}
+
+.resources-graph-bar.waiting {
+ opacity: 0.35;
+}
+
+.resource-cached .resources-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillGray.png) 6 7 6 7;
+}
+
+.resources-category-documents .resources-graph-bar {
+ -webkit-border-image: url(Images/timelinePillBlue.png) 6 7 6 7;
+}
+
+.resources-category-documents.resource-cached .resources-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillBlue.png) 6 7 6 7;
+}
+
+.resources-category-stylesheets .resources-graph-bar {
+ -webkit-border-image: url(Images/timelinePillGreen.png) 6 7 6 7;
+}
+
+.resources-category-stylesheets.resource-cached .resources-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillGreen.png) 6 7 6 7;
+}
+
+.resources-category-images .resources-graph-bar {
+ -webkit-border-image: url(Images/timelinePillPurple.png) 6 7 6 7;
+}
+
+.resources-category-images.resource-cached .resources-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillPurple.png) 6 7 6 7;
+}
+
+.resources-category-fonts .resources-graph-bar {
+ -webkit-border-image: url(Images/timelinePillRed.png) 6 7 6 7;
+}
+
+.resources-category-fonts.resource-cached .resources-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillRed.png) 6 7 6 7;
+}
+
+.resources-category-scripts .resources-graph-bar {
+ -webkit-border-image: url(Images/timelinePillOrange.png) 6 7 6 7;
+}
+
+.resources-category-scripts.resource-cached .resources-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillOrange.png) 6 7 6 7;
+}
+
+.resources-category-xhr .resources-graph-bar {
+ -webkit-border-image: url(Images/timelinePillYellow.png) 6 7 6 7;
+}
+
+.resources-category-xhr.resource-cached .resources-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillYellow.png) 6 7 6 7;
+}
+
+.tip-button {
+ background-image: url(Images/tipIcon.png);
+ border: none;
+ width: 16px;
+ height: 16px;
+ float: right;
+ background-color: transparent;
+ margin-top: 1px;
+}
+
+.tip-button:active {
+ background-image: url(Images/tipIconPressed.png);
+}
+
+.tip-balloon {
+ position: absolute;
+ left: 145px;
+ top: -5px;
+ z-index: 1000;
+ border-width: 51px 15px 18px 37px;
+ -webkit-border-image: url(Images/tipBalloon.png) 51 15 18 37;
+ width: 265px;
+}
+
+.tip-balloon.bottom {
+ position: absolute;
+ left: 145px;
+ top: auto;
+ bottom: -7px;
+ z-index: 1000;
+ border-width: 18px 15px 51px 37px;
+ -webkit-border-image: url(Images/tipBalloonBottom.png) 18 15 51 37;
+}
+
+.tip-balloon-content {
+ margin-top: -40px;
+ margin-bottom: -2px;
+ margin-left: 2px;
+}
+
+.tip-balloon.bottom .tip-balloon-content {
+ margin-top: -10px;
+ margin-bottom: -35px;
+}
+
+#resource-views {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 200px;
+ bottom: 0;
+}
+
+.source-view-frame {
+ width: 100%;
+ height: 100%;
+}
+
+.sidebar-resizer-vertical {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ width: 5px;
+ z-index: 500;
+ cursor: col-resize;
+}
+
+.sidebar-tree, .sidebar-tree .children {
+ position: relative;
+ padding: 0;
+ margin: 0;
+ list-style: none;
+ font-size: 11px;
+}
+
+.sidebar-tree-section {
+ position: relative;
+ height: 18px;
+ padding: 4px 10px 6px 10px;
+ white-space: nowrap;
+ margin-top: 1px;
+ color: rgb(92, 110, 129);
+ font-weight: bold;
+ text-shadow: rgba(255, 255, 255, 0.75) 0 1px 0;
+}
+
+.sidebar-tree-item {
+ position: relative;
+ height: 36px;
+ padding: 0 5px 0 5px;
+ white-space: nowrap;
+ margin-top: 1px;
+ line-height: 34px;
+ border-top: 1px solid transparent;
+}
+
+.sidebar-tree .children {
+ display: none;
+}
+
+.sidebar-tree .children.expanded {
+ display: block;
+}
+
+.sidebar-tree-section + .children > .sidebar-tree-item {
+ padding-left: 10px !important;
+}
+
+.sidebar-tree-section + .children.small > .sidebar-tree-item {
+ padding-left: 17px !important;
+}
+
+.sidebar-tree > .children > .sidebar-tree-item {
+ padding-left: 37px;
+}
+
+.sidebar-tree > .children > .children > .sidebar-tree-item {
+ padding-left: 37px;
+}
+
+.sidebar-tree.hide-disclosure-buttons > .children {
+ display: none;
+}
+
+.sidebar-tree > .children.hide-disclosure-buttons > .children {
+ display: none;
+}
+
+.sidebar-tree.some-expandable:not(.hide-disclosure-buttons) > .sidebar-tree-item:not(.parent) .icon {
+ margin-left: 16px;
+}
+
+.sidebar-tree-item .disclosure-button {
+ float: left;
+ width: 16px;
+ height: 100%;
+ border: 0;
+ background-color: transparent;
+ background-image: url(Images/disclosureTriangleSmallRight.png);
+ background-repeat: no-repeat;
+ background-position: center;
+ -webkit-apearance: none;
+}
+
+.sidebar-tree.hide-disclosure-buttons .sidebar-tree-item .disclosure-button {
+ display: none;
+}
+
+body.inactive .sidebar-tree-item .disclosure-button {
+ background-image: url(Images/disclosureTriangleSmallRightBlack.png);
+}
+
+body.inactive .sidebar-tree-item.expanded .disclosure-button {
+ background-image: url(Images/disclosureTriangleSmallDownBlack.png);
+}
+
+body.inactive .sidebar-tree-item .disclosure-button:active {
+ background-image: url(Images/disclosureTriangleSmallRightDownBlack.png);
+}
+
+.sidebar-tree-item.selected .disclosure-button {
+ background-image: url(Images/disclosureTriangleSmallRightWhite.png) !important;
+}
+
+.sidebar-tree-item.expanded .disclosure-button {
+ background-image: url(Images/disclosureTriangleSmallDown.png);
+}
+
+.sidebar-tree-item.selected.expanded .disclosure-button {
+ background-image: url(Images/disclosureTriangleSmallDownWhite.png) !important;
+}
+
+.sidebar-tree-item.selected .disclosure-button:active {
+ background-image: url(Images/disclosureTriangleSmallRightDownWhite.png) !important;
+}
+
+.sidebar-tree-item .disclosure-button:active {
+ background-image: url(Images/disclosureTriangleSmallRightDown.png);
+}
+
+.sidebar-tree-item .icon {
+ float: left;
+ width: 32px;
+ height: 32px;
+ margin-top: 1px;
+ margin-right: 3px;
+}
+
+.sidebar-tree-item .status {
+ float: right;
+ height: 16px;
+ margin-top: 9px;
+ margin-left: 4px;
+ line-height: 1em;
+}
+
+.sidebar-tree-item .status:empty {
+ display: none;
+}
+
+.sidebar-tree-item .status .bubble {
+ display: inline-block;
+ height: 14px;
+ min-width: 16px;
+ margin-top: 1px;
+ background-color: rgb(128, 151, 189);
+ vertical-align: middle;
+ white-space: nowrap;
+ padding: 1px 4px;
+ text-align: center;
+ font-size: 11px;
+ font-family: Helvetia, Arial, sans-serif;
+ font-weight: bold;
+ text-shadow: none;
+ color: white;
+ -webkit-border-radius: 7px;
+}
+
+.sidebar-tree-item .status .bubble:empty {
+ display: none;
+}
+
+.sidebar-tree-item.selected .status .bubble {
+ background-color: white !important;
+ color: rgb(132, 154, 190) !important;
+}
+
+:focus .sidebar-tree-item.selected .status .bubble {
+ color: rgb(36, 98, 172) !important;
+}
+
+body.inactive .sidebar-tree-item.selected .status .bubble {
+ color: rgb(159, 159, 159) !important;
+}
+
+.sidebar-tree.small .sidebar-tree-item, .sidebar-tree .children.small .sidebar-tree-item, .sidebar-tree-item.small, .small .resources-graph-side {
+ height: 20px;
+}
+
+.sidebar-tree.small .sidebar-tree-item .icon, .sidebar-tree .children.small .sidebar-tree-item .icon, .sidebar-tree-item.small .icon {
+ width: 16px;
+ height: 16px;
+}
+
+.sidebar-tree.small .sidebar-tree-item .status, .sidebar-tree .children.small .sidebar-tree-item .status, .sidebar-tree-item.small .status {
+ margin-top: 1px;
+}
+
+.sidebar-tree-item.selected {
+ color: white;
+ border-top: 1px solid rgb(145, 160, 192);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(162, 177, 207)), to(rgb(120, 138, 177)));
+ text-shadow: rgba(0, 0, 0, 0.33) 0 1px 0;
+ font-weight: bold;
+ -webkit-background-origin: padding;
+ -webkit-background-clip: padding;
+}
+
+:focus .sidebar-tree-item.selected {
+ border-top: 1px solid rgb(68, 128, 200);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(92, 147, 213)), to(rgb(21, 83, 170)));
+}
+
+body.inactive .sidebar-tree-item.selected {
+ border-top: 1px solid rgb(151, 151, 151);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(180, 180, 180)), to(rgb(138, 138, 138)));
+}
+
+.sidebar-tree-item .titles {
+ position: relative;
+ top: 5px;
+ line-height: 11px;
+ padding-bottom: 1px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+}
+
+.sidebar-tree-item .titles.no-subtitle {
+ top: 10px;
+}
+
+.sidebar-tree.small .sidebar-tree-item .titles, .sidebar-tree .children.small .sidebar-tree-item .titles, .sidebar-tree-item.small .titles {
+ top: 2px;
+ line-height: normal;
+}
+
+.sidebar-tree:not(.small) .sidebar-tree-item:not(.small) .title::after, .sidebar-tree .children:not(.small) .sidebar-tree-item .title::after {
+ content: "\A";
+ white-space: pre;
+}
+
+.sidebar-tree-item .subtitle {
+ font-size: 9px;
+ color: rgba(0, 0, 0, 0.7);
+}
+
+.sidebar-tree.small .sidebar-tree-item .subtitle, .sidebar-tree .children.small .sidebar-tree-item .subtitle, .sidebar-tree-item.small .subtitle {
+ display: none;
+}
+
+.sidebar-tree-item.selected .subtitle {
+ color: rgba(255, 255, 255, 0.9);
+}
+
+#resources-graphs {
+ position: absolute;
+ left: 0;
+ right: 0;
+ max-height: 100%;
+ top: 112px;
+}
+
+.resources-graph-side {
+ position: relative;
+ height: 36px;
+ padding: 0 5px;
+ white-space: nowrap;
+ margin-top: 1px;
+ border-top: 1px solid transparent;
+ overflow: hidden;
+}
+
+.resources-graph-bar-area {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ right: 8px;
+ left: 9px;
+}
+
+#resources-container:not(.viewing-resource) .resource-sidebar-tree-item:nth-of-type(2n) {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+
+#resources-container:not(.viewing-resource) .resources-graph-side:nth-of-type(2n) {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+
+.resources-time-graph-sidebar-item .icon {
+ content: url(Images/resourcesTimeGraphIcon.png);
+}
+
+.resources-size-graph-sidebar-item .icon {
+ content: url(Images/resourcesSizeGraphIcon.png);
+}
+
+.resources-size-graph-sidebar-item .icon {
+ content: url(Images/resourcesSizeGraphIcon.png);
+}
+
+.resource-sidebar-tree-item .icon {
+ content: url(Images/resourcePlainIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item .icon {
+ content: url(Images/resourcePlainIconSmall.png);
+}
+
+.resource-sidebar-tree-item.resources-category-documents .icon {
+ content: url(Images/resourceDocumentIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-documents .icon {
+ content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.resource-sidebar-tree-item.resources-category-stylesheets .icon {
+ content: url(Images/resourceCSSIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-stylesheets .icon {
+ content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.resource-sidebar-tree-item.resources-category-images .icon {
+ position: relative;
+ background-image: url(Images/resourcePlainIcon.png);
+ background-repeat: no-repeat;
+ content: "";
+}
+
+.resource-sidebar-tree-item.resources-category-images .image-resource-icon-preview {
+ position: absolute;
+ margin: auto;
+ top: 3px;
+ bottom: 4px;
+ left: 5px;
+ right: 5px;
+ max-width: 18px;
+ max-height: 21px;
+ min-width: 1px;
+ min-height: 1px;
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-images .icon {
+ background-image: url(Images/resourcePlainIconSmall.png);
+ content: "";
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-images .image-resource-icon-preview {
+ top: 2px;
+ bottom: 1px;
+ left: 3px;
+ right: 3px;
+ max-width: 8px;
+ max-height: 11px;
+}
+
+.resource-sidebar-tree-item.resources-category-fonts .icon {
+ content: url(Images/resourcePlainIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-fonts .icon {
+ content: url(Images/resourcePlainIconSmall.png);
+}
+
+.resource-sidebar-tree-item.resources-category-scripts .icon {
+ content: url(Images/resourceJSIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-scripts .icon {
+ content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.resource-sidebar-tree-item.resources-category-xhr .icon {
+ content: url(Images/resourcePlainIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-xhr .icon {
+ content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.bubble.warning, .console-warning-level .bubble {
+ background-color: rgb(232, 164, 0) !important;
+}
+
+.bubble.error, .console-error-level .bubble {
+ background-color: rgb(216, 35, 35) !important;
+}
+
+.bubble.search-matches {
+ background-image: url(Images/searchSmallWhite.png);
+ background-repeat: no-repeat;
+ background-position: 3px 2px;
+ padding-left: 13px !important;
+}
+
+.sidebar-tree-item.selected .bubble.search-matches {
+ background-image: url(Images/searchSmallBlue.png);
+}
+
+:focus .sidebar-tree-item.selected .bubble.search-matches {
+ background-image: url(Images/searchSmallBrightBlue.png);
+}
+
+body.inactive .sidebar-tree-item.selected .bubble.search-matches {
+ background-image: url(Images/searchSmallGray.png);
+}
+
+/* Profiler Style */
+
+#profile-views {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 200px;
+ bottom: 0;
+}
+
+#profile-view-status-bar-items {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 200px;
+ overflow: hidden;
+ border-left: 1px solid rgb(184, 184, 184);
+ margin-left: -1px;
+}
+
+.profile-sidebar-tree-item .icon {
+ content: url(Images/profileIcon.png);
+}
+
+.profile-sidebar-tree-item.small .icon {
+ content: url(Images/profileSmallIcon.png);
+}
+
+.profile-group-sidebar-tree-item .icon {
+ content: url(Images/profileGroupIcon.png);
+}
+
+.profile-view {
+ display: none;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+
+.profile-view.visible {
+ display: block;
+}
+
+.profile-view .data-grid {
+ border: none;
+ height: 100%;
+}
+
+.profile-view .data-grid th.average-column {
+ text-align: center;
+}
+
+.profile-view .data-grid td.average-column {
+ text-align: right;
+}
+
+.profile-view .data-grid th.self-column {
+ text-align: center;
+}
+
+.profile-view .data-grid td.self-column {
+ text-align: right;
+}
+
+.profile-view .data-grid th.total-column {
+ text-align: center;
+}
+
+.profile-view .data-grid td.total-column {
+ text-align: right;
+}
+
+.profile-view .data-grid .calls-column {
+ text-align: center;
+}
+
+.profile-node-file {
+ float: right;
+ color: gray;
+ margin-top: -1px;
+}
+
+.data-grid tr.selected .profile-node-file {
+ color: rgb(33%, 33%, 33%);
+}
+
+.data-grid:focus tr.selected .profile-node-file {
+ color: white;
+}
+
+#record-profile-status-bar-item {
+ background-image: url(Images/recordButtons.png);
+}
+
+#record-profile-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+#record-profile-status-bar-item.toggled-on {
+ background-position: 0 24px;
+}
+
+#record-profile-status-bar-item.toggled-on:active {
+ background-position: 32px 24px;
+}
+
+#node-search-status-bar-item {
+ background-image: url(Images/nodeSearchButtons.png);
+}
+
+#node-search-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+#node-search-status-bar-item.toggled-on {
+ background-position: 0 24px;
+}
+
+#node-search-status-bar-item.toggled-on:active {
+ background-position: 32px 24px;
+}
+
+.percent-time-status-bar-item {
+ background-image: url(Images/percentButtons.png) !important;
+}
+
+.percent-time-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+.percent-time-status-bar-item.toggled-on {
+ background-position: 0 24px;
+}
+
+.percent-time-status-bar-item.toggled-on:active {
+ background-position: 32px 24px;
+}
+
+.focus-profile-node-status-bar-item {
+ background-image: url(Images/focusButtons.png) !important;
+}
+
+.focus-profile-node-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+.exclude-profile-node-status-bar-item {
+ background-image: url(Images/excludeButtons.png) !important;
+}
+
+.exclude-profile-node-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+.reset-profile-status-bar-item {
+ background-image: url(Images/reloadButtons.png) !important;
+}
+
+.reset-profile-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+.delete-storage-status-bar-item {
+ background-image: url(Images/excludeButtons.png) !important;
+}
+
+.delete-storage-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+#storage-view-status-bar-items {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 200px;
+ overflow: hidden;
+ border-left: 1px solid rgb(184, 184, 184);
+ margin-left: -1px;
+}
+
+.refresh-storage-status-bar-item {
+ background-image: url(Images/reloadButtons.png) !important;
+}
+
+.refresh-storage-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+#storage-view-status-bar-items {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 200px;
+ overflow: hidden;
+ border-left: 1px solid rgb(184, 184, 184);
+ margin-left: -1px;
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector.html b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector.html
new file mode 100644
index 0000000..184bb45
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector.html
@@ -0,0 +1,97 @@
+<!--
+Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <link rel="stylesheet" type="text/css" href="inspector.css">
+ <script type="text/javascript" src="utilities.js"></script>
+ <script type="text/javascript" src="treeoutline.js"></script>
+ <script type="text/javascript" src="inspector.js"></script>
+ <script type="text/javascript" src="Object.js"></script>
+ <script type="text/javascript" src="TextPrompt.js"></script>
+ <script type="text/javascript" src="Placard.js"></script>
+ <script type="text/javascript" src="View.js"></script>
+ <script type="text/javascript" src="Console.js"></script>
+ <script type="text/javascript" src="Resource.js"></script>
+ <script type="text/javascript" src="ResourceCategory.js"></script>
+ <script type="text/javascript" src="Database.js"></script>
+ <script type="text/javascript" src="DOMStorage.js"></script>
+ <script type="text/javascript" src="DOMStorageItemsView.js"></script>
+ <script type="text/javascript" src="DataGrid.js"></script>
+ <script type="text/javascript" src="DOMStorageDataGrid.js"></script>
+ <script type="text/javascript" src="Script.js"></script>
+ <script type="text/javascript" src="Breakpoint.js"></script>
+ <script type="text/javascript" src="SidebarPane.js"></script>
+ <script type="text/javascript" src="ElementsTreeOutline.js"></script>
+ <script type="text/javascript" src="SidebarTreeElement.js"></script>
+ <script type="text/javascript" src="PropertiesSection.js"></script>
+ <script type="text/javascript" src="ObjectPropertiesSection.js"></script>
+ <script type="text/javascript" src="BreakpointsSidebarPane.js"></script>
+ <script type="text/javascript" src="CallStackSidebarPane.js"></script>
+ <script type="text/javascript" src="ScopeChainSidebarPane.js"></script>
+ <script type="text/javascript" src="MetricsSidebarPane.js"></script>
+ <script type="text/javascript" src="PropertiesSidebarPane.js"></script>
+ <script type="text/javascript" src="StylesSidebarPane.js"></script>
+ <script type="text/javascript" src="Panel.js"></script>
+ <script type="text/javascript" src="PanelEnablerView.js"></script>
+ <script type="text/javascript" src="ElementsPanel.js"></script>
+ <script type="text/javascript" src="ResourcesPanel.js"></script>
+ <script type="text/javascript" src="ScriptsPanel.js"></script>
+ <script type="text/javascript" src="DatabasesPanel.js"></script>
+ <script type="text/javascript" src="ProfilesPanel.js"></script>
+ <script type="text/javascript" src="ResourceView.js"></script>
+ <script type="text/javascript" src="SourceFrame.js"></script>
+ <script type="text/javascript" src="SourceView.js"></script>
+ <script type="text/javascript" src="FontView.js"></script>
+ <script type="text/javascript" src="ImageView.js"></script>
+ <script type="text/javascript" src="DatabaseTableView.js"></script>
+ <script type="text/javascript" src="DatabaseQueryView.js"></script>
+ <script type="text/javascript" src="ScriptView.js"></script>
+ <script type="text/javascript" src="ProfileDataGridTree.js"></script>
+ <script type="text/javascript" src="BottomUpProfileDataGridTree.js"></script>
+ <script type="text/javascript" src="TopDownProfileDataGridTree.js"></script>
+ <script type="text/javascript" src="ProfileView.js"></script>
+</head>
+<body class="detached">
+ <div id="toolbar">
+ <div class="toolbar-item close"><button id="close-button"></button></div>
+ <div class="toolbar-item flexable-space"></div>
+ <div class="toolbar-item hidden" id="search-results-matches"></div>
+ <div class="toolbar-item"><input id="search" type="search" incremental results="0"><div id="search-toolbar-label" class="toolbar-label"></div></div>
+ </div>
+ <div id="main">
+ <div id="main-panels" tabindex="0"></div>
+ <div id="main-status-bar" class="status-bar"><div id="anchored-status-bar-items"><button id="dock-status-bar-item" class="status-bar-item toggled"></button><button id="console-status-bar-item" class="status-bar-item"></button><div id="error-warning-count" class="hidden"></div></div></div>
+ </div>
+ <div id="console">
+ <div id="console-messages"><div id="console-prompt"><br></div></div>
+ <div id="console-status-bar" class="status-bar"><div id="other-console-status-bar-items"><button id="clear-console-status-bar-item" class="status-bar-item"></button></div></div>
+ </div>
+</body>
+</html>
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector.js
new file mode 100644
index 0000000..9d5bac0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector.js
@@ -0,0 +1,1381 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+var Preferences = {
+ ignoreWhitespace: true,
+ showUserAgentStyles: true,
+ maxInlineTextChildLength: 80,
+ minConsoleHeight: 75,
+ minSidebarWidth: 100,
+ minElementsSidebarWidth: 200,
+ minScriptsSidebarWidth: 200,
+ showInheritedComputedStyleProperties: false,
+ styleRulesExpandedState: {},
+ showMissingLocalizedStrings: false
+}
+
+var WebInspector = {
+ resources: {},
+ resourceURLMap: {},
+ missingLocalizedStrings: {},
+
+ get previousFocusElement()
+ {
+ return this._previousFocusElement;
+ },
+
+ get currentFocusElement()
+ {
+ return this._currentFocusElement;
+ },
+
+ set currentFocusElement(x)
+ {
+ if (this._currentFocusElement !== x)
+ this._previousFocusElement = this._currentFocusElement;
+ this._currentFocusElement = x;
+
+ if (this._currentFocusElement) {
+ this._currentFocusElement.focus();
+
+ // Make a caret selection inside the new element if there isn't a range selection and
+ // there isn't already a caret selection inside.
+ var selection = window.getSelection();
+ if (selection.isCollapsed && !this._currentFocusElement.isInsertionCaretInside()) {
+ var selectionRange = document.createRange();
+ selectionRange.setStart(this._currentFocusElement, 0);
+ selectionRange.setEnd(this._currentFocusElement, 0);
+
+ selection.removeAllRanges();
+ selection.addRange(selectionRange);
+ }
+ } else if (this._previousFocusElement)
+ this._previousFocusElement.blur();
+ },
+
+ get currentPanel()
+ {
+ return this._currentPanel;
+ },
+
+ set currentPanel(x)
+ {
+ if (this._currentPanel === x)
+ return;
+
+ if (this._currentPanel)
+ this._currentPanel.hide();
+
+ this._currentPanel = x;
+
+ this.updateSearchLabel();
+
+ if (x) {
+ x.show();
+
+ if (this.currentQuery) {
+ if (x.performSearch) {
+ function performPanelSearch()
+ {
+ this.updateSearchMatchesCount();
+
+ x.currentQuery = this.currentQuery;
+ x.performSearch(this.currentQuery);
+ }
+
+ // Perform the search on a timeout so the panel switches fast.
+ setTimeout(performPanelSearch.bind(this), 0);
+ } else {
+ // Update to show Not found for panels that can't be searched.
+ this.updateSearchMatchesCount();
+ }
+ }
+ }
+ },
+
+ get attached()
+ {
+ return this._attached;
+ },
+
+ set attached(x)
+ {
+ if (this._attached === x)
+ return;
+
+ this._attached = x;
+
+ this.updateSearchLabel();
+
+ var dockToggleButton = document.getElementById("dock-status-bar-item");
+ var body = document.body;
+
+ if (x) {
+ InspectorController.attach();
+ body.removeStyleClass("detached");
+ body.addStyleClass("attached");
+ dockToggleButton.title = WebInspector.UIString("Undock into separate window.");
+ } else {
+ InspectorController.detach();
+ body.removeStyleClass("attached");
+ body.addStyleClass("detached");
+ dockToggleButton.title = WebInspector.UIString("Dock to main window.");
+ }
+ },
+
+ get errors()
+ {
+ return this._errors || 0;
+ },
+
+ set errors(x)
+ {
+ x = Math.max(x, 0);
+
+ if (this._errors === x)
+ return;
+ this._errors = x;
+ this._updateErrorAndWarningCounts();
+ },
+
+ get warnings()
+ {
+ return this._warnings || 0;
+ },
+
+ set warnings(x)
+ {
+ x = Math.max(x, 0);
+
+ if (this._warnings === x)
+ return;
+ this._warnings = x;
+ this._updateErrorAndWarningCounts();
+ },
+
+ _updateErrorAndWarningCounts: function()
+ {
+ var errorWarningElement = document.getElementById("error-warning-count");
+ if (!errorWarningElement)
+ return;
+
+ if (!this.errors && !this.warnings) {
+ errorWarningElement.addStyleClass("hidden");
+ return;
+ }
+
+ errorWarningElement.removeStyleClass("hidden");
+
+ errorWarningElement.removeChildren();
+
+ if (this.errors) {
+ var errorElement = document.createElement("span");
+ errorElement.id = "error-count";
+ errorElement.textContent = this.errors;
+ errorWarningElement.appendChild(errorElement);
+ }
+
+ if (this.warnings) {
+ var warningsElement = document.createElement("span");
+ warningsElement.id = "warning-count";
+ warningsElement.textContent = this.warnings;
+ errorWarningElement.appendChild(warningsElement);
+ }
+
+ if (this.errors) {
+ if (this.warnings) {
+ if (this.errors == 1) {
+ if (this.warnings == 1)
+ errorWarningElement.title = WebInspector.UIString("%d error, %d warning", this.errors, this.warnings);
+ else
+ errorWarningElement.title = WebInspector.UIString("%d error, %d warnings", this.errors, this.warnings);
+ } else if (this.warnings == 1)
+ errorWarningElement.title = WebInspector.UIString("%d errors, %d warning", this.errors, this.warnings);
+ else
+ errorWarningElement.title = WebInspector.UIString("%d errors, %d warnings", this.errors, this.warnings);
+ } else if (this.errors == 1)
+ errorWarningElement.title = WebInspector.UIString("%d error", this.errors);
+ else
+ errorWarningElement.title = WebInspector.UIString("%d errors", this.errors);
+ } else if (this.warnings == 1)
+ errorWarningElement.title = WebInspector.UIString("%d warning", this.warnings);
+ else if (this.warnings)
+ errorWarningElement.title = WebInspector.UIString("%d warnings", this.warnings);
+ else
+ errorWarningElement.title = null;
+ },
+
+ get hoveredDOMNode()
+ {
+ return this._hoveredDOMNode;
+ },
+
+ set hoveredDOMNode(x)
+ {
+ if (objectsAreSame(this._hoveredDOMNode, x))
+ return;
+
+ this._hoveredDOMNode = x;
+
+ if (this._hoveredDOMNode)
+ this._updateHoverHighlightSoon(this.showingDOMNodeHighlight ? 50 : 500);
+ else
+ this._updateHoverHighlight();
+ },
+
+ _updateHoverHighlightSoon: function(delay)
+ {
+ if ("_updateHoverHighlightTimeout" in this)
+ clearTimeout(this._updateHoverHighlightTimeout);
+ this._updateHoverHighlightTimeout = setTimeout(this._updateHoverHighlight.bind(this), delay);
+ },
+
+ _updateHoverHighlight: function()
+ {
+ if ("_updateHoverHighlightTimeout" in this) {
+ clearTimeout(this._updateHoverHighlightTimeout);
+ delete this._updateHoverHighlightTimeout;
+ }
+
+ if (this._hoveredDOMNode) {
+ InspectorController.highlightDOMNode(this._hoveredDOMNode);
+ this.showingDOMNodeHighlight = true;
+ } else {
+ InspectorController.hideDOMNodeHighlight();
+ this.showingDOMNodeHighlight = false;
+ }
+ }
+}
+
+WebInspector.loaded = function()
+{
+ var platform = InspectorController.platform();
+ document.body.addStyleClass("platform-" + platform);
+
+ this.console = new WebInspector.Console();
+
+ this.panels = {};
+ var hiddenPanels = (InspectorController.hiddenPanels() || "").split(',');
+ if (hiddenPanels.indexOf("elements") === -1)
+ this.panels.elements = new WebInspector.ElementsPanel();
+ if (hiddenPanels.indexOf("resources") === -1)
+ this.panels.resources = new WebInspector.ResourcesPanel();
+ if (hiddenPanels.indexOf("scripts") === -1)
+ this.panels.scripts = new WebInspector.ScriptsPanel();
+ if (hiddenPanels.indexOf("profiles") === -1)
+ this.panels.profiles = new WebInspector.ProfilesPanel();
+ if (hiddenPanels.indexOf("databases") === -1)
+ this.panels.databases = new WebInspector.DatabasesPanel();
+
+ var toolbarElement = document.getElementById("toolbar");
+ var previousToolbarItem = toolbarElement.children[0];
+
+ for (var panelName in this.panels) {
+ var panel = this.panels[panelName];
+ var panelToolbarItem = panel.toolbarItem;
+ panelToolbarItem.addEventListener("click", this._toolbarItemClicked.bind(this));
+ if (previousToolbarItem)
+ toolbarElement.insertBefore(panelToolbarItem, previousToolbarItem.nextSibling);
+ else
+ toolbarElement.insertBefore(panelToolbarItem, toolbarElement.firstChild);
+ previousToolbarItem = panelToolbarItem;
+ }
+
+ this.currentPanel = this.panels.elements;
+
+ this.resourceCategories = {
+ documents: new WebInspector.ResourceCategory(WebInspector.UIString("Documents"), "documents"),
+ stylesheets: new WebInspector.ResourceCategory(WebInspector.UIString("Stylesheets"), "stylesheets"),
+ images: new WebInspector.ResourceCategory(WebInspector.UIString("Images"), "images"),
+ scripts: new WebInspector.ResourceCategory(WebInspector.UIString("Scripts"), "scripts"),
+ xhr: new WebInspector.ResourceCategory(WebInspector.UIString("XHR"), "xhr"),
+ fonts: new WebInspector.ResourceCategory(WebInspector.UIString("Fonts"), "fonts"),
+ other: new WebInspector.ResourceCategory(WebInspector.UIString("Other"), "other")
+ };
+
+ this.Tips = {
+ ResourceNotCompressed: {id: 0, message: WebInspector.UIString("You could save bandwidth by having your web server compress this transfer with gzip or zlib.")}
+ };
+
+ this.Warnings = {
+ IncorrectMIMEType: {id: 0, message: WebInspector.UIString("Resource interpreted as %s but transferred with MIME type %s.")}
+ };
+
+ this.addMainEventListeners(document);
+
+ window.addEventListener("unload", this.windowUnload.bind(this), true);
+ window.addEventListener("resize", this.windowResize.bind(this), true);
+
+ document.addEventListener("focus", this.focusChanged.bind(this), true);
+ document.addEventListener("keydown", this.documentKeyDown.bind(this), true);
+ document.addEventListener("keyup", this.documentKeyUp.bind(this), true);
+ document.addEventListener("beforecopy", this.documentCanCopy.bind(this), true);
+ document.addEventListener("copy", this.documentCopy.bind(this), true);
+
+ var mainPanelsElement = document.getElementById("main-panels");
+ mainPanelsElement.handleKeyEvent = this.mainKeyDown.bind(this);
+ mainPanelsElement.handleKeyUpEvent = this.mainKeyUp.bind(this);
+ mainPanelsElement.handleCopyEvent = this.mainCopy.bind(this);
+
+ // Focus the mainPanelsElement in a timeout so it happens after the initial focus,
+ // so it doesn't get reset to the first toolbar button. This initial focus happens
+ // on Mac when the window is made key and the WebHTMLView becomes the first responder.
+ setTimeout(function() { WebInspector.currentFocusElement = mainPanelsElement }, 0);
+
+ var dockToggleButton = document.getElementById("dock-status-bar-item");
+ dockToggleButton.addEventListener("click", this.toggleAttach.bind(this), false);
+
+ if (this.attached)
+ dockToggleButton.title = WebInspector.UIString("Undock into separate window.");
+ else
+ dockToggleButton.title = WebInspector.UIString("Dock to main window.");
+
+ var errorWarningCount = document.getElementById("error-warning-count");
+ errorWarningCount.addEventListener("click", this.console.show.bind(this.console), false);
+ this._updateErrorAndWarningCounts();
+
+ var searchField = document.getElementById("search");
+ searchField.addEventListener("keydown", this.searchKeyDown.bind(this), false);
+ searchField.addEventListener("keyup", this.searchKeyUp.bind(this), false);
+ searchField.addEventListener("search", this.performSearch.bind(this), false); // when the search is emptied
+
+ document.getElementById("toolbar").addEventListener("mousedown", this.toolbarDragStart, true);
+ document.getElementById("close-button").addEventListener("click", this.close, true);
+
+ InspectorController.loaded();
+}
+
+var windowLoaded = function()
+{
+ var localizedStringsURL = InspectorController.localizedStringsURL();
+ if (localizedStringsURL) {
+ var localizedStringsScriptElement = document.createElement("script");
+ localizedStringsScriptElement.addEventListener("load", WebInspector.loaded.bind(WebInspector), false);
+ localizedStringsScriptElement.type = "text/javascript";
+ localizedStringsScriptElement.src = localizedStringsURL;
+ document.getElementsByTagName("head").item(0).appendChild(localizedStringsScriptElement);
+ } else
+ WebInspector.loaded();
+
+ window.removeEventListener("load", windowLoaded, false);
+ delete windowLoaded;
+};
+
+window.addEventListener("load", windowLoaded, false);
+
+WebInspector.dispatch = function() {
+ var methodName = arguments[0];
+ var parameters = Array.prototype.slice.call(arguments, 1);
+ WebInspector[methodName].apply(this, parameters);
+}
+
+WebInspector.windowUnload = function(event)
+{
+ InspectorController.windowUnloading();
+}
+
+WebInspector.windowResize = function(event)
+{
+ if (this.currentPanel && this.currentPanel.resize)
+ this.currentPanel.resize();
+}
+
+WebInspector.windowFocused = function(event)
+{
+ if (event.target.nodeType === Node.DOCUMENT_NODE)
+ document.body.removeStyleClass("inactive");
+}
+
+WebInspector.windowBlured = function(event)
+{
+ if (event.target.nodeType === Node.DOCUMENT_NODE)
+ document.body.addStyleClass("inactive");
+}
+
+WebInspector.focusChanged = function(event)
+{
+ this.currentFocusElement = event.target;
+}
+
+WebInspector.setAttachedWindow = function(attached)
+{
+ this.attached = attached;
+}
+
+WebInspector.close = function(event)
+{
+ InspectorController.closeWindow();
+}
+
+WebInspector.documentClick = function(event)
+{
+ var anchor = event.target.enclosingNodeOrSelfWithNodeName("a");
+ if (!anchor)
+ return;
+
+ // Prevent the link from navigating, since we don't do any navigation by following links normally.
+ event.preventDefault();
+
+ function followLink()
+ {
+ // FIXME: support webkit-html-external-link links here.
+ if (anchor.href in WebInspector.resourceURLMap) {
+ if (anchor.hasStyleClass("webkit-html-external-link")) {
+ anchor.removeStyleClass("webkit-html-external-link");
+ anchor.addStyleClass("webkit-html-resource-link");
+ }
+
+ WebInspector.showResourceForURL(anchor.href, anchor.lineNumber, anchor.preferredPanel);
+ } else {
+ var profileStringRegEx = new RegExp("webkit-profile://.+/([0-9]+)");
+ var profileString = profileStringRegEx.exec(anchor.href);
+ if (profileString)
+ WebInspector.showProfileById(profileString[1])
+ }
+ }
+
+ if (WebInspector.followLinkTimeout)
+ clearTimeout(WebInspector.followLinkTimeout);
+
+ if (anchor.preventFollowOnDoubleClick) {
+ // Start a timeout if this is the first click, if the timeout is canceled
+ // before it fires, then a double clicked happened or another link was clicked.
+ if (event.detail === 1)
+ WebInspector.followLinkTimeout = setTimeout(followLink, 333);
+ return;
+ }
+
+ followLink();
+}
+
+WebInspector.documentKeyDown = function(event)
+{
+ if (!this.currentFocusElement)
+ return;
+ if (this.currentFocusElement.handleKeyEvent)
+ this.currentFocusElement.handleKeyEvent(event);
+ else if (this.currentFocusElement.id && this.currentFocusElement.id.length && WebInspector[this.currentFocusElement.id + "KeyDown"])
+ WebInspector[this.currentFocusElement.id + "KeyDown"](event);
+
+ if (!event.handled) {
+ var isMac = InspectorController.platform().indexOf("mac-") === 0;
+
+ switch (event.keyIdentifier) {
+ case "U+001B": // Escape key
+ this.console.visible = !this.console.visible;
+ event.preventDefault();
+ break;
+
+ case "U+0046": // F key
+ if (isMac)
+ var isFindKey = event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey;
+ else
+ var isFindKey = event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey;
+
+ if (isFindKey) {
+ var searchField = document.getElementById("search");
+ searchField.focus();
+ searchField.select();
+ event.preventDefault();
+ }
+
+ break;
+
+ case "U+0047": // G key
+ if (isMac)
+ var isFindAgainKey = event.metaKey && !event.ctrlKey && !event.altKey;
+ else
+ var isFindAgainKey = event.ctrlKey && !event.metaKey && !event.altKey;
+
+ if (isFindAgainKey) {
+ if (event.shiftKey) {
+ if (this.currentPanel.jumpToPreviousSearchResult)
+ this.currentPanel.jumpToPreviousSearchResult();
+ } else if (this.currentPanel.jumpToNextSearchResult)
+ this.currentPanel.jumpToNextSearchResult();
+ event.preventDefault();
+ }
+
+ break;
+ }
+ }
+}
+
+WebInspector.documentKeyUp = function(event)
+{
+ if (!this.currentFocusElement || !this.currentFocusElement.handleKeyUpEvent)
+ return;
+ this.currentFocusElement.handleKeyUpEvent(event);
+}
+
+WebInspector.documentCanCopy = function(event)
+{
+ if (!this.currentFocusElement)
+ return;
+ // Calling preventDefault() will say "we support copying, so enable the Copy menu".
+ if (this.currentFocusElement.handleCopyEvent)
+ event.preventDefault();
+ else if (this.currentFocusElement.id && this.currentFocusElement.id.length && WebInspector[this.currentFocusElement.id + "Copy"])
+ event.preventDefault();
+}
+
+WebInspector.documentCopy = function(event)
+{
+ if (!this.currentFocusElement)
+ return;
+ if (this.currentFocusElement.handleCopyEvent)
+ this.currentFocusElement.handleCopyEvent(event);
+ else if (this.currentFocusElement.id && this.currentFocusElement.id.length && WebInspector[this.currentFocusElement.id + "Copy"])
+ WebInspector[this.currentFocusElement.id + "Copy"](event);
+}
+
+WebInspector.mainKeyDown = function(event)
+{
+ if (this.currentPanel && this.currentPanel.handleKeyEvent)
+ this.currentPanel.handleKeyEvent(event);
+}
+
+WebInspector.mainKeyUp = function(event)
+{
+ if (this.currentPanel && this.currentPanel.handleKeyUpEvent)
+ this.currentPanel.handleKeyUpEvent(event);
+}
+
+WebInspector.mainCopy = function(event)
+{
+ if (this.currentPanel && this.currentPanel.handleCopyEvent)
+ this.currentPanel.handleCopyEvent(event);
+}
+
+WebInspector.animateStyle = function(animations, duration, callback, complete)
+{
+ if (complete === undefined)
+ complete = 0;
+ var slice = (1000 / 30); // 30 frames per second
+
+ var defaultUnit = "px";
+ var propertyUnit = {opacity: ""};
+
+ for (var i = 0; i < animations.length; ++i) {
+ var animation = animations[i];
+ var element = null;
+ var start = null;
+ var current = null;
+ var end = null;
+ for (key in animation) {
+ if (key === "element")
+ element = animation[key];
+ else if (key === "start")
+ start = animation[key];
+ else if (key === "current")
+ current = animation[key];
+ else if (key === "end")
+ end = animation[key];
+ }
+
+ if (!element || !end)
+ continue;
+
+ var computedStyle = element.ownerDocument.defaultView.getComputedStyle(element);
+ if (!start) {
+ start = {};
+ for (key in end)
+ start[key] = parseInt(computedStyle.getPropertyValue(key));
+ animation.start = start;
+ } else if (complete == 0)
+ for (key in start)
+ element.style.setProperty(key, start[key] + (key in propertyUnit ? propertyUnit[key] : defaultUnit));
+
+ if (!current) {
+ current = {};
+ for (key in start)
+ current[key] = start[key];
+ animation.current = current;
+ }
+
+ function cubicInOut(t, b, c, d)
+ {
+ if ((t/=d/2) < 1) return c/2*t*t*t + b;
+ return c/2*((t-=2)*t*t + 2) + b;
+ }
+
+ var style = element.style;
+ for (key in end) {
+ var startValue = start[key];
+ var currentValue = current[key];
+ var endValue = end[key];
+ if ((complete + slice) < duration) {
+ var delta = (endValue - startValue) / (duration / slice);
+ var newValue = cubicInOut(complete, startValue, endValue - startValue, duration);
+ style.setProperty(key, newValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit));
+ current[key] = newValue;
+ } else {
+ style.setProperty(key, endValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit));
+ }
+ }
+ }
+
+ if (complete < duration)
+ setTimeout(WebInspector.animateStyle, slice, animations, duration, callback, complete + slice);
+ else if (callback)
+ callback();
+}
+
+WebInspector.updateSearchLabel = function()
+{
+ if (!this.currentPanel)
+ return;
+
+ var newLabel = WebInspector.UIString("Search %s", this.currentPanel.toolbarItemLabel);
+ if (this.attached)
+ document.getElementById("search").setAttribute("placeholder", newLabel);
+ else {
+ document.getElementById("search").removeAttribute("placeholder");
+ document.getElementById("search-toolbar-label").textContent = newLabel;
+ }
+}
+
+WebInspector.toggleAttach = function()
+{
+ this.attached = !this.attached;
+}
+
+WebInspector.toolbarDragStart = function(event)
+{
+ if (!WebInspector.attached && InspectorController.platform() !== "mac-leopard")
+ return;
+
+ var target = event.target;
+ if (target.hasStyleClass("toolbar-item") && target.hasStyleClass("toggleable"))
+ return;
+
+ var toolbar = document.getElementById("toolbar");
+ if (target !== toolbar && !target.hasStyleClass("toolbar-item"))
+ return;
+
+ toolbar.lastScreenX = event.screenX;
+ toolbar.lastScreenY = event.screenY;
+
+ WebInspector.elementDragStart(toolbar, WebInspector.toolbarDrag, WebInspector.toolbarDragEnd, event, (WebInspector.attached ? "row-resize" : "default"));
+}
+
+WebInspector.toolbarDragEnd = function(event)
+{
+ var toolbar = document.getElementById("toolbar");
+
+ WebInspector.elementDragEnd(event);
+
+ delete toolbar.lastScreenX;
+ delete toolbar.lastScreenY;
+}
+
+WebInspector.toolbarDrag = function(event)
+{
+ var toolbar = document.getElementById("toolbar");
+
+ if (WebInspector.attached) {
+ var height = window.innerHeight - (event.screenY - toolbar.lastScreenY);
+
+ InspectorController.setAttachedWindowHeight(height);
+ } else {
+ var x = event.screenX - toolbar.lastScreenX;
+ var y = event.screenY - toolbar.lastScreenY;
+
+ // We cannot call window.moveBy here because it restricts the movement
+ // of the window at the edges.
+ InspectorController.moveByUnrestricted(x, y);
+ }
+
+ toolbar.lastScreenX = event.screenX;
+ toolbar.lastScreenY = event.screenY;
+
+ event.preventDefault();
+}
+
+WebInspector.elementDragStart = function(element, dividerDrag, elementDragEnd, event, cursor)
+{
+ if (this._elementDraggingEventListener || this._elementEndDraggingEventListener)
+ this.elementDragEnd(event);
+
+ this._elementDraggingEventListener = dividerDrag;
+ this._elementEndDraggingEventListener = elementDragEnd;
+
+ document.addEventListener("mousemove", dividerDrag, true);
+ document.addEventListener("mouseup", elementDragEnd, true);
+
+ document.body.style.cursor = cursor;
+
+ event.preventDefault();
+}
+
+WebInspector.elementDragEnd = function(event)
+{
+ document.removeEventListener("mousemove", this._elementDraggingEventListener, true);
+ document.removeEventListener("mouseup", this._elementEndDraggingEventListener, true);
+
+ document.body.style.removeProperty("cursor");
+
+ delete this._elementDraggingEventListener;
+ delete this._elementEndDraggingEventListener;
+
+ event.preventDefault();
+}
+
+WebInspector.showConsole = function()
+{
+ this.console.show();
+}
+
+WebInspector.showElementsPanel = function()
+{
+ this.currentPanel = this.panels.elements;
+}
+
+WebInspector.showResourcesPanel = function()
+{
+ this.currentPanel = this.panels.resources;
+}
+
+WebInspector.showScriptsPanel = function()
+{
+ this.currentPanel = this.panels.scripts;
+}
+
+WebInspector.showProfilesPanel = function()
+{
+ this.currentPanel = this.panels.profiles;
+}
+
+WebInspector.showDatabasesPanel = function()
+{
+ this.currentPanel = this.panels.databases;
+}
+
+WebInspector.addResource = function(identifier, payload)
+{
+ var resource = new WebInspector.Resource(
+ payload.requestHeaders,
+ payload.requestURL,
+ payload.host,
+ payload.path,
+ payload.lastPathComponent,
+ identifier,
+ payload.isMainResource,
+ payload.cached);
+ this.resources[identifier] = resource;
+ this.resourceURLMap[resource.url] = resource;
+
+ if (resource.mainResource) {
+ this.mainResource = resource;
+ this.panels.elements.reset();
+ }
+
+ if (this.panels.resources)
+ this.panels.resources.addResource(resource);
+}
+
+WebInspector.updateResource = function(identifier, payload)
+{
+ var resource = this.resources[identifier];
+ if (!resource)
+ return;
+
+ if (payload.didRequestChange) {
+ resource.url = payload.url;
+ resource.domain = payload.domain;
+ resource.path = payload.path;
+ resource.lastPathComponent = payload.lastPathComponent;
+ resource.requestHeaders = payload.requestHeaders;
+ resource.mainResource = payload.mainResource;
+ }
+
+ if (payload.didResponseChange) {
+ resource.mimeType = payload.mimeType;
+ resource.suggestedFilename = payload.suggestedFilename;
+ resource.expectedContentLength = payload.expectedContentLength;
+ resource.statusCode = payload.statusCode;
+ resource.suggestedFilename = payload.suggestedFilename;
+ resource.responseHeaders = payload.responseHeaders;
+ }
+
+ if (payload.didTypeChange) {
+ resource.type = payload.type;
+ }
+
+ if (payload.didLengthChange) {
+ resource.contentLength = payload.contentLength;
+ }
+
+ if (payload.didCompletionChange) {
+ resource.failed = payload.failed;
+ resource.finished = payload.finished;
+ }
+
+ if (payload.didTimingChange) {
+ if (payload.startTime)
+ resource.startTime = payload.startTime;
+ if (payload.responseReceivedTime)
+ resource.responseReceivedTime = payload.responseReceivedTime;
+ if (payload.endTime)
+ resource.endTime = payload.endTime;
+ }
+}
+
+WebInspector.removeResource = function(identifier)
+{
+ var resource = this.resources[identifier];
+ if (!resource)
+ return;
+
+ resource.category.removeResource(resource);
+ delete this.resourceURLMap[resource.url];
+ delete this.resources[identifier];
+
+ if (this.panels.resources)
+ this.panels.resources.removeResource(resource);
+}
+
+WebInspector.addDatabase = function(payload)
+{
+ var database = new WebInspector.Database(
+ payload.database,
+ payload.domain,
+ payload.name,
+ payload.version);
+ this.panels.databases.addDatabase(database);
+}
+
+WebInspector.addDOMStorage = function(payload)
+{
+ var domStorage = new WebInspector.DOMStorage(
+ payload.domStorage,
+ payload.host,
+ payload.isLocalStorage);
+ this.panels.databases.addDOMStorage(domStorage);
+}
+
+WebInspector.resourceTrackingWasEnabled = function()
+{
+ this.panels.resources.resourceTrackingWasEnabled();
+}
+
+WebInspector.resourceTrackingWasDisabled = function()
+{
+ this.panels.resources.resourceTrackingWasDisabled();
+}
+
+WebInspector.attachDebuggerWhenShown = function()
+{
+ this.panels.scripts.attachDebuggerWhenShown();
+}
+
+WebInspector.debuggerWasEnabled = function()
+{
+ this.panels.scripts.debuggerWasEnabled();
+}
+
+WebInspector.debuggerWasDisabled = function()
+{
+ this.panels.scripts.debuggerWasDisabled();
+}
+
+WebInspector.profilerWasEnabled = function()
+{
+ this.panels.profiles.profilerWasEnabled();
+}
+
+WebInspector.profilerWasDisabled = function()
+{
+ this.panels.profiles.profilerWasDisabled();
+}
+
+WebInspector.parsedScriptSource = function(sourceID, sourceURL, source, startingLine)
+{
+ this.panels.scripts.addScript(sourceID, sourceURL, source, startingLine);
+}
+
+WebInspector.failedToParseScriptSource = function(sourceURL, source, startingLine, errorLine, errorMessage)
+{
+ this.panels.scripts.addScript(null, sourceURL, source, startingLine, errorLine, errorMessage);
+}
+
+WebInspector.pausedScript = function()
+{
+ this.panels.scripts.debuggerPaused();
+}
+
+WebInspector.resumedScript = function()
+{
+ this.panels.scripts.debuggerResumed();
+}
+
+WebInspector.populateInterface = function()
+{
+ for (var panelName in this.panels) {
+ var panel = this.panels[panelName];
+ if ("populateInterface" in panel)
+ panel.populateInterface();
+ }
+}
+
+WebInspector.reset = function()
+{
+ for (var panelName in this.panels) {
+ var panel = this.panels[panelName];
+ if ("reset" in panel)
+ panel.reset();
+ }
+
+ for (var category in this.resourceCategories)
+ this.resourceCategories[category].removeAllResources();
+
+ this.resources = {};
+ this.resourceURLMap = {};
+ this.hoveredDOMNode = null;
+
+ delete this.mainResource;
+
+ this.console.clearMessages();
+}
+
+WebInspector.inspectedWindowCleared = function(inspectedWindow)
+{
+ this.panels.elements.inspectedWindowCleared(inspectedWindow);
+}
+
+WebInspector.resourceURLChanged = function(resource, oldURL)
+{
+ delete this.resourceURLMap[oldURL];
+ this.resourceURLMap[resource.url] = resource;
+}
+
+WebInspector.addMessageToConsole = function(payload)
+{
+ var consoleMessage = new WebInspector.ConsoleMessage(
+ payload.source,
+ payload.level,
+ payload.line,
+ payload.url,
+ payload.groupLevel,
+ payload.repeatCount);
+ consoleMessage.setMessageBody(Array.prototype.slice.call(arguments, 1));
+ this.console.addMessage(consoleMessage);
+}
+
+WebInspector.addProfile = function(profile)
+{
+ this.panels.profiles.addProfile(profile);
+}
+
+WebInspector.setRecordingProfile = function(isProfiling)
+{
+ this.panels.profiles.setRecordingProfile(isProfiling);
+}
+
+WebInspector.drawLoadingPieChart = function(canvas, percent) {
+ var g = canvas.getContext("2d");
+ var darkColor = "rgb(122, 168, 218)";
+ var lightColor = "rgb(228, 241, 251)";
+ var cx = 8;
+ var cy = 8;
+ var r = 7;
+
+ g.beginPath();
+ g.arc(cx, cy, r, 0, Math.PI * 2, false);
+ g.closePath();
+
+ g.lineWidth = 1;
+ g.strokeStyle = darkColor;
+ g.fillStyle = lightColor;
+ g.fill();
+ g.stroke();
+
+ var startangle = -Math.PI / 2;
+ var endangle = startangle + (percent * Math.PI * 2);
+
+ g.beginPath();
+ g.moveTo(cx, cy);
+ g.arc(cx, cy, r, startangle, endangle, false);
+ g.closePath();
+
+ g.fillStyle = darkColor;
+ g.fill();
+}
+
+WebInspector.updateFocusedNode = function(node)
+{
+ if (!node)
+ // FIXME: Should we deselect if null is passed in?
+ return;
+
+ this.currentPanel = this.panels.elements;
+ this.panels.elements.focusedDOMNode = node;
+}
+
+WebInspector.displayNameForURL = function(url)
+{
+ if (!url)
+ return "";
+ var resource = this.resourceURLMap[url];
+ if (resource)
+ return resource.displayName;
+ return url.trimURL(WebInspector.mainResource ? WebInspector.mainResource.domain : "");
+}
+
+WebInspector.resourceForURL = function(url)
+{
+ if (url in this.resourceURLMap)
+ return this.resourceURLMap[url];
+
+ // No direct match found. Search for resources that contain
+ // a substring of the URL.
+ for (var resourceURL in this.resourceURLMap) {
+ if (resourceURL.hasSubstring(url))
+ return this.resourceURLMap[resourceURL];
+ }
+
+ return null;
+}
+
+WebInspector.showResourceForURL = function(url, line, preferredPanel)
+{
+ var resource = this.resourceForURL(url);
+ if (!resource)
+ return false;
+
+ if (preferredPanel && preferredPanel in WebInspector.panels) {
+ var panel = this.panels[preferredPanel];
+ if (!("showResource" in panel))
+ panel = null;
+ else if ("canShowResource" in panel && !panel.canShowResource(resource))
+ panel = null;
+ }
+
+ this.currentPanel = panel || this.panels.resources;
+ if (!this.currentPanel)
+ return false;
+ this.currentPanel.showResource(resource, line);
+ return true;
+}
+
+WebInspector.linkifyStringAsFragment = function(string)
+{
+ var container = document.createDocumentFragment();
+ var linkStringRegEx = new RegExp("(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}://|www\\.)[\\w$\\-_+*'=\\|/\\\\(){}[\\]%@&#~,:;.!?]{2,}[\\w$\\-_+*=\\|/\\\\({%@&#~]");
+
+ while (string) {
+ var linkString = linkStringRegEx.exec(string);
+ if (!linkString)
+ break;
+
+ linkString = linkString[0];
+ var title = linkString;
+ var linkIndex = string.indexOf(linkString);
+ var nonLink = string.substring(0, linkIndex);
+ container.appendChild(document.createTextNode(nonLink));
+
+ var profileStringRegEx = new RegExp("webkit-profile://(.+)/[0-9]+");
+ var profileStringMatches = profileStringRegEx.exec(title);
+ var profileTitle;
+ if (profileStringMatches)
+ profileTitle = profileStringMatches[1];
+ if (profileTitle)
+ title = WebInspector.panels.profiles.displayTitleForProfileLink(profileTitle);
+
+ var realURL = (linkString.indexOf("www.") === 0 ? "http://" + linkString : linkString);
+ container.appendChild(WebInspector.linkifyURLAsNode(realURL, title, null, (realURL in WebInspector.resourceURLMap)));
+ string = string.substring(linkIndex + linkString.length, string.length);
+ }
+
+ if (string)
+ container.appendChild(document.createTextNode(string));
+
+ return container;
+}
+
+WebInspector.showProfileById = function(uid) {
+ WebInspector.showProfilesPanel();
+ WebInspector.panels.profiles.showProfileById(uid);
+}
+
+WebInspector.linkifyURLAsNode = function(url, linkText, classes, isExternal)
+{
+ if (!linkText)
+ linkText = url;
+ classes = (classes ? classes + " " : "");
+ classes += isExternal ? "webkit-html-external-link" : "webkit-html-resource-link";
+
+ var a = document.createElement("a");
+ a.href = url;
+ a.className = classes;
+ a.title = url;
+ a.target = "_blank";
+ a.textContent = linkText;
+
+ return a;
+}
+
+WebInspector.linkifyURL = function(url, linkText, classes, isExternal)
+{
+ // Use the DOM version of this function so as to avoid needing to escape attributes.
+ // FIXME: Get rid of linkifyURL entirely.
+ return WebInspector.linkifyURLAsNode(url, linkText, classes, isExternal).outerHTML;
+}
+
+WebInspector.addMainEventListeners = function(doc)
+{
+ doc.defaultView.addEventListener("focus", this.windowFocused.bind(this), true);
+ doc.defaultView.addEventListener("blur", this.windowBlured.bind(this), true);
+ doc.addEventListener("click", this.documentClick.bind(this), true);
+}
+
+WebInspector.searchKeyDown = function(event)
+{
+ if (event.keyIdentifier !== "Enter")
+ return;
+
+ // Call preventDefault since this was the Enter key. This prevents a "search" event
+ // from firing for key down. We handle the Enter key on key up in searchKeyUp. This
+ // stops performSearch from being called twice in a row.
+ event.preventDefault();
+}
+
+WebInspector.searchKeyUp = function(event)
+{
+ if (event.keyIdentifier !== "Enter")
+ return;
+
+ // Select all of the text so the user can easily type an entirely new query.
+ event.target.select();
+
+ // Only call performSearch if the Enter key was pressed. Otherwise the search
+ // performance is poor because of searching on every key. The search field has
+ // the incremental attribute set, so we still get incremental searches.
+ this.performSearch(event);
+}
+
+WebInspector.performSearch = function(event)
+{
+ var query = event.target.value;
+ var forceSearch = event.keyIdentifier === "Enter";
+
+ if (!query || !query.length || (!forceSearch && query.length < 3)) {
+ delete this.currentQuery;
+
+ for (var panelName in this.panels) {
+ var panel = this.panels[panelName];
+ if (panel.currentQuery && panel.searchCanceled)
+ panel.searchCanceled();
+ delete panel.currentQuery;
+ }
+
+ this.updateSearchMatchesCount();
+
+ return;
+ }
+
+ if (query === this.currentPanel.currentQuery && this.currentPanel.currentQuery === this.currentQuery) {
+ // When this is the same query and a forced search, jump to the next
+ // search result for a good user experience.
+ if (forceSearch && this.currentPanel.jumpToNextSearchResult)
+ this.currentPanel.jumpToNextSearchResult();
+ return;
+ }
+
+ this.currentQuery = query;
+
+ this.updateSearchMatchesCount();
+
+ if (!this.currentPanel.performSearch)
+ return;
+
+ this.currentPanel.currentQuery = query;
+ this.currentPanel.performSearch(query);
+}
+
+WebInspector.updateSearchMatchesCount = function(matches, panel)
+{
+ if (!panel)
+ panel = this.currentPanel;
+
+ panel.currentSearchMatches = matches;
+
+ if (panel !== this.currentPanel)
+ return;
+
+ if (!this.currentPanel.currentQuery) {
+ document.getElementById("search-results-matches").addStyleClass("hidden");
+ return;
+ }
+
+ if (matches) {
+ if (matches === 1)
+ var matchesString = WebInspector.UIString("1 match");
+ else
+ var matchesString = WebInspector.UIString("%d matches", matches);
+ } else
+ var matchesString = WebInspector.UIString("Not Found");
+
+ var matchesToolbarElement = document.getElementById("search-results-matches");
+ matchesToolbarElement.removeStyleClass("hidden");
+ matchesToolbarElement.textContent = matchesString;
+}
+
+WebInspector.UIString = function(string)
+{
+ if (window.localizedStrings && string in window.localizedStrings)
+ string = window.localizedStrings[string];
+ else {
+ if (!(string in this.missingLocalizedStrings)) {
+ console.error("Localized string \"" + string + "\" not found.");
+ this.missingLocalizedStrings[string] = true;
+ }
+
+ if (Preferences.showMissingLocalizedStrings)
+ string += " (not localized)";
+ }
+
+ return String.vsprintf(string, Array.prototype.slice.call(arguments, 1));
+}
+
+WebInspector.isBeingEdited = function(element)
+{
+ return element.__editing;
+}
+
+WebInspector.startEditing = function(element, committedCallback, cancelledCallback, context)
+{
+ if (element.__editing)
+ return;
+ element.__editing = true;
+
+ var oldText = element.textContent;
+ var oldHandleKeyEvent = element.handleKeyEvent;
+
+ element.addStyleClass("editing");
+
+ var oldTabIndex = element.tabIndex;
+ if (element.tabIndex < 0)
+ element.tabIndex = 0;
+
+ function blurEventListener() {
+ editingCommitted.call(element);
+ }
+
+ function cleanUpAfterEditing() {
+ delete this.__editing;
+
+ this.removeStyleClass("editing");
+ this.tabIndex = oldTabIndex;
+ this.scrollTop = 0;
+ this.scrollLeft = 0;
+
+ this.handleKeyEvent = oldHandleKeyEvent;
+ element.removeEventListener("blur", blurEventListener, false);
+
+ if (element === WebInspector.currentFocusElement || element.isAncestor(WebInspector.currentFocusElement))
+ WebInspector.currentFocusElement = WebInspector.previousFocusElement;
+ }
+
+ function editingCancelled() {
+ this.innerText = oldText;
+
+ cleanUpAfterEditing.call(this);
+
+ cancelledCallback(this, context);
+ }
+
+ function editingCommitted() {
+ cleanUpAfterEditing.call(this);
+
+ committedCallback(this, this.textContent, oldText, context);
+ }
+
+ element.handleKeyEvent = function(event) {
+ if (oldHandleKeyEvent)
+ oldHandleKeyEvent(event);
+ if (event.handled)
+ return;
+
+ if (event.keyIdentifier === "Enter") {
+ editingCommitted.call(element);
+ event.preventDefault();
+ } else if (event.keyCode === 27) { // Escape key
+ editingCancelled.call(element);
+ event.preventDefault();
+ event.handled = true;
+ }
+ }
+
+ element.addEventListener("blur", blurEventListener, false);
+
+ WebInspector.currentFocusElement = element;
+}
+
+WebInspector._toolbarItemClicked = function(event)
+{
+ var toolbarItem = event.currentTarget;
+ this.currentPanel = toolbarItem.panel;
+}
+
+// This table maps MIME types to the Resource.Types which are valid for them.
+// The following line:
+// "text/html": {0: 1},
+// means that text/html is a valid MIME type for resources that have type
+// WebInspector.Resource.Type.Document (which has a value of 0).
+WebInspector.MIMETypes = {
+ "text/html": {0: true},
+ "text/xml": {0: true},
+ "text/plain": {0: true},
+ "application/xhtml+xml": {0: true},
+ "text/css": {1: true},
+ "text/xsl": {1: true},
+ "image/jpeg": {2: true},
+ "image/png": {2: true},
+ "image/gif": {2: true},
+ "image/bmp": {2: true},
+ "image/vnd.microsoft.icon": {2: true},
+ "image/x-icon": {2: true},
+ "image/x-xbitmap": {2: true},
+ "font/ttf": {3: true},
+ "font/opentype": {3: true},
+ "application/x-font-type1": {3: true},
+ "application/x-font-ttf": {3: true},
+ "application/x-truetype-font": {3: true},
+ "text/javascript": {4: true},
+ "text/ecmascript": {4: true},
+ "application/javascript": {4: true},
+ "application/ecmascript": {4: true},
+ "application/x-javascript": {4: true},
+ "text/javascript1.1": {4: true},
+ "text/javascript1.2": {4: true},
+ "text/javascript1.3": {4: true},
+ "text/jscript": {4: true},
+ "text/livescript": {4: true},
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector_controller.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector_controller.js
new file mode 100644
index 0000000..5401b49
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector_controller.js
@@ -0,0 +1,430 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Stub implementation of the InspectorController API.
+ * This stub class is supposed to make front-end a standalone WebApp
+ * that can be implemented/refactored in isolation from the Web browser
+ * backend. Clients need to subclass it in order to wire calls to the
+ * non-stub backends.
+ */
+goog.provide('devtools.InspectorController');
+
+
+/**
+ * Creates inspector controller stub instance.
+ * @constructor.
+ */
+devtools.InspectorController = function() {
+ /**
+ * @type {boolean}
+ */
+ this.searchingForNode_ = false;
+
+ /**
+ * @type {boolean}
+ */
+ this.windowVisible_ = true;
+
+ /**
+ * @type {number}
+ */
+ this.attachedWindowHeight_ = 0;
+
+ /**
+ * @type {boolean}
+ */
+ this.debuggerEnabled_ = true;
+
+ /**
+ * @type {boolean}
+ */
+ this.profilerEnabled_ = true;
+
+ /**
+ * @type {boolean}
+ */
+ this.resourceTrackingEnabled_ = false;
+};
+
+
+/**
+ * Wraps javascript callback.
+ * @param {function():undefined} func The callback to wrap.
+ * @return {function():undefined} Callback wrapper.
+ */
+devtools.InspectorController.prototype.wrapCallback = function f(func) {
+ // Just return as is.
+ return func;
+};
+
+
+/**
+ * @return {boolean} True iff inspector window is currently visible.
+ */
+devtools.InspectorController.prototype.isWindowVisible = function() {
+ return this.windowVisible_;
+};
+
+
+/**
+ * @return {string} Platform identifier.
+ */
+devtools.InspectorController.prototype.platform = function() {
+ return 'windows';
+};
+
+
+/**
+ * Closes inspector window.
+ */
+devtools.InspectorController.prototype.closeWindow = function() {
+ this.windowVisible_ = false;
+};
+
+
+/**
+ * Attaches frontend to the backend.
+ */
+devtools.InspectorController.prototype.attach = function() {
+};
+
+
+/**
+ * Detaches frontend from the backend.
+ */
+devtools.InspectorController.prototype.detach = function() {
+};
+
+
+/**
+ * Clears console message log in the backend.
+ */
+devtools.InspectorController.prototype.clearMessages = function() {
+};
+
+
+/**
+ * Returns true iff browser is currently in the search for node mode.
+ * @return {boolean} True is currently searching for a node.
+ */
+devtools.InspectorController.prototype.searchingForNode = function() {
+ return this.searchingForNode_;
+};
+
+
+/**
+ * Initiates search for a given query starting on a given row.
+ * @param {number} sourceRow Row to start searching from.
+ * @param {string} query Query string for search for.
+ */
+devtools.InspectorController.prototype.search = function(sourceRow, query) {
+};
+
+
+/**
+ * Toggles node search mode on/off.
+ */
+devtools.InspectorController.prototype.toggleNodeSearch = function() {
+ this.searchingForNode_ = !this.searchingForNode_;
+};
+
+
+/**
+ * Sets the inspector window height while in the attached mode.
+ * @param {number} height Window height being set.
+ */
+devtools.InspectorController.prototype.setAttachedWindowHeight =
+ function(height) {
+ this.attachedWindowHeight_ = height;
+};
+
+
+/**
+ * Moves window by the given offset.
+ * @param {number} x X offset.
+ * @param {number} y Y offset.
+ */
+devtools.InspectorController.prototype.moveByUnrestricted = function(x, y) {
+};
+
+
+/**
+ * Adds resource with given identifier into the given iframe element.
+ * @param {number} identifier Identifier of the resource to add into the frame.
+ * @param {Element} element Element to add resource content to.
+ */
+devtools.InspectorController.prototype.addResourceSourceToFrame =
+ function(identifier, element) {
+};
+
+
+/**
+ * Adds given source of a given mimeType into the given iframe element.
+ * @param {string} mimeType MIME type of the content to be added.
+ * @param {string} source String content to be added.
+ * @param {Element} element Element to add resource content to.
+ */
+devtools.InspectorController.prototype.addSourceToFrame =
+ function(mimeType, source, element) {
+ return false;
+};
+
+
+/**
+ * Returns document node corresponding to the resource with given id.
+ * @return {Node} Node containing the resource.
+ */
+devtools.InspectorController.prototype.getResourceDocumentNode =
+ function(identifier) {
+ return undefined;
+};
+
+
+/**
+ * Highlights the given node on the page.
+ * @param {Node} node Node to highlight.
+ */
+devtools.InspectorController.prototype.highlightDOMNode = function(node) {
+ // Does nothing in stub.
+};
+
+
+/**
+ * Clears current highlight.
+ */
+devtools.InspectorController.prototype.hideDOMNodeHighlight = function() {
+ // Does nothing in stub.
+};
+
+
+/**
+ * @return {window} Inspectable window instance.
+ */
+devtools.InspectorController.prototype.inspectedWindow = function() {
+ return window;
+};
+
+
+/**
+ * Notifies backend that the frontend has been successfully loaded.
+ */
+devtools.InspectorController.prototype.loaded = function() {
+ // Does nothing in stub.
+};
+
+
+/**
+ * @return {string} Url of the i18n-ed strings map.
+ */
+devtools.InspectorController.prototype.localizedStringsURL = function() {
+ return undefined;
+};
+
+
+/**
+ * @return {boolean} True iff window is currently unloading.
+ */
+devtools.InspectorController.prototype.windowUnloading = function() {
+ return false;
+};
+
+
+/**
+ * @return {string} Identifiers of the panels that should be hidden.
+ */
+devtools.InspectorController.prototype.hiddenPanels = function() {
+ return '';
+};
+
+
+/**
+ * @return {boolean} True iff debugger is enabled.
+ */
+devtools.InspectorController.prototype.debuggerEnabled = function() {
+ return this.debuggerEnabled_;
+};
+
+
+/**
+ * Enables resource tracking.
+ */
+devtools.InspectorController.prototype.enableResourceTracking = function() {
+ this.resourceTrackingEnabled_ = true;
+ WebInspector.resourceTrackingWasEnabled();
+};
+
+
+/**
+ * Disables resource tracking.
+ */
+devtools.InspectorController.prototype.disableResourceTracking = function() {
+ this.resourceTrackingEnabled_ = false;
+ WebInspector.resourceTrackingWasDisabled();
+};
+
+
+/**
+ * @return {boolean} True iff resource tracking is enabled.
+ */
+devtools.InspectorController.prototype.resourceTrackingEnabled = function() {
+ return this.resourceTrackingEnabled_;
+};
+
+
+/**
+ * Enables debugger.
+ */
+devtools.InspectorController.prototype.enableDebugger = function() {
+ this.debuggerEnabled_ = true;
+};
+
+
+/**
+ * Disables debugger.
+ */
+devtools.InspectorController.prototype.disableDebugger = function() {
+ this.debuggerEnabled_ = false;
+};
+
+
+/**
+ * Adds breakpoint to the given line of the source with given ID.
+ * @param {string} sourceID Source Id to add breakpoint to.
+ * @param {number} line Line number to add breakpoint to.
+ */
+devtools.InspectorController.prototype.addBreakpoint =
+ function(sourceID, line) {
+};
+
+
+/**
+ * Removes breakpoint from the given line of the source with given ID.
+ * @param {string} sourceID Source Id to remove breakpoint from.
+ * @param {number} line Line number to remove breakpoint from.
+ */
+devtools.InspectorController.prototype.removeBreakpoint =
+ function(sourceID, line) {
+};
+
+
+/**
+ * Tells backend to pause in the debugger.
+ */
+devtools.InspectorController.prototype.pauseInDebugger = function() {
+ // Does nothing in stub.
+};
+
+
+/**
+ * @return {boolean} True iff the debugger will pause execution on the
+ * exceptions.
+ */
+devtools.InspectorController.prototype.pauseOnExceptions = function() {
+ // Does nothing in stub.
+ return false;
+};
+
+
+/**
+ * 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.InspectorController.prototype.setPauseOnExceptions = function(value) {
+};
+
+
+/**
+ * Tells backend to resume execution.
+ */
+devtools.InspectorController.prototype.resumeDebugger = function() {
+};
+
+
+/**
+ * @return {boolean} True iff profiler is enabled.
+ */
+devtools.InspectorController.prototype.profilerEnabled = function() {
+ return true;
+};
+
+
+/**
+ * Enables profiler.
+ */
+devtools.InspectorController.prototype.enableProfiler = function() {
+ this.profilerEnabled_ = true;
+};
+
+
+/**
+ * Disables profiler.
+ */
+devtools.InspectorController.prototype.disableProfiler = function() {
+ this.profilerEnabled_ = false;
+};
+
+
+/**
+ * Returns given callframe while on a debugger break.
+ * @return {Object} Current call frame.
+ */
+devtools.InspectorController.prototype.currentCallFrame = function() {
+ return undefined;
+};
+
+
+/**
+ * Tells backend to start collecting profiler data.
+ */
+devtools.InspectorController.prototype.startProfiling = function() {
+};
+
+
+/**
+ * Tells backend to stop collecting profiler data.
+ */
+devtools.InspectorController.prototype.stopProfiling = function() {
+};
+
+
+/**
+ * @return {Array.<Object>} Profile snapshots array.
+ */
+devtools.InspectorController.prototype.profiles = function() {
+ return [];
+};
+
+
+/**
+ * @return {Array.<string>} Database table names available offline.
+ */
+devtools.InspectorController.prototype.databaseTableNames =
+ function(database) {
+ return [];
+};
+
+
+/**
+ * Tells backend to step into the function in debugger.
+ */
+devtools.InspectorController.prototype.stepIntoStatementInDebugger =
+ function() {
+};
+
+
+/**
+ * Tells backend to step out of the function in debugger.
+ */
+devtools.InspectorController.prototype.stepOutOfFunctionInDebugger =
+ function() {};
+
+
+/**
+ * Tells backend to step over the statement in debugger.
+ */
+devtools.InspectorController.prototype.stepOverStatementInDebugger =
+ function() {
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector_controller_impl.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector_controller_impl.js
new file mode 100644
index 0000000..d04b16a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/inspector_controller_impl.js
@@ -0,0 +1,203 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview DevTools' implementation of the InspectorController API.
+ */
+goog.require('devtools.InspectorController');
+
+goog.provide('devtools.InspectorControllerImpl');
+
+devtools.InspectorControllerImpl = function() {
+ devtools.InspectorController.call(this);
+ this.frame_element_id_ = 1;
+};
+goog.inherits(devtools.InspectorControllerImpl,
+ devtools.InspectorController);
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorController.prototype.platform = function() {
+ return DevToolsHost.getPlatform();
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorController.prototype.clearMessages = function() {
+ RemoteToolsAgent.ClearConsoleMessages();
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorControllerImpl.prototype.hiddenPanels = function() {
+ return 'databases';
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorController.prototype.search = function(sourceRow, query) {
+ return DevToolsHost.search(sourceRow, query);
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorControllerImpl.prototype.addSourceToFrame =
+ function(mimeType, source, element) {
+ return DevToolsHost.addSourceToFrame(mimeType, source, element);
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorControllerImpl.prototype.addResourceSourceToFrame =
+ function(identifier, element) {
+ var resource = WebInspector.resources[identifier];
+ if (!resource) {
+ return;
+ }
+ DevToolsHost.addResourceSourceToFrame(identifier, resource.mimeType, element);
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorControllerImpl.prototype.hideDOMNodeHighlight = function() {
+ RemoteToolsAgent.HideDOMNodeHighlight();
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorControllerImpl.prototype.highlightDOMNode =
+ function(hoveredNode) {
+ RemoteToolsAgent.HighlightDOMNode(hoveredNode.id_);
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorControllerImpl.prototype.inspectedWindow = function() {
+ return devtools.tools.getDomAgent().getWindow();
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorController.prototype.enableResourceTracking =
+ function(always) {
+ devtools.tools.setResourceTrackingEnabled(true, always);
+}
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorController.prototype.disableResourceTracking =
+ function(always) {
+ devtools.tools.setResourceTrackingEnabled(false, always);
+};
+
+
+/**
+ * @override
+ */
+devtools.InspectorControllerImpl.prototype.debuggerEnabled = function() {
+ return true;
+};
+
+
+devtools.InspectorControllerImpl.prototype.currentCallFrame = function() {
+ return devtools.tools.getDebuggerAgent().getCurrentCallFrame();
+};
+
+
+devtools.InspectorControllerImpl.prototype.addBreakpoint = function(
+ sourceID, line) {
+ devtools.tools.getDebuggerAgent().addBreakpoint(sourceID, line);
+};
+
+
+devtools.InspectorControllerImpl.prototype.removeBreakpoint = function(
+ sourceID, line) {
+ devtools.tools.getDebuggerAgent().removeBreakpoint(sourceID, line);
+};
+
+
+devtools.InspectorController.prototype.pauseInDebugger = function() {
+ devtools.tools.getDebuggerAgent().pauseExecution();
+};
+
+
+devtools.InspectorControllerImpl.prototype.resumeDebugger = function() {
+ devtools.tools.getDebuggerAgent().resumeExecution();
+};
+
+
+devtools.InspectorControllerImpl.prototype.stepIntoStatementInDebugger =
+ function() {
+ devtools.tools.getDebuggerAgent().stepIntoStatement();
+};
+
+
+devtools.InspectorControllerImpl.prototype.stepOutOfFunctionInDebugger =
+ function() {
+ devtools.tools.getDebuggerAgent().stepOutOfFunction();
+};
+
+
+devtools.InspectorControllerImpl.prototype.stepOverStatementInDebugger =
+ function() {
+ devtools.tools.getDebuggerAgent().stepOverStatement();
+};
+
+
+/**
+ * @override
+ */
+devtools.InspectorControllerImpl.prototype.pauseOnExceptions = function() {
+ return devtools.tools.getDebuggerAgent().pauseOnExceptions();
+};
+
+
+/**
+ * @override
+ */
+devtools.InspectorControllerImpl.prototype.setPauseOnExceptions = function(
+ value) {
+ return devtools.tools.getDebuggerAgent().setPauseOnExceptions(value);
+};
+
+
+/**
+ * @override
+ */
+devtools.InspectorControllerImpl.prototype.startProfiling = function() {
+ devtools.tools.getDebuggerAgent().startProfiling();
+};
+
+
+/**
+ * @override
+ */
+devtools.InspectorControllerImpl.prototype.stopProfiling = function() {
+ devtools.tools.getDebuggerAgent().stopProfiling();
+};
+
+
+var InspectorController = new devtools.InspectorControllerImpl();
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/profile.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/profile.js
new file mode 100644
index 0000000..614c635
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/profile.js
@@ -0,0 +1,605 @@
+// Copyright 2009 the V8 project authors. 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.
+
+
+// Initlialize namespaces
+var devtools = devtools || {};
+devtools.profiler = devtools.profiler || {};
+
+
+/**
+ * Creates a profile object for processing profiling-related events
+ * and calculating function execution times.
+ *
+ * @constructor
+ */
+devtools.profiler.Profile = function() {
+ this.codeMap_ = new devtools.profiler.CodeMap();
+ this.topDownTree_ = new devtools.profiler.CallTree();
+ this.bottomUpTree_ = new devtools.profiler.CallTree();
+};
+
+
+/**
+ * Returns whether a function with the specified name must be skipped.
+ * Should be overriden by subclasses.
+ *
+ * @param {string} name Function name.
+ */
+devtools.profiler.Profile.prototype.skipThisFunction = function(name) {
+ return false;
+};
+
+
+/**
+ * Enum for profiler operations that involve looking up existing
+ * code entries.
+ *
+ * @enum {number}
+ */
+devtools.profiler.Profile.Operation = {
+ MOVE: 0,
+ DELETE: 1,
+ TICK: 2
+};
+
+
+/**
+ * Called whenever the specified operation has failed finding a function
+ * containing the specified address. Should be overriden by subclasses.
+ * See the devtools.profiler.Profile.Operation enum for the list of
+ * possible operations.
+ *
+ * @param {number} operation Operation.
+ * @param {number} addr Address of the unknown code.
+ * @param {number} opt_stackPos If an unknown address is encountered
+ * during stack strace processing, specifies a position of the frame
+ * containing the address.
+ */
+devtools.profiler.Profile.prototype.handleUnknownCode = function(
+ operation, addr, opt_stackPos) {
+};
+
+
+/**
+ * Registers static (library) code entry.
+ *
+ * @param {string} name Code entry name.
+ * @param {number} startAddr Starting address.
+ * @param {number} endAddr Ending address.
+ */
+devtools.profiler.Profile.prototype.addStaticCode = function(
+ name, startAddr, endAddr) {
+ var entry = new devtools.profiler.CodeMap.CodeEntry(
+ endAddr - startAddr, name);
+ this.codeMap_.addStaticCode(startAddr, entry);
+ return entry;
+};
+
+
+/**
+ * Registers dynamic (JIT-compiled) code entry.
+ *
+ * @param {string} type Code entry type.
+ * @param {string} name Code entry name.
+ * @param {number} start Starting address.
+ * @param {number} size Code entry size.
+ */
+devtools.profiler.Profile.prototype.addCode = function(
+ type, name, start, size) {
+ var entry = new devtools.profiler.Profile.DynamicCodeEntry(size, type, name);
+ this.codeMap_.addCode(start, entry);
+ return entry;
+};
+
+
+/**
+ * Reports about moving of a dynamic code entry.
+ *
+ * @param {number} from Current code entry address.
+ * @param {number} to New code entry address.
+ */
+devtools.profiler.Profile.prototype.moveCode = function(from, to) {
+ try {
+ this.codeMap_.moveCode(from, to);
+ } catch (e) {
+ this.handleUnknownCode(devtools.profiler.Profile.Operation.MOVE, from);
+ }
+};
+
+
+/**
+ * Reports about deletion of a dynamic code entry.
+ *
+ * @param {number} start Starting address.
+ */
+devtools.profiler.Profile.prototype.deleteCode = function(start) {
+ try {
+ this.codeMap_.deleteCode(start);
+ } catch (e) {
+ this.handleUnknownCode(devtools.profiler.Profile.Operation.DELETE, start);
+ }
+};
+
+
+/**
+ * Records a tick event. Stack must contain a sequence of
+ * addresses starting with the program counter value.
+ *
+ * @param {Array<number>} stack Stack sample.
+ */
+devtools.profiler.Profile.prototype.recordTick = function(stack) {
+ var processedStack = this.resolveAndFilterFuncs_(stack);
+ this.bottomUpTree_.addPath(processedStack);
+ processedStack.reverse();
+ this.topDownTree_.addPath(processedStack);
+};
+
+
+/**
+ * Translates addresses into function names and filters unneeded
+ * functions.
+ *
+ * @param {Array<number>} stack Stack sample.
+ */
+devtools.profiler.Profile.prototype.resolveAndFilterFuncs_ = function(stack) {
+ var result = [];
+ for (var i = 0; i < stack.length; ++i) {
+ var entry = this.codeMap_.findEntry(stack[i]);
+ if (entry) {
+ var name = entry.getName();
+ if (!this.skipThisFunction(name)) {
+ result.push(name);
+ }
+ } else {
+ this.handleUnknownCode(
+ devtools.profiler.Profile.Operation.TICK, stack[i], i);
+ }
+ }
+ return result;
+};
+
+
+/**
+ * Performs a BF traversal of the top down call graph.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ */
+devtools.profiler.Profile.prototype.traverseTopDownTree = function(f) {
+ this.topDownTree_.traverse(f);
+};
+
+
+/**
+ * Performs a BF traversal of the bottom up call graph.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ */
+devtools.profiler.Profile.prototype.traverseBottomUpTree = function(f) {
+ this.bottomUpTree_.traverse(f);
+};
+
+
+/**
+ * Calculates a top down profile for a node with the specified label.
+ * If no name specified, returns the whole top down calls tree.
+ *
+ * @param {string} opt_label Node label.
+ */
+devtools.profiler.Profile.prototype.getTopDownProfile = function(opt_label) {
+ return this.getTreeProfile_(this.topDownTree_, opt_label);
+};
+
+
+/**
+ * Calculates a bottom up profile for a node with the specified label.
+ * If no name specified, returns the whole bottom up calls tree.
+ *
+ * @param {string} opt_label Node label.
+ */
+devtools.profiler.Profile.prototype.getBottomUpProfile = function(opt_label) {
+ return this.getTreeProfile_(this.bottomUpTree_, opt_label);
+};
+
+
+/**
+ * Helper function for calculating a tree profile.
+ *
+ * @param {devtools.profiler.Profile.CallTree} tree Call tree.
+ * @param {string} opt_label Node label.
+ */
+devtools.profiler.Profile.prototype.getTreeProfile_ = function(tree, opt_label) {
+ if (!opt_label) {
+ tree.computeTotalWeights();
+ return tree;
+ } else {
+ var subTree = tree.cloneSubtree(opt_label);
+ subTree.computeTotalWeights();
+ return subTree;
+ }
+};
+
+
+/**
+ * Calculates a flat profile of callees starting from a node with
+ * the specified label. If no name specified, starts from the root.
+ *
+ * @param {string} opt_label Starting node label.
+ */
+devtools.profiler.Profile.prototype.getFlatProfile = function(opt_label) {
+ var counters = new devtools.profiler.CallTree();
+ var rootLabel = opt_label || devtools.profiler.CallTree.ROOT_NODE_LABEL;
+ var precs = {};
+ precs[rootLabel] = 0;
+ var root = counters.findOrAddChild(rootLabel);
+
+ this.topDownTree_.computeTotalWeights();
+ this.topDownTree_.traverseInDepth(
+ function onEnter(node) {
+ if (!(node.label in precs)) {
+ precs[node.label] = 0;
+ }
+ var nodeLabelIsRootLabel = node.label == rootLabel;
+ if (nodeLabelIsRootLabel || precs[rootLabel] > 0) {
+ if (precs[rootLabel] == 0) {
+ root.selfWeight += node.selfWeight;
+ root.totalWeight += node.totalWeight;
+ } else {
+ var rec = root.findOrAddChild(node.label);
+ rec.selfWeight += node.selfWeight;
+ if (nodeLabelIsRootLabel || precs[node.label] == 0) {
+ rec.totalWeight += node.totalWeight;
+ }
+ }
+ precs[node.label]++;
+ }
+ },
+ function onExit(node) {
+ if (node.label == rootLabel || precs[rootLabel] > 0) {
+ precs[node.label]--;
+ }
+ },
+ null);
+
+ if (!opt_label) {
+ // If we have created a flat profile for the whole program, we don't
+ // need an explicit root in it. Thus, replace the counters tree
+ // root with the node corresponding to the whole program.
+ counters.root_ = root;
+ } else {
+ // Propagate weights so percents can be calculated correctly.
+ counters.getRoot().selfWeight = root.selfWeight;
+ counters.getRoot().totalWeight = root.totalWeight;
+ }
+ return counters;
+};
+
+
+/**
+ * Creates a dynamic code entry.
+ *
+ * @param {number} size Code size.
+ * @param {string} type Code type.
+ * @param {string} name Function name.
+ * @constructor
+ */
+devtools.profiler.Profile.DynamicCodeEntry = function(size, type, name) {
+ devtools.profiler.CodeMap.CodeEntry.call(this, size, name);
+ this.type = type;
+};
+
+
+/**
+ * Returns node name.
+ */
+devtools.profiler.Profile.DynamicCodeEntry.prototype.getName = function() {
+ var name = this.name;
+ if (name.length == 0) {
+ name = '<anonymous>';
+ } else if (name.charAt(0) == ' ') {
+ // An anonymous function with location: " aaa.js:10".
+ name = '<anonymous>' + name;
+ }
+ return this.type + ': ' + name;
+};
+
+
+/**
+ * Constructs a call graph.
+ *
+ * @constructor
+ */
+devtools.profiler.CallTree = function() {
+ this.root_ = new devtools.profiler.CallTree.Node(
+ devtools.profiler.CallTree.ROOT_NODE_LABEL);
+};
+
+
+/**
+ * The label of the root node.
+ */
+devtools.profiler.CallTree.ROOT_NODE_LABEL = '';
+
+
+/**
+ * @private
+ */
+devtools.profiler.CallTree.prototype.totalsComputed_ = false;
+
+
+/**
+ * Returns the tree root.
+ */
+devtools.profiler.CallTree.prototype.getRoot = function() {
+ return this.root_;
+};
+
+
+/**
+ * Adds the specified call path, constructing nodes as necessary.
+ *
+ * @param {Array<string>} path Call path.
+ */
+devtools.profiler.CallTree.prototype.addPath = function(path) {
+ if (path.length == 0) {
+ return;
+ }
+ var curr = this.root_;
+ for (var i = 0; i < path.length; ++i) {
+ curr = curr.findOrAddChild(path[i]);
+ }
+ curr.selfWeight++;
+ this.totalsComputed_ = false;
+};
+
+
+/**
+ * Finds an immediate child of the specified parent with the specified
+ * label, creates a child node if necessary. If a parent node isn't
+ * specified, uses tree root.
+ *
+ * @param {string} label Child node label.
+ */
+devtools.profiler.CallTree.prototype.findOrAddChild = function(label) {
+ return this.root_.findOrAddChild(label);
+};
+
+
+/**
+ * Creates a subtree by cloning and merging all subtrees rooted at nodes
+ * with a given label. E.g. cloning the following call tree on label 'A'
+ * will give the following result:
+ *
+ * <A>--<B> <B>
+ * / /
+ * <root> == clone on 'A' ==> <root>--<A>
+ * \ \
+ * <C>--<A>--<D> <D>
+ *
+ * And <A>'s selfWeight will be the sum of selfWeights of <A>'s from the
+ * source call tree.
+ *
+ * @param {string} label The label of the new root node.
+ */
+devtools.profiler.CallTree.prototype.cloneSubtree = function(label) {
+ var subTree = new devtools.profiler.CallTree();
+ this.traverse(function(node, parent) {
+ if (!parent && node.label != label) {
+ return null;
+ }
+ var child = (parent ? parent : subTree).findOrAddChild(node.label);
+ child.selfWeight += node.selfWeight;
+ return child;
+ });
+ return subTree;
+};
+
+
+/**
+ * Computes total weights in the call graph.
+ */
+devtools.profiler.CallTree.prototype.computeTotalWeights = function() {
+ if (this.totalsComputed_) {
+ return;
+ }
+ this.root_.computeTotalWeight();
+ this.totalsComputed_ = true;
+};
+
+
+/**
+ * Traverses the call graph in preorder. This function can be used for
+ * building optionally modified tree clones. This is the boilerplate code
+ * for this scenario:
+ *
+ * callTree.traverse(function(node, parentClone) {
+ * var nodeClone = cloneNode(node);
+ * if (parentClone)
+ * parentClone.addChild(nodeClone);
+ * return nodeClone;
+ * });
+ *
+ * @param {function(devtools.profiler.CallTree.Node, *)} f Visitor function.
+ * The second parameter is the result of calling 'f' on the parent node.
+ */
+devtools.profiler.CallTree.prototype.traverse = function(f) {
+ var pairsToProcess = new ConsArray();
+ pairsToProcess.concat([{node: this.root_, param: null}]);
+ while (!pairsToProcess.atEnd()) {
+ var pair = pairsToProcess.next();
+ var node = pair.node;
+ var newParam = f(node, pair.param);
+ var morePairsToProcess = [];
+ node.forEachChild(function (child) {
+ morePairsToProcess.push({node: child, param: newParam}); });
+ pairsToProcess.concat(morePairsToProcess);
+ }
+};
+
+
+/**
+ * Performs an indepth call graph traversal.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} enter A function called
+ * prior to visiting node's children.
+ * @param {function(devtools.profiler.CallTree.Node)} exit A function called
+ * after visiting node's children.
+ */
+devtools.profiler.CallTree.prototype.traverseInDepth = function(enter, exit) {
+ function traverse(node) {
+ enter(node);
+ node.forEachChild(traverse);
+ exit(node);
+ }
+ traverse(this.root_);
+};
+
+
+/**
+ * Constructs a call graph node.
+ *
+ * @param {string} label Node label.
+ * @param {devtools.profiler.CallTree.Node} opt_parent Node parent.
+ */
+devtools.profiler.CallTree.Node = function(label, opt_parent) {
+ this.label = label;
+ this.parent = opt_parent;
+ this.children = {};
+};
+
+
+/**
+ * Node self weight (how many times this node was the last node in
+ * a call path).
+ * @type {number}
+ */
+devtools.profiler.CallTree.Node.prototype.selfWeight = 0;
+
+
+/**
+ * Node total weight (includes weights of all children).
+ * @type {number}
+ */
+devtools.profiler.CallTree.Node.prototype.totalWeight = 0;
+
+
+/**
+ * Adds a child node.
+ *
+ * @param {string} label Child node label.
+ */
+devtools.profiler.CallTree.Node.prototype.addChild = function(label) {
+ var child = new devtools.profiler.CallTree.Node(label, this);
+ this.children[label] = child;
+ return child;
+};
+
+
+/**
+ * Computes node's total weight.
+ */
+devtools.profiler.CallTree.Node.prototype.computeTotalWeight =
+ function() {
+ var totalWeight = this.selfWeight;
+ this.forEachChild(function(child) {
+ totalWeight += child.computeTotalWeight(); });
+ return this.totalWeight = totalWeight;
+};
+
+
+/**
+ * Returns all node's children as an array.
+ */
+devtools.profiler.CallTree.Node.prototype.exportChildren = function() {
+ var result = [];
+ this.forEachChild(function (node) { result.push(node); });
+ return result;
+};
+
+
+/**
+ * Finds an immediate child with the specified label.
+ *
+ * @param {string} label Child node label.
+ */
+devtools.profiler.CallTree.Node.prototype.findChild = function(label) {
+ return this.children[label] || null;
+};
+
+
+/**
+ * Finds an immediate child with the specified label, creates a child
+ * node if necessary.
+ *
+ * @param {string} label Child node label.
+ */
+devtools.profiler.CallTree.Node.prototype.findOrAddChild = function(label) {
+ return this.findChild(label) || this.addChild(label);
+};
+
+
+/**
+ * Calls the specified function for every child.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ */
+devtools.profiler.CallTree.Node.prototype.forEachChild = function(f) {
+ for (var c in this.children) {
+ f(this.children[c]);
+ }
+};
+
+
+/**
+ * Walks up from the current node up to the call tree root.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ */
+devtools.profiler.CallTree.Node.prototype.walkUpToRoot = function(f) {
+ for (var curr = this; curr != null; curr = curr.parent) {
+ f(curr);
+ }
+};
+
+
+/**
+ * Tries to find a node with the specified path.
+ *
+ * @param {Array<string>} labels The path.
+ * @param {function(devtools.profiler.CallTree.Node)} opt_f Visitor function.
+ */
+devtools.profiler.CallTree.Node.prototype.descendToChild = function(
+ labels, opt_f) {
+ for (var pos = 0, curr = this; pos < labels.length && curr != null; pos++) {
+ var child = curr.findChild(labels[pos]);
+ if (opt_f) {
+ opt_f(child, pos);
+ }
+ curr = child;
+ }
+ return curr;
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/profile_view.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/profile_view.js
new file mode 100644
index 0000000..bdea631
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/profile_view.js
@@ -0,0 +1,224 @@
+// Copyright 2009 the V8 project authors. 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.
+
+
+// Initlialize namespaces
+var devtools = devtools || {};
+devtools.profiler = devtools.profiler || {};
+
+
+/**
+ * Creates a Profile View builder object.
+ *
+ * @param {number} samplingRate Number of ms between profiler ticks.
+ * @constructor
+ */
+devtools.profiler.ViewBuilder = function(samplingRate) {
+ this.samplingRate = samplingRate;
+};
+
+
+/**
+ * Builds a profile view for the specified call tree.
+ *
+ * @param {devtools.profiler.CallTree} callTree A call tree.
+ * @param {boolean} opt_bottomUpViewWeights Whether remapping
+ * of self weights for a bottom up view is needed.
+ */
+devtools.profiler.ViewBuilder.prototype.buildView = function(
+ callTree, opt_bottomUpViewWeights) {
+ var head;
+ var samplingRate = this.samplingRate;
+ var createViewNode = this.createViewNode;
+ callTree.traverse(function(node, viewParent) {
+ var totalWeight = node.totalWeight * samplingRate;
+ var selfWeight = node.selfWeight * samplingRate;
+ if (opt_bottomUpViewWeights === true) {
+ if (viewParent === head) {
+ selfWeight = totalWeight;
+ } else {
+ selfWeight = 0;
+ }
+ }
+ var viewNode = createViewNode(node.label, totalWeight, selfWeight, head);
+ if (viewParent) {
+ viewParent.addChild(viewNode);
+ } else {
+ head = viewNode;
+ }
+ return viewNode;
+ });
+ var view = this.createView(head);
+ return view;
+};
+
+
+/**
+ * Factory method for a profile view.
+ *
+ * @param {devtools.profiler.ProfileView.Node} head View head node.
+ * @return {devtools.profiler.ProfileView} Profile view.
+ */
+devtools.profiler.ViewBuilder.prototype.createView = function(head) {
+ return new devtools.profiler.ProfileView(head);
+};
+
+
+/**
+ * Factory method for a profile view node.
+ *
+ * @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.
+ * @return {devtools.profiler.ProfileView.Node} Profile view node.
+ */
+devtools.profiler.ViewBuilder.prototype.createViewNode = function(
+ funcName, totalTime, selfTime, head) {
+ return new devtools.profiler.ProfileView.Node(
+ funcName, totalTime, selfTime, head);
+};
+
+
+/**
+ * Creates a Profile View object. It allows to perform sorting
+ * and filtering actions on the profile.
+ *
+ * @param {devtools.profiler.ProfileView.Node} head Head (root) node.
+ * @constructor
+ */
+devtools.profiler.ProfileView = function(head) {
+ this.head = head;
+};
+
+
+/**
+ * Sorts the profile view using the specified sort function.
+ *
+ * @param {function(devtools.profiler.ProfileView.Node,
+ * devtools.profiler.ProfileView.Node):number} sortFunc A sorting
+ * functions. Must comply with Array.sort sorting function requirements.
+ */
+devtools.profiler.ProfileView.prototype.sort = function(sortFunc) {
+ this.traverse(function (node) {
+ node.sortChildren(sortFunc);
+ });
+};
+
+
+/**
+ * Traverses profile view nodes in preorder.
+ *
+ * @param {function(devtools.profiler.ProfileView.Node)} f Visitor function.
+ */
+devtools.profiler.ProfileView.prototype.traverse = function(f) {
+ var nodesToTraverse = new ConsArray();
+ nodesToTraverse.concat([this.head]);
+ while (!nodesToTraverse.atEnd()) {
+ var node = nodesToTraverse.next();
+ f(node);
+ nodesToTraverse.concat(node.children);
+ }
+};
+
+
+/**
+ * Constructs a Profile View node object. Each node object corresponds to
+ * a function call.
+ *
+ * @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.ProfileView.Node = function(
+ internalFuncName, totalTime, selfTime, head) {
+ this.internalFuncName = internalFuncName;
+ this.totalTime = totalTime;
+ this.selfTime = selfTime;
+ this.head = head;
+ this.parent = null;
+ this.children = [];
+};
+
+
+/**
+ * Returns a share of the function's total time in application's total time.
+ */
+devtools.profiler.ProfileView.Node.prototype.__defineGetter__(
+ 'totalPercent',
+ function() { return this.totalTime /
+ (this.head ? this.head.totalTime : this.totalTime) * 100.0; });
+
+
+/**
+ * Returns a share of the function's self time in application's total time.
+ */
+devtools.profiler.ProfileView.Node.prototype.__defineGetter__(
+ 'selfPercent',
+ function() { return this.selfTime /
+ (this.head ? this.head.totalTime : this.totalTime) * 100.0; });
+
+
+/**
+ * Returns a share of the function's total time in its parent's total time.
+ */
+devtools.profiler.ProfileView.Node.prototype.__defineGetter__(
+ 'parentTotalPercent',
+ function() { return this.totalTime /
+ (this.parent ? this.parent.totalTime : this.totalTime) * 100.0; });
+
+
+/**
+ * Adds a child to the node.
+ *
+ * @param {devtools.profiler.ProfileView.Node} node Child node.
+ */
+devtools.profiler.ProfileView.Node.prototype.addChild = function(node) {
+ node.parent = this;
+ this.children.push(node);
+};
+
+
+/**
+ * Sorts all the node's children recursively.
+ *
+ * @param {function(devtools.profiler.ProfileView.Node,
+ * devtools.profiler.ProfileView.Node):number} sortFunc A sorting
+ * functions. Must comply with Array.sort sorting function requirements.
+ */
+devtools.profiler.ProfileView.Node.prototype.sortChildren = function(
+ sortFunc) {
+ this.children.sort(sortFunc);
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/profiler_processor.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/profiler_processor.js
new file mode 100644
index 0000000..3c4778e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/profiler_processor.js
@@ -0,0 +1,395 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @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.
+ */
+goog.provide('devtools.profiler.Processor');
+
+
+/**
+ * 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);
+};
+goog.inherits(devtools.profiler.WebKitViewBuilder,
+ devtools.profiler.ViewBuilder);
+
+
+/**
+ * @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;
+};
+goog.inherits(devtools.profiler.WebKitViewNode,
+ devtools.profiler.ProfileView.Node);
+
+
+/**
+ * RegEx for stripping V8's prefixes of compiled functions.
+ */
+devtools.profiler.WebKitViewNode.FUNC_NAME_STRIP_RE =
+ /^(?:LazyCompile|Function): (.*)$/;
+
+
+/**
+ * RegEx for extracting script source URL and line number.
+ */
+devtools.profiler.WebKitViewNode.FUNC_NAME_PARSE_RE = /^([^ ]+) (.*):(\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];
+ 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);
+};
+goog.inherits(devtools.profiler.JsProfile, devtools.profiler.Profile);
+
+
+/**
+ * RegExp that leaves only JS functions.
+ * @type {RegExp}
+ */
+devtools.profiler.JsProfile.JS_FUNC_RE = /^(LazyCompile|Function|Script):/;
+
+/**
+ * RegExp that filters out native code (ending with "native src.js:xxx").
+ * @type {RegExp}
+ */
+devtools.profiler.JsProfile.JS_NATIVE_FUNC_RE = /\ native\ \w+\.js:\d+$/;
+
+/**
+ * RegExp that filters out native scripts.
+ * @type {RegExp}
+ */
+devtools.profiler.JsProfile.JS_NATIVE_SCRIPT_RE = /^Script:\ native/;
+
+
+/**
+ * @override
+ */
+devtools.profiler.JsProfile.prototype.skipThisFunction = function(name) {
+ return !devtools.profiler.JsProfile.JS_FUNC_RE.test(name) ||
+ // To profile V8's natives comment out two lines below and '||' above.
+ devtools.profiler.JsProfile.JS_NATIVE_FUNC_RE.test(name) ||
+ devtools.profiler.JsProfile.JS_NATIVE_SCRIPT_RE.test(name);
+};
+
+
+/**
+ * Profiler processor. Consumes profiler log and builds profile views.
+ *
+ * @param {function(devtools.profiler.ProfileView)} newProfileCallback Callback
+ * that receives a new processed profile.
+ * @constructor
+ */
+devtools.profiler.Processor = function() {
+ /**
+ * Callback that is called when a new profile is encountered in the log.
+ * @type {function()}
+ */
+ this.startedProfileProcessing_ = 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;
+};
+
+
+/**
+ * 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, finished) {
+ this.startedProfileProcessing_ = started;
+ 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;
+
+
+/**
+ * A dispatch table for V8 profiler event log records.
+ * @private
+ */
+devtools.profiler.Processor.RecordsDispatch_ = {
+ 'code-creation': { parsers: [null, parseInt, parseInt, null],
+ processor: 'processCodeCreation_', needsProfile: true },
+ 'code-move': { parsers: [parseInt, parseInt],
+ processor: 'processCodeMove_', needsProfile: true },
+ 'code-delete': { parsers: [parseInt],
+ processor: 'processCodeDelete_', needsProfile: true },
+ 'tick': { parsers: [parseInt, parseInt, parseInt, 'var-args'],
+ processor: 'processTick_', needsProfile: true },
+ 'profiler': { parsers: [null, 'var-args'], processor: 'processProfiler_',
+ needsProfile: false },
+ // Not used in DevTools Profiler.
+ 'shared-library': null,
+ // Obsolete row types.
+ 'code-allocate': null,
+ 'begin-code-region': null,
+ 'end-code-region': null
+};
+
+
+/**
+ * Sets new profile callback.
+ * @param {function(devtools.profiler.ProfileView)} callback Callback function.
+ */
+devtools.profiler.Processor.prototype.setNewProfileCallback = function(
+ callback) {
+ this.newProfileCallback_ = callback;
+};
+
+
+/**
+ * Processes a portion of V8 profiler event log.
+ *
+ * @param {string} chunk A portion of log.
+ */
+devtools.profiler.Processor.prototype.processLogChunk = function(chunk) {
+ this.processLog_(chunk.split('\n'));
+};
+
+
+/**
+ * Processes a log lines.
+ *
+ * @param {Array<string>} lines Log lines.
+ * @private
+ */
+devtools.profiler.Processor.prototype.processLog_ = function(lines) {
+ var csvParser = new devtools.profiler.CsvParser();
+ try {
+ for (var i = 0, n = lines.length; i < n; ++i) {
+ var line = lines[i];
+ if (!line) {
+ continue;
+ }
+ var fields = csvParser.parseLine(line);
+ this.dispatchLogRow_(fields);
+ }
+ } catch (e) {
+ debugPrint('line ' + (i + 1) + ': ' + (e.message || e));
+ throw e;
+ }
+};
+
+
+/**
+ * Does a dispatch of a log record.
+ *
+ * @param {Array<string>} fields Log record.
+ * @private
+ */
+devtools.profiler.Processor.prototype.dispatchLogRow_ = function(fields) {
+ // Obtain the dispatch.
+ var command = fields[0];
+ if (!(command in devtools.profiler.Processor.RecordsDispatch_)) {
+ throw new Error('unknown command: ' + command);
+ }
+ var dispatch = devtools.profiler.Processor.RecordsDispatch_[command];
+
+ if (dispatch === null ||
+ (dispatch.needsProfile && this.currentProfile_ == null)) {
+ return;
+ }
+
+ // Parse fields.
+ var parsedFields = [];
+ for (var i = 0; i < dispatch.parsers.length; ++i) {
+ var parser = dispatch.parsers[i];
+ if (parser === null) {
+ parsedFields.push(fields[1 + i]);
+ } else if (typeof parser == 'function') {
+ parsedFields.push(parser(fields[1 + i]));
+ } else {
+ // var-args
+ parsedFields.push(fields.slice(1 + i));
+ break;
+ }
+ }
+
+ // Run the processor.
+ this[dispatch.processor].apply(this, parsedFields);
+};
+
+
+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_();
+ }
+ }
+ break;
+ case 'pause':
+ if (this.currentProfile_ != 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;
+ // This event is valid but isn't used.
+ case 'end': break;
+ default:
+ throw new Error('unknown profiler state: ' + state);
+ }
+};
+
+
+devtools.profiler.Processor.prototype.processCodeCreation_ = function(
+ type, start, size, name) {
+ this.currentProfile_.addCode(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.processTick_ = function(
+ pc, sp, vmState, stack) {
+ var fullStack = [pc];
+ for (var i = 0, n = stack.length; i < n; ++i) {
+ var frame = stack[i];
+ // Leave only numbers starting with 0x. Filter possible 'overflow' string.
+ if (frame.charAt(0) == '0') {
+ fullStack.push(parseInt(frame, 16));
+ }
+ }
+ // see the comment for devtools.profiler.Processor.PROGRAM_ENTRY
+ fullStack.push(devtools.profiler.Processor.PROGRAM_ENTRY);
+ this.currentProfile_.recordTick(fullStack);
+};
+
+
+/**
+ * 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/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/splaytree.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/splaytree.js
new file mode 100644
index 0000000..7b3af8b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/splaytree.js
@@ -0,0 +1,322 @@
+// Copyright 2009 the V8 project authors. 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.
+
+
+// A namespace stub. It will become more clear how to declare it properly
+// during integration of this script into Dev Tools.
+var goog = goog || {};
+goog.structs = goog.structs || {};
+
+
+/**
+ * Constructs a Splay tree. A splay tree is a self-balancing binary
+ * search tree with the additional property that recently accessed
+ * elements are quick to access again. It performs basic operations
+ * such as insertion, look-up and removal in O(log(n)) amortized time.
+ *
+ * @constructor
+ */
+goog.structs.SplayTree = function() {
+};
+
+
+/**
+ * Pointer to the root node of the tree.
+ *
+ * @type {goog.structs.SplayTree.Node}
+ * @private
+ */
+goog.structs.SplayTree.prototype.root_ = null;
+
+
+/**
+ * @return {boolean} Whether the tree is empty.
+ */
+goog.structs.SplayTree.prototype.isEmpty = function() {
+ return !this.root_;
+};
+
+
+
+/**
+ * Inserts a node into the tree with the specified key and value if
+ * the tree does not already contain a node with the specified key. If
+ * the value is inserted, it becomes the root of the tree.
+ *
+ * @param {number} key Key to insert into the tree.
+ * @param {*} value Value to insert into the tree.
+ */
+goog.structs.SplayTree.prototype.insert = function(key, value) {
+ if (this.isEmpty()) {
+ this.root_ = new goog.structs.SplayTree.Node(key, value);
+ return;
+ }
+ // Splay on the key to move the last node on the search path for
+ // the key to the root of the tree.
+ this.splay_(key);
+ if (this.root_.key == key) {
+ return;
+ }
+ var node = new goog.structs.SplayTree.Node(key, value);
+ if (key > this.root_.key) {
+ node.left = this.root_;
+ node.right = this.root_.right;
+ this.root_.right = null;
+ } else {
+ node.right = this.root_;
+ node.left = this.root_.left;
+ this.root_.left = null;
+ }
+ this.root_ = node;
+};
+
+
+/**
+ * Removes a node with the specified key from the tree if the tree
+ * contains a node with this key. The removed node is returned. If the
+ * key is not found, an exception is thrown.
+ *
+ * @param {number} key Key to find and remove from the tree.
+ * @return {goog.structs.SplayTree.Node} The removed node.
+ */
+goog.structs.SplayTree.prototype.remove = function(key) {
+ if (this.isEmpty()) {
+ throw Error('Key not found: ' + key);
+ }
+ this.splay_(key);
+ if (this.root_.key != key) {
+ throw Error('Key not found: ' + key);
+ }
+ var removed = this.root_;
+ if (!this.root_.left) {
+ this.root_ = this.root_.right;
+ } else {
+ var right = this.root_.right;
+ this.root_ = this.root_.left;
+ // Splay to make sure that the new root has an empty right child.
+ this.splay_(key);
+ // Insert the original right child as the right child of the new
+ // root.
+ this.root_.right = right;
+ }
+ return removed;
+};
+
+
+/**
+ * Returns the node having the specified key or null if the tree doesn't contain
+ * a node with the specified key.
+ *
+ * @param {number} key Key to find in the tree.
+ * @return {goog.structs.SplayTree.Node} Node having the specified key.
+ */
+goog.structs.SplayTree.prototype.find = function(key) {
+ if (this.isEmpty()) {
+ return null;
+ }
+ this.splay_(key);
+ return this.root_.key == key ? this.root_ : null;
+};
+
+
+/**
+ * @return {goog.structs.SplayTree.Node} Node having the minimum key value.
+ */
+goog.structs.SplayTree.prototype.findMin = function() {
+ if (this.isEmpty()) {
+ return null;
+ }
+ var current = this.root_;
+ while (current.left) {
+ current = current.left;
+ }
+ return current;
+};
+
+
+/**
+ * @return {goog.structs.SplayTree.Node} Node having the maximum key value.
+ */
+goog.structs.SplayTree.prototype.findMax = function(opt_startNode) {
+ if (this.isEmpty()) {
+ return null;
+ }
+ var current = opt_startNode || this.root_;
+ while (current.right) {
+ current = current.right;
+ }
+ return current;
+};
+
+
+/**
+ * @return {goog.structs.SplayTree.Node} Node having the maximum key value that
+ * is less or equal to the specified key value.
+ */
+goog.structs.SplayTree.prototype.findGreatestLessThan = function(key) {
+ if (this.isEmpty()) {
+ return null;
+ }
+ // Splay on the key to move the node with the given key or the last
+ // node on the search path to the top of the tree.
+ this.splay_(key);
+ // Now the result is either the root node or the greatest node in
+ // the left subtree.
+ if (this.root_.key <= key) {
+ return this.root_;
+ } else if (this.root_.left) {
+ return this.findMax(this.root_.left);
+ } else {
+ return null;
+ }
+};
+
+
+/**
+ * @return {Array<*>} An array containing all the values of tree's nodes.
+ */
+goog.structs.SplayTree.prototype.exportValues = function() {
+ var result = [];
+ this.traverse_(function(node) { result.push(node.value); });
+ return result;
+};
+
+
+/**
+ * Perform the splay operation for the given key. Moves the node with
+ * the given key to the top of the tree. If no node has the given
+ * key, the last node on the search path is moved to the top of the
+ * tree. This is the simplified top-down splaying algorithm from:
+ * "Self-adjusting Binary Search Trees" by Sleator and Tarjan
+ *
+ * @param {number} key Key to splay the tree on.
+ * @private
+ */
+goog.structs.SplayTree.prototype.splay_ = function(key) {
+ if (this.isEmpty()) {
+ return;
+ }
+ // Create a dummy node. The use of the dummy node is a bit
+ // counter-intuitive: The right child of the dummy node will hold
+ // the L tree of the algorithm. The left child of the dummy node
+ // will hold the R tree of the algorithm. Using a dummy node, left
+ // and right will always be nodes and we avoid special cases.
+ var dummy, left, right;
+ dummy = left = right = new goog.structs.SplayTree.Node(null, null);
+ var current = this.root_;
+ while (true) {
+ if (key < current.key) {
+ if (!current.left) {
+ break;
+ }
+ if (key < current.left.key) {
+ // Rotate right.
+ var tmp = current.left;
+ current.left = tmp.right;
+ tmp.right = current;
+ current = tmp;
+ if (!current.left) {
+ break;
+ }
+ }
+ // Link right.
+ right.left = current;
+ right = current;
+ current = current.left;
+ } else if (key > current.key) {
+ if (!current.right) {
+ break;
+ }
+ if (key > current.right.key) {
+ // Rotate left.
+ var tmp = current.right;
+ current.right = tmp.left;
+ tmp.left = current;
+ current = tmp;
+ if (!current.right) {
+ break;
+ }
+ }
+ // Link left.
+ left.right = current;
+ left = current;
+ current = current.right;
+ } else {
+ break;
+ }
+ }
+ // Assemble.
+ left.right = current.left;
+ right.left = current.right;
+ current.left = dummy.right;
+ current.right = dummy.left;
+ this.root_ = current;
+};
+
+
+/**
+ * Performs a preorder traversal of the tree.
+ *
+ * @param {function(goog.structs.SplayTree.Node)} f Visitor function.
+ * @private
+ */
+goog.structs.SplayTree.prototype.traverse_ = function(f) {
+ var nodesToVisit = [this.root_];
+ while (nodesToVisit.length > 0) {
+ var node = nodesToVisit.shift();
+ if (node == null) {
+ continue;
+ }
+ f(node);
+ nodesToVisit.push(node.left);
+ nodesToVisit.push(node.right);
+ }
+};
+
+
+/**
+ * Constructs a Splay tree node.
+ *
+ * @param {number} key Key.
+ * @param {*} value Value.
+ */
+goog.structs.SplayTree.Node = function(key, value) {
+ this.key = key;
+ this.value = value;
+};
+
+
+/**
+ * @type {goog.structs.SplayTree.Node}
+ */
+goog.structs.SplayTree.Node.prototype.left = null;
+
+
+/**
+ * @type {goog.structs.SplayTree.Node}
+ */
+goog.structs.SplayTree.Node.prototype.right = null;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/tests.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/tests.js
new file mode 100644
index 0000000..2507ed6
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/tests.js
@@ -0,0 +1,210 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/**
+ * @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.
+ */
+
+if (window.domAutomationController) {
+
+
+/**
+ * Test suite for interactive UI tests.
+ * @constructor
+ */
+TestSuite = function() {
+};
+
+
+/**
+ * Reports test failure.
+ * @param {string} message Failure description.
+ */
+TestSuite.prototype.fail = function(message) {
+ throw message;
+};
+
+
+/**
+ * Equals assertion tests that expected == actual.
+ * @param {Object} expected Expected object.
+ * @param {Object} actual Actual object.
+ */
+TestSuite.prototype.assertEquals = function(expected, actual) {
+ if (expected != actual) {
+ this.fail('Expected: "' + expected + '", but was "' + actual + '"');
+ }
+};
+
+
+/**
+ * True assertion tests that value == true.
+ * @param {Object} expected Expected object.
+ * @param {Object} value Actual object.
+ */
+TestSuite.prototype.assertTrue = function(value) {
+ this.assertEquals(true, value);
+};
+
+
+/**
+ * Runs all global functions starting with 'test' as unit tests.
+ */
+TestSuite.prototype.runAllTests = function() {
+ // For debugging purposes.
+ for (var name in this) {
+ if (name.substring(0, 4) == 'test' &&
+ typeof this[name] == 'function') {
+ this.runTest(name);
+ }
+ }
+};
+
+
+/**
+ * Async tests use this one to report that they are completed.
+ */
+TestSuite.prototype.reportOk = function() {
+ window.domAutomationController.send('[OK]');
+};
+
+
+/**
+ * Manual controller for async tests.
+ * @constructor.
+ */
+TestSuite.Controller = function() {
+ this.controlTaken_ = false;
+ this.timerId_ = -1;
+};
+
+
+/**
+ * Takes control over execution.
+ */
+TestSuite.Controller.prototype.takeControl = function() {
+ this.controlTaken_ = true;
+ // Set up guard timer.
+ var self = this;
+ this.timerId_ = setTimeout(function() {
+ self.reportFailure('Timeout exceeded: 20 sec');
+ }, 20000);
+};
+
+
+/**
+ * Async tests use this one to report that they are completed.
+ */
+TestSuite.Controller.prototype.reportOk = function() {
+ if (this.timerId_ != -1) {
+ this.timerId_ = -1;
+ clearTimeout(this.timerId_);
+ }
+ window.domAutomationController.send('[OK]');
+};
+
+
+/**
+ * Async tests use this one to report failures.
+ */
+TestSuite.Controller.prototype.reportFailure = function(error) {
+ if (this.timerId_ != -1) {
+ this.timerId_ = -1;
+ clearTimeout(this.timerId_);
+ }
+ window.domAutomationController.send('[FAILED] ' + error);
+};
+
+
+/**
+ * Runs all global functions starting with 'test' as unit tests.
+ */
+TestSuite.prototype.runTest = function(testName) {
+ var controller = new TestSuite.Controller();
+ try {
+ this[testName](controller);
+ if (!controller.controlTaken_) {
+ controller.reportOk();
+ }
+ } catch (e) {
+ controller.reportFailure(e);
+ }
+};
+
+
+// UI Tests
+
+
+/**
+ * Tests that the real injected host is present in the context.
+ */
+TestSuite.prototype.testHostIsPresent = function() {
+ var domAgent = devtools.tools.getDomAgent();
+ var doc = domAgent.getDocument();
+ this.assertTrue(typeof DevToolsHost == 'object' && !DevToolsHost.isStub);
+ this.assertTrue(!!doc.documentElement);
+};
+
+
+/**
+ * Tests elements tree has an 'HTML' root.
+ */
+TestSuite.prototype.testElementsTreeRoot = function() {
+ var domAgent = devtools.tools.getDomAgent();
+ var doc = domAgent.getDocument();
+ 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(controller) {
+ WebInspector.panels.elements.hide();
+ WebInspector.panels.resources.show();
+
+ var test = this;
+ var oldAddResource = WebInspector.addResource;
+ WebInspector.addResource = function(identifier, payload) {
+ WebInspector.addResource = oldAddResource;
+ oldAddResource.call(this, identifier, payload);
+ test.assertEquals('simple_page.html', payload.lastPathComponent);
+ WebInspector.panels.resources.refresh();
+ WebInspector.resources[identifier]._resourcesTreeElement.select();
+
+ controller.reportOk();
+ };
+
+ // 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.
+ controller.takeControl();
+};
+
+
+var uiTests = new TestSuite();
+
+
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/treeoutline.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/treeoutline.js
new file mode 100644
index 0000000..579e7fb
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/treeoutline.js
@@ -0,0 +1,846 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+function TreeOutline(listNode)
+{
+ this.children = [];
+ this.selectedTreeElement = null;
+ this._childrenListNode = listNode;
+ this._childrenListNode.removeChildren();
+ this._knownTreeElements = [];
+ this._treeElementsExpandedState = [];
+ this.expandTreeElementsWhenArrowing = false;
+ this.root = true;
+ this.hasChildren = false;
+ this.expanded = true;
+ this.selected = false;
+ this.treeOutline = this;
+}
+
+TreeOutline._knownTreeElementNextIdentifier = 1;
+
+TreeOutline._appendChild = function(child)
+{
+ if (!child)
+ throw("child can't be undefined or null");
+
+ var lastChild = this.children[this.children.length - 1];
+ if (lastChild) {
+ lastChild.nextSibling = child;
+ child.previousSibling = lastChild;
+ } else {
+ child.previousSibling = null;
+ child.nextSibling = null;
+ }
+
+ this.children.push(child);
+ this.hasChildren = true;
+ child.parent = this;
+ child.treeOutline = this.treeOutline;
+ child.treeOutline._rememberTreeElement(child);
+
+ var current = child.children[0];
+ while (current) {
+ current.treeOutline = this.treeOutline;
+ current.treeOutline._rememberTreeElement(current);
+ current = current.traverseNextTreeElement(false, child, true);
+ }
+
+ if (child.hasChildren && child.treeOutline._treeElementsExpandedState[child.identifier] !== undefined)
+ child.expanded = child.treeOutline._treeElementsExpandedState[child.identifier];
+
+ if (!this._childrenListNode) {
+ this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
+ this._childrenListNode.parentTreeElement = this;
+ this._childrenListNode.addStyleClass("children");
+ if (this.hidden)
+ this._childrenListNode.addStyleClass("hidden");
+ }
+
+ child._attach();
+}
+
+TreeOutline._insertChild = function(child, index)
+{
+ if (!child)
+ throw("child can't be undefined or null");
+
+ var previousChild = (index > 0 ? this.children[index - 1] : null);
+ if (previousChild) {
+ previousChild.nextSibling = child;
+ child.previousSibling = previousChild;
+ } else {
+ child.previousSibling = null;
+ }
+
+ var nextChild = this.children[index];
+ if (nextChild) {
+ nextChild.previousSibling = child;
+ child.nextSibling = nextChild;
+ } else {
+ child.nextSibling = null;
+ }
+
+ this.children.splice(index, 0, child);
+ this.hasChildren = true;
+ child.parent = this;
+ child.treeOutline = this.treeOutline;
+ child.treeOutline._rememberTreeElement(child);
+
+ var current = child.children[0];
+ while (current) {
+ current.treeOutline = this.treeOutline;
+ current.treeOutline._rememberTreeElement(current);
+ current = current.traverseNextTreeElement(false, child, true);
+ }
+
+ if (child.hasChildren && child.treeOutline._treeElementsExpandedState[child.identifier] !== undefined)
+ child.expanded = child.treeOutline._treeElementsExpandedState[child.identifier];
+
+ if (!this._childrenListNode) {
+ this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
+ this._childrenListNode.parentTreeElement = this;
+ this._childrenListNode.addStyleClass("children");
+ if (this.hidden)
+ this._childrenListNode.addStyleClass("hidden");
+ }
+
+ child._attach();
+}
+
+TreeOutline._removeChildAtIndex = function(childIndex)
+{
+ if (childIndex < 0 || childIndex >= this.children.length)
+ throw("childIndex out of range");
+
+ var child = this.children[childIndex];
+ this.children.splice(childIndex, 1);
+
+ child.deselect();
+
+ if (child.previousSibling)
+ child.previousSibling.nextSibling = child.nextSibling;
+ if (child.nextSibling)
+ child.nextSibling.previousSibling = child.previousSibling;
+
+ if (child.treeOutline) {
+ child.treeOutline._forgetTreeElement(child);
+ child.treeOutline._forgetChildrenRecursive(child);
+ }
+
+ child._detach();
+ child.treeOutline = null;
+ child.parent = null;
+ child.nextSibling = null;
+ child.previousSibling = null;
+}
+
+TreeOutline._removeChild = function(child)
+{
+ if (!child)
+ throw("child can't be undefined or null");
+
+ var childIndex = this.children.indexOf(child);
+ if (childIndex === -1)
+ throw("child not found in this node's children");
+
+ TreeOutline._removeChildAtIndex.call(this, childIndex);
+}
+
+TreeOutline._removeChildren = function()
+{
+ for (var i = 0; i < this.children.length; ++i) {
+ var child = this.children[i];
+ child.deselect();
+
+ if (child.treeOutline) {
+ child.treeOutline._forgetTreeElement(child);
+ child.treeOutline._forgetChildrenRecursive(child);
+ }
+
+ child._detach();
+ child.treeOutline = null;
+ child.parent = null;
+ child.nextSibling = null;
+ child.previousSibling = null;
+ }
+
+ this.children = [];
+}
+
+TreeOutline._removeChildrenRecursive = function()
+{
+ var childrenToRemove = this.children;
+
+ var child = this.children[0];
+ while (child) {
+ if (child.children.length)
+ childrenToRemove = childrenToRemove.concat(child.children);
+ child = child.traverseNextTreeElement(false, this, true);
+ }
+
+ for (var i = 0; i < childrenToRemove.length; ++i) {
+ var child = childrenToRemove[i];
+ child.deselect();
+ if (child.treeOutline)
+ child.treeOutline._forgetTreeElement(child);
+ child._detach();
+ child.children = [];
+ child.treeOutline = null;
+ child.parent = null;
+ child.nextSibling = null;
+ child.previousSibling = null;
+ }
+
+ this.children = [];
+}
+
+TreeOutline.prototype._rememberTreeElement = function(element)
+{
+ if (!this._knownTreeElements[element.identifier])
+ this._knownTreeElements[element.identifier] = [];
+
+ // check if the element is already known
+ var elements = this._knownTreeElements[element.identifier];
+ if (elements.indexOf(element) !== -1)
+ return;
+
+ // add the element
+ elements.push(element);
+}
+
+TreeOutline.prototype._forgetTreeElement = function(element)
+{
+ if (this._knownTreeElements[element.identifier])
+ this._knownTreeElements[element.identifier].remove(element, true);
+}
+
+TreeOutline.prototype._forgetChildrenRecursive = function(parentElement)
+{
+ var child = parentElement.children[0];
+ while (child) {
+ this._forgetTreeElement(child);
+ child = child.traverseNextTreeElement(false, this, true);
+ }
+}
+
+TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent, equal)
+{
+ if (!representedObject)
+ return null;
+
+ if (!equal)
+ equal = function(a, b) { return a === b };
+
+ if ("__treeElementIdentifier" in representedObject) {
+ // If this representedObject has a tree element identifier, and it is a known TreeElement
+ // in our tree we can just return that tree element.
+ var elements = this._knownTreeElements[representedObject.__treeElementIdentifier];
+ if (elements) {
+ for (var i = 0; i < elements.length; ++i)
+ if (equal(elements[i].representedObject, representedObject))
+ return elements[i];
+ }
+ }
+
+ if (!isAncestor || !(isAncestor instanceof Function) || !getParent || !(getParent instanceof Function))
+ return null;
+
+ // The representedObject isn't know, so we start at the top of the tree and work down to find the first
+ // tree element that represents representedObject or one of its ancestors.
+ var item;
+ var found = false;
+ for (var i = 0; i < this.children.length; ++i) {
+ item = this.children[i];
+ if (equal(item.representedObject, representedObject) || isAncestor(item.representedObject, representedObject)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ return null;
+
+ // Make sure the item that we found is connected to the root of the tree.
+ // Build up a list of representedObject's ancestors that aren't already in our tree.
+ var ancestors = [];
+ var currentObject = representedObject;
+ while (currentObject) {
+ ancestors.unshift(currentObject);
+ if (equal(currentObject, item.representedObject))
+ break;
+ currentObject = getParent(currentObject);
+ }
+
+ // For each of those ancestors we populate them to fill in the tree.
+ for (var i = 0; i < ancestors.length; ++i) {
+ // Make sure we don't call findTreeElement with the same representedObject
+ // again, to prevent infinite recursion.
+ if (equal(ancestors[i], representedObject))
+ continue;
+ // FIXME: we could do something faster than findTreeElement since we will know the next
+ // ancestor exists in the tree.
+ item = this.findTreeElement(ancestors[i], isAncestor, getParent, equal);
+ if (item && item.onpopulate)
+ item.onpopulate(item);
+ }
+
+ // Now that all the ancestors are populated, try to find the representedObject again. This time
+ // without the isAncestor and getParent functions to prevent an infinite recursion if it isn't found.
+ return this.findTreeElement(representedObject, null, null, equal);
+}
+
+TreeOutline.prototype.treeElementFromPoint = function(x, y)
+{
+ var node = this._childrenListNode.ownerDocument.elementFromPoint(x, y);
+ var listNode = node.enclosingNodeOrSelfWithNodeNameInArray(["ol", "li"]);
+ if (listNode)
+ return listNode.parentTreeElement || listNode.treeElement;
+ return null;
+}
+
+TreeOutline.prototype.handleKeyEvent = function(event)
+{
+ if (!this.selectedTreeElement || event.shiftKey || event.metaKey || event.ctrlKey)
+ return false;
+
+ var handled = false;
+ var nextSelectedElement;
+ if (event.keyIdentifier === "Up" && !event.altKey) {
+ nextSelectedElement = this.selectedTreeElement.traversePreviousTreeElement(true);
+ while (nextSelectedElement && !nextSelectedElement.selectable)
+ nextSelectedElement = nextSelectedElement.traversePreviousTreeElement(!this.expandTreeElementsWhenArrowing);
+ handled = nextSelectedElement ? true : false;
+ } else if (event.keyIdentifier === "Down" && !event.altKey) {
+ nextSelectedElement = this.selectedTreeElement.traverseNextTreeElement(true);
+ while (nextSelectedElement && !nextSelectedElement.selectable)
+ nextSelectedElement = nextSelectedElement.traverseNextTreeElement(!this.expandTreeElementsWhenArrowing);
+ handled = nextSelectedElement ? true : false;
+ } else if (event.keyIdentifier === "Left") {
+ if (this.selectedTreeElement.expanded) {
+ if (event.altKey)
+ this.selectedTreeElement.collapseRecursively();
+ else
+ this.selectedTreeElement.collapse();
+ handled = true;
+ } else if (this.selectedTreeElement.parent && !this.selectedTreeElement.parent.root) {
+ handled = true;
+ if (this.selectedTreeElement.parent.selectable) {
+ nextSelectedElement = this.selectedTreeElement.parent;
+ handled = nextSelectedElement ? true : false;
+ } else if (this.selectedTreeElement.parent)
+ this.selectedTreeElement.parent.collapse();
+ }
+ } else if (event.keyIdentifier === "Right") {
+ if (!this.selectedTreeElement.revealed()) {
+ this.selectedTreeElement.reveal();
+ handled = true;
+ } else if (this.selectedTreeElement.hasChildren) {
+ handled = true;
+ if (this.selectedTreeElement.expanded) {
+ nextSelectedElement = this.selectedTreeElement.children[0];
+ handled = nextSelectedElement ? true : false;
+ } else {
+ if (event.altKey)
+ this.selectedTreeElement.expandRecursively();
+ else
+ this.selectedTreeElement.expand();
+ }
+ }
+ }
+
+ if (nextSelectedElement) {
+ nextSelectedElement.reveal();
+ nextSelectedElement.select();
+ }
+
+ if (handled) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+
+ return handled;
+}
+
+TreeOutline.prototype.expand = function()
+{
+ // this is the root, do nothing
+}
+
+TreeOutline.prototype.collapse = function()
+{
+ // this is the root, do nothing
+}
+
+TreeOutline.prototype.revealed = function()
+{
+ return true;
+}
+
+TreeOutline.prototype.reveal = function()
+{
+ // this is the root, do nothing
+}
+
+TreeOutline.prototype.appendChild = TreeOutline._appendChild;
+TreeOutline.prototype.insertChild = TreeOutline._insertChild;
+TreeOutline.prototype.removeChild = TreeOutline._removeChild;
+TreeOutline.prototype.removeChildAtIndex = TreeOutline._removeChildAtIndex;
+TreeOutline.prototype.removeChildren = TreeOutline._removeChildren;
+TreeOutline.prototype.removeChildrenRecursive = TreeOutline._removeChildrenRecursive;
+
+function TreeElement(title, representedObject, hasChildren)
+{
+ this._title = title;
+ this.representedObject = (representedObject || {});
+
+ if (this.representedObject.__treeElementIdentifier)
+ this.identifier = this.representedObject.__treeElementIdentifier;
+ else {
+ this.identifier = TreeOutline._knownTreeElementNextIdentifier++;
+ this.representedObject.__treeElementIdentifier = this.identifier;
+ }
+
+ this._hidden = false;
+ this.expanded = false;
+ this.selected = false;
+ this.hasChildren = hasChildren;
+ this.children = [];
+ this.treeOutline = null;
+ this.parent = null;
+ this.previousSibling = null;
+ this.nextSibling = null;
+ this._listItemNode = null;
+}
+
+TreeElement.prototype = {
+ selectable: true,
+ arrowToggleWidth: 10,
+
+ get listItemElement() {
+ return this._listItemNode;
+ },
+
+ get childrenListElement() {
+ return this._childrenListNode;
+ },
+
+ get title() {
+ return this._title;
+ },
+
+ set title(x) {
+ this._title = x;
+ if (this._listItemNode)
+ this._listItemNode.innerHTML = x;
+ },
+
+ get tooltip() {
+ return this._tooltip;
+ },
+
+ set tooltip(x) {
+ this._tooltip = x;
+ if (this._listItemNode)
+ this._listItemNode.title = x ? x : "";
+ },
+
+ get hasChildren() {
+ return this._hasChildren;
+ },
+
+ set hasChildren(x) {
+ if (this._hasChildren === x)
+ return;
+
+ this._hasChildren = x;
+
+ if (!this._listItemNode)
+ return;
+
+ if (x)
+ this._listItemNode.addStyleClass("parent");
+ else {
+ this._listItemNode.removeStyleClass("parent");
+ this.collapse();
+ }
+ },
+
+ get hidden() {
+ return this._hidden;
+ },
+
+ set hidden(x) {
+ if (this._hidden === x)
+ return;
+
+ this._hidden = x;
+
+ if (x) {
+ if (this._listItemNode)
+ this._listItemNode.addStyleClass("hidden");
+ if (this._childrenListNode)
+ this._childrenListNode.addStyleClass("hidden");
+ } else {
+ if (this._listItemNode)
+ this._listItemNode.removeStyleClass("hidden");
+ if (this._childrenListNode)
+ this._childrenListNode.removeStyleClass("hidden");
+ }
+ },
+
+ get shouldRefreshChildren() {
+ return this._shouldRefreshChildren;
+ },
+
+ set shouldRefreshChildren(x) {
+ this._shouldRefreshChildren = x;
+ if (x && this.expanded)
+ this.expand();
+ }
+}
+
+TreeElement.prototype.appendChild = TreeOutline._appendChild;
+TreeElement.prototype.insertChild = TreeOutline._insertChild;
+TreeElement.prototype.removeChild = TreeOutline._removeChild;
+TreeElement.prototype.removeChildAtIndex = TreeOutline._removeChildAtIndex;
+TreeElement.prototype.removeChildren = TreeOutline._removeChildren;
+TreeElement.prototype.removeChildrenRecursive = TreeOutline._removeChildrenRecursive;
+
+TreeElement.prototype._attach = function()
+{
+ if (!this._listItemNode || this.parent._shouldRefreshChildren) {
+ if (this._listItemNode && this._listItemNode.parentNode)
+ this._listItemNode.parentNode.removeChild(this._listItemNode);
+
+ this._listItemNode = this.treeOutline._childrenListNode.ownerDocument.createElement("li");
+ this._listItemNode.treeElement = this;
+ this._listItemNode.innerHTML = this._title;
+ this._listItemNode.title = this._tooltip ? this._tooltip : "";
+
+ if (this.hidden)
+ this._listItemNode.addStyleClass("hidden");
+ if (this.hasChildren)
+ this._listItemNode.addStyleClass("parent");
+ if (this.expanded)
+ this._listItemNode.addStyleClass("expanded");
+ if (this.selected)
+ this._listItemNode.addStyleClass("selected");
+
+ this._listItemNode.addEventListener("mousedown", TreeElement.treeElementSelected, false);
+ this._listItemNode.addEventListener("click", TreeElement.treeElementToggled, false);
+ this._listItemNode.addEventListener("dblclick", TreeElement.treeElementDoubleClicked, false);
+
+ if (this.onattach)
+ this.onattach(this);
+ }
+
+ var nextSibling = null;
+ if (this.nextSibling && this.nextSibling._listItemNode && this.nextSibling._listItemNode.parentNode === this.parent._childrenListNode)
+ nextSibling = this.nextSibling._listItemNode;
+ this.parent._childrenListNode.insertBefore(this._listItemNode, nextSibling);
+ if (this._childrenListNode)
+ this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
+ if (this.selected)
+ this.select();
+ if (this.expanded)
+ this.expand();
+}
+
+TreeElement.prototype._detach = function()
+{
+ if (this._listItemNode && this._listItemNode.parentNode)
+ this._listItemNode.parentNode.removeChild(this._listItemNode);
+ if (this._childrenListNode && this._childrenListNode.parentNode)
+ this._childrenListNode.parentNode.removeChild(this._childrenListNode);
+}
+
+TreeElement.treeElementSelected = function(event)
+{
+ var element = event.currentTarget;
+ if (!element || !element.treeElement || !element.treeElement.selectable)
+ return;
+
+ if (element.treeElement.isEventWithinDisclosureTriangle(event))
+ return;
+
+ element.treeElement.select();
+}
+
+TreeElement.treeElementToggled = function(event)
+{
+ var element = event.currentTarget;
+ if (!element || !element.treeElement)
+ return;
+
+ if (!element.treeElement.isEventWithinDisclosureTriangle(event))
+ return;
+
+ if (element.treeElement.expanded) {
+ if (event.altKey)
+ element.treeElement.collapseRecursively();
+ else
+ element.treeElement.collapse();
+ } else {
+ if (event.altKey)
+ element.treeElement.expandRecursively();
+ else
+ element.treeElement.expand();
+ }
+}
+
+TreeElement.treeElementDoubleClicked = function(event)
+{
+ var element = event.currentTarget;
+ if (!element || !element.treeElement)
+ return;
+
+ if (element.treeElement.ondblclick)
+ element.treeElement.ondblclick(element.treeElement, event);
+ else if (element.treeElement.hasChildren && !element.treeElement.expanded)
+ element.treeElement.expand();
+}
+
+TreeElement.prototype.collapse = function()
+{
+ if (this._listItemNode)
+ this._listItemNode.removeStyleClass("expanded");
+ if (this._childrenListNode)
+ this._childrenListNode.removeStyleClass("expanded");
+
+ this.expanded = false;
+ if (this.treeOutline)
+ this.treeOutline._treeElementsExpandedState[this.identifier] = true;
+
+ if (this.oncollapse)
+ this.oncollapse(this);
+}
+
+TreeElement.prototype.collapseRecursively = function()
+{
+ var item = this;
+ while (item) {
+ if (item.expanded)
+ item.collapse();
+ item = item.traverseNextTreeElement(false, this, true);
+ }
+}
+
+TreeElement.prototype.expand = function()
+{
+ if (!this.hasChildren || (this.expanded && !this._shouldRefreshChildren && this._childrenListNode))
+ return;
+
+ if (this.treeOutline && (!this._childrenListNode || this._shouldRefreshChildren)) {
+ if (this._childrenListNode && this._childrenListNode.parentNode)
+ this._childrenListNode.parentNode.removeChild(this._childrenListNode);
+
+ this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
+ this._childrenListNode.parentTreeElement = this;
+ this._childrenListNode.addStyleClass("children");
+
+ if (this.hidden)
+ this._childrenListNode.addStyleClass("hidden");
+
+ if (this.onpopulate)
+ this.onpopulate(this);
+
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i]._attach();
+
+ delete this._shouldRefreshChildren;
+ }
+
+ if (this._listItemNode) {
+ this._listItemNode.addStyleClass("expanded");
+ if (this._childrenListNode && this._childrenListNode.parentNode != this._listItemNode.parentNode)
+ this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
+ }
+
+ if (this._childrenListNode)
+ this._childrenListNode.addStyleClass("expanded");
+
+ this.expanded = true;
+ if (this.treeOutline)
+ this.treeOutline._treeElementsExpandedState[this.identifier] = true;
+
+ if (this.onexpand)
+ this.onexpand(this);
+}
+
+TreeElement.prototype.expandRecursively = function(maxDepth)
+{
+ var item = this;
+ var info = {};
+ var depth = 0;
+
+ // The Inspector uses TreeOutlines to represents object properties, so recursive expansion
+ // in some case can be infinite, since JavaScript objects can hold circular references.
+ // So default to a recursion cap of 3 levels, since that gives fairly good results.
+ if (typeof maxDepth === "undefined" || typeof maxDepth === "null")
+ maxDepth = 3;
+
+ while (item) {
+ if (depth < maxDepth)
+ item.expand();
+ item = item.traverseNextTreeElement(false, this, (depth >= maxDepth), info);
+ depth += info.depthChange;
+ }
+}
+
+TreeElement.prototype.hasAncestor = function(ancestor) {
+ if (!ancestor)
+ return false;
+
+ var currentNode = this.parent;
+ while (currentNode) {
+ if (ancestor === currentNode)
+ return true;
+ currentNode = currentNode.parent;
+ }
+
+ return false;
+}
+
+TreeElement.prototype.reveal = function()
+{
+ var currentAncestor = this.parent;
+ while (currentAncestor && !currentAncestor.root) {
+ if (!currentAncestor.expanded)
+ currentAncestor.expand();
+ currentAncestor = currentAncestor.parent;
+ }
+
+ if (this.onreveal)
+ this.onreveal(this);
+}
+
+TreeElement.prototype.revealed = function()
+{
+ var currentAncestor = this.parent;
+ while (currentAncestor && !currentAncestor.root) {
+ if (!currentAncestor.expanded)
+ return false;
+ currentAncestor = currentAncestor.parent;
+ }
+
+ return true;
+}
+
+TreeElement.prototype.select = function(supressOnSelect)
+{
+ if (!this.treeOutline || !this.selectable || this.selected)
+ return;
+
+ if (this.treeOutline.selectedTreeElement)
+ this.treeOutline.selectedTreeElement.deselect();
+
+ this.selected = true;
+ this.treeOutline.selectedTreeElement = this;
+ if (this._listItemNode)
+ this._listItemNode.addStyleClass("selected");
+
+ if (this.onselect && !supressOnSelect)
+ this.onselect(this);
+}
+
+TreeElement.prototype.deselect = function(supressOnDeselect)
+{
+ if (!this.treeOutline || this.treeOutline.selectedTreeElement !== this || !this.selected)
+ return;
+
+ this.selected = false;
+ this.treeOutline.selectedTreeElement = null;
+ if (this._listItemNode)
+ this._listItemNode.removeStyleClass("selected");
+
+ if (this.ondeselect && !supressOnDeselect)
+ this.ondeselect(this);
+}
+
+TreeElement.prototype.traverseNextTreeElement = function(skipHidden, stayWithin, dontPopulate, info)
+{
+ if (!dontPopulate && this.hasChildren && this.onpopulate)
+ this.onpopulate(this);
+
+ if (info)
+ info.depthChange = 0;
+
+ var element = skipHidden ? (this.revealed() ? this.children[0] : null) : this.children[0];
+ if (element && (!skipHidden || (skipHidden && this.expanded))) {
+ if (info)
+ info.depthChange = 1;
+ return element;
+ }
+
+ if (this === stayWithin)
+ return null;
+
+ element = skipHidden ? (this.revealed() ? this.nextSibling : null) : this.nextSibling;
+ if (element)
+ return element;
+
+ element = this;
+ while (element && !element.root && !(skipHidden ? (element.revealed() ? element.nextSibling : null) : element.nextSibling) && element.parent !== stayWithin) {
+ if (info)
+ info.depthChange -= 1;
+ element = element.parent;
+ }
+
+ if (!element)
+ return null;
+
+ return (skipHidden ? (element.revealed() ? element.nextSibling : null) : element.nextSibling);
+}
+
+TreeElement.prototype.traversePreviousTreeElement = function(skipHidden, dontPopulate)
+{
+ var element = skipHidden ? (this.revealed() ? this.previousSibling : null) : this.previousSibling;
+ if (!dontPopulate && element && element.hasChildren && element.onpopulate)
+ element.onpopulate(element);
+
+ while (element && (skipHidden ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.children[element.children.length - 1])) {
+ if (!dontPopulate && element.hasChildren && element.onpopulate)
+ element.onpopulate(element);
+ element = (skipHidden ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.children[element.children.length - 1]);
+ }
+
+ if (element)
+ return element;
+
+ if (!this.parent || this.parent.root)
+ return null;
+
+ return this.parent;
+}
+
+TreeElement.prototype.isEventWithinDisclosureTriangle = function(event)
+{
+ var left = this._listItemNode.totalOffsetLeft;
+ return event.pageX >= left && event.pageX <= left + this.arrowToggleWidth && this.hasChildren;
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/utilities.js b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/utilities.js
new file mode 100644
index 0000000..8fb50e2
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/inspector/utilities.js
@@ -0,0 +1,1136 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+Object.type = function(obj, win)
+{
+ if (obj === null)
+ return "null";
+
+ var type = typeof obj;
+ if (type !== "object" && type !== "function")
+ return type;
+
+ win = win || window;
+
+ if (obj instanceof win.Node)
+ return "node";
+ if (obj instanceof win.String)
+ return "string";
+ if (obj instanceof win.Array)
+ return "array";
+ if (obj instanceof win.Boolean)
+ return "boolean";
+ if (obj instanceof win.Number)
+ return "number";
+ if (obj instanceof win.Date)
+ return "date";
+ if (obj instanceof win.RegExp)
+ return "regexp";
+ if (obj instanceof win.Error)
+ return "error";
+ return type;
+}
+
+Object.hasProperties = function(obj)
+{
+ if (typeof obj === "undefined" || typeof obj === "null")
+ return false;
+ for (var name in obj)
+ return true;
+ return false;
+}
+
+Object.describe = function(obj, abbreviated)
+{
+ var type1 = Object.type(obj);
+ var type2 = Object.prototype.toString.call(obj).replace(/^\[object (.*)\]$/i, "$1");
+
+ switch (type1) {
+ case "object":
+ case "node":
+ return type2;
+ case "array":
+ return "[" + obj.toString() + "]";
+ case "string":
+ if (obj.length > 100)
+ return "\"" + obj.substring(0, 100) + "\u2026\"";
+ return "\"" + obj + "\"";
+ case "function":
+ var objectText = String(obj);
+ if (!/^function /.test(objectText))
+ objectText = (type2 == "object") ? type1 : type2;
+ else if (abbreviated)
+ objectText = /.*/.exec(obj)[0].replace(/ +$/g, "");
+ return objectText;
+ case "regexp":
+ return String(obj).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1);
+ default:
+ return String(obj);
+ }
+}
+
+Object.sortedProperties = function(obj)
+{
+ var properties = [];
+ for (var prop in obj)
+ properties.push(prop);
+ properties.sort();
+ return properties;
+}
+
+Function.prototype.bind = function(thisObject)
+{
+ var func = this;
+ var args = Array.prototype.slice.call(arguments, 1);
+ return function() { return func.apply(thisObject, args.concat(Array.prototype.slice.call(arguments, 0))) };
+}
+
+Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, direction)
+{
+ var startNode;
+ var startOffset = 0;
+ var endNode;
+ var endOffset = 0;
+
+ if (!stayWithinNode)
+ stayWithinNode = this;
+
+ if (!direction || direction === "backward" || direction === "both") {
+ var node = this;
+ while (node) {
+ if (node === stayWithinNode) {
+ if (!startNode)
+ startNode = stayWithinNode;
+ break;
+ }
+
+ if (node.nodeType === Node.TEXT_NODE) {
+ var start = (node === this ? (offset - 1) : (node.nodeValue.length - 1));
+ for (var i = start; i >= 0; --i) {
+ if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
+ startNode = node;
+ startOffset = i + 1;
+ break;
+ }
+ }
+ }
+
+ if (startNode)
+ break;
+
+ node = node.traversePreviousNode(false, stayWithinNode);
+ }
+
+ if (!startNode) {
+ startNode = stayWithinNode;
+ startOffset = 0;
+ }
+ } else {
+ startNode = this;
+ startOffset = offset;
+ }
+
+ if (!direction || direction === "forward" || direction === "both") {
+ node = this;
+ while (node) {
+ if (node === stayWithinNode) {
+ if (!endNode)
+ endNode = stayWithinNode;
+ break;
+ }
+
+ if (node.nodeType === Node.TEXT_NODE) {
+ var start = (node === this ? offset : 0);
+ for (var i = start; i < node.nodeValue.length; ++i) {
+ if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
+ endNode = node;
+ endOffset = i;
+ break;
+ }
+ }
+ }
+
+ if (endNode)
+ break;
+
+ node = node.traverseNextNode(false, stayWithinNode);
+ }
+
+ if (!endNode) {
+ endNode = stayWithinNode;
+ endOffset = stayWithinNode.nodeType === Node.TEXT_NODE ? stayWithinNode.nodeValue.length : stayWithinNode.childNodes.length;
+ }
+ } else {
+ endNode = this;
+ endOffset = offset;
+ }
+
+ var result = this.ownerDocument.createRange();
+ result.setStart(startNode, startOffset);
+ result.setEnd(endNode, endOffset);
+
+ return result;
+}
+
+Element.prototype.removeStyleClass = function(className)
+{
+ // Test for the simple case before using a RegExp.
+ if (this.className === className) {
+ this.className = "";
+ return;
+ }
+
+ this.removeMatchingStyleClasses(className.escapeForRegExp());
+}
+
+Element.prototype.removeMatchingStyleClasses = function(classNameRegex)
+{
+ var regex = new RegExp("(^|\\s+)" + classNameRegex + "($|\\s+)");
+ if (regex.test(this.className))
+ this.className = this.className.replace(regex, " ");
+}
+
+Element.prototype.addStyleClass = function(className)
+{
+ if (className && !this.hasStyleClass(className))
+ this.className += (this.className.length ? " " + className : className);
+}
+
+Element.prototype.hasStyleClass = function(className)
+{
+ if (!className)
+ return false;
+ // Test for the simple case before using a RegExp.
+ if (this.className === className)
+ return true;
+ var regex = new RegExp("(^|\\s)" + className.escapeForRegExp() + "($|\\s)");
+ return regex.test(this.className);
+}
+
+Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray)
+{
+ for (var node = this; node && !objectsAreSame(node, this.ownerDocument); node = node.parentNode)
+ for (var i = 0; i < nameArray.length; ++i)
+ if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase())
+ return node;
+ return null;
+}
+
+Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName)
+{
+ return this.enclosingNodeOrSelfWithNodeNameInArray([nodeName]);
+}
+
+Node.prototype.enclosingNodeOrSelfWithClass = function(className)
+{
+ for (var node = this; node && !objectsAreSame(node, this.ownerDocument); node = node.parentNode)
+ if (node.nodeType === Node.ELEMENT_NODE && node.hasStyleClass(className))
+ return node;
+ return null;
+}
+
+Node.prototype.enclosingNodeWithClass = function(className)
+{
+ if (!this.parentNode)
+ return null;
+ return this.parentNode.enclosingNodeOrSelfWithClass(className);
+}
+
+Element.prototype.query = function(query)
+{
+ return this.ownerDocument.evaluate(query, this, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
+}
+
+Element.prototype.removeChildren = function()
+{
+ while (this.firstChild)
+ this.removeChild(this.firstChild);
+}
+
+Element.prototype.isInsertionCaretInside = function()
+{
+ var selection = window.getSelection();
+ if (!selection.rangeCount || !selection.isCollapsed)
+ return false;
+ var selectionRange = selection.getRangeAt(0);
+ return selectionRange.startContainer === this || selectionRange.startContainer.isDescendant(this);
+}
+
+Element.prototype.__defineGetter__("totalOffsetLeft", function()
+{
+ var total = 0;
+ for (var element = this; element; element = element.offsetParent)
+ total += element.offsetLeft;
+ return total;
+});
+
+Element.prototype.__defineGetter__("totalOffsetTop", function()
+{
+ var total = 0;
+ for (var element = this; element; element = element.offsetParent)
+ total += element.offsetTop;
+ return total;
+});
+
+Element.prototype.firstChildSkippingWhitespace = firstChildSkippingWhitespace;
+Element.prototype.lastChildSkippingWhitespace = lastChildSkippingWhitespace;
+
+Node.prototype.isWhitespace = isNodeWhitespace;
+Node.prototype.nodeTypeName = nodeTypeName;
+Node.prototype.displayName = nodeDisplayName;
+Node.prototype.contentPreview = nodeContentPreview;
+Node.prototype.isAncestor = isAncestorNode;
+Node.prototype.isDescendant = isDescendantNode;
+Node.prototype.firstCommonAncestor = firstCommonNodeAncestor;
+Node.prototype.nextSiblingSkippingWhitespace = nextSiblingSkippingWhitespace;
+Node.prototype.previousSiblingSkippingWhitespace = previousSiblingSkippingWhitespace;
+Node.prototype.traverseNextNode = traverseNextNode;
+Node.prototype.traversePreviousNode = traversePreviousNode;
+Node.prototype.onlyTextChild = onlyTextChild;
+
+String.prototype.hasSubstring = function(string, caseInsensitive)
+{
+ if (!caseInsensitive)
+ return this.indexOf(string) !== -1;
+ return this.match(new RegExp(string.escapeForRegExp(), "i"));
+}
+
+String.prototype.escapeCharacters = function(chars)
+{
+ var foundChar = false;
+ for (var i = 0; i < chars.length; ++i) {
+ if (this.indexOf(chars.charAt(i)) !== -1) {
+ foundChar = true;
+ break;
+ }
+ }
+
+ if (!foundChar)
+ return this;
+
+ var result = "";
+ for (var i = 0; i < this.length; ++i) {
+ if (chars.indexOf(this.charAt(i)) !== -1)
+ result += "\\";
+ result += this.charAt(i);
+ }
+
+ return result;
+}
+
+String.prototype.escapeForRegExp = function()
+{
+ return this.escapeCharacters("^[]{}()\\.$*+?|");
+}
+
+String.prototype.escapeHTML = function()
+{
+ return this.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
+}
+
+String.prototype.collapseWhitespace = function()
+{
+ return this.replace(/[\s\xA0]+/g, " ");
+}
+
+String.prototype.trimLeadingWhitespace = function()
+{
+ return this.replace(/^[\s\xA0]+/g, "");
+}
+
+String.prototype.trimTrailingWhitespace = function()
+{
+ return this.replace(/[\s\xA0]+$/g, "");
+}
+
+String.prototype.trimWhitespace = function()
+{
+ return this.replace(/^[\s\xA0]+|[\s\xA0]+$/g, "");
+}
+
+String.prototype.trimURL = function(baseURLDomain)
+{
+ var result = this.replace(new RegExp("^http[s]?:\/\/", "i"), "");
+ if (baseURLDomain)
+ result = result.replace(new RegExp("^" + baseURLDomain.escapeForRegExp(), "i"), "");
+ return result;
+}
+
+function getStyleTextWithShorthands(style)
+{
+ var cssText = "";
+ var foundProperties = {};
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ var shorthandProperty = style.getPropertyShorthand(individualProperty);
+ var propertyName = (shorthandProperty || individualProperty);
+
+ if (propertyName in foundProperties)
+ continue;
+
+ if (shorthandProperty) {
+ var value = getShorthandValue(style, shorthandProperty);
+ var priority = getShorthandPriority(style, shorthandProperty);
+ } else {
+ var value = style.getPropertyValue(individualProperty);
+ var priority = style.getPropertyPriority(individualProperty);
+ }
+
+ foundProperties[propertyName] = true;
+
+ cssText += propertyName + ": " + value;
+ if (priority)
+ cssText += " !" + priority;
+ cssText += "; ";
+ }
+
+ return cssText;
+}
+
+function getShorthandValue(style, shorthandProperty)
+{
+ var value = style.getPropertyValue(shorthandProperty);
+ if (!value) {
+ // Some shorthands (like border) return a null value, so compute a shorthand value.
+ // FIXME: remove this when http://bugs.webkit.org/show_bug.cgi?id=15823 is fixed.
+
+ var foundProperties = {};
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (individualProperty in foundProperties || style.getPropertyShorthand(individualProperty) !== shorthandProperty)
+ continue;
+
+ var individualValue = style.getPropertyValue(individualProperty);
+ if (style.isPropertyImplicit(individualProperty) || individualValue === "initial")
+ continue;
+
+ foundProperties[individualProperty] = true;
+
+ if (!value)
+ value = "";
+ else if (value.length)
+ value += " ";
+ value += individualValue;
+ }
+ }
+ return value;
+}
+
+function getShorthandPriority(style, shorthandProperty)
+{
+ var priority = style.getPropertyPriority(shorthandProperty);
+ if (!priority) {
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (style.getPropertyShorthand(individualProperty) !== shorthandProperty)
+ continue;
+ priority = style.getPropertyPriority(individualProperty);
+ break;
+ }
+ }
+ return priority;
+}
+
+function getLonghandProperties(style, shorthandProperty)
+{
+ var properties = [];
+ var foundProperties = {};
+
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (individualProperty in foundProperties || style.getPropertyShorthand(individualProperty) !== shorthandProperty)
+ continue;
+ foundProperties[individualProperty] = true;
+ properties.push(individualProperty);
+ }
+
+ return properties;
+}
+
+function getUniqueStyleProperties(style)
+{
+ var properties = [];
+ var foundProperties = {};
+
+ for (var i = 0; i < style.length; ++i) {
+ var property = style[i];
+ if (property in foundProperties)
+ continue;
+ foundProperties[property] = true;
+ properties.push(property);
+ }
+
+ return properties;
+}
+
+function isNodeWhitespace()
+{
+ if (!this || this.nodeType !== Node.TEXT_NODE)
+ return false;
+ if (!this.nodeValue.length)
+ return true;
+ return this.nodeValue.match(/^[\s\xA0]+$/);
+}
+
+function nodeTypeName()
+{
+ if (!this)
+ return "(unknown)";
+
+ switch (this.nodeType) {
+ case Node.ELEMENT_NODE: return "Element";
+ case Node.ATTRIBUTE_NODE: return "Attribute";
+ case Node.TEXT_NODE: return "Text";
+ case Node.CDATA_SECTION_NODE: return "Character Data";
+ case Node.ENTITY_REFERENCE_NODE: return "Entity Reference";
+ case Node.ENTITY_NODE: return "Entity";
+ case Node.PROCESSING_INSTRUCTION_NODE: return "Processing Instruction";
+ case Node.COMMENT_NODE: return "Comment";
+ case Node.DOCUMENT_NODE: return "Document";
+ case Node.DOCUMENT_TYPE_NODE: return "Document Type";
+ case Node.DOCUMENT_FRAGMENT_NODE: return "Document Fragment";
+ case Node.NOTATION_NODE: return "Notation";
+ }
+
+ return "(unknown)";
+}
+
+function nodeDisplayName()
+{
+ if (!this)
+ return "";
+
+ switch (this.nodeType) {
+ case Node.DOCUMENT_NODE:
+ return "Document";
+
+ case Node.ELEMENT_NODE:
+ var name = "<" + this.nodeName.toLowerCase();
+
+ if (this.hasAttributes()) {
+ var value = this.getAttribute("id");
+ if (value)
+ name += " id=\"" + value + "\"";
+ value = this.getAttribute("class");
+ if (value)
+ name += " class=\"" + value + "\"";
+ if (this.nodeName.toLowerCase() === "a") {
+ value = this.getAttribute("name");
+ if (value)
+ name += " name=\"" + value + "\"";
+ value = this.getAttribute("href");
+ if (value)
+ name += " href=\"" + value + "\"";
+ } else if (this.nodeName.toLowerCase() === "img") {
+ value = this.getAttribute("src");
+ if (value)
+ name += " src=\"" + value + "\"";
+ } else if (this.nodeName.toLowerCase() === "iframe") {
+ value = this.getAttribute("src");
+ if (value)
+ name += " src=\"" + value + "\"";
+ } else if (this.nodeName.toLowerCase() === "input") {
+ value = this.getAttribute("name");
+ if (value)
+ name += " name=\"" + value + "\"";
+ value = this.getAttribute("type");
+ if (value)
+ name += " type=\"" + value + "\"";
+ } else if (this.nodeName.toLowerCase() === "form") {
+ value = this.getAttribute("action");
+ if (value)
+ name += " action=\"" + value + "\"";
+ }
+ }
+
+ return name + ">";
+
+ case Node.TEXT_NODE:
+ if (isNodeWhitespace.call(this))
+ return "(whitespace)";
+ return "\"" + this.nodeValue + "\"";
+
+ case Node.COMMENT_NODE:
+ return "<!--" + this.nodeValue + "-->";
+
+ case Node.DOCUMENT_TYPE_NODE:
+ var docType = "<!DOCTYPE " + this.nodeName;
+ if (this.publicId) {
+ docType += " PUBLIC \"" + this.publicId + "\"";
+ if (this.systemId)
+ docType += " \"" + this.systemId + "\"";
+ } else if (this.systemId)
+ docType += " SYSTEM \"" + this.systemId + "\"";
+ if (this.internalSubset)
+ docType += " [" + this.internalSubset + "]";
+ return docType + ">";
+ }
+
+ return this.nodeName.toLowerCase().collapseWhitespace();
+}
+
+function nodeContentPreview()
+{
+ if (!this || !this.hasChildNodes || !this.hasChildNodes())
+ return "";
+
+ var limit = 0;
+ var preview = "";
+
+ // always skip whitespace here
+ var currentNode = traverseNextNode.call(this, true, this);
+ while (currentNode) {
+ if (currentNode.nodeType === Node.TEXT_NODE)
+ preview += currentNode.nodeValue.escapeHTML();
+ else
+ preview += nodeDisplayName.call(currentNode).escapeHTML();
+
+ currentNode = traverseNextNode.call(currentNode, true, this);
+
+ if (++limit > 4) {
+ preview += "&#x2026;"; // ellipsis
+ break;
+ }
+ }
+
+ return preview.collapseWhitespace();
+}
+
+function objectsAreSame(a, b)
+{
+ // FIXME: Make this more generic so is works with any wrapped object, not just nodes.
+ // This function is used to compare nodes that might be JSInspectedObjectWrappers, since
+ // JavaScript equality is not true for JSInspectedObjectWrappers of the same node wrapped
+ // with different global ExecStates, we use isSameNode to compare them.
+ if (a === b)
+ return true;
+ if (!a || !b)
+ return false;
+ if (a.isSameNode && b.isSameNode)
+ return a.isSameNode(b);
+ return false;
+}
+
+function isAncestorNode(ancestor)
+{
+ if (!this || !ancestor)
+ return false;
+
+ var currentNode = ancestor.parentNode;
+ while (currentNode) {
+ if (objectsAreSame(this, currentNode))
+ return true;
+ currentNode = currentNode.parentNode;
+ }
+
+ return false;
+}
+
+function isDescendantNode(descendant)
+{
+ return isAncestorNode.call(descendant, this);
+}
+
+function firstCommonNodeAncestor(node)
+{
+ if (!this || !node)
+ return;
+
+ var node1 = this.parentNode;
+ var node2 = node.parentNode;
+
+ if ((!node1 || !node2) || !objectsAreSame(node1, node2))
+ return null;
+
+ while (node1 && node2) {
+ if (!node1.parentNode || !node2.parentNode)
+ break;
+ if (!objectsAreSame(node1, node2))
+ break;
+
+ node1 = node1.parentNode;
+ node2 = node2.parentNode;
+ }
+
+ return node1;
+}
+
+function nextSiblingSkippingWhitespace()
+{
+ if (!this)
+ return;
+ var node = this.nextSibling;
+ while (node && node.nodeType === Node.TEXT_NODE && isNodeWhitespace.call(node))
+ node = node.nextSibling;
+ return node;
+}
+
+function previousSiblingSkippingWhitespace()
+{
+ if (!this)
+ return;
+ var node = this.previousSibling;
+ while (node && node.nodeType === Node.TEXT_NODE && isNodeWhitespace.call(node))
+ node = node.previousSibling;
+ return node;
+}
+
+function firstChildSkippingWhitespace()
+{
+ if (!this)
+ return;
+ var node = this.firstChild;
+ while (node && node.nodeType === Node.TEXT_NODE && isNodeWhitespace.call(node))
+ node = nextSiblingSkippingWhitespace.call(node);
+ return node;
+}
+
+function lastChildSkippingWhitespace()
+{
+ if (!this)
+ return;
+ var node = this.lastChild;
+ while (node && node.nodeType === Node.TEXT_NODE && isNodeWhitespace.call(node))
+ node = previousSiblingSkippingWhitespace.call(node);
+ return node;
+}
+
+function traverseNextNode(skipWhitespace, stayWithin)
+{
+ if (!this)
+ return;
+
+ var node = skipWhitespace ? firstChildSkippingWhitespace.call(this) : this.firstChild;
+ if (node)
+ return node;
+
+ if (stayWithin && objectsAreSame(this, stayWithin))
+ return null;
+
+ node = skipWhitespace ? nextSiblingSkippingWhitespace.call(this) : this.nextSibling;
+ if (node)
+ return node;
+
+ node = this;
+ while (node && !(skipWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling) && (!stayWithin || !node.parentNode || !objectsAreSame(node.parentNode, stayWithin)))
+ node = node.parentNode;
+ if (!node)
+ return null;
+
+ return skipWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling;
+}
+
+function traversePreviousNode(skipWhitespace, stayWithin)
+{
+ if (!this)
+ return;
+ if (stayWithin && objectsAreSame(this, stayWithin))
+ return null;
+ var node = skipWhitespace ? previousSiblingSkippingWhitespace.call(this) : this.previousSibling;
+ while (node && (skipWhitespace ? lastChildSkippingWhitespace.call(node) : node.lastChild) )
+ node = skipWhitespace ? lastChildSkippingWhitespace.call(node) : node.lastChild;
+ if (node)
+ return node;
+ return this.parentNode;
+}
+
+function onlyTextChild(ignoreWhitespace)
+{
+ if (!this)
+ return null;
+
+ var firstChild = ignoreWhitespace ? firstChildSkippingWhitespace.call(this) : this.firstChild;
+ if (!firstChild || firstChild.nodeType !== Node.TEXT_NODE)
+ return null;
+
+ var sibling = ignoreWhitespace ? nextSiblingSkippingWhitespace.call(firstChild) : firstChild.nextSibling;
+ return sibling ? null : firstChild;
+}
+
+function nodeTitleInfo(hasChildren, linkify)
+{
+ var info = {title: "", hasChildren: hasChildren};
+
+ switch (this.nodeType) {
+ case Node.DOCUMENT_NODE:
+ info.title = "Document";
+ break;
+
+ case Node.ELEMENT_NODE:
+ info.title = "<span class=\"webkit-html-tag\">&lt;" + this.nodeName.toLowerCase().escapeHTML();
+
+ if (this.hasAttributes()) {
+ for (var i = 0; i < this.attributes.length; ++i) {
+ var attr = this.attributes[i];
+ info.title += " <span class=\"webkit-html-attribute\"><span class=\"webkit-html-attribute-name\">" + attr.name.escapeHTML() + "</span>=&#8203;\"";
+
+ var value = attr.value;
+ if (linkify && (attr.name === "src" || attr.name === "href")) {
+ var value = value.replace(/([\/;:\)\]\}])/g, "$1\u200B");
+ info.title += linkify(attr.value, value, "webkit-html-attribute-value", this.nodeName.toLowerCase() == "a");
+ } else {
+ var value = value.escapeHTML();
+ value = value.replace(/([\/;:\)\]\}])/g, "$1&#8203;");
+ info.title += "<span class=\"webkit-html-attribute-value\">" + value + "</span>";
+ }
+ info.title += "\"</span>";
+ }
+ }
+ info.title += "&gt;</span>&#8203;";
+
+ // If this element only has a single child that is a text node,
+ // just show that text and the closing tag inline rather than
+ // create a subtree for them
+
+ var textChild = onlyTextChild.call(this, Preferences.ignoreWhitespace);
+ var showInlineText = textChild && textChild.textContent.length < Preferences.maxInlineTextChildLength;
+
+ if (showInlineText) {
+ info.title += "<span class=\"webkit-html-text-node\">" + textChild.nodeValue.escapeHTML() + "</span>&#8203;<span class=\"webkit-html-tag\">&lt;/" + this.nodeName.toLowerCase().escapeHTML() + "&gt;</span>";
+ info.hasChildren = false;
+ }
+ break;
+
+ case Node.TEXT_NODE:
+ if (isNodeWhitespace.call(this))
+ info.title = "(whitespace)";
+ else
+ info.title = "\"<span class=\"webkit-html-text-node\">" + this.nodeValue.escapeHTML() + "</span>\"";
+ break
+
+ case Node.COMMENT_NODE:
+ info.title = "<span class=\"webkit-html-comment\">&lt;!--" + this.nodeValue.escapeHTML() + "--&gt;</span>";
+ break;
+
+ case Node.DOCUMENT_TYPE_NODE:
+ info.title = "<span class=\"webkit-html-doctype\">&lt;!DOCTYPE " + this.nodeName;
+ if (this.publicId) {
+ info.title += " PUBLIC \"" + this.publicId + "\"";
+ if (this.systemId)
+ info.title += " \"" + this.systemId + "\"";
+ } else if (this.systemId)
+ info.title += " SYSTEM \"" + this.systemId + "\"";
+ if (this.internalSubset)
+ info.title += " [" + this.internalSubset + "]";
+ info.title += "&gt;</span>";
+ break;
+ default:
+ info.title = this.nodeName.toLowerCase().collapseWhitespace().escapeHTML();
+ }
+
+ return info;
+}
+
+function getDocumentForNode(node) {
+ return node.nodeType == Node.DOCUMENT_NODE ? node : node.ownerDocument;
+}
+
+function parentNodeOrFrameElement(node) {
+ var parent = node.parentNode;
+ if (parent)
+ return parent;
+
+ return getDocumentForNode(node).defaultView.frameElement;
+}
+
+function isAncestorIncludingParentFrames(a, b) {
+ if (objectsAreSame(a, b))
+ return false;
+ for (var node = b; node; node = getDocumentForNode(node).defaultView.frameElement)
+ if (objectsAreSame(a, node) || isAncestorNode.call(a, node))
+ return true;
+ return false;
+}
+
+Number.secondsToString = function(seconds, formatterFunction, higherResolution)
+{
+ if (!formatterFunction)
+ formatterFunction = String.sprintf;
+
+ var ms = seconds * 1000;
+ if (higherResolution && ms < 1000)
+ return formatterFunction("%.3fms", ms);
+ else if (ms < 1000)
+ return formatterFunction("%.0fms", ms);
+
+ if (seconds < 60)
+ return formatterFunction("%.2fs", seconds);
+
+ var minutes = seconds / 60;
+ if (minutes < 60)
+ return formatterFunction("%.1fmin", minutes);
+
+ var hours = minutes / 60;
+ if (hours < 24)
+ return formatterFunction("%.1fhrs", hours);
+
+ var days = hours / 24;
+ return formatterFunction("%.1f days", days);
+}
+
+Number.bytesToString = function(bytes, formatterFunction)
+{
+ if (!formatterFunction)
+ formatterFunction = String.sprintf;
+
+ if (bytes < 1024)
+ return formatterFunction("%.0fB", bytes);
+
+ var kilobytes = bytes / 1024;
+ if (kilobytes < 1024)
+ return formatterFunction("%.2fKB", kilobytes);
+
+ var megabytes = kilobytes / 1024;
+ return formatterFunction("%.3fMB", megabytes);
+}
+
+Number.constrain = function(num, min, max)
+{
+ if (num < min)
+ num = min;
+ else if (num > max)
+ num = max;
+ return num;
+}
+
+HTMLTextAreaElement.prototype.moveCursorToEnd = function()
+{
+ var length = this.value.length;
+ this.setSelectionRange(length, length);
+}
+
+Array.prototype.remove = function(value, onlyFirst)
+{
+ if (onlyFirst) {
+ var index = this.indexOf(value);
+ if (index !== -1)
+ this.splice(index, 1);
+ return;
+ }
+
+ var length = this.length;
+ for (var i = 0; i < length; ++i) {
+ if (this[i] === value)
+ this.splice(i, 1);
+ }
+}
+
+function insertionIndexForObjectInListSortedByFunction(anObject, aList, aFunction)
+{
+ // indexOf returns (-lowerBound - 1). Taking (-result - 1) works out to lowerBound.
+ return (-indexOfObjectInListSortedByFunction(anObject, aList, aFunction) - 1);
+}
+
+function indexOfObjectInListSortedByFunction(anObject, aList, aFunction)
+{
+ var first = 0;
+ var last = aList.length - 1;
+ var floor = Math.floor;
+ var mid, c;
+
+ while (first <= last) {
+ mid = floor((first + last) / 2);
+ c = aFunction(anObject, aList[mid]);
+
+ if (c > 0)
+ first = mid + 1;
+ else if (c < 0)
+ last = mid - 1;
+ else {
+ // Return the first occurance of an item in the list.
+ while (mid > 0 && aFunction(anObject, aList[mid - 1]) === 0)
+ mid--;
+ first = mid;
+ break;
+ }
+ }
+
+ // By returning 1 less than the negative lower search bound, we can reuse this function
+ // for both indexOf and insertionIndexFor, with some simple arithmetic.
+ return (-first - 1);
+}
+
+String.sprintf = function(format)
+{
+ return String.vsprintf(format, Array.prototype.slice.call(arguments, 1));
+}
+
+String.tokenizeFormatString = function(format)
+{
+ var tokens = [];
+ var substitutionIndex = 0;
+
+ function addStringToken(str)
+ {
+ tokens.push({ type: "string", value: str });
+ }
+
+ function addSpecifierToken(specifier, precision, substitutionIndex)
+ {
+ tokens.push({ type: "specifier", specifier: specifier, precision: precision, substitutionIndex: substitutionIndex });
+ }
+
+ var index = 0;
+ for (var precentIndex = format.indexOf("%", index); precentIndex !== -1; precentIndex = format.indexOf("%", index)) {
+ addStringToken(format.substring(index, precentIndex));
+ index = precentIndex + 1;
+
+ if (format[index] === "%") {
+ addStringToken("%");
+ ++index;
+ continue;
+ }
+
+ if (!isNaN(format[index])) {
+ // The first character is a number, it might be a substitution index.
+ var number = parseInt(format.substring(index));
+ while (!isNaN(format[index]))
+ ++index;
+ // If the number is greater than zero and ends with a "$",
+ // then this is a substitution index.
+ if (number > 0 && format[index] === "$") {
+ substitutionIndex = (number - 1);
+ ++index;
+ }
+ }
+
+ var precision = -1;
+ if (format[index] === ".") {
+ // This is a precision specifier. If no digit follows the ".",
+ // then the precision should be zero.
+ ++index;
+ precision = parseInt(format.substring(index));
+ if (isNaN(precision))
+ precision = 0;
+ while (!isNaN(format[index]))
+ ++index;
+ }
+
+ addSpecifierToken(format[index], precision, substitutionIndex);
+
+ ++substitutionIndex;
+ ++index;
+ }
+
+ addStringToken(format.substring(index));
+
+ return tokens;
+}
+
+String.standardFormatters = {
+ d: function(substitution)
+ {
+ substitution = parseInt(substitution);
+ return !isNaN(substitution) ? substitution : 0;
+ },
+
+ f: function(substitution, token)
+ {
+ substitution = parseFloat(substitution);
+ if (substitution && token.precision > -1)
+ substitution = substitution.toFixed(token.precision);
+ return !isNaN(substitution) ? substitution : (token.precision > -1 ? Number(0).toFixed(token.precision) : 0);
+ },
+
+ s: function(substitution)
+ {
+ return substitution;
+ },
+};
+
+String.vsprintf = function(format, substitutions)
+{
+ return String.format(format, substitutions, String.standardFormatters, "", function(a, b) { return a + b; }).formattedResult;
+}
+
+String.format = function(format, substitutions, formatters, initialValue, append)
+{
+ if (!format || !substitutions || !substitutions.length)
+ return { formattedResult: append(initialValue, format), unusedSubstitutions: substitutions };
+
+ function prettyFunctionName()
+ {
+ return "String.format(\"" + format + "\", \"" + substitutions.join("\", \"") + "\")";
+ }
+
+ function warn(msg)
+ {
+ console.warn(prettyFunctionName() + ": " + msg);
+ }
+
+ function error(msg)
+ {
+ console.error(prettyFunctionName() + ": " + msg);
+ }
+
+ var result = initialValue;
+ var tokens = String.tokenizeFormatString(format);
+ var usedSubstitutionIndexes = {};
+
+ for (var i = 0; i < tokens.length; ++i) {
+ var token = tokens[i];
+
+ if (token.type === "string") {
+ result = append(result, token.value);
+ continue;
+ }
+
+ if (token.type !== "specifier") {
+ error("Unknown token type \"" + token.type + "\" found.");
+ continue;
+ }
+
+ if (token.substitutionIndex >= substitutions.length) {
+ // If there are not enough substitutions for the current substitutionIndex
+ // just output the format specifier literally and move on.
+ error("not enough substitution arguments. Had " + substitutions.length + " but needed " + (token.substitutionIndex + 1) + ", so substitution was skipped.");
+ result = append(result, "%" + (token.precision > -1 ? token.precision : "") + token.specifier);
+ continue;
+ }
+
+ usedSubstitutionIndexes[token.substitutionIndex] = true;
+
+ if (!(token.specifier in formatters)) {
+ // Encountered an unsupported format character, treat as a string.
+ warn("unsupported format character \u201C" + token.specifier + "\u201D. Treating as a string.");
+ result = append(result, substitutions[token.substitutionIndex]);
+ continue;
+ }
+
+ result = append(result, formatters[token.specifier](substitutions[token.substitutionIndex], token));
+ }
+
+ var unusedSubstitutions = [];
+ for (var i = 0; i < substitutions.length; ++i) {
+ if (i in usedSubstitutionIndexes)
+ continue;
+ unusedSubstitutions.push(substitutions[i]);
+ }
+
+ return { formattedResult: result, unusedSubstitutions: unusedSubstitutions };
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/linkCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/linkCursor.png
new file mode 100644
index 0000000..e5e2749
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/linkCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/missingImage.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/missingImage.png
new file mode 100644
index 0000000..5c24d20
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/missingImage.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/moveCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/moveCursor.png
new file mode 100644
index 0000000..4ca8d70
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/moveCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/nav.pdf b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/nav.pdf
new file mode 100644
index 0000000..1fcfeb4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/nav.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/newtab.pdf b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/newtab.pdf
new file mode 100644
index 0000000..ba6a79c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/newtab.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/noDropCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/noDropCursor.png
new file mode 100644
index 0000000..54463fc
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/noDropCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/noneCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/noneCursor.png
new file mode 100644
index 0000000..bd1ff35
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/noneCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northEastResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northEastResizeCursor.png
new file mode 100644
index 0000000..0e89639
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northEastResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northEastSouthWestResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northEastSouthWestResizeCursor.png
new file mode 100644
index 0000000..9904c7b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northEastSouthWestResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northResizeCursor.png
new file mode 100644
index 0000000..0d020db
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northSouthResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northSouthResizeCursor.png
new file mode 100644
index 0000000..92400e9
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northSouthResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northWestResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northWestResizeCursor.png
new file mode 100644
index 0000000..6723f61
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northWestResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northWestSouthEastResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northWestSouthEastResizeCursor.png
new file mode 100644
index 0000000..b8de34c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/northWestSouthEastResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/notAllowedCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/notAllowedCursor.png
new file mode 100644
index 0000000..f3a5f4d
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/notAllowedCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_globe.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_globe.png
new file mode 100644
index 0000000..0fc4331
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_globe.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_history.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_history.png
new file mode 100644
index 0000000..72af696
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_history.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_more.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_more.png
new file mode 100644
index 0000000..61dfd29
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_more.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_search.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_search.png
new file mode 100644
index 0000000..441001e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_search.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_star.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_star.png
new file mode 100644
index 0000000..5919bb7b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/o2_star.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/progressCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/progressCursor.png
new file mode 100644
index 0000000..25d7021
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/progressCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/reload.pdf b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/reload.pdf
new file mode 100644
index 0000000..f3c6221
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/reload.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/renderer.sb b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/renderer.sb
new file mode 100644
index 0000000..baa851c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/renderer.sb
@@ -0,0 +1,28 @@
+;;
+;; Copyright (c) 2009 The Chromium Authors. All rights reserved.
+;; Use of this source code is governed by a BSD-style license that can be
+;; found in the LICENSE file.
+;;
+(version 1)
+(deny default)
+
+; Needed for full-page-zoomed checkboxes etc -- http://crbug.com/11325
+(allow sysctl-read)
+
+
+; Each line is marked with the System version that needs it.
+; This profile is tested with the following system versions:
+; 10.5.6, 10.6 seed release
+
+; Allow following symlinks
+(allow file-read-metadata) ; 10.5.6
+; Allow reading files out of /System/Library
+(allow file-read-data (regex #"^/System/Library")) ; 10.5.6
+
+; Needed for Fonts
+(allow mach-lookup (global-name "com.apple.FontObjectsServer")) ; 10.5.6
+(allow mach-lookup (global-name "com.apple.FontServer")) ; 10.6 seed release
+(allow file-read-data (regex #"^/Library/Fonts")) ; 10.6 seed release
+
+; Needed for IPC on 10.6
+(allow ipc-posix-shm)
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/sadtab.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/sadtab.png
new file mode 100644
index 0000000..4421311
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/sadtab.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/southEastResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/southEastResizeCursor.png
new file mode 100644
index 0000000..415aa633
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/southEastResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/southResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/southResizeCursor.png
new file mode 100644
index 0000000..60cf722
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/southResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/southWestResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/southWestResizeCursor.png
new file mode 100644
index 0000000..8dc5cdc
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/southWestResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/star.pdf b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/star.pdf
new file mode 100644
index 0000000..c0556d1
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/star.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/starred.pdf b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/starred.pdf
new file mode 100644
index 0000000..4be3d4c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/starred.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/stop.pdf b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/stop.pdf
new file mode 100644
index 0000000..dc8f11e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/stop.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/theme.pak b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/theme.pak
new file mode 100644
index 0000000..a814cf0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/theme.pak
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/throbber.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/throbber.png
new file mode 100644
index 0000000..6ca1fdd
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/throbber.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/throbber_waiting.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/throbber_waiting.png
new file mode 100644
index 0000000..c36e929
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/throbber_waiting.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/verticalTextCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/verticalTextCursor.png
new file mode 100644
index 0000000..0f2877c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/verticalTextCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/waitCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/waitCursor.png
new file mode 100644
index 0000000..91412b8
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/waitCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/westResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/westResizeCursor.png
new file mode 100644
index 0000000..544439a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/westResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/zoomInCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/zoomInCursor.png
new file mode 100644
index 0000000..feec9bc
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/zoomInCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/zoomOutCursor.png b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/zoomOutCursor.png
new file mode 100644
index 0000000..f4a954e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Chromium.app/Contents/Resources/zoomOutCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Info.plist b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Info.plist
new file mode 100644
index 0000000..826ebdd
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Info.plist
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>BreakpadProduct</key>
+ <string>Chrome_Mac</string>
+ <key>BreakpadProductDisplay</key>
+ <string>Chrome</string>
+ <key>BreakpadReportInterval</key>
+ <string>3600</string>
+ <key>BreakpadSendAndExit</key>
+ <string>YES</string>
+ <key>BreakpadSkipConfirm</key>
+ <string>YES</string>
+ <key>BreakpadURL</key>
+ <string>https://clients2.google.com/cr/report</string>
+ <key>BreakpadVersion</key>
+ <string>3.0.189.0</string>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>gif</string>
+ </array>
+ <key>CFBundleTypeMIMETypes</key>
+ <array>
+ <string>image/gif</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>GIF image</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>GIFf</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>html</string>
+ <string>htm</string>
+ </array>
+ <key>CFBundleTypeMIMETypes</key>
+ <array>
+ <string>text/html</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>HTML document</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>HTML</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>js</string>
+ </array>
+ <key>CFBundleTypeMIMETypes</key>
+ <array>
+ <string>application/x-javascript</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>JavaScript script</string>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>jpg</string>
+ <string>jpeg</string>
+ </array>
+ <key>CFBundleTypeMIMETypes</key>
+ <array>
+ <string>image/jpeg</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>JPEG image</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>JPEG</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>txt</string>
+ <string>text</string>
+ </array>
+ <key>CFBundleTypeMIMETypes</key>
+ <array>
+ <string>text/plain</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>Plain text document</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>TEXT</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>png</string>
+ </array>
+ <key>CFBundleTypeMIMETypes</key>
+ <array>
+ <string>image/png</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>PNG image</string>
+ <key>CFBundleTypeOSTypes</key>
+ <array>
+ <string>PNGf</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ </dict>
+ </array>
+ <key>CFBundleExecutable</key>
+ <string>Google Chrome</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Google Chrome 3.0.189.0, Copyright © 2006-2009 Google Inc. All Rights Reserved.</string>
+ <key>CFBundleIconFile</key>
+ <string>app.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.google.Chrome</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>Chrome</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>3.0.189</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleURLTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleURLName</key>
+ <string>Web site URL</string>
+ <key>CFBundleURLSchemes</key>
+ <array>
+ <string>http</string>
+ <string>https</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleURLName</key>
+ <string>FTP site URL</string>
+ <key>CFBundleURLSchemes</key>
+ <array>
+ <string>ftp</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleURLName</key>
+ <string>Local file URL</string>
+ <key>CFBundleURLSchemes</key>
+ <array>
+ <string>file</string>
+ </array>
+ </dict>
+ </array>
+ <key>CFBundleVersion</key>
+ <string>189.0</string>
+ <key>LSFileQuarantineEnabled</key>
+ <true/>
+ <key>LSMinimumSystemVersion</key>
+ <string>10.5.0</string>
+ <key>LSUIElement</key>
+ <string>1</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright © 2006-2009 Google Inc. All Rights Reserved.</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+ <key>SVNRevision</key>
+ <string>18159</string>
+</dict>
+</plist>
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/MacOS/Google Chrome b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/MacOS/Google Chrome
new file mode 100755
index 0000000..564b248
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/MacOS/Google Chrome
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/PkgInfo b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/PkgInfo
new file mode 100644
index 0000000..bd04210
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/PkgInfo
@@ -0,0 +1 @@
+APPL???? \ No newline at end of file
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/aliasCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/aliasCursor.png
new file mode 100644
index 0000000..d33d7e98
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/aliasCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/app.icns b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/app.icns
new file mode 100644
index 0000000..3362aa8
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/app.icns
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/back.pdf b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/back.pdf
new file mode 100644
index 0000000..0ef6af7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/back.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/cellCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/cellCursor.png
new file mode 100644
index 0000000..5c616c4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/cellCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/chrome.pak b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/chrome.pak
new file mode 100644
index 0000000..8231b77
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/chrome.pak
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/close_bar.pdf b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/close_bar.pdf
new file mode 100644
index 0000000..d2e87e7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/close_bar.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/close_bar_h.pdf b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/close_bar_h.pdf
new file mode 100644
index 0000000..6616ef8
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/close_bar_h.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/close_bar_p.pdf b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/close_bar_p.pdf
new file mode 100644
index 0000000..e2516d2
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/close_bar_p.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/contextMenuCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/contextMenuCursor.png
new file mode 100644
index 0000000..ae100c7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/contextMenuCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/copyCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/copyCursor.png
new file mode 100644
index 0000000..33be332
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/copyCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_inspector b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_inspector
new file mode 100755
index 0000000..10376d8
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_inspector
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Info.plist b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Info.plist
new file mode 100644
index 0000000..7f53db2
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Info.plist
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleDisplayName</key>
+ <string>crash_report_sender</string>
+ <key>CFBundleExecutable</key>
+ <string>crash_report_sender</string>
+ <key>CFBundleIconFile</key>
+ <string>crash_report_sender</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.Breakpad.crash_report_sender</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>crash_report_sender</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSHasLocalizedDisplayName</key>
+ <true/>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/MacOS/crash_report_sender b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/MacOS/crash_report_sender
new file mode 100755
index 0000000..0860edd
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/MacOS/crash_report_sender
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/PkgInfo b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/PkgInfo
new file mode 100644
index 0000000..bd04210
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/PkgInfo
@@ -0,0 +1 @@
+APPL???? \ No newline at end of file
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/Breakpad.nib/classes.nib b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/Breakpad.nib/classes.nib
new file mode 100644
index 0000000..ebc5ab4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/Breakpad.nib/classes.nib
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBClasses</key>
+ <array>
+ <dict>
+ <key>ACTIONS</key>
+ <dict>
+ <key>cancel</key>
+ <string>id</string>
+ <key>sendReport</key>
+ <string>id</string>
+ <key>showPrivacyPolicy</key>
+ <string>id</string>
+ </dict>
+ <key>CLASS</key>
+ <string>Reporter</string>
+ <key>LANGUAGE</key>
+ <string>ObjC</string>
+ <key>OUTLETS</key>
+ <dict>
+ <key>alertWindow_</key>
+ <string>NSWindow</string>
+ <key>cancelButton_</key>
+ <string>NSButton</string>
+ <key>commentMessage_</key>
+ <string>NSTextField</string>
+ <key>dialogTitle_</key>
+ <string>NSTextField</string>
+ <key>emailEntryField_</key>
+ <string>NSView</string>
+ <key>emailLabel_</key>
+ <string>NSTextField</string>
+ <key>emailMessage_</key>
+ <string>NSTextField</string>
+ <key>emailSectionBox_</key>
+ <string>NSBox</string>
+ <key>headerBox_</key>
+ <string>NSBox</string>
+ <key>preEmailBox_</key>
+ <string>NSBox</string>
+ <key>privacyLinkArrow_</key>
+ <string>NSView</string>
+ <key>privacyLinkLabel_</key>
+ <string>NSTextField</string>
+ <key>sendButton_</key>
+ <string>NSButton</string>
+ </dict>
+ <key>SUPERCLASS</key>
+ <string>NSObject</string>
+ </dict>
+ </array>
+ <key>IBVersion</key>
+ <string>1</string>
+</dict>
+</plist>
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/Breakpad.nib/info.nib b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/Breakpad.nib/info.nib
new file mode 100644
index 0000000..21bd631
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/Breakpad.nib/info.nib
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBFramework Version</key>
+ <string>672</string>
+ <key>IBLastKnownRelativeProjectPath</key>
+ <string>../Breakpad.xcodeproj</string>
+ <key>IBOldestOS</key>
+ <integer>5</integer>
+ <key>IBOpenObjects</key>
+ <array>
+ <integer>2</integer>
+ </array>
+ <key>IBSystem Version</key>
+ <string>9G55</string>
+ <key>targetFramework</key>
+ <string>IBCocoaFramework</string>
+</dict>
+</plist>
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/Breakpad.nib/keyedobjects.nib b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/Breakpad.nib/keyedobjects.nib
new file mode 100644
index 0000000..d0cbd3f24
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/Breakpad.nib/keyedobjects.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/English.lproj/Localizable.strings b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/English.lproj/Localizable.strings
new file mode 100644
index 0000000..305cec7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/English.lproj/Localizable.strings
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/crash_report_sender.icns b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/crash_report_sender.icns
new file mode 100644
index 0000000..e8c2124
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crash_report_sender.app/Contents/Resources/crash_report_sender.icns
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crossHairCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crossHairCursor.png
new file mode 100644
index 0000000..2823010
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/crossHairCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/eastResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/eastResizeCursor.png
new file mode 100644
index 0000000..9c1592e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/eastResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/eastWestResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/eastWestResizeCursor.png
new file mode 100644
index 0000000..f43202e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/eastWestResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/About.nib b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/About.nib
new file mode 100644
index 0000000..2e1e441
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/About.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/BrowserWindow.nib b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/BrowserWindow.nib
new file mode 100644
index 0000000..4b5c0a6
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/BrowserWindow.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/ClearBrowsingData.nib b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/ClearBrowsingData.nib
new file mode 100644
index 0000000..a730daa
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/ClearBrowsingData.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/FindBar.nib b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/FindBar.nib
new file mode 100644
index 0000000..9286a99
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/FindBar.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/FirstRunDialog.nib b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/FirstRunDialog.nib
new file mode 100644
index 0000000..9e1cefd
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/FirstRunDialog.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/MainMenu.nib b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/MainMenu.nib
new file mode 100644
index 0000000..83b6ba3
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/MainMenu.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/Preferences.nib b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/Preferences.nib
new file mode 100644
index 0000000..420ce92
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/Preferences.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/SaveAccessoryView.nib b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/SaveAccessoryView.nib
new file mode 100644
index 0000000..de4772c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/SaveAccessoryView.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/TabContents.nib b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/TabContents.nib
new file mode 100644
index 0000000..f687e42
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/TabContents.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/TabView.nib b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/TabView.nib
new file mode 100644
index 0000000..ce960e4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/TabView.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/Toolbar.nib b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/Toolbar.nib
new file mode 100644
index 0000000..024747f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/Toolbar.nib
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/locale.pak b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/locale.pak
new file mode 100644
index 0000000..a85dfee
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/en.lproj/locale.pak
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/forward.pdf b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/forward.pdf
new file mode 100644
index 0000000..c5a47f6
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/forward.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/go.pdf b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/go.pdf
new file mode 100644
index 0000000..a89afe0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/go.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/grow_box.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/grow_box.png
new file mode 100644
index 0000000..8278fec
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/grow_box.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/helpCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/helpCursor.png
new file mode 100644
index 0000000..6828d6a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/helpCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/BottomUpProfileDataGridTree.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/BottomUpProfileDataGridTree.js
new file mode 100644
index 0000000..89b4ddc
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/BottomUpProfileDataGridTree.js
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2009 280 North Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Bottom Up Profiling shows the entire callstack backwards:
+// The root node is a representation of each individual function called, and each child of that node represents
+// a reverse-callstack showing how many of those calls came from it. So, unlike top-down, the statistics in
+// each child still represent the root node. We have to be particularly careful of recursion with this mode
+// because a root node can represent itself AND an ancestor.
+
+WebInspector.BottomUpProfileDataGridTree = function(/*ProfileView*/ aProfileView, /*ProfileNode*/ aProfileNode)
+{
+ WebInspector.ProfileDataGridTree.call(this, aProfileView, aProfileNode);
+
+ // Iterate each node in pre-order.
+ var profileNodeUIDs = 0;
+ var profileNodeGroups = [[], [aProfileNode]];
+ var visitedProfileNodesForCallUID = {};
+
+ this._remainingNodeInfos = [];
+
+ for (var profileNodeGroupIndex = 0; profileNodeGroupIndex < profileNodeGroups.length; ++profileNodeGroupIndex) {
+ var parentProfileNodes = profileNodeGroups[profileNodeGroupIndex];
+ var profileNodes = profileNodeGroups[++profileNodeGroupIndex];
+ var count = profileNodes.length;
+
+ for (var index = 0; index < count; ++index) {
+ var profileNode = profileNodes[index];
+
+ if (!profileNode.UID)
+ profileNode.UID = ++profileNodeUIDs;
+
+ if (profileNode.head && profileNode !== profileNode.head) {
+ // The total time of this ancestor is accounted for if we're in any form of recursive cycle.
+ var visitedNodes = visitedProfileNodesForCallUID[profileNode.callUID];
+ var totalTimeAccountedFor = false;
+
+ if (!visitedNodes) {
+ visitedNodes = {}
+ visitedProfileNodesForCallUID[profileNode.callUID] = visitedNodes;
+ } else {
+ // The total time for this node has already been accounted for iff one of it's parents has already been visited.
+ // We can do this check in this style because we are traversing the tree in pre-order.
+ var parentCount = parentProfileNodes.length;
+ for (var parentIndex = 0; parentIndex < parentCount; ++parentIndex) {
+ if (visitedNodes[parentProfileNodes[parentIndex].UID]) {
+ totalTimeAccountedFor = true;
+ break;
+ }
+ }
+ }
+
+ visitedNodes[profileNode.UID] = true;
+
+ this._remainingNodeInfos.push({ ancestor:profileNode, focusNode:profileNode, totalTimeAccountedFor:totalTimeAccountedFor });
+ }
+
+ var children = profileNode.children;
+ if (children.length) {
+ profileNodeGroups.push(parentProfileNodes.concat([profileNode]))
+ profileNodeGroups.push(children);
+ }
+ }
+ }
+
+ // Populate the top level nodes.
+ WebInspector.BottomUpProfileDataGridNode.prototype._populate.call(this);
+
+ return this;
+}
+
+WebInspector.BottomUpProfileDataGridTree.prototype = {
+ // When focusing, we keep the entire callstack up to this ancestor.
+ focus: function(/*ProfileDataGridNode*/ profileDataGridNode)
+ {
+ if (!profileDataGridNode)
+ return;
+
+ this._save();
+
+ var currentNode = profileDataGridNode;
+ var focusNode = profileDataGridNode;
+
+ while (currentNode.parent && (currentNode instanceof WebInspector.ProfileDataGridNode)) {
+ currentNode._takePropertiesFromProfileDataGridNode(profileDataGridNode);
+
+ focusNode = currentNode;
+ currentNode = currentNode.parent;
+
+ if (currentNode instanceof WebInspector.ProfileDataGridNode)
+ currentNode._keepOnlyChild(focusNode);
+ }
+
+ this.children = [focusNode];
+ this.totalTime = profileDataGridNode.totalTime;
+ },
+
+ exclude: function(/*ProfileDataGridNode*/ profileDataGridNode)
+ {
+ if (!profileDataGridNode)
+ return;
+
+ this._save();
+
+ var excludedCallUID = profileDataGridNode.callUID;
+ var excludedTopLevelChild = this.childrenByCallUID[excludedCallUID];
+
+ // If we have a top level node that is excluded, get rid of it completely (not keeping children),
+ // since bottom up data relies entirely on the root node.
+ if (excludedTopLevelChild)
+ this.children.remove(excludedTopLevelChild);
+
+ var children = this.children;
+ var count = children.length;
+
+ for (var index = 0; index < count; ++index)
+ children[index]._exclude(excludedCallUID);
+
+ if (this.lastComparator)
+ this.sort(this.lastComparator, true);
+ }
+}
+
+WebInspector.BottomUpProfileDataGridTree.prototype.__proto__ = WebInspector.ProfileDataGridTree.prototype;
+
+WebInspector.BottomUpProfileDataGridNode = function(/*ProfileView*/ profileView, /*ProfileNode*/ profileNode, /*BottomUpProfileDataGridTree*/ owningTree)
+{
+ // In bottom up mode, our parents are our children since we display an inverted tree.
+ // However, we don't want to show the very top parent since it is redundant.
+ var hasChildren = !!(profileNode.parent && profileNode.parent.parent);
+
+ WebInspector.ProfileDataGridNode.call(this, profileView, profileNode, owningTree, hasChildren);
+
+ this._remainingNodeInfos = [];
+}
+
+WebInspector.BottomUpProfileDataGridNode.prototype = {
+ _takePropertiesFromProfileDataGridNode: function(/*ProfileDataGridNode*/ profileDataGridNode)
+ {
+ this._save();
+
+ this.selfTime = profileDataGridNode.selfTime;
+ this.totalTime = profileDataGridNode.totalTime;
+ this.numberOfCalls = profileDataGridNode.numberOfCalls;
+ },
+
+ // When focusing, we keep just the members of the callstack.
+ _keepOnlyChild: function(/*ProfileDataGridNode*/ child)
+ {
+ this._save();
+
+ this.removeChildren();
+ this.appendChild(child);
+ },
+
+ _exclude: function(aCallUID)
+ {
+ if (this._remainingNodeInfos)
+ this._populate();
+
+ this._save();
+
+ var children = this.children;
+ var index = this.children.length;
+
+ while (index--)
+ children[index]._exclude(aCallUID);
+
+ var child = this.childrenByCallUID[aCallUID];
+
+ if (child)
+ this._merge(child, true);
+ },
+
+ _merge: function(/*ProfileDataGridNode*/ child, /*Boolean*/ shouldAbsorb)
+ {
+ this.selfTime -= child.selfTime;
+
+ WebInspector.ProfileDataGridNode.prototype._merge.call(this, child, shouldAbsorb);
+ },
+
+ _populate: function(event)
+ {
+ var remainingNodeInfos = this._remainingNodeInfos;
+ var count = remainingNodeInfos.length;
+
+ for (var index = 0; index < count; ++index) {
+ var nodeInfo = remainingNodeInfos[index];
+ var ancestor = nodeInfo.ancestor;
+ var focusNode = nodeInfo.focusNode;
+ var child = this.findChild(ancestor);
+
+ // If we already have this child, then merge the data together.
+ if (child) {
+ var totalTimeAccountedFor = nodeInfo.totalTimeAccountedFor;
+
+ child.selfTime += focusNode.selfTime;
+ child.numberOfCalls += focusNode.numberOfCalls;
+
+ if (!totalTimeAccountedFor)
+ child.totalTime += focusNode.totalTime;
+ } else {
+ // If not, add it as a true ancestor.
+ // In heavy mode, we take our visual identity from ancestor node...
+ var child = new WebInspector.BottomUpProfileDataGridNode(this.profileView, ancestor, this.tree);
+
+ if (ancestor !== focusNode) {
+ // but the actual statistics from the "root" node (bottom of the callstack).
+ child.selfTime = focusNode.selfTime;
+ child.totalTime = focusNode.totalTime;
+ child.numberOfCalls = focusNode.numberOfCalls;
+ }
+
+ this.appendChild(child);
+ }
+
+ var parent = ancestor.parent;
+ if (parent && parent.parent) {
+ nodeInfo.ancestor = parent;
+ child._remainingNodeInfos.push(nodeInfo);
+ }
+ }
+
+ delete this._remainingNodeInfos;
+
+ if (this.removeEventListener)
+ this.removeEventListener("populate", this._populate, this);
+ }
+}
+
+WebInspector.BottomUpProfileDataGridNode.prototype.__proto__ = WebInspector.ProfileDataGridNode.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Breakpoint.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Breakpoint.js
new file mode 100644
index 0000000..8611cf5
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Breakpoint.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Breakpoint = function(url, line, sourceID)
+{
+ this.url = url;
+ this.line = line;
+ this.sourceID = sourceID;
+ this._enabled = true;
+}
+
+WebInspector.Breakpoint.prototype = {
+ get enabled()
+ {
+ return this._enabled;
+ },
+
+ set enabled(x)
+ {
+ if (this._enabled === x)
+ return;
+
+ this._enabled = x;
+
+ if (this._enabled)
+ this.dispatchEventToListeners("enabled");
+ else
+ this.dispatchEventToListeners("disabled");
+ }
+}
+
+WebInspector.Breakpoint.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/BreakpointsSidebarPane.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/BreakpointsSidebarPane.js
new file mode 100644
index 0000000..2b8f3cd
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/BreakpointsSidebarPane.js
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.BreakpointsSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Breakpoints"));
+
+ this.breakpoints = [];
+
+ this.emptyElement = document.createElement("div");
+ this.emptyElement.className = "info";
+ this.emptyElement.textContent = WebInspector.UIString("No Breakpoints");
+
+ this.bodyElement.appendChild(this.emptyElement);
+}
+
+WebInspector.BreakpointsSidebarPane.prototype = {
+ addBreakpoint: function(breakpoint)
+ {
+ this.breakpoints.push(breakpoint);
+ breakpoint.addEventListener("enabled", this._breakpointEnableChanged, this);
+ breakpoint.addEventListener("disabled", this._breakpointEnableChanged, this);
+
+ // FIXME: add to the breakpoints UI.
+
+ if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID)
+ return;
+
+ if (breakpoint.enabled)
+ InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line);
+ },
+
+ removeBreakpoint: function(breakpoint)
+ {
+ this.breakpoints.remove(breakpoint);
+ breakpoint.removeEventListener("enabled", null, this);
+ breakpoint.removeEventListener("disabled", null, this);
+
+ // FIXME: remove from the breakpoints UI.
+
+ if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID)
+ return;
+
+ InspectorController.removeBreakpoint(breakpoint.sourceID, breakpoint.line);
+ },
+
+ _breakpointEnableChanged: function(event)
+ {
+ var breakpoint = event.target;
+
+ // FIXME: change the breakpoint checkbox state in the UI.
+
+ if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID)
+ return;
+
+ if (breakpoint.enabled)
+ InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line);
+ else
+ InspectorController.removeBreakpoint(breakpoint.sourceID, breakpoint.line);
+ }
+}
+
+WebInspector.BreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/CallStackSidebarPane.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/CallStackSidebarPane.js
new file mode 100644
index 0000000..a2c8bed
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/CallStackSidebarPane.js
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.CallStackSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Call Stack"));
+}
+
+WebInspector.CallStackSidebarPane.prototype = {
+ update: function(callFrame, sourceIDMap)
+ {
+ this.bodyElement.removeChildren();
+
+ this.placards = [];
+ delete this._selectedCallFrame;
+
+ if (!callFrame) {
+ var infoElement = document.createElement("div");
+ infoElement.className = "info";
+ infoElement.textContent = WebInspector.UIString("Not Paused");
+ this.bodyElement.appendChild(infoElement);
+ return;
+ }
+
+ var title;
+ var subtitle;
+ var scriptOrResource;
+
+ do {
+ switch (callFrame.type) {
+ case "function":
+ title = callFrame.functionName || WebInspector.UIString("(anonymous function)");
+ break;
+ case "program":
+ title = WebInspector.UIString("(program)");
+ break;
+ }
+
+ scriptOrResource = sourceIDMap[callFrame.sourceID];
+ subtitle = WebInspector.displayNameForURL(scriptOrResource.sourceURL || scriptOrResource.url);
+
+ if (callFrame.line > 0) {
+ if (subtitle)
+ subtitle += ":" + callFrame.line;
+ else
+ subtitle = WebInspector.UIString("line %d", callFrame.line);
+ }
+
+ var placard = new WebInspector.Placard(title, subtitle);
+ placard.callFrame = callFrame;
+
+ placard.element.addEventListener("click", this._placardSelected.bind(this), false);
+
+ this.placards.push(placard);
+ this.bodyElement.appendChild(placard.element);
+
+ callFrame = callFrame.caller;
+ } while (callFrame);
+ },
+
+ get selectedCallFrame()
+ {
+ return this._selectedCallFrame;
+ },
+
+ set selectedCallFrame(x)
+ {
+ if (this._selectedCallFrame === x)
+ return;
+
+ this._selectedCallFrame = x;
+
+ for (var i = 0; i < this.placards.length; ++i) {
+ var placard = this.placards[i];
+ placard.selected = (placard.callFrame === this._selectedCallFrame);
+ }
+
+ this.dispatchEventToListeners("call frame selected");
+ },
+
+ _placardSelected: function(event)
+ {
+ var placardElement = event.target.enclosingNodeOrSelfWithClass("placard");
+ this.selectedCallFrame = placardElement.placard.callFrame;
+ }
+}
+
+WebInspector.CallStackSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Console.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Console.js
new file mode 100644
index 0000000..65cc7d0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Console.js
@@ -0,0 +1,942 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Console = function()
+{
+ this.messages = [];
+
+ WebInspector.View.call(this, document.getElementById("console"));
+
+ this.messagesElement = document.getElementById("console-messages");
+ this.messagesElement.addEventListener("selectstart", this._messagesSelectStart.bind(this), false);
+ this.messagesElement.addEventListener("click", this._messagesClicked.bind(this), true);
+
+ this.promptElement = document.getElementById("console-prompt");
+ this.promptElement.handleKeyEvent = this._promptKeyDown.bind(this);
+ this.prompt = new WebInspector.TextPrompt(this.promptElement, this.completions.bind(this), " .=:[({;");
+
+ this.toggleButton = document.getElementById("console-status-bar-item");
+ this.toggleButton.title = WebInspector.UIString("Show console.");
+ this.toggleButton.addEventListener("click", this._toggleButtonClicked.bind(this), false);
+
+ this.clearButton = document.getElementById("clear-console-status-bar-item");
+ this.clearButton.title = WebInspector.UIString("Clear console log.");
+ this.clearButton.addEventListener("click", this._clearButtonClicked.bind(this), false);
+
+ this.topGroup = new WebInspector.ConsoleGroup(null, 0);
+ this.messagesElement.insertBefore(this.topGroup.element, this.promptElement);
+ this.groupLevel = 0;
+ this.currentGroup = this.topGroup;
+
+ document.getElementById("main-status-bar").addEventListener("mousedown", this._startStatusBarDragging.bind(this), true);
+}
+
+WebInspector.Console.prototype = {
+ show: function()
+ {
+ if (this._animating || this.visible)
+ return;
+
+ WebInspector.View.prototype.show.call(this);
+
+ this._animating = true;
+
+ this.toggleButton.addStyleClass("toggled-on");
+ this.toggleButton.title = WebInspector.UIString("Hide console.");
+
+ document.body.addStyleClass("console-visible");
+
+ var anchoredItems = document.getElementById("anchored-status-bar-items");
+
+ var animations = [
+ {element: document.getElementById("main"), end: {bottom: this.element.offsetHeight}},
+ {element: document.getElementById("main-status-bar"), start: {"padding-left": anchoredItems.offsetWidth - 1}, end: {"padding-left": 0}},
+ {element: document.getElementById("other-console-status-bar-items"), start: {opacity: 0}, end: {opacity: 1}}
+ ];
+
+ var consoleStatusBar = document.getElementById("console-status-bar");
+ consoleStatusBar.insertBefore(anchoredItems, consoleStatusBar.firstChild);
+
+ function animationFinished()
+ {
+ if ("updateStatusBarItems" in WebInspector.currentPanel)
+ WebInspector.currentPanel.updateStatusBarItems();
+ WebInspector.currentFocusElement = this.promptElement;
+ delete this._animating;
+ }
+
+ WebInspector.animateStyle(animations, window.event && window.event.shiftKey ? 2000 : 250, animationFinished.bind(this));
+
+ if (!this.prompt.isCaretInsidePrompt())
+ this.prompt.moveCaretToEndOfPrompt();
+ },
+
+ hide: function()
+ {
+ if (this._animating || !this.visible)
+ return;
+
+ WebInspector.View.prototype.hide.call(this);
+
+ this._animating = true;
+
+ this.toggleButton.removeStyleClass("toggled-on");
+ this.toggleButton.title = WebInspector.UIString("Show console.");
+
+ if (this.element === WebInspector.currentFocusElement || this.element.isAncestor(WebInspector.currentFocusElement))
+ WebInspector.currentFocusElement = WebInspector.previousFocusElement;
+
+ var anchoredItems = document.getElementById("anchored-status-bar-items");
+
+ // Temporally set properties and classes to mimic the post-animation values so panels
+ // like Elements in their updateStatusBarItems call will size things to fit the final location.
+ document.getElementById("main-status-bar").style.setProperty("padding-left", (anchoredItems.offsetWidth - 1) + "px");
+ document.body.removeStyleClass("console-visible");
+ if ("updateStatusBarItems" in WebInspector.currentPanel)
+ WebInspector.currentPanel.updateStatusBarItems();
+ document.body.addStyleClass("console-visible");
+
+ var animations = [
+ {element: document.getElementById("main"), end: {bottom: 0}},
+ {element: document.getElementById("main-status-bar"), start: {"padding-left": 0}, end: {"padding-left": anchoredItems.offsetWidth - 1}},
+ {element: document.getElementById("other-console-status-bar-items"), start: {opacity: 1}, end: {opacity: 0}}
+ ];
+
+ function animationFinished()
+ {
+ var mainStatusBar = document.getElementById("main-status-bar");
+ mainStatusBar.insertBefore(anchoredItems, mainStatusBar.firstChild);
+ mainStatusBar.style.removeProperty("padding-left");
+ document.body.removeStyleClass("console-visible");
+ delete this._animating;
+ }
+
+ WebInspector.animateStyle(animations, window.event && window.event.shiftKey ? 2000 : 250, animationFinished.bind(this));
+ },
+
+ addMessage: function(msg)
+ {
+ if (msg instanceof WebInspector.ConsoleMessage && !(msg instanceof WebInspector.ConsoleCommandResult)) {
+ msg.totalRepeatCount = msg.repeatCount;
+ msg.repeatDelta = msg.repeatCount;
+
+ var messageRepeated = false;
+
+ if (msg.isEqual && msg.isEqual(this.previousMessage)) {
+ // Because sometimes we get a large number of repeated messages and sometimes
+ // we get them one at a time, we need to know the difference between how many
+ // repeats we used to have and how many we have now.
+ msg.repeatDelta -= this.previousMessage.totalRepeatCount;
+
+ if (!isNaN(this.repeatCountBeforeCommand))
+ msg.repeatCount -= this.repeatCountBeforeCommand;
+
+ if (!this.commandSincePreviousMessage) {
+ // Recreate the previous message element to reset the repeat count.
+ var messagesElement = this.currentGroup.messagesElement;
+ messagesElement.removeChild(messagesElement.lastChild);
+ messagesElement.appendChild(msg.toMessageElement());
+
+ messageRepeated = true;
+ }
+ } else
+ delete this.repeatCountBeforeCommand;
+
+ // Increment the error or warning count
+ switch (msg.level) {
+ case WebInspector.ConsoleMessage.MessageLevel.Warning:
+ WebInspector.warnings += msg.repeatDelta;
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Error:
+ WebInspector.errors += msg.repeatDelta;
+ break;
+ }
+
+ // Add message to the resource panel
+ if (msg.url in WebInspector.resourceURLMap) {
+ msg.resource = WebInspector.resourceURLMap[msg.url];
+ if (WebInspector.panels.resources)
+ WebInspector.panels.resources.addMessageToResource(msg.resource, msg);
+ }
+
+ this.commandSincePreviousMessage = false;
+ this.previousMessage = msg;
+
+ if (messageRepeated)
+ return;
+ } else if (msg instanceof WebInspector.ConsoleCommand) {
+ if (this.previousMessage) {
+ this.commandSincePreviousMessage = true;
+ this.repeatCountBeforeCommand = this.previousMessage.totalRepeatCount;
+ }
+ }
+
+ this.messages.push(msg);
+
+ if (msg.level === WebInspector.ConsoleMessage.MessageLevel.EndGroup) {
+ if (this.groupLevel < 1)
+ return;
+
+ this.groupLevel--;
+
+ this.currentGroup = this.currentGroup.parentGroup;
+ } else {
+ if (msg.level === WebInspector.ConsoleMessage.MessageLevel.StartGroup) {
+ this.groupLevel++;
+
+ var group = new WebInspector.ConsoleGroup(this.currentGroup, this.groupLevel);
+ this.currentGroup.messagesElement.appendChild(group.element);
+ this.currentGroup = group;
+ }
+
+ this.currentGroup.addMessage(msg);
+ }
+
+ this.promptElement.scrollIntoView(false);
+ },
+
+ clearMessages: function(clearInspectorController)
+ {
+ if (clearInspectorController)
+ InspectorController.clearMessages();
+ if (WebInspector.panels.resources)
+ WebInspector.panels.resources.clearMessages();
+
+ this.messages = [];
+
+ this.groupLevel = 0;
+ this.currentGroup = this.topGroup;
+ this.topGroup.messagesElement.removeChildren();
+
+ WebInspector.errors = 0;
+ WebInspector.warnings = 0;
+
+ delete this.commandSincePreviousMessage;
+ delete this.repeatCountBeforeCommand;
+ delete this.previousMessage;
+ },
+
+ completions: function(wordRange, bestMatchOnly)
+ {
+ // Pass less stop characters to rangeOfWord so the range will be a more complete expression.
+ const expressionStopCharacters = " =:{;";
+ var expressionRange = wordRange.startContainer.rangeOfWord(wordRange.startOffset, expressionStopCharacters, this.promptElement, "backward");
+ var expressionString = expressionRange.toString();
+ var lastIndex = expressionString.length - 1;
+
+ var dotNotation = (expressionString[lastIndex] === ".");
+ var bracketNotation = (expressionString[lastIndex] === "[");
+
+ if (dotNotation || bracketNotation)
+ expressionString = expressionString.substr(0, lastIndex);
+
+ var prefix = wordRange.toString();
+ if (!expressionString && !prefix)
+ return;
+
+ var result;
+ if (expressionString) {
+ try {
+ result = this._evalInInspectedWindow(expressionString);
+ } catch(e) {
+ // Do nothing, the prefix will be considered a window property.
+ }
+ } else {
+ // There is no expressionString, so the completion should happen against global properties.
+ // Or if the debugger is paused, against properties in scope of the selected call frame.
+ if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused)
+ result = WebInspector.panels.scripts.variablesInScopeForSelectedCallFrame();
+ else
+ result = InspectorController.inspectedWindow();
+ }
+
+ if (bracketNotation) {
+ if (prefix.length && prefix[0] === "'")
+ var quoteUsed = "'";
+ else
+ var quoteUsed = "\"";
+ }
+
+ var results = [];
+ var properties = Object.sortedProperties(result);
+ for (var i = 0; i < properties.length; ++i) {
+ var property = properties[i];
+
+ if (dotNotation && !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(property))
+ continue;
+
+ if (bracketNotation) {
+ if (!/^[0-9]+$/.test(property))
+ property = quoteUsed + property.escapeCharacters(quoteUsed + "\\") + quoteUsed;
+ property += "]";
+ }
+
+ if (property.length < prefix.length)
+ continue;
+ if (property.indexOf(prefix) !== 0)
+ continue;
+
+ results.push(property);
+ if (bestMatchOnly)
+ break;
+ }
+
+ return results;
+ },
+
+ _toggleButtonClicked: function()
+ {
+ this.visible = !this.visible;
+ },
+
+ _clearButtonClicked: function()
+ {
+ this.clearMessages(true);
+ },
+
+ _messagesSelectStart: function(event)
+ {
+ if (this._selectionTimeout)
+ clearTimeout(this._selectionTimeout);
+
+ this.prompt.clearAutoComplete();
+
+ function moveBackIfOutside()
+ {
+ delete this._selectionTimeout;
+ if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed)
+ this.prompt.moveCaretToEndOfPrompt();
+ this.prompt.autoCompleteSoon();
+ }
+
+ this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100);
+ },
+
+ _messagesClicked: function(event)
+ {
+ var link = event.target.enclosingNodeOrSelfWithNodeName("a");
+ if (!link || !link.representedNode)
+ return;
+
+ WebInspector.updateFocusedNode(link.representedNode);
+ event.stopPropagation();
+ event.preventDefault();
+ },
+
+ _promptKeyDown: function(event)
+ {
+ switch (event.keyIdentifier) {
+ case "Enter":
+ this._enterKeyPressed(event);
+ return;
+ }
+
+ this.prompt.handleKeyEvent(event);
+ },
+
+ _startStatusBarDragging: function(event)
+ {
+ if (!this.visible || event.target !== document.getElementById("main-status-bar"))
+ return;
+
+ WebInspector.elementDragStart(document.getElementById("main-status-bar"), this._statusBarDragging.bind(this), this._endStatusBarDragging.bind(this), event, "row-resize");
+
+ this._statusBarDragOffset = event.pageY - this.element.totalOffsetTop;
+
+ event.stopPropagation();
+ },
+
+ _statusBarDragging: function(event)
+ {
+ var mainElement = document.getElementById("main");
+
+ var height = window.innerHeight - event.pageY + this._statusBarDragOffset;
+ height = Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - mainElement.totalOffsetTop - Preferences.minConsoleHeight);
+
+ mainElement.style.bottom = height + "px";
+ this.element.style.height = height + "px";
+
+ event.preventDefault();
+ event.stopPropagation();
+ },
+
+ _endStatusBarDragging: function(event)
+ {
+ WebInspector.elementDragEnd(event);
+
+ delete this._statusBarDragOffset;
+
+ event.stopPropagation();
+ },
+
+ _evalInInspectedWindow: function(expression)
+ {
+ if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused)
+ return WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression);
+
+ var inspectedWindow = InspectorController.inspectedWindow();
+ if (!inspectedWindow._inspectorCommandLineAPI) {
+ inspectedWindow.eval("window._inspectorCommandLineAPI = { \
+ $: function() { return document.getElementById.apply(document, arguments) }, \
+ $$: function() { return document.querySelectorAll.apply(document, arguments) }, \
+ $x: function(xpath, context) { \
+ var nodes = []; \
+ try { \
+ var doc = context || document; \
+ var results = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null); \
+ var node; \
+ while (node = results.iterateNext()) nodes.push(node); \
+ } catch (e) {} \
+ return nodes; \
+ }, \
+ dir: function() { return console.dir.apply(console, arguments) }, \
+ dirxml: function() { return console.dirxml.apply(console, arguments) }, \
+ keys: function(o) { var a = []; for (k in o) a.push(k); return a; }, \
+ values: function(o) { var a = []; for (k in o) a.push(o[k]); return a; }, \
+ profile: function() { return console.profile.apply(console, arguments) }, \
+ profileEnd: function() { return console.profileEnd.apply(console, arguments) } \
+ };");
+
+ inspectedWindow._inspectorCommandLineAPI.clear = InspectorController.wrapCallback(this.clearMessages.bind(this));
+ }
+
+ // Surround the expression in with statements to inject our command line API so that
+ // the window object properties still take more precedent than our API functions.
+ expression = "with (window._inspectorCommandLineAPI) { with (window) { " + expression + " } }";
+
+ return inspectedWindow.eval(expression);
+ },
+
+ _enterKeyPressed: function(event)
+ {
+ if (event.altKey)
+ return;
+
+ event.preventDefault();
+ event.stopPropagation();
+
+ this.prompt.clearAutoComplete(true);
+
+ var str = this.prompt.text;
+ if (!str.length)
+ return;
+
+ var commandMessage = new WebInspector.ConsoleCommand(str);
+ this.addMessage(commandMessage);
+
+ var result;
+ var exception = false;
+ try {
+ result = this._evalInInspectedWindow(str);
+ } catch(e) {
+ result = e;
+ exception = true;
+ }
+
+ this.prompt.history.push(str);
+ this.prompt.historyOffset = 0;
+ this.prompt.text = "";
+
+ this.addMessage(new WebInspector.ConsoleCommandResult(result, exception, commandMessage));
+ },
+
+ _format: function(output, forceObjectFormat)
+ {
+ var type = (forceObjectFormat ? "object" : Object.type(output, InspectorController.inspectedWindow()));
+
+ // We don't perform any special formatting on these types, so we just
+ // pass them through the simple _formatvalue function.
+ var undecoratedTypes = {
+ "undefined": 1,
+ "null": 1,
+ "boolean": 1,
+ "number": 1,
+ "date": 1,
+ "function": 1,
+ };
+
+ var formatter;
+ if (forceObjectFormat)
+ formatter = "_formatobject";
+ else if (type in undecoratedTypes)
+ formatter = "_formatvalue";
+ else {
+ formatter = "_format" + type;
+ if (!(formatter in this)) {
+ formatter = "_formatobject";
+ type = "object";
+ }
+ }
+
+ var span = document.createElement("span");
+ span.addStyleClass("console-formatted-" + type);
+ this[formatter](output, span);
+ return span;
+ },
+
+ _formatvalue: function(val, elem)
+ {
+ elem.appendChild(document.createTextNode(val));
+ },
+
+ _formatstring: function(str, elem)
+ {
+ elem.appendChild(document.createTextNode("\"" + str + "\""));
+ },
+
+ _formatregexp: function(re, elem)
+ {
+ var formatted = String(re).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1);
+ elem.appendChild(document.createTextNode(formatted));
+ },
+
+ _formatarray: function(arr, elem)
+ {
+ elem.appendChild(document.createTextNode("["));
+ for (var i = 0; i < arr.length; ++i) {
+ elem.appendChild(this._format(arr[i]));
+ if (i < arr.length - 1)
+ elem.appendChild(document.createTextNode(", "));
+ }
+ elem.appendChild(document.createTextNode("]"));
+ },
+
+ _formatnode: function(node, elem)
+ {
+ var treeOutline = new WebInspector.ElementsTreeOutline();
+ treeOutline.rootDOMNode = node;
+ treeOutline.element.addStyleClass("outline-disclosure");
+ if (!treeOutline.children[0].hasChildren)
+ treeOutline.element.addStyleClass("single-node");
+ elem.appendChild(treeOutline.element);
+ },
+
+ _formatobject: function(obj, elem)
+ {
+ elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, null, null, null, true).element);
+ },
+
+ _formaterror: function(obj, elem)
+ {
+ var messageElement = document.createElement("span");
+ messageElement.className = "error-message";
+ messageElement.textContent = obj.name + ": " + obj.message;
+ elem.appendChild(messageElement);
+
+ if (obj.sourceURL) {
+ var urlElement = document.createElement("a");
+ urlElement.className = "webkit-html-resource-link";
+ urlElement.href = obj.sourceURL;
+ urlElement.lineNumber = obj.line;
+ urlElement.preferredPanel = "scripts";
+
+ if (obj.line > 0)
+ urlElement.textContent = WebInspector.displayNameForURL(obj.sourceURL) + ":" + obj.line;
+ else
+ urlElement.textContent = WebInspector.displayNameForURL(obj.sourceURL);
+
+ elem.appendChild(document.createTextNode(" ("));
+ elem.appendChild(urlElement);
+ elem.appendChild(document.createTextNode(")"));
+ }
+ },
+}
+
+WebInspector.Console.prototype.__proto__ = WebInspector.View.prototype;
+
+WebInspector.ConsoleMessage = function(source, level, line, url, groupLevel, repeatCount)
+{
+ this.source = source;
+ this.level = level;
+ this.line = line;
+ this.url = url;
+ this.groupLevel = groupLevel;
+ this.repeatCount = repeatCount;
+ if (arguments.length > 6)
+ this.setMessageBody(Array.prototype.slice.call(arguments, 6));
+}
+
+WebInspector.ConsoleMessage.prototype = {
+ setMessageBody: function(args)
+ {
+ switch (this.level) {
+ case WebInspector.ConsoleMessage.MessageLevel.Trace:
+ var span = document.createElement("span");
+ span.addStyleClass("console-formatted-trace");
+ var stack = Array.prototype.slice.call(args);
+ var funcNames = stack.map(function(f) {
+ return f || WebInspector.UIString("(anonymous function)");
+ });
+ span.appendChild(document.createTextNode(funcNames.join("\n")));
+ this.formattedMessage = span;
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Object:
+ this.formattedMessage = this._format(["%O", args[0]]);
+ break;
+ default:
+ this.formattedMessage = this._format(args);
+ break;
+ }
+
+ // This is used for inline message bubbles in SourceFrames, or other plain-text representations.
+ this.message = this.formattedMessage.textContent;
+ },
+
+ isErrorOrWarning: function()
+ {
+ return (this.level === WebInspector.ConsoleMessage.MessageLevel.Warning || this.level === WebInspector.ConsoleMessage.MessageLevel.Error);
+ },
+
+ _format: function(parameters)
+ {
+ var formattedResult = document.createElement("span");
+
+ if (!parameters.length)
+ return formattedResult;
+
+ function formatForConsole(obj)
+ {
+ return WebInspector.console._format(obj);
+ }
+
+ function formatAsObjectForConsole(obj)
+ {
+ return WebInspector.console._format(obj, true);
+ }
+
+ if (Object.type(parameters[0], InspectorController.inspectedWindow()) === "string") {
+ var formatters = {}
+ for (var i in String.standardFormatters)
+ formatters[i] = String.standardFormatters[i];
+
+ // Firebug uses %o for formatting objects.
+ formatters.o = formatForConsole;
+ // Firebug allows both %i and %d for formatting integers.
+ formatters.i = formatters.d;
+ // Support %O to force object formating, instead of the type-based %o formatting.
+ formatters.O = formatAsObjectForConsole;
+
+ function append(a, b)
+ {
+ if (!(b instanceof Node))
+ a.appendChild(WebInspector.linkifyStringAsFragment(b.toString()));
+ else
+ a.appendChild(b);
+ return a;
+ }
+
+ var result = String.format(parameters[0], parameters.slice(1), formatters, formattedResult, append);
+ formattedResult = result.formattedResult;
+ parameters = result.unusedSubstitutions;
+ if (parameters.length)
+ formattedResult.appendChild(document.createTextNode(" "));
+ }
+
+ for (var i = 0; i < parameters.length; ++i) {
+ if (typeof parameters[i] === "string")
+ formattedResult.appendChild(WebInspector.linkifyStringAsFragment(parameters[i]));
+ else
+ formattedResult.appendChild(formatForConsole(parameters[i]));
+
+ if (i < parameters.length - 1)
+ formattedResult.appendChild(document.createTextNode(" "));
+ }
+
+ return formattedResult;
+ },
+
+ toMessageElement: function()
+ {
+ if (this.propertiesSection)
+ return this.propertiesSection.element;
+
+ var element = document.createElement("div");
+ element.message = this;
+ element.className = "console-message";
+
+ switch (this.source) {
+ case WebInspector.ConsoleMessage.MessageSource.HTML:
+ element.addStyleClass("console-html-source");
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.WML:
+ element.addStyleClass("console-wml-source");
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.XML:
+ element.addStyleClass("console-xml-source");
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.JS:
+ element.addStyleClass("console-js-source");
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.CSS:
+ element.addStyleClass("console-css-source");
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.Other:
+ element.addStyleClass("console-other-source");
+ break;
+ }
+
+ switch (this.level) {
+ case WebInspector.ConsoleMessage.MessageLevel.Tip:
+ element.addStyleClass("console-tip-level");
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Log:
+ element.addStyleClass("console-log-level");
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Warning:
+ element.addStyleClass("console-warning-level");
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Error:
+ element.addStyleClass("console-error-level");
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.StartGroup:
+ element.addStyleClass("console-group-title-level");
+ }
+
+ if (this.elementsTreeOutline) {
+ element.addStyleClass("outline-disclosure");
+ element.appendChild(this.elementsTreeOutline.element);
+ return element;
+ }
+
+ if (this.repeatCount > 1) {
+ var messageRepeatCountElement = document.createElement("span");
+ messageRepeatCountElement.className = "bubble";
+ messageRepeatCountElement.textContent = this.repeatCount;
+
+ element.appendChild(messageRepeatCountElement);
+ element.addStyleClass("repeated-message");
+ }
+
+ if (this.url && this.url !== "undefined") {
+ var urlElement = document.createElement("a");
+ urlElement.className = "console-message-url webkit-html-resource-link";
+ urlElement.href = this.url;
+ urlElement.lineNumber = this.line;
+
+ if (this.source === WebInspector.ConsoleMessage.MessageSource.JS)
+ urlElement.preferredPanel = "scripts";
+
+ if (this.line > 0)
+ urlElement.textContent = WebInspector.displayNameForURL(this.url) + ":" + this.line;
+ else
+ urlElement.textContent = WebInspector.displayNameForURL(this.url);
+
+ element.appendChild(urlElement);
+ }
+
+ var messageTextElement = document.createElement("span");
+ messageTextElement.className = "console-message-text";
+ messageTextElement.appendChild(this.formattedMessage);
+ element.appendChild(messageTextElement);
+
+ return element;
+ },
+
+ toString: function()
+ {
+ var sourceString;
+ switch (this.source) {
+ case WebInspector.ConsoleMessage.MessageSource.HTML:
+ sourceString = "HTML";
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.WML:
+ sourceString = "WML";
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.XML:
+ sourceString = "XML";
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.JS:
+ sourceString = "JS";
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.CSS:
+ sourceString = "CSS";
+ break;
+ case WebInspector.ConsoleMessage.MessageSource.Other:
+ sourceString = "Other";
+ break;
+ }
+
+ var levelString;
+ switch (this.level) {
+ case WebInspector.ConsoleMessage.MessageLevel.Tip:
+ levelString = "Tip";
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Log:
+ levelString = "Log";
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Warning:
+ levelString = "Warning";
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Error:
+ levelString = "Error";
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Object:
+ levelString = "Object";
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Trace:
+ levelString = "Trace";
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.StartGroup:
+ levelString = "Start Group";
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.EndGroup:
+ levelString = "End Group";
+ break;
+ }
+
+ return sourceString + " " + levelString + ": " + this.formattedMessage.textContent + "\n" + this.url + " line " + this.line;
+ },
+
+ isEqual: function(msg, disreguardGroup)
+ {
+ if (!msg)
+ return false;
+
+ var ret = (this.source == msg.source)
+ && (this.level == msg.level)
+ && (this.line == msg.line)
+ && (this.url == msg.url)
+ && (this.message == msg.message);
+
+ return (disreguardGroup ? ret : (ret && (this.groupLevel == msg.groupLevel)));
+ }
+}
+
+// Note: Keep these constants in sync with the ones in Console.h
+WebInspector.ConsoleMessage.MessageSource = {
+ HTML: 0,
+ WML: 1,
+ XML: 2,
+ JS: 3,
+ CSS: 4,
+ Other: 5
+}
+
+WebInspector.ConsoleMessage.MessageLevel = {
+ Tip: 0,
+ Log: 1,
+ Warning: 2,
+ Error: 3,
+ Object: 4,
+ Trace: 5,
+ StartGroup: 6,
+ EndGroup: 7
+}
+
+WebInspector.ConsoleCommand = function(command)
+{
+ this.command = command;
+}
+
+WebInspector.ConsoleCommand.prototype = {
+ toMessageElement: function()
+ {
+ var element = document.createElement("div");
+ element.command = this;
+ element.className = "console-user-command";
+
+ var commandTextElement = document.createElement("span");
+ commandTextElement.className = "console-message-text";
+ commandTextElement.textContent = this.command;
+ element.appendChild(commandTextElement);
+
+ return element;
+ }
+}
+
+WebInspector.ConsoleCommandResult = function(result, exception, originatingCommand)
+{
+ var level = (exception ? WebInspector.ConsoleMessage.MessageLevel.Error : WebInspector.ConsoleMessage.MessageLevel.Log);
+ var message = (exception ? String(result) : result);
+ var line = (exception ? result.line : -1);
+ var url = (exception ? result.sourceURL : null);
+
+ WebInspector.ConsoleMessage.call(this, WebInspector.ConsoleMessage.MessageSource.JS, level, line, url, null, 1, message);
+
+ this.originatingCommand = originatingCommand;
+}
+
+WebInspector.ConsoleCommandResult.prototype = {
+ toMessageElement: function()
+ {
+ var element = WebInspector.ConsoleMessage.prototype.toMessageElement.call(this);
+ element.addStyleClass("console-user-command-result");
+ return element;
+ }
+}
+
+WebInspector.ConsoleCommandResult.prototype.__proto__ = WebInspector.ConsoleMessage.prototype;
+
+WebInspector.ConsoleGroup = function(parentGroup, level)
+{
+ this.parentGroup = parentGroup;
+ this.level = level;
+
+ var element = document.createElement("div");
+ element.className = "console-group";
+ element.group = this;
+ this.element = element;
+
+ var messagesElement = document.createElement("div");
+ messagesElement.className = "console-group-messages";
+ element.appendChild(messagesElement);
+ this.messagesElement = messagesElement;
+}
+
+WebInspector.ConsoleGroup.prototype = {
+ addMessage: function(msg)
+ {
+ var element = msg.toMessageElement();
+
+ if (msg.level === WebInspector.ConsoleMessage.MessageLevel.StartGroup) {
+ this.messagesElement.parentNode.insertBefore(element, this.messagesElement);
+ element.addEventListener("click", this._titleClicked.bind(this), true);
+ } else
+ this.messagesElement.appendChild(element);
+
+ if (element.previousSibling && msg.originatingCommand && element.previousSibling.command === msg.originatingCommand)
+ element.previousSibling.addStyleClass("console-adjacent-user-command-result");
+ },
+
+ _titleClicked: function(event)
+ {
+ var groupTitleElement = event.target.enclosingNodeOrSelfWithClass("console-group-title-level");
+ if (groupTitleElement) {
+ var groupElement = groupTitleElement.enclosingNodeOrSelfWithClass("console-group");
+ if (groupElement)
+ if (groupElement.hasStyleClass("collapsed"))
+ groupElement.removeStyleClass("collapsed");
+ else
+ groupElement.addStyleClass("collapsed");
+ groupTitleElement.scrollIntoViewIfNeeded(true);
+ }
+
+ event.stopPropagation();
+ event.preventDefault();
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DataGrid.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DataGrid.js
new file mode 100644
index 0000000..2fcb08c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DataGrid.js
@@ -0,0 +1,885 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DataGrid = function(columns)
+{
+ this.element = document.createElement("div");
+ this.element.className = "data-grid";
+ this.element.tabIndex = 0;
+ this.element.addEventListener("keydown", this._keyDown.bind(this), false);
+
+ this._headerTable = document.createElement("table");
+ this._headerTable.className = "header";
+
+ this._dataTable = document.createElement("table");
+ this._dataTable.className = "data";
+
+ this._dataTable.addEventListener("mousedown", this._mouseDownInDataTable.bind(this), true);
+ this._dataTable.addEventListener("click", this._clickInDataTable.bind(this), true);
+
+ var scrollContainer = document.createElement("div");
+ scrollContainer.className = "data-container";
+ scrollContainer.appendChild(this._dataTable);
+
+ this.element.appendChild(this._headerTable);
+ this.element.appendChild(scrollContainer);
+
+ var headerRow = document.createElement("tr");
+ var columnGroup = document.createElement("colgroup");
+ var columnCount = 0;
+
+ for (var columnIdentifier in columns) {
+ var column = columns[columnIdentifier];
+ if (column.disclosure)
+ this.disclosureColumnIdentifier = columnIdentifier;
+
+ var col = document.createElement("col");
+ if (column.width)
+ col.style.width = column.width;
+ columnGroup.appendChild(col);
+
+ var cell = document.createElement("th");
+ cell.className = columnIdentifier + "-column";
+ cell.columnIdentifier = columnIdentifier;
+
+ var div = document.createElement("div");
+ div.textContent = column.title;
+ cell.appendChild(div);
+
+ if (column.sort) {
+ cell.addStyleClass("sort-" + column.sort);
+ this._sortColumnCell = cell;
+ }
+
+ if (column.sortable) {
+ cell.addEventListener("click", this._clickInHeaderCell.bind(this), false);
+ cell.addStyleClass("sortable");
+ }
+
+ headerRow.appendChild(cell);
+
+ ++columnCount;
+ }
+
+ columnGroup.span = columnCount;
+
+ var cell = document.createElement("th");
+ cell.className = "corner";
+ headerRow.appendChild(cell);
+
+ this._headerTable.appendChild(columnGroup);
+ this.headerTableBody.appendChild(headerRow);
+
+ var fillerRow = document.createElement("tr");
+ fillerRow.className = "filler";
+
+ for (var i = 0; i < columnCount; ++i) {
+ var cell = document.createElement("td");
+ fillerRow.appendChild(cell);
+ }
+
+ this._dataTable.appendChild(columnGroup.cloneNode(true));
+ this.dataTableBody.appendChild(fillerRow);
+
+ this.columns = columns || {};
+ this.children = [];
+ this.selectedNode = null;
+ this.expandNodesWhenArrowing = false;
+ this.root = true;
+ this.hasChildren = false;
+ this.expanded = true;
+ this.revealed = true;
+ this.selected = false;
+ this.dataGrid = this;
+ this.indentWidth = 15;
+}
+
+WebInspector.DataGrid.prototype = {
+ get sortColumnIdentifier()
+ {
+ if (!this._sortColumnCell)
+ return null;
+ return this._sortColumnCell.columnIdentifier;
+ },
+
+ get sortOrder()
+ {
+ if (!this._sortColumnCell || this._sortColumnCell.hasStyleClass("sort-ascending"))
+ return "ascending";
+ if (this._sortColumnCell.hasStyleClass("sort-descending"))
+ return "descending";
+ return null;
+ },
+
+ get headerTableBody()
+ {
+ if ("_headerTableBody" in this)
+ return this._headerTableBody;
+
+ this._headerTableBody = this._headerTable.getElementsByTagName("tbody")[0];
+ if (!this._headerTableBody) {
+ this._headerTableBody = this.element.ownerDocument.createElement("tbody");
+ this._headerTable.insertBefore(this._headerTableBody, this._headerTable.tFoot);
+ }
+
+ return this._headerTableBody;
+ },
+
+ get dataTableBody()
+ {
+ if ("_dataTableBody" in this)
+ return this._dataTableBody;
+
+ this._dataTableBody = this._dataTable.getElementsByTagName("tbody")[0];
+ if (!this._dataTableBody) {
+ this._dataTableBody = this.element.ownerDocument.createElement("tbody");
+ this._dataTable.insertBefore(this._dataTableBody, this._dataTable.tFoot);
+ }
+
+ return this._dataTableBody;
+ },
+
+ appendChild: function(child)
+ {
+ this.insertChild(child, this.children.length);
+ },
+
+ insertChild: function(child, index)
+ {
+ if (!child)
+ throw("insertChild: Node can't be undefined or null.");
+ if (child.parent === this)
+ throw("insertChild: Node is already a child of this node.");
+
+ if (child.parent)
+ child.parent.removeChild(child);
+
+ this.children.splice(index, 0, child);
+ this.hasChildren = true;
+
+ child.parent = this;
+ child.dataGrid = this.dataGrid;
+ child._recalculateSiblings(index);
+
+ delete child._depth;
+ delete child._revealed;
+ delete child._attached;
+
+ var current = child.children[0];
+ while (current) {
+ current.dataGrid = this.dataGrid;
+ delete current._depth;
+ delete current._revealed;
+ delete current._attached;
+ current = current.traverseNextNode(false, child, true);
+ }
+
+ if (this.expanded)
+ child._attach();
+ },
+
+ removeChild: function(child)
+ {
+ if (!child)
+ throw("removeChild: Node can't be undefined or null.");
+ if (child.parent !== this)
+ throw("removeChild: Node is not a child of this node.");
+
+ child.deselect();
+
+ this.children.remove(child, true);
+
+ if (child.previousSibling)
+ child.previousSibling.nextSibling = child.nextSibling;
+ if (child.nextSibling)
+ child.nextSibling.previousSibling = child.previousSibling;
+
+ child.dataGrid = null;
+ child.parent = null;
+ child.nextSibling = null;
+ child.previousSibling = null;
+
+ if (this.children.length <= 0)
+ this.hasChildren = false;
+ },
+
+ removeChildren: function()
+ {
+ for (var i = 0; i < this.children.length; ++i) {
+ var child = this.children[i];
+ child.deselect();
+ child._detach();
+
+ child.dataGrid = null;
+ child.parent = null;
+ child.nextSibling = null;
+ child.previousSibling = null;
+ }
+
+ this.children = [];
+ this.hasChildren = false;
+ },
+
+ removeChildrenRecursive: function()
+ {
+ var childrenToRemove = this.children;
+
+ var child = this.children[0];
+ while (child) {
+ if (child.children.length)
+ childrenToRemove = childrenToRemove.concat(child.children);
+ child = child.traverseNextNode(false, this, true);
+ }
+
+ for (var i = 0; i < childrenToRemove.length; ++i) {
+ var child = childrenToRemove[i];
+ child.deselect();
+ child._detach();
+
+ child.children = [];
+ child.dataGrid = null;
+ child.parent = null;
+ child.nextSibling = null;
+ child.previousSibling = null;
+ }
+
+ this.children = [];
+ },
+
+ handleKeyEvent: function(event)
+ {
+ if (!this.selectedNode || event.shiftKey || event.metaKey || event.ctrlKey)
+ return false;
+
+ var handled = false;
+ var nextSelectedNode;
+ if (event.keyIdentifier === "Up" && !event.altKey) {
+ nextSelectedNode = this.selectedNode.traversePreviousNode(true);
+ while (nextSelectedNode && !nextSelectedNode.selectable)
+ nextSelectedNode = nextSelectedNode.traversePreviousNode(!this.expandTreeNodesWhenArrowing);
+ handled = nextSelectedNode ? true : false;
+ } else if (event.keyIdentifier === "Down" && !event.altKey) {
+ nextSelectedNode = this.selectedNode.traverseNextNode(true);
+ while (nextSelectedNode && !nextSelectedNode.selectable)
+ nextSelectedNode = nextSelectedNode.traverseNextNode(!this.expandTreeNodesWhenArrowing);
+ handled = nextSelectedNode ? true : false;
+ } else if (event.keyIdentifier === "Left") {
+ if (this.selectedNode.expanded) {
+ if (event.altKey)
+ this.selectedNode.collapseRecursively();
+ else
+ this.selectedNode.collapse();
+ handled = true;
+ } else if (this.selectedNode.parent && !this.selectedNode.parent.root) {
+ handled = true;
+ if (this.selectedNode.parent.selectable) {
+ nextSelectedNode = this.selectedNode.parent;
+ handled = nextSelectedNode ? true : false;
+ } else if (this.selectedNode.parent)
+ this.selectedNode.parent.collapse();
+ }
+ } else if (event.keyIdentifier === "Right") {
+ if (!this.selectedNode.revealed) {
+ this.selectedNode.reveal();
+ handled = true;
+ } else if (this.selectedNode.hasChildren) {
+ handled = true;
+ if (this.selectedNode.expanded) {
+ nextSelectedNode = this.selectedNode.children[0];
+ handled = nextSelectedNode ? true : false;
+ } else {
+ if (event.altKey)
+ this.selectedNode.expandRecursively();
+ else
+ this.selectedNode.expand();
+ }
+ }
+ }
+
+ if (nextSelectedNode) {
+ nextSelectedNode.reveal();
+ nextSelectedNode.select();
+ }
+
+ if (handled) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+
+ return handled;
+ },
+
+ expand: function()
+ {
+ // This is the root, do nothing.
+ },
+
+ collapse: function()
+ {
+ // This is the root, do nothing.
+ },
+
+ reveal: function()
+ {
+ // This is the root, do nothing.
+ },
+
+ dataGridNodeFromEvent: function(event)
+ {
+ var rowElement = event.target.enclosingNodeOrSelfWithNodeName("tr");
+ return rowElement._dataGridNode;
+ },
+
+ dataGridNodeFromPoint: function(x, y)
+ {
+ var node = this._dataTable.ownerDocument.elementFromPoint(x, y);
+ var rowElement = node.enclosingNodeOrSelfWithNodeName("tr");
+ return rowElement._dataGridNode;
+ },
+
+ _keyDown: function(event)
+ {
+ this.handleKeyEvent(event);
+ },
+
+ _clickInHeaderCell: function(event)
+ {
+ var cell = event.target.enclosingNodeOrSelfWithNodeName("th");
+ if (!cell || !cell.columnIdentifier || !cell.hasStyleClass("sortable"))
+ return;
+
+ var sortOrder = this.sortOrder;
+
+ if (this._sortColumnCell) {
+ this._sortColumnCell.removeStyleClass("sort-ascending");
+ this._sortColumnCell.removeStyleClass("sort-descending");
+ }
+
+ if (cell == this._sortColumnCell) {
+ if (sortOrder == "ascending")
+ sortOrder = "descending";
+ else
+ sortOrder = "ascending";
+ }
+
+ this._sortColumnCell = cell;
+
+ cell.addStyleClass("sort-" + sortOrder);
+
+ this.dispatchEventToListeners("sorting changed");
+ },
+
+ _mouseDownInDataTable: function(event)
+ {
+ var gridNode = this.dataGridNodeFromEvent(event);
+ if (!gridNode || !gridNode.selectable)
+ return;
+
+ if (gridNode.isEventWithinDisclosureTriangle(event))
+ return;
+
+ if (event.metaKey) {
+ if (gridNode.selected)
+ gridNode.deselect();
+ else
+ gridNode.select();
+ } else
+ gridNode.select();
+ },
+
+ _clickInDataTable: function(event)
+ {
+ var gridNode = this.dataGridNodeFromEvent(event);
+ if (!gridNode || !gridNode.hasChildren)
+ return;
+
+ if (!gridNode.isEventWithinDisclosureTriangle(event))
+ return;
+
+ if (gridNode.expanded) {
+ if (event.altKey)
+ gridNode.collapseRecursively();
+ else
+ gridNode.collapse();
+ } else {
+ if (event.altKey)
+ gridNode.expandRecursively();
+ else
+ gridNode.expand();
+ }
+ }
+}
+
+WebInspector.DataGrid.prototype.__proto__ = WebInspector.Object.prototype;
+
+WebInspector.DataGridNode = function(data, hasChildren)
+{
+ this._expanded = false;
+ this._selected = false;
+ this._shouldRefreshChildren = true;
+ this._data = data || {};
+ this.hasChildren = hasChildren || false;
+ this.children = [];
+ this.dataGrid = null;
+ this.parent = null;
+ this.previousSibling = null;
+ this.nextSibling = null;
+ this.disclosureToggleWidth = 10;
+}
+
+WebInspector.DataGridNode.prototype = {
+ selectable: true,
+
+ get element()
+ {
+ if (this._element)
+ return this._element;
+
+ if (!this.dataGrid)
+ return null;
+
+ this._element = document.createElement("tr");
+ this._element._dataGridNode = this;
+
+ if (this.hasChildren)
+ this._element.addStyleClass("parent");
+ if (this.expanded)
+ this._element.addStyleClass("expanded");
+ if (this.selected)
+ this._element.addStyleClass("selected");
+ if (this.revealed)
+ this._element.addStyleClass("revealed");
+
+ for (var columnIdentifier in this.dataGrid.columns) {
+ var cell = this.createCell(columnIdentifier);
+ this._element.appendChild(cell);
+ }
+
+ return this._element;
+ },
+
+ get data()
+ {
+ return this._data;
+ },
+
+ set data(x)
+ {
+ this._data = x || {};
+ this.refresh();
+ },
+
+ get revealed()
+ {
+ if ("_revealed" in this)
+ return this._revealed;
+
+ var currentAncestor = this.parent;
+ while (currentAncestor && !currentAncestor.root) {
+ if (!currentAncestor.expanded) {
+ this._revealed = false;
+ return false;
+ }
+
+ currentAncestor = currentAncestor.parent;
+ }
+
+ this._revealed = true;
+ return true;
+ },
+
+ set hasChildren(x)
+ {
+ if (this._hasChildren === x)
+ return;
+
+ this._hasChildren = x;
+
+ if (!this._element)
+ return;
+
+ if (this._hasChildren)
+ {
+ this._element.addStyleClass("parent");
+ if (this.expanded)
+ this._element.addStyleClass("expanded");
+ }
+ else
+ {
+ this._element.removeStyleClass("parent");
+ this._element.removeStyleClass("expanded");
+ }
+ },
+
+ get hasChildren()
+ {
+ return this._hasChildren;
+ },
+
+ set revealed(x)
+ {
+ if (this._revealed === x)
+ return;
+
+ this._revealed = x;
+
+ if (this._element) {
+ if (this._revealed)
+ this._element.addStyleClass("revealed");
+ else
+ this._element.removeStyleClass("revealed");
+ }
+
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i].revealed = x && this.expanded;
+ },
+
+ get depth()
+ {
+ if ("_depth" in this)
+ return this._depth;
+ if (this.parent && !this.parent.root)
+ this._depth = this.parent.depth + 1;
+ else
+ this._depth = 0;
+ return this._depth;
+ },
+
+ get shouldRefreshChildren()
+ {
+ return this._shouldRefreshChildren;
+ },
+
+ set shouldRefreshChildren(x)
+ {
+ this._shouldRefreshChildren = x;
+ if (x && this.expanded)
+ this.expand();
+ },
+
+ get selected()
+ {
+ return this._selected;
+ },
+
+ set selected(x)
+ {
+ if (x)
+ this.select();
+ else
+ this.deselect();
+ },
+
+ get expanded()
+ {
+ return this._expanded;
+ },
+
+ set expanded(x)
+ {
+ if (x)
+ this.expand();
+ else
+ this.collapse();
+ },
+
+ refresh: function()
+ {
+ if (!this._element || !this.dataGrid)
+ return;
+
+ this._element.removeChildren();
+
+ for (var columnIdentifier in this.dataGrid.columns) {
+ var cell = this.createCell(columnIdentifier);
+ this._element.appendChild(cell);
+ }
+ },
+
+ createCell: function(columnIdentifier)
+ {
+ var cell = document.createElement("td");
+ cell.className = columnIdentifier + "-column";
+
+ var div = document.createElement("div");
+ div.textContent = this.data[columnIdentifier];
+ cell.appendChild(div);
+
+ if (columnIdentifier === this.dataGrid.disclosureColumnIdentifier) {
+ cell.addStyleClass("disclosure");
+ if (this.depth)
+ cell.style.setProperty("padding-left", (this.depth * this.dataGrid.indentWidth) + "px");
+ }
+
+ return cell;
+ },
+
+ // Share these functions with DataGrid. They are written to work with a DataGridNode this object.
+ appendChild: WebInspector.DataGrid.prototype.appendChild,
+ insertChild: WebInspector.DataGrid.prototype.insertChild,
+ removeChild: WebInspector.DataGrid.prototype.removeChild,
+ removeChildren: WebInspector.DataGrid.prototype.removeChildren,
+ removeChildrenRecursive: WebInspector.DataGrid.prototype.removeChildrenRecursive,
+
+ _recalculateSiblings: function(myIndex)
+ {
+ if (!this.parent)
+ return;
+
+ var previousChild = (myIndex > 0 ? this.parent.children[myIndex - 1] : null);
+
+ if (previousChild) {
+ previousChild.nextSibling = this;
+ this.previousSibling = previousChild;
+ } else
+ this.previousSibling = null;
+
+ var nextChild = this.parent.children[myIndex + 1];
+
+ if (nextChild) {
+ nextChild.previousSibling = this;
+ this.nextSibling = nextChild;
+ } else
+ this.nextSibling = null;
+ },
+
+ collapse: function()
+ {
+ if (this._element)
+ this._element.removeStyleClass("expanded");
+
+ this._expanded = false;
+
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i].revealed = false;
+
+ this.dispatchEventToListeners("collapsed");
+ },
+
+ collapseRecursively: function()
+ {
+ var item = this;
+ while (item) {
+ if (item.expanded)
+ item.collapse();
+ item = item.traverseNextNode(false, this, true);
+ }
+ },
+
+ expand: function()
+ {
+ if (!this.hasChildren || this.expanded)
+ return;
+
+ if (this.revealed && !this._shouldRefreshChildren)
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i].revealed = true;
+
+ if (this._shouldRefreshChildren) {
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i]._detach();
+
+ this.dispatchEventToListeners("populate");
+
+ if (this._attached) {
+ for (var i = 0; i < this.children.length; ++i) {
+ var child = this.children[i];
+ if (this.revealed)
+ child.revealed = true;
+ child._attach();
+ }
+ }
+
+ delete this._shouldRefreshChildren;
+ }
+
+ if (this._element)
+ this._element.addStyleClass("expanded");
+
+ this._expanded = true;
+
+ this.dispatchEventToListeners("expanded");
+ },
+
+ expandRecursively: function()
+ {
+ var item = this;
+ while (item) {
+ item.expand();
+ item = item.traverseNextNode(false, this);
+ }
+ },
+
+ reveal: function()
+ {
+ var currentAncestor = this.parent;
+ while (currentAncestor && !currentAncestor.root) {
+ if (!currentAncestor.expanded)
+ currentAncestor.expand();
+ currentAncestor = currentAncestor.parent;
+ }
+
+ this.element.scrollIntoViewIfNeeded(false);
+
+ this.dispatchEventToListeners("revealed");
+ },
+
+ select: function(supressSelectedEvent)
+ {
+ if (!this.dataGrid || !this.selectable || this.selected)
+ return;
+
+ if (this.dataGrid.selectedNode)
+ this.dataGrid.selectedNode.deselect();
+
+ this._selected = true;
+ this.dataGrid.selectedNode = this;
+
+ if (this._element)
+ this._element.addStyleClass("selected");
+
+ if (!supressSelectedEvent)
+ this.dispatchEventToListeners("selected");
+ },
+
+ deselect: function(supressDeselectedEvent)
+ {
+ if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected)
+ return;
+
+ this._selected = false;
+ this.dataGrid.selectedNode = null;
+
+ if (this._element)
+ this._element.removeStyleClass("selected");
+
+ if (!supressDeselectedEvent)
+ this.dispatchEventToListeners("deselected");
+ },
+
+ traverseNextNode: function(skipHidden, stayWithin, dontPopulate, info)
+ {
+ if (!dontPopulate && this.hasChildren)
+ this.dispatchEventToListeners("populate");
+
+ if (info)
+ info.depthChange = 0;
+
+ var node = (!skipHidden || this.revealed) ? this.children[0] : null;
+ if (node && (!skipHidden || this.expanded)) {
+ if (info)
+ info.depthChange = 1;
+ return node;
+ }
+
+ if (this === stayWithin)
+ return null;
+
+ node = (!skipHidden || this.revealed) ? this.nextSibling : null;
+ if (node)
+ return node;
+
+ node = this;
+ while (node && !node.root && !((!skipHidden || node.revealed) ? node.nextSibling : null) && node.parent !== stayWithin) {
+ if (info)
+ info.depthChange -= 1;
+ node = node.parent;
+ }
+
+ if (!node)
+ return null;
+
+ return (!skipHidden || node.revealed) ? node.nextSibling : null;
+ },
+
+ traversePreviousNode: function(skipHidden, dontPopulate)
+ {
+ var node = (!skipHidden || this.revealed) ? this.previousSibling : null;
+ if (!dontPopulate && node && node.hasChildren)
+ node.dispatchEventToListeners("populate");
+
+ while (node && ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null)) {
+ if (!dontPopulate && node.hasChildren)
+ node.dispatchEventToListeners("populate");
+ node = ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null);
+ }
+
+ if (node)
+ return node;
+
+ if (!this.parent || this.parent.root)
+ return null;
+
+ return this.parent;
+ },
+
+ isEventWithinDisclosureTriangle: function(event)
+ {
+ if (!this.hasChildren)
+ return false;
+ var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
+ if (!cell.hasStyleClass("disclosure"))
+ return false;
+ var computedLeftPadding = window.getComputedStyle(cell).getPropertyCSSValue("padding-left").getFloatValue(CSSPrimitiveValue.CSS_PX);
+ var left = cell.totalOffsetLeft + computedLeftPadding;
+ return event.pageX >= left && event.pageX <= left + this.disclosureToggleWidth;
+ },
+
+ _attach: function()
+ {
+ if (!this.dataGrid || this._attached)
+ return;
+
+ this._attached = true;
+
+ var nextNode = null;
+ var previousNode = this.traversePreviousNode(true, true);
+ if (previousNode && previousNode.element.parentNode && previousNode.element.nextSibling)
+ var nextNode = previousNode.element.nextSibling;
+ if (!nextNode)
+ nextNode = this.dataGrid.dataTableBody.lastChild;
+ this.dataGrid.dataTableBody.insertBefore(this.element, nextNode);
+
+ if (this.expanded)
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i]._attach();
+ },
+
+ _detach: function()
+ {
+ if (!this._attached)
+ return;
+
+ this._attached = false;
+
+ if (this._element && this._element.parentNode)
+ this._element.parentNode.removeChild(this._element);
+
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i]._detach();
+ }
+}
+
+WebInspector.DataGridNode.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Database.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Database.js
new file mode 100644
index 0000000..ef42e15
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Database.js
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Database = function(database, domain, name, version)
+{
+ this.database = database;
+ this.domain = domain;
+ this.name = name;
+ this.version = version;
+}
+
+WebInspector.Database.prototype = {
+ get database()
+ {
+ return this._database;
+ },
+
+ set database(x)
+ {
+ if (this._database === x)
+ return;
+ this._database = x;
+ },
+
+ get name()
+ {
+ return this._name;
+ },
+
+ set name(x)
+ {
+ if (this._name === x)
+ return;
+ this._name = x;
+ },
+
+ get version()
+ {
+ return this._version;
+ },
+
+ set version(x)
+ {
+ if (this._version === x)
+ return;
+ this._version = x;
+ },
+
+ get domain()
+ {
+ return this._domain;
+ },
+
+ set domain(x)
+ {
+ if (this._domain === x)
+ return;
+ this._domain = x;
+ },
+
+ get displayDomain()
+ {
+ return WebInspector.Resource.prototype.__lookupGetter__("displayDomain").call(this);
+ },
+
+ get tableNames()
+ {
+ return InspectorController.databaseTableNames(this.database).sort();
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DatabaseQueryView.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DatabaseQueryView.js
new file mode 100644
index 0000000..122707f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DatabaseQueryView.js
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DatabaseQueryView = function(database)
+{
+ WebInspector.View.call(this);
+
+ this.database = database;
+
+ this.element.addStyleClass("storage-view");
+ this.element.addStyleClass("query");
+ this.element.tabIndex = 0;
+
+ this.element.addEventListener("selectstart", this._selectStart.bind(this), false);
+
+ this.promptElement = document.createElement("div");
+ this.promptElement.className = "database-query-prompt";
+ this.promptElement.appendChild(document.createElement("br"));
+ this.promptElement.handleKeyEvent = this._promptKeyDown.bind(this);
+ this.element.appendChild(this.promptElement);
+
+ this.prompt = new WebInspector.TextPrompt(this.promptElement, this.completions.bind(this), " ");
+}
+
+WebInspector.DatabaseQueryView.prototype = {
+ show: function(parentElement)
+ {
+ WebInspector.View.prototype.show.call(this, parentElement);
+
+ function moveBackIfOutside()
+ {
+ if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed)
+ this.prompt.moveCaretToEndOfPrompt();
+ }
+
+ setTimeout(moveBackIfOutside.bind(this), 0);
+ },
+
+ completions: function(wordRange, bestMatchOnly)
+ {
+ var prefix = wordRange.toString().toLowerCase();
+ if (!prefix.length)
+ return;
+
+ var results = [];
+
+ function accumulateMatches(textArray)
+ {
+ if (bestMatchOnly && results.length)
+ return;
+ for (var i = 0; i < textArray.length; ++i) {
+ var text = textArray[i].toLowerCase();
+ if (text.length < prefix.length)
+ continue;
+ if (text.indexOf(prefix) !== 0)
+ continue;
+ results.push(textArray[i]);
+ if (bestMatchOnly)
+ return;
+ }
+ }
+
+ accumulateMatches(this.database.tableNames.map(function(name) { return name + " " }));
+ accumulateMatches(["SELECT ", "FROM ", "WHERE ", "LIMIT ", "DELETE FROM ", "CREATE ", "DROP ", "TABLE ", "INDEX ", "UPDATE ", "INSERT INTO ", "VALUES ("]);
+
+ return results;
+ },
+
+ _promptKeyDown: function(event)
+ {
+ switch (event.keyIdentifier) {
+ case "Enter":
+ this._enterKeyPressed(event);
+ return;
+ }
+
+ this.prompt.handleKeyEvent(event);
+ },
+
+ _selectStart: function(event)
+ {
+ if (this._selectionTimeout)
+ clearTimeout(this._selectionTimeout);
+
+ this.prompt.clearAutoComplete();
+
+ function moveBackIfOutside()
+ {
+ delete this._selectionTimeout;
+ if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed)
+ this.prompt.moveCaretToEndOfPrompt();
+ this.prompt.autoCompleteSoon();
+ }
+
+ this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100);
+ },
+
+ _enterKeyPressed: function(event)
+ {
+ event.preventDefault();
+ event.stopPropagation();
+
+ this.prompt.clearAutoComplete(true);
+
+ var query = this.prompt.text;
+ if (!query.length)
+ return;
+
+ this.prompt.history.push(query);
+ this.prompt.historyOffset = 0;
+ this.prompt.text = "";
+
+ function queryTransaction(tx)
+ {
+ tx.executeSql(query, null, InspectorController.wrapCallback(this._queryFinished.bind(this, query)), InspectorController.wrapCallback(this._executeSqlError.bind(this, query)));
+ }
+
+ this.database.database.transaction(InspectorController.wrapCallback(queryTransaction.bind(this)), InspectorController.wrapCallback(this._queryError.bind(this, query)));
+ },
+
+ _queryFinished: function(query, tx, result)
+ {
+ var dataGrid = WebInspector.panels.databases.dataGridForResult(result);
+ dataGrid.element.addStyleClass("inline");
+ this._appendQueryResult(query, dataGrid.element);
+
+ if (query.match(/^create /i) || query.match(/^drop table /i))
+ WebInspector.panels.databases.updateDatabaseTables(this.database);
+ },
+
+ _queryError: function(query, error)
+ {
+ if (error.code == 1)
+ var message = error.message;
+ else if (error.code == 2)
+ var message = WebInspector.UIString("Database no longer has expected version.");
+ else
+ var message = WebInspector.UIString("An unexpected error %s occured.", error.code);
+
+ this._appendQueryResult(query, message, "error");
+ },
+
+ _executeSqlError: function(query, tx, error)
+ {
+ this._queryError(query, error);
+ },
+
+ _appendQueryResult: function(query, result, resultClassName)
+ {
+ var element = document.createElement("div");
+ element.className = "database-user-query";
+
+ var commandTextElement = document.createElement("span");
+ commandTextElement.className = "database-query-text";
+ commandTextElement.textContent = query;
+ element.appendChild(commandTextElement);
+
+ var resultElement = document.createElement("div");
+ resultElement.className = "database-query-result";
+
+ if (resultClassName)
+ resultElement.addStyleClass(resultClassName);
+
+ if (typeof result === "string" || result instanceof String)
+ resultElement.textContent = result;
+ else if (result && result.nodeName)
+ resultElement.appendChild(result);
+
+ if (resultElement.childNodes.length)
+ element.appendChild(resultElement);
+
+ this.element.insertBefore(element, this.promptElement);
+ this.promptElement.scrollIntoView(false);
+ }
+}
+
+WebInspector.DatabaseQueryView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DatabaseTableView.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DatabaseTableView.js
new file mode 100644
index 0000000..bbca9d0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DatabaseTableView.js
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DatabaseTableView = function(database, tableName)
+{
+ WebInspector.View.call(this);
+
+ this.database = database;
+ this.tableName = tableName;
+
+ this.element.addStyleClass("storage-view");
+ this.element.addStyleClass("table");
+
+ this.refreshButton = document.createElement("button");
+ this.refreshButton.title = WebInspector.UIString("Refresh");
+ this.refreshButton.className = "refresh-storage-status-bar-item status-bar-item";
+ this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
+}
+
+WebInspector.DatabaseTableView.prototype = {
+ show: function(parentElement)
+ {
+ WebInspector.View.prototype.show.call(this, parentElement);
+ this.update();
+ },
+
+ get statusBarItems()
+ {
+ return [this.refreshButton];
+ },
+
+ update: function()
+ {
+ function queryTransaction(tx)
+ {
+ tx.executeSql("SELECT * FROM " + this.tableName, null, InspectorController.wrapCallback(this._queryFinished.bind(this)), InspectorController.wrapCallback(this._queryError.bind(this)));
+ }
+
+ this.database.database.transaction(InspectorController.wrapCallback(queryTransaction.bind(this)), InspectorController.wrapCallback(this._queryError.bind(this)));
+ },
+
+ _queryFinished: function(tx, result)
+ {
+ this.element.removeChildren();
+
+ var dataGrid = WebInspector.panels.databases.dataGridForResult(result);
+ if (!dataGrid) {
+ var emptyMsgElement = document.createElement("div");
+ emptyMsgElement.className = "storage-table-empty";
+ emptyMsgElement.textContent = WebInspector.UIString("The “%s”\ntable is empty.", this.tableName);
+ this.element.appendChild(emptyMsgElement);
+ return;
+ }
+
+ this.element.appendChild(dataGrid.element);
+ },
+
+ _queryError: function(tx, error)
+ {
+ this.element.removeChildren();
+
+ var errorMsgElement = document.createElement("div");
+ errorMsgElement.className = "storage-table-error";
+ errorMsgElement.textContent = WebInspector.UIString("An error occurred trying to\nread the “%s” table.", this.tableName);
+ this.element.appendChild(errorMsgElement);
+ },
+
+ _refreshButtonClicked: function(event)
+ {
+ this.update();
+ }
+}
+
+WebInspector.DatabaseTableView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DatabasesPanel.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DatabasesPanel.js
new file mode 100644
index 0000000..4644b3b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DatabasesPanel.js
@@ -0,0 +1,526 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DatabasesPanel = function(database)
+{
+ WebInspector.Panel.call(this);
+
+ this.sidebarElement = document.createElement("div");
+ this.sidebarElement.id = "databases-sidebar";
+ this.sidebarElement.className = "sidebar";
+ this.element.appendChild(this.sidebarElement);
+
+ this.sidebarResizeElement = document.createElement("div");
+ this.sidebarResizeElement.className = "sidebar-resizer-vertical";
+ this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarDragging.bind(this), false);
+ this.element.appendChild(this.sidebarResizeElement);
+
+ this.sidebarTreeElement = document.createElement("ol");
+ this.sidebarTreeElement.className = "sidebar-tree";
+ this.sidebarElement.appendChild(this.sidebarTreeElement);
+
+ this.sidebarTree = new TreeOutline(this.sidebarTreeElement);
+
+ this.databasesListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("DATABASES"), {}, true);
+ this.sidebarTree.appendChild(this.databasesListTreeElement);
+ this.databasesListTreeElement.expand();
+
+ this.localStorageListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("LOCAL STORAGE"), {}, true);
+ this.sidebarTree.appendChild(this.localStorageListTreeElement);
+ this.localStorageListTreeElement.expand();
+
+ this.sessionStorageListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("SESSION STORAGE"), {}, true);
+ this.sidebarTree.appendChild(this.sessionStorageListTreeElement);
+ this.sessionStorageListTreeElement.expand();
+
+ this.storageViews = document.createElement("div");
+ this.storageViews.id = "storage-views";
+ this.element.appendChild(this.storageViews);
+
+ this.storageViewStatusBarItemsContainer = document.createElement("div");
+ this.storageViewStatusBarItemsContainer.id = "storage-view-status-bar-items";
+
+ this.reset();
+}
+
+WebInspector.DatabasesPanel.prototype = {
+ toolbarItemClass: "databases",
+
+ get toolbarItemLabel()
+ {
+ return WebInspector.UIString("Databases");
+ },
+
+ get statusBarItems()
+ {
+ return [this.storageViewStatusBarItemsContainer];
+ },
+
+ show: function()
+ {
+ WebInspector.Panel.prototype.show.call(this);
+ this._updateSidebarWidth();
+ },
+
+ reset: function()
+ {
+ if (this._databases) {
+ var databasesLength = this._databases.length;
+ for (var i = 0; i < databasesLength; ++i) {
+ var database = this._databases[i];
+
+ delete database._tableViews;
+ delete database._queryView;
+ }
+ }
+
+ this._databases = [];
+
+ if (this._domStorage) {
+ var domStorageLength = this._domStorage.length;
+ for (var i = 0; i < domStorageLength; ++i) {
+ var domStorage = this._domStorage[i];
+
+ delete domStorage._domStorageView;
+ }
+ }
+
+ this._domStorage = [];
+
+ this.databasesListTreeElement.removeChildren();
+ this.localStorageListTreeElement.removeChildren();
+ this.sessionStorageListTreeElement.removeChildren();
+ this.storageViews.removeChildren();
+
+ this.storageViewStatusBarItemsContainer.removeChildren();
+ },
+
+ handleKeyEvent: function(event)
+ {
+ this.sidebarTree.handleKeyEvent(event);
+ },
+
+ addDatabase: function(database)
+ {
+ this._databases.push(database);
+
+ var databaseTreeElement = new WebInspector.DatabaseSidebarTreeElement(database);
+ database._databasesTreeElement = databaseTreeElement;
+ this.databasesListTreeElement.appendChild(databaseTreeElement);
+ },
+
+ addDOMStorage: function(domStorage)
+ {
+ this._domStorage.push(domStorage);
+ var domStorageTreeElement = new WebInspector.DOMStorageSidebarTreeElement(domStorage);
+ domStorage._domStorageTreeElement = domStorageTreeElement;
+ if (domStorage.isLocalStorage)
+ this.localStorageListTreeElement.appendChild(domStorageTreeElement);
+ else
+ this.sessionStorageListTreeElement.appendChild(domStorageTreeElement);
+ },
+
+ showDatabase: function(database, tableName)
+ {
+ if (!database)
+ return;
+
+ if (this.visibleView)
+ this.visibleView.hide();
+
+ var view;
+ if (tableName) {
+ if (!("_tableViews" in database))
+ database._tableViews = {};
+ view = database._tableViews[tableName];
+ if (!view) {
+ view = new WebInspector.DatabaseTableView(database, tableName);
+ database._tableViews[tableName] = view;
+ }
+ } else {
+ view = database._queryView;
+ if (!view) {
+ view = new WebInspector.DatabaseQueryView(database);
+ database._queryView = view;
+ }
+ }
+
+ view.show(this.storageViews);
+
+ this.visibleView = view;
+
+ this.storageViewStatusBarItemsContainer.removeChildren();
+ var statusBarItems = view.statusBarItems;
+ for (var i = 0; i < statusBarItems.length; ++i)
+ this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
+ },
+
+ showDOMStorage: function(domStorage)
+ {
+ if (!domStorage)
+ return;
+
+ if (this.visibleView)
+ this.visibleView.hide();
+
+ var view;
+ view = domStorage._domStorageView;
+ if (!view) {
+ view = new WebInspector.DOMStorageItemsView(domStorage);
+ domStorage._domStorageView = view;
+ }
+
+ view.show(this.storageViews);
+
+ this.visibleView = view;
+
+ this.storageViewStatusBarItemsContainer.removeChildren();
+ var statusBarItems = view.statusBarItems;
+ for (var i = 0; i < statusBarItems.length; ++i)
+ this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
+ },
+
+ closeVisibleView: function()
+ {
+ if (this.visibleView)
+ this.visibleView.hide();
+ delete this.visibleView;
+ },
+
+ updateDatabaseTables: function(database)
+ {
+ if (!database || !database._databasesTreeElement)
+ return;
+
+ database._databasesTreeElement.shouldRefreshChildren = true;
+
+ if (!("_tableViews" in database))
+ return;
+
+ var tableNamesHash = {};
+ var tableNames = database.tableNames;
+ var tableNamesLength = tableNames.length;
+ for (var i = 0; i < tableNamesLength; ++i)
+ tableNamesHash[tableNames[i]] = true;
+
+ for (var tableName in database._tableViews) {
+ if (!(tableName in tableNamesHash)) {
+ if (this.visibleView === database._tableViews[tableName])
+ this.closeVisibleView();
+ delete database._tableViews[tableName];
+ }
+ }
+ },
+
+ dataGridForResult: function(result)
+ {
+ if (!result.rows.length)
+ return null;
+
+ var columns = {};
+
+ var rows = result.rows;
+ for (var columnIdentifier in rows.item(0)) {
+ var column = {};
+ column.width = columnIdentifier.length;
+ column.title = columnIdentifier;
+
+ columns[columnIdentifier] = column;
+ }
+
+ var nodes = [];
+ var length = rows.length;
+ for (var i = 0; i < length; ++i) {
+ var data = {};
+
+ var row = rows.item(i);
+ for (var columnIdentifier in row) {
+ // FIXME: (Bug 19439) We should specially format SQL NULL here
+ // (which is represented by JavaScript null here, and turned
+ // into the string "null" by the String() function).
+ var text = String(row[columnIdentifier]);
+ data[columnIdentifier] = text;
+ if (text.length > columns[columnIdentifier].width)
+ columns[columnIdentifier].width = text.length;
+ }
+
+ var node = new WebInspector.DataGridNode(data, false);
+ node.selectable = false;
+ nodes.push(node);
+ }
+
+ var totalColumnWidths = 0;
+ for (var columnIdentifier in columns)
+ totalColumnWidths += columns[columnIdentifier].width;
+
+ // Calculate the percentage width for the columns.
+ const minimumPrecent = 5;
+ var recoupPercent = 0;
+ for (var columnIdentifier in columns) {
+ var width = columns[columnIdentifier].width;
+ width = Math.round((width / totalColumnWidths) * 100);
+ if (width < minimumPrecent) {
+ recoupPercent += (minimumPrecent - width);
+ width = minimumPrecent;
+ }
+
+ columns[columnIdentifier].width = width;
+ }
+
+ // Enforce the minimum percentage width.
+ while (recoupPercent > 0) {
+ for (var columnIdentifier in columns) {
+ if (columns[columnIdentifier].width > minimumPrecent) {
+ --columns[columnIdentifier].width;
+ --recoupPercent;
+ if (!recoupPercent)
+ break;
+ }
+ }
+ }
+
+ // Change the width property to a string suitable for a style width.
+ for (var columnIdentifier in columns)
+ columns[columnIdentifier].width += "%";
+
+ var dataGrid = new WebInspector.DataGrid(columns);
+ var length = nodes.length;
+ for (var i = 0; i < length; ++i)
+ dataGrid.appendChild(nodes[i]);
+
+ return dataGrid;
+ },
+
+ dataGridForDOMStorage: function(domStorage)
+ {
+ if (!domStorage.length)
+ return null;
+
+ var columns = {};
+ columns[0] = {};
+ columns[1] = {};
+ columns[0].title = WebInspector.UIString("Key");
+ columns[0].width = columns[0].title.length;
+ columns[1].title = WebInspector.UIString("Value");
+ columns[1].width = columns[0].title.length;
+
+ var nodes = [];
+
+ var length = domStorage.length;
+ for (index = 0; index < domStorage.length; index++) {
+ var data = {};
+
+ var key = String(domStorage.key(index));
+ data[0] = key;
+ if (key.length > columns[0].width)
+ columns[0].width = key.length;
+
+ var value = String(domStorage.getItem(key));
+ data[1] = value;
+ if (value.length > columns[1].width)
+ columns[1].width = value.length;
+ var node = new WebInspector.DataGridNode(data, false);
+ node.selectable = true;
+ nodes.push(node);
+ }
+
+ var totalColumnWidths = columns[0].width + columns[1].width;
+ width = Math.round((columns[0].width * 100) / totalColumnWidths);
+ const minimumPrecent = 10;
+ if (width < minimumPrecent)
+ width = minimumPrecent;
+ if (width > 100 - minimumPrecent)
+ width = 100 - minimumPrecent;
+ columns[0].width = width;
+ columns[1].width = 100 - width;
+ columns[0].width += "%";
+ columns[1].width += "%";
+
+ var dataGrid = new WebInspector.DOMStorageDataGrid(columns);
+ var length = nodes.length;
+ for (var i = 0; i < length; ++i)
+ dataGrid.appendChild(nodes[i]);
+ if (length > 0)
+ nodes[0].selected = true;
+ return dataGrid;
+ },
+
+ _startSidebarDragging: function(event)
+ {
+ WebInspector.elementDragStart(this.sidebarResizeElement, this._sidebarDragging.bind(this), this._endSidebarDragging.bind(this), event, "col-resize");
+ },
+
+ _sidebarDragging: function(event)
+ {
+ this._updateSidebarWidth(event.pageX);
+
+ event.preventDefault();
+ },
+
+ _endSidebarDragging: function(event)
+ {
+ WebInspector.elementDragEnd(event);
+ },
+
+ _updateSidebarWidth: function(width)
+ {
+ if (this.sidebarElement.offsetWidth <= 0) {
+ // The stylesheet hasn't loaded yet or the window is closed,
+ // so we can't calculate what is need. Return early.
+ return;
+ }
+
+ if (!("_currentSidebarWidth" in this))
+ this._currentSidebarWidth = this.sidebarElement.offsetWidth;
+
+ if (typeof width === "undefined")
+ width = this._currentSidebarWidth;
+
+ width = Number.constrain(width, Preferences.minSidebarWidth, window.innerWidth / 2);
+
+ this._currentSidebarWidth = width;
+
+ this.sidebarElement.style.width = width + "px";
+ this.storageViews.style.left = width + "px";
+ this.storageViewStatusBarItemsContainer.style.left = width + "px";
+ this.sidebarResizeElement.style.left = (width - 3) + "px";
+ }
+}
+
+WebInspector.DatabasesPanel.prototype.__proto__ = WebInspector.Panel.prototype;
+
+WebInspector.DatabaseSidebarTreeElement = function(database)
+{
+ this.database = database;
+
+ WebInspector.SidebarTreeElement.call(this, "database-sidebar-tree-item", "", "", database, true);
+
+ this.refreshTitles();
+}
+
+WebInspector.DatabaseSidebarTreeElement.prototype = {
+ onselect: function()
+ {
+ WebInspector.panels.databases.showDatabase(this.database);
+ },
+
+ oncollapse: function()
+ {
+ // Request a refresh after every collapse so the next
+ // expand will have an updated table list.
+ this.shouldRefreshChildren = true;
+ },
+
+ onpopulate: function()
+ {
+ this.removeChildren();
+
+ var tableNames = this.database.tableNames;
+ var tableNamesLength = tableNames.length;
+ for (var i = 0; i < tableNamesLength; ++i)
+ this.appendChild(new WebInspector.SidebarDatabaseTableTreeElement(this.database, tableNames[i]));
+ },
+
+ get mainTitle()
+ {
+ return this.database.name;
+ },
+
+ set mainTitle(x)
+ {
+ // Do nothing.
+ },
+
+ get subtitle()
+ {
+ return this.database.displayDomain;
+ },
+
+ set subtitle(x)
+ {
+ // Do nothing.
+ }
+}
+
+WebInspector.DatabaseSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
+
+WebInspector.SidebarDatabaseTableTreeElement = function(database, tableName)
+{
+ this.database = database;
+ this.tableName = tableName;
+
+ WebInspector.SidebarTreeElement.call(this, "database-table-sidebar-tree-item small", tableName, "", null, false);
+}
+
+WebInspector.SidebarDatabaseTableTreeElement.prototype = {
+ onselect: function()
+ {
+ WebInspector.panels.databases.showDatabase(this.database, this.tableName);
+ }
+}
+
+WebInspector.SidebarDatabaseTableTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
+
+WebInspector.DOMStorageSidebarTreeElement = function(domStorage)
+{
+
+ this.domStorage = domStorage;
+
+ WebInspector.SidebarTreeElement.call(this, "domstorage-sidebar-tree-item", domStorage, "", null, false);
+
+ this.refreshTitles();
+}
+
+WebInspector.DOMStorageSidebarTreeElement.prototype = {
+ onselect: function()
+ {
+ WebInspector.panels.databases.showDOMStorage(this.domStorage);
+ },
+
+ get mainTitle()
+ {
+ return this.domStorage.domain;
+ },
+
+ set mainTitle(x)
+ {
+ // Do nothing.
+ },
+
+ get subtitle()
+ {
+ return ""; //this.database.displayDomain;
+ },
+
+ set subtitle(x)
+ {
+ // Do nothing.
+ }
+}
+
+WebInspector.DOMStorageSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DebuggerConsole.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DebuggerConsole.js
new file mode 100644
index 0000000..0ba3b28
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DebuggerConsole.js
@@ -0,0 +1,173 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Helper functions and objects for the JS debugger UI.
+ * @see debugger.html
+ */
+
+/**
+ * Document load listener.
+ */
+function onLoad() {
+ var debuggerConsole = new DebuggerConsole();
+ DebuggerIPC.init(debuggerConsole);
+ DebugShell.initDebugShell(debuggerConsole);
+ debuggerConsole.focusOnCommandLine();
+}
+
+/**
+ * @constructor
+ */
+function DebuggerConsole()
+{
+ this._output = document.getElementById("output");
+
+ var input = document.getElementById("command-line-text");
+ var self = this;
+ input.addEventListener(
+ 'keydown',
+ function(e) {
+ return self._onInputKeyDown(e);
+ },
+ true);
+ input.addEventListener(
+ 'keypress',
+ function(e) {
+ return self._onInputKeyPress(e);
+ },
+ true);
+ this._commandLineInput = input;
+
+ // command object stores command-line history state.
+ this._command = {
+ history: [],
+ history_index: 0,
+ pending: null
+ };
+};
+
+DebuggerConsole.prototype = {
+ /**
+ * Sets focus to command-line-text element.
+ */
+ focusOnCommandLine: function() {
+ this._commandLineInput.focus();
+ },
+
+ /**
+ * Called by chrome code when there's output to display.
+ * @param {string} txt
+ */
+ appendText: function(txt)
+ {
+ this._output.appendChild(document.createTextNode(txt));
+ this._output.appendChild(document.createElement('br'));
+ document.body.scrollTop = document.body.scrollHeight;
+ },
+
+ /**
+ * Called by chrome code to set the current state as to whether the debugger
+ * is stopped at a breakpoint or is running.
+ * @param {boolean} isBroken
+ */
+ setDebuggerBreak: function(isBroken)
+ {
+ var out = this._output;
+ if (isBroken) {
+ out.style.color = "black";
+ this.focusOnCommandLine();
+ } else {
+ out.style.color = "gray";
+ }
+ },
+
+ /**
+ * Execute a debugger command, add it to the command history and display it in
+ * the output window.
+ * @param {string} str
+ */
+ executeCommand: function(str) {
+ this.appendText("$ " + str);
+ // Sends message to DebuggerContents.HandleCommand.
+ if (DebugShell.singleton) {
+ DebugShell.singleton.command(str);
+ } else {
+ this.appendText("FAILED to send the command as DebugShell is null");
+ }
+
+ this._command.history.push(str);
+ this._command.history_index = this._command.history.length;
+ this._command.pending = null;
+ },
+
+
+ /**
+ * Display the previous history item in the given text field.
+ * @param {HTMLInputElement} field
+ */
+ selectPreviousCommand_: function(field) {
+ var command = this._command;
+ if (command.history_index > 0) {
+ // Remember the current field value as a pending command if we're at the
+ // end (it's something the user typed in).
+ if (command.history_index == command.history.length)
+ command.pending = field.value;
+ command.history_index--;
+ field.value = command.history[command.history_index];
+ field.select();
+ }
+ },
+
+ /**
+ * Display the next history item in the given text field.
+ * @param {HTMLInputElement} field
+ */
+ selectNextCommand_: function(field) {
+ var command = this._command;
+ if (command.history_index < command.history.length) {
+ command.history_index++;
+ if (command.history_index == command.history.length) {
+ field.value = command.pending || "";
+ } else {
+ field.value = command.history[command.history_index];
+ }
+ field.select();
+ }
+ },
+
+ /**
+ * command-line-text's onkeydown handler.
+ * @param {KeyboardEvent} e
+ * @return {boolean}
+ */
+ _onInputKeyDown: function (e) {
+ var field = e.target;
+ var key = e.keyCode;
+ if (key == 38) { // up arrow
+ this.selectPreviousCommand_(field);
+ return false;
+ } else if (key == 40) { // down arrow
+ this.selectNextCommand_(field);
+ return false;
+ }
+ return true;
+ },
+
+ /**
+ * command-line-text's onkeypress handler.
+ * @param {KeyboardEvent} e
+ * @return {boolean}
+ */
+ _onInputKeyPress: function (e) {
+ var field = e.target;
+ var key = e.keyCode;
+ if (key == 13) { // enter
+ this.executeCommand(field.value);
+ field.value = "";
+ return false;
+ }
+ return true;
+ }
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DebuggerIPC.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DebuggerIPC.js
new file mode 100644
index 0000000..15835fc
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DebuggerIPC.js
@@ -0,0 +1,109 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Implementation of debugger inter-process communication.
+ * Debugger UI can send messages to the DebuggerHost object living in
+ * Chrome browser process. The messages are either processed by DebuggerHost
+ * itself or trigger IPC message(such as break, evaluate script etc) from
+ * browser process to the renderer where the v8 instance being debugged
+ * will process them.
+ */
+
+var DebuggerIPC = {};
+
+/**
+ * Set up default debugger UI.
+ * @param {DebuggerPanel|DebuggerConsole} debuggerUI
+ */
+DebuggerIPC.init = function(debuggerUI) {
+ DebuggerIPC.debuggerUI = debuggerUI;
+}
+
+/**
+ * Sends JSON message to DebuggerHost.
+ * @param {Array.<Object>} nameAndArguments
+ */
+DebuggerIPC.sendMessage = function(nameAndArguments) {
+ //alert("DebuggerIPC.sendMessage " + nameAndArguments);
+ dprint("DebuggerIPC.callMethod([" + nameAndArguments + "])");
+ // convert all arguments to strings
+ // TODO(yurys): extend chrome.send to accept array of any value
+ // objects not only strings
+ for (var i = 0; i < nameAndArguments.length; i++) {
+ if (typeof nameAndArguments[i] != "string") {
+ nameAndArguments[i] = "" + nameAndArguments[i];
+ }
+ }
+
+ chrome.send("DebuggerHostMessage", nameAndArguments);
+};
+
+/**
+ * Handles messages from DebuggerHost.
+ * @param {Object} msg An object representing the message.
+ */
+DebuggerIPC.onMessageReceived = function(msg) {
+ //alert("DebuggerIPC.onMessageReceived " + msg.event);
+ var ui = DebuggerIPC.debuggerUI;
+ dprint("onMessageReceived: " + (msg && msg.event));
+ if (msg.type == "event") {
+ if (msg.event == "setDebuggerBreak") {
+ var val = msg.body.argument;
+ ui.setDebuggerBreak(val);
+ } else if (msg.event == "appendText") {
+ var text = msg.body.text;
+ ui.appendText(text);
+ } else if (msg.event == "focusOnCommandLine") {
+ dprint("focusOnCommandLine event received");
+ // messages to DebugShell
+ } else if (msg.event == "initDebugShell") {
+ // DebugShell.initDebugShell();
+ dprint(msg.event + " done");
+ } else if (msg.event == "on_attach") {
+ if (DebugShell.singleton) {
+ var args = msg.body.arguments;
+ if (!args || args.length != 1) {
+ dprint(msg.event + " failed: invalid arguments");
+ return;
+ }
+ var title = args[0];
+ DebugShell.singleton.on_attach(title);
+ dprint(msg.event + " done");
+ } else {
+ dprint(msg.event + " failed: DebugShell.singleton == null");
+ }
+ } else if (msg.event == "on_disconnect") {
+ if (DebugShell.singleton) {
+ DebugShell.singleton.on_disconnect();
+ dprint(msg.event + " done");
+ } else {
+ dprint(msg.event + " failed: DebugShell.singleton == null");
+ }
+ } else if (msg.event == "exit") {
+ if (DebugShell.singleton) {
+ DebugShell.singleton.exit();
+ dprint(msg.event + " done");
+ } else {
+ dprint(msg.event + " failed: DebugShell.singleton == null");
+ }
+ } else if (msg.event == "response") {
+ if (DebugShell.singleton) {
+ var args = msg.body.arguments;
+ if (!args || args.length != 1) {
+ dprint(msg.event + " failed: invalid argument");
+ return;
+ }
+ DebugShell.singleton.response(args[0]);
+ dprint(msg.event + " done");
+ } else {
+ ui.appendText(msg.event + " failed: DebugShell.singleton == null");
+ }
+ } else {
+ ui.appendText("Unknown event: " + msg.event);
+ }
+ } else {
+ ui.appendText("Unknown message type: " + msg.type);
+ }
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DebuggerPanel.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DebuggerPanel.js
new file mode 100644
index 0000000..bb059ac
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DebuggerPanel.js
@@ -0,0 +1,201 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview WebInspector panel representing command line debugger.
+ */
+
+/**
+ * Command line debugger panel.
+ * @constructor
+ * @extends {WebInspector.Panel}
+ */
+WebInspector.DebuggerPanel = function()
+{
+ WebInspector.Panel.call(this);
+
+ this.contentElement = document.createElement("div");
+ this.contentElement.id = "debugger-content";
+
+ var table = document.createElement("table");
+ table.id = 'outer';
+ var tr = document.createElement("tr");
+ this._output = document.createElement("td");
+ this._output.id = "output";
+ this._output.valign = "bottom";
+ this.appendText("Chrome JavaScript Debugger");
+ this.appendText("Type 'help' for a list of commands.");
+
+ tr.appendChild(this._output);
+ table.appendChild(tr);
+ this.contentElement.appendChild(table);
+
+
+ var commandLine = document.createElement("div");
+ commandLine.id = "command-line";
+ var input = document.createElement("input");
+ input.id = "command-line-text";
+ input.addEventListener('keydown', this._onInputKeyDown.bind(this), true);
+ input.addEventListener('keypress', this._onInputKeyPress.bind(this), true);
+ input.type = "text";
+ this.commandLineInput_ = input;
+
+ commandLine.appendChild(input);
+ this.contentElement.appendChild(commandLine);
+
+ // command object stores command-line history state.
+ this._command = {
+ history: [],
+ history_index: 0,
+ pending: null
+ };
+
+ this.element.appendChild(this.contentElement);
+ p('DebuggerPanel created');
+};
+
+WebInspector.DebuggerPanel.prototype = {
+ toolbarItemClass: "debugger",
+
+ get toolbarItemLabel()
+ {
+ return "Debugger"; //WebInspector.UIString("Debugger");
+ },
+
+ show: function()
+ {
+ WebInspector.Panel.prototype.show.call(this);
+ this.focusOnCommandLine();
+ },
+
+ /**
+ * Sets focus to command-line-text element.
+ */
+ focusOnCommandLine: function()
+ {
+ if (this.visible) {
+ this.commandLineInput_.focus();
+ }
+ },
+
+ /**
+ * Called by chrome code when there's output to display.
+ * @param {string} txt
+ */
+ appendText: function(txt)
+ {
+ this._output.appendChild(document.createTextNode(txt));
+ this._output.appendChild(document.createElement('br'));
+ },
+
+ /**
+ * Called by chrome code to set the current state as to whether the debugger
+ * is stopped at a breakpoint or is running.
+ * @param {boolean} isBroken
+ */
+ setDebuggerBreak: function(isBroken)
+ {
+ var out = this._output;
+ if (isBroken) {
+ out.style.color = "black";
+ this.focusOnCommandLine();
+ } else {
+ out.style.color = "gray";
+ }
+ },
+
+ /**
+ * Execute a debugger command, add it to the command history and display
+ * it in the output window.
+ * @param {string} str
+ */
+ executeCommand: function(str)
+ {
+ this.appendText("$ " + str);
+ // Sends message to DebuggerContents.HandleCommand.
+ if (DebugShell.singleton) {
+ DebugShell.singleton.command(str);
+ } else {
+ this.appendText("FAILED to send the command as DebugShell is null");
+ }
+
+ this._command.history.push(str);
+ this._command.history_index = this._command.history.length;
+ this._command.pending = null;
+ },
+
+ /**
+ * Display the previous history item in the given text field.
+ * @param {HTMLInputElement} field
+ */
+ _selectPreviousCommand: function(field)
+ {
+ var command = this._command;
+ if (command.history_index > 0) {
+ // Remember the current field value as a pending command if we're at the
+ // end (it's something the user typed in).
+ if (command.history_index == command.history.length)
+ command.pending = field.value;
+ command.history_index--;
+ field.value = command.history[command.history_index];
+ field.select();
+ }
+ },
+
+ /**
+ * Display the next history item in the given text field.
+ * @param {HTMLInputElement} field
+ */
+ _selectNextCommand: function(field)
+ {
+ var command = this._command;
+ if (command.history_index < command.history.length) {
+ command.history_index++;
+ if (command.history_index == command.history.length) {
+ field.value = command.pending || "";
+ } else {
+ field.value = command.history[command.history_index];
+ }
+ field.select();
+ }
+ },
+
+ /**
+ * command-line-text's onkeydown handler.
+ * @param {KeyboardEvent} e
+ * @return {boolean}
+ */
+ _onInputKeyDown: function (e)
+ {
+ var field = e.target;
+ var key = e.keyCode;
+ if (key == 38) { // up arrow
+ this._selectPreviousCommand(field);
+ return false;
+ } else if (key == 40) { // down arrow
+ this._selectNextCommand(field);
+ return false;
+ }
+ return true;
+ },
+
+ /**
+ * command-line-text's onkeypress handler.
+ * @param {KeyboardEvent} e
+ * @return {boolean}
+ */
+ _onInputKeyPress: function (e)
+ {
+ var field = e.target;
+ var key = e.keyCode;
+ if (key == 13) { // enter
+ this.executeCommand(field.value);
+ field.value = "";
+ return false;
+ }
+ return true;
+ }
+};
+
+WebInspector.DebuggerPanel.prototype.__proto__ = WebInspector.Panel.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DebuggerShell.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DebuggerShell.js
new file mode 100644
index 0000000..907dce7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/DebuggerShell.js
@@ -0,0 +1,1458 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Shell objects and global helper functions for Chrome
+ * automation shell / debugger. This file is loaded into the global namespace
+ * of the interactive shell, so users can simply call global functions
+ * directly.
+ */
+
+// TODO(erikkay): look into how this can be split up into multiple files
+// It's currently loaded explicitly by Chrome, so maybe I need an "include"
+// or "source" builtin to allow a core source file to reference multiple
+// sub-files.
+
+/**
+ * Sequence number of the DebugCommand.
+ */
+DebugCommand.next_seq_ = 0;
+
+/**
+ * Command messages to be sent to the debugger.
+ * @constructor
+ */
+function DebugCommand(str) {
+ this.command = undefined;
+ // first, strip off of the leading word as the command
+ var argv = str.split(' ');
+ this.user_command = argv.shift();
+ // the rest of the string is argv to the command
+ str = argv.join(' ');
+ if (DebugCommand.aliases[this.user_command])
+ this.user_command = DebugCommand.aliases[this.user_command];
+ if (this.parseArgs_(str) == 1)
+ this.type = "request";
+ if (this.command == undefined)
+ this.command = this.user_command;
+};
+
+// Mapping of some control characters to avoid the \uXXXX syntax for most
+// commonly used control cahracters.
+const ctrlCharMap_ = {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+};
+
+// Regular expression matching ", \ and control characters (0x00 - 0x1F)
+// globally.
+const ctrlCharMatch_ = /["\\\\\x00-\x1F]/g;
+
+/**
+ * Convert a String to its JSON representation.
+ * @param {String} value - String to be converted
+ * @return {String} JSON formatted String
+ */
+DebugCommand.stringToJSON = function(value) {
+ // Check for" , \ and control characters (0x00 - 0x1F).
+ if (ctrlCharMatch_.test(value)) {
+ // Replace ", \ and control characters (0x00 - 0x1F).
+ return '"' + value.replace(ctrlCharMatch_, function (char) {
+ // Use charmap if possible.
+ var mapped = ctrlCharMap_[char];
+ if (mapped) return mapped;
+ mapped = char.charCodeAt();
+ // Convert control character to unicode escape sequence.
+ var dig1 = (Math.floor(mapped / 16));
+ var dig2 = (mapped % 16)
+ return '\\u00' + dig1.toString(16) + dig2.toString(16);
+ })
+ + '"';
+ }
+
+ // Simple string with no special characters.
+ return '"' + value + '"';
+};
+
+/**
+ * @return {bool} True if x is an integer.
+ */
+DebugCommand.isInt = function(x) {
+ var y = parseInt(x);
+ if (isNaN(y))
+ return false;
+ return x == y && x.toString() == y.toString();
+};
+
+/**
+ * @return {float} log base 10 of num
+ */
+DebugCommand.log10 = function(num) {
+ return Math.log(num)/Math.log(10);
+};
+
+/**
+ * Take an object and encode it (non-recursively) as a JSON dict.
+ * @param {Object} obj - object to encode
+ */
+DebugCommand.toJSON = function(obj) {
+ // TODO(erikkay): use a real JSON library
+ var json = '{';
+ for (var key in obj) {
+ if (json.length > 1)
+ json += ",";
+ var val = obj[key];
+ if (!DebugCommand.isInt(val)) {
+ val = DebugCommand.stringToJSON(val.toString());
+ }
+ json += '"' + key + '":' + val;
+ }
+ json += '}';
+ return json;
+};
+
+/**
+ * Encode the DebugCommand object into the V8 debugger JSON protocol format.
+ */
+DebugCommand.prototype.toJSONProtocol = function() {
+ // TODO(erikkay): use a real JSON library
+ var json = '{';
+ json += '"seq":"' + this.seq;
+ json += '","type":"' + this.type;
+ json += '","command":"' + this.command + '"';
+ if (this.arguments) {
+ json += ',"arguments":' + DebugCommand.toJSON(this.arguments);
+ }
+ json += '}'
+ return json;
+}
+
+/**
+ * Encode the contents of this message and send it to the debugger.
+ * @param {Object} tab - tab being debugged. This is an internal
+ * Chrome object.
+ */
+DebugCommand.prototype.sendToDebugger = function(tab) {
+ this.seq = DebugCommand.next_seq_++;
+ str = this.toJSONProtocol();
+ dprint("sending: " + str);
+ tab.sendToDebugger(str);
+};
+
+DebugCommand.trim = function(str) {
+ return str.replace(/^\s*/, '').replace(/\s*$/, '');
+};
+
+/**
+ * Strip off a trailing parameter after a ':'. As the identifier for the
+ * source can contain ':' characters (e.g. 'http://www....) something after
+ * a ':' is only considered a parameter if it is numeric.
+ * @return {Array} two element array, the trimmed string and the parameter,
+ * or -1 if no parameter
+ */
+DebugCommand.stripTrailingParameter = function(str, opt_separator) {
+ var sep = opt_separator || ':';
+ var index = str.lastIndexOf(sep);
+ // If a separator character if found strip if numeric.
+ if (index != -1) {
+ var value = parseInt(str.substring(index + 1, str.length), 10);
+ if (isNaN(value) || value < 0) {
+ return [str, -1];
+ }
+ str = str.substring(0, index);
+ return [str, value];
+ }
+ return [str, -1];
+};
+
+/**
+ * Format source and location strings based on source location input data.
+ * @param {Object} script - script information object
+ * @param {String} source - source code for the current location
+ * @param {int} line - line number (0-based)
+ * @param {String} func - function name
+ * @return {array} [location(string), source line(string), line number(int)]
+ */
+DebugCommand.getSourceLocation = function(script, source, line, func) {
+ // source line is 0-based, we present as 1-based
+ line++;
+
+ // TODO(erikkay): take column into account as well
+ if (source)
+ source = "" + line + ": " + source;
+ var location = '';
+ if (func) {
+ location = func + ", ";
+ }
+ location += script ? script.name : '[no source]';
+ return [location, source, line];
+};
+
+/**
+ * Aliases for debugger commands.
+ */
+DebugCommand.aliases = {
+ 'b': 'break',
+ 'bi': 'break_info',
+ 'br': 'break',
+ 'bt': 'backtrace',
+ 'c': 'continue',
+ 'f': 'frame',
+ 'h': 'help',
+ '?': 'help',
+ 'ls': 'source',
+ 'n': 'next',
+ 'p': 'print',
+ 's': 'step',
+ 'so': 'stepout',
+};
+
+/**
+ * Parses arguments to "args" and "locals" command, and initializes
+ * the underlying DebugCommand (which is a frame request).
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseArgsAndLocals_ = function(str) {
+ this.command = "frame";
+ return str.length ? -1 : 1;
+};
+
+/**
+ * Parses arguments to "break_info" command, and executes it.
+ * "break_info" has an optional argument, which is the breakpoint
+ * identifier.
+ * @see DebugCommand.commands
+ * @param {string} str - The arguments to be parsed.
+ * @return -1 for usage error, 0 for success
+ */
+DebugCommand.prototype.parseBreakInfo_ = function(str) {
+ this.type = "shell";
+
+ // Array of breakpoints to be printed by this command
+ // (default to all breakpoints)
+ var breakpointsToPrint = shell_.breakpoints;
+
+ if (str.length > 0) {
+ // User specified an invalid breakpoint (not a number)
+ if (!str.match(/^\s*\d+\s*$/))
+ return -1; // invalid usage
+
+ // Check that the specified breakpoint identifier exists
+ var id = parseInt(str);
+ var info = shell_.breakpoints[id];
+ if (!info) {
+ print("Error: Invalid breakpoint");
+ return 0; // success (of sorts)
+ }
+ breakpointsToPrint = [info];
+ } else {
+ // breakpointsToPrint.length isn't accurate, because of
+ // deletions
+ var num_breakpoints = 0;
+ for (var i in breakpointsToPrint) num_breakpoints++;
+
+ print("Num breakpoints: " + num_breakpoints);
+ }
+
+ DebugShell.printBreakpoints_(breakpointsToPrint);
+
+ return 0; // success
+}
+
+/**
+ * Parses arguments to "step" command.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseStep_ = function(str, opt_stepaction) {
+ this.command = "continue";
+ action = opt_stepaction || "in";
+ this.arguments = {"stepaction" : action}
+ if (str.length) {
+ count = parseInt(str);
+ if (count > 0) {
+ this.arguments["stepcount"] = count;
+ } else {
+ return -1;
+ }
+ }
+ return 1;
+};
+
+/**
+ * Parses arguments to "step" command.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseStepOut_ = function(str) {
+ return this.parseStep_(str, "out");
+};
+
+/**
+ * Parses arguments to "next" command.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseNext_ = function(str) {
+ return this.parseStep_(str, "next");
+};
+
+/**
+ * Parse the arguments to "print" command.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return 1 - always succeeds
+ */
+DebugCommand.prototype.parsePrint_ = function(str) {
+ this.command = "evaluate";
+ this.arguments = { "expression" : str };
+ // If the page is in the running state, then we force the expression to
+ // evaluate in the global context to avoid evaluating in a random context.
+ if (shell_.running)
+ this.arguments["global"] = true;
+ return 1;
+};
+
+/**
+ * Handle the response to a "print" command and display output to user.
+ * @param {ProtocolPacket} evaluate_response - the V8 debugger response object
+ */
+DebugCommand.responsePrint_ = function(evaluate_response) {
+ body = evaluate_response.body();
+ if (body['text'] != undefined) {
+ print(body['text']);
+ } else {
+ // TODO(erikkay): is "text" ever not set?
+ print("can't print response");
+ }
+};
+
+/**
+ * Parse the arguments to "dir" command.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return 1 - always succeeds
+ */
+DebugCommand.prototype.parseDir_ = function(str) {
+ this.command = "evaluate";
+ this.arguments = { "expression" : str };
+ // If the page is in the running state, then we force the expression to
+ // evaluate in the global context to avoid evaluating in a random context.
+ if (shell_.running)
+ this.arguments["global"] = true;
+ return 1;
+};
+
+/**
+ * Handle the response to a "dir" command and display output to user.
+ * @see http://wiki/Main/V8Debugger
+ * @param {ProtocolPacket} evaluate_response - the V8 debugger response object
+ */
+DebugCommand.responseDir_ = function(evaluate_response) {
+ var body = evaluate_response.body();
+ if (body.properties) {
+ print(body.properties.length + ' properties');
+ for (var n in body.properties) {
+ var property_info = body.properties[n].name;
+ property_info += ': ';
+ var value = evaluate_response.lookup(body.properties[n].ref);
+ if (value && value.type) {
+ property_info += value.type;
+ } else {
+ property_info += '<no type>';
+ }
+ property_info += ' (#';
+ property_info += body.properties[n].ref;
+ property_info += '#)';
+ print(property_info);
+ }
+ }
+};
+
+/**
+ * Parses arguments to "break" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success, 0 for handled internally
+ */
+DebugCommand.prototype.parseBreak_ = function(str) {
+ function stripTrailingParameter() {
+ var ret = DebugCommand.stripTrailingParameter(str, ':');
+ str = ret[0];
+ return ret[1];
+ }
+
+ if (str.length == 0) {
+ this.command = "break";
+ return 1;
+ } else {
+ var parts = str.split(/\s+/);
+ var condition = null;
+ if (parts.length > 1) {
+ str = parts.shift();
+ condition = parts.join(" ");
+ }
+
+ this.command = "setbreakpoint";
+
+ // Locate ...[:line[:column]] if present.
+ var line = -1;
+ var column = -1;
+ line = stripTrailingParameter();
+ if (line != -1) {
+ line -= 1;
+ var l = stripTrailingParameter();
+ if (l != -1) {
+ column = line;
+ line = l - 1;
+ }
+ }
+
+ if (line == -1 && column == -1) {
+ this.arguments = { 'type' : 'function',
+ 'target' : str };
+ } else {
+ var script = shell_.matchScript(str, line);
+ if (script) {
+ this.arguments = { 'type' : 'script',
+ 'target' : script.name };
+ } else {
+ this.arguments = { 'type' : 'function',
+ 'target' : str };
+ }
+ this.arguments.line = line;
+ if (column != -1)
+ this.arguments.position = column;
+ }
+ if (condition)
+ this.arguments.condition = condition;
+ }
+ return 1;
+};
+
+/**
+ * Handle the response to a "break" command and display output to user.
+ * @param {ResponsePacket} setbreakpoint_response - the V8 debugger response
+ * object
+ */
+DebugCommand.responseBreak_ = function(setbreakpoint_response) {
+ var body = setbreakpoint_response.body();
+ var info = new BreakpointInfo(
+ parseInt(body.breakpoint),
+ setbreakpoint_response.command.arguments.type,
+ setbreakpoint_response.command.arguments.target,
+ setbreakpoint_response.command.arguments.line,
+ setbreakpoint_response.command.arguments.position,
+ setbreakpoint_response.command.arguments.condition);
+ shell_.addedBreakpoint(info);
+};
+
+/**
+ * Parses arguments to "backtrace" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+ DebugCommand.prototype.parseBacktrace_ = function(str) {
+ if (str.length > 0) {
+ var parts = str.split(/\s+/);
+ var non_empty_parts = parts.filter(function(s) { return s.length > 0; });
+ // We need exactly two arguments.
+ if (non_empty_parts.length != 2) {
+ return -1;
+ }
+ var from = parseInt(non_empty_parts[0], 10);
+ var to = parseInt(non_empty_parts[1], 10);
+ // The two arguments have to be integers.
+ if (from != non_empty_parts[0] || to != non_empty_parts[1]) {
+ return -1;
+ }
+ this.arguments = { 'fromFrame': from, 'toFrame': to + 1 };
+ } else {
+ // Default to fetching the first 10 frames.
+ this.arguments = { 'fromFrame': 0, 'toFrame': 10 };
+ }
+ return 1;
+};
+
+/**
+ * Handle the response to a "backtrace" command and display output to user.
+ * @param {ResponsePacket} backtrace_response - the V8 debugger response object
+ */
+DebugCommand.responseBacktrace_ = function(backtrace_response) {
+ body = backtrace_response.body();
+ if (body && body.totalFrames) {
+ print('Frames #' + body.fromFrame + ' to #' + (body.toFrame - 1) +
+ ' of ' + body.totalFrames + ":");
+ for (var i = 0; i < body.frames.length; i++) {
+ print(body.frames[i].text);
+ }
+ } else {
+ print("unimplemented (sorry)");
+ }
+};
+
+
+/**
+ * Parses arguments to "clear" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseClearCommand_ = function(str) {
+ this.command = "clearbreakpoint";
+ if (str.length > 0) {
+ var i = parseInt(str, 10);
+ if (i != str) {
+ return -1;
+ }
+ this.arguments = { 'breakpoint': i };
+ }
+ return 1;
+}
+
+/**
+ * Handle the response to a "clear" command and display output to user.
+ * @param {ResponsePacket} clearbreakpoint_response - the V8 debugger response
+ * object
+ */
+DebugCommand.responseClear_ = function(clearbreakpoint_response) {
+ var body = clearbreakpoint_response.body();
+ shell_.clearedBreakpoint(parseInt(msg.command.arguments.breakpoint));
+}
+
+
+/**
+ * Parses arguments to "continue" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseContinueCommand_ = function(str) {
+ this.command = "continue";
+ if (str.length > 0) {
+ return -1;
+ }
+ return 1;
+}
+
+/**
+ * Parses arguments to "frame" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseFrame_ = function(str) {
+ if (str.length > 0) {
+ var i = parseInt(str, 10);
+ if (i != str) {
+ return -1;
+ }
+ this.arguments = { 'number': i };
+ }
+ return 1;
+};
+
+/**
+ * Handle the response to a "frame" command and display output to user.
+ * @param {ResponsePacket} frame_response - the V8 debugger response object
+ */
+DebugCommand.responseFrame_ = function(frame_response) {
+ var body = frame_response.body();
+ var func = frame_response.lookup(body.func.ref);
+ loc = DebugCommand.getSourceLocation(func.script,
+ body.sourceLineText, body.line, func.name);
+ print("#" + (body.index <= 9 ? '0' : '') + body.index + " " + loc[0]);
+ print(loc[1]);
+ shell_.current_frame = body.index;
+ shell_.current_line = loc[2];
+ shell_.current_script = func.script;
+};
+
+/**
+ * Handle the response to a "args" command and display output to user.
+ * @param {ProtocolPacket} frame_response - the V8 debugger response object (for
+ * "frame" command)
+ */
+DebugCommand.responseArgs_ = function(frame_response) {
+ var body = frame_response.body();
+ DebugCommand.printVariables_(body.arguments, frame_response);
+}
+
+/**
+ * Handle the response to a "locals" command and display output to user.
+ * @param {Object} msg - the V8 debugger response object (for "frame" command)
+ */
+DebugCommand.responseLocals_ = function(frame_response) {
+ var body = frame_response.body();
+ DebugCommand.printVariables_(body.locals, frame_response);
+}
+
+DebugCommand.printVariables_ = function(variables, protocol_packet) {
+ for (var i = 0; i < variables.length; i++) {
+ print(variables[i].name + " = " +
+ DebugCommand.toPreviewString_(protocol_packet.lookup(variables[i].value.ref)));
+ }
+}
+
+DebugCommand.toPreviewString_ = function(value) {
+ // TODO(ericroman): pretty print arrays and objects, recursively.
+ // TODO(ericroman): truncate length of preview if too long?
+ if (value.type == "string") {
+ // Wrap the string in quote marks and JS-escape
+ return DebugCommand.stringToJSON(value.text);
+ }
+ return value.text;
+}
+
+/**
+ * Parses arguments to "scripts" command.
+ * @see DebugCommand.commands
+ * @param {string} str - The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseScripts_ = function(str) {
+ return 1
+};
+
+/**
+ * Handle the response to a "scripts" command and display output to user.
+ * @param {ResponsePacket} scripts_response - the V8 debugger response object
+ */
+DebugCommand.responseScripts_ = function(scripts_response) {
+ scripts = scripts_response.body();
+ shell_.scripts = [];
+ for (var i in scripts) {
+ var script = scripts[i];
+
+ // Add this script to the internal list of scripts.
+ shell_.scripts.push(script);
+
+ // Print result if this response was the result of a user command.
+ if (scripts_response.command.from_user) {
+ var name = script.name;
+ if (name) {
+ if (script.lineOffset > 0) {
+ print(name + " (lines " + script.lineOffset + "-" +
+ (script.lineOffset + script.lineCount - 1) + ")");
+ } else {
+ print(name + " (lines " + script.lineCount + ")");
+ }
+ } else {
+ // For unnamed scripts (typically eval) display some source.
+ var sourceStart = script.sourceStart;
+ if (sourceStart.length > 40)
+ sourceStart = sourceStart.substring(0, 37) + '...';
+ print("[unnamed] (source:\"" + sourceStart + "\")");
+ }
+ }
+ }
+};
+
+/**
+ * Parses arguments to "source" command.
+ * @see DebugCommand.commands
+ * @param {string} str - The arguments to be parsed.
+ * @return -1 for usage error, 1 for success
+ */
+DebugCommand.prototype.parseSource_ = function(str) {
+ this.arguments = {};
+ if (this.current_frame > 0)
+ this.arguments.frame = this.current_frame;
+ if (str.length) {
+ var args = str.split(" ");
+ if (args.length == 1) {
+ // with 1 argument n, we print 10 lines starting at n
+ var num = parseInt(args[0]);
+ if (num > 0) {
+ this.arguments.fromLine = num - 1;
+ this.arguments.toLine = this.arguments.fromLine + 10;
+ } else {
+ return -1;
+ }
+ } else if (args.length == 2) {
+ // with 2 arguments x and y, we print from line x to line x + y
+ var from = parseInt(args[0]);
+ var len = parseInt(args[1]);
+ if (from > 0 && len > 0) {
+ this.arguments.fromLine = from - 1;
+ this.arguments.toLine = this.arguments.fromLine + len;
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ if (this.arguments.fromLine < 0)
+ return -1;
+ if (this.arguments.toLine <= this.arguments.fromLine)
+ return -1;
+ } else if (shell_.current_line > 0) {
+ // with no arguments, we print 11 lines with the current line as the center
+ this.arguments.fromLine =
+ Math.max(0, shell_.current_line - 6);
+ this.arguments.toLine = this.arguments.fromLine + 11;
+ }
+ return 1;
+};
+
+/**
+ * Handle the response to a "source" command and display output to user.
+ * @param {ProtocolPacket} source_response - the V8 debugger response object
+ */
+DebugCommand.responseSource_ = function(source_response) {
+ var body = source_response.body();
+ var from_line = parseInt(body.fromLine) + 1;
+ var source = body.source;
+ var lines = source.split('\n');
+ var maxdigits = 1 + Math.floor(DebugCommand.log10(from_line + lines.length))
+ for (var num in lines) {
+ // there's an extra newline at the end
+ if (num >= (lines.length - 1) && lines[num].length == 0)
+ break;
+ spacer = maxdigits - (1 + Math.floor(DebugCommand.log10(from_line)))
+ var line = "";
+ if (from_line == shell_.current_line) {
+ for (var i = 0; i < (maxdigits + 2); i++)
+ line += ">";
+ } else {
+ for (var i = 0; i < spacer; i++)
+ line += " ";
+ line += from_line + ": ";
+ }
+ line += lines[num];
+ print(line);
+ from_line++;
+ }
+};
+
+/**
+ * Parses arguments to "help" command. See DebugCommand.commands below
+ * for syntax details.
+ * @see DebugCommand.commands
+ * @param {string} str The arguments to be parsed.
+ * @return 0 for handled internally
+ */
+DebugCommand.parseHelp_ = function(str) {
+ DebugCommand.help(str);
+ return 0;
+};
+
+/**
+ * Takes argument and evaluates it in the context of the shell to allow commands
+ * to be escaped to the outer shell. Used primarily for development purposes.
+ * @see DebugCommand.commands
+ * @param {string} str The expression to be evaluated
+ * @return 0 for handled internally
+ */
+DebugCommand.parseShell_ = function(str) {
+ print(eval(str));
+ return 0;
+}
+
+DebugCommand.parseShellDebug_ = function(str) {
+ shell_.debug = !shell_.debug;
+ if (shell_.debug) {
+ print("shell debugging enabled");
+ } else {
+ print("shell debugging disabled");
+ }
+ return 0;
+}
+
+/**
+ * Parses a user-entered command string.
+ * @param {string} str The arguments to be parsed.
+ */
+DebugCommand.prototype.parseArgs_ = function(str) {
+ if (str.length)
+ str = DebugCommand.trim(str);
+ var cmd = DebugCommand.commands[this.user_command];
+ if (cmd) {
+ var parse = cmd['parse'];
+ if (parse == undefined) {
+ print('>>>can\'t find parse func for ' + this.user_command);
+ this.type = "error";
+ } else {
+ var ret = parse.call(this, str);
+ if (ret > 0) {
+ // Command gererated a debugger request.
+ this.type = "request";
+ } else if (ret == 0) {
+ // Command handeled internally.
+ this.type = "handled";
+ } else if (ret < 0) {
+ // Command error.
+ this.type = "handled";
+ DebugCommand.help(this.user_command);
+ }
+ }
+ } else {
+ this.type = "handled";
+ print('unknown command: ' + this.user_command);
+ DebugCommand.help();
+ }
+};
+
+/**
+ * Displays command help or all help.
+ * @param {string} opt_str Which command to print help for.
+ */
+DebugCommand.help = function(opt_str) {
+ if (opt_str) {
+ var cmd = DebugCommand.commands[opt_str];
+ var usage = cmd.usage;
+ print('usage: ' + usage);
+ // Print additional details for the command.
+ if (cmd.help) {
+ print(cmd.help);
+ }
+ } else {
+ if (shell_.running) {
+ print('Status: page is running');
+ } else {
+ print('Status: page is paused');
+ }
+ print('Available commands:');
+ for (var key in DebugCommand.commands) {
+ var cmd = DebugCommand.commands[key];
+ if (!cmd['hidden'] && (!shell_.running || cmd['while_running'])) {
+ var usage = cmd.usage;
+ print(' ' + usage);
+ }
+ }
+ }
+};
+
+/**
+ * Valid commands, their argument parser and their associated usage text.
+ */
+DebugCommand.commands = {
+ 'args': { 'parse': DebugCommand.prototype.parseArgsAndLocals_,
+ 'usage': 'args',
+ 'help': 'summarize the arguments to the current function.',
+ 'response': DebugCommand.responseArgs_ },
+ 'break': { 'parse': DebugCommand.prototype.parseBreak_,
+ 'response': DebugCommand.responseBreak_,
+ 'usage': 'break [location] <condition>',
+ 'help': 'location is one of <function> | <script:function> | <script:line> | <script:line:pos>',
+ 'while_running': true },
+ 'break_info': { 'parse': DebugCommand.prototype.parseBreakInfo_,
+ 'usage': 'break_info [breakpoint #]',
+ 'help': 'list the current breakpoints, or the details on a single one',
+ 'while_running': true },
+ 'backtrace': { 'parse': DebugCommand.prototype.parseBacktrace_,
+ 'response': DebugCommand.responseBacktrace_,
+ 'usage': 'backtrace [from frame #] [to frame #]' },
+ 'clear': { 'parse': DebugCommand.prototype.parseClearCommand_,
+ 'response': DebugCommand.responseClear_,
+ 'usage': 'clear <breakpoint #>',
+ 'while_running': true },
+ 'continue': { 'parse': DebugCommand.prototype.parseContinueCommand_,
+ 'usage': 'continue' },
+ 'dir': { 'parse': DebugCommand.prototype.parseDir_,
+ 'response': DebugCommand.responseDir_,
+ 'usage': 'dir <expression>',
+ 'while_running': true },
+ 'frame': { 'parse': DebugCommand.prototype.parseFrame_,
+ 'response': DebugCommand.responseFrame_,
+ 'usage': 'frame <frame #>' },
+ 'help': { 'parse': DebugCommand.parseHelp_,
+ 'usage': 'help [command]',
+ 'while_running': true },
+ 'locals': { 'parse': DebugCommand.prototype.parseArgsAndLocals_,
+ 'usage': 'locals',
+ 'help': 'summarize the local variables for current frame',
+ 'response': DebugCommand.responseLocals_ },
+ 'next': { 'parse': DebugCommand.prototype.parseNext_,
+ 'usage': 'next' } ,
+ 'print': { 'parse': DebugCommand.prototype.parsePrint_,
+ 'response': DebugCommand.responsePrint_,
+ 'usage': 'print <expression>',
+ 'while_running': true },
+ 'scripts': { 'parse': DebugCommand.prototype.parseScripts_,
+ 'response': DebugCommand.responseScripts_,
+ 'usage': 'scripts',
+ 'while_running': true },
+ 'source': { 'parse': DebugCommand.prototype.parseSource_,
+ 'response': DebugCommand.responseSource_,
+ 'usage': 'source [from line] | [<from line> <num lines>]' },
+ 'step': { 'parse': DebugCommand.prototype.parseStep_,
+ 'usage': 'step' },
+ 'stepout': { 'parse': DebugCommand.prototype.parseStepOut_,
+ 'usage': 'stepout' },
+ // local eval for debugging - remove this later
+ 'shell': { 'parse': DebugCommand.parseShell_,
+ 'usage': 'shell <expression>',
+ 'while_running': true,
+ 'hidden': true },
+ 'shelldebug': { 'parse': DebugCommand.parseShellDebug_,
+ 'usage': 'shelldebug',
+ 'while_running': true,
+ 'hidden': true },
+};
+
+
+/**
+ * Debug shell using the new JSON protocol
+ * @param {Object} tab - which tab is to be debugged. This is an internal
+ * Chrome object.
+ * @constructor
+ */
+function DebugShell(tab) {
+ this.tab = tab;
+ this.tab.attach();
+ this.ready = true;
+ this.running = true;
+ this.current_command = undefined;
+ this.pending_commands = [];
+ // The auto continue flag is used to indicate whether the JavaScript execution
+ // should automatically continue after a break event and the processing of
+ // pending commands. This is used to make it possible for the user to issue
+ // commands, e.g. setting break points, without making an explicit break. In
+ // this case the debugger will silently issue a forced break issue the command
+ // and silently continue afterwards.
+ this.auto_continue = false;
+ this.debug = false;
+ this.current_line = -1;
+ this.current_pos = -1;
+ this.current_frame = 0;
+ this.current_script = undefined;
+ this.scripts = [];
+
+ // Mapping of breakpoints id --> info.
+ // Must use numeric keys.
+ this.breakpoints = [];
+};
+
+DebugShell.prototype.set_ready = function(ready) {
+ if (ready != this.ready) {
+ this.ready = ready;
+ ChromeNode.setDebuggerReady(this.ready);
+ }
+};
+
+DebugShell.prototype.set_running = function(running) {
+ if (running != this.running) {
+ this.running = running;
+ ChromeNode.setDebuggerBreak(!this.running);
+ }
+};
+
+/**
+ * Execute a constructed DebugCommand object if possible, otherwise pend.
+ * @param cmd {DebugCommand} - command to execute
+ */
+DebugShell.prototype.process_command = function(cmd) {
+ dprint("Running: " + (this.running ? "yes" : "no"));
+
+ // The "break" commands needs to be handled seperatly
+ if (cmd.command == "break") {
+ if (this.running) {
+ // Schedule a break.
+ print("Stopping JavaScript execution...");
+ this.tab.debugBreak(false);
+ } else {
+ print("JavaScript execution already stopped.");
+ }
+ return;
+ }
+
+ // If page is running an break needs to be issued.
+ if (this.running) {
+ // Some requests are not valid when the page is running.
+ var cmd_info = DebugCommand.commands[cmd.user_command];
+ if (!cmd_info['while_running']) {
+ print(cmd.user_command + " can only be run while paused");
+ return;
+ }
+
+ // Add the command as pending before scheduling a break.
+ this.pending_commands.push(cmd);
+ dprint("pending command: " + cmd.toJSONProtocol());
+
+ // Schedule a forced break and enable auto continue.
+ this.tab.debugBreak(true);
+ this.auto_continue = true;
+ this.set_ready(false);
+ return;
+ }
+
+ // If waiting for a response add command as pending otherwise send the
+ // command.
+ if (this.current_command) {
+ this.pending_commands.push(cmd);
+ dprint("pending command: " + cmd.toJSONProtocol());
+ } else {
+ this.current_command = cmd;
+ cmd.sendToDebugger(this.tab);
+ this.set_ready(false);
+ }
+};
+
+/**
+ * Handle a break event from the debugger.
+ * @param msg {ResponsePacket} - break_event protocol message to handle
+ */
+DebugShell.prototype.event_break = function(break_event) {
+ this.current_frame = 0;
+ this.set_running(false);
+ var body = break_event.body();
+ if (body) {
+ this.current_script = body.script;
+ var loc = DebugCommand.getSourceLocation(body.script,
+ body.sourceLineText, body.sourceLine, body.invocationText);
+ var location = loc[0];
+ var source = loc[1];
+ this.current_line = loc[2];
+ if (body.breakpoints) {
+ // Always disable auto continue if a real break point is hit.
+ this.auto_continue = false;
+ var breakpoints = body.breakpoints;
+ print("paused at breakpoint " + breakpoints.join(",") + ": " +
+ location);
+ for (var i = 0; i < breakpoints.length; i++)
+ this.didHitBreakpoint(parseInt(breakpoints[i]));
+ } else if (body.scriptData == "") {
+ print("paused");
+ } else {
+ // step, stepout, next, "break" and a "debugger" line in the code
+ // are all treated the same (they're not really distinguishable anyway)
+ if (location != this.last_break_location) {
+ // We only print the location (function + script) when it changes,
+ // so as we step, you only see the source line when you transition
+ // to a new script and/or function. Also if auto continue is enables
+ // don't print the break location.
+ if (!this.auto_continue)
+ print(location);
+ }
+ }
+ // Print th current source line unless auto continue is enabled.
+ if (source && !this.auto_continue)
+ print(source);
+ this.last_break_location = location;
+ }
+ if (!this.auto_continue)
+ this.set_ready(true);
+};
+
+/**
+ * Handle an exception event from the debugger.
+ * @param msg {ResponsePacket} - exception_event protocol message to handle
+ */
+DebugShell.prototype.event_exception = function(exception_event) {
+ this.set_running(false);
+ this.set_ready(true);
+ var body = exception_event.body();
+ if (body) {
+ if (body["uncaught"]) {
+ print("uncaught exception " + body["exception"].text);
+ } else {
+ print("paused at exception " + body["exception"].text);
+ }
+ }
+};
+
+DebugShell.prototype.matchScript = function(script_match, line) {
+ var script = null;
+ // In the v8 debugger, all scripts have a name, line offset and line count
+ // Script names are usually URLs which are a pain to have to type again and
+ // again, so we match the tail end of the script name. This makes it easy
+ // to type break foo.js:23 rather than
+ // http://www.foo.com/bar/baz/quux/test/foo.js:23. In addition to the tail
+ // of the name we also look at the lines the script cover. If there are
+ // several scripts with the same tail including the requested line we match
+ // the first one encountered.
+ // TODO(sgjesse) Find how to handle several matching scripts.
+ var candidate_scripts = [];
+ for (var i in this.scripts) {
+ if (this.scripts[i].name &&
+ this.scripts[i].name.indexOf(script_match) >= 0) {
+ candidate_scripts.push(this.scripts[i]);
+ }
+ }
+ for (var i in candidate_scripts) {
+ var s = candidate_scripts[i];
+ var from = s.lineOffset;
+ var to = from + s.lineCount;
+ if (from <= line && line < to) {
+ script = s;
+ break;
+ }
+ }
+ if (script)
+ return script;
+ else
+ return null;
+}
+
+// The Chrome Subshell interface requires:
+// prompt(), command(), response(), exit() and on_disconnect()
+
+/**
+ * Called by Chrome Shell to get a prompt string to display.
+ */
+DebugShell.prototype.prompt = function() {
+ if (this.current_command)
+ return '';
+ if (!this.running)
+ return 'v8(paused)> ';
+ else
+ return 'v8(running)> ';
+};
+
+/**
+ * Called by Chrome Shell when command input has been received from the user.
+ */
+DebugShell.prototype.command = function(str) {
+ if (this.tab) {
+ str = DebugCommand.trim(str);
+ if (str.length) {
+ var cmd = new DebugCommand(str);
+ cmd.from_user = true;
+ if (cmd.type == "request")
+ this.process_command(cmd);
+ }
+ } else {
+ print(">>not connected to a tab");
+ }
+};
+
+/**
+ * Called by Chrome Shell when a response to a previous command has been
+ * received.
+ * @param {Object} msg Message object.
+ */
+DebugShell.prototype.response = function(msg) {
+ dprint("received: " + (msg && msg.type));
+ var response;
+ try {
+ response = new ProtocolPackage(msg);
+ } catch (error) {
+ print(error.toString(), str);
+ return;
+ }
+ if (response.type() == "event") {
+ ev = response.event();
+ if (ev == "break") {
+ this.event_break(response);
+ } else if (ev == "exception") {
+ this.event_exception(response);
+ }
+ } else if (response.type() == "response") {
+ if (response.requestSeq() != undefined) {
+ if (!this.current_command || this.current_command.seq != response.requestSeq()){
+ throw("received response to unknown command " + str);
+ }
+ } else {
+ // TODO(erikkay): should we reject these when they happen?
+ print(">>no request_seq in response " + str);
+ }
+ var cmd = DebugCommand.commands[this.current_command.user_command]
+ response.command = this.current_command;
+ this.current_command = null
+ this.set_running(response.running());
+ if (!response.success()) {
+ print(response.message());
+ } else {
+ var handler = cmd['response'];
+ if (handler != undefined) {
+ handler.call(this, response);
+ }
+ }
+ this.set_ready(true);
+ }
+
+ // Process next pending command if any.
+ if (this.pending_commands.length) {
+ this.process_command(this.pending_commands.shift());
+ } else if (this.auto_continue) {
+ // If no more pending commands and auto continue is active issue a continue command.
+ this.auto_continue = false;
+ this.process_command(new DebugCommand("continue"));
+ }
+};
+
+/**
+ * Called when a breakpoint has been set.
+ * @param {BreakpointInfo} info - details of breakpoint set.
+ */
+DebugShell.prototype.addedBreakpoint = function(info) {
+ print("set breakpoint #" + info.id);
+ this.breakpoints[info.id] = info;
+}
+
+/**
+ * Called when a breakpoint has been cleared.
+ * @param {int} id - the breakpoint number that was cleared.
+ */
+DebugShell.prototype.clearedBreakpoint = function(id) {
+ assertIsNumberType(id, "clearedBreakpoint called with invalid id");
+
+ print("cleared breakpoint #" + id);
+ delete this.breakpoints[id];
+}
+
+/**
+ * Called when a breakpoint has been reached.
+ * @param {int} id - the breakpoint number that was hit.
+ */
+DebugShell.prototype.didHitBreakpoint = function(id) {
+ assertIsNumberType(id, "didHitBreakpoint called with invalid id");
+
+ var info = this.breakpoints[id];
+ if (!info)
+ throw "Could not find breakpoint #" + id;
+
+ info.hit_count ++;
+}
+
+/**
+ * Print a summary of the specified breakpoints.
+ *
+ * @param {Array<BreakpointInfo>} breakpointsToPrint - List of breakpoints. The
+ * index is unused (id is determined from the info).
+ */
+DebugShell.printBreakpoints_ = function(breakpoints) {
+ // TODO(ericroman): this would look much nicer if we could output as an HTML
+ // table. I tried outputting as formatted text table, but this looks aweful
+ // once it triggers wrapping (which is very likely if the target is a script)
+
+ // Output as a comma separated list of key=value
+ for (var i in breakpoints) {
+ var b = breakpoints[i];
+ var props = ["id", "hit_count", "type", "target", "line", "position",
+ "condition"];
+ var propertyList = [];
+ for (var i = 0; i < props.length; i++) {
+ var prop = props[i];
+ var val = b[prop];
+ if (val != undefined)
+ propertyList.push(prop + "=" + val);
+ }
+ print(propertyList.join(", "));
+ }
+}
+
+/**
+ * Called by Chrome Shell when the outer shell is detaching from debugging
+ * this tab.
+ */
+DebugShell.prototype.exit = function() {
+ if (this.tab) {
+ this.tab.detach();
+ this.tab = null;
+ }
+};
+
+/**
+ * Called by the Chrome Shell when the tab that the shell is debugging
+ * have attached.
+ */
+DebugShell.prototype.on_attach = function(title) {
+ if (!title)
+ title = "Untitled";
+ print('attached to ' + title);
+ // on attach, we update our current script list
+ var cmd = new DebugCommand("scripts");
+ cmd.from_user = false;
+ this.process_command(cmd);
+};
+
+
+/**
+ * Called by the Chrome Shell when the tab that the shell is debugging
+ * went away.
+ */
+DebugShell.prototype.on_disconnect = function() {
+ print(">>lost connection to tab");
+ this.tab = null;
+};
+
+
+/**
+ * Protocol packages send from the debugger.
+ * @param {string} json - raw protocol packet as JSON string.
+ * @constructor
+ */
+function ProtocolPackage(msg) {
+ this.packet_ = 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];
+ }
+ }
+}
+
+
+/**
+ * Get the packet type.
+ * @return {String} the packet type
+ */
+ProtocolPackage.prototype.type = function() {
+ return this.packet_.type;
+}
+
+
+/**
+ * Get the packet event.
+ * @return {Object} the packet event
+ */
+ProtocolPackage.prototype.event = function() {
+ return this.packet_.event;
+}
+
+
+/**
+ * Get the packet request sequence.
+ * @return {number} the packet request sequence
+ */
+ProtocolPackage.prototype.requestSeq = function() {
+ return this.packet_.request_seq;
+}
+
+
+/**
+ * Get the packet request sequence.
+ * @return {number} the packet request sequence
+ */
+ProtocolPackage.prototype.running = function() {
+ return this.packet_.running ? true : false;
+}
+
+
+ProtocolPackage.prototype.success = function() {
+ return this.packet_.success ? true : false;
+}
+
+
+ProtocolPackage.prototype.message = function() {
+ return this.packet_.message;
+}
+
+
+ProtocolPackage.prototype.body = function() {
+ return this.packet_.body;
+}
+
+
+ProtocolPackage.prototype.lookup = function(handle) {
+ return this.refs_[handle];
+}
+
+
+/**
+ * Structure that holds the details about a breakpoint.
+ * @constructor
+ *
+ * @param {int} id - breakpoint number
+ * @param {string} type - "script" or "function"
+ * @param {string} target - either a function name, or script url
+ * @param {int} line - line number in the script, or undefined
+ * @param {int} position - column in the script, or undefined
+ * @param {string} condition - boolean expression, or undefined
+ */
+function BreakpointInfo(id, type, target, line, position, condition) {
+ this.id = id;
+ this.type = type;
+ this.target = target;
+
+ if (line != undefined)
+ this.line = line;
+ if (position != undefined)
+ this.position = position;
+ if (condition != undefined)
+ this.condition = condition;
+
+ this.hit_count = 0;
+
+ // Check that the id is numeric, otherwise will run into problems later
+ assertIsNumberType(this.id, "id is not a number");
+}
+
+var shell_ = null;
+DebugShell.initDebugShell = function(debuggerUI) {
+ if (!DebugShell.singleton) {
+ DebugShell.ui = debuggerUI;
+ DebugShell.singleton = new DebugShell(TabNode);
+ shell_ = DebugShell.singleton;
+
+ // enable debug output
+ //shell_.debug = true;
+ }
+};
+
+/**
+ * Print debugging message when DebugShell's debug flag is true.
+ */
+function dprint(str) {
+ if (shell_ && shell_.debug) {
+ print(str);
+ }
+};
+
+/**
+ * Helper that throws error if x is not a number
+ * @param x {object} - object to test type of
+ * @param error_message {string} - error to throw on failure
+ */
+function assertIsNumberType(x, error_message) {
+ if (typeof x != "number")
+ throw error_message;
+}
+
+////////////////////// migration staff //////////////////////////
+// This file was copied from chrome\browser\debugger\resources\debugger_shell.js
+
+function print(txt) {
+ var ui = DebugShell.ui;
+ if (ui) {
+ ui.appendText(txt);
+ }
+}
+
+var TabNode = {
+ debugBreak: function(force) {
+ DebuggerIPC.sendMessage(["debugBreak", force]);
+ },
+ attach: function() {
+ DebuggerIPC.sendMessage(["attach"]);
+ },
+ detach: function() {
+ // TODO(yurys): send this from DebugHandler when it's being destroyed?
+ DebuggerIPC.sendMessage(["detach"]);
+ },
+ sendToDebugger: function(str) {
+ DebuggerIPC.sendMessage(["sendToDebugger", str]);
+ }
+};
+
+var ChromeNode = {
+ setDebuggerReady: function(isReady) {
+ DebuggerIPC.sendMessage(["setDebuggerReady", isReady]);
+ },
+ setDebuggerBreak: function(isBreak) {
+ var ui = DebugShell.ui;
+ if (ui) {
+ ui.setDebuggerBreak(isBreak);
+ }
+ DebuggerIPC.sendMessage(["setDebuggerBreak", isBreak]);
+ }
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ElementsPanel.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ElementsPanel.js
new file mode 100644
index 0000000..3c9be54
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ElementsPanel.js
@@ -0,0 +1,1206 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ElementsPanel = function()
+{
+ WebInspector.Panel.call(this);
+
+ this.element.addStyleClass("elements");
+
+ this.contentElement = document.createElement("div");
+ this.contentElement.id = "elements-content";
+ this.contentElement.className = "outline-disclosure";
+
+ this.treeOutline = new WebInspector.ElementsTreeOutline();
+ this.treeOutline.panel = this;
+ this.treeOutline.includeRootDOMNode = false;
+ this.treeOutline.selectEnabled = true;
+
+ this.treeOutline.focusedNodeChanged = function(forceUpdate)
+ {
+ if (this.panel.visible && WebInspector.currentFocusElement !== document.getElementById("search"))
+ WebInspector.currentFocusElement = document.getElementById("main-panels");
+
+ this.panel.updateBreadcrumb(forceUpdate);
+
+ for (var pane in this.panel.sidebarPanes)
+ this.panel.sidebarPanes[pane].needsUpdate = true;
+
+ this.panel.updateStyles(true);
+ this.panel.updateMetrics();
+ this.panel.updateProperties();
+
+ if (InspectorController.searchingForNode()) {
+ InspectorController.toggleNodeSearch();
+ this.panel.nodeSearchButton.removeStyleClass("toggled-on");
+ }
+ };
+
+ this.contentElement.appendChild(this.treeOutline.element);
+
+ this.crumbsElement = document.createElement("div");
+ this.crumbsElement.className = "crumbs";
+ this.crumbsElement.addEventListener("mousemove", this._mouseMovedInCrumbs.bind(this), false);
+ this.crumbsElement.addEventListener("mouseout", this._mouseMovedOutOfCrumbs.bind(this), false);
+
+ this.sidebarPanes = {};
+ this.sidebarPanes.styles = new WebInspector.StylesSidebarPane();
+ this.sidebarPanes.metrics = new WebInspector.MetricsSidebarPane();
+ this.sidebarPanes.properties = new WebInspector.PropertiesSidebarPane();
+
+ this.sidebarPanes.styles.onexpand = this.updateStyles.bind(this);
+ this.sidebarPanes.metrics.onexpand = this.updateMetrics.bind(this);
+ this.sidebarPanes.properties.onexpand = this.updateProperties.bind(this);
+
+ this.sidebarPanes.styles.expanded = true;
+
+ this.sidebarPanes.styles.addEventListener("style edited", this._stylesPaneEdited, this);
+ this.sidebarPanes.styles.addEventListener("style property toggled", this._stylesPaneEdited, this);
+ this.sidebarPanes.metrics.addEventListener("metrics edited", this._metricsPaneEdited, this);
+
+ this.sidebarElement = document.createElement("div");
+ this.sidebarElement.id = "elements-sidebar";
+
+ this.sidebarElement.appendChild(this.sidebarPanes.styles.element);
+ this.sidebarElement.appendChild(this.sidebarPanes.metrics.element);
+ this.sidebarElement.appendChild(this.sidebarPanes.properties.element);
+
+ this.sidebarResizeElement = document.createElement("div");
+ this.sidebarResizeElement.className = "sidebar-resizer-vertical";
+ this.sidebarResizeElement.addEventListener("mousedown", this.rightSidebarResizerDragStart.bind(this), false);
+
+ this.nodeSearchButton = document.createElement("button");
+ this.nodeSearchButton.title = WebInspector.UIString("Select an element in the page to inspect it.");
+ this.nodeSearchButton.id = "node-search-status-bar-item";
+ this.nodeSearchButton.className = "status-bar-item";
+ this.nodeSearchButton.addEventListener("click", this._nodeSearchButtonClicked.bind(this), false);
+
+ this.searchingForNode = false;
+
+ this.element.appendChild(this.contentElement);
+ this.element.appendChild(this.sidebarElement);
+ this.element.appendChild(this.sidebarResizeElement);
+
+ this._mutationMonitoredWindows = [];
+ this._nodeInsertedEventListener = InspectorController.wrapCallback(this._nodeInserted.bind(this));
+ this._nodeRemovedEventListener = InspectorController.wrapCallback(this._nodeRemoved.bind(this));
+ this._contentLoadedEventListener = InspectorController.wrapCallback(this._contentLoaded.bind(this));
+
+ this.reset();
+}
+
+WebInspector.ElementsPanel.prototype = {
+ toolbarItemClass: "elements",
+
+ get toolbarItemLabel()
+ {
+ return WebInspector.UIString("Elements");
+ },
+
+ get statusBarItems()
+ {
+ return [this.nodeSearchButton, this.crumbsElement];
+ },
+
+ updateStatusBarItems: function()
+ {
+ this.updateBreadcrumbSizes();
+ },
+
+ show: function()
+ {
+ WebInspector.Panel.prototype.show.call(this);
+ this.sidebarResizeElement.style.right = (this.sidebarElement.offsetWidth - 3) + "px";
+ this.updateBreadcrumb();
+ this.treeOutline.updateSelection();
+ if (this.recentlyModifiedNodes.length)
+ this._updateModifiedNodes();
+ },
+
+ hide: function()
+ {
+ WebInspector.Panel.prototype.hide.call(this);
+
+ WebInspector.hoveredDOMNode = null;
+
+ if (InspectorController.searchingForNode()) {
+ InspectorController.toggleNodeSearch();
+ this.nodeSearchButton.removeStyleClass("toggled-on");
+ }
+ },
+
+ resize: function()
+ {
+ this.treeOutline.updateSelection();
+ this.updateBreadcrumbSizes();
+ },
+
+ reset: function()
+ {
+ this.rootDOMNode = null;
+ this.focusedDOMNode = null;
+
+ WebInspector.hoveredDOMNode = null;
+
+ if (InspectorController.searchingForNode()) {
+ InspectorController.toggleNodeSearch();
+ this.nodeSearchButton.removeStyleClass("toggled-on");
+ }
+
+ this.recentlyModifiedNodes = [];
+ this.unregisterAllMutationEventListeners();
+
+ delete this.currentQuery;
+ this.searchCanceled();
+
+ var inspectedWindow = InspectorController.inspectedWindow();
+ if (!inspectedWindow || !inspectedWindow.document)
+ return;
+
+ if (!inspectedWindow.document.firstChild) {
+ function contentLoaded()
+ {
+ inspectedWindow.document.removeEventListener("DOMContentLoaded", contentLoadedCallback, false);
+
+ this.reset();
+ }
+
+ var contentLoadedCallback = InspectorController.wrapCallback(contentLoaded.bind(this));
+ inspectedWindow.document.addEventListener("DOMContentLoaded", contentLoadedCallback, false);
+ return;
+ }
+
+ // If the window isn't visible, return early so the DOM tree isn't built
+ // and mutation event listeners are not added.
+ if (!InspectorController.isWindowVisible())
+ return;
+
+ this.registerMutationEventListeners(inspectedWindow);
+
+ var inspectedRootDocument = inspectedWindow.document;
+ this.rootDOMNode = inspectedRootDocument;
+
+ var canidateFocusNode = inspectedRootDocument.body || inspectedRootDocument.documentElement;
+ if (canidateFocusNode) {
+ this.treeOutline.suppressSelectHighlight = true;
+ this.focusedDOMNode = canidateFocusNode;
+ this.treeOutline.suppressSelectHighlight = false;
+
+ if (this.treeOutline.selectedTreeElement)
+ this.treeOutline.selectedTreeElement.expand();
+ }
+ },
+
+ includedInSearchResultsPropertyName: "__includedInInspectorSearchResults",
+
+ searchCanceled: function()
+ {
+ if (this._searchResults) {
+ const searchResultsProperty = this.includedInSearchResultsPropertyName;
+ for (var i = 0; i < this._searchResults.length; ++i) {
+ var node = this._searchResults[i];
+
+ // Remove the searchResultsProperty since there might be an unfinished search.
+ delete node[searchResultsProperty];
+
+ var treeElement = this.treeOutline.findTreeElement(node);
+ if (treeElement)
+ treeElement.highlighted = false;
+ }
+ }
+
+ WebInspector.updateSearchMatchesCount(0, this);
+
+ if (this._currentSearchChunkIntervalIdentifier) {
+ clearInterval(this._currentSearchChunkIntervalIdentifier);
+ delete this._currentSearchChunkIntervalIdentifier;
+ }
+
+ this._currentSearchResultIndex = 0;
+ this._searchResults = [];
+ },
+
+ performSearch: function(query)
+ {
+ // Call searchCanceled since it will reset everything we need before doing a new search.
+ this.searchCanceled();
+
+ const whitespaceTrimmedQuery = query.trimWhitespace();
+ if (!whitespaceTrimmedQuery.length)
+ return;
+
+ var tagNameQuery = whitespaceTrimmedQuery;
+ var attributeNameQuery = whitespaceTrimmedQuery;
+ var startTagFound = (tagNameQuery.indexOf("<") === 0);
+ var endTagFound = (tagNameQuery.lastIndexOf(">") === (tagNameQuery.length - 1));
+
+ if (startTagFound || endTagFound) {
+ var tagNameQueryLength = tagNameQuery.length;
+ tagNameQuery = tagNameQuery.substring((startTagFound ? 1 : 0), (endTagFound ? (tagNameQueryLength - 1) : tagNameQueryLength));
+ }
+
+ // Check the tagNameQuery is it is a possibly valid tag name.
+ if (!/^[a-zA-Z0-9\-_:]+$/.test(tagNameQuery))
+ tagNameQuery = null;
+
+ // Check the attributeNameQuery is it is a possibly valid tag name.
+ if (!/^[a-zA-Z0-9\-_:]+$/.test(attributeNameQuery))
+ attributeNameQuery = null;
+
+ const escapedQuery = query.escapeCharacters("'");
+ const escapedTagNameQuery = (tagNameQuery ? tagNameQuery.escapeCharacters("'") : null);
+ const escapedWhitespaceTrimmedQuery = whitespaceTrimmedQuery.escapeCharacters("'");
+ const searchResultsProperty = this.includedInSearchResultsPropertyName;
+
+ var updatedMatchCountOnce = false;
+ var matchesCountUpdateTimeout = null;
+
+ function updateMatchesCount()
+ {
+ WebInspector.updateSearchMatchesCount(this._searchResults.length, this);
+ matchesCountUpdateTimeout = null;
+ updatedMatchCountOnce = true;
+ }
+
+ function updateMatchesCountSoon()
+ {
+ if (!updatedMatchCountOnce)
+ return updateMatchesCount.call(this);
+ if (matchesCountUpdateTimeout)
+ return;
+ // Update the matches count every half-second so it doesn't feel twitchy.
+ matchesCountUpdateTimeout = setTimeout(updateMatchesCount.bind(this), 500);
+ }
+
+ function addNodesToResults(nodes, length, getItem)
+ {
+ if (!length)
+ return;
+
+ for (var i = 0; i < length; ++i) {
+ var node = getItem.call(nodes, i);
+ // Skip this node if it already has the property.
+ if (searchResultsProperty in node)
+ continue;
+
+ if (!this._searchResults.length) {
+ this._currentSearchResultIndex = 0;
+ this.focusedDOMNode = node;
+ }
+
+ node[searchResultsProperty] = true;
+ this._searchResults.push(node);
+
+ // Highlight the tree element to show it matched the search.
+ // FIXME: highlight the substrings in text nodes and attributes.
+ var treeElement = this.treeOutline.findTreeElement(node);
+ if (treeElement)
+ treeElement.highlighted = true;
+ }
+
+ updateMatchesCountSoon.call(this);
+ }
+
+ function matchExactItems(doc)
+ {
+ matchExactId.call(this, doc);
+ matchExactClassNames.call(this, doc);
+ matchExactTagNames.call(this, doc);
+ matchExactAttributeNames.call(this, doc);
+ }
+
+ function matchExactId(doc)
+ {
+ const result = doc.__proto__.getElementById.call(doc, whitespaceTrimmedQuery);
+ addNodesToResults.call(this, result, (result ? 1 : 0), function() { return this });
+ }
+
+ function matchExactClassNames(doc)
+ {
+ const result = doc.__proto__.getElementsByClassName.call(doc, whitespaceTrimmedQuery);
+ addNodesToResults.call(this, result, result.length, result.item);
+ }
+
+ function matchExactTagNames(doc)
+ {
+ if (!tagNameQuery)
+ return;
+ const result = doc.__proto__.getElementsByTagName.call(doc, tagNameQuery);
+ addNodesToResults.call(this, result, result.length, result.item);
+ }
+
+ function matchExactAttributeNames(doc)
+ {
+ if (!attributeNameQuery)
+ return;
+ const result = doc.__proto__.querySelectorAll.call(doc, "[" + attributeNameQuery + "]");
+ addNodesToResults.call(this, result, result.length, result.item);
+ }
+
+ function matchPartialTagNames(doc)
+ {
+ if (!tagNameQuery)
+ return;
+ const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function matchStartOfTagNames(doc)
+ {
+ if (!tagNameQuery)
+ return;
+ const result = doc.__proto__.evaluate.call(doc, "//*[starts-with(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function matchPartialTagNamesAndAttributeValues(doc)
+ {
+ if (!tagNameQuery) {
+ matchPartialAttributeValues.call(this, doc);
+ return;
+ }
+
+ const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "') or contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function matchPartialAttributeValues(doc)
+ {
+ const result = doc.__proto__.evaluate.call(doc, "//*[contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function matchStyleSelector(doc)
+ {
+ const result = doc.__proto__.querySelectorAll.call(doc, whitespaceTrimmedQuery);
+ addNodesToResults.call(this, result, result.length, result.item);
+ }
+
+ function matchPlainText(doc)
+ {
+ const result = doc.__proto__.evaluate.call(doc, "//text()[contains(., '" + escapedQuery + "')] | //comment()[contains(., '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function matchXPathQuery(doc)
+ {
+ const result = doc.__proto__.evaluate.call(doc, whitespaceTrimmedQuery, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
+ addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem);
+ }
+
+ function finishedSearching()
+ {
+ // Remove the searchResultsProperty now that the search is finished.
+ for (var i = 0; i < this._searchResults.length; ++i)
+ delete this._searchResults[i][searchResultsProperty];
+ }
+
+ const mainFrameDocument = InspectorController.inspectedWindow().document;
+ const searchDocuments = [mainFrameDocument];
+
+ if (tagNameQuery && startTagFound && endTagFound)
+ const searchFunctions = [matchExactTagNames, matchPlainText];
+ else if (tagNameQuery && startTagFound)
+ const searchFunctions = [matchStartOfTagNames, matchPlainText];
+ else if (tagNameQuery && endTagFound) {
+ // FIXME: we should have a matchEndOfTagNames search function if endTagFound is true but not startTagFound.
+ // This requires ends-with() support in XPath, WebKit only supports starts-with() and contains().
+ const searchFunctions = [matchPartialTagNames, matchPlainText];
+ } else if (whitespaceTrimmedQuery === "//*" || whitespaceTrimmedQuery === "*") {
+ // These queries will match every node. Matching everything isn't useful and can be slow for large pages,
+ // so limit the search functions list to plain text and attribute matching.
+ const searchFunctions = [matchPartialAttributeValues, matchPlainText];
+ } else
+ const searchFunctions = [matchExactItems, matchStyleSelector, matchPartialTagNamesAndAttributeValues, matchPlainText, matchXPathQuery];
+
+ // Find all frames, iframes and object elements to search their documents.
+ const querySelectorAllFunction = InspectorController.inspectedWindow().Document.prototype.querySelectorAll;
+ const subdocumentResult = querySelectorAllFunction.call(mainFrameDocument, "iframe, frame, object");
+
+ for (var i = 0; i < subdocumentResult.length; ++i) {
+ var element = subdocumentResult.item(i);
+ if (element.contentDocument)
+ searchDocuments.push(element.contentDocument);
+ }
+
+ const panel = this;
+ var documentIndex = 0;
+ var searchFunctionIndex = 0;
+ var chunkIntervalIdentifier = null;
+
+ // Split up the work into chunks so we don't block the UI thread while processing.
+
+ function processChunk()
+ {
+ var searchDocument = searchDocuments[documentIndex];
+ var searchFunction = searchFunctions[searchFunctionIndex];
+
+ if (++searchFunctionIndex > searchFunctions.length) {
+ searchFunction = searchFunctions[0];
+ searchFunctionIndex = 0;
+
+ if (++documentIndex > searchDocuments.length) {
+ if (panel._currentSearchChunkIntervalIdentifier === chunkIntervalIdentifier)
+ delete panel._currentSearchChunkIntervalIdentifier;
+ clearInterval(chunkIntervalIdentifier);
+ finishedSearching.call(panel);
+ return;
+ }
+
+ searchDocument = searchDocuments[documentIndex];
+ }
+
+ if (!searchDocument || !searchFunction)
+ return;
+
+ try {
+ searchFunction.call(panel, searchDocument);
+ } catch(err) {
+ // ignore any exceptions. the query might be malformed, but we allow that.
+ }
+ }
+
+ processChunk();
+
+ chunkIntervalIdentifier = setInterval(processChunk, 25);
+ this._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier;
+ },
+
+ jumpToNextSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ if (++this._currentSearchResultIndex >= this._searchResults.length)
+ this._currentSearchResultIndex = 0;
+ this.focusedDOMNode = this._searchResults[this._currentSearchResultIndex];
+ },
+
+ jumpToPreviousSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ if (--this._currentSearchResultIndex < 0)
+ this._currentSearchResultIndex = (this._searchResults.length - 1);
+ this.focusedDOMNode = this._searchResults[this._currentSearchResultIndex];
+ },
+
+ inspectedWindowCleared: function(window)
+ {
+ if (InspectorController.isWindowVisible())
+ this.updateMutationEventListeners(window);
+ },
+
+ _addMutationEventListeners: function(monitoredWindow)
+ {
+ monitoredWindow.document.addEventListener("DOMNodeInserted", this._nodeInsertedEventListener, true);
+ monitoredWindow.document.addEventListener("DOMNodeRemoved", this._nodeRemovedEventListener, true);
+ if (monitoredWindow.frameElement)
+ monitoredWindow.addEventListener("DOMContentLoaded", this._contentLoadedEventListener, true);
+ },
+
+ _removeMutationEventListeners: function(monitoredWindow)
+ {
+ if (monitoredWindow.frameElement)
+ monitoredWindow.removeEventListener("DOMContentLoaded", this._contentLoadedEventListener, true);
+ if (!monitoredWindow.document)
+ return;
+ monitoredWindow.document.removeEventListener("DOMNodeInserted", this._nodeInsertedEventListener, true);
+ monitoredWindow.document.removeEventListener("DOMNodeRemoved", this._nodeRemovedEventListener, true);
+ },
+
+ updateMutationEventListeners: function(monitoredWindow)
+ {
+ this._addMutationEventListeners(monitoredWindow);
+ },
+
+ registerMutationEventListeners: function(monitoredWindow)
+ {
+ if (!monitoredWindow || this._mutationMonitoredWindows.indexOf(monitoredWindow) !== -1)
+ return;
+ this._mutationMonitoredWindows.push(monitoredWindow);
+ if (InspectorController.isWindowVisible())
+ this._addMutationEventListeners(monitoredWindow);
+ },
+
+ unregisterMutationEventListeners: function(monitoredWindow)
+ {
+ if (!monitoredWindow || this._mutationMonitoredWindows.indexOf(monitoredWindow) === -1)
+ return;
+ this._mutationMonitoredWindows.remove(monitoredWindow);
+ this._removeMutationEventListeners(monitoredWindow);
+ },
+
+ unregisterAllMutationEventListeners: function()
+ {
+ for (var i = 0; i < this._mutationMonitoredWindows.length; ++i)
+ this._removeMutationEventListeners(this._mutationMonitoredWindows[i]);
+ this._mutationMonitoredWindows = [];
+ },
+
+ get rootDOMNode()
+ {
+ return this.treeOutline.rootDOMNode;
+ },
+
+ set rootDOMNode(x)
+ {
+ this.treeOutline.rootDOMNode = x;
+ },
+
+ get focusedDOMNode()
+ {
+ return this.treeOutline.focusedDOMNode;
+ },
+
+ set focusedDOMNode(x)
+ {
+ this.treeOutline.focusedDOMNode = x;
+ },
+
+ _contentLoaded: function(event)
+ {
+ this.recentlyModifiedNodes.push({node: event.target, parent: event.target.defaultView.frameElement, replaced: true});
+ if (this.visible)
+ this._updateModifiedNodesSoon();
+ },
+
+ _nodeInserted: function(event)
+ {
+ this.recentlyModifiedNodes.push({node: event.target, parent: event.relatedNode, inserted: true});
+ if (this.visible)
+ this._updateModifiedNodesSoon();
+ },
+
+ _nodeRemoved: function(event)
+ {
+ this.recentlyModifiedNodes.push({node: event.target, parent: event.relatedNode, removed: true});
+ if (this.visible)
+ this._updateModifiedNodesSoon();
+ },
+
+ _updateModifiedNodesSoon: function()
+ {
+ if ("_updateModifiedNodesTimeout" in this)
+ return;
+ this._updateModifiedNodesTimeout = setTimeout(this._updateModifiedNodes.bind(this), 0);
+ },
+
+ _updateModifiedNodes: function()
+ {
+ if ("_updateModifiedNodesTimeout" in this) {
+ clearTimeout(this._updateModifiedNodesTimeout);
+ delete this._updateModifiedNodesTimeout;
+ }
+
+ var updatedParentTreeElements = [];
+ var updateBreadcrumbs = false;
+
+ for (var i = 0; i < this.recentlyModifiedNodes.length; ++i) {
+ var replaced = this.recentlyModifiedNodes[i].replaced;
+ var parent = this.recentlyModifiedNodes[i].parent;
+ if (!parent)
+ continue;
+
+ var parentNodeItem = this.treeOutline.findTreeElement(parent, null, null, objectsAreSame);
+ if (parentNodeItem && !parentNodeItem.alreadyUpdatedChildren) {
+ parentNodeItem.updateChildren(replaced);
+ parentNodeItem.alreadyUpdatedChildren = true;
+ updatedParentTreeElements.push(parentNodeItem);
+ }
+
+ if (!updateBreadcrumbs && (objectsAreSame(this.focusedDOMNode, parent) || isAncestorIncludingParentFrames(this.focusedDOMNode, parent)))
+ updateBreadcrumbs = true;
+ }
+
+ for (var i = 0; i < updatedParentTreeElements.length; ++i)
+ delete updatedParentTreeElements[i].alreadyUpdatedChildren;
+
+ this.recentlyModifiedNodes = [];
+
+ if (updateBreadcrumbs)
+ this.updateBreadcrumb(true);
+ },
+
+ _stylesPaneEdited: function()
+ {
+ this.sidebarPanes.metrics.needsUpdate = true;
+ this.updateMetrics();
+ },
+
+ _metricsPaneEdited: function()
+ {
+ this.sidebarPanes.styles.needsUpdate = true;
+ this.updateStyles(true);
+ },
+
+ _mouseMovedInCrumbs: function(event)
+ {
+ var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
+ var crumbElement = nodeUnderMouse.enclosingNodeOrSelfWithClass("crumb");
+
+ WebInspector.hoveredDOMNode = (crumbElement ? crumbElement.representedObject : null);
+
+ if ("_mouseOutOfCrumbsTimeout" in this) {
+ clearTimeout(this._mouseOutOfCrumbsTimeout);
+ delete this._mouseOutOfCrumbsTimeout;
+ }
+ },
+
+ _mouseMovedOutOfCrumbs: function(event)
+ {
+ var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
+ if (nodeUnderMouse.isDescendant(this.crumbsElement))
+ return;
+
+ WebInspector.hoveredDOMNode = null;
+
+ this._mouseOutOfCrumbsTimeout = setTimeout(this.updateBreadcrumbSizes.bind(this), 1000);
+ },
+
+ updateBreadcrumb: function(forceUpdate)
+ {
+ if (!this.visible)
+ return;
+
+ var crumbs = this.crumbsElement;
+
+ var handled = false;
+ var foundRoot = false;
+ var crumb = crumbs.firstChild;
+ while (crumb) {
+ if (objectsAreSame(crumb.representedObject, this.rootDOMNode))
+ foundRoot = true;
+
+ if (foundRoot)
+ crumb.addStyleClass("dimmed");
+ else
+ crumb.removeStyleClass("dimmed");
+
+ if (objectsAreSame(crumb.representedObject, this.focusedDOMNode)) {
+ crumb.addStyleClass("selected");
+ handled = true;
+ } else {
+ crumb.removeStyleClass("selected");
+ }
+
+ crumb = crumb.nextSibling;
+ }
+
+ if (handled && !forceUpdate) {
+ // We don't need to rebuild the crumbs, but we need to adjust sizes
+ // to reflect the new focused or root node.
+ this.updateBreadcrumbSizes();
+ return;
+ }
+
+ crumbs.removeChildren();
+
+ var panel = this;
+
+ function selectCrumbFunction(event)
+ {
+ var crumb = event.currentTarget;
+ if (crumb.hasStyleClass("collapsed")) {
+ // Clicking a collapsed crumb will expose the hidden crumbs.
+ if (crumb === panel.crumbsElement.firstChild) {
+ // If the focused crumb is the first child, pick the farthest crumb
+ // that is still hidden. This allows the user to expose every crumb.
+ var currentCrumb = crumb;
+ while (currentCrumb) {
+ var hidden = currentCrumb.hasStyleClass("hidden");
+ var collapsed = currentCrumb.hasStyleClass("collapsed");
+ if (!hidden && !collapsed)
+ break;
+ crumb = currentCrumb;
+ currentCrumb = currentCrumb.nextSibling;
+ }
+ }
+
+ panel.updateBreadcrumbSizes(crumb);
+ } else {
+ // Clicking a dimmed crumb or double clicking (event.detail >= 2)
+ // will change the root node in addition to the focused node.
+ if (event.detail >= 2 || crumb.hasStyleClass("dimmed"))
+ panel.rootDOMNode = crumb.representedObject.parentNode;
+ panel.focusedDOMNode = crumb.representedObject;
+ }
+
+ event.preventDefault();
+ }
+
+ foundRoot = false;
+ for (var current = this.focusedDOMNode; current; current = parentNodeOrFrameElement(current)) {
+ if (current.nodeType === Node.DOCUMENT_NODE)
+ continue;
+
+ if (objectsAreSame(current, this.rootDOMNode))
+ foundRoot = true;
+
+ var crumb = document.createElement("span");
+ crumb.className = "crumb";
+ crumb.representedObject = current;
+ crumb.addEventListener("mousedown", selectCrumbFunction, false);
+
+ var crumbTitle;
+ switch (current.nodeType) {
+ case Node.ELEMENT_NODE:
+ crumbTitle = current.nodeName.toLowerCase();
+
+ var nameElement = document.createElement("span");
+ nameElement.textContent = crumbTitle;
+ crumb.appendChild(nameElement);
+
+ var idAttribute = current.getAttribute("id");
+ if (idAttribute) {
+ var idElement = document.createElement("span");
+ crumb.appendChild(idElement);
+
+ var part = "#" + idAttribute;
+ crumbTitle += part;
+ idElement.appendChild(document.createTextNode(part));
+
+ // Mark the name as extra, since the ID is more important.
+ nameElement.className = "extra";
+ }
+
+ var classAttribute = current.getAttribute("class");
+ if (classAttribute) {
+ var classes = classAttribute.split(/\s+/);
+ var foundClasses = {};
+
+ if (classes.length) {
+ var classesElement = document.createElement("span");
+ classesElement.className = "extra";
+ crumb.appendChild(classesElement);
+
+ for (var i = 0; i < classes.length; ++i) {
+ var className = classes[i];
+ if (className && !(className in foundClasses)) {
+ var part = "." + className;
+ crumbTitle += part;
+ classesElement.appendChild(document.createTextNode(part));
+ foundClasses[className] = true;
+ }
+ }
+ }
+ }
+
+ break;
+
+ case Node.TEXT_NODE:
+ if (isNodeWhitespace.call(current))
+ crumbTitle = WebInspector.UIString("(whitespace)");
+ else
+ crumbTitle = WebInspector.UIString("(text)");
+ break
+
+ case Node.COMMENT_NODE:
+ crumbTitle = "<!-->";
+ break;
+
+ case Node.DOCUMENT_TYPE_NODE:
+ crumbTitle = "<!DOCTYPE>";
+ break;
+
+ default:
+ crumbTitle = current.nodeName.toLowerCase();
+ }
+
+ if (!crumb.childNodes.length) {
+ var nameElement = document.createElement("span");
+ nameElement.textContent = crumbTitle;
+ crumb.appendChild(nameElement);
+ }
+
+ crumb.title = crumbTitle;
+
+ if (foundRoot)
+ crumb.addStyleClass("dimmed");
+ if (objectsAreSame(current, this.focusedDOMNode))
+ crumb.addStyleClass("selected");
+ if (!crumbs.childNodes.length)
+ crumb.addStyleClass("end");
+
+ crumbs.appendChild(crumb);
+ }
+
+ if (crumbs.hasChildNodes())
+ crumbs.lastChild.addStyleClass("start");
+
+ this.updateBreadcrumbSizes();
+ },
+
+ updateBreadcrumbSizes: function(focusedCrumb)
+ {
+ if (!this.visible)
+ return;
+
+ if (document.body.offsetWidth <= 0) {
+ // The stylesheet hasn't loaded yet or the window is closed,
+ // so we can't calculate what is need. Return early.
+ return;
+ }
+
+ var crumbs = this.crumbsElement;
+ if (!crumbs.childNodes.length || crumbs.offsetWidth <= 0)
+ return; // No crumbs, do nothing.
+
+ // A Zero index is the right most child crumb in the breadcrumb.
+ var selectedIndex = 0;
+ var focusedIndex = 0;
+ var selectedCrumb;
+
+ var i = 0;
+ var crumb = crumbs.firstChild;
+ while (crumb) {
+ // Find the selected crumb and index.
+ if (!selectedCrumb && crumb.hasStyleClass("selected")) {
+ selectedCrumb = crumb;
+ selectedIndex = i;
+ }
+
+ // Find the focused crumb index.
+ if (crumb === focusedCrumb)
+ focusedIndex = i;
+
+ // Remove any styles that affect size before
+ // deciding to shorten any crumbs.
+ if (crumb !== crumbs.lastChild)
+ crumb.removeStyleClass("start");
+ if (crumb !== crumbs.firstChild)
+ crumb.removeStyleClass("end");
+
+ crumb.removeStyleClass("compact");
+ crumb.removeStyleClass("collapsed");
+ crumb.removeStyleClass("hidden");
+
+ crumb = crumb.nextSibling;
+ ++i;
+ }
+
+ // Restore the start and end crumb classes in case they got removed in coalesceCollapsedCrumbs().
+ // The order of the crumbs in the document is opposite of the visual order.
+ crumbs.firstChild.addStyleClass("end");
+ crumbs.lastChild.addStyleClass("start");
+
+ function crumbsAreSmallerThanContainer()
+ {
+ var rightPadding = 20;
+ var errorWarningElement = document.getElementById("error-warning-count");
+ if (!WebInspector.console.visible && errorWarningElement)
+ rightPadding += errorWarningElement.offsetWidth;
+ return ((crumbs.totalOffsetLeft + crumbs.offsetWidth + rightPadding) < window.innerWidth);
+ }
+
+ if (crumbsAreSmallerThanContainer())
+ return; // No need to compact the crumbs, they all fit at full size.
+
+ var BothSides = 0;
+ var AncestorSide = -1;
+ var ChildSide = 1;
+
+ function makeCrumbsSmaller(shrinkingFunction, direction, significantCrumb)
+ {
+ if (!significantCrumb)
+ significantCrumb = (focusedCrumb || selectedCrumb);
+
+ if (significantCrumb === selectedCrumb)
+ var significantIndex = selectedIndex;
+ else if (significantCrumb === focusedCrumb)
+ var significantIndex = focusedIndex;
+ else {
+ var significantIndex = 0;
+ for (var i = 0; i < crumbs.childNodes.length; ++i) {
+ if (crumbs.childNodes[i] === significantCrumb) {
+ significantIndex = i;
+ break;
+ }
+ }
+ }
+
+ function shrinkCrumbAtIndex(index)
+ {
+ var shrinkCrumb = crumbs.childNodes[index];
+ if (shrinkCrumb && shrinkCrumb !== significantCrumb)
+ shrinkingFunction(shrinkCrumb);
+ if (crumbsAreSmallerThanContainer())
+ return true; // No need to compact the crumbs more.
+ return false;
+ }
+
+ // Shrink crumbs one at a time by applying the shrinkingFunction until the crumbs
+ // fit in the container or we run out of crumbs to shrink.
+ if (direction) {
+ // Crumbs are shrunk on only one side (based on direction) of the signifcant crumb.
+ var index = (direction > 0 ? 0 : crumbs.childNodes.length - 1);
+ while (index !== significantIndex) {
+ if (shrinkCrumbAtIndex(index))
+ return true;
+ index += (direction > 0 ? 1 : -1);
+ }
+ } else {
+ // Crumbs are shrunk in order of descending distance from the signifcant crumb,
+ // with a tie going to child crumbs.
+ var startIndex = 0;
+ var endIndex = crumbs.childNodes.length - 1;
+ while (startIndex != significantIndex || endIndex != significantIndex) {
+ var startDistance = significantIndex - startIndex;
+ var endDistance = endIndex - significantIndex;
+ if (startDistance >= endDistance)
+ var index = startIndex++;
+ else
+ var index = endIndex--;
+ if (shrinkCrumbAtIndex(index))
+ return true;
+ }
+ }
+
+ // We are not small enough yet, return false so the caller knows.
+ return false;
+ }
+
+ function coalesceCollapsedCrumbs()
+ {
+ var crumb = crumbs.firstChild;
+ var collapsedRun = false;
+ var newStartNeeded = false;
+ var newEndNeeded = false;
+ while (crumb) {
+ var hidden = crumb.hasStyleClass("hidden");
+ if (!hidden) {
+ var collapsed = crumb.hasStyleClass("collapsed");
+ if (collapsedRun && collapsed) {
+ crumb.addStyleClass("hidden");
+ crumb.removeStyleClass("compact");
+ crumb.removeStyleClass("collapsed");
+
+ if (crumb.hasStyleClass("start")) {
+ crumb.removeStyleClass("start");
+ newStartNeeded = true;
+ }
+
+ if (crumb.hasStyleClass("end")) {
+ crumb.removeStyleClass("end");
+ newEndNeeded = true;
+ }
+
+ continue;
+ }
+
+ collapsedRun = collapsed;
+
+ if (newEndNeeded) {
+ newEndNeeded = false;
+ crumb.addStyleClass("end");
+ }
+ } else
+ collapsedRun = true;
+ crumb = crumb.nextSibling;
+ }
+
+ if (newStartNeeded) {
+ crumb = crumbs.lastChild;
+ while (crumb) {
+ if (!crumb.hasStyleClass("hidden")) {
+ crumb.addStyleClass("start");
+ break;
+ }
+ crumb = crumb.previousSibling;
+ }
+ }
+ }
+
+ function compact(crumb)
+ {
+ if (crumb.hasStyleClass("hidden"))
+ return;
+ crumb.addStyleClass("compact");
+ }
+
+ function collapse(crumb, dontCoalesce)
+ {
+ if (crumb.hasStyleClass("hidden"))
+ return;
+ crumb.addStyleClass("collapsed");
+ crumb.removeStyleClass("compact");
+ if (!dontCoalesce)
+ coalesceCollapsedCrumbs();
+ }
+
+ function compactDimmed(crumb)
+ {
+ if (crumb.hasStyleClass("dimmed"))
+ compact(crumb);
+ }
+
+ function collapseDimmed(crumb)
+ {
+ if (crumb.hasStyleClass("dimmed"))
+ collapse(crumb);
+ }
+
+ if (!focusedCrumb) {
+ // When not focused on a crumb we can be biased and collapse less important
+ // crumbs that the user might not care much about.
+
+ // Compact child crumbs.
+ if (makeCrumbsSmaller(compact, ChildSide))
+ return;
+
+ // Collapse child crumbs.
+ if (makeCrumbsSmaller(collapse, ChildSide))
+ return;
+
+ // Compact dimmed ancestor crumbs.
+ if (makeCrumbsSmaller(compactDimmed, AncestorSide))
+ return;
+
+ // Collapse dimmed ancestor crumbs.
+ if (makeCrumbsSmaller(collapseDimmed, AncestorSide))
+ return;
+ }
+
+ // Compact ancestor crumbs, or from both sides if focused.
+ if (makeCrumbsSmaller(compact, (focusedCrumb ? BothSides : AncestorSide)))
+ return;
+
+ // Collapse ancestor crumbs, or from both sides if focused.
+ if (makeCrumbsSmaller(collapse, (focusedCrumb ? BothSides : AncestorSide)))
+ return;
+
+ if (!selectedCrumb)
+ return;
+
+ // Compact the selected crumb.
+ compact(selectedCrumb);
+ if (crumbsAreSmallerThanContainer())
+ return;
+
+ // Collapse the selected crumb as a last resort. Pass true to prevent coalescing.
+ collapse(selectedCrumb, true);
+ },
+
+ updateStyles: function(forceUpdate)
+ {
+ var stylesSidebarPane = this.sidebarPanes.styles;
+ if (!stylesSidebarPane.expanded || !stylesSidebarPane.needsUpdate)
+ return;
+
+ stylesSidebarPane.update(this.focusedDOMNode, null, forceUpdate);
+ stylesSidebarPane.needsUpdate = false;
+ },
+
+ updateMetrics: function()
+ {
+ var metricsSidebarPane = this.sidebarPanes.metrics;
+ if (!metricsSidebarPane.expanded || !metricsSidebarPane.needsUpdate)
+ return;
+
+ metricsSidebarPane.update(this.focusedDOMNode);
+ metricsSidebarPane.needsUpdate = false;
+ },
+
+ updateProperties: function()
+ {
+ var propertiesSidebarPane = this.sidebarPanes.properties;
+ if (!propertiesSidebarPane.expanded || !propertiesSidebarPane.needsUpdate)
+ return;
+
+ propertiesSidebarPane.update(this.focusedDOMNode);
+ propertiesSidebarPane.needsUpdate = false;
+ },
+
+ handleKeyEvent: function(event)
+ {
+ this.treeOutline.handleKeyEvent(event);
+ },
+
+ handleCopyEvent: function(event)
+ {
+ // Don't prevent the normal copy if the user has a selection.
+ if (!window.getSelection().isCollapsed)
+ return;
+
+ switch (this.focusedDOMNode.nodeType) {
+ case Node.ELEMENT_NODE:
+ var data = this.focusedDOMNode.outerHTML;
+ break;
+
+ case Node.COMMENT_NODE:
+ var data = "<!--" + this.focusedDOMNode.nodeValue + "-->";
+ break;
+
+ default:
+ case Node.TEXT_NODE:
+ var data = this.focusedDOMNode.nodeValue;
+ }
+
+ event.clipboardData.clearData();
+ event.preventDefault();
+
+ if (data)
+ event.clipboardData.setData("text/plain", data);
+ },
+
+ rightSidebarResizerDragStart: function(event)
+ {
+ WebInspector.elementDragStart(this.sidebarElement, this.rightSidebarResizerDrag.bind(this), this.rightSidebarResizerDragEnd.bind(this), event, "col-resize");
+ },
+
+ rightSidebarResizerDragEnd: function(event)
+ {
+ WebInspector.elementDragEnd(event);
+ },
+
+ rightSidebarResizerDrag: function(event)
+ {
+ var x = event.pageX;
+ var newWidth = Number.constrain(window.innerWidth - x, Preferences.minElementsSidebarWidth, window.innerWidth * 0.66);
+
+ this.sidebarElement.style.width = newWidth + "px";
+ this.contentElement.style.right = newWidth + "px";
+ this.sidebarResizeElement.style.right = (newWidth - 3) + "px";
+
+ this.treeOutline.updateSelection();
+
+ event.preventDefault();
+ },
+
+ _nodeSearchButtonClicked: function(event)
+ {
+ InspectorController.toggleNodeSearch();
+
+ if (InspectorController.searchingForNode())
+ this.nodeSearchButton.addStyleClass("toggled-on");
+ else
+ this.nodeSearchButton.removeStyleClass("toggled-on");
+ }
+}
+
+WebInspector.ElementsPanel.prototype.__proto__ = WebInspector.Panel.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ElementsTreeOutline.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ElementsTreeOutline.js
new file mode 100644
index 0000000..2da2f10
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ElementsTreeOutline.js
@@ -0,0 +1,626 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ElementsTreeOutline = function() {
+ this.element = document.createElement("ol");
+ this.element.addEventListener("mousedown", this._onmousedown.bind(this), false);
+ this.element.addEventListener("dblclick", this._ondblclick.bind(this), false);
+ this.element.addEventListener("mousemove", this._onmousemove.bind(this), false);
+ this.element.addEventListener("mouseout", this._onmouseout.bind(this), false);
+
+ TreeOutline.call(this, this.element);
+
+ this.includeRootDOMNode = true;
+ this.selectEnabled = false;
+ this.rootDOMNode = null;
+ this.focusedDOMNode = null;
+}
+
+WebInspector.ElementsTreeOutline.prototype = {
+ get rootDOMNode()
+ {
+ return this._rootDOMNode;
+ },
+
+ set rootDOMNode(x)
+ {
+ if (objectsAreSame(this._rootDOMNode, x))
+ return;
+
+ this._rootDOMNode = x;
+
+ this.update();
+ },
+
+ get focusedDOMNode()
+ {
+ return this._focusedDOMNode;
+ },
+
+ set focusedDOMNode(x)
+ {
+ if (objectsAreSame(this._focusedDOMNode, x)) {
+ this.revealAndSelectNode(x);
+ return;
+ }
+
+ this._focusedDOMNode = x;
+
+ this.revealAndSelectNode(x);
+
+ // The revealAndSelectNode() method might find a different element if there is inlined text,
+ // and the select() call would change the focusedDOMNode and reenter this setter. So to
+ // avoid calling focusedNodeChanged() twice, first check if _focusedDOMNode is the same
+ // node as the one passed in.
+ if (objectsAreSame(this._focusedDOMNode, x)) {
+ this.focusedNodeChanged();
+
+ if (x && !this.suppressSelectHighlight) {
+ InspectorController.highlightDOMNode(x);
+
+ if ("_restorePreviousHighlightNodeTimeout" in this)
+ clearTimeout(this._restorePreviousHighlightNodeTimeout);
+
+ function restoreHighlightToHoveredNode()
+ {
+ var hoveredNode = WebInspector.hoveredDOMNode;
+ if (hoveredNode)
+ InspectorController.highlightDOMNode(hoveredNode);
+ else
+ InspectorController.hideDOMNodeHighlight();
+ }
+
+ this._restorePreviousHighlightNodeTimeout = setTimeout(restoreHighlightToHoveredNode, 2000);
+ }
+ }
+ },
+
+ update: function()
+ {
+ this.removeChildren();
+
+ if (!this.rootDOMNode)
+ return;
+
+ var treeElement;
+ if (this.includeRootDOMNode) {
+ treeElement = new WebInspector.ElementsTreeElement(this.rootDOMNode);
+ treeElement.selectable = this.selectEnabled;
+ this.appendChild(treeElement);
+ } else {
+ // FIXME: this could use findTreeElement to reuse a tree element if it already exists
+ var node = (Preferences.ignoreWhitespace ? firstChildSkippingWhitespace.call(this.rootDOMNode) : this.rootDOMNode.firstChild);
+ while (node) {
+ treeElement = new WebInspector.ElementsTreeElement(node);
+ treeElement.selectable = this.selectEnabled;
+ this.appendChild(treeElement);
+ node = Preferences.ignoreWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling;
+ }
+ }
+
+ this.updateSelection();
+ },
+
+ updateSelection: function()
+ {
+ if (!this.selectedTreeElement)
+ return;
+ var element = this.treeOutline.selectedTreeElement;
+ element.updateSelection();
+ },
+
+ focusedNodeChanged: function(forceUpdate) {},
+
+ findTreeElement: function(node, isAncestor, getParent, equal)
+ {
+ if (typeof isAncestor === "undefined")
+ isAncestor = isAncestorIncludingParentFrames;
+ if (typeof getParent === "undefined")
+ getParent = parentNodeOrFrameElement;
+ if (typeof equal === "undefined")
+ equal = objectsAreSame;
+
+ var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestor, getParent, equal);
+ if (!treeElement && node.nodeType === Node.TEXT_NODE) {
+ // The text node might have been inlined if it was short, so try to find the parent element.
+ treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestor, getParent, equal);
+ }
+
+ return treeElement;
+ },
+
+ revealAndSelectNode: function(node)
+ {
+ if (!node)
+ return;
+
+ var treeElement = this.findTreeElement(node);
+ if (!treeElement)
+ return;
+
+ treeElement.reveal();
+ treeElement.select();
+ },
+
+ _treeElementFromEvent: function(event)
+ {
+ var root = this.element;
+
+ // We choose this X coordinate based on the knowledge that our list
+ // items extend nearly to the right edge of the outer <ol>.
+ var x = root.totalOffsetLeft + root.offsetWidth - 20;
+
+ var y = event.pageY;
+
+ // Our list items have 1-pixel cracks between them vertically. We avoid
+ // the cracks by checking slightly above and slightly below the mouse
+ // and seeing if we hit the same element each time.
+ var elementUnderMouse = this.treeElementFromPoint(x, y);
+ var elementAboveMouse = this.treeElementFromPoint(x, y - 2);
+ var element;
+ if (elementUnderMouse === elementAboveMouse)
+ element = elementUnderMouse;
+ else
+ element = this.treeElementFromPoint(x, y + 2);
+
+ return element;
+ },
+
+ _ondblclick: function(event)
+ {
+ var element = this._treeElementFromEvent(event);
+
+ if (!element || !element.ondblclick)
+ return;
+
+ element.ondblclick(element, event);
+ },
+
+ _onmousedown: function(event)
+ {
+ var element = this._treeElementFromEvent(event);
+
+ if (!element || element.isEventWithinDisclosureTriangle(event))
+ return;
+
+ element.select();
+ },
+
+ _onmousemove: function(event)
+ {
+ if (this._previousHoveredElement) {
+ this._previousHoveredElement.hovered = false;
+ delete this._previousHoveredElement;
+ }
+
+ var element = this._treeElementFromEvent(event);
+ if (element && !element.elementCloseTag) {
+ element.hovered = true;
+ this._previousHoveredElement = element;
+ }
+
+ WebInspector.hoveredDOMNode = (element && !element.elementCloseTag ? element.representedObject : null);
+ },
+
+ _onmouseout: function(event)
+ {
+ var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
+ if (nodeUnderMouse.isDescendant(this.element))
+ return;
+
+ if (this._previousHoveredElement) {
+ this._previousHoveredElement.hovered = false;
+ delete this._previousHoveredElement;
+ }
+
+ WebInspector.hoveredDOMNode = null;
+ }
+}
+
+WebInspector.ElementsTreeOutline.prototype.__proto__ = TreeOutline.prototype;
+
+WebInspector.ElementsTreeElement = function(node)
+{
+ var hasChildren = node.contentDocument || (Preferences.ignoreWhitespace ? (firstChildSkippingWhitespace.call(node) ? true : false) : node.hasChildNodes());
+ var titleInfo = nodeTitleInfo.call(node, hasChildren, WebInspector.linkifyURL);
+
+ if (titleInfo.hasChildren)
+ this.whitespaceIgnored = Preferences.ignoreWhitespace;
+
+ // The title will be updated in onattach.
+ TreeElement.call(this, "", node, titleInfo.hasChildren);
+}
+
+WebInspector.ElementsTreeElement.prototype = {
+ get highlighted()
+ {
+ return this._highlighted;
+ },
+
+ set highlighted(x)
+ {
+ if (this._highlighted === x)
+ return;
+
+ this._highlighted = x;
+
+ if (this.listItemElement) {
+ if (x)
+ this.listItemElement.addStyleClass("highlighted");
+ else
+ this.listItemElement.removeStyleClass("highlighted");
+ }
+ },
+
+ get hovered()
+ {
+ return this._hovered;
+ },
+
+ set hovered(x)
+ {
+ if (this._hovered === x)
+ return;
+
+ this._hovered = x;
+
+ if (this.listItemElement) {
+ if (x) {
+ this.updateSelection();
+ this.listItemElement.addStyleClass("hovered");
+ } else
+ this.listItemElement.removeStyleClass("hovered");
+ }
+ },
+
+ updateSelection: function()
+ {
+ var listItemElement = this.listItemElement;
+ if (!listItemElement)
+ return;
+
+ if (document.body.offsetWidth <= 0) {
+ // The stylesheet hasn't loaded yet or the window is closed,
+ // so we can't calculate what is need. Return early.
+ return;
+ }
+
+ if (!this.selectionElement) {
+ this.selectionElement = document.createElement("div");
+ this.selectionElement.className = "selection selected";
+ listItemElement.insertBefore(this.selectionElement, listItemElement.firstChild);
+ }
+
+ this.selectionElement.style.height = listItemElement.offsetHeight + "px";
+ },
+
+ onattach: function()
+ {
+ this.listItemElement.addEventListener("mousedown", this.onmousedown.bind(this), false);
+
+ if (this._highlighted)
+ this.listItemElement.addStyleClass("highlighted");
+
+ if (this._hovered) {
+ this.updateSelection();
+ this.listItemElement.addStyleClass("hovered");
+ }
+
+ this._updateTitle();
+
+ this._preventFollowingLinksOnDoubleClick();
+ },
+
+ _preventFollowingLinksOnDoubleClick: function()
+ {
+ var links = this.listItemElement.querySelectorAll("li > .webkit-html-tag > .webkit-html-attribute > .webkit-html-external-link, li > .webkit-html-tag > .webkit-html-attribute > .webkit-html-resource-link");
+ if (!links)
+ return;
+
+ for (var i = 0; i < links.length; ++i)
+ links[i].preventFollowOnDoubleClick = true;
+ },
+
+ onpopulate: function()
+ {
+ if (this.children.length || this.whitespaceIgnored !== Preferences.ignoreWhitespace)
+ return;
+
+ this.whitespaceIgnored = Preferences.ignoreWhitespace;
+
+ this.updateChildren();
+ },
+
+ updateChildren: function(fullRefresh)
+ {
+ if (fullRefresh) {
+ var selectedTreeElement = this.treeOutline.selectedTreeElement;
+ if (selectedTreeElement && selectedTreeElement.hasAncestor(this))
+ this.select();
+ this.removeChildren();
+ }
+
+ var treeElement = this;
+ var treeChildIndex = 0;
+
+ function updateChildrenOfNode(node)
+ {
+ var treeOutline = treeElement.treeOutline;
+ var child = (Preferences.ignoreWhitespace ? firstChildSkippingWhitespace.call(node) : node.firstChild);
+ while (child) {
+ var currentTreeElement = treeElement.children[treeChildIndex];
+ if (!currentTreeElement || !objectsAreSame(currentTreeElement.representedObject, child)) {
+ // Find any existing element that is later in the children list.
+ var existingTreeElement = null;
+ for (var i = (treeChildIndex + 1); i < treeElement.children.length; ++i) {
+ if (objectsAreSame(treeElement.children[i].representedObject, child)) {
+ existingTreeElement = treeElement.children[i];
+ break;
+ }
+ }
+
+ if (existingTreeElement && existingTreeElement.parent === treeElement) {
+ // If an existing element was found and it has the same parent, just move it.
+ var wasSelected = existingTreeElement.selected;
+ treeElement.removeChild(existingTreeElement);
+ treeElement.insertChild(existingTreeElement, treeChildIndex);
+ if (wasSelected)
+ existingTreeElement.select();
+ } else {
+ // No existing element found, insert a new element.
+ var newElement = new WebInspector.ElementsTreeElement(child);
+ newElement.selectable = treeOutline.selectEnabled;
+ treeElement.insertChild(newElement, treeChildIndex);
+ }
+ }
+
+ child = Preferences.ignoreWhitespace ? nextSiblingSkippingWhitespace.call(child) : child.nextSibling;
+ ++treeChildIndex;
+ }
+ }
+
+ // Remove any tree elements that no longer have this node (or this node's contentDocument) as their parent.
+ for (var i = (this.children.length - 1); i >= 0; --i) {
+ if ("elementCloseTag" in this.children[i])
+ continue;
+
+ var currentChild = this.children[i];
+ var currentNode = currentChild.representedObject;
+ var currentParentNode = currentNode.parentNode;
+
+ if (objectsAreSame(currentParentNode, this.representedObject))
+ continue;
+ if (this.representedObject.contentDocument && objectsAreSame(currentParentNode, this.representedObject.contentDocument))
+ continue;
+
+ var selectedTreeElement = this.treeOutline.selectedTreeElement;
+ if (selectedTreeElement && (selectedTreeElement === currentChild || selectedTreeElement.hasAncestor(currentChild)))
+ this.select();
+
+ this.removeChildAtIndex(i);
+
+ if (this.treeOutline.panel && currentNode.contentDocument)
+ this.treeOutline.panel.unregisterMutationEventListeners(currentNode.contentDocument.defaultView);
+ }
+
+ if (this.representedObject.contentDocument)
+ updateChildrenOfNode(this.representedObject.contentDocument);
+ updateChildrenOfNode(this.representedObject);
+
+ var lastChild = this.children[this.children.length - 1];
+ if (this.representedObject.nodeType == Node.ELEMENT_NODE && (!lastChild || !lastChild.elementCloseTag)) {
+ var title = "<span class=\"webkit-html-tag close\">&lt;/" + this.representedObject.nodeName.toLowerCase().escapeHTML() + "&gt;</span>";
+ var item = new TreeElement(title, null, false);
+ item.selectable = false;
+ item.elementCloseTag = true;
+ this.appendChild(item);
+ }
+ },
+
+ onexpand: function()
+ {
+ this.treeOutline.updateSelection();
+
+ if (this.treeOutline.panel && this.representedObject.contentDocument)
+ this.treeOutline.panel.registerMutationEventListeners(this.representedObject.contentDocument.defaultView);
+ },
+
+ oncollapse: function()
+ {
+ this.treeOutline.updateSelection();
+ },
+
+ onreveal: function()
+ {
+ if (this.listItemElement)
+ this.listItemElement.scrollIntoViewIfNeeded(false);
+ },
+
+ onselect: function()
+ {
+ this.treeOutline.focusedDOMNode = this.representedObject;
+ this.updateSelection();
+ },
+
+ onmousedown: function(event)
+ {
+ if (this._editing)
+ return;
+
+ // Prevent selecting the nearest word on double click.
+ if (event.detail >= 2)
+ event.preventDefault();
+ },
+
+ ondblclick: function(treeElement, event)
+ {
+ if (this._editing)
+ return;
+
+ if (this._startEditing(event))
+ return;
+
+ if (this.treeOutline.panel) {
+ this.treeOutline.rootDOMNode = this.representedObject.parentNode;
+ this.treeOutline.focusedDOMNode = this.representedObject;
+ }
+
+ if (this.hasChildren && !this.expanded)
+ this.expand();
+ },
+
+ _startEditing: function(event)
+ {
+ if (this.treeOutline.focusedDOMNode != this.representedObject)
+ return;
+
+ if (this.representedObject.nodeType != Node.ELEMENT_NODE && this.representedObject.nodeType != Node.TEXT_NODE)
+ return false;
+
+ var textNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-text-node");
+ if (textNode)
+ return this._startEditingTextNode(textNode);
+
+ var attribute = event.target.enclosingNodeOrSelfWithClass("webkit-html-attribute");
+ if (attribute)
+ return this._startEditingAttribute(attribute, event);
+
+ return false;
+ },
+
+ _startEditingAttribute: function(attribute, event)
+ {
+ if (WebInspector.isBeingEdited(attribute))
+ return true;
+
+ var attributeNameElement = attribute.getElementsByClassName("webkit-html-attribute-name")[0];
+ if (!attributeNameElement)
+ return false;
+
+ var attributeName = attributeNameElement.innerText;
+
+ function removeZeroWidthSpaceRecursive(node)
+ {
+ if (node.nodeType === Node.TEXT_NODE) {
+ node.nodeValue = node.nodeValue.replace(/\u200B/g, "");
+ return;
+ }
+
+ if (node.nodeType !== Node.ELEMENT_NODE)
+ return;
+
+ for (var child = node.firstChild; child; child = child.nextSibling)
+ removeZeroWidthSpaceRecursive(child);
+ }
+
+ // Remove zero-width spaces that were added by nodeTitleInfo.
+ removeZeroWidthSpaceRecursive(attribute);
+
+ this._editing = true;
+
+ WebInspector.startEditing(attribute, this._attributeEditingCommitted.bind(this), this._editingCancelled.bind(this), attributeName);
+ window.getSelection().setBaseAndExtent(event.target, 0, event.target, 1);
+
+ return true;
+ },
+
+ _startEditingTextNode: function(textNode)
+ {
+ if (WebInspector.isBeingEdited(textNode))
+ return true;
+
+ this._editing = true;
+
+ WebInspector.startEditing(textNode, this._textNodeEditingCommitted.bind(this), this._editingCancelled.bind(this));
+ window.getSelection().setBaseAndExtent(textNode, 0, textNode, 1);
+
+ return true;
+ },
+
+ _attributeEditingCommitted: function(element, newText, oldText, attributeName)
+ {
+ delete this._editing;
+
+ var parseContainerElement = document.createElement("span");
+ parseContainerElement.innerHTML = "<span " + newText + "></span>";
+ var parseElement = parseContainerElement.firstChild;
+ if (!parseElement || !parseElement.hasAttributes()) {
+ this._editingCancelled(element, context);
+ return;
+ }
+
+ var foundOriginalAttribute = false;
+ for (var i = 0; i < parseElement.attributes.length; ++i) {
+ var attr = parseElement.attributes[i];
+ foundOriginalAttribute = foundOriginalAttribute || attr.name === attributeName;
+ InspectorController.inspectedWindow().Element.prototype.setAttribute.call(this.representedObject, attr.name, attr.value);
+ }
+
+ if (!foundOriginalAttribute)
+ InspectorController.inspectedWindow().Element.prototype.removeAttribute.call(this.representedObject, attributeName);
+
+ this._updateTitle();
+
+ this.treeOutline.focusedNodeChanged(true);
+ },
+
+ _textNodeEditingCommitted: function(element, newText)
+ {
+ delete this._editing;
+
+ var textNode;
+ if (this.representedObject.nodeType == Node.ELEMENT_NODE) {
+ // We only show text nodes inline in elements if the element only
+ // has a single child, and that child is a text node.
+ textNode = this.representedObject.firstChild;
+ } else if (this.representedObject.nodeType == Node.TEXT_NODE)
+ textNode = this.representedObject;
+
+ textNode.nodeValue = newText;
+ this._updateTitle();
+ },
+
+ _editingCancelled: function(element, context)
+ {
+ delete this._editing;
+
+ this._updateTitle();
+ },
+
+ _updateTitle: function()
+ {
+ var title = nodeTitleInfo.call(this.representedObject, this.hasChildren, WebInspector.linkifyURL).title;
+ this.title = "<span class=\"highlight\">" + title + "</span>";
+ delete this.selectionElement;
+ this.updateSelection();
+ this._preventFollowingLinksOnDoubleClick();
+ },
+}
+
+WebInspector.ElementsTreeElement.prototype.__proto__ = TreeElement.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/FontView.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/FontView.js
new file mode 100644
index 0000000..4e1c931
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/FontView.js
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.FontView = function(resource)
+{
+ WebInspector.ResourceView.call(this, resource);
+
+ this.element.addStyleClass("font");
+
+ var uniqueFontName = "WebInspectorFontPreview" + this.resource.identifier;
+
+ this.fontStyleElement = document.createElement("style");
+ this.fontStyleElement.textContent = "@font-face { font-family: \"" + uniqueFontName + "\"; src: url(" + this.resource.url + "); }";
+ document.getElementsByTagName("head").item(0).appendChild(this.fontStyleElement);
+
+ this.fontPreviewElement = document.createElement("div");
+ this.fontPreviewElement.className = "preview";
+ this.contentElement.appendChild(this.fontPreviewElement);
+
+ this.fontPreviewElement.style.setProperty("font-family", uniqueFontName, null);
+ this.fontPreviewElement.innerHTML = "ABCDEFGHIJKLM<br>NOPQRSTUVWXYZ<br>abcdefghijklm<br>nopqrstuvwxyz<br>1234567890";
+
+ this.updateFontPreviewSize();
+}
+
+WebInspector.FontView.prototype = {
+ show: function(parentElement)
+ {
+ WebInspector.ResourceView.prototype.show.call(this, parentElement);
+ this.updateFontPreviewSize();
+ },
+
+ resize: function()
+ {
+ this.updateFontPreviewSize();
+ },
+
+ updateFontPreviewSize: function ()
+ {
+ if (!this.fontPreviewElement || !this.visible)
+ return;
+
+ this.fontPreviewElement.removeStyleClass("preview");
+
+ var measureFontSize = 50;
+ this.fontPreviewElement.style.setProperty("position", "absolute", null);
+ this.fontPreviewElement.style.setProperty("font-size", measureFontSize + "px", null);
+ this.fontPreviewElement.style.removeProperty("height");
+
+ var height = this.fontPreviewElement.offsetHeight;
+ var width = this.fontPreviewElement.offsetWidth;
+
+ var containerWidth = this.contentElement.offsetWidth;
+
+ // Subtract some padding. This should match the padding in the CSS plus room for the scrollbar.
+ containerWidth -= 40;
+
+ if (!height || !width || !containerWidth) {
+ this.fontPreviewElement.style.removeProperty("font-size");
+ this.fontPreviewElement.style.removeProperty("position");
+ this.fontPreviewElement.addStyleClass("preview");
+ return;
+ }
+
+ var lineCount = this.fontPreviewElement.getElementsByTagName("br").length + 1;
+ var realLineHeight = Math.floor(height / lineCount);
+ var fontSizeLineRatio = measureFontSize / realLineHeight;
+ var widthRatio = containerWidth / width;
+ var finalFontSize = Math.floor(realLineHeight * widthRatio * fontSizeLineRatio) - 1;
+
+ this.fontPreviewElement.style.setProperty("font-size", finalFontSize + "px", null);
+ this.fontPreviewElement.style.setProperty("height", this.fontPreviewElement.offsetHeight + "px", null);
+ this.fontPreviewElement.style.removeProperty("position");
+
+ this.fontPreviewElement.addStyleClass("preview");
+ }
+}
+
+WebInspector.FontView.prototype.__proto__ = WebInspector.ResourceView.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ImageView.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ImageView.js
new file mode 100644
index 0000000..001ffdd
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ImageView.js
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ImageView = function(resource)
+{
+ WebInspector.ResourceView.call(this, resource);
+
+ this.element.addStyleClass("image");
+
+ var container = document.createElement("div");
+ container.className = "image";
+ this.contentElement.appendChild(container);
+
+ this.imagePreviewElement = document.createElement("img");
+ this.imagePreviewElement.setAttribute("src", this.resource.url);
+
+ container.appendChild(this.imagePreviewElement);
+
+ container = document.createElement("div");
+ container.className = "info";
+ this.contentElement.appendChild(container);
+
+ var imageNameElement = document.createElement("h1");
+ imageNameElement.className = "title";
+ imageNameElement.textContent = this.resource.displayName;
+ container.appendChild(imageNameElement);
+
+ var infoListElement = document.createElement("dl");
+ infoListElement.className = "infoList";
+
+ var imageProperties = [
+ { name: WebInspector.UIString("Dimensions"), value: WebInspector.UIString("%d × %d", this.imagePreviewElement.naturalWidth, this.imagePreviewElement.height) },
+ { name: WebInspector.UIString("File size"), value: Number.bytesToString(this.resource.contentLength, WebInspector.UIString.bind(WebInspector)) },
+ { name: WebInspector.UIString("MIME type"), value: this.resource.mimeType }
+ ];
+
+ var listHTML = '';
+ for (var i = 0; i < imageProperties.length; ++i)
+ listHTML += "<dt>" + imageProperties[i].name + "</dt><dd>" + imageProperties[i].value + "</dd>";
+
+ infoListElement.innerHTML = listHTML;
+ container.appendChild(infoListElement);
+}
+
+WebInspector.ImageView.prototype = {
+
+}
+
+WebInspector.ImageView.prototype.__proto__ = WebInspector.ResourceView.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/back.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/back.png
new file mode 100644
index 0000000..9363960
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/back.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/checker.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/checker.png
new file mode 100644
index 0000000..8349908
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/checker.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/clearConsoleButtons.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/clearConsoleButtons.png
new file mode 100644
index 0000000..140a4fb
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/clearConsoleButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/closeButtons.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/closeButtons.png
new file mode 100644
index 0000000..28158a4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/closeButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/consoleButtons.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/consoleButtons.png
new file mode 100644
index 0000000..fb5f0897
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/consoleButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/database.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/database.png
new file mode 100644
index 0000000..339efa6
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/database.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/databaseTable.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/databaseTable.png
new file mode 100644
index 0000000..3718708
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/databaseTable.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/databasesIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/databasesIcon.png
new file mode 100644
index 0000000..79c7bb3
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/databasesIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerContinue.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerContinue.png
new file mode 100644
index 0000000..d90a855
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerContinue.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerPause.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerPause.png
new file mode 100644
index 0000000..97f958a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerPause.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerStepInto.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerStepInto.png
new file mode 100644
index 0000000..277f126
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerStepInto.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerStepOut.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerStepOut.png
new file mode 100644
index 0000000..3032e32
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerStepOut.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerStepOver.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerStepOver.png
new file mode 100644
index 0000000..7d47245
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/debuggerStepOver.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDown.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDown.png
new file mode 100644
index 0000000..cffc835
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDown.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDownBlack.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDownBlack.png
new file mode 100644
index 0000000..4b49c13
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDownBlack.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDownWhite.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDownWhite.png
new file mode 100644
index 0000000..aebae12
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallDownWhite.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRight.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRight.png
new file mode 100644
index 0000000..a3102ea
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRight.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightBlack.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightBlack.png
new file mode 100644
index 0000000..2c45859
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightBlack.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDown.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDown.png
new file mode 100644
index 0000000..035c069
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDown.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDownBlack.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDownBlack.png
new file mode 100644
index 0000000..86f67bd
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDownBlack.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDownWhite.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDownWhite.png
new file mode 100644
index 0000000..972d794
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightDownWhite.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightWhite.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightWhite.png
new file mode 100644
index 0000000..a10168f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/disclosureTriangleSmallRightWhite.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/dockButtons.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/dockButtons.png
new file mode 100644
index 0000000..4b01d66
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/dockButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/elementsIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/elementsIcon.png
new file mode 100644
index 0000000..fde3db9
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/elementsIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/enableButtons.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/enableButtons.png
new file mode 100644
index 0000000..facee60
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/enableButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/errorIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/errorIcon.png
new file mode 100644
index 0000000..c697263
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/errorIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/errorMediumIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/errorMediumIcon.png
new file mode 100644
index 0000000..6ca32bb
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/errorMediumIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/excludeButtons.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/excludeButtons.png
new file mode 100644
index 0000000..f1c53a9
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/excludeButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/focusButtons.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/focusButtons.png
new file mode 100644
index 0000000..47eaa04
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/focusButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/forward.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/forward.png
new file mode 100644
index 0000000..ad70f3e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/forward.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/glossyHeader.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/glossyHeader.png
new file mode 100644
index 0000000..6cbefb7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/glossyHeader.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/glossyHeaderPressed.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/glossyHeaderPressed.png
new file mode 100644
index 0000000..1153506
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/glossyHeaderPressed.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/glossyHeaderSelected.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/glossyHeaderSelected.png
new file mode 100644
index 0000000..71d5af6
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/glossyHeaderSelected.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/glossyHeaderSelectedPressed.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/glossyHeaderSelectedPressed.png
new file mode 100644
index 0000000..7047dbe
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/glossyHeaderSelectedPressed.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/goArrow.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/goArrow.png
new file mode 100644
index 0000000..f318a56
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/goArrow.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/graphLabelCalloutLeft.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/graphLabelCalloutLeft.png
new file mode 100644
index 0000000..6426dbd
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/graphLabelCalloutLeft.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/graphLabelCalloutRight.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/graphLabelCalloutRight.png
new file mode 100644
index 0000000..8c87eae
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/graphLabelCalloutRight.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/largerResourcesButtons.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/largerResourcesButtons.png
new file mode 100644
index 0000000..caf3f14
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/largerResourcesButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/nodeSearchButtons.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/nodeSearchButtons.png
new file mode 100644
index 0000000..0599bd4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/nodeSearchButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/paneBottomGrow.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/paneBottomGrow.png
new file mode 100644
index 0000000..d55b865
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/paneBottomGrow.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/paneBottomGrowActive.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/paneBottomGrowActive.png
new file mode 100644
index 0000000..ef3f259
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/paneBottomGrowActive.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/paneGrowHandleLine.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/paneGrowHandleLine.png
new file mode 100644
index 0000000..4eaf61b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/paneGrowHandleLine.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/pauseOnExceptionButtons.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/pauseOnExceptionButtons.png
new file mode 100644
index 0000000..a4dd33a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/pauseOnExceptionButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/percentButtons.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/percentButtons.png
new file mode 100644
index 0000000..2635b24
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/percentButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profileGroupIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profileGroupIcon.png
new file mode 100644
index 0000000..44616d4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profileGroupIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profileIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profileIcon.png
new file mode 100644
index 0000000..8008f9b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profileIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profileSmallIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profileSmallIcon.png
new file mode 100644
index 0000000..7935520
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profileSmallIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profilesIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profilesIcon.png
new file mode 100644
index 0000000..ecd5b04
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profilesIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profilesSilhouette.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profilesSilhouette.png
new file mode 100644
index 0000000..42bb966
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/profilesSilhouette.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/radioDot.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/radioDot.png
new file mode 100644
index 0000000..609878f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/radioDot.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/recordButtons.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/recordButtons.png
new file mode 100644
index 0000000..3676154
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/recordButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/reloadButtons.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/reloadButtons.png
new file mode 100644
index 0000000..1e45671
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/reloadButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourceCSSIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourceCSSIcon.png
new file mode 100644
index 0000000..aead6a7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourceCSSIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourceDocumentIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourceDocumentIcon.png
new file mode 100644
index 0000000..1683a09
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourceDocumentIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourceDocumentIconSmall.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourceDocumentIconSmall.png
new file mode 100644
index 0000000..468ced9
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourceDocumentIconSmall.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourceJSIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourceJSIcon.png
new file mode 100644
index 0000000..9ef6ed0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourceJSIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcePlainIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcePlainIcon.png
new file mode 100644
index 0000000..0ed37b6
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcePlainIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcePlainIconSmall.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcePlainIconSmall.png
new file mode 100644
index 0000000..0fa967d
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcePlainIconSmall.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcesIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcesIcon.png
new file mode 100644
index 0000000..982424d
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcesIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcesSizeGraphIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcesSizeGraphIcon.png
new file mode 100644
index 0000000..e60dbe5
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcesSizeGraphIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcesTimeGraphIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcesTimeGraphIcon.png
new file mode 100644
index 0000000..c6953e9
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/resourcesTimeGraphIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/scriptsIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/scriptsIcon.png
new file mode 100644
index 0000000..213b31e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/scriptsIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/scriptsSilhouette.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/scriptsSilhouette.png
new file mode 100644
index 0000000..206396f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/scriptsSilhouette.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/searchSmallBlue.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/searchSmallBlue.png
new file mode 100644
index 0000000..9c990f4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/searchSmallBlue.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/searchSmallBrightBlue.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/searchSmallBrightBlue.png
new file mode 100644
index 0000000..b1d8055
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/searchSmallBrightBlue.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/searchSmallGray.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/searchSmallGray.png
new file mode 100644
index 0000000..4f3c068
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/searchSmallGray.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/searchSmallWhite.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/searchSmallWhite.png
new file mode 100644
index 0000000..85f430d
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/searchSmallWhite.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segment.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segment.png
new file mode 100644
index 0000000..759266e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segment.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentEnd.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentEnd.png
new file mode 100644
index 0000000..72672ff
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentEnd.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentHover.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentHover.png
new file mode 100644
index 0000000..c5017f4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentHover.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentHoverEnd.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentHoverEnd.png
new file mode 100644
index 0000000..d51363d
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentHoverEnd.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentSelected.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentSelected.png
new file mode 100644
index 0000000..c92f584
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentSelected.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentSelectedEnd.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentSelectedEnd.png
new file mode 100644
index 0000000..be5e0852
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/segmentSelectedEnd.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/splitviewDimple.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/splitviewDimple.png
new file mode 100644
index 0000000..584ffd4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/splitviewDimple.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/splitviewDividerBackground.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/splitviewDividerBackground.png
new file mode 100644
index 0000000..1120a7f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/splitviewDividerBackground.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarBackground.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarBackground.png
new file mode 100644
index 0000000..b466a49
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarBackground.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarBottomBackground.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarBottomBackground.png
new file mode 100644
index 0000000..fb5c9e4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarBottomBackground.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarButtons.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarButtons.png
new file mode 100644
index 0000000..e8090cb
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarButtons.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarMenuButton.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarMenuButton.png
new file mode 100644
index 0000000..9b3abdd
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarMenuButton.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarMenuButtonSelected.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarMenuButtonSelected.png
new file mode 100644
index 0000000..8189c43
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarMenuButtonSelected.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarResizerHorizontal.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarResizerHorizontal.png
new file mode 100644
index 0000000..56deeab
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarResizerHorizontal.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarResizerVertical.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarResizerVertical.png
new file mode 100644
index 0000000..7fc145277
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/statusbarResizerVertical.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillBlue.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillBlue.png
new file mode 100644
index 0000000..c7c273b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillBlue.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillGray.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillGray.png
new file mode 100644
index 0000000..9ff37ef
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillGray.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillGreen.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillGreen.png
new file mode 100644
index 0000000..cc5a8f3
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillGreen.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillOrange.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillOrange.png
new file mode 100644
index 0000000..08a81e4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillOrange.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillPurple.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillPurple.png
new file mode 100644
index 0000000..565a05c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillPurple.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillRed.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillRed.png
new file mode 100644
index 0000000..c3a1b9b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillRed.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillYellow.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillYellow.png
new file mode 100644
index 0000000..780045b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelineHollowPillYellow.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillBlue.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillBlue.png
new file mode 100644
index 0000000..c897faa
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillBlue.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillGray.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillGray.png
new file mode 100644
index 0000000..2128896
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillGray.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillGreen.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillGreen.png
new file mode 100644
index 0000000..9b66125
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillGreen.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillOrange.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillOrange.png
new file mode 100644
index 0000000..dd944fb
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillOrange.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillPurple.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillPurple.png
new file mode 100644
index 0000000..21b96f7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillPurple.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillRed.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillRed.png
new file mode 100644
index 0000000..f5e213b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillRed.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillYellow.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillYellow.png
new file mode 100644
index 0000000..ae2a5a23
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/timelinePillYellow.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/tipBalloon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/tipBalloon.png
new file mode 100644
index 0000000..4cdf738
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/tipBalloon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/tipBalloonBottom.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/tipBalloonBottom.png
new file mode 100644
index 0000000..3317a5a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/tipBalloonBottom.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/tipIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/tipIcon.png
new file mode 100644
index 0000000..8ca6124
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/tipIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/tipIconPressed.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/tipIconPressed.png
new file mode 100644
index 0000000..443e410
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/tipIconPressed.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/toolbarItemSelected.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/toolbarItemSelected.png
new file mode 100644
index 0000000..bd681f18
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/toolbarItemSelected.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeDownTriangleBlack.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeDownTriangleBlack.png
new file mode 100644
index 0000000..0821112
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeDownTriangleBlack.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeDownTriangleWhite.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeDownTriangleWhite.png
new file mode 100644
index 0000000..1667b51
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeDownTriangleWhite.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeRightTriangleBlack.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeRightTriangleBlack.png
new file mode 100644
index 0000000..90de820
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeRightTriangleBlack.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeRightTriangleWhite.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeRightTriangleWhite.png
new file mode 100644
index 0000000..2b6a82f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeRightTriangleWhite.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeUpTriangleBlack.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeUpTriangleBlack.png
new file mode 100644
index 0000000..ef69dbc
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeUpTriangleBlack.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeUpTriangleWhite.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeUpTriangleWhite.png
new file mode 100644
index 0000000..43ce4be
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/treeUpTriangleWhite.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/userInputIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/userInputIcon.png
new file mode 100644
index 0000000..325023f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/userInputIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/userInputPreviousIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/userInputPreviousIcon.png
new file mode 100644
index 0000000..068d572
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/userInputPreviousIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/warningIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/warningIcon.png
new file mode 100644
index 0000000..d5e4c82
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/warningIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/warningMediumIcon.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/warningMediumIcon.png
new file mode 100644
index 0000000..291e111
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/warningMediumIcon.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/warningsErrors.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/warningsErrors.png
new file mode 100644
index 0000000..878b593
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Images/warningsErrors.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/MetricsSidebarPane.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/MetricsSidebarPane.js
new file mode 100644
index 0000000..a22a000
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/MetricsSidebarPane.js
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.MetricsSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Metrics"));
+}
+
+WebInspector.MetricsSidebarPane.prototype = {
+ update: function(node)
+ {
+ var body = this.bodyElement;
+
+ body.removeChildren();
+
+ if (node)
+ this.node = node;
+ else
+ node = this.node;
+
+ if (!node || !node.ownerDocument.defaultView)
+ return;
+
+ var style;
+ if (node.nodeType === Node.ELEMENT_NODE)
+ style = node.ownerDocument.defaultView.getComputedStyle(node);
+ if (!style)
+ return;
+
+ var metricsElement = document.createElement("div");
+ metricsElement.className = "metrics";
+
+ function createBoxPartElement(style, name, side, suffix)
+ {
+ var propertyName = (name !== "position" ? name + "-" : "") + side + suffix;
+ var value = style.getPropertyValue(propertyName);
+ if (value === "" || (name !== "position" && value === "0px"))
+ value = "\u2012";
+ else if (name === "position" && value === "auto")
+ value = "\u2012";
+ value = value.replace(/px$/, "");
+
+ var element = document.createElement("div");
+ element.className = side;
+ element.textContent = value;
+ element.addEventListener("dblclick", this.startEditing.bind(this, element, name, propertyName), false);
+ return element;
+ }
+
+ // Display types for which margin is ignored.
+ var noMarginDisplayType = {
+ "table-cell": true,
+ "table-column": true,
+ "table-column-group": true,
+ "table-footer-group": true,
+ "table-header-group": true,
+ "table-row": true,
+ "table-row-group": true
+ };
+
+ // Display types for which padding is ignored.
+ var noPaddingDisplayType = {
+ "table-column": true,
+ "table-column-group": true,
+ "table-footer-group": true,
+ "table-header-group": true,
+ "table-row": true,
+ "table-row-group": true
+ };
+
+ // Position types for which top, left, bottom and right are ignored.
+ var noPositionType = {
+ "static": true
+ };
+
+ var boxes = ["content", "padding", "border", "margin", "position"];
+ var boxLabels = [WebInspector.UIString("content"), WebInspector.UIString("padding"), WebInspector.UIString("border"), WebInspector.UIString("margin"), WebInspector.UIString("position")];
+ var previousBox;
+ for (var i = 0; i < boxes.length; ++i) {
+ var name = boxes[i];
+
+ if (name === "margin" && noMarginDisplayType[style.display])
+ continue;
+ if (name === "padding" && noPaddingDisplayType[style.display])
+ continue;
+ if (name === "position" && noPositionType[style.position])
+ continue;
+
+ var boxElement = document.createElement("div");
+ boxElement.className = name;
+
+ if (name === "content") {
+ var width = style.width.replace(/px$/, "");
+ var widthElement = document.createElement("span");
+ widthElement.textContent = width;
+ widthElement.addEventListener("dblclick", this.startEditing.bind(this, widthElement, "width", "width"), false);
+
+ var height = style.height.replace(/px$/, "");
+ var heightElement = document.createElement("span");
+ heightElement.textContent = height;
+ heightElement.addEventListener("dblclick", this.startEditing.bind(this, heightElement, "height", "height"), false);
+
+ boxElement.appendChild(widthElement);
+ boxElement.appendChild(document.createTextNode(" \u00D7 "));
+ boxElement.appendChild(heightElement);
+ } else {
+ var suffix = (name === "border" ? "-width" : "");
+
+ var labelElement = document.createElement("div");
+ labelElement.className = "label";
+ labelElement.textContent = boxLabels[i];
+ boxElement.appendChild(labelElement);
+
+ boxElement.appendChild(createBoxPartElement.call(this, style, name, "top", suffix));
+ boxElement.appendChild(document.createElement("br"));
+ boxElement.appendChild(createBoxPartElement.call(this, style, name, "left", suffix));
+
+ if (previousBox)
+ boxElement.appendChild(previousBox);
+
+ boxElement.appendChild(createBoxPartElement.call(this, style, name, "right", suffix));
+ boxElement.appendChild(document.createElement("br"));
+ boxElement.appendChild(createBoxPartElement.call(this, style, name, "bottom", suffix));
+ }
+
+ previousBox = boxElement;
+ }
+
+ metricsElement.appendChild(previousBox);
+ body.appendChild(metricsElement);
+ },
+
+ startEditing: function(targetElement, box, styleProperty)
+ {
+ if (WebInspector.isBeingEdited(targetElement))
+ return;
+
+ var context = { box: box, styleProperty: styleProperty };
+
+ WebInspector.startEditing(targetElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
+ },
+
+ editingCancelled: function(element, context)
+ {
+ this.update();
+ },
+
+ editingCommitted: function(element, userInput, previousContent, context)
+ {
+ if (userInput === previousContent)
+ return this.editingCancelled(element, context); // nothing changed, so cancel
+
+ if (context.box !== "position" && (!userInput || userInput === "\u2012"))
+ userInput = "0px";
+ else if (context.box === "position" && (!userInput || userInput === "\u2012"))
+ userInput = "auto";
+
+ // Append a "px" unit if the user input was just a number.
+ if (/^\d+$/.test(userInput))
+ userInput += "px";
+
+ this.node.style.setProperty(context.styleProperty, userInput, "");
+
+ this.dispatchEventToListeners("metrics edited");
+
+ this.update();
+ }
+}
+
+WebInspector.MetricsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Object.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Object.js
new file mode 100644
index 0000000..80202b0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Object.js
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Object = function() {
+}
+
+WebInspector.Object.prototype = {
+ addEventListener: function(eventType, listener, thisObject) {
+ if (!("_listeners" in this))
+ this._listeners = {};
+ if (!(eventType in this._listeners))
+ this._listeners[eventType] = [];
+ this._listeners[eventType].push({ thisObject: thisObject, listener: listener });
+ },
+
+ removeEventListener: function(eventType, listener, thisObject) {
+ if (!("_listeners" in this) || !(eventType in this._listeners))
+ return;
+ var listeners = this._listeners[eventType];
+ for (var i = 0; i < listeners.length; ++i) {
+ if (listener && listeners[i].listener === listener && listeners[i].thisObject === thisObject)
+ listeners.splice(i, 1);
+ else if (!listener && thisObject && listeners[i].thisObject === thisObject)
+ listeners.splice(i, 1);
+ }
+
+ if (!listeners.length)
+ delete this._listeners[eventType];
+ },
+
+ dispatchEventToListeners: function(eventType) {
+ if (!("_listeners" in this) || !(eventType in this._listeners))
+ return;
+
+ var stoppedPropagation = false;
+
+ function stopPropagation()
+ {
+ stoppedPropagation = true;
+ }
+
+ function preventDefault()
+ {
+ this.defaultPrevented = true;
+ }
+
+ var event = {target: this, type: eventType, defaultPrevented: false};
+ event.stopPropagation = stopPropagation.bind(event);
+ event.preventDefault = preventDefault.bind(event);
+
+ var listeners = this._listeners[eventType];
+ for (var i = 0; i < listeners.length; ++i) {
+ listeners[i].listener.call(listeners[i].thisObject, event);
+ if (stoppedPropagation)
+ break;
+ }
+
+ return event.defaultPrevented;
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ObjectPropertiesSection.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ObjectPropertiesSection.js
new file mode 100644
index 0000000..ab6ac55
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ObjectPropertiesSection.js
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ObjectPropertiesSection = function(object, title, subtitle, emptyPlaceholder, ignoreHasOwnProperty, extraProperties, treeElementConstructor)
+{
+ if (!title) {
+ title = Object.describe(object);
+ if (title.match(/Prototype$/)) {
+ title = title.replace(/Prototype$/, "");
+ if (!subtitle)
+ subtitle = WebInspector.UIString("Prototype");
+ }
+ }
+
+ this.emptyPlaceholder = (emptyPlaceholder || WebInspector.UIString("No Properties"));
+ this.object = object;
+ this.ignoreHasOwnProperty = ignoreHasOwnProperty;
+ this.extraProperties = extraProperties;
+ this.treeElementConstructor = treeElementConstructor || WebInspector.ObjectPropertyTreeElement;
+ this.editable = true;
+
+ WebInspector.PropertiesSection.call(this, title, subtitle);
+}
+
+WebInspector.ObjectPropertiesSection.prototype = {
+ onpopulate: function()
+ {
+ this.update();
+ },
+
+ update: function()
+ {
+ var properties = [];
+ for (var prop in this.object)
+ properties.push(prop);
+ if (this.extraProperties)
+ for (var prop in this.extraProperties)
+ properties.push(prop);
+ properties.sort();
+
+ this.propertiesTreeOutline.removeChildren();
+
+ for (var i = 0; i < properties.length; ++i) {
+ var object = this.object;
+ var propertyName = properties[i];
+ if (this.extraProperties && propertyName in this.extraProperties)
+ object = this.extraProperties;
+ if (propertyName === "__treeElementIdentifier")
+ continue;
+ if (!this.ignoreHasOwnProperty && "hasOwnProperty" in object && !object.hasOwnProperty(propertyName))
+ continue;
+ this.propertiesTreeOutline.appendChild(new this.treeElementConstructor(object, propertyName));
+ }
+
+ if (!this.propertiesTreeOutline.children.length) {
+ var title = "<div class=\"info\">" + this.emptyPlaceholder + "</div>";
+ var infoElement = new TreeElement(title, null, false);
+ this.propertiesTreeOutline.appendChild(infoElement);
+ }
+ }
+}
+
+WebInspector.ObjectPropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
+
+WebInspector.ObjectPropertyTreeElement = function(parentObject, propertyName)
+{
+ this.parentObject = parentObject;
+ this.propertyName = propertyName;
+
+ // Pass an empty title, the title gets made later in onattach.
+ TreeElement.call(this, "", null, false);
+}
+
+WebInspector.ObjectPropertyTreeElement.prototype = {
+ safePropertyValue: function(object, propertyName)
+ {
+ if (object["__lookupGetter__"] && object.__lookupGetter__(propertyName))
+ return;
+ return object[propertyName];
+ },
+
+ onpopulate: function()
+ {
+ if (this.children.length && !this.shouldRefreshChildren)
+ return;
+
+ this.removeChildren();
+
+ var childObject = this.safePropertyValue(this.parentObject, this.propertyName);
+ var properties = Object.sortedProperties(childObject);
+ for (var i = 0; i < properties.length; ++i) {
+ var propertyName = properties[i];
+ if (propertyName === "__treeElementIdentifier")
+ continue;
+ this.appendChild(new this.treeOutline.section.treeElementConstructor(childObject, propertyName));
+ }
+ },
+
+ ondblclick: function(element, event)
+ {
+ this.startEditing();
+ },
+
+ onattach: function()
+ {
+ this.update();
+ },
+
+ update: function()
+ {
+ var childObject = this.safePropertyValue(this.parentObject, this.propertyName);
+ var isGetter = ("__lookupGetter__" in this.parentObject && this.parentObject.__lookupGetter__(this.propertyName));
+
+ var nameElement = document.createElement("span");
+ nameElement.className = "name";
+ nameElement.textContent = this.propertyName;
+
+ this.valueElement = document.createElement("span");
+ this.valueElement.className = "value";
+ if (!isGetter) {
+ this.valueElement.textContent = Object.describe(childObject, true);
+ } else {
+ // FIXME: this should show something like "getter" (bug 16734).
+ this.valueElement.textContent = "\u2014"; // em dash
+ this.valueElement.addStyleClass("dimmed");
+ }
+
+ this.listItemElement.removeChildren();
+
+ this.listItemElement.appendChild(nameElement);
+ this.listItemElement.appendChild(document.createTextNode(": "));
+ this.listItemElement.appendChild(this.valueElement);
+
+ var hasSubProperties = false;
+ var type = typeof childObject;
+ if (childObject && (type === "object" || type === "function")) {
+ for (subPropertyName in childObject) {
+ if (subPropertyName === "__treeElementIdentifier")
+ continue;
+ hasSubProperties = true;
+ break;
+ }
+ }
+
+ this.hasChildren = hasSubProperties;
+ },
+
+ updateSiblings: function()
+ {
+ if (this.parent.root)
+ this.treeOutline.section.update();
+ else
+ this.parent.shouldRefreshChildren = true;
+ },
+
+ startEditing: function()
+ {
+ if (WebInspector.isBeingEdited(this.valueElement) || !this.treeOutline.section.editable)
+ return;
+
+ var context = { expanded: this.expanded };
+
+ // Lie about our children to prevent expanding on double click and to collapse subproperties.
+ this.hasChildren = false;
+
+ this.listItemElement.addStyleClass("editing-sub-part");
+
+ WebInspector.startEditing(this.valueElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
+ },
+
+ editingEnded: function(context)
+ {
+ this.listItemElement.scrollLeft = 0;
+ this.listItemElement.removeStyleClass("editing-sub-part");
+ if (context.expanded)
+ this.expand();
+ },
+
+ editingCancelled: function(element, context)
+ {
+ this.update();
+ this.editingEnded(context);
+ },
+
+ editingCommitted: function(element, userInput, previousContent, context)
+ {
+ if (userInput === previousContent)
+ return this.editingCancelled(element, context); // nothing changed, so cancel
+
+ this.applyExpression(userInput, true);
+
+ this.editingEnded(context);
+ },
+
+ evaluateExpression: function(expression)
+ {
+ // Evaluate in the currently selected call frame if the debugger is paused.
+ // Otherwise evaluate in against the inspected window.
+ if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused && this.treeOutline.section.editInSelectedCallFrameWhenPaused)
+ return WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false);
+ return InspectorController.inspectedWindow().eval(expression);
+ },
+
+ applyExpression: function(expression, updateInterface)
+ {
+ var expressionLength = expression.trimWhitespace().length;
+
+ if (!expressionLength) {
+ // The user deleted everything, so try to delete the property.
+ delete this.parentObject[this.propertyName];
+
+ if (updateInterface) {
+ if (this.propertyName in this.parentObject) {
+ // The property was not deleted, so update.
+ this.update();
+ } else {
+ // The property was deleted, so remove this tree element.
+ this.parent.removeChild(this);
+ }
+ }
+
+ return;
+ }
+
+ try {
+ // Surround the expression in parenthesis so the result of the eval is the result
+ // of the whole expression not the last potential sub-expression.
+ var result = this.evaluateExpression("(" + expression + ")");
+
+ // Store the result in the property.
+ this.parentObject[this.propertyName] = result;
+ } catch(e) {
+ try {
+ // Try to update as a string
+ var result = this.evaluateExpression("\"" + expression.escapeCharacters("\"") + "\"");
+
+ // Store the result in the property.
+ this.parentObject[this.propertyName] = result;
+ } catch(e) {
+ // The expression failed so don't change the value. So just update and return.
+ if (updateInterface)
+ this.update();
+ return;
+ }
+ }
+
+ if (updateInterface) {
+ // Call updateSiblings since their value might be based on the value that just changed.
+ this.updateSiblings();
+ }
+ }
+}
+
+WebInspector.ObjectPropertyTreeElement.prototype.__proto__ = TreeElement.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Panel.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Panel.js
new file mode 100644
index 0000000..5046f6b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Panel.js
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Panel = function()
+{
+ WebInspector.View.call(this);
+
+ this.element.addStyleClass("panel");
+}
+
+WebInspector.Panel.prototype = {
+ get toolbarItem()
+ {
+ if (this._toolbarItem)
+ return this._toolbarItem;
+
+ // Sample toolbar item as markup:
+ // <button class="toolbar-item resources toggleable">
+ // <div class="toolbar-icon"></div>
+ // <div class="toolbar-label">Resources</div>
+ // </button>
+
+ this._toolbarItem = document.createElement("button");
+ this._toolbarItem.className = "toolbar-item toggleable";
+ this._toolbarItem.panel = this;
+
+ if ("toolbarItemClass" in this)
+ this._toolbarItem.addStyleClass(this.toolbarItemClass);
+
+ var iconElement = document.createElement("div");
+ iconElement.className = "toolbar-icon";
+ this._toolbarItem.appendChild(iconElement);
+
+ if ("toolbarItemLabel" in this) {
+ var labelElement = document.createElement("div");
+ labelElement.className = "toolbar-label";
+ labelElement.textContent = this.toolbarItemLabel;
+ this._toolbarItem.appendChild(labelElement);
+ }
+
+ return this._toolbarItem;
+ },
+
+ show: function()
+ {
+ WebInspector.View.prototype.show.call(this);
+
+ var statusBarItems = this.statusBarItems;
+ if (statusBarItems) {
+ this._statusBarItemContainer = document.createElement("div");
+ for (var i = 0; i < statusBarItems.length; ++i)
+ this._statusBarItemContainer.appendChild(statusBarItems[i]);
+ document.getElementById("main-status-bar").appendChild(this._statusBarItemContainer);
+ }
+
+ if ("_toolbarItem" in this)
+ this._toolbarItem.addStyleClass("toggled-on");
+
+ WebInspector.currentFocusElement = document.getElementById("main-panels");
+ },
+
+ hide: function()
+ {
+ WebInspector.View.prototype.hide.call(this);
+
+ if (this._statusBarItemContainer && this._statusBarItemContainer.parentNode)
+ this._statusBarItemContainer.parentNode.removeChild(this._statusBarItemContainer);
+ delete this._statusBarItemContainer;
+ if ("_toolbarItem" in this)
+ this._toolbarItem.removeStyleClass("toggled-on");
+ },
+
+ attach: function()
+ {
+ if (!this.element.parentNode)
+ document.getElementById("main-panels").appendChild(this.element);
+ },
+
+ searchCanceled: function(startingNewSearch)
+ {
+ if (this._searchResults) {
+ for (var i = 0; i < this._searchResults.length; ++i) {
+ var view = this._searchResults[i];
+ if (view.searchCanceled)
+ view.searchCanceled();
+ delete view.currentQuery;
+ }
+ }
+
+ WebInspector.updateSearchMatchesCount(0, this);
+
+ if (this._currentSearchChunkIntervalIdentifier) {
+ clearInterval(this._currentSearchChunkIntervalIdentifier);
+ delete this._currentSearchChunkIntervalIdentifier;
+ }
+
+ this._totalSearchMatches = 0;
+ this._currentSearchResultIndex = 0;
+ this._searchResults = [];
+ },
+
+ performSearch: function(query)
+ {
+ // Call searchCanceled since it will reset everything we need before doing a new search.
+ this.searchCanceled(true);
+
+ var searchableViews = this.searchableViews;
+ if (!searchableViews || !searchableViews.length)
+ return;
+
+ var parentElement = this.viewsContainerElement;
+ var visibleView = this.visibleView;
+ var sortFuction = this.searchResultsSortFunction;
+
+ var matchesCountUpdateTimeout = null;
+
+ function updateMatchesCount()
+ {
+ WebInspector.updateSearchMatchesCount(this._totalSearchMatches, this);
+ matchesCountUpdateTimeout = null;
+ }
+
+ function updateMatchesCountSoon()
+ {
+ if (matchesCountUpdateTimeout)
+ return;
+ // Update the matches count every half-second so it doesn't feel twitchy.
+ matchesCountUpdateTimeout = setTimeout(updateMatchesCount.bind(this), 500);
+ }
+
+ function finishedCallback(view, searchMatches)
+ {
+ if (!searchMatches)
+ return;
+
+ this._totalSearchMatches += searchMatches;
+ this._searchResults.push(view);
+
+ if (sortFuction)
+ this._searchResults.sort(sortFuction);
+
+ if (this.searchMatchFound)
+ this.searchMatchFound(view, searchMatches);
+
+ updateMatchesCountSoon.call(this);
+
+ if (view === visibleView)
+ view.jumpToFirstSearchResult();
+ }
+
+ var i = 0;
+ var panel = this;
+ var boundFinishedCallback = finishedCallback.bind(this);
+ var chunkIntervalIdentifier = null;
+
+ // Split up the work into chunks so we don't block the
+ // UI thread while processing.
+
+ function processChunk()
+ {
+ var view = searchableViews[i];
+
+ if (++i >= searchableViews.length) {
+ if (panel._currentSearchChunkIntervalIdentifier === chunkIntervalIdentifier)
+ delete panel._currentSearchChunkIntervalIdentifier;
+ clearInterval(chunkIntervalIdentifier);
+ }
+
+ if (!view)
+ return;
+
+ if (view.element.parentNode !== parentElement && view.element.parentNode && parentElement)
+ view.detach();
+
+ view.currentQuery = query;
+ view.performSearch(query, boundFinishedCallback);
+ }
+
+ processChunk();
+
+ chunkIntervalIdentifier = setInterval(processChunk, 25);
+ this._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier;
+ },
+
+ jumpToNextSearchResult: function()
+ {
+ if (!this.showView || !this._searchResults || !this._searchResults.length)
+ return;
+
+ var showFirstResult = false;
+
+ this._currentSearchResultIndex = this._searchResults.indexOf(this.visibleView);
+ if (this._currentSearchResultIndex === -1) {
+ this._currentSearchResultIndex = 0;
+ showFirstResult = true;
+ }
+
+ var currentView = this._searchResults[this._currentSearchResultIndex];
+
+ if (currentView.showingLastSearchResult()) {
+ if (++this._currentSearchResultIndex >= this._searchResults.length)
+ this._currentSearchResultIndex = 0;
+ currentView = this._searchResults[this._currentSearchResultIndex];
+ showFirstResult = true;
+ }
+
+ if (currentView !== this.visibleView)
+ this.showView(currentView);
+
+ if (showFirstResult)
+ currentView.jumpToFirstSearchResult();
+ else
+ currentView.jumpToNextSearchResult();
+ },
+
+ jumpToPreviousSearchResult: function()
+ {
+ if (!this.showView || !this._searchResults || !this._searchResults.length)
+ return;
+
+ var showLastResult = false;
+
+ this._currentSearchResultIndex = this._searchResults.indexOf(this.visibleView);
+ if (this._currentSearchResultIndex === -1) {
+ this._currentSearchResultIndex = 0;
+ showLastResult = true;
+ }
+
+ var currentView = this._searchResults[this._currentSearchResultIndex];
+
+ if (currentView.showingFirstSearchResult()) {
+ if (--this._currentSearchResultIndex < 0)
+ this._currentSearchResultIndex = (this._searchResults.length - 1);
+ currentView = this._searchResults[this._currentSearchResultIndex];
+ showLastResult = true;
+ }
+
+ if (currentView !== this.visibleView)
+ this.showView(currentView);
+
+ if (showLastResult)
+ currentView.jumpToLastSearchResult();
+ else
+ currentView.jumpToPreviousSearchResult();
+ }
+}
+
+WebInspector.Panel.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/PanelEnablerView.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/PanelEnablerView.js
new file mode 100644
index 0000000..fab6d76
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/PanelEnablerView.js
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.PanelEnablerView = function(identifier, headingText, disclaimerText, buttonTitle)
+{
+ WebInspector.View.call(this);
+
+ this.element.addStyleClass("panel-enabler-view");
+ this.element.addStyleClass(identifier);
+
+ this.contentElement = document.createElement("div");
+ this.contentElement.className = "panel-enabler-view-content";
+ this.element.appendChild(this.contentElement);
+
+ this.imageElement = document.createElement("img");
+ this.contentElement.appendChild(this.imageElement);
+
+ this.choicesForm = document.createElement("form");
+ this.contentElement.appendChild(this.choicesForm);
+
+ this.headerElement = document.createElement("h1");
+ this.headerElement.textContent = headingText;
+ this.choicesForm.appendChild(this.headerElement);
+
+ var self = this;
+ function enableOption(text, checked) {
+ var label = document.createElement("label");
+ var option = document.createElement("input");
+ option.type = "radio";
+ option.name = "enable-option";
+ if (checked)
+ option.checked = true;
+ label.appendChild(option);
+ label.appendChild(document.createTextNode(text));
+ self.choicesForm.appendChild(label);
+ return option;
+ };
+
+ this.enabledForSession = enableOption(WebInspector.UIString("Only enable for this session"), true);
+ this.enabledAlways = enableOption(WebInspector.UIString("Always enable"));
+
+ this.disclaimerElement = document.createElement("div");
+ this.disclaimerElement.className = "panel-enabler-disclaimer";
+ this.disclaimerElement.textContent = disclaimerText;
+ this.choicesForm.appendChild(this.disclaimerElement);
+
+ this.enableButton = document.createElement("button");
+ this.enableButton.setAttribute("type", "button");
+ this.enableButton.textContent = buttonTitle;
+ this.enableButton.addEventListener("click", this._enableButtonCicked.bind(this), false);
+ this.choicesForm.appendChild(this.enableButton);
+
+ window.addEventListener("resize", this._windowResized.bind(this), true);
+}
+
+WebInspector.PanelEnablerView.prototype = {
+ _enableButtonCicked: function()
+ {
+ this.dispatchEventToListeners("enable clicked");
+ },
+
+ _windowResized: function()
+ {
+ this.imageElement.removeStyleClass("hidden");
+
+ if (this.element.offsetWidth < (this.choicesForm.offsetWidth + this.imageElement.offsetWidth))
+ this.imageElement.addStyleClass("hidden");
+ },
+
+ get alwaysEnabled() {
+ return this.enabledAlways.checked;
+ }
+}
+
+WebInspector.PanelEnablerView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Placard.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Placard.js
new file mode 100644
index 0000000..69a168e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Placard.js
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Placard = function(title, subtitle)
+{
+ this.element = document.createElement("div");
+ this.element.className = "placard";
+ this.element.placard = this;
+
+ this.titleElement = document.createElement("div");
+ this.titleElement.className = "title";
+
+ this.subtitleElement = document.createElement("div");
+ this.subtitleElement.className = "subtitle";
+
+ this.element.appendChild(this.subtitleElement);
+ this.element.appendChild(this.titleElement);
+
+ this.title = title;
+ this.subtitle = subtitle;
+ this.selected = false;
+}
+
+WebInspector.Placard.prototype = {
+ get title()
+ {
+ return this._title;
+ },
+
+ set title(x)
+ {
+ if (this._title === x)
+ return;
+ this._title = x;
+ this.titleElement.textContent = x;
+ },
+
+ get subtitle()
+ {
+ return this._subtitle;
+ },
+
+ set subtitle(x)
+ {
+ if (this._subtitle === x)
+ return;
+ this._subtitle = x;
+ this.subtitleElement.innerHTML = x;
+ },
+
+ get selected()
+ {
+ return this._selected;
+ },
+
+ set selected(x)
+ {
+ if (x)
+ this.select();
+ else
+ this.deselect();
+ },
+
+ select: function()
+ {
+ if (this._selected)
+ return;
+ this._selected = true;
+ this.element.addStyleClass("selected");
+ },
+
+ deselect: function()
+ {
+ if (!this._selected)
+ return;
+ this._selected = false;
+ this.element.removeStyleClass("selected");
+ },
+
+ toggleSelected: function()
+ {
+ this.selected = !this.selected;
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ProfileDataGridTree.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ProfileDataGridTree.js
new file mode 100644
index 0000000..84d9923
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ProfileDataGridTree.js
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2009 280 North Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ProfileDataGridNode = function(profileView, profileNode, owningTree, hasChildren)
+{
+ this.profileView = profileView;
+ this.profileNode = profileNode;
+
+ WebInspector.DataGridNode.call(this, null, hasChildren);
+
+ this.addEventListener("populate", this._populate, this);
+
+ this.tree = owningTree;
+
+ this.childrenByCallUID = {};
+ this.lastComparator = null;
+
+ this.callUID = profileNode.callUID;
+ this.selfTime = profileNode.selfTime;
+ this.totalTime = profileNode.totalTime;
+ this.functionName = profileNode.functionName;
+ this.numberOfCalls = profileNode.numberOfCalls;
+ this.url = profileNode.url;
+}
+
+WebInspector.ProfileDataGridNode.prototype = {
+ get data()
+ {
+ function formatMilliseconds(time)
+ {
+ return Number.secondsToString(time / 1000, WebInspector.UIString.bind(WebInspector), true);
+ }
+
+ var data = {};
+
+ data["function"] = this.functionName;
+ data["calls"] = this.numberOfCalls;
+
+ if (this.profileView.showSelfTimeAsPercent)
+ data["self"] = WebInspector.UIString("%.2f%%", this.selfPercent);
+ else
+ data["self"] = formatMilliseconds(this.selfTime);
+
+ if (this.profileView.showTotalTimeAsPercent)
+ data["total"] = WebInspector.UIString("%.2f%%", this.totalPercent);
+ else
+ data["total"] = formatMilliseconds(this.totalTime);
+
+ if (this.profileView.showAverageTimeAsPercent)
+ data["average"] = WebInspector.UIString("%.2f%%", this.averagePercent);
+ else
+ data["average"] = formatMilliseconds(this.averageTime);
+
+ return data;
+ },
+
+ createCell: function(columnIdentifier)
+ {
+ var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier);
+
+ if (columnIdentifier === "self" && this._searchMatchedSelfColumn)
+ cell.addStyleClass("highlight");
+ else if (columnIdentifier === "total" && this._searchMatchedTotalColumn)
+ cell.addStyleClass("highlight");
+ else if (columnIdentifier === "average" && this._searchMatchedAverageColumn)
+ cell.addStyleClass("highlight");
+ else if (columnIdentifier === "calls" && this._searchMatchedCallsColumn)
+ cell.addStyleClass("highlight");
+
+ if (columnIdentifier !== "function")
+ return cell;
+
+ if (this.profileNode._searchMatchedFunctionColumn)
+ cell.addStyleClass("highlight");
+
+ if (this.profileNode.url) {
+ var fileName = WebInspector.displayNameForURL(this.profileNode.url);
+
+ var urlElement = document.createElement("a");
+ urlElement.className = "profile-node-file webkit-html-resource-link";
+ urlElement.href = this.profileNode.url;
+ urlElement.lineNumber = this.profileNode.lineNumber;
+
+ if (this.profileNode.lineNumber > 0)
+ urlElement.textContent = fileName + ":" + this.profileNode.lineNumber;
+ else
+ urlElement.textContent = fileName;
+
+ cell.insertBefore(urlElement, cell.firstChild);
+ }
+
+ return cell;
+ },
+
+ select: function(supressSelectedEvent)
+ {
+ WebInspector.DataGridNode.prototype.select.call(this, supressSelectedEvent);
+ this.profileView._dataGridNodeSelected(this);
+ },
+
+ deselect: function(supressDeselectedEvent)
+ {
+ WebInspector.DataGridNode.prototype.deselect.call(this, supressDeselectedEvent);
+ this.profileView._dataGridNodeDeselected(this);
+ },
+
+ expand: function()
+ {
+ if (!this.parent) {
+ var currentComparator = this.parent.lastComparator;
+
+ if (!currentComparator || (currentComparator === this.lastComparator))
+ return;
+
+ this.sort(currentComparator);
+ }
+
+ WebInspector.DataGridNode.prototype.expand.call(this);
+ },
+
+ sort: function(/*Function*/ comparator, /*Boolean*/ force)
+ {
+ var gridNodeGroups = [[this]];
+
+ for (var gridNodeGroupIndex = 0; gridNodeGroupIndex < gridNodeGroups.length; ++gridNodeGroupIndex) {
+ var gridNodes = gridNodeGroups[gridNodeGroupIndex];
+ var count = gridNodes.length;
+
+ for (var index = 0; index < count; ++index) {
+ var gridNode = gridNodes[index];
+
+ // If the grid node is collapsed, then don't sort children (save operation for later).
+ // If the grid node has the same sorting as previously, then there is no point in sorting it again.
+ if (!force && !gridNode.expanded || gridNode.lastComparator === comparator)
+ continue;
+
+ gridNode.lastComparator = comparator;
+
+ var children = gridNode.children;
+ var childCount = children.length;
+
+ if (childCount) {
+ children.sort(comparator);
+
+ for (var childIndex = 0; childIndex < childCount; ++childIndex)
+ children[childIndex]._recalculateSiblings(childIndex);
+
+ gridNodeGroups.push(children);
+ }
+ }
+ }
+ },
+
+ insertChild: function(/*ProfileDataGridNode*/ profileDataGridNode, index)
+ {
+ WebInspector.DataGridNode.prototype.insertChild.call(this, profileDataGridNode, index);
+
+ this.childrenByCallUID[profileDataGridNode.callUID] = profileDataGridNode;
+ },
+
+ removeChild: function(/*ProfileDataGridNode*/ profileDataGridNode)
+ {
+ WebInspector.DataGridNode.prototype.removeChild.call(this, profileDataGridNode);
+
+ delete this.childrenByCallUID[profileDataGridNode.callUID];
+ },
+
+ removeChildren: function(/*ProfileDataGridNode*/ profileDataGridNode)
+ {
+ WebInspector.DataGridNode.prototype.removeChildren.call(this);
+
+ this.childrenByCallUID = {};
+ },
+
+ findChild: function(/*Node*/ node)
+ {
+ if (!node)
+ return null;
+ return this.childrenByCallUID[node.callUID];
+ },
+
+ get averageTime()
+ {
+ return this.selfTime / Math.max(1, this.numberOfCalls);
+ },
+
+ get averagePercent()
+ {
+ return this.averageTime / this.tree.totalTime * 100.0;
+ },
+
+ get selfPercent()
+ {
+ return this.selfTime / this.tree.totalTime * 100.0;
+ },
+
+ get totalPercent()
+ {
+ return this.totalTime / this.tree.totalTime * 100.0;
+ },
+
+ // When focusing and collapsing we modify lots of nodes in the tree.
+ // This allows us to restore them all to their original state when we revert.
+ _save: function()
+ {
+ if (this._savedChildren)
+ return;
+
+ this._savedSelfTime = this.selfTime;
+ this._savedTotalTime = this.totalTime;
+ this._savedNumberOfCalls = this.numberOfCalls;
+
+ this._savedChildren = this.children.slice();
+ },
+
+ // When focusing and collapsing we modify lots of nodes in the tree.
+ // This allows us to restore them all to their original state when we revert.
+ _restore: function()
+ {
+ if (!this._savedChildren)
+ return;
+
+ this.selfTime = this._savedSelfTime;
+ this.totalTime = this._savedTotalTime;
+ this.numberOfCalls = this._savedNumberOfCalls;
+
+ this.removeChildren();
+
+ var children = this._savedChildren;
+ var count = children.length;
+
+ for (var index = 0; index < count; ++index) {
+ children[index]._restore();
+ this.appendChild(children[index]);
+ }
+ },
+
+ _merge: function(child, shouldAbsorb)
+ {
+ this.selfTime += child.selfTime;
+
+ if (!shouldAbsorb) {
+ this.totalTime += child.totalTime;
+ this.numberOfCalls += child.numberOfCalls;
+ }
+
+ var children = this.children.slice();
+
+ this.removeChildren();
+
+ var count = children.length;
+
+ for (var index = 0; index < count; ++index) {
+ if (!shouldAbsorb || children[index] !== child)
+ this.appendChild(children[index]);
+ }
+
+ children = child.children.slice();
+ count = children.length;
+
+ for (var index = 0; index < count; ++index) {
+ var orphanedChild = children[index],
+ existingChild = this.childrenByCallUID[orphanedChild.callUID];
+
+ if (existingChild)
+ existingChild._merge(orphanedChild, false);
+ else
+ this.appendChild(orphanedChild);
+ }
+ }
+}
+
+WebInspector.ProfileDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
+
+WebInspector.ProfileDataGridTree = function(profileView, profileNode)
+{
+ this.tree = this;
+ this.children = [];
+
+ this.profileView = profileView;
+
+ this.totalTime = profileNode.totalTime;
+ this.lastComparator = null;
+
+ this.childrenByCallUID = {};
+}
+
+WebInspector.ProfileDataGridTree.prototype = {
+ get expanded()
+ {
+ return true;
+ },
+
+ appendChild: function(child)
+ {
+ this.insertChild(child, this.children.length);
+ },
+
+ insertChild: function(child, index)
+ {
+ this.children.splice(index, 0, child);
+ this.childrenByCallUID[child.callUID] = child;
+ },
+
+ removeChildren: function()
+ {
+ this.children = [];
+ this.childrenByCallUID = {};
+ },
+
+ findChild: WebInspector.ProfileDataGridNode.prototype.findChild,
+ sort: WebInspector.ProfileDataGridNode.prototype.sort,
+
+ _save: function()
+ {
+ if (this._savedChildren)
+ return;
+
+ this._savedTotalTime = this.totalTime;
+ this._savedChildren = this.children.slice();
+ },
+
+ restore: function()
+ {
+ if (!this._savedChildren)
+ return;
+
+ this.children = this._savedChildren;
+ this.totalTime = this._savedTotalTime;
+
+ var children = this.children;
+ var count = children.length;
+
+ for (var index = 0; index < count; ++index)
+ children[index]._restore();
+
+ this._savedChildren = null;
+ }
+}
+
+WebInspector.ProfileDataGridTree.propertyComparators = [{}, {}];
+
+WebInspector.ProfileDataGridTree.propertyComparator = function(/*String*/ property, /*Boolean*/ isAscending)
+{
+ var comparator = this.propertyComparators[(isAscending ? 1 : 0)][property];
+
+ if (!comparator) {
+ if (isAscending) {
+ comparator = function(lhs, rhs)
+ {
+ if (lhs[property] < rhs[property])
+ return -1;
+
+ if (lhs[property] > rhs[property])
+ return 1;
+
+ return 0;
+ }
+ } else {
+ comparator = function(lhs, rhs)
+ {
+ if (lhs[property] > rhs[property])
+ return -1;
+
+ if (lhs[property] < rhs[property])
+ return 1;
+
+ return 0;
+ }
+ }
+
+ this.propertyComparators[(isAscending ? 1 : 0)][property] = comparator;
+ }
+
+ return comparator;
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ProfileView.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ProfileView.js
new file mode 100644
index 0000000..d00733c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ProfileView.js
@@ -0,0 +1,580 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ProfileView = function(profile)
+{
+ WebInspector.View.call(this);
+
+ this.element.addStyleClass("profile-view");
+
+ this.showSelfTimeAsPercent = true;
+ this.showTotalTimeAsPercent = true;
+ this.showAverageTimeAsPercent = true;
+
+ var columns = { "self": { title: WebInspector.UIString("Self"), width: "72px", sort: "descending", sortable: true },
+ "total": { title: WebInspector.UIString("Total"), width: "72px", sortable: true },
+ "average": { title: WebInspector.UIString("Average"), width: "72px", sortable: true },
+ "calls": { title: WebInspector.UIString("Calls"), width: "54px", sortable: true },
+ "function": { title: WebInspector.UIString("Function"), disclosure: true, 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.viewSelectElement = document.createElement("select");
+ this.viewSelectElement.className = "status-bar-item";
+ this.viewSelectElement.addEventListener("change", this._changeView.bind(this), false);
+ this.view = "Heavy";
+
+ var heavyViewOption = document.createElement("option");
+ heavyViewOption.label = WebInspector.UIString("Heavy (Bottom Up)");
+ var treeViewOption = document.createElement("option");
+ treeViewOption.label = WebInspector.UIString("Tree (Top Down)");
+ this.viewSelectElement.appendChild(heavyViewOption);
+ this.viewSelectElement.appendChild(treeViewOption);
+
+ this.percentButton = document.createElement("button");
+ this.percentButton.className = "percent-time-status-bar-item status-bar-item";
+ this.percentButton.addEventListener("click", this._percentClicked.bind(this), false);
+
+ this.focusButton = document.createElement("button");
+ this.focusButton.title = WebInspector.UIString("Focus selected function.");
+ this.focusButton.className = "focus-profile-node-status-bar-item status-bar-item";
+ this.focusButton.disabled = true;
+ this.focusButton.addEventListener("click", this._focusClicked.bind(this), false);
+
+ this.excludeButton = document.createElement("button");
+ this.excludeButton.title = WebInspector.UIString("Exclude selected function.");
+ this.excludeButton.className = "exclude-profile-node-status-bar-item status-bar-item";
+ this.excludeButton.disabled = true;
+ this.excludeButton.addEventListener("click", this._excludeClicked.bind(this), false);
+
+ this.resetButton = document.createElement("button");
+ this.resetButton.title = WebInspector.UIString("Restore all functions.");
+ this.resetButton.className = "reset-profile-status-bar-item status-bar-item hidden";
+ this.resetButton.addEventListener("click", this._resetClicked.bind(this), false);
+
+ this.profile = profile;
+
+ this.profileDataGridTree = this.bottomUpProfileDataGridTree;
+ this.profileDataGridTree.sort(WebInspector.ProfileDataGridTree.propertyComparator("selfTime", false));
+
+ this.refresh();
+
+ this._updatePercentButton();
+}
+
+WebInspector.ProfileView.prototype = {
+ get statusBarItems()
+ {
+ return [this.viewSelectElement, this.percentButton, this.focusButton, this.excludeButton, this.resetButton];
+ },
+
+ get profile()
+ {
+ return this._profile;
+ },
+
+ set profile(profile)
+ {
+ this._profile = profile;
+ },
+
+ get bottomUpProfileDataGridTree()
+ {
+ if (!this._bottomUpProfileDataGridTree)
+ this._bottomUpProfileDataGridTree = new WebInspector.BottomUpProfileDataGridTree(this, this.profile.head);
+ return this._bottomUpProfileDataGridTree;
+ },
+
+ get topDownProfileDataGridTree()
+ {
+ if (!this._topDownProfileDataGridTree)
+ this._topDownProfileDataGridTree = new WebInspector.TopDownProfileDataGridTree(this, this.profile.head);
+ return this._topDownProfileDataGridTree;
+ },
+
+ get currentTree()
+ {
+ return this._currentTree;
+ },
+
+ set currentTree(tree)
+ {
+ this._currentTree = tree;
+ this.refresh();
+ },
+
+ get topDownTree()
+ {
+ if (!this._topDownTree) {
+ this._topDownTree = WebInspector.TopDownTreeFactory.create(this.profile.head);
+ this._sortProfile(this._topDownTree);
+ }
+
+ return this._topDownTree;
+ },
+
+ get bottomUpTree()
+ {
+ if (!this._bottomUpTree) {
+ this._bottomUpTree = WebInspector.BottomUpTreeFactory.create(this.profile.head);
+ this._sortProfile(this._bottomUpTree);
+ }
+
+ return this._bottomUpTree;
+ },
+
+ hide: function()
+ {
+ WebInspector.View.prototype.hide.call(this);
+ this._currentSearchResultIndex = -1;
+ },
+
+ refresh: function()
+ {
+ var selectedProfileNode = this.dataGrid.selectedNode ? this.dataGrid.selectedNode.profileNode : null;
+
+ this.dataGrid.removeChildren();
+
+ var children = this.profileDataGridTree.children;
+ var count = children.length;
+
+ for (var index = 0; index < count; ++index)
+ this.dataGrid.appendChild(children[index]);
+
+ if (selectedProfileNode && selectedProfileNode._dataGridNode)
+ selectedProfileNode._dataGridNode.selected = true;
+ },
+
+ refreshVisibleData: function()
+ {
+ var child = this.dataGrid.children[0];
+ while (child) {
+ child.refresh();
+ child = child.traverseNextNode(false, null, true);
+ }
+ },
+
+ refreshShowAsPercents: function()
+ {
+ this._updatePercentButton();
+ this.refreshVisibleData();
+ },
+
+ searchCanceled: function()
+ {
+ if (this._searchResults) {
+ for (var i = 0; i < this._searchResults.length; ++i) {
+ var profileNode = this._searchResults[i].profileNode;
+
+ delete profileNode._searchMatchedSelfColumn;
+ delete profileNode._searchMatchedTotalColumn;
+ delete profileNode._searchMatchedCallsColumn;
+ delete profileNode._searchMatchedFunctionColumn;
+
+ if (profileNode._dataGridNode)
+ profileNode._dataGridNode.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 greaterThan = (query.indexOf(">") === 0);
+ var lessThan = (query.indexOf("<") === 0);
+ var equalTo = (query.indexOf("=") === 0 || ((greaterThan || lessThan) && query.indexOf("=") === 1));
+ var percentUnits = (query.lastIndexOf("%") === (query.length - 1));
+ var millisecondsUnits = (query.length > 2 && query.lastIndexOf("ms") === (query.length - 2));
+ var secondsUnits = (!millisecondsUnits && query.lastIndexOf("s") === (query.length - 1));
+
+ var queryNumber = parseFloat(query);
+ if (greaterThan || lessThan || equalTo) {
+ if (equalTo && (greaterThan || lessThan))
+ queryNumber = parseFloat(query.substring(2));
+ else
+ queryNumber = parseFloat(query.substring(1));
+ }
+
+ var queryNumberMilliseconds = (secondsUnits ? (queryNumber * 1000) : queryNumber);
+
+ // Make equalTo implicitly true if it wasn't specified there is no other operator.
+ if (!isNaN(queryNumber) && !(greaterThan || lessThan))
+ equalTo = true;
+
+ function matchesQuery(/*ProfileDataGridNode*/ profileDataGridNode)
+ {
+ delete profileDataGridNode._searchMatchedSelfColumn;
+ delete profileDataGridNode._searchMatchedTotalColumn;
+ delete profileDataGridNode._searchMatchedAverageColumn;
+ delete profileDataGridNode._searchMatchedCallsColumn;
+ delete profileDataGridNode._searchMatchedFunctionColumn;
+
+ if (percentUnits) {
+ if (lessThan) {
+ if (profileDataGridNode.selfPercent < queryNumber)
+ profileDataGridNode._searchMatchedSelfColumn = true;
+ if (profileDataGridNode.totalPercent < queryNumber)
+ profileDataGridNode._searchMatchedTotalColumn = true;
+ if (profileDataGridNode.averagePercent < queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedAverageColumn = true;
+ } else if (greaterThan) {
+ if (profileDataGridNode.selfPercent > queryNumber)
+ profileDataGridNode._searchMatchedSelfColumn = true;
+ if (profileDataGridNode.totalPercent > queryNumber)
+ profileDataGridNode._searchMatchedTotalColumn = true;
+ if (profileDataGridNode.averagePercent < queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedAverageColumn = true;
+ }
+
+ if (equalTo) {
+ if (profileDataGridNode.selfPercent == queryNumber)
+ profileDataGridNode._searchMatchedSelfColumn = true;
+ if (profileDataGridNode.totalPercent == queryNumber)
+ profileDataGridNode._searchMatchedTotalColumn = true;
+ if (profileDataGridNode.averagePercent < queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedAverageColumn = true;
+ }
+ } else if (millisecondsUnits || secondsUnits) {
+ if (lessThan) {
+ if (profileDataGridNode.selfTime < queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedSelfColumn = true;
+ if (profileDataGridNode.totalTime < queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedTotalColumn = true;
+ if (profileDataGridNode.averageTime < queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedAverageColumn = true;
+ } else if (greaterThan) {
+ if (profileDataGridNode.selfTime > queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedSelfColumn = true;
+ if (profileDataGridNode.totalTime > queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedTotalColumn = true;
+ if (profileDataGridNode.averageTime > queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedAverageColumn = true;
+ }
+
+ if (equalTo) {
+ if (profileDataGridNode.selfTime == queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedSelfColumn = true;
+ if (profileDataGridNode.totalTime == queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedTotalColumn = true;
+ if (profileDataGridNode.averageTime == queryNumberMilliseconds)
+ profileDataGridNode._searchMatchedAverageColumn = true;
+ }
+ } else {
+ if (equalTo && profileDataGridNode.numberOfCalls == queryNumber)
+ profileDataGridNode._searchMatchedCallsColumn = true;
+ if (greaterThan && profileDataGridNode.numberOfCalls > queryNumber)
+ profileDataGridNode._searchMatchedCallsColumn = true;
+ if (lessThan && profileDataGridNode.numberOfCalls < queryNumber)
+ profileDataGridNode._searchMatchedCallsColumn = true;
+ }
+
+ if (profileDataGridNode.functionName.hasSubstring(query, true) || profileDataGridNode.url.hasSubstring(query, true))
+ profileDataGridNode._searchMatchedFunctionColumn = true;
+
+ if (profileDataGridNode._searchMatchedSelfColumn ||
+ profileDataGridNode._searchMatchedTotalColumn ||
+ profileDataGridNode._searchMatchedAverageColumn ||
+ profileDataGridNode._searchMatchedCallsColumn ||
+ profileDataGridNode._searchMatchedFunctionColumn);
+ {
+ profileDataGridNode.refresh();
+ return true;
+ }
+
+ return false;
+ }
+
+ var current = this.dataGrid;
+ var ancestors = [];
+ var nextIndexes = [];
+ var startIndex = 0;
+
+ while (current) {
+ var children = current.children;
+ var childrenLength = children.length;
+
+ if (startIndex >= childrenLength) {
+ current = ancestors.pop();
+ startIndex = nextIndexes.pop();
+ continue;
+ }
+
+ for (var i = startIndex; i < childrenLength; ++i) {
+ var child = children[i];
+
+ if (matchesQuery(child)) {
+ if (child._dataGridNode) {
+ // The child has a data grid node already, no need to remember the ancestors.
+ this._searchResults.push({ profileNode: child });
+ } else {
+ var ancestorsCopy = [].concat(ancestors);
+ ancestorsCopy.push(current);
+ this._searchResults.push({ profileNode: child, ancestors: ancestorsCopy });
+ }
+ }
+
+ if (child.children.length) {
+ ancestors.push(current);
+ nextIndexes.push(i + 1);
+ current = child;
+ startIndex = 0;
+ break;
+ }
+
+ if (i === (childrenLength - 1)) {
+ current = ancestors.pop();
+ startIndex = nextIndexes.pop();
+ }
+ }
+ }
+
+ finishedCallback(this, this._searchResults.length);
+ },
+
+ jumpToFirstSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ this._currentSearchResultIndex = 0;
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToLastSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ this._currentSearchResultIndex = (this._searchResults.length - 1);
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToNextSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ if (++this._currentSearchResultIndex >= this._searchResults.length)
+ this._currentSearchResultIndex = 0;
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToPreviousSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ if (--this._currentSearchResultIndex < 0)
+ this._currentSearchResultIndex = (this._searchResults.length - 1);
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ showingFirstSearchResult: function()
+ {
+ return (this._currentSearchResultIndex === 0);
+ },
+
+ showingLastSearchResult: function()
+ {
+ return (this._searchResults && this._currentSearchResultIndex === (this._searchResults.length - 1));
+ },
+
+ _jumpToSearchResult: function(index)
+ {
+ var searchResult = this._searchResults[index];
+ if (!searchResult)
+ return;
+
+ var profileNode = this._searchResults[index].profileNode;
+ if (!profileNode._dataGridNode && searchResult.ancestors) {
+ var ancestors = searchResult.ancestors;
+ for (var i = 0; i < ancestors.length; ++i) {
+ var ancestorProfileNode = ancestors[i];
+ var gridNode = ancestorProfileNode._dataGridNode;
+ if (gridNode)
+ gridNode.expand();
+ }
+
+ // No need to keep the ancestors around.
+ delete searchResult.ancestors;
+ }
+
+ gridNode = profileNode._dataGridNode;
+ if (!gridNode)
+ return;
+
+ gridNode.reveal();
+ gridNode.select();
+ },
+
+ _changeView: function(event)
+ {
+ if (!event || !this.profile)
+ return;
+
+ if (event.target.selectedIndex == 1 && this.view == "Heavy") {
+ this.profileDataGridTree = this.topDownProfileDataGridTree;
+ this._sortProfile();
+ this.view = "Tree";
+ } else if (event.target.selectedIndex == 0 && this.view == "Tree") {
+ this.profileDataGridTree = this.bottomUpProfileDataGridTree;
+ this._sortProfile();
+ this.view = "Heavy";
+ }
+
+ 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 the with same query and callback.
+ this._searchFinishedCallback(this, -this._searchResults.length);
+ this.performSearch(this.currentQuery, this._searchFinishedCallback);
+ },
+
+ _percentClicked: function(event)
+ {
+ var currentState = this.showSelfTimeAsPercent && this.showTotalTimeAsPercent && this.showAverageTimeAsPercent;
+ this.showSelfTimeAsPercent = !currentState;
+ this.showTotalTimeAsPercent = !currentState;
+ this.showAverageTimeAsPercent = !currentState;
+ this.refreshShowAsPercents();
+ },
+
+ _updatePercentButton: function()
+ {
+ if (this.showSelfTimeAsPercent && this.showTotalTimeAsPercent && this.showAverageTimeAsPercent) {
+ this.percentButton.title = WebInspector.UIString("Show absolute total and self times.");
+ this.percentButton.addStyleClass("toggled-on");
+ } else {
+ this.percentButton.title = WebInspector.UIString("Show total and self times as percentages.");
+ this.percentButton.removeStyleClass("toggled-on");
+ }
+ },
+
+ _focusClicked: function(event)
+ {
+ if (!this.dataGrid.selectedNode)
+ return;
+
+ this.resetButton.removeStyleClass("hidden");
+ this.profileDataGridTree.focus(this.dataGrid.selectedNode);
+ this.refresh();
+ this.refreshVisibleData();
+ },
+
+ _excludeClicked: function(event)
+ {
+ var selectedNode = this.dataGrid.selectedNode
+
+ if (!selectedNode)
+ return;
+
+ selectedNode.deselect();
+
+ this.resetButton.removeStyleClass("hidden");
+ this.profileDataGridTree.exclude(selectedNode);
+ this.refresh();
+ this.refreshVisibleData();
+ },
+
+ _resetClicked: function(event)
+ {
+ this.resetButton.addStyleClass("hidden");
+ this.profileDataGridTree.restore();
+ this.refresh();
+ this.refreshVisibleData();
+ },
+
+ _dataGridNodeSelected: function(node)
+ {
+ this.focusButton.disabled = false;
+ this.excludeButton.disabled = false;
+ },
+
+ _dataGridNodeDeselected: function(node)
+ {
+ this.focusButton.disabled = true;
+ this.excludeButton.disabled = true;
+ },
+
+ _sortData: function(event)
+ {
+ this._sortProfile(this.profile);
+ },
+
+ _sortProfile: function()
+ {
+ var sortAscending = this.dataGrid.sortOrder === "ascending";
+ var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
+ var sortProperty = {
+ "average": "averageTime",
+ "self": "selfTime",
+ "total": "totalTime",
+ "calls": "numberOfCalls",
+ "function": "functionName"
+ }[sortColumnIdentifier];
+
+ this.profileDataGridTree.sort(WebInspector.ProfileDataGridTree.propertyComparator(sortProperty, sortAscending));
+
+ this.refresh();
+ },
+
+ _mouseDownInDataGrid: function(event)
+ {
+ if (event.detail < 2)
+ return;
+
+ var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
+ if (!cell || (!cell.hasStyleClass("total-column") && !cell.hasStyleClass("self-column") && !cell.hasStyleClass("average-column")))
+ return;
+
+ if (cell.hasStyleClass("total-column"))
+ this.showTotalTimeAsPercent = !this.showTotalTimeAsPercent;
+ else if (cell.hasStyleClass("self-column"))
+ this.showSelfTimeAsPercent = !this.showSelfTimeAsPercent;
+ else if (cell.hasStyleClass("average-column"))
+ this.showAverageTimeAsPercent = !this.showAverageTimeAsPercent;
+
+ this.refreshShowAsPercents();
+
+ event.preventDefault();
+ event.stopPropagation();
+ }
+}
+
+WebInspector.ProfileView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ProfilesPanel.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ProfilesPanel.js
new file mode 100644
index 0000000..aafc306
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ProfilesPanel.js
@@ -0,0 +1,502 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+const UserInitiatedProfileName = "org.webkit.profiles.user-initiated";
+
+WebInspector.ProfilesPanel = function()
+{
+ WebInspector.Panel.call(this);
+
+ this.element.addStyleClass("profiles");
+
+ var panelEnablerHeading = WebInspector.UIString("You need to enable profiling before you can use the Profiles panel.");
+ var panelEnablerDisclaimer = WebInspector.UIString("Enabling profiling will make scripts run slower.");
+ var panelEnablerButton = WebInspector.UIString("Enable Profiling");
+ this.panelEnablerView = new WebInspector.PanelEnablerView("profiles", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
+ this.panelEnablerView.addEventListener("enable clicked", this._enableProfiling, this);
+
+ this.element.appendChild(this.panelEnablerView.element);
+
+ this.sidebarElement = document.createElement("div");
+ this.sidebarElement.id = "profiles-sidebar";
+ this.sidebarElement.className = "sidebar";
+ this.element.appendChild(this.sidebarElement);
+
+ this.sidebarResizeElement = document.createElement("div");
+ this.sidebarResizeElement.className = "sidebar-resizer-vertical";
+ this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarDragging.bind(this), false);
+ this.element.appendChild(this.sidebarResizeElement);
+
+ this.sidebarTreeElement = document.createElement("ol");
+ this.sidebarTreeElement.className = "sidebar-tree";
+ this.sidebarElement.appendChild(this.sidebarTreeElement);
+
+ this.sidebarTree = new TreeOutline(this.sidebarTreeElement);
+
+ this.profileViews = document.createElement("div");
+ this.profileViews.id = "profile-views";
+ this.element.appendChild(this.profileViews);
+
+ this.enableToggleButton = document.createElement("button");
+ this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item";
+ this.enableToggleButton.addEventListener("click", this._toggleProfiling.bind(this), false);
+
+ this.recordButton = document.createElement("button");
+ this.recordButton.title = WebInspector.UIString("Start profiling.");
+ this.recordButton.id = "record-profile-status-bar-item";
+ this.recordButton.className = "status-bar-item";
+ this.recordButton.addEventListener("click", this._recordClicked.bind(this), false);
+
+ this.recording = false;
+
+ this.profileViewStatusBarItemsContainer = document.createElement("div");
+ this.profileViewStatusBarItemsContainer.id = "profile-view-status-bar-items";
+
+ this.reset();
+}
+
+WebInspector.ProfilesPanel.prototype = {
+ toolbarItemClass: "profiles",
+
+ get toolbarItemLabel()
+ {
+ return WebInspector.UIString("Profiles");
+ },
+
+ get statusBarItems()
+ {
+ return [this.enableToggleButton, this.recordButton, this.profileViewStatusBarItemsContainer];
+ },
+
+ show: function()
+ {
+ WebInspector.Panel.prototype.show.call(this);
+ this._updateSidebarWidth();
+ if (this._shouldPopulateProfiles)
+ this._populateProfiles();
+ },
+
+ populateInterface: function()
+ {
+ if (this.visible)
+ this._populateProfiles();
+ else
+ this._shouldPopulateProfiles = true;
+ },
+
+ profilerWasEnabled: function()
+ {
+ this.reset();
+ this.populateInterface();
+ },
+
+ profilerWasDisabled: function()
+ {
+ this.reset();
+ },
+
+ reset: function()
+ {
+ if (this._profiles) {
+ var profiledLength = this._profiles.length;
+ for (var i = 0; i < profiledLength; ++i) {
+ var profile = this._profiles[i];
+ delete profile._profileView;
+ }
+ }
+
+ delete this.currentQuery;
+ this.searchCanceled();
+
+ this._profiles = [];
+ this._profilesIdMap = {};
+ this._profileGroups = {};
+ this._profileGroupsForLinks = {}
+
+ this.sidebarTreeElement.removeStyleClass("some-expandable");
+
+ this.sidebarTree.removeChildren();
+ this.profileViews.removeChildren();
+
+ this.profileViewStatusBarItemsContainer.removeChildren();
+
+ this._updateInterface();
+ },
+
+ handleKeyEvent: function(event)
+ {
+ this.sidebarTree.handleKeyEvent(event);
+ },
+
+ addProfile: function(profile)
+ {
+ this._profiles.push(profile);
+ this._profilesIdMap[profile.uid] = profile;
+
+ var sidebarParent = this.sidebarTree;
+ var small = false;
+ var alternateTitle;
+
+ if (profile.title.indexOf(UserInitiatedProfileName) !== 0) {
+ if (!(profile.title in this._profileGroups))
+ this._profileGroups[profile.title] = [];
+
+ var group = this._profileGroups[profile.title];
+ group.push(profile);
+
+ if (group.length === 2) {
+ // Make a group TreeElement now that there are 2 profiles.
+ group._profilesTreeElement = new WebInspector.ProfileGroupSidebarTreeElement(profile.title);
+
+ // Insert at the same index for the first profile of the group.
+ var index = this.sidebarTree.children.indexOf(group[0]._profilesTreeElement);
+ this.sidebarTree.insertChild(group._profilesTreeElement, index);
+
+ // Move the first profile to the group.
+ var selected = group[0]._profilesTreeElement.selected;
+ this.sidebarTree.removeChild(group[0]._profilesTreeElement);
+ group._profilesTreeElement.appendChild(group[0]._profilesTreeElement);
+ if (selected) {
+ group[0]._profilesTreeElement.select();
+ group[0]._profilesTreeElement.reveal();
+ }
+
+ group[0]._profilesTreeElement.small = true;
+ group[0]._profilesTreeElement.mainTitle = WebInspector.UIString("Run %d", 1);
+
+ this.sidebarTreeElement.addStyleClass("some-expandable");
+ }
+
+ if (group.length >= 2) {
+ sidebarParent = group._profilesTreeElement;
+ alternateTitle = WebInspector.UIString("Run %d", group.length);
+ small = true;
+ }
+ }
+
+ var profileTreeElement = new WebInspector.ProfileSidebarTreeElement(profile);
+ profileTreeElement.small = small;
+ if (alternateTitle)
+ profileTreeElement.mainTitle = alternateTitle;
+ profile._profilesTreeElement = profileTreeElement;
+
+ sidebarParent.appendChild(profileTreeElement);
+ },
+
+ showProfile: function(profile)
+ {
+ if (!profile)
+ return;
+
+ if (this.visibleView)
+ this.visibleView.hide();
+
+ var view = this.profileViewForProfile(profile);
+
+ view.show(this.profileViews);
+
+ profile._profilesTreeElement.select(true);
+ profile._profilesTreeElement.reveal();
+
+ this.visibleView = view;
+
+ this.profileViewStatusBarItemsContainer.removeChildren();
+
+ var statusBarItems = view.statusBarItems;
+ for (var i = 0; i < statusBarItems.length; ++i)
+ this.profileViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
+ },
+
+ showView: function(view)
+ {
+ this.showProfile(view.profile);
+ },
+
+ profileViewForProfile: function(profile)
+ {
+ if (!profile)
+ return null;
+ if (!profile._profileView)
+ profile._profileView = new WebInspector.ProfileView(profile);
+ return profile._profileView;
+ },
+
+ showProfileById: function(uid)
+ {
+ this.showProfile(this._profilesIdMap[uid]);
+ },
+
+ closeVisibleView: function()
+ {
+ if (this.visibleView)
+ this.visibleView.hide();
+ delete this.visibleView;
+ },
+
+ displayTitleForProfileLink: function(title)
+ {
+ title = unescape(title);
+ if (title.indexOf(UserInitiatedProfileName) === 0) {
+ title = WebInspector.UIString("Profile %d", title.substring(UserInitiatedProfileName.length + 1));
+ } else {
+ if (!(title in this._profileGroupsForLinks))
+ this._profileGroupsForLinks[title] = 0;
+
+ groupNumber = ++this._profileGroupsForLinks[title];
+
+ if (groupNumber >= 2)
+ title += " " + WebInspector.UIString("Run %d", groupNumber);
+ }
+
+ return title;
+ },
+
+ get searchableViews()
+ {
+ var views = [];
+
+ const visibleView = this.visibleView;
+ if (visibleView && visibleView.performSearch)
+ views.push(visibleView);
+
+ var profilesLength = this._profiles.length;
+ for (var i = 0; i < profilesLength; ++i) {
+ var view = this.profileViewForProfile(this._profiles[i]);
+ if (!view.performSearch || view === visibleView)
+ continue;
+ views.push(view);
+ }
+
+ return views;
+ },
+
+ searchMatchFound: function(view, matches)
+ {
+ view.profile._profilesTreeElement.searchMatches = matches;
+ },
+
+ searchCanceled: function(startingNewSearch)
+ {
+ WebInspector.Panel.prototype.searchCanceled.call(this, startingNewSearch);
+
+ if (!this._profiles)
+ return;
+
+ for (var i = 0; i < this._profiles.length; ++i) {
+ var profile = this._profiles[i];
+ profile._profilesTreeElement.searchMatches = 0;
+ }
+ },
+
+ setRecordingProfile: function(isProfiling)
+ {
+ this.recording = isProfiling;
+
+ if (isProfiling) {
+ this.recordButton.addStyleClass("toggled-on");
+ this.recordButton.title = WebInspector.UIString("Stop profiling.");
+ } else {
+ this.recordButton.removeStyleClass("toggled-on");
+ this.recordButton.title = WebInspector.UIString("Start profiling.");
+ }
+ },
+
+ _updateInterface: function()
+ {
+ if (InspectorController.profilerEnabled()) {
+ this.enableToggleButton.title = WebInspector.UIString("Profiling enabled. Click to disable.");
+ this.enableToggleButton.addStyleClass("toggled-on");
+ this.recordButton.removeStyleClass("hidden");
+ this.profileViewStatusBarItemsContainer.removeStyleClass("hidden");
+ this.panelEnablerView.visible = false;
+ } else {
+ this.enableToggleButton.title = WebInspector.UIString("Profiling disabled. Click to enable.");
+ this.enableToggleButton.removeStyleClass("toggled-on");
+ this.recordButton.addStyleClass("hidden");
+ this.profileViewStatusBarItemsContainer.addStyleClass("hidden");
+ this.panelEnablerView.visible = true;
+ }
+ },
+
+ _recordClicked: function()
+ {
+ this.recording = !this.recording;
+
+ if (this.recording)
+ InspectorController.startProfiling();
+ else
+ InspectorController.stopProfiling();
+ },
+
+ _enableProfiling: function()
+ {
+ if (InspectorController.profilerEnabled())
+ return;
+ this._toggleProfiling(this.panelEnablerView.alwaysEnabled);
+ },
+
+ _toggleProfiling: function(optionalAlways)
+ {
+ if (InspectorController.profilerEnabled())
+ InspectorController.disableProfiler(true);
+ else
+ InspectorController.enableProfiler(!!optionalAlways);
+ },
+
+ _populateProfiles: function()
+ {
+ if (this.sidebarTree.children.length)
+ return;
+
+ var profiles = InspectorController.profiles();
+ var profilesLength = profiles.length;
+ for (var i = 0; i < profilesLength; ++i) {
+ var profile = profiles[i];
+ this.addProfile(profile);
+ }
+
+ if (this.sidebarTree.children[0])
+ this.sidebarTree.children[0].select();
+
+ delete this._shouldPopulateProfiles;
+ },
+
+ _startSidebarDragging: function(event)
+ {
+ WebInspector.elementDragStart(this.sidebarResizeElement, this._sidebarDragging.bind(this), this._endSidebarDragging.bind(this), event, "col-resize");
+ },
+
+ _sidebarDragging: function(event)
+ {
+ this._updateSidebarWidth(event.pageX);
+
+ event.preventDefault();
+ },
+
+ _endSidebarDragging: function(event)
+ {
+ WebInspector.elementDragEnd(event);
+ },
+
+ _updateSidebarWidth: function(width)
+ {
+ if (this.sidebarElement.offsetWidth <= 0) {
+ // The stylesheet hasn't loaded yet or the window is closed,
+ // so we can't calculate what is need. Return early.
+ return;
+ }
+
+ if (!("_currentSidebarWidth" in this))
+ this._currentSidebarWidth = this.sidebarElement.offsetWidth;
+
+ if (typeof width === "undefined")
+ width = this._currentSidebarWidth;
+
+ width = Number.constrain(width, Preferences.minSidebarWidth, window.innerWidth / 2);
+
+ this._currentSidebarWidth = width;
+
+ this.sidebarElement.style.width = width + "px";
+ this.profileViews.style.left = width + "px";
+ this.profileViewStatusBarItemsContainer.style.left = width + "px";
+ this.sidebarResizeElement.style.left = (width - 3) + "px";
+ }
+}
+
+WebInspector.ProfilesPanel.prototype.__proto__ = WebInspector.Panel.prototype;
+
+WebInspector.ProfileSidebarTreeElement = function(profile)
+{
+ this.profile = profile;
+
+ if (this.profile.title.indexOf(UserInitiatedProfileName) === 0)
+ this._profileNumber = this.profile.title.substring(UserInitiatedProfileName.length + 1);
+
+ WebInspector.SidebarTreeElement.call(this, "profile-sidebar-tree-item", "", "", profile, false);
+
+ this.refreshTitles();
+}
+
+WebInspector.ProfileSidebarTreeElement.prototype = {
+ onselect: function()
+ {
+ WebInspector.panels.profiles.showProfile(this.profile);
+ },
+
+ get mainTitle()
+ {
+ if (this._mainTitle)
+ return this._mainTitle;
+ if (this.profile.title.indexOf(UserInitiatedProfileName) === 0)
+ return WebInspector.UIString("Profile %d", this._profileNumber);
+ return this.profile.title;
+ },
+
+ set mainTitle(x)
+ {
+ this._mainTitle = x;
+ this.refreshTitles();
+ },
+
+ get subtitle()
+ {
+ // There is no subtitle.
+ },
+
+ set subtitle(x)
+ {
+ // Can't change subtitle.
+ },
+
+ set searchMatches(matches)
+ {
+ if (!matches) {
+ if (!this.bubbleElement)
+ return;
+ this.bubbleElement.removeStyleClass("search-matches");
+ this.bubbleText = "";
+ return;
+ }
+
+ this.bubbleText = matches;
+ this.bubbleElement.addStyleClass("search-matches");
+ }
+}
+
+WebInspector.ProfileSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
+
+WebInspector.ProfileGroupSidebarTreeElement = function(title, subtitle)
+{
+ WebInspector.SidebarTreeElement.call(this, "profile-group-sidebar-tree-item", title, subtitle, null, true);
+}
+
+WebInspector.ProfileGroupSidebarTreeElement.prototype = {
+ onselect: function()
+ {
+ WebInspector.panels.profiles.showProfile(this.children[this.children.length - 1].profile);
+ }
+}
+
+WebInspector.ProfileGroupSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/PropertiesSection.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/PropertiesSection.js
new file mode 100644
index 0000000..a4b2fba
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/PropertiesSection.js
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.PropertiesSection = function(title, subtitle)
+{
+ this.element = document.createElement("div");
+ this.element.className = "section";
+
+ this.headerElement = document.createElement("div");
+ this.headerElement.className = "header";
+
+ this.titleElement = document.createElement("div");
+ this.titleElement.className = "title";
+
+ this.subtitleElement = document.createElement("div");
+ this.subtitleElement.className = "subtitle";
+
+ this.headerElement.appendChild(this.subtitleElement);
+ this.headerElement.appendChild(this.titleElement);
+
+ this.headerElement.addEventListener("click", this.toggleExpanded.bind(this), false);
+
+ this.propertiesElement = document.createElement("ol");
+ this.propertiesElement.className = "properties";
+ this.propertiesTreeOutline = new TreeOutline(this.propertiesElement);
+ this.propertiesTreeOutline.section = this;
+
+ this.element.appendChild(this.headerElement);
+ this.element.appendChild(this.propertiesElement);
+
+ this.title = title;
+ this.subtitle = subtitle;
+ this._expanded = false;
+}
+
+WebInspector.PropertiesSection.prototype = {
+ get title()
+ {
+ return this._title;
+ },
+
+ set title(x)
+ {
+ if (this._title === x)
+ return;
+ this._title = x;
+
+ if (x instanceof Node) {
+ this.titleElement.removeChildren();
+ this.titleElement.appendChild(x);
+ } else
+ this.titleElement.textContent = x;
+ },
+
+ get subtitle()
+ {
+ return this._subtitle;
+ },
+
+ set subtitle(x)
+ {
+ if (this._subtitle === x)
+ return;
+ this._subtitle = x;
+ this.subtitleElement.innerHTML = x;
+ },
+
+ get expanded()
+ {
+ return this._expanded;
+ },
+
+ set expanded(x)
+ {
+ if (x)
+ this.expand();
+ else
+ this.collapse();
+ },
+
+ get populated()
+ {
+ return this._populated;
+ },
+
+ set populated(x)
+ {
+ this._populated = x;
+ if (!x && this.onpopulate && this._expanded) {
+ this.onpopulate(this);
+ this._populated = true;
+ }
+ },
+
+ expand: function()
+ {
+ if (this._expanded)
+ return;
+ this._expanded = true;
+ this.element.addStyleClass("expanded");
+
+ if (!this._populated && this.onpopulate) {
+ this.onpopulate(this);
+ this._populated = true;
+ }
+ },
+
+ collapse: function()
+ {
+ if (!this._expanded)
+ return;
+ this._expanded = false;
+ this.element.removeStyleClass("expanded");
+ },
+
+ toggleExpanded: function()
+ {
+ this.expanded = !this.expanded;
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/PropertiesSidebarPane.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/PropertiesSidebarPane.js
new file mode 100644
index 0000000..70db805
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/PropertiesSidebarPane.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.PropertiesSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Properties"));
+}
+
+WebInspector.PropertiesSidebarPane.prototype = {
+ update: function(object)
+ {
+ var body = this.bodyElement;
+
+ body.removeChildren();
+
+ this.sections = [];
+
+ if (!object)
+ return;
+
+ for (var prototype = object; prototype; prototype = prototype.__proto__) {
+ var section = new WebInspector.ObjectPropertiesSection(prototype);
+ this.sections.push(section);
+ body.appendChild(section.element);
+ }
+ }
+}
+
+WebInspector.PropertiesSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Resource.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Resource.js
new file mode 100644
index 0000000..058f232
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Resource.js
@@ -0,0 +1,625 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Resource = function(requestHeaders, url, domain, path, lastPathComponent, identifier, mainResource, cached)
+{
+ this.identifier = identifier;
+
+ this.startTime = -1;
+ this.endTime = -1;
+ this.mainResource = mainResource;
+ this.requestHeaders = requestHeaders;
+ this.url = url;
+ this.domain = domain;
+ this.path = path;
+ this.lastPathComponent = lastPathComponent;
+ this.cached = cached;
+
+ this.category = WebInspector.resourceCategories.other;
+}
+
+// Keep these in sync with WebCore::InspectorResource::Type
+WebInspector.Resource.Type = {
+ Document: 0,
+ Stylesheet: 1,
+ Image: 2,
+ Font: 3,
+ Script: 4,
+ XHR: 5,
+ Other: 6,
+
+ isTextType: function(type)
+ {
+ return (type === this.Document) || (type === this.Stylesheet) || (type === this.Script) || (type === this.XHR);
+ },
+
+ toString: function(type)
+ {
+ switch (type) {
+ case this.Document:
+ return WebInspector.UIString("document");
+ case this.Stylesheet:
+ return WebInspector.UIString("stylesheet");
+ case this.Image:
+ return WebInspector.UIString("image");
+ case this.Font:
+ return WebInspector.UIString("font");
+ case this.Script:
+ return WebInspector.UIString("script");
+ case this.XHR:
+ return WebInspector.UIString("XHR");
+ case this.Other:
+ default:
+ return WebInspector.UIString("other");
+ }
+ }
+}
+
+WebInspector.Resource.prototype = {
+ get url()
+ {
+ return this._url;
+ },
+
+ set url(x)
+ {
+ if (this._url === x)
+ return;
+
+ var oldURL = this._url;
+ this._url = x;
+
+ // FIXME: We should make the WebInspector object listen for the "url changed" event.
+ // Then resourceURLChanged can be removed.
+ WebInspector.resourceURLChanged(this, oldURL);
+
+ this.dispatchEventToListeners("url changed");
+ },
+
+ get domain()
+ {
+ return this._domain;
+ },
+
+ set domain(x)
+ {
+ if (this._domain === x)
+ return;
+ this._domain = x;
+ },
+
+ get lastPathComponent()
+ {
+ return this._lastPathComponent;
+ },
+
+ set lastPathComponent(x)
+ {
+ if (this._lastPathComponent === x)
+ return;
+ this._lastPathComponent = x;
+ this._lastPathComponentLowerCase = x ? x.toLowerCase() : null;
+ },
+
+ get displayName()
+ {
+ var title = this.lastPathComponent;
+ if (!title)
+ title = this.displayDomain;
+ if (!title && this.url)
+ title = this.url.trimURL(WebInspector.mainResource ? WebInspector.mainResource.domain : "");
+ if (title === "/")
+ title = this.url;
+ return title;
+ },
+
+ get displayDomain()
+ {
+ // WebInspector.Database calls this, so don't access more than this.domain.
+ if (this.domain && (!WebInspector.mainResource || (WebInspector.mainResource && this.domain !== WebInspector.mainResource.domain)))
+ return this.domain;
+ return "";
+ },
+
+ get startTime()
+ {
+ return this._startTime || -1;
+ },
+
+ set startTime(x)
+ {
+ if (this._startTime === x)
+ return;
+
+ this._startTime = x;
+
+ if (WebInspector.panels.resources)
+ WebInspector.panels.resources.refreshResource(this);
+ },
+
+ get responseReceivedTime()
+ {
+ return this._responseReceivedTime || -1;
+ },
+
+ set responseReceivedTime(x)
+ {
+ if (this._responseReceivedTime === x)
+ return;
+
+ this._responseReceivedTime = x;
+
+ if (WebInspector.panels.resources)
+ WebInspector.panels.resources.refreshResource(this);
+ },
+
+ get endTime()
+ {
+ return this._endTime || -1;
+ },
+
+ set endTime(x)
+ {
+ if (this._endTime === x)
+ return;
+
+ this._endTime = x;
+
+ if (WebInspector.panels.resources)
+ WebInspector.panels.resources.refreshResource(this);
+ },
+
+ get duration()
+ {
+ if (this._endTime === -1 || this._startTime === -1)
+ return -1;
+ return this._endTime - this._startTime;
+ },
+
+ get latency()
+ {
+ if (this._responseReceivedTime === -1 || this._startTime === -1)
+ return -1;
+ return this._responseReceivedTime - this._startTime;
+ },
+
+ get contentLength()
+ {
+ return this._contentLength || 0;
+ },
+
+ set contentLength(x)
+ {
+ if (this._contentLength === x)
+ return;
+
+ this._contentLength = x;
+
+ if (WebInspector.panels.resources)
+ WebInspector.panels.resources.refreshResource(this);
+ },
+
+ get expectedContentLength()
+ {
+ return this._expectedContentLength || 0;
+ },
+
+ set expectedContentLength(x)
+ {
+ if (this._expectedContentLength === x)
+ return;
+ this._expectedContentLength = x;
+ },
+
+ get finished()
+ {
+ return this._finished;
+ },
+
+ set finished(x)
+ {
+ if (this._finished === x)
+ return;
+
+ this._finished = x;
+
+ if (x) {
+ this._checkTips();
+ this._checkWarnings();
+ this.dispatchEventToListeners("finished");
+ }
+ },
+
+ get failed()
+ {
+ return this._failed;
+ },
+
+ set failed(x)
+ {
+ this._failed = x;
+ },
+
+ get category()
+ {
+ return this._category;
+ },
+
+ set category(x)
+ {
+ if (this._category === x)
+ return;
+
+ var oldCategory = this._category;
+ if (oldCategory)
+ oldCategory.removeResource(this);
+
+ this._category = x;
+
+ if (this._category)
+ this._category.addResource(this);
+
+ if (WebInspector.panels.resources) {
+ WebInspector.panels.resources.refreshResource(this);
+ WebInspector.panels.resources.recreateViewForResourceIfNeeded(this);
+ }
+ },
+
+ get mimeType()
+ {
+ return this._mimeType;
+ },
+
+ set mimeType(x)
+ {
+ if (this._mimeType === x)
+ return;
+
+ this._mimeType = x;
+ },
+
+ get type()
+ {
+ return this._type;
+ },
+
+ set type(x)
+ {
+ if (this._type === x)
+ return;
+
+ this._type = x;
+
+ switch (x) {
+ case WebInspector.Resource.Type.Document:
+ this.category = WebInspector.resourceCategories.documents;
+ break;
+ case WebInspector.Resource.Type.Stylesheet:
+ this.category = WebInspector.resourceCategories.stylesheets;
+ break;
+ case WebInspector.Resource.Type.Script:
+ this.category = WebInspector.resourceCategories.scripts;
+ break;
+ case WebInspector.Resource.Type.Image:
+ this.category = WebInspector.resourceCategories.images;
+ break;
+ case WebInspector.Resource.Type.Font:
+ this.category = WebInspector.resourceCategories.fonts;
+ break;
+ case WebInspector.Resource.Type.XHR:
+ this.category = WebInspector.resourceCategories.xhr;
+ break;
+ case WebInspector.Resource.Type.Other:
+ default:
+ this.category = WebInspector.resourceCategories.other;
+ break;
+ }
+ },
+
+ get documentNode() {
+ if ("identifier" in this)
+ return InspectorController.getResourceDocumentNode(this.identifier);
+ return null;
+ },
+
+ get requestHeaders()
+ {
+ if (this._requestHeaders === undefined)
+ this._requestHeaders = {};
+ return this._requestHeaders;
+ },
+
+ set requestHeaders(x)
+ {
+ if (this._requestHeaders === x)
+ return;
+
+ this._requestHeaders = x;
+ delete this._sortedRequestHeaders;
+
+ this.dispatchEventToListeners("requestHeaders changed");
+ },
+
+ get sortedRequestHeaders()
+ {
+ if (this._sortedRequestHeaders !== undefined)
+ return this._sortedRequestHeaders;
+
+ this._sortedRequestHeaders = [];
+ for (var key in this.requestHeaders)
+ this._sortedRequestHeaders.push({header: key, value: this.requestHeaders[key]});
+ this._sortedRequestHeaders.sort(function(a,b) { return a.header.localeCompare(b.header) });
+
+ return this._sortedRequestHeaders;
+ },
+
+ get responseHeaders()
+ {
+ if (this._responseHeaders === undefined)
+ this._responseHeaders = {};
+ return this._responseHeaders;
+ },
+
+ set responseHeaders(x)
+ {
+ if (this._responseHeaders === x)
+ return;
+
+ this._responseHeaders = x;
+ delete this._sortedResponseHeaders;
+
+ this.dispatchEventToListeners("responseHeaders changed");
+ },
+
+ get sortedResponseHeaders()
+ {
+ if (this._sortedResponseHeaders !== undefined)
+ return this._sortedResponseHeaders;
+
+ this._sortedResponseHeaders = [];
+ for (var key in this.responseHeaders)
+ this._sortedResponseHeaders.push({header: key, value: this.responseHeaders[key]});
+ this._sortedResponseHeaders.sort(function(a,b) { return a.header.localeCompare(b.header) });
+
+ return this._sortedResponseHeaders;
+ },
+
+ get scripts()
+ {
+ if (!("_scripts" in this))
+ this._scripts = [];
+ return this._scripts;
+ },
+
+ addScript: function(script)
+ {
+ if (!script)
+ return;
+ this.scripts.unshift(script);
+ script.resource = this;
+ },
+
+ removeAllScripts: function()
+ {
+ if (!this._scripts)
+ return;
+
+ for (var i = 0; i < this._scripts.length; ++i) {
+ if (this._scripts[i].resource === this)
+ delete this._scripts[i].resource;
+ }
+
+ delete this._scripts;
+ },
+
+ removeScript: function(script)
+ {
+ if (!script)
+ return;
+
+ if (script.resource === this)
+ delete script.resource;
+
+ if (!this._scripts)
+ return;
+
+ this._scripts.remove(script);
+ },
+
+ get errors()
+ {
+ return this._errors || 0;
+ },
+
+ set errors(x)
+ {
+ this._errors = x;
+ },
+
+ get warnings()
+ {
+ return this._warnings || 0;
+ },
+
+ set warnings(x)
+ {
+ this._warnings = x;
+ },
+
+ get tips()
+ {
+ if (!("_tips" in this))
+ this._tips = {};
+ return this._tips;
+ },
+
+ _addTip: function(tip)
+ {
+ if (tip.id in this.tips)
+ return;
+
+ this.tips[tip.id] = tip;
+
+ // FIXME: Re-enable this code once we have a scope bar in the Console.
+ // Otherwise, we flood the Console with too many tips.
+ /*
+ var msg = new WebInspector.ConsoleMessage(WebInspector.ConsoleMessage.MessageSource.Other,
+ WebInspector.ConsoleMessage.MessageLevel.Tip, -1, this.url, null, 1, tip.message);
+ WebInspector.console.addMessage(msg);
+ */
+ },
+
+ _checkTips: function()
+ {
+ for (var tip in WebInspector.Tips)
+ this._checkTip(WebInspector.Tips[tip]);
+ },
+
+ _checkTip: function(tip)
+ {
+ var addTip = false;
+ switch (tip.id) {
+ case WebInspector.Tips.ResourceNotCompressed.id:
+ addTip = this._shouldCompress();
+ break;
+ }
+
+ if (addTip)
+ this._addTip(tip);
+ },
+
+ _shouldCompress: function()
+ {
+ return WebInspector.Resource.Type.isTextType(this.type)
+ && this.domain
+ && !("Content-Encoding" in this.responseHeaders)
+ && this.contentLength !== undefined
+ && this.contentLength >= 512;
+ },
+
+ _mimeTypeIsConsistentWithType: function()
+ {
+ if (typeof this.type === "undefined"
+ || this.type === WebInspector.Resource.Type.Other
+ || this.type === WebInspector.Resource.Type.XHR)
+ return true;
+
+ if (this.mimeType in WebInspector.MIMETypes)
+ return this.type in WebInspector.MIMETypes[this.mimeType];
+
+ return true;
+ },
+
+ _checkWarnings: function()
+ {
+ for (var warning in WebInspector.Warnings)
+ this._checkWarning(WebInspector.Warnings[warning]);
+ },
+
+ _checkWarning: function(warning)
+ {
+ var addWarning = false;
+ var msg;
+ switch (warning.id) {
+ case WebInspector.Warnings.IncorrectMIMEType.id:
+ if (!this._mimeTypeIsConsistentWithType())
+ msg = new WebInspector.ConsoleMessage(WebInspector.ConsoleMessage.MessageSource.Other,
+ WebInspector.ConsoleMessage.MessageLevel.Warning, -1, this.url, null, 1,
+ String.sprintf(WebInspector.Warnings.IncorrectMIMEType.message,
+ WebInspector.Resource.Type.toString(this.type), this.mimeType));
+ break;
+ }
+
+ if (msg)
+ WebInspector.console.addMessage(msg);
+ }
+}
+
+WebInspector.Resource.prototype.__proto__ = WebInspector.Object.prototype;
+
+WebInspector.Resource.CompareByStartTime = function(a, b)
+{
+ if (a.startTime < b.startTime)
+ return -1;
+ if (a.startTime > b.startTime)
+ return 1;
+ return 0;
+}
+
+WebInspector.Resource.CompareByResponseReceivedTime = function(a, b)
+{
+ if (a.responseReceivedTime === -1 && b.responseReceivedTime !== -1)
+ return 1;
+ if (a.responseReceivedTime !== -1 && b.responseReceivedTime === -1)
+ return -1;
+ if (a.responseReceivedTime < b.responseReceivedTime)
+ return -1;
+ if (a.responseReceivedTime > b.responseReceivedTime)
+ return 1;
+ return 0;
+}
+
+WebInspector.Resource.CompareByEndTime = function(a, b)
+{
+ if (a.endTime === -1 && b.endTime !== -1)
+ return 1;
+ if (a.endTime !== -1 && b.endTime === -1)
+ return -1;
+ if (a.endTime < b.endTime)
+ return -1;
+ if (a.endTime > b.endTime)
+ return 1;
+ return 0;
+}
+
+WebInspector.Resource.CompareByDuration = function(a, b)
+{
+ if (a.duration < b.duration)
+ return -1;
+ if (a.duration > b.duration)
+ return 1;
+ return 0;
+}
+
+WebInspector.Resource.CompareByLatency = function(a, b)
+{
+ if (a.latency < b.latency)
+ return -1;
+ if (a.latency > b.latency)
+ return 1;
+ return 0;
+}
+
+WebInspector.Resource.CompareBySize = function(a, b)
+{
+ if (a.contentLength < b.contentLength)
+ return -1;
+ if (a.contentLength > b.contentLength)
+ return 1;
+ return 0;
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ResourceCategory.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ResourceCategory.js
new file mode 100644
index 0000000..fc508d0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ResourceCategory.js
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ResourceCategory = function(title, name)
+{
+ this.name = name;
+ this.title = title;
+ this.resources = [];
+}
+
+WebInspector.ResourceCategory.prototype = {
+ toString: function()
+ {
+ return this.title;
+ },
+
+ addResource: function(resource)
+ {
+ var a = resource;
+ var resourcesLength = this.resources.length;
+ for (var i = 0; i < resourcesLength; ++i) {
+ var b = this.resources[i];
+ if (a._lastPathComponentLowerCase && b._lastPathComponentLowerCase)
+ if (a._lastPathComponentLowerCase < b._lastPathComponentLowerCase)
+ break;
+ else if (a.name && b.name)
+ if (a.name < b.name)
+ break;
+ }
+
+ this.resources.splice(i, 0, resource);
+ },
+
+ removeResource: function(resource)
+ {
+ this.resources.remove(resource, true);
+ },
+
+ removeAllResources: function(resource)
+ {
+ this.resources = [];
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ResourceView.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ResourceView.js
new file mode 100644
index 0000000..b480362
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ResourceView.js
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ResourceView = function(resource)
+{
+ WebInspector.View.call(this);
+
+ this.element.addStyleClass("resource-view");
+
+ this.resource = resource;
+
+ this.headersElement = document.createElement("div");
+ this.headersElement.className = "resource-view-headers";
+ this.element.appendChild(this.headersElement);
+
+ this.contentElement = document.createElement("div");
+ this.contentElement.className = "resource-view-content";
+ this.element.appendChild(this.contentElement);
+
+ this.headersListElement = document.createElement("ol");
+ this.headersListElement.className = "outline-disclosure";
+ this.headersElement.appendChild(this.headersListElement);
+
+ this.headersTreeOutline = new TreeOutline(this.headersListElement);
+ this.headersTreeOutline.expandTreeElementsWhenArrowing = true;
+
+ this.urlTreeElement = new TreeElement("", null, false);
+ this.urlTreeElement.selectable = false;
+ this.headersTreeOutline.appendChild(this.urlTreeElement);
+
+ this.requestHeadersTreeElement = new TreeElement("", null, true);
+ this.requestHeadersTreeElement.expanded = false;
+ this.requestHeadersTreeElement.selectable = false;
+ this.headersTreeOutline.appendChild(this.requestHeadersTreeElement);
+
+ this.responseHeadersTreeElement = new TreeElement("", null, true);
+ this.responseHeadersTreeElement.expanded = false;
+ this.responseHeadersTreeElement.selectable = false;
+ this.headersTreeOutline.appendChild(this.responseHeadersTreeElement);
+
+ this.headersVisible = true;
+
+ resource.addEventListener("url changed", this._refreshURL, this);
+ resource.addEventListener("requestHeaders changed", this._refreshRequestHeaders, this);
+ resource.addEventListener("responseHeaders changed", this._refreshResponseHeaders, this);
+
+ this._refreshURL();
+ this._refreshRequestHeaders();
+ this._refreshResponseHeaders();
+}
+
+WebInspector.ResourceView.prototype = {
+ get headersVisible()
+ {
+ return this._headersVisible;
+ },
+
+ set headersVisible(x)
+ {
+ if (x === this._headersVisible)
+ return;
+
+ this._headersVisible = x;
+
+ if (x)
+ this.element.addStyleClass("headers-visible");
+ else
+ this.element.removeStyleClass("headers-visible");
+ },
+
+ attach: function()
+ {
+ if (!this.element.parentNode) {
+ var parentElement = (document.getElementById("resource-views") || document.getElementById("script-resource-views"));
+ if (parentElement)
+ parentElement.appendChild(this.element);
+ }
+ },
+
+ _refreshURL: function()
+ {
+ this.urlTreeElement.title = this.resource.url.escapeHTML();
+ },
+
+ _refreshRequestHeaders: function()
+ {
+ this._refreshHeaders(WebInspector.UIString("Request Headers"), this.resource.sortedRequestHeaders, this.requestHeadersTreeElement);
+ },
+
+ _refreshResponseHeaders: function()
+ {
+ this._refreshHeaders(WebInspector.UIString("Response Headers"), this.resource.sortedResponseHeaders, this.responseHeadersTreeElement);
+ },
+
+ _refreshHeaders: function(title, headers, headersTreeElement)
+ {
+ headersTreeElement.removeChildren();
+
+ var length = headers.length;
+ headersTreeElement.title = title.escapeHTML() + "<span class=\"header-count\">" + WebInspector.UIString(" (%d)", length) + "</span>";
+ headersTreeElement.hidden = !length;
+
+ var length = headers.length;
+ for (var i = 0; i < length; ++i) {
+ var title = "<div class=\"header-name\">" + headers[i].header.escapeHTML() + ":</div>";
+ title += "<div class=\"header-value\">" + headers[i].value.escapeHTML() + "</div>"
+
+ var headerTreeElement = new TreeElement(title, null, false);
+ headerTreeElement.selectable = false;
+ headersTreeElement.appendChild(headerTreeElement);
+ }
+ }
+}
+
+WebInspector.ResourceView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ResourcesPanel.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ResourcesPanel.js
new file mode 100644
index 0000000..04d998e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ResourcesPanel.js
@@ -0,0 +1,1706 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Anthony Ricaud (rik24d@gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ResourcesPanel = function()
+{
+ WebInspector.Panel.call(this);
+
+ this.element.addStyleClass("resources");
+
+ this.viewsContainerElement = document.createElement("div");
+ this.viewsContainerElement.id = "resource-views";
+ this.element.appendChild(this.viewsContainerElement);
+
+ this.containerElement = document.createElement("div");
+ this.containerElement.id = "resources-container";
+ this.containerElement.addEventListener("scroll", this._updateDividersLabelBarPosition.bind(this), false);
+ this.element.appendChild(this.containerElement);
+
+ this.sidebarElement = document.createElement("div");
+ this.sidebarElement.id = "resources-sidebar";
+ this.sidebarElement.className = "sidebar";
+ this.containerElement.appendChild(this.sidebarElement);
+
+ this.sidebarResizeElement = document.createElement("div");
+ this.sidebarResizeElement.className = "sidebar-resizer-vertical";
+ this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarDragging.bind(this), false);
+ this.element.appendChild(this.sidebarResizeElement);
+
+ this.containerContentElement = document.createElement("div");
+ this.containerContentElement.id = "resources-container-content";
+ this.containerElement.appendChild(this.containerContentElement);
+
+ this.summaryElement = document.createElement("div");
+ this.summaryElement.id = "resources-summary";
+ this.containerContentElement.appendChild(this.summaryElement);
+
+ this.resourcesGraphsElement = document.createElement("div");
+ this.resourcesGraphsElement.id = "resources-graphs";
+ this.containerContentElement.appendChild(this.resourcesGraphsElement);
+
+ this.dividersElement = document.createElement("div");
+ this.dividersElement.id = "resources-dividers";
+ this.containerContentElement.appendChild(this.dividersElement);
+
+ this.dividersLabelBarElement = document.createElement("div");
+ this.dividersLabelBarElement.id = "resources-dividers-label-bar";
+ this.containerContentElement.appendChild(this.dividersLabelBarElement);
+
+ this.summaryGraphElement = document.createElement("canvas");
+ this.summaryGraphElement.setAttribute("width", "450");
+ this.summaryGraphElement.setAttribute("height", "38");
+ this.summaryGraphElement.id = "resources-summary-graph";
+ this.summaryElement.appendChild(this.summaryGraphElement);
+
+ this.legendElement = document.createElement("div");
+ this.legendElement.id = "resources-graph-legend";
+ this.summaryElement.appendChild(this.legendElement);
+
+ this.sidebarTreeElement = document.createElement("ol");
+ this.sidebarTreeElement.className = "sidebar-tree";
+ this.sidebarElement.appendChild(this.sidebarTreeElement);
+
+ this.sidebarTree = new TreeOutline(this.sidebarTreeElement);
+
+ var timeGraphItem = new WebInspector.SidebarTreeElement("resources-time-graph-sidebar-item", WebInspector.UIString("Time"));
+ timeGraphItem.onselect = this._graphSelected.bind(this);
+
+ var transferTimeCalculator = new WebInspector.ResourceTransferTimeCalculator();
+ var transferDurationCalculator = new WebInspector.ResourceTransferDurationCalculator();
+
+ timeGraphItem.sortingOptions = [
+ { name: WebInspector.UIString("Sort by Start Time"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByAscendingStartTime, calculator: transferTimeCalculator },
+ { name: WebInspector.UIString("Sort by Response Time"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByAscendingResponseReceivedTime, calculator: transferTimeCalculator },
+ { name: WebInspector.UIString("Sort by End Time"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByAscendingEndTime, calculator: transferTimeCalculator },
+ { name: WebInspector.UIString("Sort by Duration"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByDescendingDuration, calculator: transferDurationCalculator },
+ { name: WebInspector.UIString("Sort by Latency"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByDescendingLatency, calculator: transferDurationCalculator },
+ ];
+
+ timeGraphItem.selectedSortingOptionIndex = 1;
+
+ var sizeGraphItem = new WebInspector.SidebarTreeElement("resources-size-graph-sidebar-item", WebInspector.UIString("Size"));
+ sizeGraphItem.onselect = this._graphSelected.bind(this);
+
+ var transferSizeCalculator = new WebInspector.ResourceTransferSizeCalculator();
+ sizeGraphItem.sortingOptions = [
+ { name: WebInspector.UIString("Sort by Size"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByDescendingSize, calculator: transferSizeCalculator },
+ ];
+
+ sizeGraphItem.selectedSortingOptionIndex = 0;
+
+ this.graphsTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("GRAPHS"), {}, true);
+ this.sidebarTree.appendChild(this.graphsTreeElement);
+
+ this.graphsTreeElement.appendChild(timeGraphItem);
+ this.graphsTreeElement.appendChild(sizeGraphItem);
+ this.graphsTreeElement.expand();
+
+ this.resourcesTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("RESOURCES"), {}, true);
+ this.sidebarTree.appendChild(this.resourcesTreeElement);
+
+ this.resourcesTreeElement.expand();
+
+ var panelEnablerHeading = WebInspector.UIString("You need to enable resource tracking to use the this panel.");
+ var panelEnablerDisclaimer = WebInspector.UIString("Enabling resource tracking will reload the page and make page loading slower.");
+ var panelEnablerButton = WebInspector.UIString("Enable resource tracking");
+
+ this.panelEnablerView = new WebInspector.PanelEnablerView("resources", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
+ this.panelEnablerView.addEventListener("enable clicked", this._enableResourceTracking, this);
+
+ this.element.appendChild(this.panelEnablerView.element);
+
+ this.enableToggleButton = document.createElement("button");
+ this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item";
+ this.enableToggleButton.addEventListener("click", this._toggleResourceTracking.bind(this), false);
+
+ this.largerResourcesButton = document.createElement("button");
+ this.largerResourcesButton.id = "resources-larger-resources-status-bar-item";
+ this.largerResourcesButton.className = "status-bar-item toggled-on";
+ this.largerResourcesButton.title = WebInspector.UIString("Use small resource rows.");
+ this.largerResourcesButton.addEventListener("click", this._toggleLargerResources.bind(this), false);
+
+ this.sortingSelectElement = document.createElement("select");
+ this.sortingSelectElement.className = "status-bar-item";
+ this.sortingSelectElement.addEventListener("change", this._changeSortingFunction.bind(this), false);
+
+ this.reset();
+
+ timeGraphItem.select();
+}
+
+WebInspector.ResourcesPanel.prototype = {
+ toolbarItemClass: "resources",
+
+ get toolbarItemLabel()
+ {
+ return WebInspector.UIString("Resources");
+ },
+
+ get statusBarItems()
+ {
+ return [this.enableToggleButton, this.largerResourcesButton, this.sortingSelectElement];
+ },
+
+ show: function()
+ {
+ WebInspector.Panel.prototype.show.call(this);
+
+ this._updateDividersLabelBarPosition();
+ this._updateSidebarWidth();
+ this.refreshIfNeeded();
+
+ var visibleView = this.visibleView;
+ if (visibleView) {
+ visibleView.headersVisible = true;
+ visibleView.show(this.viewsContainerElement);
+ }
+
+ // Hide any views that are visible that are not this panel's current visible view.
+ // This can happen when a ResourceView is visible in the Scripts panel then switched
+ // to the this panel.
+ var resourcesLength = this._resources.length;
+ for (var i = 0; i < resourcesLength; ++i) {
+ var resource = this._resources[i];
+ var view = resource._resourcesView;
+ if (!view || view === visibleView)
+ continue;
+ view.visible = false;
+ }
+ },
+
+ resize: function()
+ {
+ this._updateGraphDividersIfNeeded();
+
+ var visibleView = this.visibleView;
+ if (visibleView && "resize" in visibleView)
+ visibleView.resize();
+ },
+
+ get searchableViews()
+ {
+ var views = [];
+
+ const visibleView = this.visibleView;
+ if (visibleView && visibleView.performSearch)
+ views.push(visibleView);
+
+ var resourcesLength = this._resources.length;
+ for (var i = 0; i < resourcesLength; ++i) {
+ var resource = this._resources[i];
+ if (!resource._resourcesTreeElement)
+ continue;
+ var resourceView = this.resourceViewForResource(resource);
+ if (!resourceView.performSearch || resourceView === visibleView)
+ continue;
+ views.push(resourceView);
+ }
+
+ return views;
+ },
+
+ get searchResultsSortFunction()
+ {
+ const resourceTreeElementSortFunction = this.sortingFunction;
+
+ function sortFuction(a, b)
+ {
+ return resourceTreeElementSortFunction(a.resource._resourcesTreeElement, b.resource._resourcesTreeElement);
+ }
+
+ return sortFuction;
+ },
+
+ searchMatchFound: function(view, matches)
+ {
+ view.resource._resourcesTreeElement.searchMatches = matches;
+ },
+
+ searchCanceled: function(startingNewSearch)
+ {
+ WebInspector.Panel.prototype.searchCanceled.call(this, startingNewSearch);
+
+ if (startingNewSearch || !this._resources)
+ return;
+
+ for (var i = 0; i < this._resources.length; ++i) {
+ var resource = this._resources[i];
+ if (resource._resourcesTreeElement)
+ resource._resourcesTreeElement.updateErrorsAndWarnings();
+ }
+ },
+
+ performSearch: function(query)
+ {
+ for (var i = 0; i < this._resources.length; ++i) {
+ var resource = this._resources[i];
+ if (resource._resourcesTreeElement)
+ resource._resourcesTreeElement.resetBubble();
+ }
+
+ WebInspector.Panel.prototype.performSearch.call(this, query);
+ },
+
+ get visibleView()
+ {
+ if (this.visibleResource)
+ return this.visibleResource._resourcesView;
+ return null;
+ },
+
+ get calculator()
+ {
+ return this._calculator;
+ },
+
+ set calculator(x)
+ {
+ if (!x || this._calculator === x)
+ return;
+
+ this._calculator = x;
+ this._calculator.reset();
+
+ this._staleResources = this._resources;
+ this.refresh();
+ },
+
+ get sortingFunction()
+ {
+ return this._sortingFunction;
+ },
+
+ set sortingFunction(x)
+ {
+ this._sortingFunction = x;
+ this._sortResourcesIfNeeded();
+ },
+
+ get needsRefresh()
+ {
+ return this._needsRefresh;
+ },
+
+ set needsRefresh(x)
+ {
+ if (this._needsRefresh === x)
+ return;
+
+ this._needsRefresh = x;
+
+ if (x) {
+ if (this.visible && !("_refreshTimeout" in this))
+ this._refreshTimeout = setTimeout(this.refresh.bind(this), 500);
+ } else {
+ if ("_refreshTimeout" in this) {
+ clearTimeout(this._refreshTimeout);
+ delete this._refreshTimeout;
+ }
+ }
+ },
+
+ refreshIfNeeded: function()
+ {
+ if (this.needsRefresh)
+ this.refresh();
+ },
+
+ refresh: function()
+ {
+ this.needsRefresh = false;
+
+ var staleResourcesLength = this._staleResources.length;
+ var boundariesChanged = false;
+
+ for (var i = 0; i < staleResourcesLength; ++i) {
+ var resource = this._staleResources[i];
+ if (!resource._resourcesTreeElement) {
+ // Create the resource tree element and graph.
+ resource._resourcesTreeElement = new WebInspector.ResourceSidebarTreeElement(resource);
+ resource._resourcesTreeElement._resourceGraph = new WebInspector.ResourceGraph(resource);
+
+ this.resourcesTreeElement.appendChild(resource._resourcesTreeElement);
+ this.resourcesGraphsElement.appendChild(resource._resourcesTreeElement._resourceGraph.graphElement);
+ }
+
+ resource._resourcesTreeElement.refresh();
+
+ if (this.calculator.updateBoundaries(resource))
+ boundariesChanged = true;
+ }
+
+ if (boundariesChanged) {
+ // The boundaries changed, so all resource graphs are stale.
+ this._staleResources = this._resources;
+ staleResourcesLength = this._staleResources.length;
+ }
+
+ for (var i = 0; i < staleResourcesLength; ++i)
+ this._staleResources[i]._resourcesTreeElement._resourceGraph.refresh(this.calculator);
+
+ this._staleResources = [];
+
+ this._updateGraphDividersIfNeeded();
+ this._sortResourcesIfNeeded();
+ this._updateSummaryGraph();
+ },
+
+ resourceTrackingWasEnabled: function()
+ {
+ this.reset();
+ },
+
+ resourceTrackingWasDisabled: function()
+ {
+ this.reset();
+ },
+
+ reset: function()
+ {
+ this.closeVisibleResource();
+
+ this.containerElement.scrollTop = 0;
+
+ delete this.currentQuery;
+ this.searchCanceled();
+
+ if (this._calculator)
+ this._calculator.reset();
+
+ if (this._resources) {
+ var resourcesLength = this._resources.length;
+ for (var i = 0; i < resourcesLength; ++i) {
+ var resource = this._resources[i];
+
+ resource.warnings = 0;
+ resource.errors = 0;
+
+ delete resource._resourcesTreeElement;
+ delete resource._resourcesView;
+ }
+ }
+
+ this._resources = [];
+ this._staleResources = [];
+
+ this.resourcesTreeElement.removeChildren();
+ this.viewsContainerElement.removeChildren();
+ this.resourcesGraphsElement.removeChildren();
+ this.legendElement.removeChildren();
+
+ this._updateGraphDividersIfNeeded(true);
+
+ this._drawSummaryGraph(); // draws an empty graph
+
+ if (InspectorController.resourceTrackingEnabled()) {
+ this.enableToggleButton.title = WebInspector.UIString("Resource tracking enabled. Click to disable.");
+ this.enableToggleButton.addStyleClass("toggled-on");
+ this.largerResourcesButton.removeStyleClass("hidden");
+ this.sortingSelectElement.removeStyleClass("hidden");
+ this.panelEnablerView.visible = false;
+ } else {
+ this.enableToggleButton.title = WebInspector.UIString("Resource tracking disabled. Click to enable.");
+ this.enableToggleButton.removeStyleClass("toggled-on");
+ this.largerResourcesButton.addStyleClass("hidden");
+ this.sortingSelectElement.addStyleClass("hidden");
+ this.panelEnablerView.visible = true;
+ }
+ },
+
+ addResource: function(resource)
+ {
+ this._resources.push(resource);
+ this.refreshResource(resource);
+ },
+
+ removeResource: function(resource)
+ {
+ if (this.visibleView === resource._resourcesView)
+ this.closeVisibleResource();
+
+ this._resources.remove(resource, true);
+
+ if (resource._resourcesTreeElement) {
+ this.resourcesTreeElement.removeChild(resource._resourcesTreeElement);
+ this.resourcesGraphsElement.removeChild(resource._resourcesTreeElement._resourceGraph.graphElement);
+ }
+
+ resource.warnings = 0;
+ resource.errors = 0;
+
+ delete resource._resourcesTreeElement;
+ delete resource._resourcesView;
+
+ this._adjustScrollPosition();
+ },
+
+ addMessageToResource: function(resource, msg)
+ {
+ if (!resource)
+ return;
+
+ switch (msg.level) {
+ case WebInspector.ConsoleMessage.MessageLevel.Warning:
+ resource.warnings += msg.repeatDelta;
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Error:
+ resource.errors += msg.repeatDelta;
+ break;
+ }
+
+ if (!this.currentQuery && resource._resourcesTreeElement)
+ resource._resourcesTreeElement.updateErrorsAndWarnings();
+
+ var view = this.resourceViewForResource(resource);
+ if (view.addMessage)
+ view.addMessage(msg);
+ },
+
+ clearMessages: function()
+ {
+ var resourcesLength = this._resources.length;
+ for (var i = 0; i < resourcesLength; ++i) {
+ var resource = this._resources[i];
+ resource.warnings = 0;
+ resource.errors = 0;
+
+ if (!this.currentQuery && resource._resourcesTreeElement)
+ resource._resourcesTreeElement.updateErrorsAndWarnings();
+
+ var view = resource._resourcesView;
+ if (!view || !view.clearMessages)
+ continue;
+ view.clearMessages();
+ }
+ },
+
+ refreshResource: function(resource)
+ {
+ this._staleResources.push(resource);
+ this.needsRefresh = true;
+ },
+
+ recreateViewForResourceIfNeeded: function(resource)
+ {
+ if (!resource || !resource._resourcesView)
+ return;
+
+ var newView = this._createResourceView(resource);
+ if (newView.prototype === resource._resourcesView.prototype)
+ return;
+
+ resource.warnings = 0;
+ resource.errors = 0;
+
+ if (!this.currentQuery && resource._resourcesTreeElement)
+ resource._resourcesTreeElement.updateErrorsAndWarnings();
+
+ var oldView = resource._resourcesView;
+
+ resource._resourcesView.detach();
+ delete resource._resourcesView;
+
+ resource._resourcesView = newView;
+
+ newView.headersVisible = oldView.headersVisible;
+
+ if (oldView.visible && oldView.element.parentNode)
+ newView.show(oldView.element.parentNode);
+ },
+
+ showResource: function(resource, line)
+ {
+ if (!resource)
+ return;
+
+ this.containerElement.addStyleClass("viewing-resource");
+
+ if (this.visibleResource && this.visibleResource._resourcesView)
+ this.visibleResource._resourcesView.hide();
+
+ var view = this.resourceViewForResource(resource);
+ view.headersVisible = true;
+ view.show(this.viewsContainerElement);
+
+ if (line) {
+ if (view.revealLine)
+ view.revealLine(line);
+ if (view.highlightLine)
+ view.highlightLine(line);
+ }
+
+ if (resource._resourcesTreeElement) {
+ resource._resourcesTreeElement.reveal();
+ resource._resourcesTreeElement.select(true);
+ }
+
+ this.visibleResource = resource;
+
+ this._updateSidebarWidth();
+ },
+
+ showView: function(view)
+ {
+ if (!view)
+ return;
+ this.showResource(view.resource);
+ },
+
+ closeVisibleResource: function()
+ {
+ this.containerElement.removeStyleClass("viewing-resource");
+ this._updateDividersLabelBarPosition();
+
+ if (this.visibleResource && this.visibleResource._resourcesView)
+ this.visibleResource._resourcesView.hide();
+ delete this.visibleResource;
+
+ if (this._lastSelectedGraphTreeElement)
+ this._lastSelectedGraphTreeElement.select(true);
+
+ this._updateSidebarWidth();
+ },
+
+ resourceViewForResource: function(resource)
+ {
+ if (!resource)
+ return null;
+ if (!resource._resourcesView)
+ resource._resourcesView = this._createResourceView(resource);
+ return resource._resourcesView;
+ },
+
+ sourceFrameForResource: function(resource)
+ {
+ var view = this.resourceViewForResource(resource);
+ if (!view)
+ return null;
+
+ if (!view.setupSourceFrameIfNeeded)
+ return null;
+
+ // Setting up the source frame requires that we be attached.
+ if (!this.element.parentNode)
+ this.attach();
+
+ view.setupSourceFrameIfNeeded();
+ return view.sourceFrame;
+ },
+
+ handleKeyEvent: function(event)
+ {
+ this.sidebarTree.handleKeyEvent(event);
+ },
+
+ _makeLegendElement: function(label, value, color)
+ {
+ var legendElement = document.createElement("label");
+ legendElement.className = "resources-graph-legend-item";
+
+ if (color) {
+ var swatch = document.createElement("canvas");
+ swatch.className = "resources-graph-legend-swatch";
+ swatch.setAttribute("width", "13");
+ swatch.setAttribute("height", "24");
+
+ legendElement.appendChild(swatch);
+
+ this._drawSwatch(swatch, color);
+ }
+
+ var labelElement = document.createElement("div");
+ labelElement.className = "resources-graph-legend-label";
+ legendElement.appendChild(labelElement);
+
+ var headerElement = document.createElement("div");
+ var headerElement = document.createElement("div");
+ headerElement.className = "resources-graph-legend-header";
+ headerElement.textContent = label;
+ labelElement.appendChild(headerElement);
+
+ var valueElement = document.createElement("div");
+ valueElement.className = "resources-graph-legend-value";
+ valueElement.textContent = value;
+ labelElement.appendChild(valueElement);
+
+ return legendElement;
+ },
+
+ _sortResourcesIfNeeded: function()
+ {
+ var sortedElements = [].concat(this.resourcesTreeElement.children);
+ sortedElements.sort(this.sortingFunction);
+
+ var sortedElementsLength = sortedElements.length;
+ for (var i = 0; i < sortedElementsLength; ++i) {
+ var treeElement = sortedElements[i];
+ if (treeElement === this.resourcesTreeElement.children[i])
+ continue;
+
+ var wasSelected = treeElement.selected;
+ this.resourcesTreeElement.removeChild(treeElement);
+ this.resourcesTreeElement.insertChild(treeElement, i);
+ if (wasSelected)
+ treeElement.select(true);
+
+ var graphElement = treeElement._resourceGraph.graphElement;
+ this.resourcesGraphsElement.insertBefore(graphElement, this.resourcesGraphsElement.children[i]);
+ }
+ },
+
+ _updateGraphDividersIfNeeded: function(force)
+ {
+ if (!this.visible) {
+ this.needsRefresh = true;
+ return;
+ }
+
+ if (document.body.offsetWidth <= 0) {
+ // The stylesheet hasn't loaded yet or the window is closed,
+ // so we can't calculate what is need. Return early.
+ return;
+ }
+
+ var dividerCount = Math.round(this.dividersElement.offsetWidth / 64);
+ var slice = this.calculator.boundarySpan / dividerCount;
+ if (!force && this._currentDividerSlice === slice)
+ return;
+
+ this._currentDividerSlice = slice;
+
+ this.dividersElement.removeChildren();
+ this.dividersLabelBarElement.removeChildren();
+
+ for (var i = 1; i <= dividerCount; ++i) {
+ var divider = document.createElement("div");
+ divider.className = "resources-divider";
+ if (i === dividerCount)
+ divider.addStyleClass("last");
+ divider.style.left = ((i / dividerCount) * 100) + "%";
+
+ this.dividersElement.appendChild(divider.cloneNode());
+
+ var label = document.createElement("div");
+ label.className = "resources-divider-label";
+ if (!isNaN(slice))
+ label.textContent = this.calculator.formatValue(slice * i);
+ divider.appendChild(label);
+
+ this.dividersLabelBarElement.appendChild(divider);
+ }
+ },
+
+ _fadeOutRect: function(ctx, x, y, w, h, a1, a2)
+ {
+ ctx.save();
+
+ var gradient = ctx.createLinearGradient(x, y, x, y + h);
+ gradient.addColorStop(0.0, "rgba(0, 0, 0, " + (1.0 - a1) + ")");
+ gradient.addColorStop(0.8, "rgba(0, 0, 0, " + (1.0 - a2) + ")");
+ gradient.addColorStop(1.0, "rgba(0, 0, 0, 1.0)");
+
+ ctx.globalCompositeOperation = "destination-out";
+
+ ctx.fillStyle = gradient;
+ ctx.fillRect(x, y, w, h);
+
+ ctx.restore();
+ },
+
+ _drawSwatch: function(canvas, color)
+ {
+ var ctx = canvas.getContext("2d");
+
+ function drawSwatchSquare() {
+ ctx.fillStyle = color;
+ ctx.fillRect(0, 0, 13, 13);
+
+ var gradient = ctx.createLinearGradient(0, 0, 13, 13);
+ gradient.addColorStop(0.0, "rgba(255, 255, 255, 0.2)");
+ gradient.addColorStop(1.0, "rgba(255, 255, 255, 0.0)");
+
+ ctx.fillStyle = gradient;
+ ctx.fillRect(0, 0, 13, 13);
+
+ gradient = ctx.createLinearGradient(13, 13, 0, 0);
+ gradient.addColorStop(0.0, "rgba(0, 0, 0, 0.2)");
+ gradient.addColorStop(1.0, "rgba(0, 0, 0, 0.0)");
+
+ ctx.fillStyle = gradient;
+ ctx.fillRect(0, 0, 13, 13);
+
+ ctx.strokeStyle = "rgba(0, 0, 0, 0.6)";
+ ctx.strokeRect(0.5, 0.5, 12, 12);
+ }
+
+ ctx.clearRect(0, 0, 13, 24);
+
+ drawSwatchSquare();
+
+ ctx.save();
+
+ ctx.translate(0, 25);
+ ctx.scale(1, -1);
+
+ drawSwatchSquare();
+
+ ctx.restore();
+
+ this._fadeOutRect(ctx, 0, 13, 13, 13, 0.5, 0.0);
+ },
+
+ _drawSummaryGraph: function(segments)
+ {
+ if (!this.summaryGraphElement)
+ return;
+
+ if (!segments || !segments.length) {
+ segments = [{color: "white", value: 1}];
+ this._showingEmptySummaryGraph = true;
+ } else
+ delete this._showingEmptySummaryGraph;
+
+ // Calculate the total of all segments.
+ var total = 0;
+ for (var i = 0; i < segments.length; ++i)
+ total += segments[i].value;
+
+ // Calculate the percentage of each segment, rounded to the nearest percent.
+ var percents = segments.map(function(s) { return Math.max(Math.round(100 * s.value / total), 1) });
+
+ // Calculate the total percentage.
+ var percentTotal = 0;
+ for (var i = 0; i < percents.length; ++i)
+ percentTotal += percents[i];
+
+ // Make sure our percentage total is not greater-than 100, it can be greater
+ // if we rounded up for a few segments.
+ while (percentTotal > 100) {
+ for (var i = 0; i < percents.length && percentTotal > 100; ++i) {
+ if (percents[i] > 1) {
+ --percents[i];
+ --percentTotal;
+ }
+ }
+ }
+
+ // Make sure our percentage total is not less-than 100, it can be less
+ // if we rounded down for a few segments.
+ while (percentTotal < 100) {
+ for (var i = 0; i < percents.length && percentTotal < 100; ++i) {
+ ++percents[i];
+ ++percentTotal;
+ }
+ }
+
+ var ctx = this.summaryGraphElement.getContext("2d");
+
+ var x = 0;
+ var y = 0;
+ var w = 450;
+ var h = 19;
+ var r = (h / 2);
+
+ function drawPillShadow()
+ {
+ // This draws a line with a shadow that is offset away from the line. The line is stroked
+ // twice with different X shadow offsets to give more feathered edges. Later we erase the
+ // line with destination-out 100% transparent black, leaving only the shadow. This only
+ // works if nothing has been drawn into the canvas yet.
+
+ ctx.beginPath();
+ ctx.moveTo(x + 4, y + h - 3 - 0.5);
+ ctx.lineTo(x + w - 4, y + h - 3 - 0.5);
+ ctx.closePath();
+
+ ctx.save();
+
+ ctx.shadowBlur = 2;
+ ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
+ ctx.shadowOffsetX = 3;
+ ctx.shadowOffsetY = 5;
+
+ ctx.strokeStyle = "white";
+ ctx.lineWidth = 1;
+
+ ctx.stroke();
+
+ ctx.shadowOffsetX = -3;
+
+ ctx.stroke();
+
+ ctx.restore();
+
+ ctx.save();
+
+ ctx.globalCompositeOperation = "destination-out";
+ ctx.strokeStyle = "rgba(0, 0, 0, 1)";
+ ctx.lineWidth = 1;
+
+ ctx.stroke();
+
+ ctx.restore();
+ }
+
+ function drawPill()
+ {
+ // Make a rounded rect path.
+ ctx.beginPath();
+ ctx.moveTo(x, y + r);
+ ctx.lineTo(x, y + h - r);
+ ctx.quadraticCurveTo(x, y + h, x + r, y + h);
+ ctx.lineTo(x + w - r, y + h);
+ ctx.quadraticCurveTo(x + w, y + h, x + w, y + h - r);
+ ctx.lineTo(x + w, y + r);
+ ctx.quadraticCurveTo(x + w, y, x + w - r, y);
+ ctx.lineTo(x + r, y);
+ ctx.quadraticCurveTo(x, y, x, y + r);
+ ctx.closePath();
+
+ // Clip to the rounded rect path.
+ ctx.save();
+ ctx.clip();
+
+ // Fill the segments with the associated color.
+ var previousSegmentsWidth = 0;
+ for (var i = 0; i < segments.length; ++i) {
+ var segmentWidth = Math.round(w * percents[i] / 100);
+ ctx.fillStyle = segments[i].color;
+ ctx.fillRect(x + previousSegmentsWidth, y, segmentWidth, h);
+ previousSegmentsWidth += segmentWidth;
+ }
+
+ // Draw the segment divider lines.
+ ctx.lineWidth = 1;
+ for (var i = 1; i < 20; ++i) {
+ ctx.beginPath();
+ ctx.moveTo(x + (i * Math.round(w / 20)) + 0.5, y);
+ ctx.lineTo(x + (i * Math.round(w / 20)) + 0.5, y + h);
+ ctx.closePath();
+
+ ctx.strokeStyle = "rgba(0, 0, 0, 0.2)";
+ ctx.stroke();
+
+ ctx.beginPath();
+ ctx.moveTo(x + (i * Math.round(w / 20)) + 1.5, y);
+ ctx.lineTo(x + (i * Math.round(w / 20)) + 1.5, y + h);
+ ctx.closePath();
+
+ ctx.strokeStyle = "rgba(255, 255, 255, 0.2)";
+ ctx.stroke();
+ }
+
+ // Draw the pill shading.
+ var lightGradient = ctx.createLinearGradient(x, y, x, y + (h / 1.5));
+ lightGradient.addColorStop(0.0, "rgba(220, 220, 220, 0.6)");
+ lightGradient.addColorStop(0.4, "rgba(220, 220, 220, 0.2)");
+ lightGradient.addColorStop(1.0, "rgba(255, 255, 255, 0.0)");
+
+ var darkGradient = ctx.createLinearGradient(x, y + (h / 3), x, y + h);
+ darkGradient.addColorStop(0.0, "rgba(0, 0, 0, 0.0)");
+ darkGradient.addColorStop(0.8, "rgba(0, 0, 0, 0.2)");
+ darkGradient.addColorStop(1.0, "rgba(0, 0, 0, 0.5)");
+
+ ctx.fillStyle = darkGradient;
+ ctx.fillRect(x, y, w, h);
+
+ ctx.fillStyle = lightGradient;
+ ctx.fillRect(x, y, w, h);
+
+ ctx.restore();
+ }
+
+ ctx.clearRect(x, y, w, (h * 2));
+
+ drawPillShadow();
+ drawPill();
+
+ ctx.save();
+
+ ctx.translate(0, (h * 2) + 1);
+ ctx.scale(1, -1);
+
+ drawPill();
+
+ ctx.restore();
+
+ this._fadeOutRect(ctx, x, y + h + 1, w, h, 0.5, 0.0);
+ },
+
+ _updateSummaryGraph: function()
+ {
+ var graphInfo = this.calculator.computeSummaryValues(this._resources);
+
+ var categoryOrder = ["documents", "stylesheets", "images", "scripts", "xhr", "fonts", "other"];
+ var categoryColors = {documents: {r: 47, g: 102, b: 236}, stylesheets: {r: 157, g: 231, b: 119}, images: {r: 164, g: 60, b: 255}, scripts: {r: 255, g: 121, b: 0}, xhr: {r: 231, g: 231, b: 10}, fonts: {r: 255, g: 82, b: 62}, other: {r: 186, g: 186, b: 186}};
+ var fillSegments = [];
+
+ this.legendElement.removeChildren();
+
+ for (var i = 0; i < categoryOrder.length; ++i) {
+ var category = categoryOrder[i];
+ var size = graphInfo.categoryValues[category];
+ if (!size)
+ continue;
+
+ var color = categoryColors[category];
+ var colorString = "rgb(" + color.r + ", " + color.g + ", " + color.b + ")";
+
+ var fillSegment = {color: colorString, value: size};
+ fillSegments.push(fillSegment);
+
+ var legendLabel = this._makeLegendElement(WebInspector.resourceCategories[category].title, this.calculator.formatValue(size), colorString);
+ this.legendElement.appendChild(legendLabel);
+ }
+
+ if (graphInfo.total) {
+ var totalLegendLabel = this._makeLegendElement(WebInspector.UIString("Total"), this.calculator.formatValue(graphInfo.total));
+ totalLegendLabel.addStyleClass("total");
+ this.legendElement.appendChild(totalLegendLabel);
+ }
+
+ this._drawSummaryGraph(fillSegments);
+ },
+
+ _updateDividersLabelBarPosition: function()
+ {
+ var scrollTop = this.containerElement.scrollTop;
+ var dividersTop = (scrollTop < this.summaryElement.offsetHeight ? this.summaryElement.offsetHeight : scrollTop);
+ this.dividersElement.style.top = scrollTop + "px";
+ this.dividersLabelBarElement.style.top = dividersTop + "px";
+ },
+
+ _graphSelected: function(treeElement)
+ {
+ if (this._lastSelectedGraphTreeElement)
+ this._lastSelectedGraphTreeElement.selectedSortingOptionIndex = this.sortingSelectElement.selectedIndex;
+
+ this._lastSelectedGraphTreeElement = treeElement;
+
+ this.sortingSelectElement.removeChildren();
+ for (var i = 0; i < treeElement.sortingOptions.length; ++i) {
+ var sortingOption = treeElement.sortingOptions[i];
+ var option = document.createElement("option");
+ option.label = sortingOption.name;
+ option.sortingFunction = sortingOption.sortingFunction;
+ option.calculator = sortingOption.calculator;
+ this.sortingSelectElement.appendChild(option);
+ }
+
+ this.sortingSelectElement.selectedIndex = treeElement.selectedSortingOptionIndex;
+ this._changeSortingFunction();
+
+ this.closeVisibleResource();
+ this.containerElement.scrollTop = 0;
+ },
+
+ _toggleLargerResources: function()
+ {
+ if (!this.resourcesTreeElement._childrenListNode)
+ return;
+
+ this.resourcesTreeElement.smallChildren = !this.resourcesTreeElement.smallChildren;
+
+ if (this.resourcesTreeElement.smallChildren) {
+ this.resourcesGraphsElement.addStyleClass("small");
+ this.largerResourcesButton.title = WebInspector.UIString("Use large resource rows.");
+ this.largerResourcesButton.removeStyleClass("toggled-on");
+ this._adjustScrollPosition();
+ } else {
+ this.resourcesGraphsElement.removeStyleClass("small");
+ this.largerResourcesButton.title = WebInspector.UIString("Use small resource rows.");
+ this.largerResourcesButton.addStyleClass("toggled-on");
+ }
+ },
+
+ _adjustScrollPosition: function()
+ {
+ // Prevent the container from being scrolled off the end.
+ if ((this.containerElement.scrollTop + this.containerElement.offsetHeight) > this.sidebarElement.offsetHeight)
+ this.containerElement.scrollTop = (this.sidebarElement.offsetHeight - this.containerElement.offsetHeight);
+ },
+
+ _changeSortingFunction: function()
+ {
+ var selectedOption = this.sortingSelectElement[this.sortingSelectElement.selectedIndex];
+ this.sortingFunction = selectedOption.sortingFunction;
+ this.calculator = selectedOption.calculator;
+ },
+
+ _createResourceView: function(resource)
+ {
+ switch (resource.category) {
+ case WebInspector.resourceCategories.documents:
+ case WebInspector.resourceCategories.stylesheets:
+ case WebInspector.resourceCategories.scripts:
+ case WebInspector.resourceCategories.xhr:
+ return new WebInspector.SourceView(resource);
+ case WebInspector.resourceCategories.images:
+ return new WebInspector.ImageView(resource);
+ case WebInspector.resourceCategories.fonts:
+ return new WebInspector.FontView(resource);
+ default:
+ return new WebInspector.ResourceView(resource);
+ }
+ },
+
+ _startSidebarDragging: function(event)
+ {
+ WebInspector.elementDragStart(this.sidebarResizeElement, this._sidebarDragging.bind(this), this._endSidebarDragging.bind(this), event, "col-resize");
+ },
+
+ _sidebarDragging: function(event)
+ {
+ this._updateSidebarWidth(event.pageX);
+
+ event.preventDefault();
+ },
+
+ _endSidebarDragging: function(event)
+ {
+ WebInspector.elementDragEnd(event);
+ },
+
+ _updateSidebarWidth: function(width)
+ {
+ if (this.sidebarElement.offsetWidth <= 0) {
+ // The stylesheet hasn't loaded yet or the window is closed,
+ // so we can't calculate what is need. Return early.
+ return;
+ }
+
+ if (!("_currentSidebarWidth" in this))
+ this._currentSidebarWidth = this.sidebarElement.offsetWidth;
+
+ if (typeof width === "undefined")
+ width = this._currentSidebarWidth;
+
+ width = Number.constrain(width, Preferences.minSidebarWidth, window.innerWidth / 2);
+
+ this._currentSidebarWidth = width;
+
+ if (this.visibleResource) {
+ this.containerElement.style.width = width + "px";
+ this.sidebarElement.style.removeProperty("width");
+ } else {
+ this.sidebarElement.style.width = width + "px";
+ this.containerElement.style.removeProperty("width");
+ }
+
+ this.containerContentElement.style.left = width + "px";
+ this.viewsContainerElement.style.left = width + "px";
+ this.sidebarResizeElement.style.left = (width - 3) + "px";
+
+ this._updateGraphDividersIfNeeded();
+
+ var visibleView = this.visibleView;
+ if (visibleView && "resize" in visibleView)
+ visibleView.resize();
+ },
+
+ _enableResourceTracking: function()
+ {
+ if (InspectorController.resourceTrackingEnabled())
+ return;
+ this._toggleResourceTracking(this.panelEnablerView.alwaysEnabled);
+ },
+
+ _toggleResourceTracking: function(optionalAlways)
+ {
+ if (InspectorController.resourceTrackingEnabled()) {
+ this.largerResourcesButton.visible = false;
+ this.sortingSelectElement.visible = false;
+ InspectorController.disableResourceTracking(true);
+ } else {
+ this.largerResourcesButton.visible = true;
+ this.sortingSelectElement.visible = true;
+ InspectorController.enableResourceTracking(!!optionalAlways);
+ }
+ }
+}
+
+WebInspector.ResourcesPanel.prototype.__proto__ = WebInspector.Panel.prototype;
+
+WebInspector.ResourceCalculator = function()
+{
+}
+
+WebInspector.ResourceCalculator.prototype = {
+ computeSummaryValues: function(resources)
+ {
+ var total = 0;
+ var categoryValues = {};
+
+ var resourcesLength = resources.length;
+ for (var i = 0; i < resourcesLength; ++i) {
+ var resource = resources[i];
+ var value = this._value(resource);
+ if (typeof value === "undefined")
+ continue;
+ if (!(resource.category.name in categoryValues))
+ categoryValues[resource.category.name] = 0;
+ categoryValues[resource.category.name] += value;
+ total += value;
+ }
+
+ return {categoryValues: categoryValues, total: total};
+ },
+
+ computeBarGraphPercentages: function(resource)
+ {
+ return {start: 0, middle: 0, end: (this._value(resource) / this.boundarySpan) * 100};
+ },
+
+ computeBarGraphLabels: function(resource)
+ {
+ const label = this.formatValue(this._value(resource));
+ var tooltip = label;
+ if (resource.cached)
+ tooltip = WebInspector.UIString("%s (from cache)", tooltip);
+ return {left: label, right: label, tooltip: tooltip};
+ },
+
+ get boundarySpan()
+ {
+ return this.maximumBoundary - this.minimumBoundary;
+ },
+
+ updateBoundaries: function(resource)
+ {
+ this.minimumBoundary = 0;
+
+ var value = this._value(resource);
+ if (typeof this.maximumBoundary === "undefined" || value > this.maximumBoundary) {
+ this.maximumBoundary = value;
+ return true;
+ }
+
+ return false;
+ },
+
+ reset: function()
+ {
+ delete this.minimumBoundary;
+ delete this.maximumBoundary;
+ },
+
+ _value: function(resource)
+ {
+ return 0;
+ },
+
+ formatValue: function(value)
+ {
+ return value.toString();
+ }
+}
+
+WebInspector.ResourceTimeCalculator = function(startAtZero)
+{
+ WebInspector.ResourceCalculator.call(this);
+ this.startAtZero = startAtZero;
+}
+
+WebInspector.ResourceTimeCalculator.prototype = {
+ computeSummaryValues: function(resources)
+ {
+ var resourcesByCategory = {};
+ var resourcesLength = resources.length;
+ for (var i = 0; i < resourcesLength; ++i) {
+ var resource = resources[i];
+ if (!(resource.category.name in resourcesByCategory))
+ resourcesByCategory[resource.category.name] = [];
+ resourcesByCategory[resource.category.name].push(resource);
+ }
+
+ var earliestStart;
+ var latestEnd;
+ var categoryValues = {};
+ for (var category in resourcesByCategory) {
+ resourcesByCategory[category].sort(WebInspector.Resource.CompareByTime);
+ categoryValues[category] = 0;
+
+ var segment = {start: -1, end: -1};
+
+ var categoryResources = resourcesByCategory[category];
+ var resourcesLength = categoryResources.length;
+ for (var i = 0; i < resourcesLength; ++i) {
+ var resource = categoryResources[i];
+ if (resource.startTime === -1 || resource.endTime === -1)
+ continue;
+
+ if (typeof earliestStart === "undefined")
+ earliestStart = resource.startTime;
+ else
+ earliestStart = Math.min(earliestStart, resource.startTime);
+
+ if (typeof latestEnd === "undefined")
+ latestEnd = resource.endTime;
+ else
+ latestEnd = Math.max(latestEnd, resource.endTime);
+
+ if (resource.startTime <= segment.end) {
+ segment.end = Math.max(segment.end, resource.endTime);
+ continue;
+ }
+
+ categoryValues[category] += segment.end - segment.start;
+
+ segment.start = resource.startTime;
+ segment.end = resource.endTime;
+ }
+
+ // Add the last segment
+ categoryValues[category] += segment.end - segment.start;
+ }
+
+ return {categoryValues: categoryValues, total: latestEnd - earliestStart};
+ },
+
+ computeBarGraphPercentages: function(resource)
+ {
+ if (resource.startTime !== -1)
+ var start = ((resource.startTime - this.minimumBoundary) / this.boundarySpan) * 100;
+ else
+ var start = 0;
+
+ if (resource.responseReceivedTime !== -1)
+ var middle = ((resource.responseReceivedTime - this.minimumBoundary) / this.boundarySpan) * 100;
+ else
+ var middle = (this.startAtZero ? start : 100);
+
+ if (resource.endTime !== -1)
+ var end = ((resource.endTime - this.minimumBoundary) / this.boundarySpan) * 100;
+ else
+ var end = (this.startAtZero ? middle : 100);
+
+ if (this.startAtZero) {
+ end -= start;
+ middle -= start;
+ start = 0;
+ }
+
+ return {start: start, middle: middle, end: end};
+ },
+
+ computeBarGraphLabels: function(resource)
+ {
+ var leftLabel = "";
+ if (resource.latency > 0)
+ leftLabel = this.formatValue(resource.latency);
+
+ var rightLabel = "";
+ if (resource.responseReceivedTime !== -1 && resource.endTime !== -1)
+ rightLabel = this.formatValue(resource.endTime - resource.responseReceivedTime);
+
+ if (leftLabel && rightLabel) {
+ var total = this.formatValue(resource.duration);
+ var tooltip = WebInspector.UIString("%s latency, %s download (%s total)", leftLabel, rightLabel, total);
+ } else if (leftLabel)
+ var tooltip = WebInspector.UIString("%s latency", leftLabel);
+ else if (rightLabel)
+ var tooltip = WebInspector.UIString("%s download", rightLabel);
+
+ if (resource.cached)
+ tooltip = WebInspector.UIString("%s (from cache)", tooltip);
+
+ return {left: leftLabel, right: rightLabel, tooltip: tooltip};
+ },
+
+ updateBoundaries: function(resource)
+ {
+ var didChange = false;
+
+ var lowerBound;
+ if (this.startAtZero)
+ lowerBound = 0;
+ else
+ lowerBound = this._lowerBound(resource);
+
+ if (lowerBound !== -1 && (typeof this.minimumBoundary === "undefined" || lowerBound < this.minimumBoundary)) {
+ this.minimumBoundary = lowerBound;
+ didChange = true;
+ }
+
+ var upperBound = this._upperBound(resource);
+ if (upperBound !== -1 && (typeof this.maximumBoundary === "undefined" || upperBound > this.maximumBoundary)) {
+ this.maximumBoundary = upperBound;
+ didChange = true;
+ }
+
+ return didChange;
+ },
+
+ formatValue: function(value)
+ {
+ return Number.secondsToString(value, WebInspector.UIString.bind(WebInspector));
+ },
+
+ _lowerBound: function(resource)
+ {
+ return 0;
+ },
+
+ _upperBound: function(resource)
+ {
+ return 0;
+ },
+}
+
+WebInspector.ResourceTimeCalculator.prototype.__proto__ = WebInspector.ResourceCalculator.prototype;
+
+WebInspector.ResourceTransferTimeCalculator = function()
+{
+ WebInspector.ResourceTimeCalculator.call(this, false);
+}
+
+WebInspector.ResourceTransferTimeCalculator.prototype = {
+ formatValue: function(value)
+ {
+ return Number.secondsToString(value, WebInspector.UIString.bind(WebInspector));
+ },
+
+ _lowerBound: function(resource)
+ {
+ return resource.startTime;
+ },
+
+ _upperBound: function(resource)
+ {
+ return resource.endTime;
+ }
+}
+
+WebInspector.ResourceTransferTimeCalculator.prototype.__proto__ = WebInspector.ResourceTimeCalculator.prototype;
+
+WebInspector.ResourceTransferDurationCalculator = function()
+{
+ WebInspector.ResourceTimeCalculator.call(this, true);
+}
+
+WebInspector.ResourceTransferDurationCalculator.prototype = {
+ formatValue: function(value)
+ {
+ return Number.secondsToString(value, WebInspector.UIString.bind(WebInspector));
+ },
+
+ _upperBound: function(resource)
+ {
+ return resource.duration;
+ }
+}
+
+WebInspector.ResourceTransferDurationCalculator.prototype.__proto__ = WebInspector.ResourceTimeCalculator.prototype;
+
+WebInspector.ResourceTransferSizeCalculator = function()
+{
+ WebInspector.ResourceCalculator.call(this);
+}
+
+WebInspector.ResourceTransferSizeCalculator.prototype = {
+ _value: function(resource)
+ {
+ return resource.contentLength;
+ },
+
+ formatValue: function(value)
+ {
+ return Number.bytesToString(value, WebInspector.UIString.bind(WebInspector));
+ }
+}
+
+WebInspector.ResourceTransferSizeCalculator.prototype.__proto__ = WebInspector.ResourceCalculator.prototype;
+
+WebInspector.ResourceSidebarTreeElement = function(resource)
+{
+ this.resource = resource;
+
+ this.createIconElement();
+
+ WebInspector.SidebarTreeElement.call(this, "resource-sidebar-tree-item", "", "", resource);
+
+ this.refreshTitles();
+}
+
+WebInspector.ResourceSidebarTreeElement.prototype = {
+ onattach: function()
+ {
+ WebInspector.SidebarTreeElement.prototype.onattach.call(this);
+
+ this._listItemNode.addStyleClass("resources-category-" + this.resource.category.name);
+ },
+
+ onselect: function()
+ {
+ WebInspector.panels.resources.showResource(this.resource);
+ },
+
+ get mainTitle()
+ {
+ return this.resource.displayName;
+ },
+
+ set mainTitle(x)
+ {
+ // Do nothing.
+ },
+
+ get subtitle()
+ {
+ var subtitle = this.resource.displayDomain;
+
+ if (this.resource.path && this.resource.lastPathComponent) {
+ var lastPathComponentIndex = this.resource.path.lastIndexOf("/" + this.resource.lastPathComponent);
+ if (lastPathComponentIndex != -1)
+ subtitle += this.resource.path.substring(0, lastPathComponentIndex);
+ }
+
+ return subtitle;
+ },
+
+ set subtitle(x)
+ {
+ // Do nothing.
+ },
+
+ createIconElement: function()
+ {
+ var previousIconElement = this.iconElement;
+
+ if (this.resource.category === WebInspector.resourceCategories.images) {
+ var previewImage = document.createElement("img");
+ previewImage.className = "image-resource-icon-preview";
+ previewImage.src = this.resource.url;
+
+ this.iconElement = document.createElement("div");
+ this.iconElement.className = "icon";
+ this.iconElement.appendChild(previewImage);
+ } else {
+ this.iconElement = document.createElement("img");
+ this.iconElement.className = "icon";
+ }
+
+ if (previousIconElement)
+ previousIconElement.parentNode.replaceChild(this.iconElement, previousIconElement);
+ },
+
+ refresh: function()
+ {
+ this.refreshTitles();
+
+ if (!this._listItemNode.hasStyleClass("resources-category-" + this.resource.category.name)) {
+ this._listItemNode.removeMatchingStyleClasses("resources-category-\\w+");
+ this._listItemNode.addStyleClass("resources-category-" + this.resource.category.name);
+
+ this.createIconElement();
+ }
+ },
+
+ resetBubble: function()
+ {
+ this.bubbleText = "";
+ this.bubbleElement.removeStyleClass("search-matches");
+ this.bubbleElement.removeStyleClass("warning");
+ this.bubbleElement.removeStyleClass("error");
+ },
+
+ set searchMatches(matches)
+ {
+ this.resetBubble();
+
+ if (!matches)
+ return;
+
+ this.bubbleText = matches;
+ this.bubbleElement.addStyleClass("search-matches");
+ },
+
+ updateErrorsAndWarnings: function()
+ {
+ this.resetBubble();
+
+ if (this.resource.warnings || this.resource.errors)
+ this.bubbleText = (this.resource.warnings + this.resource.errors);
+
+ if (this.resource.warnings)
+ this.bubbleElement.addStyleClass("warning");
+
+ if (this.resource.errors)
+ this.bubbleElement.addStyleClass("error");
+ }
+}
+
+WebInspector.ResourceSidebarTreeElement.CompareByAscendingStartTime = function(a, b)
+{
+ return WebInspector.Resource.CompareByStartTime(a.resource, b.resource)
+ || WebInspector.Resource.CompareByEndTime(a.resource, b.resource)
+ || WebInspector.Resource.CompareByResponseReceivedTime(a.resource, b.resource);
+}
+
+WebInspector.ResourceSidebarTreeElement.CompareByAscendingResponseReceivedTime = function(a, b)
+{
+ return WebInspector.Resource.CompareByResponseReceivedTime(a.resource, b.resource)
+ || WebInspector.Resource.CompareByStartTime(a.resource, b.resource)
+ || WebInspector.Resource.CompareByEndTime(a.resource, b.resource);
+}
+
+WebInspector.ResourceSidebarTreeElement.CompareByAscendingEndTime = function(a, b)
+{
+ return WebInspector.Resource.CompareByEndTime(a.resource, b.resource)
+ || WebInspector.Resource.CompareByStartTime(a.resource, b.resource)
+ || WebInspector.Resource.CompareByResponseReceivedTime(a.resource, b.resource);
+}
+
+WebInspector.ResourceSidebarTreeElement.CompareByDescendingDuration = function(a, b)
+{
+ return -1 * WebInspector.Resource.CompareByDuration(a.resource, b.resource);
+}
+
+WebInspector.ResourceSidebarTreeElement.CompareByDescendingLatency = function(a, b)
+{
+ return -1 * WebInspector.Resource.CompareByLatency(a.resource, b.resource);
+}
+
+WebInspector.ResourceSidebarTreeElement.CompareByDescendingSize = function(a, b)
+{
+ return -1 * WebInspector.Resource.CompareBySize(a.resource, b.resource);
+}
+
+WebInspector.ResourceSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
+
+WebInspector.ResourceGraph = function(resource)
+{
+ this.resource = resource;
+
+ this._graphElement = document.createElement("div");
+ this._graphElement.className = "resources-graph-side";
+ this._graphElement.addEventListener("mouseover", this.refreshLabelPositions.bind(this), false);
+
+ if (resource.cached)
+ this._graphElement.addStyleClass("resource-cached");
+
+ this._barAreaElement = document.createElement("div");
+ this._barAreaElement.className = "resources-graph-bar-area hidden";
+ this._graphElement.appendChild(this._barAreaElement);
+
+ this._barLeftElement = document.createElement("div");
+ this._barLeftElement.className = "resources-graph-bar waiting";
+ this._barAreaElement.appendChild(this._barLeftElement);
+
+ this._barRightElement = document.createElement("div");
+ this._barRightElement.className = "resources-graph-bar";
+ this._barAreaElement.appendChild(this._barRightElement);
+
+ this._labelLeftElement = document.createElement("div");
+ this._labelLeftElement.className = "resources-graph-label waiting";
+ this._barAreaElement.appendChild(this._labelLeftElement);
+
+ this._labelRightElement = document.createElement("div");
+ this._labelRightElement.className = "resources-graph-label";
+ this._barAreaElement.appendChild(this._labelRightElement);
+
+ this._graphElement.addStyleClass("resources-category-" + resource.category.name);
+}
+
+WebInspector.ResourceGraph.prototype = {
+ get graphElement()
+ {
+ return this._graphElement;
+ },
+
+ refreshLabelPositions: function()
+ {
+ this._labelLeftElement.style.removeProperty("left");
+ this._labelLeftElement.style.removeProperty("right");
+ this._labelLeftElement.removeStyleClass("before");
+ this._labelLeftElement.removeStyleClass("hidden");
+
+ this._labelRightElement.style.removeProperty("left");
+ this._labelRightElement.style.removeProperty("right");
+ this._labelRightElement.removeStyleClass("after");
+ this._labelRightElement.removeStyleClass("hidden");
+
+ const labelPadding = 10;
+ const rightBarWidth = (this._barRightElement.offsetWidth - labelPadding);
+ const leftBarWidth = ((this._barLeftElement.offsetWidth - this._barRightElement.offsetWidth) - labelPadding);
+
+ var labelBefore = (this._labelLeftElement.offsetWidth > leftBarWidth);
+ var labelAfter = (this._labelRightElement.offsetWidth > rightBarWidth);
+
+ if (labelBefore) {
+ if ((this._graphElement.offsetWidth * (this._percentages.start / 100)) < (this._labelLeftElement.offsetWidth + 10))
+ this._labelLeftElement.addStyleClass("hidden");
+ this._labelLeftElement.style.setProperty("right", (100 - this._percentages.start) + "%");
+ this._labelLeftElement.addStyleClass("before");
+ } else {
+ this._labelLeftElement.style.setProperty("left", this._percentages.start + "%");
+ this._labelLeftElement.style.setProperty("right", (100 - this._percentages.middle) + "%");
+ }
+
+ if (labelAfter) {
+ if ((this._graphElement.offsetWidth * ((100 - this._percentages.end) / 100)) < (this._labelRightElement.offsetWidth + 10))
+ this._labelRightElement.addStyleClass("hidden");
+ this._labelRightElement.style.setProperty("left", this._percentages.end + "%");
+ this._labelRightElement.addStyleClass("after");
+ } else {
+ this._labelRightElement.style.setProperty("left", this._percentages.middle + "%");
+ this._labelRightElement.style.setProperty("right", (100 - this._percentages.end) + "%");
+ }
+ },
+
+ refresh: function(calculator)
+ {
+ var percentages = calculator.computeBarGraphPercentages(this.resource);
+ var labels = calculator.computeBarGraphLabels(this.resource);
+
+ this._percentages = percentages;
+
+ this._barAreaElement.removeStyleClass("hidden");
+
+ if (!this._graphElement.hasStyleClass("resources-category-" + this.resource.category.name)) {
+ this._graphElement.removeMatchingStyleClasses("resources-category-\\w+");
+ this._graphElement.addStyleClass("resources-category-" + this.resource.category.name);
+ }
+
+ this._barLeftElement.style.setProperty("left", percentages.start + "%");
+ this._barLeftElement.style.setProperty("right", (100 - percentages.end) + "%");
+
+ this._barRightElement.style.setProperty("left", percentages.middle + "%");
+ this._barRightElement.style.setProperty("right", (100 - percentages.end) + "%");
+
+ this._labelLeftElement.textContent = labels.left;
+ this._labelRightElement.textContent = labels.right;
+
+ var tooltip = (labels.tooltip || "");
+ this._barLeftElement.title = tooltip;
+ this._labelLeftElement.title = tooltip;
+ this._labelRightElement.title = tooltip;
+ this._barRightElement.title = tooltip;
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ScopeChainSidebarPane.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ScopeChainSidebarPane.js
new file mode 100644
index 0000000..157cee9
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ScopeChainSidebarPane.js
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ScopeChainSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Scope Variables"));
+}
+
+WebInspector.ScopeChainSidebarPane.prototype = {
+ update: function(callFrame)
+ {
+ this.bodyElement.removeChildren();
+
+ this.sections = [];
+ this.callFrame = callFrame;
+
+ if (!callFrame) {
+ var infoElement = document.createElement("div");
+ infoElement.className = "info";
+ infoElement.textContent = WebInspector.UIString("Not Paused");
+ this.bodyElement.appendChild(infoElement);
+ return;
+ }
+
+ if (!callFrame._expandedProperties) {
+ // FIXME: fix this when https://bugs.webkit.org/show_bug.cgi?id=19410 is fixed.
+ // The callFrame is a JSInspectedObjectWrapper, so we are not allowed to assign
+ // an object created in the Inspector's context to that object. So create an
+ // Object from the inspectedWindow.
+ var inspectedWindow = InspectorController.inspectedWindow();
+ callFrame._expandedProperties = new inspectedWindow.Object;
+ }
+
+ var foundLocalScope = false;
+ var scopeChain = callFrame.scopeChain;
+ for (var i = 0; i < scopeChain.length; ++i) {
+ var scopeObject = scopeChain[i];
+ var title = null;
+ var subtitle = Object.describe(scopeObject, true);
+ var emptyPlaceholder = null;
+ var localScope = false;
+ var extraProperties = null;
+
+ if (Object.prototype.toString.call(scopeObject) === "[object JSActivation]") {
+ if (!foundLocalScope) {
+ extraProperties = { "this": callFrame.thisObject };
+ title = WebInspector.UIString("Local");
+ } else
+ title = WebInspector.UIString("Closure");
+ emptyPlaceholder = WebInspector.UIString("No Variables");
+ subtitle = null;
+ foundLocalScope = true;
+ localScope = true;
+ } else if (i === (scopeChain.length - 1))
+ title = WebInspector.UIString("Global");
+ else if (foundLocalScope && scopeObject instanceof InspectorController.inspectedWindow().Element)
+ title = WebInspector.UIString("Event Target");
+ else if (foundLocalScope && scopeObject instanceof InspectorController.inspectedWindow().Document)
+ title = WebInspector.UIString("Event Document");
+ else if (!foundLocalScope && !localScope)
+ title = WebInspector.UIString("With Block");
+
+ if (!title || title === subtitle)
+ subtitle = null;
+
+ var section = new WebInspector.ObjectPropertiesSection(scopeObject, title, subtitle, emptyPlaceholder, true, extraProperties, WebInspector.ScopeVariableTreeElement);
+ section.editInSelectedCallFrameWhenPaused = true;
+ section.pane = this;
+
+ if (!foundLocalScope || localScope)
+ section.expanded = true;
+
+ this.sections.push(section);
+ this.bodyElement.appendChild(section.element);
+ }
+ }
+}
+
+WebInspector.ScopeChainSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
+
+WebInspector.ScopeVariableTreeElement = function(parentObject, propertyName)
+{
+ WebInspector.ObjectPropertyTreeElement.call(this, parentObject, propertyName);
+}
+
+WebInspector.ScopeVariableTreeElement.prototype = {
+ onattach: function()
+ {
+ WebInspector.ObjectPropertyTreeElement.prototype.onattach.call(this);
+ if (this.hasChildren && this.propertyIdentifier in this.treeOutline.section.pane.callFrame._expandedProperties)
+ this.expand();
+ },
+
+ onexpand: function()
+ {
+ this.treeOutline.section.pane.callFrame._expandedProperties[this.propertyIdentifier] = true;
+ },
+
+ oncollapse: function()
+ {
+ delete this.treeOutline.section.pane.callFrame._expandedProperties[this.propertyIdentifier];
+ },
+
+ get propertyIdentifier()
+ {
+ if ("_propertyIdentifier" in this)
+ return this._propertyIdentifier;
+ var section = this.treeOutline.section;
+ this._propertyIdentifier = section.title + ":" + (section.subtitle ? section.subtitle + ":" : "") + this.propertyPath;
+ return this._propertyIdentifier;
+ },
+
+ get propertyPath()
+ {
+ if ("_propertyPath" in this)
+ return this._propertyPath;
+
+ var current = this;
+ var result;
+
+ do {
+ if (result)
+ result = current.propertyName + "." + result;
+ else
+ result = current.propertyName;
+ current = current.parent;
+ } while (current && !current.root);
+
+ this._propertyPath = result;
+ return result;
+ }
+}
+
+WebInspector.ScopeVariableTreeElement.prototype.__proto__ = WebInspector.ObjectPropertyTreeElement.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Script.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Script.js
new file mode 100644
index 0000000..46502a6
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/Script.js
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Script = function(sourceID, sourceURL, source, startingLine, errorLine, errorMessage)
+{
+ this.sourceID = sourceID;
+ this.sourceURL = sourceURL;
+ this.source = source;
+ this.startingLine = startingLine;
+ this.errorLine = errorLine;
+ this.errorMessage = errorMessage;
+}
+
+WebInspector.Script.prototype = {
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ScriptView.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ScriptView.js
new file mode 100644
index 0000000..124190c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ScriptView.js
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ScriptView = function(script)
+{
+ WebInspector.View.call(this);
+
+ this.element.addStyleClass("script-view");
+
+ this.script = script;
+
+ this._frameNeedsSetup = true;
+ this._sourceFrameSetup = false;
+
+ this.sourceFrame = new WebInspector.SourceFrame(null, this._addBreakpoint.bind(this));
+
+ this.element.appendChild(this.sourceFrame.element);
+}
+
+WebInspector.ScriptView.prototype = {
+ show: function(parentElement)
+ {
+ WebInspector.View.prototype.show.call(this, parentElement);
+ this.setupSourceFrameIfNeeded();
+ },
+
+ hide: function()
+ {
+ WebInspector.View.prototype.hide.call(this);
+ this._currentSearchResultIndex = -1;
+ },
+
+ setupSourceFrameIfNeeded: function()
+ {
+ if (!this._frameNeedsSetup)
+ return;
+
+ this.attach();
+
+ if (!InspectorController.addSourceToFrame("text/javascript", this.script.source, this.sourceFrame.element))
+ return;
+
+ delete this._frameNeedsSetup;
+
+ this.sourceFrame.addEventListener("syntax highlighting complete", this._syntaxHighlightingComplete, this);
+ this.sourceFrame.syntaxHighlightJavascript();
+ },
+
+ attach: function()
+ {
+ if (!this.element.parentNode)
+ document.getElementById("script-resource-views").appendChild(this.element);
+ },
+
+ _addBreakpoint: function(line)
+ {
+ var breakpoint = new WebInspector.Breakpoint(this.script.sourceURL, line, this.script.sourceID);
+ WebInspector.panels.scripts.addBreakpoint(breakpoint);
+ },
+
+ // The follow methods are pulled from SourceView, since they are
+ // generic and work with ScriptView just fine.
+
+ revealLine: WebInspector.SourceView.prototype.revealLine,
+ highlightLine: WebInspector.SourceView.prototype.highlightLine,
+ addMessage: WebInspector.SourceView.prototype.addMessage,
+ clearMessages: WebInspector.SourceView.prototype.clearMessages,
+ searchCanceled: WebInspector.SourceView.prototype.searchCanceled,
+ performSearch: WebInspector.SourceView.prototype.performSearch,
+ jumpToFirstSearchResult: WebInspector.SourceView.prototype.jumpToFirstSearchResult,
+ jumpToLastSearchResult: WebInspector.SourceView.prototype.jumpToLastSearchResult,
+ jumpToNextSearchResult: WebInspector.SourceView.prototype.jumpToNextSearchResult,
+ jumpToPreviousSearchResult: WebInspector.SourceView.prototype.jumpToPreviousSearchResult,
+ showingFirstSearchResult: WebInspector.SourceView.prototype.showingFirstSearchResult,
+ showingLastSearchResult: WebInspector.SourceView.prototype.showingLastSearchResult,
+ _jumpToSearchResult: WebInspector.SourceView.prototype._jumpToSearchResult,
+ _sourceFrameSetupFinished: WebInspector.SourceView.prototype._sourceFrameSetupFinished,
+ _syntaxHighlightingComplete: WebInspector.SourceView.prototype._syntaxHighlightingComplete
+}
+
+WebInspector.ScriptView.prototype.__proto__ = WebInspector.View.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ScriptsPanel.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ScriptsPanel.js
new file mode 100644
index 0000000..7af9292
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/ScriptsPanel.js
@@ -0,0 +1,854 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ScriptsPanel = function()
+{
+ WebInspector.Panel.call(this);
+
+ this.element.addStyleClass("scripts");
+
+ this.topStatusBar = document.createElement("div");
+ this.topStatusBar.className = "status-bar";
+ this.topStatusBar.id = "scripts-status-bar";
+ this.element.appendChild(this.topStatusBar);
+
+ this.backButton = document.createElement("button");
+ this.backButton.className = "status-bar-item";
+ this.backButton.id = "scripts-back";
+ this.backButton.title = WebInspector.UIString("Show the previous script resource.");
+ this.backButton.disabled = true;
+ this.backButton.appendChild(document.createElement("img"));
+ this.backButton.addEventListener("click", this._goBack.bind(this), false);
+ this.topStatusBar.appendChild(this.backButton);
+
+ this.forwardButton = document.createElement("button");
+ this.forwardButton.className = "status-bar-item";
+ this.forwardButton.id = "scripts-forward";
+ this.forwardButton.title = WebInspector.UIString("Show the next script resource.");
+ this.forwardButton.disabled = true;
+ this.forwardButton.appendChild(document.createElement("img"));
+ this.forwardButton.addEventListener("click", this._goForward.bind(this), false);
+ this.topStatusBar.appendChild(this.forwardButton);
+
+ this.filesSelectElement = document.createElement("select");
+ this.filesSelectElement.className = "status-bar-item";
+ this.filesSelectElement.id = "scripts-files";
+ this.filesSelectElement.addEventListener("change", this._changeVisibleFile.bind(this), false);
+ this.topStatusBar.appendChild(this.filesSelectElement);
+
+ this.functionsSelectElement = document.createElement("select");
+ this.functionsSelectElement.className = "status-bar-item";
+ this.functionsSelectElement.id = "scripts-functions";
+
+ // FIXME: append the functions select element to the top status bar when it is implemented.
+ // this.topStatusBar.appendChild(this.functionsSelectElement);
+
+ this.sidebarButtonsElement = document.createElement("div");
+ this.sidebarButtonsElement.id = "scripts-sidebar-buttons";
+ this.topStatusBar.appendChild(this.sidebarButtonsElement);
+
+ this.pauseButton = document.createElement("button");
+ this.pauseButton.className = "status-bar-item";
+ this.pauseButton.id = "scripts-pause";
+ this.pauseButton.title = WebInspector.UIString("Pause script execution.");
+ this.pauseButton.disabled = true;
+ this.pauseButton.appendChild(document.createElement("img"));
+ this.pauseButton.addEventListener("click", this._togglePause.bind(this), false);
+ this.sidebarButtonsElement.appendChild(this.pauseButton);
+
+ this.stepOverButton = document.createElement("button");
+ this.stepOverButton.className = "status-bar-item";
+ this.stepOverButton.id = "scripts-step-over";
+ this.stepOverButton.title = WebInspector.UIString("Step over next function call.");
+ this.stepOverButton.disabled = true;
+ this.stepOverButton.addEventListener("click", this._stepOverClicked.bind(this), false);
+ this.stepOverButton.appendChild(document.createElement("img"));
+ this.sidebarButtonsElement.appendChild(this.stepOverButton);
+
+ this.stepIntoButton = document.createElement("button");
+ this.stepIntoButton.className = "status-bar-item";
+ this.stepIntoButton.id = "scripts-step-into";
+ this.stepIntoButton.title = WebInspector.UIString("Step into next function call.");
+ this.stepIntoButton.disabled = true;
+ this.stepIntoButton.addEventListener("click", this._stepIntoClicked.bind(this), false);
+ this.stepIntoButton.appendChild(document.createElement("img"));
+ this.sidebarButtonsElement.appendChild(this.stepIntoButton);
+
+ this.stepOutButton = document.createElement("button");
+ this.stepOutButton.className = "status-bar-item";
+ this.stepOutButton.id = "scripts-step-out";
+ this.stepOutButton.title = WebInspector.UIString("Step out of current function.");
+ this.stepOutButton.disabled = true;
+ this.stepOutButton.addEventListener("click", this._stepOutClicked.bind(this), false);
+ this.stepOutButton.appendChild(document.createElement("img"));
+ this.sidebarButtonsElement.appendChild(this.stepOutButton);
+
+ this.debuggerStatusElement = document.createElement("div");
+ this.debuggerStatusElement.id = "scripts-debugger-status";
+ this.sidebarButtonsElement.appendChild(this.debuggerStatusElement);
+
+ this.viewsContainerElement = document.createElement("div");
+ this.viewsContainerElement.id = "script-resource-views";
+
+ this.sidebarElement = document.createElement("div");
+ this.sidebarElement.id = "scripts-sidebar";
+
+ this.sidebarResizeElement = document.createElement("div");
+ this.sidebarResizeElement.className = "sidebar-resizer-vertical";
+ this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
+
+ this.sidebarResizeWidgetElement = document.createElement("div");
+ this.sidebarResizeWidgetElement.id = "scripts-sidebar-resizer-widget";
+ this.sidebarResizeWidgetElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
+ this.topStatusBar.appendChild(this.sidebarResizeWidgetElement);
+
+ this.sidebarPanes = {};
+ this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
+ this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
+ this.sidebarPanes.breakpoints = new WebInspector.BreakpointsSidebarPane();
+
+ for (var pane in this.sidebarPanes)
+ this.sidebarElement.appendChild(this.sidebarPanes[pane].element);
+
+ // FIXME: remove the following line of code when the Breakpoints pane has content.
+ this.sidebarElement.removeChild(this.sidebarPanes.breakpoints.element);
+
+ this.sidebarPanes.callstack.expanded = true;
+ this.sidebarPanes.callstack.addEventListener("call frame selected", this._callFrameSelected, this);
+
+ this.sidebarPanes.scopechain.expanded = true;
+
+ var panelEnablerHeading = WebInspector.UIString("You need to enable debugging before you can use the Scripts panel.");
+ var panelEnablerDisclaimer = WebInspector.UIString("Enabling debugging will make scripts run slower.");
+ var panelEnablerButton = WebInspector.UIString("Enable Debugging");
+
+ this.panelEnablerView = new WebInspector.PanelEnablerView("scripts", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
+ this.panelEnablerView.addEventListener("enable clicked", this._enableDebugging, this);
+
+ this.element.appendChild(this.panelEnablerView.element);
+ this.element.appendChild(this.viewsContainerElement);
+ this.element.appendChild(this.sidebarElement);
+ this.element.appendChild(this.sidebarResizeElement);
+
+ this.enableToggleButton = document.createElement("button");
+ this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item";
+ this.enableToggleButton.addEventListener("click", this._toggleDebugging.bind(this), false);
+
+ this.pauseOnExceptionButton = document.createElement("button");
+ this.pauseOnExceptionButton.id = "scripts-pause-on-exceptions-status-bar-item";
+ this.pauseOnExceptionButton.className = "status-bar-item";
+ this.pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions.bind(this), false);
+
+ this._breakpointsURLMap = {};
+
+ this.reset();
+}
+
+WebInspector.ScriptsPanel.prototype = {
+ toolbarItemClass: "scripts",
+
+ get toolbarItemLabel()
+ {
+ return WebInspector.UIString("Scripts");
+ },
+
+ get statusBarItems()
+ {
+ return [this.enableToggleButton, this.pauseOnExceptionButton];
+ },
+
+ get paused()
+ {
+ return this._paused;
+ },
+
+ show: function()
+ {
+ WebInspector.Panel.prototype.show.call(this);
+ this.sidebarResizeElement.style.right = (this.sidebarElement.offsetWidth - 3) + "px";
+
+ if (this.visibleView) {
+ if (this.visibleView instanceof WebInspector.ResourceView)
+ this.visibleView.headersVisible = false;
+ this.visibleView.show(this.viewsContainerElement);
+ }
+
+ // Hide any views that are visible that are not this panel's current visible view.
+ // This can happen when a ResourceView is visible in the Resources panel then switched
+ // to the this panel.
+ for (var sourceID in this._sourceIDMap) {
+ var scriptOrResource = this._sourceIDMap[sourceID];
+ var view = this._sourceViewForScriptOrResource(scriptOrResource);
+ if (!view || view === this.visibleView)
+ continue;
+ view.visible = false;
+ }
+ if (this._attachDebuggerWhenShown) {
+ InspectorController.enableDebuggerFromFrontend(false);
+ delete this._attachDebuggerWhenShown;
+ }
+ },
+
+ get searchableViews()
+ {
+ var views = [];
+
+ const visibleView = this.visibleView;
+ if (visibleView && visibleView.performSearch) {
+ visibleView.alreadySearching = true;
+ views.push(visibleView);
+ }
+
+ for (var sourceID in this._sourceIDMap) {
+ var scriptOrResource = this._sourceIDMap[sourceID];
+ var view = this._sourceViewForScriptOrResource(scriptOrResource);
+ if (!view || !view.performSearch || view.alreadySearching)
+ continue;
+
+ view.alreadySearching = true;
+ views.push(view);
+ }
+
+ for (var i = 0; i < views.length; ++i)
+ delete views[i].alreadySearching;
+
+ return views;
+ },
+
+ addScript: function(sourceID, sourceURL, source, startingLine, errorLine, errorMessage)
+ {
+ var script = new WebInspector.Script(sourceID, sourceURL, source, startingLine, errorLine, errorMessage);
+
+ if (sourceURL in WebInspector.resourceURLMap) {
+ var resource = WebInspector.resourceURLMap[sourceURL];
+ resource.addScript(script);
+ }
+
+ if (sourceURL in this._breakpointsURLMap && sourceID) {
+ var breakpoints = this._breakpointsURLMap[sourceURL];
+ var breakpointsLength = breakpoints.length;
+ for (var i = 0; i < breakpointsLength; ++i) {
+ var breakpoint = breakpoints[i];
+ if (startingLine <= breakpoint.line) {
+ breakpoint.sourceID = sourceID;
+ if (breakpoint.enabled)
+ InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line);
+ }
+ }
+ }
+
+ if (sourceID)
+ this._sourceIDMap[sourceID] = (resource || script);
+
+ this._addScriptToFilesMenu(script);
+ },
+
+ addBreakpoint: function(breakpoint)
+ {
+ this.sidebarPanes.breakpoints.addBreakpoint(breakpoint);
+
+ var sourceFrame;
+ if (breakpoint.url) {
+ if (!(breakpoint.url in this._breakpointsURLMap))
+ this._breakpointsURLMap[breakpoint.url] = [];
+ this._breakpointsURLMap[breakpoint.url].unshift(breakpoint);
+
+ if (breakpoint.url in WebInspector.resourceURLMap) {
+ var resource = WebInspector.resourceURLMap[breakpoint.url];
+ sourceFrame = this._sourceFrameForScriptOrResource(resource);
+ }
+ }
+
+ if (breakpoint.sourceID && !sourceFrame) {
+ var object = this._sourceIDMap[breakpoint.sourceID]
+ sourceFrame = this._sourceFrameForScriptOrResource(object);
+ }
+
+ if (sourceFrame)
+ sourceFrame.addBreakpoint(breakpoint);
+ },
+
+ removeBreakpoint: function(breakpoint)
+ {
+ this.sidebarPanes.breakpoints.removeBreakpoint(breakpoint);
+
+ var sourceFrame;
+ if (breakpoint.url && breakpoint.url in this._breakpointsURLMap) {
+ var breakpoints = this._breakpointsURLMap[breakpoint.url];
+ breakpoints.remove(breakpoint);
+ if (!breakpoints.length)
+ delete this._breakpointsURLMap[breakpoint.url];
+
+ if (breakpoint.url in WebInspector.resourceURLMap) {
+ var resource = WebInspector.resourceURLMap[breakpoint.url];
+ sourceFrame = this._sourceFrameForScriptOrResource(resource);
+ }
+ }
+
+ if (breakpoint.sourceID && !sourceFrame) {
+ var object = this._sourceIDMap[breakpoint.sourceID]
+ sourceFrame = this._sourceFrameForScriptOrResource(object);
+ }
+
+ if (sourceFrame)
+ sourceFrame.removeBreakpoint(breakpoint);
+ },
+
+ evaluateInSelectedCallFrame: function(code, updateInterface)
+ {
+ var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
+ if (!this._paused || !selectedCallFrame)
+ return;
+ if (typeof updateInterface === "undefined")
+ updateInterface = true;
+ var result = selectedCallFrame.evaluate(code);
+ if (updateInterface)
+ this.sidebarPanes.scopechain.update(selectedCallFrame);
+ return result;
+ },
+
+ variablesInScopeForSelectedCallFrame: function()
+ {
+ var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
+ if (!this._paused || !selectedCallFrame)
+ return {};
+
+ var result = {};
+ var scopeChain = selectedCallFrame.scopeChain;
+ for (var i = 0; i < scopeChain.length; ++i) {
+ var scopeObject = scopeChain[i];
+ for (var property in scopeObject)
+ result[property] = true;
+ }
+
+ return result;
+ },
+
+ debuggerPaused: function()
+ {
+ this._paused = true;
+ this._waitingToPause = false;
+ this._stepping = false;
+
+ this._updateDebuggerButtons();
+
+ var callStackPane = this.sidebarPanes.callstack;
+ var currentFrame = InspectorController.currentCallFrame();
+ callStackPane.update(currentFrame, this._sourceIDMap);
+ callStackPane.selectedCallFrame = currentFrame;
+
+ WebInspector.currentPanel = this;
+ window.focus();
+ },
+
+ debuggerResumed: function()
+ {
+ this._paused = false;
+ this._waitingToPause = false;
+ this._stepping = false;
+
+ this._clearInterface();
+ },
+
+ attachDebuggerWhenShown: function()
+ {
+ if (this.element.parentElement) {
+ InspectorController.enableDebuggerFromFrontend(false);
+ } else {
+ this._attachDebuggerWhenShown = true;
+ }
+ },
+
+ debuggerWasEnabled: function()
+ {
+ this.reset();
+ },
+
+ debuggerWasDisabled: function()
+ {
+ this.reset();
+ },
+
+ reset: function()
+ {
+ this.visibleView = null;
+
+ delete this.currentQuery;
+ this.searchCanceled();
+
+ if (!InspectorController.debuggerEnabled()) {
+ this._paused = false;
+ this._waitingToPause = false;
+ this._stepping = false;
+ }
+
+ this._clearInterface();
+
+ this._backForwardList = [];
+ this._currentBackForwardIndex = -1;
+ this._updateBackAndForwardButtons();
+
+ this._scriptsForURLsInFilesSelect = {};
+ this.filesSelectElement.removeChildren();
+ this.functionsSelectElement.removeChildren();
+ this.viewsContainerElement.removeChildren();
+
+ if (this._sourceIDMap) {
+ for (var sourceID in this._sourceIDMap) {
+ var object = this._sourceIDMap[sourceID];
+ if (object instanceof WebInspector.Resource)
+ object.removeAllScripts();
+ }
+ }
+
+ this._sourceIDMap = {};
+ },
+
+ get visibleView()
+ {
+ return this._visibleView;
+ },
+
+ set visibleView(x)
+ {
+ if (this._visibleView === x)
+ return;
+
+ if (this._visibleView)
+ this._visibleView.hide();
+
+ this._visibleView = x;
+
+ if (x)
+ x.show(this.viewsContainerElement);
+ },
+
+ canShowResource: function(resource)
+ {
+ return resource && resource.scripts.length && InspectorController.debuggerEnabled();
+ },
+
+ showScript: function(script, line)
+ {
+ this._showScriptOrResource(script, line, true);
+ },
+
+ showResource: function(resource, line)
+ {
+ this._showScriptOrResource(resource, line, true);
+ },
+
+ showView: function(view)
+ {
+ if (!view)
+ return;
+ this._showScriptOrResource((view.resource || view.script));
+ },
+
+ scriptViewForScript: function(script)
+ {
+ if (!script)
+ return null;
+ if (!script._scriptView)
+ script._scriptView = new WebInspector.ScriptView(script);
+ return script._scriptView;
+ },
+
+ sourceFrameForScript: function(script)
+ {
+ var view = this.scriptViewForScript(script);
+ if (!view)
+ return null;
+
+ // Setting up the source frame requires that we be attached.
+ if (!this.element.parentNode)
+ this.attach();
+
+ view.setupSourceFrameIfNeeded();
+ return view.sourceFrame;
+ },
+
+ _sourceViewForScriptOrResource: function(scriptOrResource)
+ {
+ if (scriptOrResource instanceof WebInspector.Resource) {
+ if (!WebInspector.panels.resources)
+ return null;
+ return WebInspector.panels.resources.resourceViewForResource(scriptOrResource);
+ }
+ if (scriptOrResource instanceof WebInspector.Script)
+ return this.scriptViewForScript(scriptOrResource);
+ },
+
+ _sourceFrameForScriptOrResource: function(scriptOrResource)
+ {
+ if (scriptOrResource instanceof WebInspector.Resource) {
+ if (!WebInspector.panels.resources)
+ return null;
+ return WebInspector.panels.resources.sourceFrameForResource(scriptOrResource);
+ }
+ if (scriptOrResource instanceof WebInspector.Script)
+ return this.sourceFrameForScript(scriptOrResource);
+ },
+
+ _showScriptOrResource: function(scriptOrResource, line, shouldHighlightLine, fromBackForwardAction)
+ {
+ if (!scriptOrResource)
+ return;
+
+ var view;
+ if (scriptOrResource instanceof WebInspector.Resource) {
+ if (!WebInspector.panels.resources)
+ return null;
+ view = WebInspector.panels.resources.resourceViewForResource(scriptOrResource);
+ view.headersVisible = false;
+
+ if (scriptOrResource.url in this._breakpointsURLMap) {
+ var sourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource);
+ if (sourceFrame && !sourceFrame.breakpoints.length) {
+ var breakpoints = this._breakpointsURLMap[scriptOrResource.url];
+ var breakpointsLength = breakpoints.length;
+ for (var i = 0; i < breakpointsLength; ++i)
+ sourceFrame.addBreakpoint(breakpoints[i]);
+ }
+ }
+ } else if (scriptOrResource instanceof WebInspector.Script)
+ view = this.scriptViewForScript(scriptOrResource);
+
+ if (!view)
+ return;
+
+ if (!fromBackForwardAction) {
+ var oldIndex = this._currentBackForwardIndex;
+ if (oldIndex >= 0)
+ this._backForwardList.splice(oldIndex + 1, this._backForwardList.length - oldIndex);
+
+ // Check for a previous entry of the same object in _backForwardList.
+ // If one is found, remove it and update _currentBackForwardIndex to match.
+ var previousEntryIndex = this._backForwardList.indexOf(scriptOrResource);
+ if (previousEntryIndex !== -1) {
+ this._backForwardList.splice(previousEntryIndex, 1);
+ --this._currentBackForwardIndex;
+ }
+
+ this._backForwardList.push(scriptOrResource);
+ ++this._currentBackForwardIndex;
+
+ this._updateBackAndForwardButtons();
+ }
+
+ this.visibleView = view;
+
+ if (line) {
+ if (view.revealLine)
+ view.revealLine(line);
+ if (view.highlightLine && shouldHighlightLine)
+ view.highlightLine(line);
+ }
+
+ var option;
+ if (scriptOrResource instanceof WebInspector.Script) {
+ option = scriptOrResource.filesSelectOption;
+ console.assert(option);
+ } else {
+ var url = scriptOrResource.url;
+ var script = this._scriptsForURLsInFilesSelect[url];
+ if (script)
+ option = script.filesSelectOption;
+ }
+
+ if (option)
+ this.filesSelectElement.selectedIndex = option.index;
+ },
+
+ _addScriptToFilesMenu: function(script)
+ {
+ if (script.resource && this._scriptsForURLsInFilesSelect[script.sourceURL])
+ return;
+
+ this._scriptsForURLsInFilesSelect[script.sourceURL] = script;
+
+ var select = this.filesSelectElement;
+
+ var option = document.createElement("option");
+ option.representedObject = (script.resource || script);
+ option.text = (script.sourceURL ? WebInspector.displayNameForURL(script.sourceURL) : WebInspector.UIString("(program)"));
+
+ function optionCompare(a, b)
+ {
+ var aTitle = a.text.toLowerCase();
+ var bTitle = b.text.toLowerCase();
+ if (aTitle < bTitle)
+ return -1;
+ else if (aTitle > bTitle)
+ return 1;
+
+ var aSourceID = a.representedObject.sourceID;
+ var bSourceID = b.representedObject.sourceID;
+ if (aSourceID < bSourceID)
+ return -1;
+ else if (aSourceID > bSourceID)
+ return 1;
+ return 0;
+ }
+
+ var insertionIndex = insertionIndexForObjectInListSortedByFunction(option, select.childNodes, optionCompare);
+ if (insertionIndex < 0)
+ select.appendChild(option);
+ else
+ select.insertBefore(option, select.childNodes.item(insertionIndex));
+
+ script.filesSelectOption = option;
+
+ // Call _showScriptOrResource if the option we just appended ended up being selected.
+ // This will happen for the first item added to the menu.
+ if (select.options[select.selectedIndex] === option)
+ this._showScriptOrResource(option.representedObject);
+ },
+
+ _clearCurrentExecutionLine: function()
+ {
+ if (this._executionSourceFrame)
+ this._executionSourceFrame.executionLine = 0;
+ delete this._executionSourceFrame;
+ },
+
+ _callFrameSelected: function()
+ {
+ this._clearCurrentExecutionLine();
+
+ var callStackPane = this.sidebarPanes.callstack;
+ var currentFrame = callStackPane.selectedCallFrame;
+ if (!currentFrame)
+ return;
+
+ this.sidebarPanes.scopechain.update(currentFrame);
+
+ var scriptOrResource = this._sourceIDMap[currentFrame.sourceID];
+ this._showScriptOrResource(scriptOrResource, currentFrame.line);
+
+ this._executionSourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource);
+ if (this._executionSourceFrame)
+ this._executionSourceFrame.executionLine = currentFrame.line;
+ },
+
+ _changeVisibleFile: function(event)
+ {
+ var select = this.filesSelectElement;
+ this._showScriptOrResource(select.options[select.selectedIndex].representedObject);
+ },
+
+ _startSidebarResizeDrag: function(event)
+ {
+ WebInspector.elementDragStart(this.sidebarElement, this._sidebarResizeDrag.bind(this), this._endSidebarResizeDrag.bind(this), event, "col-resize");
+
+ if (event.target === this.sidebarResizeWidgetElement)
+ this._dragOffset = (event.target.offsetWidth - (event.pageX - event.target.totalOffsetLeft));
+ else
+ this._dragOffset = 0;
+ },
+
+ _endSidebarResizeDrag: function(event)
+ {
+ WebInspector.elementDragEnd(event);
+
+ delete this._dragOffset;
+ },
+
+ _sidebarResizeDrag: function(event)
+ {
+ var x = event.pageX + this._dragOffset;
+ var newWidth = Number.constrain(window.innerWidth - x, Preferences.minScriptsSidebarWidth, window.innerWidth * 0.66);
+
+ this.sidebarElement.style.width = newWidth + "px";
+ this.sidebarButtonsElement.style.width = newWidth + "px";
+ this.viewsContainerElement.style.right = newWidth + "px";
+ this.sidebarResizeWidgetElement.style.right = newWidth + "px";
+ this.sidebarResizeElement.style.right = (newWidth - 3) + "px";
+
+ event.preventDefault();
+ },
+
+ _updatePauseOnExceptionsButton: function()
+ {
+ if (InspectorController.pauseOnExceptions()) {
+ this.pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions.");
+ this.pauseOnExceptionButton.addStyleClass("toggled-on");
+ } else {
+ this.pauseOnExceptionButton.title = WebInspector.UIString("Pause on exceptions.");
+ this.pauseOnExceptionButton.removeStyleClass("toggled-on");
+ }
+ },
+
+ _updateDebuggerButtons: function()
+ {
+ if (InspectorController.debuggerEnabled()) {
+ this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable.");
+ this.enableToggleButton.addStyleClass("toggled-on");
+ this.pauseOnExceptionButton.removeStyleClass("hidden");
+ this.panelEnablerView.visible = false;
+ } else {
+ this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable.");
+ this.enableToggleButton.removeStyleClass("toggled-on");
+ this.pauseOnExceptionButton.addStyleClass("hidden");
+ this.panelEnablerView.visible = true;
+ }
+
+ this._updatePauseOnExceptionsButton();
+
+ if (this._paused) {
+ this.pauseButton.addStyleClass("paused");
+
+ this.pauseButton.disabled = false;
+ this.stepOverButton.disabled = false;
+ this.stepIntoButton.disabled = false;
+ this.stepOutButton.disabled = false;
+
+ this.debuggerStatusElement.textContent = WebInspector.UIString("Paused");
+ } else {
+ this.pauseButton.removeStyleClass("paused");
+
+ this.pauseButton.disabled = this._waitingToPause;
+ this.stepOverButton.disabled = true;
+ this.stepIntoButton.disabled = true;
+ this.stepOutButton.disabled = true;
+
+ if (this._waitingToPause)
+ this.debuggerStatusElement.textContent = WebInspector.UIString("Pausing");
+ else if (this._stepping)
+ this.debuggerStatusElement.textContent = WebInspector.UIString("Stepping");
+ else
+ this.debuggerStatusElement.textContent = "";
+ }
+ },
+
+ _updateBackAndForwardButtons: function()
+ {
+ this.backButton.disabled = this._currentBackForwardIndex <= 0;
+ this.forwardButton.disabled = this._currentBackForwardIndex >= (this._backForwardList.length - 1);
+ },
+
+ _clearInterface: function()
+ {
+ this.sidebarPanes.callstack.update(null);
+ this.sidebarPanes.scopechain.update(null);
+
+ this._clearCurrentExecutionLine();
+ this._updateDebuggerButtons();
+ },
+
+ _goBack: function()
+ {
+ if (this._currentBackForwardIndex <= 0) {
+ console.error("Can't go back from index " + this._currentBackForwardIndex);
+ return;
+ }
+
+ this._showScriptOrResource(this._backForwardList[--this._currentBackForwardIndex], null, false, true);
+ this._updateBackAndForwardButtons();
+ },
+
+ _goForward: function()
+ {
+ if (this._currentBackForwardIndex >= this._backForwardList.length - 1) {
+ console.error("Can't go forward from index " + this._currentBackForwardIndex);
+ return;
+ }
+
+ this._showScriptOrResource(this._backForwardList[++this._currentBackForwardIndex], null, false, true);
+ this._updateBackAndForwardButtons();
+ },
+
+ _enableDebugging: function()
+ {
+ if (InspectorController.debuggerEnabled())
+ return;
+ this._toggleDebugging(this.panelEnablerView.alwaysEnabled);
+ },
+
+ _toggleDebugging: function(optionalAlways)
+ {
+ this._paused = false;
+ this._waitingToPause = false;
+ this._stepping = false;
+
+ if (InspectorController.debuggerEnabled())
+ InspectorController.disableDebugger(true);
+ else
+ InspectorController.enableDebuggerFromFrontend(!!optionalAlways);
+ },
+
+ _togglePauseOnExceptions: function()
+ {
+ InspectorController.setPauseOnExceptions(!InspectorController.pauseOnExceptions());
+ this._updatePauseOnExceptionsButton();
+ },
+
+ _togglePause: function()
+ {
+ if (this._paused) {
+ this._paused = false;
+ this._waitingToPause = false;
+ InspectorController.resumeDebugger();
+ } else {
+ this._stepping = false;
+ this._waitingToPause = true;
+ InspectorController.pauseInDebugger();
+ }
+
+ this._clearInterface();
+ },
+
+ _stepOverClicked: function()
+ {
+ this._paused = false;
+ this._stepping = true;
+
+ this._clearInterface();
+
+ InspectorController.stepOverStatementInDebugger();
+ },
+
+ _stepIntoClicked: function()
+ {
+ this._paused = false;
+ this._stepping = true;
+
+ this._clearInterface();
+
+ InspectorController.stepIntoStatementInDebugger();
+ },
+
+ _stepOutClicked: function()
+ {
+ this._paused = false;
+ this._stepping = true;
+
+ this._clearInterface();
+
+ InspectorController.stepOutOfFunctionInDebugger();
+ }
+}
+
+WebInspector.ScriptsPanel.prototype.__proto__ = WebInspector.Panel.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/SidebarPane.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/SidebarPane.js
new file mode 100644
index 0000000..af9e5f9
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/SidebarPane.js
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SidebarPane = function(title)
+{
+ this.element = document.createElement("div");
+ this.element.className = "pane";
+
+ this.titleElement = document.createElement("div");
+ this.titleElement.className = "title";
+ this.titleElement.addEventListener("click", this.toggleExpanded.bind(this), false);
+
+ this.bodyElement = document.createElement("div");
+ this.bodyElement.className = "body";
+
+ this.element.appendChild(this.titleElement);
+ this.element.appendChild(this.bodyElement);
+
+ this.title = title;
+ this.growbarVisible = false;
+ this.expanded = false;
+}
+
+WebInspector.SidebarPane.prototype = {
+ get title()
+ {
+ return this._title;
+ },
+
+ set title(x)
+ {
+ if (this._title === x)
+ return;
+ this._title = x;
+ this.titleElement.textContent = x;
+ },
+
+ get growbarVisible()
+ {
+ return this._growbarVisible;
+ },
+
+ set growbarVisible(x)
+ {
+ if (this._growbarVisible === x)
+ return;
+
+ this._growbarVisible = x;
+
+ if (x && !this._growbarElement) {
+ this._growbarElement = document.createElement("div");
+ this._growbarElement.className = "growbar";
+ this.element.appendChild(this._growbarElement);
+ } else if (!x && this._growbarElement) {
+ if (this._growbarElement.parentNode)
+ this._growbarElement.parentNode(this._growbarElement);
+ delete this._growbarElement;
+ }
+ },
+
+ get expanded()
+ {
+ return this._expanded;
+ },
+
+ set expanded(x)
+ {
+ if (x)
+ this.expand();
+ else
+ this.collapse();
+ },
+
+ expand: function()
+ {
+ if (this._expanded)
+ return;
+ this._expanded = true;
+ this.element.addStyleClass("expanded");
+ if (this.onexpand)
+ this.onexpand(this);
+ },
+
+ collapse: function()
+ {
+ if (!this._expanded)
+ return;
+ this._expanded = false;
+ this.element.removeStyleClass("expanded");
+ if (this.oncollapse)
+ this.oncollapse(this);
+ },
+
+ toggleExpanded: function()
+ {
+ this.expanded = !this.expanded;
+ }
+}
+
+WebInspector.SidebarPane.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/SidebarTreeElement.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/SidebarTreeElement.js
new file mode 100644
index 0000000..c08b0ef
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/SidebarTreeElement.js
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SidebarSectionTreeElement = function(title, representedObject, hasChildren)
+{
+ TreeElement.call(this, title.escapeHTML(), representedObject || {}, hasChildren);
+}
+
+WebInspector.SidebarSectionTreeElement.prototype = {
+ selectable: false,
+
+ get smallChildren()
+ {
+ return this._smallChildren;
+ },
+
+ set smallChildren(x)
+ {
+ if (this._smallChildren === x)
+ return;
+
+ this._smallChildren = x;
+
+ if (this._smallChildren)
+ this._childrenListNode.addStyleClass("small");
+ else
+ this._childrenListNode.removeStyleClass("small");
+ },
+
+ onattach: function()
+ {
+ this._listItemNode.addStyleClass("sidebar-tree-section");
+ },
+
+ onreveal: function()
+ {
+ if (this.listItemElement)
+ this.listItemElement.scrollIntoViewIfNeeded(false);
+ }
+}
+
+WebInspector.SidebarSectionTreeElement.prototype.__proto__ = TreeElement.prototype;
+
+WebInspector.SidebarTreeElement = function(className, title, subtitle, representedObject, hasChildren)
+{
+ TreeElement.call(this, "", representedObject || {}, hasChildren);
+
+ if (hasChildren) {
+ this.disclosureButton = document.createElement("button");
+ this.disclosureButton.className = "disclosure-button";
+ }
+
+ if (!this.iconElement) {
+ this.iconElement = document.createElement("img");
+ this.iconElement.className = "icon";
+ }
+
+ this.statusElement = document.createElement("div");
+ this.statusElement.className = "status";
+
+ this.titlesElement = document.createElement("div");
+ this.titlesElement.className = "titles";
+
+ this.titleElement = document.createElement("span");
+ this.titleElement.className = "title";
+ this.titlesElement.appendChild(this.titleElement);
+
+ this.subtitleElement = document.createElement("span");
+ this.subtitleElement.className = "subtitle";
+ this.titlesElement.appendChild(this.subtitleElement);
+
+ this.className = className;
+ this.mainTitle = title;
+ this.subtitle = subtitle;
+}
+
+WebInspector.SidebarTreeElement.prototype = {
+ get small()
+ {
+ return this._small;
+ },
+
+ set small(x)
+ {
+ this._small = x;
+
+ if (this._listItemNode) {
+ if (this._small)
+ this._listItemNode.addStyleClass("small");
+ else
+ this._listItemNode.removeStyleClass("small");
+ }
+ },
+
+ get mainTitle()
+ {
+ return this._mainTitle;
+ },
+
+ set mainTitle(x)
+ {
+ this._mainTitle = x;
+ this.refreshTitles();
+ },
+
+ get subtitle()
+ {
+ return this._subtitle;
+ },
+
+ set subtitle(x)
+ {
+ this._subtitle = x;
+ this.refreshTitles();
+ },
+
+ get bubbleText()
+ {
+ return this._bubbleText;
+ },
+
+ set bubbleText(x)
+ {
+ if (!this.bubbleElement) {
+ this.bubbleElement = document.createElement("div");
+ this.bubbleElement.className = "bubble";
+ this.statusElement.appendChild(this.bubbleElement);
+ }
+
+ this._bubbleText = x;
+ this.bubbleElement.textContent = x;
+ },
+
+ refreshTitles: function()
+ {
+ var mainTitle = this.mainTitle;
+ if (this.titleElement.textContent !== mainTitle)
+ this.titleElement.textContent = mainTitle;
+
+ var subtitle = this.subtitle;
+ if (subtitle) {
+ if (this.subtitleElement.textContent !== subtitle)
+ this.subtitleElement.textContent = subtitle;
+ this.titlesElement.removeStyleClass("no-subtitle");
+ } else
+ this.titlesElement.addStyleClass("no-subtitle");
+ },
+
+ isEventWithinDisclosureTriangle: function(event)
+ {
+ return event.target === this.disclosureButton;
+ },
+
+ onattach: function()
+ {
+ this._listItemNode.addStyleClass("sidebar-tree-item");
+
+ if (this.className)
+ this._listItemNode.addStyleClass(this.className);
+
+ if (this.small)
+ this._listItemNode.addStyleClass("small");
+
+ if (this.hasChildren && this.disclosureButton)
+ this._listItemNode.appendChild(this.disclosureButton);
+
+ this._listItemNode.appendChild(this.iconElement);
+ this._listItemNode.appendChild(this.statusElement);
+ this._listItemNode.appendChild(this.titlesElement);
+ },
+
+ onreveal: function()
+ {
+ if (this._listItemNode)
+ this._listItemNode.scrollIntoViewIfNeeded(false);
+ }
+}
+
+WebInspector.SidebarTreeElement.prototype.__proto__ = TreeElement.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/SourceFrame.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/SourceFrame.js
new file mode 100644
index 0000000..18d9073
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/SourceFrame.js
@@ -0,0 +1,730 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SourceFrame = function(element, addBreakpointDelegate)
+{
+ this.messages = [];
+ this.breakpoints = [];
+
+ this.addBreakpointDelegate = addBreakpointDelegate;
+
+ this.element = element || document.createElement("iframe");
+ this.element.addStyleClass("source-view-frame");
+ this.element.setAttribute("viewsource", "true");
+
+ this.element.addEventListener("load", this._loaded.bind(this), false);
+}
+
+WebInspector.SourceFrame.prototype = {
+ get executionLine()
+ {
+ return this._executionLine;
+ },
+
+ set executionLine(x)
+ {
+ if (this._executionLine === x)
+ return;
+
+ var previousLine = this._executionLine;
+ this._executionLine = x;
+
+ this._updateExecutionLine(previousLine);
+ },
+
+ get autoSizesToFitContentHeight()
+ {
+ return this._autoSizesToFitContentHeight;
+ },
+
+ set autoSizesToFitContentHeight(x)
+ {
+ if (this._autoSizesToFitContentHeight === x)
+ return;
+
+ this._autoSizesToFitContentHeight = x;
+
+ if (this._autoSizesToFitContentHeight) {
+ this._windowResizeListener = this._windowResized.bind(this);
+ window.addEventListener("resize", this._windowResizeListener, false);
+ this.sizeToFitContentHeight();
+ } else {
+ this.element.style.removeProperty("height");
+ if (this.element.contentDocument)
+ this.element.contentDocument.body.removeStyleClass("webkit-height-sized-to-fit");
+ window.removeEventListener("resize", this._windowResizeListener, false);
+ delete this._windowResizeListener;
+ }
+ },
+
+ sourceRow: function(lineNumber)
+ {
+ if (!lineNumber || !this.element.contentDocument)
+ return;
+
+ var table = this.element.contentDocument.getElementsByTagName("table")[0];
+ if (!table)
+ return;
+
+ var rows = table.rows;
+
+ // Line numbers are a 1-based index, but the rows collection is 0-based.
+ --lineNumber;
+
+ return rows[lineNumber];
+ },
+
+ lineNumberForSourceRow: function(sourceRow)
+ {
+ // Line numbers are a 1-based index, but the rows collection is 0-based.
+ var lineNumber = 0;
+ while (sourceRow) {
+ ++lineNumber;
+ sourceRow = sourceRow.previousSibling;
+ }
+
+ return lineNumber;
+ },
+
+ revealLine: function(lineNumber)
+ {
+ if (!this._isContentLoaded()) {
+ this._lineNumberToReveal = lineNumber;
+ return;
+ }
+
+ var row = this.sourceRow(lineNumber);
+ if (row)
+ row.scrollIntoViewIfNeeded(true);
+ },
+
+ addBreakpoint: function(breakpoint)
+ {
+ this.breakpoints.push(breakpoint);
+ breakpoint.addEventListener("enabled", this._breakpointEnableChanged, this);
+ breakpoint.addEventListener("disabled", this._breakpointEnableChanged, this);
+ this._addBreakpointToSource(breakpoint);
+ },
+
+ removeBreakpoint: function(breakpoint)
+ {
+ this.breakpoints.remove(breakpoint);
+ breakpoint.removeEventListener("enabled", null, this);
+ breakpoint.removeEventListener("disabled", null, this);
+ this._removeBreakpointFromSource(breakpoint);
+ },
+
+ addMessage: function(msg)
+ {
+ // Don't add the message if there is no message or valid line or if the msg isn't an error or warning.
+ if (!msg.message || msg.line <= 0 || !msg.isErrorOrWarning())
+ return;
+ this.messages.push(msg);
+ this._addMessageToSource(msg);
+ },
+
+ clearMessages: function()
+ {
+ this.messages = [];
+
+ if (!this.element.contentDocument)
+ return;
+
+ var bubbles = this.element.contentDocument.querySelectorAll(".webkit-html-message-bubble");
+ if (!bubbles)
+ return;
+
+ for (var i = 0; i < bubbles.length; ++i) {
+ var bubble = bubbles[i];
+ bubble.parentNode.removeChild(bubble);
+ }
+ },
+
+ sizeToFitContentHeight: function()
+ {
+ if (this.element.contentDocument) {
+ this.element.style.setProperty("height", this.element.contentDocument.body.offsetHeight + "px");
+ this.element.contentDocument.body.addStyleClass("webkit-height-sized-to-fit");
+ }
+ },
+
+ _highlightLineEnds: function(event)
+ {
+ event.target.parentNode.removeStyleClass("webkit-highlighted-line");
+ },
+
+ highlightLine: function(lineNumber)
+ {
+ if (!this._isContentLoaded()) {
+ this._lineNumberToHighlight = lineNumber;
+ return;
+ }
+
+ var sourceRow = this.sourceRow(lineNumber);
+ if (!sourceRow)
+ return;
+ var line = sourceRow.getElementsByClassName('webkit-line-content')[0];
+ // Trick to reset the animation if the user clicks on the same link
+ // Using a timeout to avoid coalesced style updates
+ line.style.setProperty("-webkit-animation-name", "none");
+ setTimeout(function () {
+ line.style.removeProperty("-webkit-animation-name");
+ sourceRow.addStyleClass("webkit-highlighted-line");
+ }, 0);
+ },
+
+ _loaded: function()
+ {
+ WebInspector.addMainEventListeners(this.element.contentDocument);
+ this.element.contentDocument.addEventListener("mousedown", this._documentMouseDown.bind(this), true);
+ this.element.contentDocument.addEventListener("webkitAnimationEnd", this._highlightLineEnds.bind(this), false);
+
+ var headElement = this.element.contentDocument.getElementsByTagName("head")[0];
+ if (!headElement) {
+ headElement = this.element.contentDocument.createElement("head");
+ this.element.contentDocument.documentElement.insertBefore(headElement, this.element.contentDocument.documentElement.firstChild);
+ }
+
+ var styleElement = this.element.contentDocument.createElement("style");
+ headElement.appendChild(styleElement);
+
+ // Add these style rules here since they are specific to the Inspector. They also behave oddly and not
+ // all properties apply if added to view-source.css (becuase it is a user agent sheet.)
+ var styleText = ".webkit-line-number { background-repeat: no-repeat; background-position: right 1px; }\n";
+ styleText += ".webkit-breakpoint .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint); }\n";
+ styleText += ".webkit-breakpoint-disabled .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint-disabled); }\n";
+ styleText += ".webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(program-counter); }\n";
+ styleText += ".webkit-breakpoint.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-program-counter); }\n";
+ styleText += ".webkit-breakpoint-disabled.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-disabled-program-counter); }\n";
+ styleText += ".webkit-execution-line .webkit-line-content { background-color: rgb(171, 191, 254); outline: 1px solid rgb(64, 115, 244); }\n";
+ styleText += ".webkit-height-sized-to-fit { overflow-y: hidden }\n";
+ styleText += ".webkit-line-content { background-color: white; }\n";
+ styleText += "@-webkit-keyframes fadeout {from {background-color: rgb(255, 255, 120);} to { background-color: white;}}\n";
+ styleText += ".webkit-highlighted-line .webkit-line-content { background-color: rgb(255, 255, 120); -webkit-animation: 'fadeout' 2s 500ms}\n";
+ styleText += ".webkit-javascript-comment { color: rgb(0, 116, 0); }\n";
+ styleText += ".webkit-javascript-keyword { color: rgb(170, 13, 145); }\n";
+ styleText += ".webkit-javascript-number { color: rgb(28, 0, 207); }\n";
+ styleText += ".webkit-javascript-string, .webkit-javascript-regexp { color: rgb(196, 26, 22); }\n";
+
+ styleElement.textContent = styleText;
+
+ this._needsProgramCounterImage = true;
+ this._needsBreakpointImages = true;
+
+ this.element.contentWindow.Element.prototype.addStyleClass = Element.prototype.addStyleClass;
+ this.element.contentWindow.Element.prototype.removeStyleClass = Element.prototype.removeStyleClass;
+ this.element.contentWindow.Element.prototype.removeMatchingStyleClasses = Element.prototype.removeMatchingStyleClasses;
+ this.element.contentWindow.Element.prototype.hasStyleClass = Element.prototype.hasStyleClass;
+ this.element.contentWindow.Node.prototype.enclosingNodeOrSelfWithNodeName = Node.prototype.enclosingNodeOrSelfWithNodeName;
+ this.element.contentWindow.Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = Node.prototype.enclosingNodeOrSelfWithNodeNameInArray;
+
+ this._addExistingMessagesToSource();
+ this._addExistingBreakpointsToSource();
+ this._updateExecutionLine();
+ if (this._executionLine)
+ this.revealLine(this._executionLine);
+
+ if (this.autoSizesToFitContentHeight)
+ this.sizeToFitContentHeight();
+
+ if (this._lineNumberToReveal) {
+ this.revealLine(this._lineNumberToReveal);
+ delete this._lineNumberToReveal;
+ }
+
+ if (this._lineNumberToHighlight) {
+ this.highlightLine(this._lineNumberToHighlight);
+ delete this._lineNumberToHighlight;
+ }
+
+ this.dispatchEventToListeners("content loaded");
+ },
+
+ _isContentLoaded: function() {
+ var doc = this.element.contentDocument;
+ return doc && doc.getElementsByTagName("table")[0];
+ },
+
+ _windowResized: function(event)
+ {
+ if (!this._autoSizesToFitContentHeight)
+ return;
+ this.sizeToFitContentHeight();
+ },
+
+ _documentMouseDown: function(event)
+ {
+ if (!event.target.hasStyleClass("webkit-line-number"))
+ return;
+
+ var sourceRow = event.target.enclosingNodeOrSelfWithNodeName("tr");
+ if (sourceRow._breakpointObject)
+ sourceRow._breakpointObject.enabled = !sourceRow._breakpointObject.enabled;
+ else if (this.addBreakpointDelegate)
+ this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow));
+ },
+
+ _breakpointEnableChanged: function(event)
+ {
+ var breakpoint = event.target;
+ var sourceRow = this.sourceRow(breakpoint.line);
+ if (!sourceRow)
+ return;
+
+ sourceRow.addStyleClass("webkit-breakpoint");
+
+ if (breakpoint.enabled)
+ sourceRow.removeStyleClass("webkit-breakpoint-disabled");
+ else
+ sourceRow.addStyleClass("webkit-breakpoint-disabled");
+ },
+
+ _updateExecutionLine: function(previousLine)
+ {
+ if (previousLine) {
+ var sourceRow = this.sourceRow(previousLine);
+ if (sourceRow)
+ sourceRow.removeStyleClass("webkit-execution-line");
+ }
+
+ if (!this._executionLine)
+ return;
+
+ this._drawProgramCounterImageIfNeeded();
+
+ var sourceRow = this.sourceRow(this._executionLine);
+ if (sourceRow)
+ sourceRow.addStyleClass("webkit-execution-line");
+ },
+
+ _addExistingBreakpointsToSource: function()
+ {
+ var length = this.breakpoints.length;
+ for (var i = 0; i < length; ++i)
+ this._addBreakpointToSource(this.breakpoints[i]);
+ },
+
+ _addBreakpointToSource: function(breakpoint)
+ {
+ var sourceRow = this.sourceRow(breakpoint.line);
+ if (!sourceRow)
+ return;
+
+ this._drawBreakpointImagesIfNeeded();
+
+ sourceRow._breakpointObject = breakpoint;
+
+ sourceRow.addStyleClass("webkit-breakpoint");
+ if (!breakpoint.enabled)
+ sourceRow.addStyleClass("webkit-breakpoint-disabled");
+ },
+
+ _removeBreakpointFromSource: function(breakpoint)
+ {
+ var sourceRow = this.sourceRow(breakpoint.line);
+ if (!sourceRow)
+ return;
+
+ delete sourceRow._breakpointObject;
+
+ sourceRow.removeStyleClass("webkit-breakpoint");
+ sourceRow.removeStyleClass("webkit-breakpoint-disabled");
+ },
+
+ _incrementMessageRepeatCount: function(msg, repeatDelta)
+ {
+ if (!msg._resourceMessageLineElement)
+ return;
+
+ if (!msg._resourceMessageRepeatCountElement) {
+ var repeatedElement = document.createElement("span");
+ msg._resourceMessageLineElement.appendChild(repeatedElement);
+ msg._resourceMessageRepeatCountElement = repeatedElement;
+ }
+
+ msg.repeatCount += repeatDelta;
+ msg._resourceMessageRepeatCountElement.textContent = WebInspector.UIString(" (repeated %d times)", msg.repeatCount);
+ },
+
+ _addExistingMessagesToSource: function()
+ {
+ var length = this.messages.length;
+ for (var i = 0; i < length; ++i)
+ this._addMessageToSource(this.messages[i]);
+ },
+
+ _addMessageToSource: function(msg)
+ {
+ var row = this.sourceRow(msg.line);
+ if (!row)
+ return;
+
+ var cell = row.cells[1];
+ if (!cell)
+ return;
+
+ var messageBubbleElement = cell.lastChild;
+ if (!messageBubbleElement || messageBubbleElement.nodeType !== Node.ELEMENT_NODE || !messageBubbleElement.hasStyleClass("webkit-html-message-bubble")) {
+ messageBubbleElement = this.element.contentDocument.createElement("div");
+ messageBubbleElement.className = "webkit-html-message-bubble";
+ cell.appendChild(messageBubbleElement);
+ }
+
+ if (!row.messages)
+ row.messages = [];
+
+ for (var i = 0; i < row.messages.length; ++i) {
+ if (row.messages[i].isEqual(msg, true)) {
+ this._incrementMessageRepeatCount(row.messages[i], msg.repeatDelta);
+ return;
+ }
+ }
+
+ row.messages.push(msg);
+
+ var imageURL;
+ switch (msg.level) {
+ case WebInspector.ConsoleMessage.MessageLevel.Error:
+ messageBubbleElement.addStyleClass("webkit-html-error-message");
+ imageURL = "Images/errorIcon.png";
+ break;
+ case WebInspector.ConsoleMessage.MessageLevel.Warning:
+ messageBubbleElement.addStyleClass("webkit-html-warning-message");
+ imageURL = "Images/warningIcon.png";
+ break;
+ }
+
+ var messageLineElement = this.element.contentDocument.createElement("div");
+ messageLineElement.className = "webkit-html-message-line";
+ messageBubbleElement.appendChild(messageLineElement);
+
+ // Create the image element in the Inspector's document so we can use relative image URLs.
+ var image = document.createElement("img");
+ image.src = imageURL;
+ image.className = "webkit-html-message-icon";
+
+ // Adopt the image element since it wasn't created in element's contentDocument.
+ image = this.element.contentDocument.adoptNode(image);
+ messageLineElement.appendChild(image);
+ messageLineElement.appendChild(this.element.contentDocument.createTextNode(msg.message));
+
+ msg._resourceMessageLineElement = messageLineElement;
+ },
+
+ _drawProgramCounterInContext: function(ctx, glow)
+ {
+ if (glow)
+ ctx.save();
+
+ ctx.beginPath();
+ ctx.moveTo(17, 2);
+ ctx.lineTo(19, 2);
+ ctx.lineTo(19, 0);
+ ctx.lineTo(21, 0);
+ ctx.lineTo(26, 5.5);
+ ctx.lineTo(21, 11);
+ ctx.lineTo(19, 11);
+ ctx.lineTo(19, 9);
+ ctx.lineTo(17, 9);
+ ctx.closePath();
+ ctx.fillStyle = "rgb(142, 5, 4)";
+
+ if (glow) {
+ ctx.shadowBlur = 4;
+ ctx.shadowColor = "rgb(255, 255, 255)";
+ ctx.shadowOffsetX = -1;
+ ctx.shadowOffsetY = 0;
+ }
+
+ ctx.fill();
+ ctx.fill(); // Fill twice to get a good shadow and darker anti-aliased pixels.
+
+ if (glow)
+ ctx.restore();
+ },
+
+ _drawProgramCounterImageIfNeeded: function()
+ {
+ if (!this._needsProgramCounterImage || !this.element.contentDocument)
+ return;
+
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "program-counter", 26, 11);
+ ctx.clearRect(0, 0, 26, 11);
+ this._drawProgramCounterInContext(ctx, true);
+
+ delete this._needsProgramCounterImage;
+ },
+
+ _drawBreakpointImagesIfNeeded: function()
+ {
+ if (!this._needsBreakpointImages || !this.element.contentDocument)
+ return;
+
+ function drawBreakpoint(ctx, disabled)
+ {
+ ctx.beginPath();
+ ctx.moveTo(0, 2);
+ ctx.lineTo(2, 0);
+ ctx.lineTo(21, 0);
+ ctx.lineTo(26, 5.5);
+ ctx.lineTo(21, 11);
+ ctx.lineTo(2, 11);
+ ctx.lineTo(0, 9);
+ ctx.closePath();
+ ctx.fillStyle = "rgb(1, 142, 217)";
+ ctx.strokeStyle = "rgb(0, 103, 205)";
+ ctx.lineWidth = 3;
+ ctx.fill();
+ ctx.save();
+ ctx.clip();
+ ctx.stroke();
+ ctx.restore();
+
+ if (!disabled)
+ return;
+
+ ctx.save();
+ ctx.globalCompositeOperation = "destination-out";
+ ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
+ ctx.fillRect(0, 0, 26, 11);
+ ctx.restore();
+ }
+
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint", 26, 11);
+ ctx.clearRect(0, 0, 26, 11);
+ drawBreakpoint(ctx);
+
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-program-counter", 26, 11);
+ ctx.clearRect(0, 0, 26, 11);
+ drawBreakpoint(ctx);
+ ctx.clearRect(20, 0, 6, 11);
+ this._drawProgramCounterInContext(ctx, true);
+
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-disabled", 26, 11);
+ ctx.clearRect(0, 0, 26, 11);
+ drawBreakpoint(ctx, true);
+
+ var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-disabled-program-counter", 26, 11);
+ ctx.clearRect(0, 0, 26, 11);
+ drawBreakpoint(ctx, true);
+ ctx.clearRect(20, 0, 6, 11);
+ this._drawProgramCounterInContext(ctx, true);
+
+ delete this._needsBreakpointImages;
+ },
+
+ syntaxHighlightJavascript: function()
+ {
+ var table = this.element.contentDocument.getElementsByTagName("table")[0];
+ if (!table)
+ return;
+
+ function deleteContinueFlags(cell)
+ {
+ if (!cell)
+ return;
+ delete cell._commentContinues;
+ delete cell._singleQuoteStringContinues;
+ delete cell._doubleQuoteStringContinues;
+ delete cell._regexpContinues;
+ }
+
+ function createSpan(content, className)
+ {
+ var span = document.createElement("span");
+ span.className = className;
+ span.appendChild(document.createTextNode(content));
+ return span;
+ }
+
+ function generateFinder(regex, matchNumber, className)
+ {
+ return function(str) {
+ var match = regex.exec(str);
+ if (!match)
+ return null;
+ previousMatchLength = match[matchNumber].length;
+ return createSpan(match[matchNumber], className);
+ };
+ }
+
+ var findNumber = generateFinder(/^(-?(\d+\.?\d*([eE][+-]\d+)?|0[xX]\h+|Infinity)|NaN)(?:\W|$)/, 1, "webkit-javascript-number");
+ var findKeyword = generateFinder(/^(null|true|false|break|case|catch|const|default|finally|for|instanceof|new|var|continue|function|return|void|delete|if|this|do|while|else|in|switch|throw|try|typeof|with|debugger|class|enum|export|extends|import|super|get|set)(?:\W|$)/, 1, "webkit-javascript-keyword");
+ var findSingleLineString = generateFinder(/^"(?:[^"\\]|\\.)*"|^'([^'\\]|\\.)*'/, 0, "webkit-javascript-string"); // " this quote keeps Xcode happy
+ var findMultilineCommentStart = generateFinder(/^\/\*.*$/, 0, "webkit-javascript-comment");
+ var findMultilineCommentEnd = generateFinder(/^.*?\*\//, 0, "webkit-javascript-comment");
+ var findMultilineSingleQuoteStringStart = generateFinder(/^'(?:[^'\\]|\\.)*\\$/, 0, "webkit-javascript-string");
+ var findMultilineSingleQuoteStringEnd = generateFinder(/^(?:[^'\\]|\\.)*?'/, 0, "webkit-javascript-string");
+ var findMultilineDoubleQuoteStringStart = generateFinder(/^"(?:[^"\\]|\\.)*\\$/, 0, "webkit-javascript-string");
+ var findMultilineDoubleQuoteStringEnd = generateFinder(/^(?:[^"\\]|\\.)*?"/, 0, "webkit-javascript-string");
+ var findMultilineRegExpEnd = generateFinder(/^(?:[^\/\\]|\\.)*?\/([gim]{0,3})/, 0, "webkit-javascript-regexp");
+ var findSingleLineComment = generateFinder(/^\/\/.*|^\/\*.*?\*\//, 0, "webkit-javascript-comment");
+
+ function findMultilineRegExpStart(str)
+ {
+ var match = /^\/(?:[^\/\\]|\\.)*\\$/.exec(str);
+ if (!match || !/\\|\$|\.[\?\*\+]|[^\|]\|[^\|]/.test(match[0]))
+ return null;
+ var node = createSpan(match[0], "webkit-javascript-regexp");
+ previousMatchLength = match[0].length;
+ return node;
+ }
+
+ function findSingleLineRegExp(str)
+ {
+ var match = /^(\/(?:[^\/\\]|\\.)*\/([gim]{0,3}))(.?)/.exec(str);
+ if (!match || !(match[2].length > 0 || /\\|\$|\.[\?\*\+]|[^\|]\|[^\|]/.test(match[1]) || /\.|;|,/.test(match[3])))
+ return null;
+ var node = createSpan(match[1], "webkit-javascript-regexp");
+ previousMatchLength = match[1].length;
+ return node;
+ }
+
+ function syntaxHighlightJavascriptLine(line, prevLine)
+ {
+ var messageBubble = line.lastChild;
+ if (messageBubble && messageBubble.nodeType === Node.ELEMENT_NODE && messageBubble.hasStyleClass("webkit-html-message-bubble"))
+ line.removeChild(messageBubble);
+ else
+ messageBubble = null;
+
+ var code = line.textContent;
+
+ while (line.firstChild)
+ line.removeChild(line.firstChild);
+
+ var token;
+ var tmp = 0;
+ var i = 0;
+ previousMatchLength = 0;
+
+ if (prevLine) {
+ if (prevLine._commentContinues) {
+ if (!(token = findMultilineCommentEnd(code))) {
+ token = createSpan(code, "webkit-javascript-comment");
+ line._commentContinues = true;
+ }
+ } else if (prevLine._singleQuoteStringContinues) {
+ if (!(token = findMultilineSingleQuoteStringEnd(code))) {
+ token = createSpan(code, "webkit-javascript-string");
+ line._singleQuoteStringContinues = true;
+ }
+ } else if (prevLine._doubleQuoteStringContinues) {
+ if (!(token = findMultilineDoubleQuoteStringEnd(code))) {
+ token = createSpan(code, "webkit-javascript-string");
+ line._doubleQuoteStringContinues = true;
+ }
+ } else if (prevLine._regexpContinues) {
+ if (!(token = findMultilineRegExpEnd(code))) {
+ token = createSpan(code, "webkit-javascript-regexp");
+ line._regexpContinues = true;
+ }
+ }
+ if (token) {
+ i += previousMatchLength ? previousMatchLength : code.length;
+ tmp = i;
+ line.appendChild(token);
+ }
+ }
+
+ for ( ; i < code.length; ++i) {
+ var codeFragment = code.substr(i);
+ var prevChar = code[i - 1];
+ token = findSingleLineComment(codeFragment);
+ if (!token) {
+ if ((token = findMultilineCommentStart(codeFragment)))
+ line._commentContinues = true;
+ else if (!prevChar || /^\W/.test(prevChar)) {
+ token = findNumber(codeFragment, code[i - 1]) ||
+ findKeyword(codeFragment, code[i - 1]) ||
+ findSingleLineString(codeFragment) ||
+ findSingleLineRegExp(codeFragment);
+ if (!token) {
+ if (token = findMultilineSingleQuoteStringStart(codeFragment))
+ line._singleQuoteStringContinues = true;
+ else if (token = findMultilineDoubleQuoteStringStart(codeFragment))
+ line._doubleQuoteStringContinues = true;
+ else if (token = findMultilineRegExpStart(codeFragment))
+ line._regexpContinues = true;
+ }
+ }
+ }
+
+ if (token) {
+ if (tmp !== i)
+ line.appendChild(document.createTextNode(code.substring(tmp, i)));
+ line.appendChild(token);
+ i += previousMatchLength - 1;
+ tmp = i + 1;
+ }
+ }
+
+ if (tmp < code.length)
+ line.appendChild(document.createTextNode(code.substring(tmp, i)));
+
+ if (messageBubble)
+ line.appendChild(messageBubble);
+ }
+
+ var i = 0;
+ var rows = table.rows;
+ var rowsLength = rows.length;
+ var previousCell = null;
+ var previousMatchLength = 0;
+ var sourceFrame = this;
+
+ // Split up the work into chunks so we don't block the
+ // UI thread while processing.
+
+ function processChunk()
+ {
+ for (var end = Math.min(i + 10, rowsLength); i < end; ++i) {
+ var row = rows[i];
+ if (!row)
+ continue;
+ var cell = row.cells[1];
+ if (!cell)
+ continue;
+ syntaxHighlightJavascriptLine(cell, previousCell);
+ if (i < (end - 1))
+ deleteContinueFlags(previousCell);
+ previousCell = cell;
+ }
+
+ if (i >= rowsLength && processChunkInterval) {
+ deleteContinueFlags(previousCell);
+ clearInterval(processChunkInterval);
+
+ sourceFrame.dispatchEventToListeners("syntax highlighting complete");
+ }
+ }
+
+ processChunk();
+
+ var processChunkInterval = setInterval(processChunk, 25);
+ }
+}
+
+WebInspector.SourceFrame.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/SourceView.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/SourceView.js
new file mode 100644
index 0000000..7510c8c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/SourceView.js
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SourceView = function(resource)
+{
+ // Set the sourceFrame first since WebInspector.ResourceView will set headersVisible
+ // and our override of headersVisible needs the sourceFrame.
+ this.sourceFrame = new WebInspector.SourceFrame(null, this._addBreakpoint.bind(this));
+
+ WebInspector.ResourceView.call(this, resource);
+
+ resource.addEventListener("finished", this._resourceLoadingFinished, this);
+
+ this.element.addStyleClass("source");
+
+ this._frameNeedsSetup = true;
+
+ this.contentElement.appendChild(this.sourceFrame.element);
+
+ var gutterElement = document.createElement("div");
+ gutterElement.className = "webkit-line-gutter-backdrop";
+ this.element.appendChild(gutterElement);
+}
+
+WebInspector.SourceView.prototype = {
+ set headersVisible(x)
+ {
+ if (x === this._headersVisible)
+ return;
+
+ var superSetter = WebInspector.ResourceView.prototype.__lookupSetter__("headersVisible");
+ if (superSetter)
+ superSetter.call(this, x);
+
+ this.sourceFrame.autoSizesToFitContentHeight = x;
+ },
+
+ show: function(parentElement)
+ {
+ WebInspector.ResourceView.prototype.show.call(this, parentElement);
+ this.setupSourceFrameIfNeeded();
+ },
+
+ hide: function()
+ {
+ WebInspector.View.prototype.hide.call(this);
+ this._currentSearchResultIndex = -1;
+ },
+
+ resize: function()
+ {
+ if (this.sourceFrame.autoSizesToFitContentHeight)
+ this.sourceFrame.sizeToFitContentHeight();
+ },
+
+ detach: function()
+ {
+ WebInspector.ResourceView.prototype.detach.call(this);
+
+ // FIXME: We need to mark the frame for setup on detach because the frame DOM is cleared
+ // when it is removed from the document. Is this a bug?
+ this._frameNeedsSetup = true;
+ this._sourceFrameSetup = false;
+ },
+
+ setupSourceFrameIfNeeded: function()
+ {
+ if (!this._frameNeedsSetup)
+ return;
+
+ this.attach();
+
+ delete this._frameNeedsSetup;
+ this.sourceFrame.addEventListener("content loaded", this._contentLoaded, this);
+ InspectorController.addResourceSourceToFrame(this.resource.identifier, this.sourceFrame.element);
+ },
+
+ _contentLoaded: function()
+ {
+ delete this._frameNeedsSetup;
+ this.sourceFrame.removeEventListener("content loaded", this._contentLoaded, this);
+
+ if (this.resource.type === WebInspector.Resource.Type.Script) {
+ this.sourceFrame.addEventListener("syntax highlighting complete", this._syntaxHighlightingComplete, this);
+ this.sourceFrame.syntaxHighlightJavascript();
+ } else
+ this._sourceFrameSetupFinished();
+ },
+
+ _resourceLoadingFinished: function(event)
+ {
+ this._frameNeedsSetup = true;
+ this._sourceFrameSetup = false;
+ if (this.visible)
+ this.setupSourceFrameIfNeeded();
+ this.resource.removeEventListener("finished", this._resourceLoadingFinished, this);
+ },
+
+ _addBreakpoint: function(line)
+ {
+ var sourceID = null;
+ var closestStartingLine = 0;
+ var scripts = this.resource.scripts;
+ for (var i = 0; i < scripts.length; ++i) {
+ var script = scripts[i];
+ if (script.startingLine <= line && script.startingLine >= closestStartingLine) {
+ closestStartingLine = script.startingLine;
+ sourceID = script.sourceID;
+ }
+ }
+
+ if (WebInspector.panels.scripts) {
+ var breakpoint = new WebInspector.Breakpoint(this.resource.url, line, sourceID);
+ WebInspector.panels.scripts.addBreakpoint(breakpoint);
+ }
+ },
+
+ // The rest of the methods in this prototype need to be generic enough to work with a ScriptView.
+ // The ScriptView prototype pulls these methods into it's prototype to avoid duplicate code.
+
+ searchCanceled: function()
+ {
+ this._currentSearchResultIndex = -1;
+ this._searchResults = [];
+ delete this._delayedFindSearchMatches;
+ },
+
+ performSearch: function(query, finishedCallback)
+ {
+ // Call searchCanceled since it will reset everything we need before doing a new search.
+ this.searchCanceled();
+
+ var lineQueryRegex = /(^|\s)(?:#|line:\s*)(\d+)(\s|$)/i;
+ var lineQueryMatch = query.match(lineQueryRegex);
+ if (lineQueryMatch) {
+ var lineToSearch = parseInt(lineQueryMatch[2]);
+
+ // If there was a space before and after the line query part, replace with a space.
+ // Otherwise replace with an empty string to eat the prefix or postfix space.
+ var lineQueryReplacement = (lineQueryMatch[1] && lineQueryMatch[3] ? " " : "");
+ var filterlessQuery = query.replace(lineQueryRegex, lineQueryReplacement);
+ }
+
+ this._searchFinishedCallback = finishedCallback;
+
+ function findSearchMatches(query, finishedCallback)
+ {
+ if (isNaN(lineToSearch)) {
+ // Search the whole document since there was no line to search.
+ this._searchResults = (InspectorController.search(this.sourceFrame.element.contentDocument, query) || []);
+ } else {
+ var sourceRow = this.sourceFrame.sourceRow(lineToSearch);
+ if (sourceRow) {
+ if (filterlessQuery) {
+ // There is still a query string, so search for that string in the line.
+ this._searchResults = (InspectorController.search(sourceRow, filterlessQuery) || []);
+ } else {
+ // Match the whole line, since there was no remaining query string to match.
+ var rowRange = this.sourceFrame.element.contentDocument.createRange();
+ rowRange.selectNodeContents(sourceRow);
+ this._searchResults = [rowRange];
+ }
+ }
+
+ // Attempt to search for the whole query, just incase it matches a color like "#333".
+ var wholeQueryMatches = InspectorController.search(this.sourceFrame.element.contentDocument, query);
+ if (wholeQueryMatches)
+ this._searchResults = this._searchResults.concat(wholeQueryMatches);
+ }
+
+ if (this._searchResults)
+ finishedCallback(this, this._searchResults.length);
+ }
+
+ if (!this._sourceFrameSetup) {
+ // The search is performed in _sourceFrameSetupFinished by calling _delayedFindSearchMatches.
+ this._delayedFindSearchMatches = findSearchMatches.bind(this, query, finishedCallback);
+ this.setupSourceFrameIfNeeded();
+ return;
+ }
+
+ findSearchMatches.call(this, query, finishedCallback);
+ },
+
+ jumpToFirstSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ this._currentSearchResultIndex = 0;
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToLastSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ this._currentSearchResultIndex = (this._searchResults.length - 1);
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToNextSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ if (++this._currentSearchResultIndex >= this._searchResults.length)
+ this._currentSearchResultIndex = 0;
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToPreviousSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ if (--this._currentSearchResultIndex < 0)
+ this._currentSearchResultIndex = (this._searchResults.length - 1);
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ showingFirstSearchResult: function()
+ {
+ return (this._currentSearchResultIndex === 0);
+ },
+
+ showingLastSearchResult: function()
+ {
+ return (this._searchResults && this._currentSearchResultIndex === (this._searchResults.length - 1));
+ },
+
+ revealLine: function(lineNumber)
+ {
+ this.setupSourceFrameIfNeeded();
+ this.sourceFrame.revealLine(lineNumber);
+ },
+
+ highlightLine: function(lineNumber)
+ {
+ this.setupSourceFrameIfNeeded();
+ this.sourceFrame.highlightLine(lineNumber);
+ },
+
+ addMessage: function(msg)
+ {
+ this.sourceFrame.addMessage(msg);
+ },
+
+ clearMessages: function()
+ {
+ this.sourceFrame.clearMessages();
+ },
+
+ _jumpToSearchResult: function(index)
+ {
+ var foundRange = this._searchResults[index];
+ if (!foundRange)
+ return;
+
+ var selection = this.sourceFrame.element.contentWindow.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(foundRange);
+
+ if (foundRange.startContainer.scrollIntoViewIfNeeded)
+ foundRange.startContainer.scrollIntoViewIfNeeded(true);
+ else if (foundRange.startContainer.parentNode)
+ foundRange.startContainer.parentNode.scrollIntoViewIfNeeded(true);
+ },
+
+ _sourceFrameSetupFinished: function()
+ {
+ this._sourceFrameSetup = true;
+ if (this._delayedFindSearchMatches) {
+ this._delayedFindSearchMatches();
+ delete this._delayedFindSearchMatches;
+ }
+ },
+
+ _syntaxHighlightingComplete: function(event)
+ {
+ this._sourceFrameSetupFinished();
+ this.sourceFrame.removeEventListener("syntax highlighting complete", null, this);
+ }
+}
+
+WebInspector.SourceView.prototype.__proto__ = WebInspector.ResourceView.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/StylesSidebarPane.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/StylesSidebarPane.js
new file mode 100644
index 0000000..c30444b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/StylesSidebarPane.js
@@ -0,0 +1,927 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.StylesSidebarPane = function()
+{
+ WebInspector.SidebarPane.call(this, WebInspector.UIString("Styles"));
+}
+
+WebInspector.StylesSidebarPane.prototype = {
+ update: function(node, editedSection, forceUpdate)
+ {
+ var refresh = false;
+
+ if (forceUpdate)
+ delete this.node;
+
+ if (!forceUpdate && (!node || node === this.node))
+ refresh = true;
+
+ if (node && node.nodeType === Node.TEXT_NODE && node.parentNode)
+ node = node.parentNode;
+
+ if (node && node.nodeType !== Node.ELEMENT_NODE)
+ node = null;
+
+ if (node)
+ this.node = node;
+ else
+ node = this.node;
+
+ var body = this.bodyElement;
+ if (!refresh || !node) {
+ body.removeChildren();
+ this.sections = [];
+ }
+
+ if (!node)
+ return;
+
+ var styleRules = [];
+
+ if (refresh) {
+ for (var i = 0; i < this.sections.length; ++i) {
+ var section = this.sections[i];
+ if (section.computedStyle)
+ section.styleRule.style = node.ownerDocument.defaultView.getComputedStyle(node);
+ var styleRule = { section: section, style: section.styleRule.style, computedStyle: section.computedStyle };
+ styleRules.push(styleRule);
+ }
+ } else {
+ var computedStyle = node.ownerDocument.defaultView.getComputedStyle(node);
+ styleRules.push({ computedStyle: true, selectorText: WebInspector.UIString("Computed Style"), style: computedStyle, editable: false });
+
+ var nodeName = node.nodeName.toLowerCase();
+ for (var i = 0; i < node.attributes.length; ++i) {
+ var attr = node.attributes[i];
+ if (attr.style) {
+ var attrStyle = { style: attr.style, editable: false };
+ attrStyle.subtitle = WebInspector.UIString("element’s “%s” attribute", attr.name);
+ attrStyle.selectorText = nodeName + "[" + attr.name;
+ if (attr.value.length)
+ attrStyle.selectorText += "=" + attr.value;
+ attrStyle.selectorText += "]";
+ styleRules.push(attrStyle);
+ }
+ }
+
+ if (node.style && (node.style.length || Object.hasProperties(node.style.__disabledProperties))) {
+ var inlineStyle = { selectorText: WebInspector.UIString("Inline Style Attribute"), style: node.style };
+ inlineStyle.subtitle = WebInspector.UIString("element’s “%s” attribute", "style");
+ styleRules.push(inlineStyle);
+ }
+
+ var matchedStyleRules = node.ownerDocument.defaultView.getMatchedCSSRules(node, "", !Preferences.showUserAgentStyles);
+ if (matchedStyleRules) {
+ // Add rules in reverse order to match the cascade order.
+ for (var i = (matchedStyleRules.length - 1); i >= 0; --i) {
+ var rule = matchedStyleRules[i];
+ styleRules.push({ style: rule.style, selectorText: rule.selectorText, parentStyleSheet: rule.parentStyleSheet });
+ }
+ }
+ }
+
+ function deleteDisabledProperty(style, name)
+ {
+ if (!style || !name)
+ return;
+ if (style.__disabledPropertyValues)
+ delete style.__disabledPropertyValues[name];
+ if (style.__disabledPropertyPriorities)
+ delete style.__disabledPropertyPriorities[name];
+ if (style.__disabledProperties)
+ delete style.__disabledProperties[name];
+ }
+
+ var usedProperties = {};
+ var disabledComputedProperties = {};
+ var priorityUsed = false;
+
+ // Walk the style rules and make a list of all used and overloaded properties.
+ for (var i = 0; i < styleRules.length; ++i) {
+ var styleRule = styleRules[i];
+ if (styleRule.computedStyle)
+ continue;
+
+ styleRule.usedProperties = {};
+
+ var style = styleRule.style;
+ for (var j = 0; j < style.length; ++j) {
+ var name = style[j];
+
+ if (!priorityUsed && style.getPropertyPriority(name).length)
+ priorityUsed = true;
+
+ // If the property name is already used by another rule then this rule's
+ // property is overloaded, so don't add it to the rule's usedProperties.
+ if (!(name in usedProperties))
+ styleRule.usedProperties[name] = true;
+
+ if (name === "font") {
+ // The font property is not reported as a shorthand. Report finding the individual
+ // properties so they are visible in computed style.
+ // FIXME: remove this when http://bugs.webkit.org/show_bug.cgi?id=15598 is fixed.
+ styleRule.usedProperties["font-family"] = true;
+ styleRule.usedProperties["font-size"] = true;
+ styleRule.usedProperties["font-style"] = true;
+ styleRule.usedProperties["font-variant"] = true;
+ styleRule.usedProperties["font-weight"] = true;
+ styleRule.usedProperties["line-height"] = true;
+ }
+
+ // Delete any disabled properties, since the property does exist.
+ // This prevents it from showing twice.
+ deleteDisabledProperty(style, name);
+ deleteDisabledProperty(style, style.getPropertyShorthand(name));
+ }
+
+ // Add all the properties found in this style to the used properties list.
+ // Do this here so only future rules are affect by properties used in this rule.
+ for (var name in styleRules[i].usedProperties)
+ usedProperties[name] = true;
+
+ // Remember all disabled properties so they show up in computed style.
+ if (style.__disabledProperties)
+ for (var name in style.__disabledProperties)
+ disabledComputedProperties[name] = true;
+ }
+
+ if (priorityUsed) {
+ // Walk the properties again and account for !important.
+ var foundPriorityProperties = [];
+
+ // Walk in reverse to match the order !important overrides.
+ for (var i = (styleRules.length - 1); i >= 0; --i) {
+ if (styleRules[i].computedStyle)
+ continue;
+
+ var style = styleRules[i].style;
+ var uniqueProperties = getUniqueStyleProperties(style);
+ for (var j = 0; j < uniqueProperties.length; ++j) {
+ var name = uniqueProperties[j];
+ if (style.getPropertyPriority(name).length) {
+ if (!(name in foundPriorityProperties))
+ styleRules[i].usedProperties[name] = true;
+ else
+ delete styleRules[i].usedProperties[name];
+ foundPriorityProperties[name] = true;
+ } else if (name in foundPriorityProperties)
+ delete styleRules[i].usedProperties[name];
+ }
+ }
+ }
+
+ if (refresh) {
+ // Walk the style rules and update the sections with new overloaded and used properties.
+ for (var i = 0; i < styleRules.length; ++i) {
+ var styleRule = styleRules[i];
+ var section = styleRule.section;
+ if (styleRule.computedStyle)
+ section.disabledComputedProperties = disabledComputedProperties;
+ section._usedProperties = (styleRule.usedProperties || usedProperties);
+ section.update((section === editedSection) || styleRule.computedStyle);
+ }
+ } else {
+ // Make a property section for each style rule.
+ for (var i = 0; i < styleRules.length; ++i) {
+ var styleRule = styleRules[i];
+ var subtitle = styleRule.subtitle;
+ delete styleRule.subtitle;
+
+ var computedStyle = styleRule.computedStyle;
+ delete styleRule.computedStyle;
+
+ var ruleUsedProperties = styleRule.usedProperties;
+ delete styleRule.usedProperties;
+
+ var editable = styleRule.editable;
+ delete styleRule.editable;
+
+ // Default editable to true if it was omitted.
+ if (typeof editable === "undefined")
+ editable = true;
+
+ var section = new WebInspector.StylePropertiesSection(styleRule, subtitle, computedStyle, (ruleUsedProperties || usedProperties), editable);
+ if (computedStyle)
+ section.disabledComputedProperties = disabledComputedProperties;
+ section.pane = this;
+
+ if (Preferences.styleRulesExpandedState && section.identifier in Preferences.styleRulesExpandedState)
+ section.expanded = Preferences.styleRulesExpandedState[section.identifier];
+ else if (computedStyle)
+ section.collapse(true);
+ else
+ section.expand(true);
+
+ body.appendChild(section.element);
+ this.sections.push(section);
+ }
+ }
+ }
+}
+
+WebInspector.StylesSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
+
+WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyle, usedProperties, editable)
+{
+ WebInspector.PropertiesSection.call(this, styleRule.selectorText);
+
+ this.styleRule = styleRule;
+ this.computedStyle = computedStyle;
+ this.editable = (editable && !computedStyle);
+
+ // Prevent editing the user agent and user rules.
+ var isUserAgent = this.styleRule.parentStyleSheet && !this.styleRule.parentStyleSheet.ownerNode && !this.styleRule.parentStyleSheet.href;
+ var isUser = this.styleRule.parentStyleSheet && this.styleRule.parentStyleSheet.ownerNode && this.styleRule.parentStyleSheet.ownerNode.nodeName == '#document';
+ if (isUserAgent || isUser)
+ this.editable = false;
+
+ this._usedProperties = usedProperties;
+
+ if (computedStyle) {
+ this.element.addStyleClass("computed-style");
+
+ if (Preferences.showInheritedComputedStyleProperties)
+ this.element.addStyleClass("show-inherited");
+
+ var showInheritedLabel = document.createElement("label");
+ var showInheritedInput = document.createElement("input");
+ showInheritedInput.type = "checkbox";
+ showInheritedInput.checked = Preferences.showInheritedComputedStyleProperties;
+
+ var computedStyleSection = this;
+ var showInheritedToggleFunction = function(event) {
+ Preferences.showInheritedComputedStyleProperties = showInheritedInput.checked;
+ if (Preferences.showInheritedComputedStyleProperties)
+ computedStyleSection.element.addStyleClass("show-inherited");
+ else
+ computedStyleSection.element.removeStyleClass("show-inherited");
+ event.stopPropagation();
+ };
+
+ showInheritedLabel.addEventListener("click", showInheritedToggleFunction, false);
+
+ showInheritedLabel.appendChild(showInheritedInput);
+ showInheritedLabel.appendChild(document.createTextNode(WebInspector.UIString("Show inherited")));
+ this.subtitleElement.appendChild(showInheritedLabel);
+ } else {
+ if (!subtitle) {
+ if (this.styleRule.parentStyleSheet && this.styleRule.parentStyleSheet.href) {
+ var url = this.styleRule.parentStyleSheet.href;
+ subtitle = WebInspector.linkifyURL(url, WebInspector.displayNameForURL(url));
+ this.subtitleElement.addStyleClass("file");
+ } else if (isUserAgent)
+ subtitle = WebInspector.UIString("user agent stylesheet");
+ else if (isUser)
+ subtitle = WebInspector.UIString("user stylesheet");
+ else
+ subtitle = WebInspector.UIString("inline stylesheet");
+ }
+
+ this.subtitle = subtitle;
+ }
+
+ this.identifier = styleRule.selectorText;
+ if (this.subtitle)
+ this.identifier += ":" + this.subtitleElement.textContent;
+}
+
+WebInspector.StylePropertiesSection.prototype = {
+ get usedProperties()
+ {
+ return this._usedProperties || {};
+ },
+
+ set usedProperties(x)
+ {
+ this._usedProperties = x;
+ this.update();
+ },
+
+ expand: function(dontRememberState)
+ {
+ WebInspector.PropertiesSection.prototype.expand.call(this);
+ if (dontRememberState)
+ return;
+
+ if (!Preferences.styleRulesExpandedState)
+ Preferences.styleRulesExpandedState = {};
+ Preferences.styleRulesExpandedState[this.identifier] = true;
+ },
+
+ collapse: function(dontRememberState)
+ {
+ WebInspector.PropertiesSection.prototype.collapse.call(this);
+ if (dontRememberState)
+ return;
+
+ if (!Preferences.styleRulesExpandedState)
+ Preferences.styleRulesExpandedState = {};
+ Preferences.styleRulesExpandedState[this.identifier] = false;
+ },
+
+ isPropertyInherited: function(property)
+ {
+ if (!this.computedStyle || !this._usedProperties)
+ return false;
+ // These properties should always show for Computed Style.
+ var alwaysShowComputedProperties = { "display": true, "height": true, "width": true };
+ return !(property in this.usedProperties) && !(property in alwaysShowComputedProperties) && !(property in this.disabledComputedProperties);
+ },
+
+ isPropertyOverloaded: function(property, shorthand)
+ {
+ if (this.computedStyle || !this._usedProperties)
+ return false;
+
+ var used = (property in this.usedProperties);
+ if (used || !shorthand)
+ return !used;
+
+ // Find out if any of the individual longhand properties of the shorthand
+ // are used, if none are then the shorthand is overloaded too.
+ var longhandProperties = getLonghandProperties(this.styleRule.style, property);
+ for (var j = 0; j < longhandProperties.length; ++j) {
+ var individualProperty = longhandProperties[j];
+ if (individualProperty in this.usedProperties)
+ return false;
+ }
+
+ return true;
+ },
+
+ update: function(full)
+ {
+ if (full || this.computedStyle) {
+ this.propertiesTreeOutline.removeChildren();
+ this.populated = false;
+ } else {
+ var child = this.propertiesTreeOutline.children[0];
+ while (child) {
+ child.overloaded = this.isPropertyOverloaded(child.name, child.shorthand);
+ child = child.traverseNextTreeElement(false, null, true);
+ }
+ }
+ },
+
+ onpopulate: function()
+ {
+ var style = this.styleRule.style;
+
+ var foundShorthands = {};
+ var uniqueProperties = getUniqueStyleProperties(style);
+ var disabledProperties = style.__disabledPropertyValues || {};
+
+ for (var name in disabledProperties)
+ uniqueProperties.push(name);
+
+ uniqueProperties.sort();
+
+ for (var i = 0; i < uniqueProperties.length; ++i) {
+ var name = uniqueProperties[i];
+ var disabled = name in disabledProperties;
+ if (!disabled && this.disabledComputedProperties && !(name in this.usedProperties) && name in this.disabledComputedProperties)
+ disabled = true;
+
+ var shorthand = !disabled ? style.getPropertyShorthand(name) : null;
+
+ if (shorthand && shorthand in foundShorthands)
+ continue;
+
+ if (shorthand) {
+ foundShorthands[shorthand] = true;
+ name = shorthand;
+ }
+
+ var isShorthand = (shorthand ? true : false);
+ var inherited = this.isPropertyInherited(name);
+ var overloaded = this.isPropertyOverloaded(name, isShorthand);
+
+ var item = new WebInspector.StylePropertyTreeElement(style, name, isShorthand, inherited, overloaded, disabled);
+ this.propertiesTreeOutline.appendChild(item);
+ }
+ }
+}
+
+WebInspector.StylePropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
+
+WebInspector.StylePropertyTreeElement = function(style, name, shorthand, inherited, overloaded, disabled)
+{
+ this.style = style;
+ this.name = name;
+ this.shorthand = shorthand;
+ this._inherited = inherited;
+ this._overloaded = overloaded;
+ this._disabled = disabled;
+
+ // Pass an empty title, the title gets made later in onattach.
+ TreeElement.call(this, "", null, shorthand);
+}
+
+WebInspector.StylePropertyTreeElement.prototype = {
+ get inherited()
+ {
+ return this._inherited;
+ },
+
+ set inherited(x)
+ {
+ if (x === this._inherited)
+ return;
+ this._inherited = x;
+ this.updateState();
+ },
+
+ get overloaded()
+ {
+ return this._overloaded;
+ },
+
+ set overloaded(x)
+ {
+ if (x === this._overloaded)
+ return;
+ this._overloaded = x;
+ this.updateState();
+ },
+
+ get disabled()
+ {
+ return this._disabled;
+ },
+
+ set disabled(x)
+ {
+ if (x === this._disabled)
+ return;
+ this._disabled = x;
+ this.updateState();
+ },
+
+ get priority()
+ {
+ if (this.disabled && this.style.__disabledPropertyPriorities && this.name in this.style.__disabledPropertyPriorities)
+ return this.style.__disabledPropertyPriorities[this.name];
+ return (this.shorthand ? getShorthandPriority(this.style, this.name) : this.style.getPropertyPriority(this.name));
+ },
+
+ get value()
+ {
+ if (this.disabled && this.style.__disabledPropertyValues && this.name in this.style.__disabledPropertyValues)
+ return this.style.__disabledPropertyValues[this.name];
+ return (this.shorthand ? getShorthandValue(this.style, this.name) : this.style.getPropertyValue(this.name));
+ },
+
+ onattach: function()
+ {
+ this.updateTitle();
+ },
+
+ updateTitle: function()
+ {
+ // "Nicknames" for some common values that are easier to read.
+ var valueNicknames = {
+ "rgb(0, 0, 0)": "black",
+ "#000": "black",
+ "#000000": "black",
+ "rgb(255, 255, 255)": "white",
+ "#fff": "white",
+ "#ffffff": "white",
+ "#FFF": "white",
+ "#FFFFFF": "white",
+ "rgba(0, 0, 0, 0)": "transparent",
+ "rgb(255, 0, 0)": "red",
+ "rgb(0, 255, 0)": "lime",
+ "rgb(0, 0, 255)": "blue",
+ "rgb(255, 255, 0)": "yellow",
+ "rgb(255, 0, 255)": "magenta",
+ "rgb(0, 255, 255)": "cyan"
+ };
+
+ var priority = this.priority;
+ var value = this.value;
+ var htmlValue = value;
+
+ if (priority && !priority.length)
+ delete priority;
+ if (priority)
+ priority = "!" + priority;
+
+ if (value) {
+ var urls = value.match(/url\([^)]+\)/);
+ if (urls) {
+ for (var i = 0; i < urls.length; ++i) {
+ var url = urls[i].substring(4, urls[i].length - 1);
+ htmlValue = htmlValue.replace(urls[i], "url(" + WebInspector.linkifyURL(url) + ")");
+ }
+ } else {
+ if (value in valueNicknames)
+ htmlValue = valueNicknames[value];
+ htmlValue = htmlValue.escapeHTML();
+ }
+ } else
+ htmlValue = value = "";
+
+ this.updateState();
+
+ var enabledCheckboxElement = document.createElement("input");
+ enabledCheckboxElement.className = "enabled-button";
+ enabledCheckboxElement.type = "checkbox";
+ enabledCheckboxElement.checked = !this.disabled;
+ enabledCheckboxElement.addEventListener("change", this.toggleEnabled.bind(this), false);
+
+ var nameElement = document.createElement("span");
+ nameElement.className = "name";
+ nameElement.textContent = this.name;
+
+ var valueElement = document.createElement("span");
+ valueElement.className = "value";
+ valueElement.innerHTML = htmlValue;
+
+ if (priority) {
+ var priorityElement = document.createElement("span");
+ priorityElement.className = "priority";
+ priorityElement.textContent = priority;
+ }
+
+ this.listItemElement.removeChildren();
+
+ // Append the checkbox for root elements of an editable section.
+ if (this.treeOutline.section && this.treeOutline.section.editable && this.parent.root)
+ this.listItemElement.appendChild(enabledCheckboxElement);
+ this.listItemElement.appendChild(nameElement);
+ this.listItemElement.appendChild(document.createTextNode(": "));
+ this.listItemElement.appendChild(valueElement);
+
+ if (priorityElement) {
+ this.listItemElement.appendChild(document.createTextNode(" "));
+ this.listItemElement.appendChild(priorityElement);
+ }
+
+ this.listItemElement.appendChild(document.createTextNode(";"));
+
+ if (value) {
+ // FIXME: this only covers W3C and CSS 16 valid color names
+ var colors = value.match(/((rgb|hsl)a?\([^)]+\))|(#[0-9a-fA-F]{6})|(#[0-9a-fA-F]{3})|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow/g);
+ if (colors) {
+ var colorsLength = colors.length;
+ for (var i = 0; i < colorsLength; ++i) {
+ var swatchElement = document.createElement("span");
+ swatchElement.className = "swatch";
+ swatchElement.style.setProperty("background-color", colors[i]);
+ this.listItemElement.appendChild(swatchElement);
+ }
+ }
+ }
+
+ this.tooltip = this.name + ": " + (valueNicknames[value] || value) + (priority ? " " + priority : "");
+ },
+
+ updateAll: function(updateAllRules)
+ {
+ if (updateAllRules && this.treeOutline.section && this.treeOutline.section.pane)
+ this.treeOutline.section.pane.update(null, this.treeOutline.section);
+ else if (this.treeOutline.section)
+ this.treeOutline.section.update(true);
+ else
+ this.updateTitle(); // FIXME: this will not show new properties. But we don't hit his case yet.
+ },
+
+ toggleEnabled: function(event)
+ {
+ var disabled = !event.target.checked;
+
+ if (disabled) {
+ if (!this.style.__disabledPropertyValues || !this.style.__disabledPropertyPriorities) {
+ var inspectedWindow = InspectorController.inspectedWindow();
+ this.style.__disabledProperties = new inspectedWindow.Object;
+ this.style.__disabledPropertyValues = new inspectedWindow.Object;
+ this.style.__disabledPropertyPriorities = new inspectedWindow.Object;
+ }
+
+ this.style.__disabledPropertyValues[this.name] = this.value;
+ this.style.__disabledPropertyPriorities[this.name] = this.priority;
+
+ if (this.shorthand) {
+ var longhandProperties = getLonghandProperties(this.style, this.name);
+ for (var i = 0; i < longhandProperties.length; ++i) {
+ this.style.__disabledProperties[longhandProperties[i]] = true;
+ this.style.removeProperty(longhandProperties[i]);
+ }
+ } else {
+ this.style.__disabledProperties[this.name] = true;
+ this.style.removeProperty(this.name);
+ }
+ } else {
+ this.style.setProperty(this.name, this.value, this.priority);
+ delete this.style.__disabledProperties[this.name];
+ delete this.style.__disabledPropertyValues[this.name];
+ delete this.style.__disabledPropertyPriorities[this.name];
+ }
+
+ // Set the disabled property here, since the code above replies on it not changing
+ // until after the value and priority are retrieved.
+ this.disabled = disabled;
+
+ if (this.treeOutline.section && this.treeOutline.section.pane)
+ this.treeOutline.section.pane.dispatchEventToListeners("style property toggled");
+
+ this.updateAll(true);
+ },
+
+ updateState: function()
+ {
+ if (!this.listItemElement)
+ return;
+
+ if (this.style.isPropertyImplicit(this.name) || this.value === "initial")
+ this.listItemElement.addStyleClass("implicit");
+ else
+ this.listItemElement.removeStyleClass("implicit");
+
+ if (this.inherited)
+ this.listItemElement.addStyleClass("inherited");
+ else
+ this.listItemElement.removeStyleClass("inherited");
+
+ if (this.overloaded)
+ this.listItemElement.addStyleClass("overloaded");
+ else
+ this.listItemElement.removeStyleClass("overloaded");
+
+ if (this.disabled)
+ this.listItemElement.addStyleClass("disabled");
+ else
+ this.listItemElement.removeStyleClass("disabled");
+ },
+
+ onpopulate: function()
+ {
+ // Only populate once and if this property is a shorthand.
+ if (this.children.length || !this.shorthand)
+ return;
+
+ var longhandProperties = getLonghandProperties(this.style, this.name);
+ for (var i = 0; i < longhandProperties.length; ++i) {
+ var name = longhandProperties[i];
+
+ if (this.treeOutline.section) {
+ var inherited = this.treeOutline.section.isPropertyInherited(name);
+ var overloaded = this.treeOutline.section.isPropertyOverloaded(name);
+ }
+
+ var item = new WebInspector.StylePropertyTreeElement(this.style, name, false, inherited, overloaded);
+ this.appendChild(item);
+ }
+ },
+
+ ondblclick: function(element, event)
+ {
+ this.startEditing(event.target);
+ },
+
+ startEditing: function(selectElement)
+ {
+ // FIXME: we don't allow editing of longhand properties under a shorthand right now.
+ if (this.parent.shorthand)
+ return;
+
+ if (WebInspector.isBeingEdited(this.listItemElement) || (this.treeOutline.section && !this.treeOutline.section.editable))
+ return;
+
+ var context = { expanded: this.expanded, hasChildren: this.hasChildren };
+
+ // Lie about our children to prevent expanding on double click and to collapse shorthands.
+ this.hasChildren = false;
+
+ if (!selectElement)
+ selectElement = this.listItemElement;
+
+ this.listItemElement.handleKeyEvent = this.editingKeyDown.bind(this);
+
+ WebInspector.startEditing(this.listItemElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
+ window.getSelection().setBaseAndExtent(selectElement, 0, selectElement, 1);
+ },
+
+ editingKeyDown: function(event)
+ {
+ var arrowKeyPressed = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down");
+ var pageKeyPressed = (event.keyIdentifier === "PageUp" || event.keyIdentifier === "PageDown");
+ if (!arrowKeyPressed && !pageKeyPressed)
+ return;
+
+ var selection = window.getSelection();
+ if (!selection.rangeCount)
+ return;
+
+ var selectionRange = selection.getRangeAt(0);
+ if (selectionRange.commonAncestorContainer !== this.listItemElement && !selectionRange.commonAncestorContainer.isDescendant(this.listItemElement))
+ return;
+
+ const styleValueDelimeters = " \t\n\"':;,/()";
+ var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, styleValueDelimeters, this.listItemElement);
+ var wordString = wordRange.toString();
+ var replacementString = wordString;
+
+ var matches = /(.*?)(-?\d+(?:\.\d+)?)(.*)/.exec(wordString);
+ if (matches && matches.length) {
+ var prefix = matches[1];
+ var number = parseFloat(matches[2]);
+ var suffix = matches[3];
+
+ // If the number is near zero or the number is one and the direction will take it near zero.
+ var numberNearZero = (number < 1 && number > -1);
+ if (number === 1 && event.keyIdentifier === "Down")
+ numberNearZero = true;
+ else if (number === -1 && event.keyIdentifier === "Up")
+ numberNearZero = true;
+
+ if (numberNearZero && event.altKey && arrowKeyPressed) {
+ if (event.keyIdentifier === "Down")
+ number = Math.ceil(number - 1);
+ else
+ number = Math.floor(number + 1);
+ } else {
+ // Jump by 10 when shift is down or jump by 0.1 when near zero or Alt/Option is down.
+ // Also jump by 10 for page up and down, or by 100 if shift is held with a page key.
+ var changeAmount = 1;
+ if (event.shiftKey && pageKeyPressed)
+ changeAmount = 100;
+ else if (event.shiftKey || pageKeyPressed)
+ changeAmount = 10;
+ else if (event.altKey || numberNearZero)
+ changeAmount = 0.1;
+
+ if (event.keyIdentifier === "Down" || event.keyIdentifier === "PageDown")
+ changeAmount *= -1;
+
+ // Make the new number and constrain it to a precision of 6, this matches numbers the engine returns.
+ // Use the Number constructor to forget the fixed precision, so 1.100000 will print as 1.1.
+ number = Number((number + changeAmount).toFixed(6));
+ }
+
+ replacementString = prefix + number + suffix;
+ } else {
+ // FIXME: this should cycle through known keywords for the current property name.
+ return;
+ }
+
+ var replacementTextNode = document.createTextNode(replacementString);
+
+ wordRange.deleteContents();
+ wordRange.insertNode(replacementTextNode);
+
+ var finalSelectionRange = document.createRange();
+ finalSelectionRange.setStart(replacementTextNode, 0);
+ finalSelectionRange.setEnd(replacementTextNode, replacementString.length);
+
+ selection.removeAllRanges();
+ selection.addRange(finalSelectionRange);
+
+ event.preventDefault();
+ event.handled = true;
+
+ if (!this.originalCSSText) {
+ // Remember the rule's original CSS text, so it can be restored
+ // if the editing is canceled and before each apply.
+ this.originalCSSText = getStyleTextWithShorthands(this.style);
+ } else {
+ // Restore the original CSS text before applying user changes. This is needed to prevent
+ // new properties from sticking around if the user adds one, then removes it.
+ this.style.cssText = this.originalCSSText;
+ }
+
+ this.applyStyleText(this.listItemElement.textContent);
+ },
+
+ editingEnded: function(context)
+ {
+ this.hasChildren = context.hasChildren;
+ if (context.expanded)
+ this.expand();
+ delete this.listItemElement.handleKeyEvent;
+ delete this.originalCSSText;
+ },
+
+ editingCancelled: function(element, context)
+ {
+ if (this.originalCSSText) {
+ this.style.cssText = this.originalCSSText;
+
+ if (this.treeOutline.section && this.treeOutline.section.pane)
+ this.treeOutline.section.pane.dispatchEventToListeners("style edited");
+
+ this.updateAll();
+ } else
+ this.updateTitle();
+
+ this.editingEnded(context);
+ },
+
+ editingCommitted: function(element, userInput, previousContent, context)
+ {
+ this.editingEnded(context);
+
+ if (userInput === previousContent)
+ return; // nothing changed, so do nothing else
+
+ this.applyStyleText(userInput, true);
+ },
+
+ applyStyleText: function(styleText, updateInterface)
+ {
+ var styleTextLength = styleText.trimWhitespace().length;
+
+ // Create a new element to parse the user input CSS.
+ var parseElement = document.createElement("span");
+ parseElement.setAttribute("style", styleText);
+
+ var tempStyle = parseElement.style;
+ if (tempStyle.length || !styleTextLength) {
+ // The input was parsable or the user deleted everything, so remove the
+ // original property from the real style declaration. If this represents
+ // a shorthand remove all the longhand properties.
+ if (this.shorthand) {
+ var longhandProperties = getLonghandProperties(this.style, this.name);
+ for (var i = 0; i < longhandProperties.length; ++i)
+ this.style.removeProperty(longhandProperties[i]);
+ } else
+ this.style.removeProperty(this.name);
+ }
+
+ if (!styleTextLength) {
+ if (updateInterface) {
+ // The user deleted the everything, so remove the tree element and update.
+ if (this.treeOutline.section && this.treeOutline.section.pane)
+ this.treeOutline.section.pane.update();
+ this.parent.removeChild(this);
+ }
+ return;
+ }
+
+ if (!tempStyle.length) {
+ // The user typed something, but it didn't parse. Just abort and restore
+ // the original title for this property.
+ if (updateInterface)
+ this.updateTitle();
+ return;
+ }
+
+ // Iterate of the properties on the test element's style declaration and
+ // add them to the real style declaration. We take care to move shorthands.
+ var foundShorthands = {};
+ var uniqueProperties = getUniqueStyleProperties(tempStyle);
+ for (var i = 0; i < uniqueProperties.length; ++i) {
+ var name = uniqueProperties[i];
+ var shorthand = tempStyle.getPropertyShorthand(name);
+
+ if (shorthand && shorthand in foundShorthands)
+ continue;
+
+ if (shorthand) {
+ var value = getShorthandValue(tempStyle, shorthand);
+ var priority = getShorthandPriority(tempStyle, shorthand);
+ foundShorthands[shorthand] = true;
+ } else {
+ var value = tempStyle.getPropertyValue(name);
+ var priority = tempStyle.getPropertyPriority(name);
+ }
+
+ // Set the property on the real style declaration.
+ this.style.setProperty((shorthand || name), value, priority);
+ }
+
+ if (this.treeOutline.section && this.treeOutline.section.pane)
+ this.treeOutline.section.pane.dispatchEventToListeners("style edited");
+
+ if (updateInterface)
+ this.updateAll(true);
+ }
+}
+
+WebInspector.StylePropertyTreeElement.prototype.__proto__ = TreeElement.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/TextPrompt.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/TextPrompt.js
new file mode 100644
index 0000000..61e1b52db
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/TextPrompt.js
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TextPrompt = function(element, completions, stopCharacters)
+{
+ this.element = element;
+ this.completions = completions;
+ this.completionStopCharacters = stopCharacters;
+ this.history = [];
+ this.historyOffset = 0;
+}
+
+WebInspector.TextPrompt.prototype = {
+ get text()
+ {
+ return this.element.textContent;
+ },
+
+ set text(x)
+ {
+ if (!x) {
+ // Append a break element instead of setting textContent to make sure the selection is inside the prompt.
+ this.element.removeChildren();
+ this.element.appendChild(document.createElement("br"));
+ } else
+ this.element.textContent = x;
+
+ this.moveCaretToEndOfPrompt();
+ },
+
+ handleKeyEvent: function(event)
+ {
+ switch (event.keyIdentifier) {
+ case "Up":
+ this._upKeyPressed(event);
+ break;
+ case "Down":
+ this._downKeyPressed(event);
+ break;
+ case "U+0009": // Tab
+ this._tabKeyPressed(event);
+ break;
+ case "Right":
+ if (!this.acceptAutoComplete())
+ this.autoCompleteSoon();
+ break;
+ default:
+ this.clearAutoComplete();
+ this.autoCompleteSoon();
+ break;
+ }
+ },
+
+ acceptAutoComplete: function()
+ {
+ if (!this.autoCompleteElement || !this.autoCompleteElement.parentNode)
+ return false;
+
+ var text = this.autoCompleteElement.textContent;
+ var textNode = document.createTextNode(text);
+ this.autoCompleteElement.parentNode.replaceChild(textNode, this.autoCompleteElement);
+ delete this.autoCompleteElement;
+
+ var finalSelectionRange = document.createRange();
+ finalSelectionRange.setStart(textNode, text.length);
+ finalSelectionRange.setEnd(textNode, text.length);
+
+ var selection = window.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(finalSelectionRange);
+
+ return true;
+ },
+
+ clearAutoComplete: function(includeTimeout)
+ {
+ if (includeTimeout && "_completeTimeout" in this) {
+ clearTimeout(this._completeTimeout);
+ delete this._completeTimeout;
+ }
+
+ if (!this.autoCompleteElement)
+ return;
+
+ if (this.autoCompleteElement.parentNode)
+ this.autoCompleteElement.parentNode.removeChild(this.autoCompleteElement);
+ delete this.autoCompleteElement;
+
+ if (!this._userEnteredRange || !this._userEnteredText)
+ return;
+
+ this._userEnteredRange.deleteContents();
+
+ var userTextNode = document.createTextNode(this._userEnteredText);
+ this._userEnteredRange.insertNode(userTextNode);
+
+ var selectionRange = document.createRange();
+ selectionRange.setStart(userTextNode, this._userEnteredText.length);
+ selectionRange.setEnd(userTextNode, this._userEnteredText.length);
+
+ var selection = window.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(selectionRange);
+
+ delete this._userEnteredRange;
+ delete this._userEnteredText;
+ },
+
+ autoCompleteSoon: function()
+ {
+ if (!("_completeTimeout" in this))
+ this._completeTimeout = setTimeout(this.complete.bind(this, true), 250);
+ },
+
+ complete: function(auto)
+ {
+ this.clearAutoComplete(true);
+
+ var selection = window.getSelection();
+ if (!selection.rangeCount)
+ return;
+
+ var selectionRange = selection.getRangeAt(0);
+ if (!selectionRange.commonAncestorContainer.isDescendant(this.element))
+ return;
+ if (auto && !this.isCaretAtEndOfPrompt())
+ return;
+
+ var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, this.completionStopCharacters, this.element, "backward");
+ var completions = this.completions(wordPrefixRange, auto);
+
+ if (!completions || !completions.length)
+ return;
+
+ var fullWordRange = document.createRange();
+ fullWordRange.setStart(wordPrefixRange.startContainer, wordPrefixRange.startOffset);
+ fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffset);
+
+ if (completions.length === 1 || selection.isCollapsed || auto) {
+ var completionText = completions[0];
+ } else {
+ var currentText = fullWordRange.toString();
+
+ var foundIndex = null;
+ for (var i = 0; i < completions.length; ++i) {
+ if (completions[i] === currentText)
+ foundIndex = i;
+ }
+
+ if (foundIndex === null || (foundIndex + 1) >= completions.length)
+ var completionText = completions[0];
+ else
+ var completionText = completions[foundIndex + 1];
+ }
+
+ var wordPrefixLength = wordPrefixRange.toString().length;
+
+ this._userEnteredRange = fullWordRange;
+ this._userEnteredText = fullWordRange.toString();
+
+ fullWordRange.deleteContents();
+
+ var finalSelectionRange = document.createRange();
+
+ if (auto) {
+ var prefixText = completionText.substring(0, wordPrefixLength);
+ var suffixText = completionText.substring(wordPrefixLength);
+
+ var prefixTextNode = document.createTextNode(prefixText);
+ fullWordRange.insertNode(prefixTextNode);
+
+ this.autoCompleteElement = document.createElement("span");
+ this.autoCompleteElement.className = "auto-complete-text";
+ this.autoCompleteElement.textContent = suffixText;
+
+ prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, prefixTextNode.nextSibling);
+
+ finalSelectionRange.setStart(prefixTextNode, wordPrefixLength);
+ finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength);
+ } else {
+ var completionTextNode = document.createTextNode(completionText);
+ fullWordRange.insertNode(completionTextNode);
+
+ if (completions.length > 1)
+ finalSelectionRange.setStart(completionTextNode, wordPrefixLength);
+ else
+ finalSelectionRange.setStart(completionTextNode, completionText.length);
+
+ finalSelectionRange.setEnd(completionTextNode, completionText.length);
+ }
+
+ selection.removeAllRanges();
+ selection.addRange(finalSelectionRange);
+ },
+
+ isCaretInsidePrompt: function()
+ {
+ return this.element.isInsertionCaretInside();
+ },
+
+ isCaretAtEndOfPrompt: function()
+ {
+ var selection = window.getSelection();
+ if (!selection.rangeCount || !selection.isCollapsed)
+ return false;
+
+ var selectionRange = selection.getRangeAt(0);
+ var node = selectionRange.startContainer;
+ if (node !== this.element && !node.isDescendant(this.element))
+ return false;
+
+ if (node.nodeType === Node.TEXT_NODE && selectionRange.startOffset < node.nodeValue.length)
+ return false;
+
+ var foundNextText = false;
+ while (node) {
+ if (node.nodeType === Node.TEXT_NODE && node.nodeValue.length) {
+ if (foundNextText)
+ return false;
+ foundNextText = true;
+ }
+
+ node = node.traverseNextNode(false, this.element);
+ }
+
+ return true;
+ },
+
+ moveCaretToEndOfPrompt: function()
+ {
+ var selection = window.getSelection();
+ var selectionRange = document.createRange();
+
+ var offset = this.element.childNodes.length;
+ selectionRange.setStart(this.element, offset);
+ selectionRange.setEnd(this.element, offset);
+
+ selection.removeAllRanges();
+ selection.addRange(selectionRange);
+ },
+
+ _tabKeyPressed: function(event)
+ {
+ event.preventDefault();
+ event.stopPropagation();
+
+ this.complete();
+ },
+
+ _upKeyPressed: function(event)
+ {
+ event.preventDefault();
+ event.stopPropagation();
+
+ if (this.historyOffset == this.history.length)
+ return;
+
+ this.clearAutoComplete(true);
+
+ if (this.historyOffset == 0)
+ this.tempSavedCommand = this.text;
+
+ ++this.historyOffset;
+ this.text = this.history[this.history.length - this.historyOffset];
+ },
+
+ _downKeyPressed: function(event)
+ {
+ event.preventDefault();
+ event.stopPropagation();
+
+ if (this.historyOffset == 0)
+ return;
+
+ this.clearAutoComplete(true);
+
+ --this.historyOffset;
+
+ if (this.historyOffset == 0) {
+ this.text = this.tempSavedCommand;
+ delete this.tempSavedCommand;
+ return;
+ }
+
+ this.text = this.history[this.history.length - this.historyOffset];
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/TopDownProfileDataGridTree.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/TopDownProfileDataGridTree.js
new file mode 100644
index 0000000..b9d8b94
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/TopDownProfileDataGridTree.js
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2009 280 North Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TopDownProfileDataGridNode = function(/*ProfileView*/ profileView, /*ProfileNode*/ profileNode, /*TopDownProfileDataGridTree*/ owningTree)
+{
+ var hasChildren = (profileNode.children && profileNode.children.length);
+
+ WebInspector.ProfileDataGridNode.call(this, profileView, profileNode, owningTree, hasChildren);
+
+ this._remainingChildren = profileNode.children;
+}
+
+WebInspector.TopDownProfileDataGridNode.prototype = {
+ _populate: function(event)
+ {
+ var children = this._remainingChildren;
+ var childrenLength = children.length;
+
+ for (var i = 0; i < childrenLength; ++i)
+ this.appendChild(new WebInspector.TopDownProfileDataGridNode(this.profileView, children[i], this.tree));
+
+ if (this.removeEventListener)
+ this.removeEventListener("populate", this._populate, this);
+
+ this._remainingChildren = null;
+ },
+
+ _exclude: function(aCallUID)
+ {
+ if (this._remainingChildren)
+ this._populate();
+
+ this._save();
+
+ var children = this.children;
+ var index = this.children.length;
+
+ while (index--)
+ children[index]._exclude(aCallUID);
+
+ var child = this.childrenByCallUID[aCallUID];
+
+ if (child)
+ this._merge(child, true);
+ }
+}
+
+WebInspector.TopDownProfileDataGridNode.prototype.__proto__ = WebInspector.ProfileDataGridNode.prototype;
+
+WebInspector.TopDownProfileDataGridTree = function(/*ProfileView*/ profileView, /*ProfileNode*/ profileNode)
+{
+ WebInspector.ProfileDataGridTree.call(this, profileView, profileNode);
+
+ this._remainingChildren = profileNode.children;
+
+ WebInspector.TopDownProfileDataGridNode.prototype._populate.call(this);
+}
+
+WebInspector.TopDownProfileDataGridTree.prototype = {
+ focus: function(/*ProfileDataGridNode*/ profileDataGrideNode)
+ {
+ if (!profileDataGrideNode)
+ return;
+
+ this._save();
+
+ this.children = [profileDataGrideNode];
+ this.totalTime = profileDataGrideNode.totalTime;
+ },
+
+ exclude: function(/*ProfileDataGridNode*/ profileDataGrideNode)
+ {
+ if (!profileDataGrideNode)
+ return;
+
+ this._save();
+
+ var excludedCallUID = profileDataGrideNode.callUID;
+
+ WebInspector.TopDownProfileDataGridNode.prototype._exclude.call(this, excludedCallUID);
+
+ if (this.lastComparator)
+ this.sort(this.lastComparator, true);
+ },
+
+ _merge: WebInspector.TopDownProfileDataGridNode.prototype._merge
+}
+
+WebInspector.TopDownProfileDataGridTree.prototype.__proto__ = WebInspector.ProfileDataGridTree.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/View.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/View.js
new file mode 100644
index 0000000..632a61ae
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/View.js
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.View = function(element)
+{
+ this.element = element || document.createElement("div");
+ this._visible = false;
+}
+
+WebInspector.View.prototype = {
+ get visible()
+ {
+ return this._visible;
+ },
+
+ set visible(x)
+ {
+ if (this._visible === x)
+ return;
+
+ if (x)
+ this.show();
+ else
+ this.hide();
+ },
+
+ show: function(parentElement)
+ {
+ this._visible = true;
+ if (parentElement && parentElement !== this.element.parentNode) {
+ this.detach();
+ parentElement.appendChild(this.element);
+ }
+ if (!this.element.parentNode && this.attach)
+ this.attach();
+ this.element.addStyleClass("visible");
+ },
+
+ hide: function()
+ {
+ this.element.removeStyleClass("visible");
+ this._visible = false;
+ },
+
+ detach: function()
+ {
+ if (this.element.parentNode)
+ this.element.parentNode.removeChild(this.element);
+ }
+}
+
+WebInspector.View.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/base.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/base.js
new file mode 100644
index 0000000..8f029a1
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/base.js
@@ -0,0 +1,1015 @@
+// Copyright 2006 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.
+//
+// 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.
+
+// NOTE: This file has been changed from the one on doctype. The following
+// changes were made:
+// - Removed goog.globalEval because it calls eval() which is not allowed from
+// inside v8 extensions. If we ever need to use globalEval, we will need to
+// find a way to work around this problem.
+// - Remove Function.prototype.apply() emulation for the same reason. This one
+// is useless anyway because V8 supports apply() natively.
+
+/**
+ * @fileoverview Bootstrap for the Google JS Library
+ */
+
+/**
+ * @define {boolean} Overridden to true by the compiler when
+ * --mark_as_compiled is specified.
+ */
+var COMPILED = true;
+
+
+/**
+ * Base namespace for the Google JS library. Checks to see goog is
+ * already defined in the current scope before assigning to prevent
+ * clobbering if base.js is loaded more than once.
+ */
+var goog = {}; // Check to see if already defined in current scope
+
+
+/**
+ * Reference to the global context. In most cases this will be 'window'.
+ */
+goog.global = this;
+
+
+/**
+ * Indicates whether or not we can call 'eval' directly to eval code in the
+ * global scope. Set to a Boolean by the first call to goog.globalEval (which
+ * empirically tests whether eval works for globals). @see goog.globalEval
+ * @type {boolean?}
+ * @private
+ */
+goog.evalWorksForGlobals_ = null;
+
+
+/**
+ * Creates object stubs for a namespace. When present in a file, goog.provide
+ * also indicates that the file defines the indicated object.
+ * @param {string} name name of the object that this file defines.
+ */
+goog.provide = function(name) {
+ if (!COMPILED) {
+ // Ensure that the same namespace isn't provided twice. This is intended
+ // to teach new developers that 'goog.provide' is effectively a variable
+ // declaration. And when JSCompiler transforms goog.provide into a real
+ // variable declaration, the compiled JS should work the same as the raw
+ // JS--even when the raw JS uses goog.provide incorrectly.
+ if (goog.getObjectByName(name) && !goog.implicitNamespaces_[name]) {
+ throw 'Namespace "' + name + '" already declared.';
+ }
+
+ var namespace = name;
+ while ((namespace = namespace.substr(0, namespace.lastIndexOf('.')))) {
+ goog.implicitNamespaces_[namespace] = true;
+ }
+ }
+
+ goog.exportPath_(name);
+};
+
+
+if (!COMPILED) {
+ /**
+ * Namespaces implicitly defined by goog.provide. For example,
+ * goog.provide('goog.events.Event') implicitly declares
+ * that 'goog' and 'goog.events' must be namespaces.
+ *
+ * @type {Object}
+ * @private
+ */
+ goog.implicitNamespaces_ = {};
+}
+
+
+/**
+ * Builds an object structure for the provided namespace path,
+ * ensuring that names that already exist are not overwritten. For
+ * example:
+ * "a.b.c" -> a = {};a.b={};a.b.c={};
+ * Used by goog.provide and goog.exportSymbol.
+ * @param {string} name name of the object that this file defines.
+ * @param {Object} opt_object the object to expose at the end of the path.
+ * @private
+ */
+goog.exportPath_ = function(name, opt_object) {
+ var parts = name.split('.');
+ var cur = goog.global;
+ var part;
+
+ // Internet Explorer exhibits strange behavior when throwing errors from
+ // methods externed in this manner. See the testExportSymbolExceptions in
+ // base_test.html for an example.
+ if (!(parts[0] in cur) && cur.execScript) {
+ cur.execScript('var ' + parts[0]);
+ }
+
+ // Parentheses added to eliminate strict JS warning in Firefox.
+ while ((part = parts.shift())) {
+ if (!parts.length && goog.isDef(opt_object)) {
+ // last part and we have an object; use it
+ cur[part] = opt_object;
+ } else if (cur[part]) {
+ cur = cur[part];
+ } else {
+ cur = cur[part] = {};
+ }
+ }
+};
+
+
+/**
+ * Returns an object based on its fully qualified name
+ * @param {string} name The fully qualified name.
+ * @return {Object?} The object or, if not found, null.
+ */
+goog.getObjectByName = function(name) {
+ var parts = name.split('.');
+ var cur = goog.global;
+ for (var part; part = parts.shift(); ) {
+ if (cur[part]) {
+ cur = cur[part];
+ } else {
+ return null;
+ }
+ }
+ return cur;
+};
+
+
+/**
+ * Globalizes a whole namespace, such as goog or goog.lang.
+ *
+ * @param {Object} obj The namespace to globalize.
+ * @param {Object} opt_global The object to add the properties to.
+ * @deprecated Properties may be explicitly exported to the global scope, but
+ * this should no longer be done in bulk.
+ */
+goog.globalize = function(obj, opt_global) {
+ var global = opt_global || goog.global;
+ for (var x in obj) {
+ global[x] = obj[x];
+ }
+};
+
+
+/**
+ * Adds a dependency from a file to the files it requires.
+ * @param {string} relPath The path to the js file.
+ * @param {Array} provides An array of strings with the names of the objects
+ * this file provides.
+ * @param {Array} requires An array of strings with the names of the objects
+ * this file requires.
+ */
+goog.addDependency = function(relPath, provides, requires) {
+ if (!COMPILED) {
+ var provide, require;
+ var path = relPath.replace(/\\/g, '/');
+ var deps = goog.dependencies_;
+ for (var i = 0; provide = provides[i]; i++) {
+ deps.nameToPath[provide] = path;
+ if (!(path in deps.pathToNames)) {
+ deps.pathToNames[path] = {};
+ }
+ deps.pathToNames[path][provide] = true;
+ }
+ for (var j = 0; require = requires[j]; j++) {
+ if (!(path in deps.requires)) {
+ deps.requires[path] = {};
+ }
+ deps.requires[path][require] = true;
+ }
+ }
+};
+
+
+/**
+ * Implements a system for the dynamic resolution of dependencies
+ * that works in parallel with the BUILD system.
+ * @param {string} rule Rule to include, in the form goog.package.part.
+ */
+goog.require = function(rule) {
+
+ // if the object already exists we do not need do do anything
+ if (!COMPILED) {
+ if (goog.getObjectByName(rule)) {
+ return;
+ }
+ var path = goog.getPathFromDeps_(rule);
+ if (path) {
+ goog.included_[path] = true;
+ goog.writeScripts_();
+ } else {
+ // NOTE(nicksantos): We could throw an error, but this would break
+ // legacy users that depended on this failing silently. Instead, the
+ // compiler should warn us when there are invalid goog.require calls.
+ }
+ }
+};
+
+
+/**
+ * Path for included scripts
+ * @type {string}
+ */
+goog.basePath = '';
+
+
+/**
+ * Null function used for default values of callbacks, etc.
+ * @type {Function}
+ */
+goog.nullFunction = function() {};
+
+
+/**
+ * When defining a class Foo with an abstract method bar(), you can do:
+ *
+ * Foo.prototype.bar = goog.abstractMethod
+ *
+ * Now if a subclass of Foo fails to override bar(), an error
+ * will be thrown when bar() is invoked.
+ *
+ * Note: This does not take the name of the function to override as
+ * an argument because that would make it more difficult to obfuscate
+ * our JavaScript code.
+ *
+ * @throws {Error} when invoked to indicate the method should be
+ * overridden.
+ */
+goog.abstractMethod = function() {
+ throw Error('unimplemented abstract method');
+};
+
+
+if (!COMPILED) {
+ /**
+ * Object used to keep track of urls that have already been added. This
+ * record allows the prevention of circular dependencies.
+ * @type {Object}
+ * @private
+ */
+ goog.included_ = {};
+
+
+ /**
+ * This object is used to keep track of dependencies and other data that is
+ * used for loading scripts
+ * @private
+ * @type {Object}
+ */
+ goog.dependencies_ = {
+ pathToNames: {}, // 1 to many
+ nameToPath: {}, // 1 to 1
+ requires: {}, // 1 to many
+ visited: {}, // used when resolving dependencies to prevent us from
+ // visiting the file twice
+ written: {} // used to keep track of script files we have written
+ };
+
+
+ /**
+ * Tries to detect the base path of the base.js script that bootstraps
+ * Google JS Library
+ * @private
+ */
+ goog.findBasePath_ = function() {
+ var doc = goog.global.document;
+ if (typeof doc == 'undefined') {
+ return;
+ }
+ if (goog.global.GOOG_BASE_PATH) {
+ goog.basePath = goog.global.GOOG_BASE_PATH;
+ return;
+ } else {
+ goog.global.GOOG_BASE_PATH = null;
+ }
+ var scripts = doc.getElementsByTagName('script');
+ for (var script, i = 0; script = scripts[i]; i++) {
+ var src = script.src;
+ var l = src.length;
+ if (src.substr(l - 7) == 'base.js') {
+ goog.basePath = src.substr(0, l - 7);
+ return;
+ }
+ }
+ };
+
+
+ /**
+ * Writes a script tag if, and only if, that script hasn't already been added
+ * to the document. (Must be called at execution time)
+ * @param {string} src Script source.
+ * @private
+ */
+ goog.writeScriptTag_ = function(src) {
+ var doc = goog.global.document;
+ if (typeof doc != 'undefined' &&
+ !goog.dependencies_.written[src]) {
+ goog.dependencies_.written[src] = true;
+ doc.write('<script type="text/javascript" src="' +
+ src + '"></' + 'script>');
+ }
+ };
+
+
+ /**
+ * Resolves dependencies based on the dependencies added using addDependency
+ * and calls writeScriptTag_ in the correct order.
+ * @private
+ */
+ goog.writeScripts_ = function() {
+ // the scripts we need to write this time
+ var scripts = [];
+ var seenScript = {};
+ var deps = goog.dependencies_;
+
+ function visitNode(path) {
+ if (path in deps.written) {
+ return;
+ }
+
+ // we have already visited this one. We can get here if we have cyclic
+ // dependencies
+ if (path in deps.visited) {
+ if (!(path in seenScript)) {
+ seenScript[path] = true;
+ scripts.push(path);
+ }
+ return;
+ }
+
+ deps.visited[path] = true;
+
+ if (path in deps.requires) {
+ for (var requireName in deps.requires[path]) {
+ visitNode(deps.nameToPath[requireName]);
+ }
+ }
+
+ if (!(path in seenScript)) {
+ seenScript[path] = true;
+ scripts.push(path);
+ }
+ }
+
+ for (var path in goog.included_) {
+ if (!deps.written[path]) {
+ visitNode(path);
+ }
+ }
+
+ for (var i = 0; i < scripts.length; i++) {
+ if (scripts[i]) {
+ goog.writeScriptTag_(goog.basePath + scripts[i]);
+ } else {
+ throw Error('Undefined script input');
+ }
+ }
+ };
+
+
+ /**
+ * Looks at the dependency rules and tries to determine the script file that
+ * fulfills a particular rule.
+ * @param {string} rule In the form goog.namespace.Class or project.script.
+ * @return {string?} Url corresponding to the rule, or null.
+ * @private
+ */
+ goog.getPathFromDeps_ = function(rule) {
+ if (rule in goog.dependencies_.nameToPath) {
+ return goog.dependencies_.nameToPath[rule];
+ } else {
+ return null;
+ }
+ };
+
+ goog.findBasePath_();
+ goog.writeScriptTag_(goog.basePath + 'deps.js');
+}
+
+
+
+//==============================================================================
+// Language Enhancements
+//==============================================================================
+
+
+/**
+ * This is a "fixed" version of the typeof operator. It differs from the typeof
+ * operator in such a way that null returns 'null' and arrays return 'array'.
+ * @param {*} value The value to get the type of.
+ * @return {string} The name of the type.
+ */
+goog.typeOf = function(value) {
+ var s = typeof value;
+ if (s == 'object') {
+ if (value) {
+ // We cannot use constructor == Array or instanceof Array because
+ // different frames have different Array objects. In IE6, if the iframe
+ // where the array was created is destroyed, the array loses its
+ // prototype. Then dereferencing val.splice here throws an exception, so
+ // we can't use goog.isFunction. Calling typeof directly returns 'unknown'
+ // so that will work. In this case, this function will return false and
+ // most array functions will still work because the array is still
+ // array-like (supports length and []) even though it has lost its
+ // prototype. Custom object cannot have non enumerable length and
+ // NodeLists don't have a slice method.
+ if (typeof value.length == 'number' &&
+ typeof value.splice != 'undefined' &&
+ !goog.propertyIsEnumerable_(value, 'length')) {
+ return 'array';
+ }
+
+ // IE in cross-window calls does not correctly marshal the function type
+ // (it appears just as an object) so we cannot use just typeof val ==
+ // 'function'. However, if the object has a call property, it is a
+ // function.
+ if (typeof value.call != 'undefined') {
+ return 'function';
+ }
+ } else {
+ return 'null';
+ }
+
+ // In Safari typeof nodeList returns function. We would like to return
+ // object for those and we can detect an invalid function by making sure that
+ // the function object has a call method
+ } else if (s == 'function' && typeof value.call == 'undefined') {
+ return 'object';
+ }
+ return s;
+};
+
+if (Object.prototype.propertyIsEnumerable) {
+ /**
+ * Safe way to test whether a property is enumarable. It allows testing
+ * for enumarable on objects where 'propertyIsEnumerable' is overridden or
+ * does not exist (like DOM nodes in IE).
+ * @param {Object} object The object to test if the property is enumerable.
+ * @param {string} propName The property name to check for.
+ * @return {boolean} True if the property is enumarable.
+ * @private
+ */
+ goog.propertyIsEnumerable_ = function(object, propName) {
+ return Object.prototype.propertyIsEnumerable.call(object, propName);
+ };
+} else {
+ /**
+ * Safe way to test whether a property is enumarable. It allows testing
+ * for enumarable on objects where 'propertyIsEnumerable' is overridden or
+ * does not exist (like DOM nodes in IE).
+ * @param {Object} object The object to test if the property is enumerable.
+ * @param {string} propName The property name to check for.
+ * @return {boolean} True if the property is enumarable.
+ * @private
+ */
+ goog.propertyIsEnumerable_ = function(object, propName) {
+ // KJS in Safari 2 is not ECMAScript compatible and lacks crucial methods
+ // such as propertyIsEnumerable. We therefore use a workaround.
+ // Does anyone know a more efficient work around?
+ if (propName in object) {
+ for (var key in object) {
+ if (key == propName) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+}
+
+/**
+ * Returns true if the specified value is not |undefined|.
+ * WARNING: Do not use this to test if an object has a property. Use the in
+ * operator instead.
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is defined.
+ */
+goog.isDef = function(val) {
+ return typeof val != 'undefined';
+};
+
+
+/**
+ * Returns true if the specified value is |null|
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is null.
+ */
+goog.isNull = function(val) {
+ return val === null;
+};
+
+
+/**
+ * Returns true if the specified value is defined and not null
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is defined and not null.
+ */
+goog.isDefAndNotNull = function(val) {
+ return goog.isDef(val) && !goog.isNull(val);
+};
+
+
+/**
+ * Returns true if the specified value is an array
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is an array.
+ */
+goog.isArray = function(val) {
+ return goog.typeOf(val) == 'array';
+};
+
+
+/**
+ * Returns true if the object looks like an array. To qualify as array like
+ * the value needs to be either a NodeList or an object with a Number length
+ * property.
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is an array.
+ */
+goog.isArrayLike = function(val) {
+ var type = goog.typeOf(val);
+ return type == 'array' || type == 'object' && typeof val.length == 'number';
+};
+
+
+/**
+ * Returns true if the object looks like a Date. To qualify as Date-like
+ * the value needs to be an object and have a getFullYear() function.
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is a like a Date.
+ */
+goog.isDateLike = function(val) {
+ return goog.isObject(val) && typeof val.getFullYear == 'function';
+};
+
+
+/**
+ * Returns true if the specified value is a string
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is a string.
+ */
+goog.isString = function(val) {
+ return typeof val == 'string';
+};
+
+
+/**
+ * Returns true if the specified value is a boolean
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is boolean.
+ */
+goog.isBoolean = function(val) {
+ return typeof val == 'boolean';
+};
+
+
+/**
+ * Returns true if the specified value is a number
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is a number.
+ */
+goog.isNumber = function(val) {
+ return typeof val == 'number';
+};
+
+
+/**
+ * Returns true if the specified value is a function
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is a function.
+ */
+goog.isFunction = function(val) {
+ return goog.typeOf(val) == 'function';
+};
+
+
+/**
+ * Returns true if the specified value is an object. This includes arrays
+ * and functions.
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is an object.
+ */
+goog.isObject = function(val) {
+ var type = goog.typeOf(val);
+ return type == 'object' || type == 'array' || type == 'function';
+};
+
+
+/**
+ * Adds a hash code field to an object. The hash code is unique for the
+ * given object.
+ * @param {Object} obj The object to get the hash code for.
+ * @return {number} The hash code for the object.
+ */
+goog.getHashCode = function(obj) {
+ // In IE, DOM nodes do not extend Object so they do not have this method.
+ // we need to check hasOwnProperty because the proto might have this set.
+
+ if (obj.hasOwnProperty && obj.hasOwnProperty(goog.HASH_CODE_PROPERTY_)) {
+ return obj[goog.HASH_CODE_PROPERTY_];
+ }
+ if (!obj[goog.HASH_CODE_PROPERTY_]) {
+ obj[goog.HASH_CODE_PROPERTY_] = ++goog.hashCodeCounter_;
+ }
+ return obj[goog.HASH_CODE_PROPERTY_];
+};
+
+
+/**
+ * Removes the hash code field from an object.
+ * @param {Object} obj The object to remove the field from.
+ */
+goog.removeHashCode = function(obj) {
+ // DOM nodes in IE are not instance of Object and throws exception
+ // for delete. Instead we try to use removeAttribute
+ if ('removeAttribute' in obj) {
+ obj.removeAttribute(goog.HASH_CODE_PROPERTY_);
+ }
+ /** @preserveTry */
+ try {
+ delete obj[goog.HASH_CODE_PROPERTY_];
+ } catch (ex) {
+ }
+};
+
+
+/**
+ * {String} Name for hash code property
+ * @private
+ */
+goog.HASH_CODE_PROPERTY_ = 'goog_hashCode_';
+
+
+/**
+ * @type {number} Counter for hash codes.
+ * @private
+ */
+goog.hashCodeCounter_ = 0;
+
+
+/**
+ * Clone an object/array (recursively)
+ * @param {Object} proto Object to clone.
+ * @return {Object} Clone of x;.
+ */
+goog.cloneObject = function(proto) {
+ var type = goog.typeOf(proto);
+ if (type == 'object' || type == 'array') {
+ if (proto.clone) {
+ return proto.clone();
+ }
+ var clone = type == 'array' ? [] : {};
+ for (var key in proto) {
+ clone[key] = goog.cloneObject(proto[key]);
+ }
+ return clone;
+ }
+
+ return proto;
+};
+
+
+/**
+ * Partially applies this function to a particular 'this object' and zero or
+ * more arguments. The result is a new function with some arguments of the first
+ * function pre-filled and the value of |this| 'pre-specified'.<br><br>
+ *
+ * Remaining arguments specified at call-time are appended to the pre-
+ * specified ones.<br><br>
+ *
+ * Also see: {@link #partial}.<br><br>
+ *
+ * Note that bind and partial are optimized such that repeated calls to it do
+ * not create more than one function object, so there is no additional cost for
+ * something like:<br>
+ *
+ * <pre>var g = bind(f, obj);
+ * var h = partial(g, 1, 2, 3);
+ * var k = partial(h, a, b, c);</pre>
+ *
+ * Usage:
+ * <pre>var barMethBound = bind(myFunction, myObj, 'arg1', 'arg2');
+ * barMethBound('arg3', 'arg4');</pre>
+ *
+ * @param {Function} fn A function to partially apply.
+ * @param {Object} self Specifies the object which |this| should point to
+ * when the function is run. If the value is null or undefined, it will
+ * default to the global object.
+ * @param {Object} var_args Additional arguments that are partially
+ * applied to the function.
+ *
+ * @return {Function} A partially-applied form of the function bind() was
+ * invoked as a method of.
+ */
+goog.bind = function(fn, self, var_args) {
+ var boundArgs = fn.boundArgs_;
+
+ if (arguments.length > 2) {
+ var args = Array.prototype.slice.call(arguments, 2);
+ if (boundArgs) {
+ args.unshift.apply(args, boundArgs);
+ }
+ boundArgs = args;
+ }
+
+ self = fn.boundSelf_ || self;
+ fn = fn.boundFn_ || fn;
+
+ var newfn;
+ var context = self || goog.global;
+
+ if (boundArgs) {
+ newfn = function() {
+ // Combine the static args and the new args into one big array
+ var args = Array.prototype.slice.call(arguments);
+ args.unshift.apply(args, boundArgs);
+ return fn.apply(context, args);
+ }
+ } else {
+ newfn = function() {
+ return fn.apply(context, arguments);
+ }
+ }
+
+ newfn.boundArgs_ = boundArgs;
+ newfn.boundSelf_ = self;
+ newfn.boundFn_ = fn;
+
+ return newfn;
+};
+
+
+/**
+ * Like bind(), except that a 'this object' is not required. Useful when the
+ * target function is already bound.
+ *
+ * Usage:
+ * var g = partial(f, arg1, arg2);
+ * g(arg3, arg4);
+ *
+ * @param {Function} fn A function to partially apply.
+ * @param {Object} var_args Additional arguments that are partially
+ * applied to fn.
+ * @return {Function} A partially-applied form of the function bind() was
+ * invoked as a method of.
+ */
+goog.partial = function(fn, var_args) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ args.unshift(fn, null);
+ return goog.bind.apply(null, args);
+};
+
+
+/**
+ * Copies all the members of a source object to a target object.
+ * This is deprecated. Use goog.object.extend instead.
+ * @param {Object} target Target.
+ * @param {Object} source Source.
+ * @deprecated
+ */
+goog.mixin = function(target, source) {
+ for (var x in source) {
+ target[x] = source[x];
+ }
+
+ // For IE the for-in-loop does not contain any properties that are not
+ // enumerable on the prototype object (for example, isPrototypeOf from
+ // Object.prototype) but also it will not include 'replace' on objects that
+ // extend String and change 'replace' (not that it is common for anyone to
+ // extend anything except Object).
+};
+
+
+/**
+ * A simple wrapper for new Date().getTime().
+ *
+ * @return {number} An integer value representing the number of milliseconds
+ * between midnight, January 1, 1970 and the current time.
+ */
+goog.now = Date.now || (function() {
+ return new Date().getTime();
+});
+
+
+/**
+ * Abstract implementation of goog.getMsg for use with localized messages
+ * @param {string} str Translatable string, places holders in the form.{$foo}
+ * @param {Object} opt_values Map of place holder name to value.
+ */
+goog.getMsg = function(str, opt_values) {
+ var values = opt_values || {};
+ for (var key in values) {
+ str = str.replace(new RegExp('\\{\\$' + key + '\\}', 'gi'), values[key]);
+ }
+ return str;
+};
+
+
+/**
+ * Exposes an unobfuscated global namespace path for the given object.
+ * Note that fields of the exported object *will* be obfuscated,
+ * unless they are exported in turn via this function or
+ * goog.exportProperty
+ *
+ * <p>Also handy for making public items that are defined in anonymous
+ * closures.
+ *
+ * ex. goog.exportSymbol('Foo', Foo);
+ *
+ * ex. goog.exportSymbol('public.path.Foo.staticFunction',
+ * Foo.staticFunction);
+ * public.path.Foo.staticFunction();
+ *
+ * ex. goog.exportSymbol('public.path.Foo.prototype.myMethod',
+ * Foo.prototype.myMethod);
+ * new public.path.Foo().myMethod();
+ *
+ * @param {string} publicPath Unobfuscated name to export.
+ * @param {Object} object Object the name should point to.
+ */
+goog.exportSymbol = function(publicPath, object) {
+ goog.exportPath_(publicPath, object);
+};
+
+
+/**
+ * Exports a property unobfuscated into the object's namespace.
+ * ex. goog.exportProperty(Foo, 'staticFunction', Foo.staticFunction);
+ * ex. goog.exportProperty(Foo.prototype, 'myMethod', Foo.prototype.myMethod);
+ * @param {Object} object Object whose static property is being exported.
+ * @param {string} publicName Unobfuscated name to export.
+ * @param {Object} symbol Object the name should point to.
+ */
+goog.exportProperty = function(object, publicName, symbol) {
+ object[publicName] = symbol;
+};
+
+
+
+//==============================================================================
+// Extending Function
+//==============================================================================
+
+
+/**
+ * An alias to the {@link goog.bind()} global function.
+ *
+ * Usage:
+ * var g = f.bind(obj, arg1, arg2);
+ * g(arg3, arg4);
+ *
+ * @param {Object} self Specifies the object to which |this| should point
+ * when the function is run. If the value is null or undefined, it will
+ * default to the global object.
+ * @param {Object} var_args Additional arguments that are partially
+ * applied to fn.
+ * @return {Function} A partially-applied form of the Function on which bind()
+ * was invoked as a method.
+ * @deprecated
+ */
+Function.prototype.bind = function(self, var_args) {
+ if (arguments.length > 1) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ args.unshift(this, self);
+ return goog.bind.apply(null, args);
+ } else {
+ return goog.bind(this, self);
+ }
+};
+
+
+/**
+ * An alias to the {@link goog.partial()} global function.
+ *
+ * Usage:
+ * var g = f.partial(arg1, arg2);
+ * g(arg3, arg4);
+ *
+ * @param {Object} var_args Additional arguments that are partially
+ * applied to fn.
+ * @return {Function} A partially-applied form of the function partial() was
+ * invoked as a method of.
+ * @deprecated
+ */
+Function.prototype.partial = function(var_args) {
+ var args = Array.prototype.slice.call(arguments);
+ args.unshift(this, null);
+ return goog.bind.apply(null, args);
+};
+
+
+/**
+ * Inherit the prototype methods from one constructor into another.
+ *
+ * Usage:
+ * <pre>
+ * function ParentClass(a, b) { }
+ * ParentClass.prototype.foo = function(a) { }
+ *
+ * function ChildClass(a, b, c) {
+ * ParentClass.call(this, a, b);
+ * }
+ *
+ * ChildClass.inherits(ParentClass);
+ *
+ * var child = new ChildClass('a', 'b', 'see');
+ * child.foo(); // works
+ * </pre>
+ *
+ * In addition, a superclass' implementation of a method can be invoked
+ * as follows:
+ *
+ * <pre>
+ * ChildClass.prototype.foo = function(a) {
+ * ChildClass.superClass_.foo.call(this, a);
+ * // other code
+ * };
+ * </pre>
+ *
+ * @param {Function} parentCtor Parent class.
+ */
+Function.prototype.inherits = function(parentCtor) {
+ goog.inherits(this, parentCtor);
+};
+
+
+/**
+ * Static variant of Function.prototype.inherits.
+ * @param {Function} childCtor Child class.
+ * @param {Function} parentCtor Parent class.
+ */
+goog.inherits = function(childCtor, parentCtor) {
+ /** @constructor */
+ function tempCtor() {};
+ tempCtor.prototype = parentCtor.prototype;
+ childCtor.superClass_ = parentCtor.prototype;
+ childCtor.prototype = new tempCtor();
+ childCtor.prototype.constructor = childCtor;
+};
+
+
+/**
+ * Mixes in an object's properties and methods into the callee's prototype.
+ * Basically mixin based inheritance, thus providing an alternative method for
+ * adding properties and methods to a class' prototype.
+ *
+ * <pre>
+ * function X() {}
+ * X.mixin({
+ * one: 1,
+ * two: 2,
+ * three: 3,
+ * doit: function() { return this.one + this.two + this.three; }
+ * });
+ *
+ * function Y() { }
+ * Y.mixin(X.prototype);
+ * Y.prototype.four = 15;
+ * Y.prototype.doit2 = function() { return this.doit() + this.four; }
+ * });
+ *
+ * // or
+ *
+ * function Y() { }
+ * Y.inherits(X);
+ * Y.mixin({
+ * one: 10,
+ * four: 15,
+ * doit2: function() { return this.doit() + this.four; }
+ * });
+ * </pre>
+ *
+ * @param {Object} source from which to copy properties.
+ * @see goog.mixin
+ * @deprecated
+ */
+Function.prototype.mixin = function(source) {
+ goog.mixin(this.prototype, source);
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/codemap.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/codemap.js
new file mode 100644
index 0000000..3766db0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/codemap.js
@@ -0,0 +1,230 @@
+// Copyright 2009 the V8 project authors. 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.
+
+
+// Initlialize namespaces
+var devtools = devtools || {};
+devtools.profiler = devtools.profiler || {};
+
+
+/**
+ * Constructs a mapper that maps addresses into code entries.
+ *
+ * @constructor
+ */
+devtools.profiler.CodeMap = function() {
+ /**
+ * Dynamic code entries. Used for JIT compiled code.
+ */
+ this.dynamics_ = new goog.structs.SplayTree();
+
+ /**
+ * Name generator for entries having duplicate names.
+ */
+ this.dynamicsNameGen_ = new devtools.profiler.CodeMap.NameGenerator();
+
+ /**
+ * Static code entries. Used for libraries code.
+ */
+ this.statics_ = new goog.structs.SplayTree();
+
+ /**
+ * Map of memory pages occupied with static code.
+ */
+ this.pages_ = [];
+};
+
+
+/**
+ * The number of alignment bits in a page address.
+ */
+devtools.profiler.CodeMap.PAGE_ALIGNMENT = 12;
+
+
+/**
+ * Page size in bytes.
+ */
+devtools.profiler.CodeMap.PAGE_SIZE =
+ 1 << devtools.profiler.CodeMap.PAGE_ALIGNMENT;
+
+
+/**
+ * Adds a dynamic (i.e. moveable and discardable) code entry.
+ *
+ * @param {number} start The starting address.
+ * @param {devtools.profiler.CodeMap.CodeEntry} codeEntry Code entry object.
+ */
+devtools.profiler.CodeMap.prototype.addCode = function(start, codeEntry) {
+ this.dynamics_.insert(start, codeEntry);
+};
+
+
+/**
+ * Moves a dynamic code entry. Throws an exception if there is no dynamic
+ * code entry with the specified starting address.
+ *
+ * @param {number} from The starting address of the entry being moved.
+ * @param {number} to The destination address.
+ */
+devtools.profiler.CodeMap.prototype.moveCode = function(from, to) {
+ var removedNode = this.dynamics_.remove(from);
+ this.dynamics_.insert(to, removedNode.value);
+};
+
+
+/**
+ * Discards a dynamic code entry. Throws an exception if there is no dynamic
+ * code entry with the specified starting address.
+ *
+ * @param {number} start The starting address of the entry being deleted.
+ */
+devtools.profiler.CodeMap.prototype.deleteCode = function(start) {
+ var removedNode = this.dynamics_.remove(start);
+};
+
+
+/**
+ * Adds a static code entry.
+ *
+ * @param {number} start The starting address.
+ * @param {devtools.profiler.CodeMap.CodeEntry} codeEntry Code entry object.
+ */
+devtools.profiler.CodeMap.prototype.addStaticCode = function(
+ start, codeEntry) {
+ this.markPages_(start, start + codeEntry.size);
+ this.statics_.insert(start, codeEntry);
+};
+
+
+/**
+ * @private
+ */
+devtools.profiler.CodeMap.prototype.markPages_ = function(start, end) {
+ for (var addr = start; addr <= end;
+ addr += devtools.profiler.CodeMap.PAGE_SIZE) {
+ this.pages_[addr >> devtools.profiler.CodeMap.PAGE_ALIGNMENT] = 1;
+ }
+};
+
+
+/**
+ * @private
+ */
+devtools.profiler.CodeMap.prototype.isAddressBelongsTo_ = function(addr, node) {
+ return addr >= node.key && addr < (node.key + node.value.size);
+};
+
+
+/**
+ * @private
+ */
+devtools.profiler.CodeMap.prototype.findInTree_ = function(tree, addr) {
+ var node = tree.findGreatestLessThan(addr);
+ return node && this.isAddressBelongsTo_(addr, node) ? node.value : null;
+};
+
+
+/**
+ * Finds a code entry that contains the specified address. Both static and
+ * dynamic code entries are considered.
+ *
+ * @param {number} addr Address.
+ */
+devtools.profiler.CodeMap.prototype.findEntry = function(addr) {
+ var pageAddr = addr >> devtools.profiler.CodeMap.PAGE_ALIGNMENT;
+ if (pageAddr in this.pages_) {
+ return this.findInTree_(this.statics_, addr);
+ }
+ var min = this.dynamics_.findMin();
+ var max = this.dynamics_.findMax();
+ if (max != null && addr < (max.key + max.value.size) && addr >= min.key) {
+ var dynaEntry = this.findInTree_(this.dynamics_, addr);
+ if (dynaEntry == null) return null;
+ // Dedupe entry name.
+ if (!dynaEntry.nameUpdated_) {
+ dynaEntry.name = this.dynamicsNameGen_.getName(dynaEntry.name);
+ dynaEntry.nameUpdated_ = true;
+ }
+ return dynaEntry;
+ }
+ return null;
+};
+
+
+/**
+ * Returns an array of all dynamic code entries, including deleted ones.
+ */
+devtools.profiler.CodeMap.prototype.getAllDynamicEntries = function() {
+ return this.dynamics_.exportValues();
+};
+
+
+/**
+ * Returns an array of all static code entries.
+ */
+devtools.profiler.CodeMap.prototype.getAllStaticEntries = function() {
+ return this.statics_.exportValues();
+};
+
+
+/**
+ * Creates a code entry object.
+ *
+ * @param {number} size Code entry size in bytes.
+ * @param {string} opt_name Code entry name.
+ * @constructor
+ */
+devtools.profiler.CodeMap.CodeEntry = function(size, opt_name) {
+ this.size = size;
+ this.name = opt_name || '';
+ this.nameUpdated_ = false;
+};
+
+
+devtools.profiler.CodeMap.CodeEntry.prototype.getName = function() {
+ return this.name;
+};
+
+
+devtools.profiler.CodeMap.CodeEntry.prototype.toString = function() {
+ return this.name + ': ' + this.size.toString(16);
+};
+
+
+devtools.profiler.CodeMap.NameGenerator = function() {
+ this.knownNames_ = [];
+};
+
+
+devtools.profiler.CodeMap.NameGenerator.prototype.getName = function(name) {
+ if (!(name in this.knownNames_)) {
+ this.knownNames_[name] = 0;
+ return name;
+ }
+ var count = ++this.knownNames_[name];
+ return name + ' {' + count + '}';
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/consarray.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/consarray.js
new file mode 100644
index 0000000..c67abb7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/consarray.js
@@ -0,0 +1,93 @@
+// Copyright 2009 the V8 project authors. 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.
+
+
+/**
+ * Constructs a ConsArray object. It is used mainly for tree traversal.
+ * In this use case we have lots of arrays that we need to iterate
+ * sequentally. The internal Array implementation is horribly slow
+ * when concatenating on large (10K items) arrays due to memory copying.
+ * That's why we avoid copying memory and insead build a linked list
+ * of arrays to iterate through.
+ *
+ * @constructor
+ */
+function ConsArray() {
+ this.tail_ = new ConsArray.Cell(null, null);
+ this.currCell_ = this.tail_;
+ this.currCellPos_ = 0;
+};
+
+
+/**
+ * Concatenates another array for iterating. Empty arrays are ignored.
+ * This operation can be safely performed during ongoing ConsArray
+ * iteration.
+ *
+ * @param {Array} arr Array to concatenate.
+ */
+ConsArray.prototype.concat = function(arr) {
+ if (arr.length > 0) {
+ this.tail_.data = arr;
+ this.tail_ = this.tail_.next = new ConsArray.Cell(null, null);
+ }
+};
+
+
+/**
+ * Whether the end of iteration is reached.
+ */
+ConsArray.prototype.atEnd = function() {
+ return this.currCell_ === null ||
+ this.currCell_.data === null ||
+ this.currCellPos_ >= this.currCell_.data.length;
+};
+
+
+/**
+ * Returns the current item, moves to the next one.
+ */
+ConsArray.prototype.next = function() {
+ var result = this.currCell_.data[this.currCellPos_++];
+ if (this.currCellPos_ >= this.currCell_.data.length) {
+ this.currCell_ = this.currCell_.next;
+ this.currCellPos_ = 0;
+ }
+ return result;
+};
+
+
+/**
+ * A cell object used for constructing a list in ConsArray.
+ *
+ * @constructor
+ */
+ConsArray.Cell = function(data, next) {
+ this.data = data;
+ this.next = next;
+};
+
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/csvparser.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/csvparser.js
new file mode 100644
index 0000000..9e58dea
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/csvparser.js
@@ -0,0 +1,98 @@
+// Copyright 2009 the V8 project authors. 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.
+
+
+// Initlialize namespaces.
+var devtools = devtools || {};
+devtools.profiler = devtools.profiler || {};
+
+
+/**
+ * Creates a CSV lines parser.
+ */
+devtools.profiler.CsvParser = function() {
+};
+
+
+/**
+ * A regex for matching a trailing quote.
+ * @private
+ */
+devtools.profiler.CsvParser.TRAILING_QUOTE_RE_ = /\"$/;
+
+
+/**
+ * A regex for matching a double quote.
+ * @private
+ */
+devtools.profiler.CsvParser.DOUBLE_QUOTE_RE_ = /\"\"/g;
+
+
+/**
+ * Parses a line of CSV-encoded values. Returns an array of fields.
+ *
+ * @param {string} line Input line.
+ */
+devtools.profiler.CsvParser.prototype.parseLine = function(line) {
+ var insideQuotes = false;
+ var fields = [];
+ var prevPos = 0;
+ for (var i = 0, n = line.length; i < n; ++i) {
+ switch (line.charAt(i)) {
+ case ',':
+ if (!insideQuotes) {
+ fields.push(line.substring(prevPos, i));
+ prevPos = i + 1;
+ }
+ break;
+ case '"':
+ if (!insideQuotes) {
+ insideQuotes = true;
+ // Skip the leading quote.
+ prevPos++;
+ } else {
+ if (i + 1 < n && line.charAt(i + 1) != '"') {
+ insideQuotes = false;
+ } else {
+ i++;
+ }
+ }
+ break;
+ }
+ }
+ if (n > 0) {
+ fields.push(line.substring(prevPos));
+ }
+
+ for (i = 0; i < fields.length; ++i) {
+ // Eliminate trailing quotes.
+ fields[i] = fields[i].replace(devtools.profiler.CsvParser.TRAILING_QUOTE_RE_, '');
+ // Convert quoted quotes into single ones.
+ fields[i] = fields[i].replace(devtools.profiler.CsvParser.DOUBLE_QUOTE_RE_, '"');
+ }
+ return fields;
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/debugger.css b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/debugger.css
new file mode 100644
index 0000000..ed9df2f
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/debugger.css
@@ -0,0 +1,35 @@
+/**
+ * Style for javascript debugger. See debugger.html.
+ */
+
+html,body {
+ margin: 0px;
+ padding: 0px;
+ height: 100%;
+}
+#output {
+ font-family: monospace;
+ background-color: #ffffff;
+ min-height: 100%;
+}
+#outer {
+ height: 100%;
+ width: 100%;
+ white-space: pre-wrap;
+ padding: 0px 0px 24px 0px;
+}
+#command-line {
+ bottom: 0px;
+ /* not quite sure why this 5px is necessary */
+ right: 5px;
+ left: 0px;
+ position: fixed;
+ padding: 0px;
+ margin: 0px;
+}
+#command-line-text {
+ height: 20px;
+ display: block;
+ width: 100%;
+ font-family: monospace;
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/debugger.html b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/debugger.html
new file mode 100644
index 0000000..f6bb917
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/debugger.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<!--
+ The UI for the javascript debugger window.
+-->
+ <head>
+ <title>JavaScript Debugger</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF8" />
+ <link rel="stylesheet" href="debugger.css" type="text/css" />
+ <script type="text/javascript" src="DebuggerConsole.js"></script>
+ <script type="text/javascript" src="DebuggerIPC.js"></script>
+ <script type="text/javascript" src="DebuggerShell.js"></script>
+ </head>
+
+ <body onload="onLoad();">
+
+ <table id='outer'>
+ <tr>
+ <td valign='bottom' id='output'>Chrome JavaScript Debugger<br />Type 'help' for a list of commands.<br /></td>
+ </tr>
+ </table>
+
+ <div id='command-line'>
+ <!-- TODO(erikkay) - use addEventListener instead -->
+ <input id='command-line-text'
+ type="text" />
+ </div>
+
+ </body>
+</html>
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/debugger_agent.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/debugger_agent.js
new file mode 100644
index 0000000..6eec36e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/debugger_agent.js
@@ -0,0 +1,1185 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Provides communication interface to remote v8 debugger. See
+ * protocol decription at http://code.google.com/p/v8/wiki/DebuggerProtocol
+ */
+goog.provide('devtools.DebuggerAgent');
+
+
+/**
+ * @constructor
+ */
+devtools.DebuggerAgent = function() {
+ RemoteDebuggerAgent.DebuggerOutput =
+ goog.bind(this.handleDebuggerOutput_, this);
+ RemoteDebuggerAgent.DidGetContextId =
+ goog.bind(this.didGetContextId_, this);
+ RemoteDebuggerAgent.DidIsProfilingStarted =
+ goog.bind(this.didIsProfilingStarted_, this);
+ RemoteDebuggerAgent.DidGetNextLogLines =
+ goog.bind(this.didGetNextLogLines_, 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 top frame.
+ * See JavaScriptCallFrame.idl.
+ * @type {?devtools.CallFrame}
+ */
+ this.currentCallFrame_ = null;
+
+ /**
+ * Whether to stop in the debugger on the exceptions.
+ * @type {boolean}
+ */
+ this.pauseOnExceptions_ = true;
+
+ /**
+ * Mapping: request sequence number->callback.
+ * @type {Object}
+ */
+ this.requestSeqToCallback_ = null;
+
+ /**
+ * Whether the scripts list has been requested.
+ * @type {boolean}
+ */
+ this.scriptsCacheInitialized_ = false;
+
+ /**
+ * Whether profiling session is started.
+ * @type {boolean}
+ */
+ this.isProfilingStarted_ = false;
+
+ /**
+ * Profiler processor instance.
+ * @type {devtools.profiler.Processor}
+ */
+ this.profilerProcessor_ = new devtools.profiler.Processor();
+};
+
+
+/**
+ * Resets debugger agent to its initial state.
+ */
+devtools.DebuggerAgent.prototype.reset = function() {
+ this.scriptsCacheInitialized_ = false;
+ this.contextId_ = null;
+ this.parsedScripts_ = {};
+ this.requestNumberToBreakpointInfo_ = {};
+ this.currentCallFrame_ = null;
+ this.requestSeqToCallback_ = {};
+
+ // Profiler isn't reset because it contains no data that is
+ // specific for a particular V8 instance. All such data is
+ // managed by an agent on the Render's side.
+};
+
+
+/**
+ * Requests scripts list if it has not been requested yet.
+ */
+devtools.DebuggerAgent.prototype.initializeScriptsCache = function() {
+ if (!this.scriptsCacheInitialized_) {
+ this.scriptsCacheInitialized_ = true;
+ this.requestScripts();
+ }
+};
+
+
+/**
+ * Asynchronously requests for all parsed script sources. Response will be
+ * processed in handleScriptsResponse_.
+ */
+devtools.DebuggerAgent.prototype.requestScripts = function() {
+ if (this.contextId_ === null) {
+ // Update context id first to filter the scripts.
+ RemoteDebuggerAgent.GetContextId();
+ return;
+ }
+ var cmd = new devtools.DebugCommand('scripts', {
+ 'includeSource': false
+ });
+ devtools.DebuggerAgent.sendCommand_(cmd);
+ // Force v8 execution so that it gets to processing the requested command.
+ devtools.tools.evaluateJavaScript('javascript:void(0)');
+};
+
+
+/**
+ * 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) {
+ 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.
+ devtools.tools.evaluateJavaScript('javascript:void(0)');
+
+ this.requestSeqToCallback_[cmd.getSequenceNumber()] = function(msg) {
+ if (msg.isSuccess()) {
+ var scriptJson = msg.getBody()[0];
+ callback(scriptJson.source);
+ } else {
+ callback(null);
+ }
+ };
+};
+
+
+/**
+ * Tells the v8 debugger to stop on as soon as possible.
+ */
+devtools.DebuggerAgent.prototype.pauseExecution = function() {
+ RemoteDebuggerAgent.DebugBreak();
+};
+
+
+/**
+ * @param {number} sourceId Id of the script fot the breakpoint.
+ * @param {number} line Number of the line for the breakpoint.
+ */
+devtools.DebuggerAgent.prototype.addBreakpoint = function(sourceId, line) {
+ var script = this.parsedScripts_[sourceId];
+ if (!script) {
+ return;
+ }
+
+ line = devtools.DebuggerAgent.webkitToV8LineNumber_(line);
+
+ var breakpointInfo = script.getBreakpointInfo(line);
+ if (breakpointInfo) {
+ return;
+ }
+
+ breakpointInfo = new devtools.BreakpointInfo(sourceId, line);
+ script.addBreakpointInfo(breakpointInfo);
+
+ var cmd = new devtools.DebugCommand('setbreakpoint', {
+ 'type': 'scriptId',
+ 'target': sourceId,
+ 'line': line
+ });
+
+ this.requestNumberToBreakpointInfo_[cmd.getSequenceNumber()] = breakpointInfo;
+
+ devtools.DebuggerAgent.sendCommand_(cmd);
+};
+
+
+/**
+ * @param {number} sourceId Id of the script fot 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 = script.getBreakpointInfo(line);
+ script.removeBreakpointInfo(breakpointInfo);
+ 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);
+ }
+};
+
+
+/**
+ * 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() {
+ var cmd = new devtools.DebugCommand('continue');
+ devtools.DebuggerAgent.sendCommand_(cmd);
+};
+
+
+/**
+ * @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;
+};
+
+
+/**
+ * Current stack top frame.
+ * @return {devtools.CallFrame}
+ */
+devtools.DebuggerAgent.prototype.getCurrentCallFrame = function() {
+ return this.currentCallFrame_;
+};
+
+
+/**
+ * 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.
+ */
+devtools.DebuggerAgent.prototype.resolveChildren = function(object, callback) {
+ if ('ref' in object) {
+ 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);
+ } else {
+ result.error = 'Failed to resolve children: ' + msg.getMessage();
+ }
+ object.resolvedValue = result;
+ callback(object);
+ });
+
+ return;
+ } else {
+ if (!object.resolvedValue) {
+ var message = 'Corrupted object: ' + JSON.stringify(object);
+ object.resolvedValue = {};
+ object.resolvedValue.error = message;
+ }
+ callback(object);
+ }
+};
+
+
+/**
+ * Sets up callbacks that deal with profiles processing.
+ */
+devtools.DebuggerAgent.prototype.setupProfilerProcessorCallbacks = function() {
+ // A temporary icon indicating that the profile is being processed.
+ var processingIcon = new WebInspector.SidebarTreeElement(
+ "profile-sidebar-tree-item", "Processing...", "", null, false);
+ var profilesSidebar = WebInspector.panels.profiles.sidebarTree;
+
+ this.profilerProcessor_.setCallbacks(
+ function onProfileProcessingStarted() {
+ profilesSidebar.appendChild(processingIcon);
+ },
+ function onProfileProcessingFinished(profile) {
+ profilesSidebar.removeChild(processingIcon);
+ WebInspector.addProfile(profile);
+ }
+ );
+};
+
+
+/**
+ * Initializes profiling state.
+ */
+devtools.DebuggerAgent.prototype.initializeProfiling = function() {
+ this.setupProfilerProcessorCallbacks();
+ RemoteDebuggerAgent.IsProfilingStarted();
+};
+
+
+/**
+ * Starts (resumes) profiling.
+ */
+devtools.DebuggerAgent.prototype.startProfiling = function() {
+ RemoteDebuggerAgent.StartProfiling();
+ RemoteDebuggerAgent.IsProfilingStarted();
+};
+
+
+/**
+ * Stops (pauses) profiling.
+ */
+devtools.DebuggerAgent.prototype.stopProfiling = function() {
+ RemoteDebuggerAgent.StopProfiling();
+};
+
+
+/**
+ * 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);
+};
+
+
+/**
+ * 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) {
+ 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;
+};
+
+
+/**
+ * Handles GetContextId response.
+ * @param {number} contextId Id of the inspected page global context.
+ */
+devtools.DebuggerAgent.prototype.didGetContextId_ = function(contextId) {
+ this.contextId_ = contextId;
+ // Update scripts.
+ this.requestScripts();
+};
+
+
+/**
+ * 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 reponse:\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.handleScriptsResponse_(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);
+ }
+ }
+};
+
+
+/**
+ * @param {devtools.DebuggerMessage} msg
+ */
+devtools.DebuggerAgent.prototype.handleBreakEvent_ = function(msg) {
+ var body = msg.getBody();
+
+ var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(body.sourceLine);
+ this.currentCallFrame_ = new devtools.CallFrame();
+ this.currentCallFrame_.sourceID = body.script.id;
+ this.currentCallFrame_.line = line;
+ this.currentCallFrame_.script = body.script;
+ this.requestBacktrace_();
+};
+
+
+/**
+ * @param {devtools.DebuggerMessage} msg
+ */
+devtools.DebuggerAgent.prototype.handleExceptionEvent_ = function(msg) {
+ var body = msg.getBody();
+ debugPrint('Uncaught exception in ' + body.script.name + ':' +
+ body.sourceLine + '\n' + body.sourceLineText);
+ if (this.pauseOnExceptions_) {
+ var body = msg.getBody();
+
+ var sourceId = -1;
+ // The exception may happen in native code in which case there is no script.
+ if (body.script) {
+ sourceId = body.script.id;
+ }
+
+ var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(body.sourceLine);
+
+ this.currentCallFrame_ = new devtools.CallFrame();
+ this.currentCallFrame_.sourceID = sourceId;
+ this.currentCallFrame_.line = line;
+ this.currentCallFrame_.script = body.script;
+ this.requestBacktrace_();
+ } else {
+ this.resumeExecution();
+ }
+};
+
+
+/**
+ * @param {devtools.DebuggerMessage} msg
+ */
+devtools.DebuggerAgent.prototype.handleScriptsResponse_ = function(msg) {
+ if (this.invokeCallbackForResponse_(msg)) {
+ return;
+ }
+
+ 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);
+ }
+};
+
+
+/**
+ * @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 (!goog.isDef(scriptContextId)) {
+ return false; // Always ignore scripts from the utility context.
+ }
+ if (this.contextId_ === null) {
+ return true;
+ }
+ return (scriptContextId == 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) {
+ var script = msg.getBody().script;
+ // Ignore scripts from other tabs.
+ if (!this.isScriptFromInspectedContext_(script, msg)) {
+ return;
+ }
+ this.addScriptInfo_(script);
+};
+
+
+/**
+ * Handles current profiler status.
+ */
+devtools.DebuggerAgent.prototype.didIsProfilingStarted_ = function(
+ is_started) {
+ if (is_started && !this.isProfilingStarted_) {
+ // Start to query log data.
+ RemoteDebuggerAgent.GetNextLogLines();
+ }
+ this.isProfilingStarted_ = is_started;
+ // Update button.
+ WebInspector.setRecordingProfile(is_started);
+ if (is_started) {
+ // Monitor profiler state. It can stop itself on buffer fill-up.
+ setTimeout(function() { RemoteDebuggerAgent.IsProfilingStarted(); }, 1000);
+ }
+};
+
+
+/**
+ * Handles a portion of a profiler log retrieved by GetNextLogLines call.
+ * @param {string} log A portion of profiler log.
+ */
+devtools.DebuggerAgent.prototype.didGetNextLogLines_ = function(log) {
+ if (log.length > 0) {
+ this.profilerProcessor_.processLogChunk(log);
+ } else if (!this.isProfilingStarted_) {
+ // No new data and profiling is stopped---suspend log reading.
+ return;
+ }
+ setTimeout(function() { RemoteDebuggerAgent.GetNextLogLines(); }, 500);
+};
+
+
+/**
+ * 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.
+ */
+devtools.DebuggerAgent.prototype.addScriptInfo_ = function(script) {
+ this.parsedScripts_[script.id] = new devtools.ScriptInfo(
+ script.id, script.lineOffset);
+ 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.currentCallFrame_) {
+ return;
+ }
+
+ var script = this.currentCallFrame_.script;
+
+ var callerFrame = null;
+ var f = null;
+ var frames = msg.getBody().frames;
+ for (var i = frames.length - 1; i>=0; i--) {
+ var nextFrame = frames[i];
+ var f = devtools.DebuggerAgent.formatCallFrame_(nextFrame, script, msg);
+ f.frameNumber = i;
+ f.caller = callerFrame;
+ callerFrame = f;
+ }
+
+ this.currentCallFrame_ = f;
+
+ WebInspector.pausedScript();
+ DevToolsHost.activateWindow();
+};
+
+
+/**
+ * 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;
+};
+
+
+devtools.DebuggerAgent.prototype.evaluateInCallFrame_ = function(expression) {
+};
+
+
+/**
+ * @param {Object} stackFrame Frame json object from 'backtrace' response.
+ * @param {Object} script Script json object from 'break' event.
+ * @param {devtools.DebuggerMessage} msg Parsed 'backtrace' response.
+ * @return {!devtools.CallFrame} Object containing information related to the
+ * call frame in the format expected by ScriptsPanel and its panes.
+ */
+devtools.DebuggerAgent.formatCallFrame_ = function(stackFrame, script, msg) {
+ var sourceId = script.id;
+
+ var func = stackFrame.func;
+ var sourceId = func.scriptId;
+ var funcName = func.name || func.inferredName || '(anonymous function)';
+
+ var scope = {};
+
+ // Add arguments.
+ devtools.DebuggerAgent.argumentsArrayToMap_(stackFrame.arguments, scope);
+
+ // Add local variables.
+ devtools.DebuggerAgent.propertiesToMap_(stackFrame.locals, scope);
+
+ var thisObject = devtools.DebuggerAgent.formatObjectReference_(
+ stackFrame.receiver);
+ // Add variable with name 'this' to the scope.
+ scope['this'] = thisObject;
+
+ var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(stackFrame.line);
+ var result = new devtools.CallFrame();
+ result.sourceID = sourceId;
+ result.line = line;
+ result.type = 'function';
+ result.functionName = funcName;
+ result.localScope = scope;
+ result.scopeChain = [scope];
+ result.thisObject = thisObject;
+ return result;
+};
+
+
+/**
+ * Collects properties for an object from the debugger response.
+ * @param {Object} object An object from the debugger protocol response.
+ * @param {Object} result A map to put the properties in.
+ */
+devtools.DebuggerAgent.formatObjectProperties_ = function(object, result) {
+ devtools.DebuggerAgent.propertiesToMap_(object.properties, result);
+ result.protoObject = devtools.DebuggerAgent.formatObjectReference_(
+ object.protoObject);
+ result.prototypeObject = devtools.DebuggerAgent.formatObjectReference_(
+ object.prototypeObject);
+ result.constructorFunction = devtools.DebuggerAgent.formatObjectReference_(
+ object.constructorFunction);
+};
+
+
+/**
+ * For each property in 'properties' puts its name and user-friendly value into
+ * 'map'.
+ * @param {Array.<Object>} properties Receiver properties or locals array from
+ * 'backtrace' response.
+ * @param {Object} map Result holder.
+ */
+devtools.DebuggerAgent.propertiesToMap_ = function(properties, map) {
+ for (var j = 0; j < properties.length; j++) {
+ var nextValue = properties[j];
+ // Skip unnamed properties. They may appear e.g. when number of actual
+ // parameters is greater the that of formal. In that case the superfluous
+ // parameters will be present in the arguments list as elements without
+ // names.
+ if (nextValue.name) {
+ map[nextValue.name] =
+ devtools.DebuggerAgent.formatObjectReference_(nextValue.value);
+ }
+ }
+};
+
+
+/**
+ * Puts arguments from the protocol arguments array to the map assigning names
+ * to the anonymous arguments.
+ * @param {Array.<Object>} array Arguments array from 'backtrace' response.
+ * @param {Object} map Result holder.
+ */
+devtools.DebuggerAgent.argumentsArrayToMap_ = function(array, map) {
+ for (var j = 0; j < array.length; j++) {
+ var nextValue = array[j];
+ // Skip unnamed properties. They may appear e.g. when number of actual
+ // parameters is greater the that of formal. In that case the superfluous
+ // parameters will be present in the arguments list as elements without
+ // names.
+ var name = nextValue.name ? nextValue.name : '<arg #' + j + '>';
+ map[name] = devtools.DebuggerAgent.formatObjectReference_(nextValue.value);
+ }
+};
+
+
+/**
+ * @param {Object} v An object reference from the debugger response.
+ * @return {*} The value representation expected by ScriptsPanel.
+ */
+devtools.DebuggerAgent.formatObjectReference_ = function(v) {
+ if (v.type == 'object') {
+ return v;
+ } else if (v.type == 'function') {
+ var f = function() {};
+ f.ref = v.ref;
+ return f;
+ } else if (goog.isDef(v.value)) {
+ return v.value;
+ } else if (v.type == 'undefined') {
+ return 'undefined';
+ } else if (v.type == 'null') {
+ return 'null';
+ } else if (v.name) {
+ return v.name;
+ } else if (v.className) {
+ return v.className;
+ } else {
+ return '<unresolved ref: ' + v.ref + ', type: ' + v.type + '>';
+ }
+};
+
+
+/**
+ * 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 {number} lineOffset First line 0-based offset in the containing
+ * document.
+ * @constructor
+ */
+devtools.ScriptInfo = function(scriptId, lineOffset) {
+ this.scriptId_ = scriptId;
+ this.lineOffset_ = lineOffset;
+
+ this.lineToBreakpointInfo_ = {};
+};
+
+
+/**
+ * @return {number}
+ */
+devtools.ScriptInfo.prototype.getLineOffset = function() {
+ return this.lineOffset_;
+};
+
+
+/**
+ * @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} scriptId Id of the owning script.
+ * @param {number} line Breakpoint 0-based line number in the containing script.
+ * @constructor
+ */
+devtools.BreakpointInfo = function(sourceId, line) {
+ this.sourceId_ = sourceId;
+ this.line_ = line;
+ this.v8id_ = -1;
+ this.removed_ = false;
+};
+
+
+/**
+ * @return {number}
+ */
+devtools.BreakpointInfo.prototype.getSourceId = function(n) {
+ return this.sourceId_;
+};
+
+
+/**
+ * @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.
+ * @construnctor
+ */
+devtools.CallFrame = function() {
+ this.sourceID = null;
+ this.line = null;
+ this.type = 'function';
+ this.functionName = null;
+ this.caller = null;
+ this.localScope = null;
+ this.scopeChain = [];
+ this.thisObject = {};
+ this.frameNumber = null;
+};
+
+
+/**
+ * This method is called by
+ * WebInspector.ScriptsPanel.evaluateInSelectedCallFrame. This method issues
+ * asynchronous evaluate request.
+ * @param {string} expression An expression to be evaluated in the context of
+ * this call frame.
+ * @return {string} User message that the expression is being evaluated.
+ */
+devtools.CallFrame.prototype.evaluate = function(expression) {
+ devtools.tools.getDebuggerAgent().requestEvaluate({
+ 'expression': expression,
+ 'frame': this.frameNumber,
+ 'global': false,
+ 'disable_break': false
+ },
+ devtools.CallFrame.handleEvaluateResponse_);
+ return 'evaluating...';
+};
+
+
+/**
+ * Handles 'evaluate' response for a call frame
+ * @param {devtools.DebuggerMessage} response
+ */
+devtools.CallFrame.handleEvaluateResponse_ = function(response) {
+ var body = response.getBody();
+ var value = devtools.DebuggerAgent.formatObjectReference_(body);
+ WebInspector.console.addMessage(new WebInspector.ConsoleCommandResult(
+ value, false /* exception */, null /* commandMessage */));
+};
+
+
+/**
+ * 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) {
+ var jsExpression = '[' + msg + '][0]';
+ this.packet_ = eval(jsExpression);
+ 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/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/devtools.html b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/devtools.html
new file mode 100644
index 0000000..018573d
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/devtools.html
@@ -0,0 +1,126 @@
+<!--
+Copyright (c) 2009 The Chromium Authors. All rights reserved.
+
+This is the Chromium version of the WebInspector. This html file serves
+as a deployment descriptor and specifies which js libraries to include into the
+app. Once the "main" frontend method that is building WebInspector
+from the js building blocks is extracted, we will be able have different
+implementations of it for Chromium and WebKit. That would allow us for
+example not to create WebKit Database tab and remove corresponding js files
+from here. Longer term we would like to employ closure + basic js compilation.
+That way js libraries would know their dependencies and js compiler would be
+able to compile them into a single file. After that this HTML file will
+include single <script src='fe-compiled.js'> and will become upstreamable.
+
+Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <link rel="stylesheet" type="text/css" href="inspector.css">
+ <script type="text/javascript" src="base.js"></script>
+ <script type="text/javascript" src="utilities.js"></script>
+ <script type="text/javascript" src="treeoutline.js"></script>
+ <script type="text/javascript" src="devtools_callback.js"></script>
+ <script type="text/javascript" src="debugger_agent.js"></script>
+ <script type="text/javascript" src="dom_agent.js"></script>
+ <script type="text/javascript" src="inspector_controller.js"></script>
+ <script type="text/javascript" src="inspector_controller_impl.js"></script>
+ <script type="text/javascript" src="inspector.js"></script>
+ <script type="text/javascript" src="codemap.js"></script>
+ <script type="text/javascript" src="consarray.js"></script>
+ <script type="text/javascript" src="csvparser.js"></script>
+ <script type="text/javascript" src="profile.js"></script>
+ <script type="text/javascript" src="profile_view.js"></script>
+ <script type="text/javascript" src="profiler_processor.js"></script>
+ <script type="text/javascript" src="splaytree.js"></script>
+ <script type="text/javascript" src="Object.js"></script>
+ <script type="text/javascript" src="TextPrompt.js"></script>
+ <script type="text/javascript" src="Placard.js"></script>
+ <script type="text/javascript" src="View.js"></script>
+ <script type="text/javascript" src="Console.js"></script>
+ <script type="text/javascript" src="Resource.js"></script>
+ <script type="text/javascript" src="ResourceCategory.js"></script>
+ <script type="text/javascript" src="Database.js"></script>
+ <script type="text/javascript" src="DOMStorage.js"></script>
+ <script type="text/javascript" src="DOMStorageItemsView.js"></script>
+ <script type="text/javascript" src="DataGrid.js"></script>
+ <script type="text/javascript" src="DOMStorageDataGrid.js"></script>
+ <script type="text/javascript" src="Script.js"></script>
+ <script type="text/javascript" src="Breakpoint.js"></script>
+ <script type="text/javascript" src="SidebarPane.js"></script>
+ <script type="text/javascript" src="ElementsTreeOutline.js"></script>
+ <script type="text/javascript" src="SidebarTreeElement.js"></script>
+ <script type="text/javascript" src="PropertiesSection.js"></script>
+ <script type="text/javascript" src="ObjectPropertiesSection.js"></script>
+ <script type="text/javascript" src="BreakpointsSidebarPane.js"></script>
+ <script type="text/javascript" src="CallStackSidebarPane.js"></script>
+ <script type="text/javascript" src="ScopeChainSidebarPane.js"></script>
+ <script type="text/javascript" src="MetricsSidebarPane.js"></script>
+ <script type="text/javascript" src="PropertiesSidebarPane.js"></script>
+ <script type="text/javascript" src="StylesSidebarPane.js"></script>
+ <script type="text/javascript" src="Panel.js"></script>
+ <script type="text/javascript" src="PanelEnablerView.js"></script>
+ <script type="text/javascript" src="ElementsPanel.js"></script>
+ <script type="text/javascript" src="ResourcesPanel.js"></script>
+ <script type="text/javascript" src="ScriptsPanel.js"></script>
+ <script type="text/javascript" src="DatabasesPanel.js"></script>
+ <script type="text/javascript" src="ProfilesPanel.js"></script>
+ <script type="text/javascript" src="ResourceView.js"></script>
+ <script type="text/javascript" src="SourceFrame.js"></script>
+ <script type="text/javascript" src="SourceView.js"></script>
+ <script type="text/javascript" src="FontView.js"></script>
+ <script type="text/javascript" src="ImageView.js"></script>
+ <script type="text/javascript" src="DatabaseTableView.js"></script>
+ <script type="text/javascript" src="DatabaseQueryView.js"></script>
+ <script type="text/javascript" src="ScriptView.js"></script>
+ <script type="text/javascript" src="ProfileView.js"></script>
+ <script type="text/javascript" src="ProfileDataGridTree.js"></script>
+ <script type="text/javascript" src="BottomUpProfileDataGridTree.js"></script>
+ <script type="text/javascript" src="TopDownProfileDataGridTree.js"></script>
+ <script type="text/javascript" src="devtools.js"></script>
+ <script type="text/javascript" src="devtools_host_stub.js"></script>
+ <script type="text/javascript" src="tests.js"></script>
+</head>
+<body class="detached">
+ <div id="toolbar">
+ <div class="toolbar-item close"><button id="close-button"></button></div>
+ <div class="toolbar-item flexable-space"></div>
+ <div class="toolbar-item hidden" id="search-results-matches"></div>
+ <div class="toolbar-item"><input id="search" type="search" incremental results="0"><div id="search-toolbar-label" class="toolbar-label"></div></div>
+ </div>
+ <div id="main">
+ <div id="main-panels" tabindex="0"></div>
+ <div id="main-status-bar" class="status-bar"><div id="anchored-status-bar-items"><button id="dock-status-bar-item" class="status-bar-item toggled"></button><button id="console-status-bar-item" class="status-bar-item"></button><div id="error-warning-count" class="hidden"></div></div></div>
+ </div>
+ <div id="console">
+ <div id="console-messages"><div id="console-prompt"><br></div></div>
+ <div id="console-status-bar" class="status-bar"><div id="other-console-status-bar-items"><button id="clear-console-status-bar-item" class="status-bar-item"></button></div></div>
+ </div>
+</body>
+</html>
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/devtools.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/devtools.js
new file mode 100644
index 0000000..ac88652
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/devtools.js
@@ -0,0 +1,896 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @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.
+ */
+goog.provide('devtools.Tools');
+
+goog.require('devtools.DebuggerAgent');
+goog.require('devtools.DomAgent');
+
+
+/**
+ * Dispatches raw message from the host.
+ * @param {string} remoteName
+ * @prama {string} methodName
+ * @param {Object} msg Message to dispatch.
+ */
+devtools.dispatch = function(remoteName, methodName, msg) {
+ 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.apply(this, msg);
+};
+
+
+devtools.ToolsAgent = function() {
+ RemoteToolsAgent.DidEvaluateJavaScript = devtools.Callback.processCallback;
+ RemoteToolsAgent.DidExecuteUtilityFunction =
+ devtools.Callback.processCallback;
+ RemoteToolsAgent.UpdateFocusedNode =
+ goog.bind(this.updateFocusedNode_, this);
+ RemoteToolsAgent.FrameNavigate =
+ goog.bind(this.frameNavigate_, this);
+ RemoteToolsAgent.AddMessageToConsole =
+ goog.bind(this.addMessageToConsole_, this);
+ RemoteToolsAgent.DispatchOnClient =
+ goog.bind(this.dispatchOnClient_, this);
+ RemoteToolsAgent.DidGetResourceContent =
+ devtools.Callback.processCallback;
+ RemoteToolsAgent.SetResourcesPanelEnabled =
+ goog.bind(this.setResourcesPanelEnabled_, this);
+ this.debuggerAgent_ = new devtools.DebuggerAgent();
+ this.domAgent_ = new devtools.DomAgent();
+};
+
+
+/**
+ * Resets tools agent to its initial state.
+ */
+devtools.ToolsAgent.prototype.reset = function() {
+ DevToolsHost.reset();
+ this.domAgent_.reset();
+ this.debuggerAgent_.reset();
+
+ this.domAgent_.getDocumentElementAsync();
+};
+
+
+/**
+ * @param {string} script Script exression to be evaluated in the context of the
+ * inspected page.
+ * @param {function(string):undefined} callback Function to call with the
+ * result.
+ */
+devtools.ToolsAgent.prototype.evaluateJavaScript = function(script, callback) {
+ var callbackId = devtools.Callback.wrap(callback);
+ RemoteToolsAgent.EvaluateJavaScript(callbackId, script);
+};
+
+
+/**
+ * @return {devtools.DebuggerAgent} Debugger agent instance.
+ */
+devtools.ToolsAgent.prototype.getDebuggerAgent = function() {
+ return this.debuggerAgent_;
+};
+
+/**
+ * DomAgent accessor.
+ * @return {devtools.DomAgent} Dom agent instance.
+ */
+devtools.ToolsAgent.prototype.getDomAgent = function() {
+ return this.domAgent_;
+};
+
+
+/**
+ * @see tools_agent.h
+ * @private
+ */
+devtools.ToolsAgent.prototype.updateFocusedNode_ = function(nodeId) {
+ var node = this.domAgent_.getNodeForId(nodeId);
+ WebInspector.updateFocusedNode(node);
+};
+
+
+/**
+ * @param {string} url Url frame navigated to.
+ * @param {bool} topLevel True iff top level navigation occurred.
+ * @see tools_agent.h
+ * @private
+ */
+devtools.ToolsAgent.prototype.frameNavigate_ = function(url, topLevel) {
+ if (topLevel) {
+ 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 {Object} message Message object to add.
+ * @see tools_agent.h
+ * @private
+ */
+devtools.ToolsAgent.prototype.addMessageToConsole_ = function(message) {
+ var console = WebInspector.console;
+ if (console) {
+ console.addMessage(new WebInspector.ConsoleMessage(
+ message.source, message.level, message.line, message.sourceId,
+ undefined, 1, message.text));
+ }
+};
+
+
+/**
+ * @param {string} message Serialized call to be dispatched on WebInspector.
+ * @private
+ */
+devtools.ToolsAgent.prototype.dispatchOnClient_ = function(message) {
+ var messageObj = JSON.parse(message);
+ WebInspector.dispatch.apply(WebInspector, messageObj);
+};
+
+
+/**
+ * Evaluates js expression.
+ * @param {string} expr
+ */
+devtools.ToolsAgent.prototype.evaluate = function(expr) {
+ RemoteToolsAgent.evaluate(expr);
+};
+
+
+/**
+ * Asynchronously queries for the resource content.
+ * @param {number} identifier Resource identifier.
+ * @param {function(string):undefined} opt_callback Callback to call when
+ * result is available.
+ */
+devtools.ToolsAgent.prototype.getResourceContentAsync = function(identifier,
+ opt_callback) {
+ var resource = WebInspector.resources[identifier];
+ if (!resource) {
+ return;
+ }
+ RemoteToolsAgent.GetResourceContent(
+ devtools.Callback.wrap(opt_callback), identifier);
+};
+
+
+/**
+ * Enables / disables resource tracking.
+ * @param {boolean} enabled Sets tracking status.
+ * @param {boolean} always Determines whether tracking status should be sticky.
+ */
+devtools.ToolsAgent.prototype.setResourceTrackingEnabled = function(enabled,
+ always) {
+ RemoteToolsAgent.SetResourceTrackingEnabled(enabled, always);
+};
+
+
+/**
+ * Enables / disables resources panel in the ui.
+ * @param {boolean} enabled New panel status.
+ */
+devtools.ToolsAgent.prototype.setResourcesPanelEnabled_ = function(enabled) {
+ InspectorController.resourceTrackingEnabled_ = enabled;
+ // TODO(pfeldman): Extract this upstream.
+ var panel = WebInspector.panels.resources;
+ if (enabled) {
+ panel.enableToggleButton.title =
+ WebInspector.UIString("Resource tracking enabled. Click to disable.");
+ panel.enableToggleButton.addStyleClass("toggled-on");
+ panel.largerResourcesButton.removeStyleClass("hidden");
+ panel.sortingSelectElement.removeStyleClass("hidden");
+ panel.panelEnablerView.visible = false;
+ } else {
+ panel.enableToggleButton.title =
+ WebInspector.UIString("Resource tracking disabled. Click to enable.");
+ panel.enableToggleButton.removeStyleClass("toggled-on");
+ panel.largerResourcesButton.addStyleClass("hidden");
+ panel.sortingSelectElement.addStyleClass("hidden");
+ panel.panelEnablerView.visible = true;
+ }
+};
+
+
+/**
+ * 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(
+ '', undefined, 1, '', 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;
+ oldLoaded.call(this);
+
+ DevToolsHost.loaded();
+};
+
+
+var webkitUpdateChildren =
+ WebInspector.ElementsTreeElement.prototype.updateChildren;
+
+
+/**
+ * @override
+ */
+WebInspector.ElementsTreeElement.prototype.updateChildren = function() {
+ var self = this;
+ devtools.tools.getDomAgent().getChildNodesAsync(this.representedObject,
+ function() {
+ webkitUpdateChildren.call(self);
+ });
+};
+
+
+/**
+ * @override
+ */
+WebInspector.ElementsPanel.prototype.performSearch = function(query) {
+ this.searchCanceled();
+ devtools.tools.getDomAgent().performSearch(query,
+ goog.bind(this.performSearchCallback_, this));
+};
+
+
+WebInspector.ElementsPanel.prototype.performSearchCallback_ = function(nodes) {
+ for (var i = 0; i < nodes.length; ++i) {
+ var treeElement = this.treeOutline.findTreeElement(nodes[i]);
+ if (treeElement)
+ treeElement.highlighted = true;
+ }
+
+ if (nodes.length) {
+ this.currentSearchResultIndex_ = 0;
+ this.focusedDOMNode = nodes[0];
+ }
+
+ this.searchResultCount_ = nodes.length;
+};
+
+
+/**
+ * @override
+ */
+WebInspector.ElementsPanel.prototype.searchCanceled = function() {
+ this.currentSearchResultIndex_ = 0;
+ this.searchResultCount_ = 0;
+ devtools.tools.getDomAgent().searchCanceled(
+ goog.bind(this.searchCanceledCallback_, this));
+};
+
+
+WebInspector.ElementsPanel.prototype.searchCanceledCallback_ = function(nodes) {
+ for (var i = 0; i < nodes.length; i++) {
+ var treeElement = this.treeOutline.findTreeElement(nodes[i]);
+ if (treeElement)
+ treeElement.highlighted = false;
+ }
+};
+
+
+/**
+ * @override
+ */
+WebInspector.ElementsPanel.prototype.jumpToNextSearchResult = function() {
+ if (!this.searchResultCount_)
+ return;
+
+ if (++this.currentSearchResultIndex_ >= this.searchResultCount_)
+ this.currentSearchResultIndex_ = 0;
+
+ this.focusedDOMNode = devtools.tools.getDomAgent().
+ getSearchResultNode(this.currentSearchResultIndex_);
+};
+
+
+/**
+ * @override
+ */
+WebInspector.ElementsPanel.prototype.jumpToPreviousSearchResult = function() {
+ if (!this.searchResultCount_)
+ return;
+
+ if (--this.currentSearchResultIndex_ < 0)
+ this.currentSearchResultIndex_ = this.searchResultCount_ - 1;
+
+ this.focusedDOMNode = devtools.tools.getDomAgent().
+ getSearchResultNode(this.currentSearchResultIndex_);
+};
+
+
+/**
+ * @override
+ */
+WebInspector.Console.prototype._evalInInspectedWindow = function(expr) {
+ return devtools.tools.evaluate(expr);
+};
+
+
+/**
+ * Disable autocompletion in the console.
+ * TODO(yurys): change WebKit implementation to allow asynchronous completion.
+ * @override
+ */
+WebInspector.Console.prototype.completions = function(
+ wordRange, bestMatchOnly) {
+ return null;
+};
+
+
+/**
+ * @override
+ */
+WebInspector.ElementsPanel.prototype.updateStyles = function(forceUpdate) {
+ var stylesSidebarPane = this.sidebarPanes.styles;
+ if (!stylesSidebarPane.expanded || !stylesSidebarPane.needsUpdate) {
+ return;
+ }
+ this.invokeWithStyleSet_(function(node) {
+ stylesSidebarPane.needsUpdate = !!node;
+ stylesSidebarPane.update(node, null, forceUpdate);
+ });
+};
+
+
+/**
+ * @override
+ */
+WebInspector.ElementsPanel.prototype.updateMetrics = function() {
+ var metricsSidebarPane = this.sidebarPanes.metrics;
+ if (!metricsSidebarPane.expanded || !metricsSidebarPane.needsUpdate) {
+ return;
+ }
+ this.invokeWithStyleSet_(function(node) {
+ metricsSidebarPane.needsUpdate = !!node;
+ metricsSidebarPane.update(node);
+ });
+};
+
+
+/**
+ * Temporarily sets style fetched from the inspectable tab to the currently
+ * focused node, invokes updateUI callback and clears the styles.
+ * @param {function(Node):undefined} updateUI Callback to call while styles are
+ * set.
+ */
+WebInspector.ElementsPanel.prototype.invokeWithStyleSet_ =
+ function(updateUI) {
+ var node = this.focusedDOMNode;
+ if (node && node.nodeType === Node.TEXT_NODE && node.parentNode)
+ node = node.parentNode;
+
+ if (node && node.nodeType == Node.ELEMENT_NODE) {
+ var callback = function(stylesStr) {
+ var styles = JSON.parse(stylesStr);
+ if (!styles.computedStyle) {
+ return;
+ }
+ node.setStyles(styles.computedStyle, styles.inlineStyle,
+ styles.styleAttributes, styles.matchedCSSRules);
+ updateUI(node);
+ node.clearStyles();
+ };
+ devtools.tools.getDomAgent().getNodeStylesAsync(
+ node,
+ !Preferences.showUserAgentStyles,
+ callback);
+ } else {
+ updateUI(null);
+ }
+};
+
+
+/**
+ * @override
+ */
+WebInspector.MetricsSidebarPane.prototype.editingCommitted =
+ function(element, userInput, previousContent, context) {
+ if (userInput === previousContent) {
+ // nothing changed, so cancel
+ return this.editingCancelled(element, context);
+ }
+
+ if (context.box !== "position" && (!userInput || userInput === "\u2012")) {
+ userInput = "0px";
+ } else if (context.box === "position" &&
+ (!userInput || userInput === "\u2012")) {
+ userInput = "auto";
+ }
+
+ // Append a "px" unit if the user input was just a number.
+ if (/^\d+$/.test(userInput)) {
+ userInput += "px";
+ }
+ devtools.tools.getDomAgent().setStylePropertyAsync(
+ this.node,
+ context.styleProperty,
+ userInput,
+ WebInspector.updateStylesAndMetrics_);
+};
+
+
+/**
+ * @override
+ */
+WebInspector.PropertiesSidebarPane.prototype.update = function(object) {
+ var body = this.bodyElement;
+ body.removeChildren();
+
+ this.sections = [];
+
+ if (!object) {
+ return;
+ }
+
+
+ var self = this;
+ devtools.tools.getDomAgent().getNodePrototypesAsync(object.id_,
+ function(json) {
+ // Get array of prototype user-friendly names.
+ var prototypes = JSON.parse(json);
+ for (var i = 0; i < prototypes.length; ++i) {
+ var prototype = {};
+ prototype.id_ = object.id_;
+ prototype.protoDepth_ = i;
+ var section = new WebInspector.SidebarObjectPropertiesSection(
+ prototype,
+ prototypes[i]);
+ self.sections.push(section);
+ body.appendChild(section.element);
+ }
+ });
+};
+
+
+/**
+ * Our implementation of ObjectPropertiesSection for Elements tab.
+ * @constructor
+ */
+WebInspector.SidebarObjectPropertiesSection = function(object, title) {
+ WebInspector.ObjectPropertiesSection.call(this, object, title,
+ null /* subtitle */, null /* emptyPlaceholder */,
+ null /* ignoreHasOwnProperty */, null /* extraProperties */,
+ WebInspector.SidebarObjectPropertyTreeElement /* treeElementConstructor */
+ );
+};
+goog.inherits(WebInspector.SidebarObjectPropertiesSection,
+ WebInspector.ObjectPropertiesSection);
+
+
+/**
+ * @override
+ */
+WebInspector.SidebarObjectPropertiesSection.prototype.onpopulate = function() {
+ var nodeId = this.object.id_;
+ var protoDepth = this.object.protoDepth_;
+ var path = [];
+ devtools.tools.getDomAgent().getNodePropertiesAsync(nodeId, path, protoDepth,
+ goog.partial(WebInspector.didGetNodePropertiesAsync_,
+ this.propertiesTreeOutline,
+ this.treeElementConstructor,
+ nodeId,
+ path));
+};
+
+
+/**
+ * Our implementation of ObjectPropertyTreeElement for Elements tab.
+ * @constructor
+ */
+WebInspector.SidebarObjectPropertyTreeElement = function(parentObject,
+ propertyName) {
+ WebInspector.ObjectPropertyTreeElement.call(this, parentObject,
+ propertyName);
+};
+goog.inherits(WebInspector.SidebarObjectPropertyTreeElement,
+ WebInspector.ObjectPropertyTreeElement);
+
+
+/**
+ * @override
+ */
+WebInspector.SidebarObjectPropertyTreeElement.prototype.onpopulate =
+ function() {
+ var nodeId = this.parentObject.devtools$$nodeId_;
+ var path = this.parentObject.devtools$$path_.slice(0);
+ path.push(this.propertyName);
+ devtools.tools.getDomAgent().getNodePropertiesAsync(nodeId, path, -1,
+ goog.partial(
+ WebInspector.didGetNodePropertiesAsync_,
+ this,
+ this.treeOutline.section.treeElementConstructor,
+ nodeId, path));
+};
+
+
+/**
+ * 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 || '<source is not available>';
+ self.didResolveScriptSource_();
+ });
+ }
+};
+
+
+/**
+ * Performs source frame setup when script source is aready resolved.
+ */
+WebInspector.ScriptView.prototype.didResolveScriptSource_ = function() {
+ if (!InspectorController.addSourceToFrame(
+ "text/javascript", this.script.source, this.sourceFrame.element)) {
+ return;
+ }
+
+ delete this._frameNeedsSetup;
+
+ this.sourceFrame.addEventListener(
+ "syntax highlighting complete", this._syntaxHighlightingComplete, this);
+ this.sourceFrame.syntaxHighlightJavascript();
+};
+
+
+/**
+ * Dummy object used during properties inspection.
+ * @see WebInspector.didGetNodePropertiesAsync_
+ */
+WebInspector.dummyObject_ = { 'foo' : 'bar' };
+
+
+/**
+ * Dummy function used during properties inspection.
+ * @see WebInspector.didGetNodePropertiesAsync_
+ */
+WebInspector.dummyFunction_ = function() {};
+
+
+/**
+ * Callback function used with the getNodeProperties.
+ */
+WebInspector.didGetNodePropertiesAsync_ = function(treeOutline, constructor,
+ nodeId, path, json) {
+ var props = JSON.parse(json);
+ var properties = [];
+ var obj = {};
+ obj.devtools$$nodeId_ = nodeId;
+ obj.devtools$$path_ = path;
+ for (var i = 0; i < props.length; i += 3) {
+ var type = props[i];
+ var name = props[i + 1];
+ var value = props[i + 2];
+ properties.push(name);
+ if (type == 'object') {
+ // fake object is going to be replaced on expand.
+ obj[name] = WebInspector.dummyObject_;
+ } else if (type == 'function') {
+ // fake function is going to be replaced on expand.
+ obj[name] = WebInspector.dummyFunction_;
+ } else {
+ obj[name] = value;
+ }
+ }
+ properties.sort();
+
+ treeOutline.removeChildren();
+
+ for (var i = 0; i < properties.length; ++i) {
+ var propertyName = properties[i];
+ treeOutline.appendChild(new constructor(obj, propertyName));
+ }
+};
+
+
+/**
+ * Replace WebKit method with our own implementation to use our call stack
+ * representation. Original method uses Object.prototype.toString.call to
+ * learn if scope object is a JSActivation which doesn't work in Chrome.
+ */
+WebInspector.ScopeChainSidebarPane.prototype.update = function(callFrame) {
+ this.bodyElement.removeChildren();
+
+ this.sections = [];
+ this.callFrame = callFrame;
+
+ if (!callFrame) {
+ var infoElement = document.createElement('div');
+ infoElement.className = 'info';
+ infoElement.textContent = WebInspector.UIString('Not Paused');
+ this.bodyElement.appendChild(infoElement);
+ return;
+ }
+
+ if (!callFrame._expandedProperties) {
+ callFrame._expandedProperties = {};
+ }
+
+ var scopeObject = callFrame.localScope;
+ var title = WebInspector.UIString('Local');
+ var subtitle = Object.describe(scopeObject, true);
+ var emptyPlaceholder = null;
+ var extraProperties = null;
+
+ var section = new WebInspector.ObjectPropertiesSection(scopeObject, title,
+ subtitle, emptyPlaceholder, true, extraProperties,
+ WebInspector.ScopeChainSidebarPane.TreeElement);
+ section.editInSelectedCallFrameWhenPaused = true;
+ section.pane = this;
+
+ section.expanded = true;
+
+ this.sections.push(section);
+ this.bodyElement.appendChild(section.element);
+};
+
+
+/**
+ * Custom implementation of TreeElement that asynchronously resolves children
+ * using the debugger agent.
+ * @constructor
+ */
+WebInspector.ScopeChainSidebarPane.TreeElement = function(parentObject,
+ propertyName) {
+ WebInspector.ScopeVariableTreeElement.call(this, parentObject, propertyName);
+}
+WebInspector.ScopeChainSidebarPane.TreeElement.inherits(
+ WebInspector.ScopeVariableTreeElement);
+
+
+/**
+ * @override
+ */
+WebInspector.ScopeChainSidebarPane.TreeElement.prototype.onpopulate =
+ function() {
+ var obj = this.parentObject[this.propertyName];
+ devtools.tools.getDebuggerAgent().resolveChildren(obj,
+ goog.bind(this.didResolveChildren_, this));
+};
+
+
+/**
+ * Callback function used with the resolveChildren.
+ */
+WebInspector.ScopeChainSidebarPane.TreeElement.prototype.didResolveChildren_ =
+ function(object) {
+ this.removeChildren();
+ var constructor = this.treeOutline.section.treeElementConstructor;
+ object = object.resolvedValue;
+ for (var name in object) {
+ this.appendChild(new constructor(object, name));
+ }
+};
+
+
+/**
+ * @override
+ */
+WebInspector.StylePropertyTreeElement.prototype.toggleEnabled =
+ function(event) {
+ var enabled = event.target.checked;
+ devtools.tools.getDomAgent().toggleNodeStyleAsync(
+ this.style,
+ enabled,
+ this.name,
+ WebInspector.updateStylesAndMetrics_);
+};
+
+
+/**
+ * @override
+ */
+WebInspector.StylePropertyTreeElement.prototype.applyStyleText = function(
+ styleText, updateInterface) {
+ devtools.tools.getDomAgent().applyStyleTextAsync(this.style, this.name,
+ styleText,
+ function() {
+ if (updateInterface) {
+ WebInspector.updateStylesAndMetrics_();
+ }
+ });
+};
+
+
+/**
+ * Forces update of styles and metrics sidebar panes.
+ */
+WebInspector.updateStylesAndMetrics_ = function() {
+ WebInspector.panels.elements.sidebarPanes.metrics.needsUpdate = true;
+ WebInspector.panels.elements.updateMetrics();
+ WebInspector.panels.elements.sidebarPanes.styles.needsUpdate = true;
+ WebInspector.panels.elements.updateStyles(true);
+};
+
+
+/**
+ * This function overrides standard searchableViews getters to perform search
+ * only in the current view (other views are loaded asynchronously, no way to
+ * search them yet).
+ */
+WebInspector.searchableViews_ = function() {
+ var views = [];
+ const visibleView = this.visibleView;
+ if (visibleView && visibleView.performSearch) {
+ views.push(visibleView);
+ }
+ return views;
+};
+
+
+/**
+ * @override
+ */
+WebInspector.ResourcesPanel.prototype.__defineGetter__(
+ 'searchableViews',
+ WebInspector.searchableViews_);
+
+
+/**
+ * @override
+ */
+WebInspector.ScriptsPanel.prototype.__defineGetter__(
+ 'searchableViews',
+ WebInspector.searchableViews_);
+
+
+/**
+ * @override
+ */
+WebInspector.Console.prototype._evalInInspectedWindow = function(expression) {
+ if (WebInspector.panels.scripts.paused)
+ return WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression);
+
+ var console = this;
+ devtools.tools.evaluateJavaScript(expression, function(response) {
+ // TODO(yurys): send exception information along with the response
+ var exception = false;
+ console.addMessage(new WebInspector.ConsoleCommandResult(
+ response, exception, null /* commandMessage */));
+ });
+ // TODO(yurys): refactor WebInspector.Console so that the result is added into
+ // the command log message.
+ return 'evaluating...';
+};
+
+
+(function() {
+ var oldShow = WebInspector.ScriptsPanel.prototype.show;
+ WebInspector.ScriptsPanel.prototype.show = function() {
+ devtools.tools.getDebuggerAgent().initializeScriptsCache();
+ oldShow.call(this);
+ };
+})();
+
+
+// As columns in data grid can't be changed after initialization,
+// we need to intercept the constructor and modify columns upon creation.
+(function InterceptDataGridForProfiler() {
+ var originalDataGrid = WebInspector.DataGrid;
+ WebInspector.DataGrid = function(columns) {
+ if (('average' in columns) && ('calls' in columns)) {
+ delete columns['average'];
+ delete columns['calls'];
+ }
+ return new originalDataGrid(columns);
+ };
+})();
+
+
+// WebKit's profiler displays milliseconds with high resolution (shows
+// three digits after the decimal point). We never have such resolution,
+// as our minimal sampling rate is 1 ms. So we are disabling high resolution
+// to avoid visual clutter caused by meaningless ".000" parts.
+(function InterceptTimeDisplayInProfiler() {
+ var originalDataGetter =
+ WebInspector.ProfileDataGridNode.prototype.__lookupGetter__('data');
+ WebInspector.ProfileDataGridNode.prototype.__defineGetter__('data',
+ function() {
+ var oldNumberSecondsToString = Number.secondsToString;
+ Number.secondsToString = function(seconds, formatterFunction) {
+ return oldNumberSecondsToString(seconds, formatterFunction, false);
+ };
+ var data = originalDataGetter.call(this);
+ Number.secondsToString = oldNumberSecondsToString;
+ return data;
+ });
+})();
+
+
+(function InterceptProfilesPanelEvents() {
+ var oldShow = WebInspector.ProfilesPanel.prototype.show;
+ WebInspector.ProfilesPanel.prototype.show = function() {
+ devtools.tools.getDebuggerAgent().initializeProfiling();
+ 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(pfeldman): Add l10n.
+ */
+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 = 'Developer Tools - ' + resource.url;
+ }
+ };
+})();
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/devtools_callback.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/devtools_callback.js
new file mode 100644
index 0000000..f252861
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/devtools_callback.js
@@ -0,0 +1,57 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Generic callback manager.
+ */
+goog.provide('devtools.Callback');
+
+
+/**
+ * Generic callback support as a singleton object.
+ * @constructor
+ */
+devtools.Callback = function() {
+ this.lastCallbackId_ = 1;
+ this.callbacks_ = {};
+};
+
+
+/**
+ * Assigns id to a callback.
+ * @param {Function} callback Callback to assign id to.
+ * @return {number} Callback id.
+ */
+devtools.Callback.prototype.wrap = function(callback) {
+ var callbackId = this.lastCallbackId_++;
+ this.callbacks_[callbackId] = callback || function() {};
+ return callbackId;
+};
+
+
+/**
+ * Executes callback with the given id.
+ * @param {callbackId} callbackId Id of a callback to call.
+ */
+devtools.Callback.prototype.processCallback = function(callbackId,
+ opt_vararg) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ var callback = this.callbacks_[callbackId];
+ callback.apply(null, args);
+ delete this.callbacks_[callbackId];
+};
+
+
+/**
+ * @type {devtools.Callback} Callback support singleton.
+ * @private
+ */
+devtools.Callback.INSTANCE_ = new devtools.Callback();
+
+devtools.Callback.wrap = goog.bind(
+ devtools.Callback.INSTANCE_.wrap,
+ devtools.Callback.INSTANCE_);
+devtools.Callback.processCallback = goog.bind(
+ devtools.Callback.INSTANCE_.processCallback,
+ devtools.Callback.INSTANCE_);
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/devtools_host_stub.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/devtools_host_stub.js
new file mode 100644
index 0000000..42a27ea
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/devtools_host_stub.js
@@ -0,0 +1,341 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview These stubs emulate backend functionality and allows
+ * DevTools frontend to function as a standalone web app.
+ */
+
+/**
+ * @constructor
+ */
+RemoteDebuggerAgentStub = function() {
+ this.isProfiling_ = false;
+ this.profileLogPos_ = 0;
+};
+
+RemoteDebuggerAgentStub.prototype.DebugBreak = function() {
+};
+
+RemoteDebuggerAgentStub.prototype.GetContextId = function() {
+ RemoteDebuggerAgent.DidGetContextId(3);
+};
+
+RemoteDebuggerAgentStub.prototype.StopProfiling = function() {
+ this.isProfiling_ = false;
+};
+
+RemoteDebuggerAgentStub.prototype.StartProfiling = function() {
+ this.isProfiling_ = true;
+};
+
+RemoteDebuggerAgentStub.prototype.IsProfilingStarted = function() {
+ var self = this;
+ setTimeout(function() {
+ RemoteDebuggerAgent.DidIsProfilingStarted(self.isProfiling_);
+ }, 100);
+};
+
+RemoteDebuggerAgentStub.prototype.GetNextLogLines = function() {
+ if (this.profileLogPos_ < RemoteDebuggerAgentStub.ProfilerLogBuffer.length) {
+ this.profileLogPos_ += RemoteDebuggerAgentStub.ProfilerLogBuffer.length;
+ setTimeout(function() {
+ RemoteDebuggerAgent.DidGetNextLogLines(
+ RemoteDebuggerAgentStub.ProfilerLogBuffer);
+ },
+ 100);
+ } else {
+ setTimeout(function() { RemoteDebuggerAgent.DidGetNextLogLines(''); }, 100);
+ }
+};
+
+/**
+ * @constructor
+ */
+RemoteDomAgentStub = function() {
+};
+
+
+RemoteDomAgentStub.sendDocumentElement_ = function() {
+ RemoteDomAgent.SetDocumentElement([
+ 1, // id
+ 1, // type = Node.ELEMENT_NODE,
+ 'HTML', // nodeName
+ '', // nodeValue
+ ['foo','bar'], // attributes
+ 2, // childNodeCount
+ ]);
+};
+
+
+RemoteDomAgentStub.sendChildNodes_ = function(id) {
+ if (id == 1) {
+ RemoteDomAgent.SetChildNodes(id,
+ [
+ [
+ 2, // id
+ 1, // type = Node.ELEMENT_NODE,
+ 'DIV', // nodeName
+ '', // nodeValue
+ ['foo','bar'], // attributes
+ 1, // childNodeCount
+ ],
+ [
+ 3, // id
+ 3, // type = Node.TEXT_NODE,
+ '', // nodeName
+ 'Text', // nodeValue
+ ]
+ ]);
+ } else if (id == 2) {
+ RemoteDomAgent.SetChildNodes(id,
+ [
+ [
+ 4, // id
+ 1, // type = Node.ELEMENT_NODE,
+ 'span', // nodeName
+ '', // nodeValue
+ ['foo','bar'], // attributes
+ 0, // childNodeCount
+ ]
+ ]);
+ }
+};
+
+
+RemoteDomAgentStub.prototype.GetDocumentElement = function(callId) {
+ setTimeout(function() {
+ RemoteDomAgentStub.sendDocumentElement_();
+ }, 0);
+};
+
+
+RemoteDomAgentStub.prototype.GetChildNodes = function(callId, id) {
+ setTimeout(function() {
+ RemoteDomAgentStub.sendChildNodes_(id);
+ RemoteDomAgent.DidGetChildNodes(callId);
+ }, 0);
+};
+
+
+RemoteDomAgentStub.prototype.SetAttribute = function(callId) {
+ setTimeout(function() {
+ RemoteDomAgent.DidApplyDomChange(callId, true);
+ }, 0);
+};
+
+
+RemoteDomAgentStub.prototype.RemoveAttribute = function(callId) {
+ setTimeout(function() {
+ RemoteDomAgent.DidApplyDomChange(callId, true);
+ }, 0);
+};
+
+
+RemoteDomAgentStub.prototype.SetTextNodeValue = function(callId) {
+ setTimeout(function() {
+ RemoteDomAgent.DidApplyDomChange(callId, true);
+ }, 0);
+};
+
+
+RemoteDomAgentStub.prototype.PerformSearch = function(callId, query) {
+ setTimeout(function() {
+ RemoteDomAgent.DidPerformSearch(callId, [1]);
+ }, 0);
+};
+
+
+RemoteDomAgentStub.prototype.DiscardBindings = function() {
+};
+
+
+/**
+ * @constructor
+ */
+RemoteToolsAgentStub = function() {
+};
+
+
+RemoteToolsAgentStub.prototype.HideDOMNodeHighlight = function() {
+};
+
+
+RemoteToolsAgentStub.prototype.HighlightDOMNode = function() {
+};
+
+
+RemoteToolsAgentStub.prototype.evaluate = function(expr) {
+ window.eval(expr);
+};
+
+RemoteToolsAgentStub.prototype.EvaluateJavaScript = function(callId, script) {
+ setTimeout(function() {
+ var result = eval(script);
+ RemoteToolsAgent.DidEvaluateJavaScript(callId, result);
+ }, 0);
+};
+
+
+RemoteToolsAgentStub.prototype.ExecuteUtilityFunction = function(callId,
+ functionName, nodeId, args) {
+ setTimeout(function() {
+ var result = [];
+ if (functionName == 'getProperties') {
+ result = [
+ 'undefined', 'undefined_key', undefined,
+ 'string', 'string_key', 'value',
+ 'function', 'func', undefined,
+ 'array', 'array_key', [10],
+ 'object', 'object_key', undefined,
+ 'boolean', 'boolean_key', true,
+ 'number', 'num_key', 911,
+ 'date', 'date_key', new Date() ];
+ } else if (functionName == 'getPrototypes') {
+ result = ['Proto1', 'Proto2', 'Proto3'];
+ } else if (functionName == 'getStyles') {
+ result = {
+ 'computedStyle' : [0, '0px', '0px', null, null, null, ['display', false, false, '', 'none']],
+ 'inlineStyle' : [1, '0px', '0px', null, null, null, ['display', false, false, '', 'none']],
+ 'styleAttributes' : {
+ attr: [2, '0px', '0px', null, null, null, ['display', false, false, '', 'none']]
+ },
+ 'matchedCSSRules' : [
+ { 'selector' : 'S',
+ 'style' : [3, '0px', '0px', null, null, null, ['display', false, false, '', 'none']],
+ 'parentStyleSheet' : { 'href' : 'http://localhost',
+ 'ownerNodeName' : 'DIV' }
+ }
+ ]
+ };
+ } else if (functionName == 'toggleNodeStyle' ||
+ functionName == 'applyStyleText' ||
+ functionName == 'setStyleProperty') {
+ alert(functionName + '(' + nodeId + ', ' + args + ')');
+ } else {
+ alert('Unexpected utility function:' + functionName);
+ }
+ RemoteToolsAgent.DidExecuteUtilityFunction(callId,
+ JSON.stringify(result), '');
+ }, 0);
+};
+
+
+RemoteToolsAgentStub.prototype.GetNodePrototypes = function(callId, nodeId) {
+ setTimeout(function() {
+ RemoteToolsAgent.DidGetNodePrototypes(callId,
+ JSON.stringify());
+ }, 0);
+};
+
+
+RemoteToolsAgentStub.prototype.ClearConsoleMessages = function() {
+};
+
+
+RemoteToolsAgentStub.prototype.SetResourceTrackingEnabled = function(enabled, always) {
+ RemoteToolsAgent.SetResourcesPanelEnabled(enabled);
+ if (enabled) {
+ WebInspector.resourceTrackingWasEnabled();
+ } else {
+ WebInspector.resourceTrackingWasDisabled();
+ }
+ addDummyResource();
+};
+
+
+RemoteDebuggerAgentStub.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';
+
+
+/**
+ * @constructor
+ */
+RemoteDebuggerCommandExecutorStub = function() {
+};
+
+
+RemoteDebuggerCommandExecutorStub.prototype.DebuggerCommand = function(cmd) {
+};
+
+
+/**
+ * @constructor
+ */
+DevToolsHostStub = function() {
+ this.isStub = true;
+ window.domAutomationController = {
+ send: function(text) {
+ debugPrint(text);
+ }
+ };
+};
+
+
+function addDummyResource() {
+ var payload = {
+ requestHeaders : {},
+ requestURL: 'http://google.com/simple_page.html',
+ host: 'google.com',
+ path: 'simple_page.html',
+ lastPathComponent: 'simple_page.html',
+ isMainResource: true,
+ cached: false,
+ mimeType: 'text/html',
+ suggestedFilename: 'simple_page.html',
+ expectedContentLength: 10000,
+ statusCode: 200,
+ contentLength: 10000,
+ responseHeaders: {},
+ type: WebInspector.Resource.Type.Document,
+ finished: true,
+ startTime: new Date(),
+
+ didResponseChange: true,
+ didCompletionChange: true,
+ didTypeChange: true
+ };
+
+ WebInspector.addResource(1, payload);
+ WebInspector.updateResource(1, payload);
+}
+
+
+DevToolsHostStub.prototype.loaded = function() {
+ RemoteDomAgentStub.sendDocumentElement_();
+ RemoteDomAgentStub.sendChildNodes_(1);
+ RemoteDomAgentStub.sendChildNodes_(2);
+ devtools.tools.updateFocusedNode_(4);
+ addDummyResource();
+
+ uiTests.runAllTests();
+};
+
+
+DevToolsHostStub.prototype.addResourceSourceToFrame = function(
+ identifier, mimeType, element) {
+};
+
+
+if (!window['DevToolsHost']) {
+ window['RemoteDebuggerAgent'] = new RemoteDebuggerAgentStub();
+ window['RemoteDebuggerCommandExecutor'] =
+ new RemoteDebuggerCommandExecutorStub();
+ window['RemoteDomAgent'] = new RemoteDomAgentStub();
+ window['RemoteToolsAgent'] = new RemoteToolsAgentStub();
+ window['DevToolsHost'] = new DevToolsHostStub();
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/dom_agent.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/dom_agent.js
new file mode 100644
index 0000000..3ab2017
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/dom_agent.js
@@ -0,0 +1,1032 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Dom and DomNode are used to represent remote DOM in the
+ * web inspector.
+ */
+goog.provide('devtools.DomAgent');
+goog.provide('devtools.DomDocument');
+goog.provide('devtools.DomNode');
+
+goog.require('devtools.Callback');
+
+
+/**
+ * Defines indexes for the node payload properties.
+ */
+devtools.PayloadIndex = {
+ ID : 0,
+ TYPE : 1,
+ NAME : 2,
+ VALUE : 3,
+ ATTRS : 4,
+ HAS_CHILDREN : 5,
+ CHILD_NODES : 6
+};
+
+
+/**
+ * Creates document node in a given document based on a given payload data.
+ * @param {devtools.Doc} doc Document to create node in.
+ * @param {Array.<Object>} payload Data to build node based upon.
+ * @constructor
+ */
+devtools.DomNode = function(doc, payload) {
+ this.ownerDocument = doc;
+
+ this.id_ = payload[devtools.PayloadIndex.ID];
+ this.nodeType = payload[devtools.PayloadIndex.TYPE];
+ this.nodeName = payload[devtools.PayloadIndex.NAME];
+ this.nodeValue_ = payload[devtools.PayloadIndex.VALUE];
+ this.textContent = this.nodeValue;
+
+ this.attributes = [];
+ this.attributesMap_ = {};
+ if (payload.length > devtools.PayloadIndex.ATTRS) {
+ this.setAttributesPayload_(payload[devtools.PayloadIndex.ATTRS]);
+ }
+
+ this.childNodesCount_ = payload[devtools.PayloadIndex.HAS_CHILDREN];
+ this.children = null;
+
+ this.nextSibling = null;
+ this.prevSibling = null;
+ this.firstChild = null;
+ this.parentNode = null;
+
+ this.disabledStyleProperties_ = {};
+
+ if (payload.length > devtools.PayloadIndex.CHILD_NODES) {
+ // Has children payloads
+ this.setChildrenPayload_(
+ payload[devtools.PayloadIndex.CHILD_NODES]);
+ }
+
+ this.computedStyle_ = null;
+ this.style = null;
+ this.matchedCSSRules_ = [];
+};
+
+
+/**
+ * Overrides for getters and setters.
+ */
+devtools.DomNode.prototype = {
+ get nodeValue() {
+ return this.nodeValue_;
+ },
+
+ set nodeValue(value) {
+ if (this.nodeType != Node.TEXT_NODE) {
+ return;
+ }
+ var self = this;
+ this.ownerDocument.domAgent_.setTextNodeValueAsync(this, value,
+ function() {
+ self.nodeValue_ = value;
+ self.textContent = value;
+ });
+ }
+};
+
+
+/**
+ * Sets attributes for a given node based on a given attrs payload.
+ * @param {Array.<string>} attrs Attribute key-value pairs to set.
+ * @private
+ */
+devtools.DomNode.prototype.setAttributesPayload_ = function(attrs) {
+ for (var i = 0; i < attrs.length; i += 2) {
+ this.addAttribute_(attrs[i], attrs[i + 1]);
+ }
+};
+
+
+/**
+ * @return True iff node has attributes.
+ */
+devtools.DomNode.prototype.hasAttributes = function() {
+ return this.attributes.length > 0;
+};
+
+
+/**
+ * @return True iff node has child nodes.
+ */
+devtools.DomNode.prototype.hasChildNodes = function() {
+ return this.childNodesCount_ > 0;
+};
+
+
+/**
+ * Inserts child node into this node after a given anchor.
+ * @param {devtools.DomNode} prev Node to insert child after.
+ * @param {Array.<Object>} payload Child node data.
+ * @private
+ */
+devtools.DomNode.prototype.insertChild_ = function(prev, payload) {
+ var node = new devtools.DomNode(this.ownerDocument, payload);
+ if (!prev) {
+ // First node
+ this.children = [ node ];
+ } else {
+ this.children.splice(this.children.indexOf(prev) + 1, 0, node);
+ }
+ this.renumber_();
+ return node;
+};
+
+
+/**
+ * Removes child node from this node.
+ * @param {devtools.DomNode} node Node to remove.
+ * @private
+ */
+devtools.DomNode.prototype.removeChild_ = function(node) {
+ this.children.splice(this.children.indexOf(node), 1);
+ node.parentNode = null;
+ this.renumber_();
+};
+
+
+/**
+ * Sets children for this node based on the given payload.
+ * @param {Array.<Object>} payload Data for children.
+ * @private
+ */
+devtools.DomNode.prototype.setChildrenPayload_ = function(payloads) {
+ this.children = [];
+ for (var i = 0; i < payloads.length; ++i) {
+ var payload = payloads[i];
+ var node = new devtools.DomNode(this.ownerDocument, payload);
+ this.children.push(node);
+ }
+ this.renumber_();
+};
+
+
+/**
+ * Normalizes prev/next/parent/firstChild links for this node's children.
+ * @private
+ */
+devtools.DomNode.prototype.renumber_ = function() {
+ this.childNodesCount_ = this.children.length;
+ if (this.childNodesCount_ == 0) {
+ this.firstChild = null;
+ return;
+ }
+ this.firstChild = this.children[0];
+ for (var i = 0; i < this.childNodesCount_; ++i) {
+ var child = this.children[i];
+ child.nextSibling = i + 1 < this.childNodesCount_ ?
+ this.children[i + 1] : null;
+ child.prevSibling = i - 1 >= 0 ? this.children[i - 1] : null;
+ child.parentNode = this;
+ }
+};
+
+
+/**
+ * Returns attribute value.
+ * @param {string} name Attribute name to get value for.
+ * @return {string} Attribute value.
+ */
+devtools.DomNode.prototype.getAttribute = function(name) {
+ var attr = this.attributesMap_[name];
+ return attr ? attr.value : undefined;
+};
+
+
+/**
+ * Sends 'set attribute' command to the remote agent.
+ * @param {string} name Attribute name to set value for.
+ * @param {string} value Attribute value to set.
+ */
+devtools.DomNode.prototype.setAttribute = function(name, value) {
+ var self = this;
+ this.ownerDocument.domAgent_.setAttributeAsync(this, name, value,
+ function() {
+ var attr = self.attributesMap_[name];
+ if (attr) {
+ attr.value = value;
+ } else {
+ attr = self.addAttribute_(name, value);
+ }
+ });
+};
+
+
+/**
+ * Creates an attribute-like object and adds it to the object.
+ * @param {string} name Attribute name to set value for.
+ * @param {string} value Attribute value to set.
+ */
+devtools.DomNode.prototype.addAttribute_ = function(name, value) {
+ var attr = {
+ 'name': name,
+ 'value': value,
+ node_: this
+ };
+
+ this.attributesMap_[name] = attr;
+ this.attributes.push(attr);
+};
+
+
+/**
+ * Sends 'remove attribute' command to the remote agent.
+ * @param {string} name Attribute name to set value for.
+ */
+devtools.DomNode.prototype.removeAttribute = function(name) {
+ var self = this;
+ this.ownerDocument.domAgent_.removeAttributeAsync(this, name, function() {
+ delete self.attributesMap_[name];
+ for (var i = 0; i < self.attributes.length; ++i) {
+ if (self.attributes[i].name == name) {
+ self.attributes.splice(i, 1);
+ break;
+ }
+ }
+ });
+};
+
+
+/**
+ * Makes available the following methods and properties:
+ * - node.style property
+ * - node.document.defaultView.getComputedStyles(node)
+ * - node.document.defaultView.getMatchedCSSRules(node, ...)
+ * - style attribute of node's attributes
+ * @param {string} computedStyle is a cssText of result of getComputedStyle().
+ * @param {string} inlineStyle is a style.cssText (defined in the STYLE
+ * attribute).
+ * @param {Object} styleAttributes represents 'style' property
+ * of attributes.
+ * @param {Array.<object>} matchedCSSRules represents result of the
+ * getMatchedCSSRules(node, '', authorOnly). Each elemet consists of:
+ * selector, rule.style.cssText[, rule.parentStyleSheet.href
+ * [, rule.parentStyleSheet.ownerNode.nodeName]].
+ */
+devtools.DomNode.prototype.setStyles = function(computedStyle, inlineStyle,
+ styleAttributes, matchedCSSRules) {
+ this.computedStyle_ = this.makeStyle_(computedStyle);
+ this.style = this.makeStyle_(inlineStyle);
+
+ for (var name in styleAttributes) {
+ if (this.attributesMap_[name]) {
+ this.attributesMap_[name].style =
+ this.makeStyle_(styleAttributes[name]);
+ }
+ }
+
+ this.matchedCSSRules_ = [];
+ for (var i = 0; i < matchedCSSRules.length; i++) {
+ var descr = matchedCSSRules[i];
+
+ var rule = {};
+ rule.selectorText = descr['selector'];
+ rule.style = this.makeStyle_(descr['style']);
+
+ if (descr['parentStyleSheet']) {
+ var parentStyleMock = {};
+ parentStyleMock.href = descr['parentStyleSheet']['href'];
+ var nodeName = descr['parentStyleSheet']['ownerNodeName'];
+ if (nodeName) {
+ parentStyleMock.ownerNode = {
+ 'nodeName': nodeName
+ };
+ }
+ rule.parentStyleSheet = parentStyleMock;
+ }
+ this.matchedCSSRules_.push(rule);
+ }
+};
+
+
+/**
+ * Creates a style declaration.
+ * @param {payload} payload
+ * @return {devtools.CSSStyleDeclaration:undefined}
+ * @see devtools.CSSStyleDeclaration
+ */
+devtools.DomNode.prototype.makeStyle_ = function(payload) {
+ var style = new devtools.CSSStyleDeclaration(payload);
+ style.nodeId_ = this.id_;
+ return style;
+};
+
+
+/**
+ * Remove references to the style information to release
+ * resources when styles are not going to be used.
+ * @see setStyles.
+ */
+devtools.DomNode.prototype.clearStyles = function() {
+ this.computedStyle = null;
+ this.style = null;
+ for (var name in this.attributesMap_) {
+ this.attributesMap_[name].style = null;
+ }
+ this.matchedCSSRules_ = null;
+};
+
+
+/**
+ * Remote Dom document abstraction.
+ * @param {devtools.DomAgent} domAgent owner agent.
+ * @param {devtools.DomWindow} defaultView owner window.
+ * @constructor.
+ */
+devtools.DomDocument = function(domAgent, defaultView) {
+ devtools.DomNode.call(this, null,
+ [
+ 0, // id
+ 9, // type = Node.DOCUMENT_NODE,
+ '', // nodeName
+ '', // nodeValue
+ [], // attributes
+ 0, // childNodeCount
+ ]);
+ this.listeners_ = {};
+ this.domAgent_ = domAgent;
+ this.defaultView = defaultView;
+};
+goog.inherits(devtools.DomDocument, devtools.DomNode);
+
+
+/**
+ * Adds event listener to the Dom.
+ * @param {string} name Event name.
+ * @param {function(Event):undefined} callback Listener callback.
+ * @param {bool} useCapture Listener's useCapture settings.
+ */
+devtools.DomDocument.prototype.addEventListener =
+ function(name, callback, useCapture) {
+ var listeners = this.listeners_[name];
+ if (!listeners) {
+ listeners = [];
+ this.listeners_[name] = listeners;
+ }
+ listeners.push(callback);
+};
+
+
+/**
+ * Removes event listener from the Dom.
+ * @param {string} name Event name.
+ * @param {function(Event):undefined} callback Listener callback.
+ * @param {bool} useCapture Listener's useCapture settings.
+ */
+devtools.DomDocument.prototype.removeEventListener =
+ function(name, callback, useCapture) {
+ var listeners = this.listeners_[name];
+ if (!listeners) {
+ return;
+ }
+ var index = listeners.indexOf(callback);
+ if (index != -1) {
+ listeners.splice(index, 1);
+ }
+};
+
+
+/**
+ * Fires Dom event to the listeners for given event type.
+ * @param {string} name Event type.
+ * @param {Event} event Event to fire.
+ * @private
+ */
+devtools.DomDocument.prototype.fireDomEvent_ = function(name, event) {
+ var listeners = this.listeners_[name];
+ if (!listeners) {
+ return;
+ }
+ for (var i = 0; i < listeners.length; ++i) {
+ listeners[i](event);
+ }
+};
+
+
+
+/**
+ * Simulation of inspected DOMWindow.
+ * @param {devtools.DomAgent} domAgent owner agent.
+ * @constructor
+ */
+devtools.DomWindow = function(domAgent) {
+ this.document = new devtools.DomDocument(domAgent, this);
+};
+
+/**
+ * Represents DOM Node class.
+ */
+devtools.DomWindow.prototype.__defineGetter__('Node', function() {
+ return devtools.DomNode;
+});
+
+/**
+ * Represents DOM Element class.
+ * @constructor
+ */
+devtools.DomWindow.prototype.__defineGetter__('Element', function() {
+ return devtools.DomNode;
+});
+
+
+/**
+ * See usages in ScopeChainSidebarPane.js where it's called as
+ * constructor.
+ */
+devtools.DomWindow.prototype.Object = function() {
+};
+
+
+/**
+ * Simulates the DOM interface for styles.
+ * @param {devtools.DomNode} node
+ * @return {CSSStyleDescription}
+ */
+devtools.DomWindow.prototype.getComputedStyle = function(node) {
+ return node.computedStyle_;
+};
+
+
+/**
+ * Simulates the DOM interface for styles.
+ * @param {devtools.DomNode} nodeStyles
+ * @param {string} pseudoElement assumed to be empty string.
+ * @param {boolean} authorOnly assumed to be equal to authorOnly argument of
+ * getNodeStylesAsync.
+ * @return {CSSStyleDescription}
+ */
+devtools.DomWindow.prototype.getMatchedCSSRules = function(node,
+ pseudoElement, authorOnly) {
+ return node.matchedCSSRules_;
+};
+
+
+/**
+ * Creates DomAgent Js representation.
+ * @constructor
+ */
+devtools.DomAgent = function() {
+ RemoteDomAgent.DidGetChildNodes =
+ devtools.Callback.processCallback;
+ RemoteDomAgent.DidPerformSearch =
+ devtools.Callback.processCallback;
+ RemoteDomAgent.DidApplyDomChange =
+ devtools.Callback.processCallback;
+ RemoteDomAgent.DidRemoveAttribute =
+ devtools.Callback.processCallback;
+ RemoteDomAgent.DidSetTextNodeValue =
+ devtools.Callback.processCallback;
+ RemoteDomAgent.AttributesUpdated =
+ goog.bind(this.attributesUpdated_, this);
+ RemoteDomAgent.SetDocumentElement =
+ goog.bind(this.setDocumentElement_, this);
+ RemoteDomAgent.SetChildNodes =
+ goog.bind(this.setChildNodes_, this);
+ RemoteDomAgent.HasChildrenUpdated =
+ goog.bind(this.hasChildrenUpdated_, this);
+ RemoteDomAgent.ChildNodeInserted =
+ goog.bind(this.childNodeInserted_, this);
+ RemoteDomAgent.ChildNodeRemoved =
+ goog.bind(this.childNodeRemoved_, this);
+
+ /**
+ * Top-level (and the only) document.
+ * @type {devtools.DomWindow}
+ * @private
+ */
+ this.window_ = null;
+
+ /**
+ * Id to node mapping.
+ * @type {Object}
+ * @private
+ */
+ this.idToDomNode_ = null;
+
+ /**
+ * @type {Array.<number>} Node ids for search results.
+ * @private
+ */
+ this.searchResults_ = null;
+};
+
+
+/**
+ * Resets dom agent to its initial state.
+ */
+devtools.DomAgent.prototype.reset = function() {
+ this.window_ = new devtools.DomWindow(this);
+ this.idToDomNode_ = { 0 : this.getDocument() };
+ this.searchResults_ = [];
+};
+
+
+/**
+ * @return {devtools.DomWindow} Window for the top level (and the only) document.
+ */
+devtools.DomAgent.prototype.getWindow = function() {
+ return this.window_;
+};
+
+
+/**
+ * @return {devtools.DomDocument} A document of the top level window.
+ */
+devtools.DomAgent.prototype.getDocument = function() {
+ return this.window_.document;
+};
+
+
+/**
+ * Requests that the document element is sent from the agent.
+ */
+devtools.DomAgent.prototype.getDocumentElementAsync = function() {
+ if (this.getDocument().documentElement) {
+ return;
+ }
+ RemoteDomAgent.GetDocumentElement();
+};
+
+
+/**
+ * Asynchronously fetches children from the element with given id.
+ * @param {devtools.DomNode} parent Element to get children for.
+ * @param {function(devtools.DomNode):undefined} opt_callback Callback with
+ * the result.
+ */
+devtools.DomAgent.prototype.getChildNodesAsync = function(parent,
+ opt_callback) {
+ var children = parent.children;
+ if (children && opt_callback) {
+ opt_callback(children);
+ return;
+ }
+ var mycallback = function() {
+ if (opt_callback) {
+ opt_callback(parent.children);
+ }
+ };
+ var callId = devtools.Callback.wrap(mycallback);
+ RemoteDomAgent.GetChildNodes(callId, parent.id_);
+};
+
+
+/**
+ * Sends 'set attribute' command to the remote agent.
+ * @param {devtools.DomNode} node Node to change.
+ * @param {string} name Attribute name to set value for.
+ * @param {string} value Attribute value to set.
+ * @param {function():undefined} opt_callback Callback on success.
+ */
+devtools.DomAgent.prototype.setAttributeAsync = function(node, name, value,
+ callback) {
+ var mycallback = goog.bind(this.didApplyDomChange_, this, node, callback);
+ RemoteDomAgent.SetAttribute(devtools.Callback.wrap(mycallback),
+ node.id_, name, value);
+};
+
+
+/**
+ * Sends 'remove attribute' command to the remote agent.
+ * @param {devtools.DomNode} node Node to change.
+ * @param {string} name Attribute name to set value for.
+ * @param {function():undefined} opt_callback Callback on success.
+ */
+devtools.DomAgent.prototype.removeAttributeAsync = function(node, name,
+ callback) {
+ var mycallback = goog.bind(this.didApplyDomChange_, this, node, callback);
+ RemoteDomAgent.RemoveAttribute(devtools.Callback.wrap(mycallback),
+ node.id_, name);
+};
+
+
+/**
+ * Sends 'set text node value' command to the remote agent.
+ * @param {devtools.DomNode} node Node to change.
+ * @param {string} text Text value to set.
+ * @param {function():undefined} opt_callback Callback on success.
+ */
+devtools.DomAgent.prototype.setTextNodeValueAsync = function(node, text,
+ callback) {
+ var mycallback = goog.bind(this.didApplyDomChange_, this, node, callback);
+ RemoteDomAgent.SetTextNodeValue(devtools.Callback.wrap(mycallback),
+ node.id_, text);
+};
+
+
+/**
+ * Universal callback wrapper for edit dom operations.
+ * @param {devtools.DomNode} node Node to apply local changes on.
+ * @param {Function} callback Post-operation call.
+ * @param {boolean} success True iff operation has completed successfully.
+ * @private
+ */
+devtools.DomAgent.prototype.didApplyDomChange_ = function(node,
+ callback, success) {
+ if (!success) {
+ return;
+ }
+ callback();
+ var elem = WebInspector.panels.elements.treeOutline.findTreeElement(node);
+ if (elem) {
+ elem._updateTitle();
+ }
+};
+
+
+/**
+ * @see DomAgentDelegate.
+ * {@inheritDoc}.
+ * @private
+ */
+devtools.DomAgent.prototype.attributesUpdated_ = function(nodeId, attrsArray) {
+ var node = this.idToDomNode_[nodeId];
+ node.setAttributesPayload_(attrsArray);
+};
+
+
+/**
+ * Returns node for id.
+ * @param {number} nodeId Id to get node for.
+ * @return {devtools.DomNode} Node with given id.
+ */
+devtools.DomAgent.prototype.getNodeForId = function(nodeId) {
+ return this.idToDomNode_[nodeId];
+};
+
+
+/**
+ * @see DomAgentDelegate.
+ * {@inheritDoc}.
+ * @private
+ */
+devtools.DomAgent.prototype.setDocumentElement_ = function(payload) {
+ var doc = this.getDocument();
+ if (doc.documentElement) {
+ this.reset();
+ doc = this.getDocument();
+ }
+ this.setChildNodes_(0, [payload]);
+ doc.documentElement = doc.firstChild;
+ doc.documentElement.ownerDocument = doc;
+ WebInspector.panels.elements.reset();
+};
+
+
+/**
+ * @see DomAgentDelegate.
+ * {@inheritDoc}.
+ * @private
+ */
+devtools.DomAgent.prototype.setChildNodes_ = function(parentId, payloads) {
+ var parent = this.idToDomNode_[parentId];
+ if (parent.children) {
+ return;
+ }
+ parent.setChildrenPayload_(payloads);
+ this.bindNodes_(parent.children);
+};
+
+
+/**
+ * Binds nodes to ids recursively.
+ * @param {Array.<devtools.DomNode>} children Nodes to bind.
+ * @private
+ */
+devtools.DomAgent.prototype.bindNodes_ = function(children) {
+ for (var i = 0; i < children.length; ++i) {
+ var child = children[i];
+ this.idToDomNode_[child.id_] = child;
+ if (child.children) {
+ this.bindNodes_(child.children);
+ }
+ }
+};
+
+
+/**
+ * @see DomAgentDelegate.
+ * {@inheritDoc}.
+ * @private
+ */
+devtools.DomAgent.prototype.hasChildrenUpdated_ = function(nodeId, newValue) {
+ var node = this.idToDomNode_[nodeId];
+ var outline = WebInspector.panels.elements.treeOutline;
+ var treeElement = outline.findTreeElement(node);
+ if (treeElement) {
+ treeElement.hasChildren = newValue;
+ treeElement.whitespaceIgnored = Preferences.ignoreWhitespace;
+ }
+};
+
+
+/**
+ * @see DomAgentDelegate.
+ * {@inheritDoc}.
+ * @private
+ */
+devtools.DomAgent.prototype.childNodeInserted_ = function(
+ parentId, prevId, payload) {
+ var parent = this.idToDomNode_[parentId];
+ var prev = this.idToDomNode_[prevId];
+ var node = parent.insertChild_(prev, payload);
+ this.idToDomNode_[node.id_] = node;
+ var event = { target : node, relatedNode : parent };
+ this.getDocument().fireDomEvent_('DOMNodeInserted', event);
+};
+
+
+/**
+ * @see DomAgentDelegate.
+ * {@inheritDoc}.
+ * @private
+ */
+devtools.DomAgent.prototype.childNodeRemoved_ = function(
+ parentId, nodeId) {
+ var parent = this.idToDomNode_[parentId];
+ var node = this.idToDomNode_[nodeId];
+ parent.removeChild_(node);
+ var event = { target : node, relatedNode : parent };
+ this.getDocument().fireDomEvent_('DOMNodeRemoved', event);
+ delete this.idToDomNode_[nodeId];
+};
+
+
+/**
+ * @see DomAgentDelegate.
+ * {@inheritDoc}.
+ */
+devtools.DomAgent.prototype.performSearch = function(query, callback) {
+ this.searchResults_ = [];
+ RemoteDomAgent.PerformSearch(
+ devtools.Callback.wrap(
+ goog.bind(this.performSearchCallback_, this, callback,
+ this.searchResults_)),
+ query);
+};
+
+
+/**
+ * Invokes callback for nodes that needs to clear highlighting.
+ * @param {function(Array.<devtools.DomNode>)} callback to accept the result.
+ */
+devtools.DomAgent.prototype.searchCanceled = function(callback) {
+ if (!this.searchResults_)
+ return;
+
+ var nodes = [];
+ for (var i = 0; i < this.searchResults_.length; ++i) {
+ var nodeId = this.searchResults_[i];
+ var node = this.idToDomNode_[nodeId];
+ nodes.push(node);
+ }
+
+ callback(nodes);
+ this.searchResults_ = null;
+};
+
+
+/**
+ * Invokes callback for each node that needs to gain highlighting.
+ * @param {function(Array.<devtools.DomNode>)} callback to accept the result.
+ * @param {Array.<number>} searchResults to be populated.
+ * @param {Array.<number>} nodeIds Ids to highlight.
+ * @private
+ */
+devtools.DomAgent.prototype.performSearchCallback_ = function(callback,
+ searchResults, nodeIds) {
+
+ if (this.searchResults_ !== searchResults)
+ return; // another search has requested and this results are obsolete
+
+ var nodes = [];
+
+ for (var i = 0; i < nodeIds.length; ++i) {
+ var node = this.idToDomNode_[nodeIds[i]];
+ searchResults.push(nodeIds[i]);
+ nodes.push(node);
+ }
+
+ callback(nodes);
+};
+
+
+/**
+ * Returns a node by index from the actual search results
+ * (last performSearch).
+ * @param {number} index in the results.
+ * @return {devtools.DomNode}
+ */
+devtools.DomAgent.prototype.getSearchResultNode = function(index) {
+ return this.idToDomNode_[this.searchResults_[index]];
+};
+
+
+/**
+ * Returns all properties of the given node.
+ * @param {number} nodeId Node to get properties for.
+ * @param {Array.<string>} path Path to the object.
+ * @param {number} protoDepth Depth to the exact proto level.
+ * @param {function(string):undefined} callback Function to call with the
+ * result.
+ */
+devtools.DomAgent.prototype.getNodePropertiesAsync = function(nodeId,
+ path, protoDepth, callback) {
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
+ RemoteToolsAgent.ExecuteUtilityFunction(callbackId,
+ 'getProperties', nodeId,
+ JSON.stringify([path, protoDepth]));
+};
+
+
+/**
+ * Returns prototype chain for a given node.
+ * @param {number} nodeId Node to get prototypes for.
+ * @param {Function} callback.
+ */
+devtools.DomAgent.prototype.getNodePrototypesAsync = function(nodeId,
+ callback) {
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
+ RemoteToolsAgent.ExecuteUtilityFunction(callbackId,
+ 'getPrototypes', nodeId, '[]');
+};
+
+
+/**
+ * Returns styles for given node.
+ * @param {devtools.DomNode} node Node to get prototypes for.
+ * @param {boolean} authorOnly Returns only author styles if true.
+ * @param {Function} callback.
+ */
+devtools.DomAgent.prototype.getNodeStylesAsync = function(node,
+ authorOnly, callback) {
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
+ RemoteToolsAgent.ExecuteUtilityFunction(callbackId,
+ 'getStyles',
+ node.id_,
+ JSON.stringify([authorOnly]));
+};
+
+
+/**
+ * Toggles style with given id on/off.
+ * @param {devtools.CSSStyleDeclaration} style Style to toggle.
+ * @param {boolean} enabled True if style should be enabled.
+ * @param {string} name Style name.
+ * @param {Function} callback.
+ */
+devtools.DomAgent.prototype.toggleNodeStyleAsync = function(
+ style, enabled, name, callback) {
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
+ RemoteToolsAgent.ExecuteUtilityFunction(callbackId,
+ 'toggleNodeStyle',
+ style.nodeId_,
+ JSON.stringify([style.id_, enabled, name]));
+};
+
+
+/**
+ * Applies new text to a style.
+ * @param {devtools.CSSStyleDeclaration} style Style to edit.
+ * @param {string} name Property name to edit.
+ * @param {string} styleText Text to set the style from.
+ * @param {Function} callback.
+ */
+devtools.DomAgent.prototype.applyStyleTextAsync = function(
+ style, name, styleText, callback) {
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
+ RemoteToolsAgent.ExecuteUtilityFunction(
+ callbackId,
+ 'applyStyleText',
+ style.nodeId_,
+ JSON.stringify([style.id_, name, styleText]));
+};
+
+
+/**
+ * Sets style property with given name to a value.
+ * @param {devtools.DomNode} node Node to edit style for.
+ * @param {string} name Property name to edit.
+ * @param {string} value New value.
+ * @param {Function} callback.
+ */
+devtools.DomAgent.prototype.setStylePropertyAsync = function(
+ node, name, value, callback) {
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
+ RemoteToolsAgent.ExecuteUtilityFunction(
+ callbackId,
+ 'setStyleProperty',
+ node.id_,
+ JSON.stringify([name, value]));
+};
+
+
+/**
+ * Dumps exception if something went wrong in ExecuteUtilityFunction.
+ * @param {Function} callback Callback to wrap.
+ * @return {number} Callback id.
+ */
+devtools.DomAgent.prototype.utilityFunctionCallbackWrapper_ =
+ function(callback) {
+ var mycallback = function(result, exception) {
+ if (exception && exception.length) {
+ debugPrint('Exception in ExecuteUtilityFunction styles:' + exception);
+ return;
+ }
+ callback(result);
+ };
+ return devtools.Callback.wrap(mycallback);
+};
+
+
+/**
+ * Represents remote CSSStyleDeclaration for using in StyleSidebarPane.
+ * @param {id, Array<Object>} payload built by inject's getStyle from the
+ * injected js.
+ * @constructor
+ */
+devtools.CSSStyleDeclaration = function(payload) {
+ this.id_ = payload[0];
+ this.width = payload[1];
+ this.height = payload[2];
+ this.__disabledProperties = payload[3];
+ this.__disabledPropertyValues = payload[4];
+ this.__disabledPropertyPriorities = payload[5];
+
+ this.length = payload.length - 6;
+ this.priority_ = {};
+ this.implicit_ = {};
+ this.shorthand_ = {};
+ this.value_ = {};
+
+ for (var i = 6; i < payload.length; ++i) {
+ var p = payload[i];
+ var name = p[0];
+
+ this.priority_[name] = p[1];
+ this.implicit_[name] = p[2];
+ this.shorthand_[name] = p[3];
+ this.value_[name] = p[4];
+
+ this[i - 6] = name;
+ }
+};
+
+
+/**
+ * @param {string} name of a CSS property.
+ * @return {string}
+ */
+devtools.CSSStyleDeclaration.prototype.getPropertyValue = function(name) {
+ return this.value_[name] || '';
+};
+
+
+/**
+ * @param {string} name of a CSS property.
+ * @return {string} 'important' | ''.
+ */
+devtools.CSSStyleDeclaration.prototype.getPropertyPriority = function(name) {
+ return this.priority_[name] || '';
+};
+
+
+/**
+ * @param {string} name of a CSS property.
+ * @return {string} shorthand name or ''
+ */
+devtools.CSSStyleDeclaration.prototype.getPropertyShorthand = function(name) {
+ return this.shorthand_[name] || '';
+};
+
+
+/**
+ * @param {string} name of a CSS property.
+ * @return {boolean}
+ */
+devtools.CSSStyleDeclaration.prototype.isPropertyImplicit = function(name) {
+ return !!this.implicit_[name];
+};
+
+
+function firstChildSkippingWhitespace() {
+ return this.firstChild;
+}
+
+
+function onlyTextChild() {
+ if (!this.children) {
+ return null;
+ } else if (this.children.length == 1 &&
+ this.children[0].nodeType == Node.TEXT_NODE) {
+ return this.children[0];
+ } else {
+ return null;
+ }
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inject.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inject.js
new file mode 100644
index 0000000..5c1050a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inject.js
@@ -0,0 +1,463 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Javascript that is being injected into the inspectable page
+ * while debugging.
+ */
+goog.provide('devtools.Injected');
+
+
+/**
+ * Main injected object.
+ * @constructor.
+ */
+devtools.Injected = function() {
+ /**
+ * Unique style id generator.
+ * @type {number}
+ * @private
+ */
+ this.lastStyleId_ = 1;
+
+ /**
+ * This array is not unused as it may seem. It stores references to the
+ * styles so that they could be found for future editing.
+ * @type {Array<CSSStyleDeclaration>}
+ * @private
+ */
+ this.styles_ = [];
+};
+
+
+/**
+ * Returns array of properties for a given node on a given path.
+ * @param {Node} node Node to get property value for.
+ * @param {Array.<string>} path Path to the nested object.
+ * @param {number} protoDepth Depth of the actual proto to inspect.
+ * @return {Array.<Object>} Array where each property is represented
+ * by the tree entries [{string} type, {string} name, {Object} value].
+ */
+devtools.Injected.prototype.getProperties = function(node, path, protoDepth) {
+ var result = [];
+ var obj = node;
+
+ // Follow the path.
+ for (var i = 0; obj && i < path.length; ++i) {
+ obj = obj[path[i]];
+ }
+
+ if (!obj) {
+ return [];
+ }
+
+ // Get to the necessary proto layer.
+ for (var i = 0; obj && i < protoDepth; ++i) {
+ obj = obj.__proto__;
+ }
+
+ if (!obj) {
+ return [];
+ }
+
+ // Go over properties, prepare results.
+ for (var name in obj) {
+ if (protoDepth != -1 && 'hasOwnProperty' in obj &&
+ !obj.hasOwnProperty(name)) {
+ continue;
+ }
+ var type = typeof obj[name];
+ result.push(type);
+ result.push(name);
+ if (type == 'string') {
+ var str = obj[name];
+ result.push(str.length > 99 ? str.substr(0, 99) + '...' : str);
+ } else if (type != 'object' && type != 'array' &&
+ type != 'function') {
+ result.push(obj[name]);
+ } else {
+ result.push(undefined);
+ }
+ }
+ return result;
+};
+
+
+/**
+ * Returns array of prototypes for a given node.
+ * @param {Node} node Node to get prorotypes for.
+ * @return {Array<string>} Array of proto names.
+ */
+devtools.Injected.prototype.getPrototypes = function(node) {
+ var result = [];
+ for (var prototype = node; prototype; prototype = prototype.__proto__) {
+ var description = Object.prototype.toString.call(prototype);
+ result.push(description.replace(/^\[object (.*)\]$/i, '$1'));
+ }
+ return result;
+};
+
+
+/**
+ * Returns style information that is used in devtools.js.
+ * @param {Node} node Node to get prorotypes for.
+ * @param {boolean} authorOnly Determines whether only author styles need to
+ * be added.
+ * @return {string} Style collection descriptor.
+ */
+devtools.Injected.prototype.getStyles = function(node, authorOnly) {
+ if (!node.nodeType == Node.ELEMENT_NODE) {
+ return {};
+ }
+ var matchedRules = window.getMatchedCSSRules(node, '', false);
+ var matchedCSSRulesObj = [];
+ for (var i = 0; matchedRules && i < matchedRules.length; ++i) {
+ var rule = matchedRules[i];
+ var parentStyleSheet = rule.parentStyleSheet;
+ var isUserAgent = parentStyleSheet && !parentStyleSheet.ownerNode &&
+ !parentStyleSheet.href;
+ var isUser = parentStyleSheet && parentStyleSheet.ownerNode &&
+ parentStyleSheet.ownerNode.nodeName == '#document';
+
+ var style = this.serializeStyle_(rule.style, !isUserAgent && !isUser);
+ var ruleValue = {
+ 'selector' : rule.selectorText,
+ 'style' : style
+ };
+ if (parentStyleSheet) {
+ ruleValue['parentStyleSheet'] = {
+ 'href' : parentStyleSheet.href,
+ 'ownerNodeName' : parentStyleSheet.ownerNode ?
+ parentStyleSheet.ownerNode.name : null
+ };
+ }
+ matchedCSSRulesObj.push(ruleValue);
+ }
+
+ var attributeStyles = {};
+ var attributes = node.attributes;
+ for (var i = 0; attributes && i < attributes.length; ++i) {
+ if (attributes[i].style) {
+ attributeStyles[attributes[i].name] =
+ this.serializeStyle_(attributes[i].style, true);
+ }
+ }
+ var result = {
+ 'inlineStyle' : this.serializeStyle_(node.style, true),
+ 'computedStyle' : this.serializeStyle_(
+ window.getComputedStyle(node, '')),
+ 'matchedCSSRules' : matchedCSSRulesObj,
+ 'styleAttributes' : attributeStyles
+ };
+ return result;
+};
+
+
+/**
+ * Returns style decoration object for given id.
+ * @param {Node} node Node to get prorotypes for.
+ * @param {number} id Style id.
+ * @return {Object} Style object.
+ * @private
+ */
+devtools.Injected.prototype.getStyleForId_ = function(node, id) {
+ var matchedRules = window.getMatchedCSSRules(node, '', false);
+ for (var i = 0; matchedRules && i < matchedRules.length; ++i) {
+ var rule = matchedRules[i];
+ if (rule.style.__id == id) {
+ return rule.style;
+ }
+ }
+ var attributes = node.attributes;
+ for (var i = 0; attributes && i < attributes.length; ++i) {
+ if (attributes[i].style && attributes[i].style.__id == id) {
+ return attributes[i].style;
+ }
+ }
+ if (node.style.__id == id) {
+ return node.style;
+ }
+ return null;
+};
+
+
+
+
+/**
+ * Converts given style into serializable object.
+ * @param {CSSStyleDeclaration} style Style to serialize.
+ * @param {boolean} opt_bind Determins whether this style should be bound.
+ * @return {Array<Object>} Serializable object.
+ * @private
+ */
+devtools.Injected.prototype.serializeStyle_ = function(style, opt_bind) {
+ if (!style) {
+ return [];
+ }
+ var id = style.__id;
+ if (opt_bind && !id) {
+ id = style.__id = this.lastStyleId_++;
+ this.styles_.push(style);
+ }
+ var result = [
+ id,
+ style.width,
+ style.height,
+ style.__disabledProperties,
+ style.__disabledPropertyValues,
+ style.__disabledPropertyPriorities
+ ];
+ for (var i = 0; i < style.length; ++i) {
+ var name = style[i];
+ result.push([
+ name,
+ style.getPropertyPriority(name),
+ style.isPropertyImplicit(name),
+ style.getPropertyShorthand(name),
+ style.getPropertyValue(name)
+ ]);
+ }
+ return result;
+};
+
+
+/**
+ * Toggles style with given id on/off.
+ * @param {Node} node Node to get prorotypes for.
+ * @param {number} styleId Id of style to toggle.
+ * @param {boolean} enabled Determines value to toggle to,
+ * @param {string} name Name of the property.
+ */
+devtools.Injected.prototype.toggleNodeStyle = function(node, styleId, enabled,
+ name) {
+ var style = this.getStyleForId_(node, styleId);
+ if (!style) {
+ return false;
+ }
+
+ if (!enabled) {
+ if (!style.__disabledPropertyValues ||
+ !style.__disabledPropertyPriorities) {
+ style.__disabledProperties = {};
+ style.__disabledPropertyValues = {};
+ style.__disabledPropertyPriorities = {};
+ }
+
+ style.__disabledPropertyValues[name] = style.getPropertyValue(name);
+ style.__disabledPropertyPriorities[name] = style.getPropertyPriority(name);
+
+ if (style.getPropertyShorthand(name)) {
+ var longhandProperties = this.getLonghandProperties_(style, name);
+ for (var i = 0; i < longhandProperties.length; ++i) {
+ style.__disabledProperties[longhandProperties[i]] = true;
+ style.removeProperty(longhandProperties[i]);
+ }
+ } else {
+ style.__disabledProperties[name] = true;
+ style.removeProperty(name);
+ }
+ } else if (style.__disabledProperties &&
+ style.__disabledProperties[name]) {
+ var value = style.__disabledPropertyValues[name];
+ var priority = style.__disabledPropertyPriorities[name];
+ style.setProperty(name, value, priority);
+
+ delete style.__disabledProperties[name];
+ delete style.__disabledPropertyValues[name];
+ delete style.__disabledPropertyPriorities[name];
+ }
+ return true;
+};
+
+
+/**
+ * Applies given text to a style.
+ * @param {Node} node Node to get prorotypes for.
+ * @param {number} styleId Id of style to toggle.
+ * @param {string} name Style element name.
+ * @param {string} styleText New style text.
+ * @return {boolean} True iff style has been edited successfully.
+ */
+devtools.Injected.prototype.applyStyleText = function(node, styleId,
+ name, styleText) {
+ var style = this.getStyleForId_(node, styleId);
+ if (!style) {
+ return false;
+ }
+
+ var styleTextLength = this.trimWhitespace_(styleText).length;
+
+ // Create a new element to parse the user input CSS.
+ var parseElement = document.createElement("span");
+ parseElement.setAttribute("style", styleText);
+
+ var tempStyle = parseElement.style;
+ if (tempStyle.length || !styleTextLength) {
+ // The input was parsable or the user deleted everything, so remove the
+ // original property from the real style declaration. If this represents
+ // a shorthand remove all the longhand properties.
+ if (style.getPropertyShorthand(name)) {
+ var longhandProperties = this.getLonghandProperties_(style, name);
+ for (var i = 0; i < longhandProperties.length; ++i) {
+ style.removeProperty(longhandProperties[i]);
+ }
+ } else {
+ style.removeProperty(name);
+ }
+ }
+ if (!tempStyle.length) {
+ // The user typed something, but it didn't parse. Just abort and restore
+ // the original title for this property.
+ return false;
+ }
+
+ // Iterate of the properties on the test element's style declaration and
+ // add them to the real style declaration. We take care to move shorthands.
+ var foundShorthands = {};
+ var uniqueProperties = this.getUniqueStyleProperties_(tempStyle);
+ for (var i = 0; i < uniqueProperties.length; ++i) {
+ var name = uniqueProperties[i];
+ var shorthand = tempStyle.getPropertyShorthand(name);
+
+ if (shorthand && shorthand in foundShorthands) {
+ continue;
+ }
+
+ if (shorthand) {
+ var value = this.getShorthandValue_(tempStyle, shorthand);
+ var priority = this.getShorthandPriority_(tempStyle, shorthand);
+ foundShorthands[shorthand] = true;
+ } else {
+ var value = tempStyle.getPropertyValue(name);
+ var priority = tempStyle.getPropertyPriority(name);
+ }
+ // Set the property on the real style declaration.
+ style.setProperty((shorthand || name), value, priority);
+ }
+ return true;
+};
+
+
+/**
+ * Sets style property with given name to a value.
+ * @param {Node} node Node to get prorotypes for.
+ * @param {string} name Style element name.
+ * @param {string} value Value.
+ * @return {boolean} True iff style has been edited successfully.
+ */
+devtools.Injected.prototype.setStyleProperty = function(node,
+ name, value) {
+ node.style.setProperty(name, value, "");
+ return true;
+};
+
+
+/**
+ * Taken from utilities.js as is for injected evaluation.
+ */
+devtools.Injected.prototype.getLonghandProperties_ = function(style,
+ shorthandProperty) {
+ var properties = [];
+ var foundProperties = {};
+
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (individualProperty in foundProperties ||
+ style.getPropertyShorthand(individualProperty) != shorthandProperty) {
+ continue;
+ }
+ foundProperties[individualProperty] = true;
+ properties.push(individualProperty);
+ }
+ return properties;
+};
+
+
+/**
+ * Taken from utilities.js as is for injected evaluation.
+ */
+devtools.Injected.prototype.getShorthandValue_ = function(style,
+ shorthandProperty) {
+ var value = style.getPropertyValue(shorthandProperty);
+ if (!value) {
+ // Some shorthands (like border) return a null value, so compute a
+ // shorthand value.
+ // FIXME: remove this when http://bugs.webkit.org/show_bug.cgi?id=15823
+ // is fixed.
+
+ var foundProperties = {};
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (individualProperty in foundProperties ||
+ style.getPropertyShorthand(individualProperty) !==
+ shorthandProperty) {
+ continue;
+ }
+
+ var individualValue = style.getPropertyValue(individualProperty);
+ if (style.isPropertyImplicit(individualProperty) ||
+ individualValue === "initial") {
+ continue;
+ }
+
+ foundProperties[individualProperty] = true;
+
+ if (!value) {
+ value = "";
+ } else if (value.length) {
+ value += " ";
+ }
+ value += individualValue;
+ }
+ }
+ return value;
+};
+
+
+/**
+ * Taken from utilities.js as is for injected evaluation.
+ */
+devtools.Injected.prototype.getShorthandPriority_ = function(style,
+ shorthandProperty) {
+ var priority = style.getPropertyPriority(shorthandProperty);
+ if (!priority) {
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (style.getPropertyShorthand(individualProperty) !==
+ shorthandProperty) {
+ continue;
+ }
+ priority = style.getPropertyPriority(individualProperty);
+ break;
+ }
+ }
+ return priority;
+};
+
+
+/**
+ * Taken from utilities.js as is for injected evaluation.
+ */
+devtools.Injected.prototype.trimWhitespace_ = function(str) {
+ return str.replace(/^[\s\xA0]+|[\s\xA0]+$/g, '');
+};
+
+
+/**
+ * Taken from utilities.js as is for injected evaluation.
+ */
+devtools.Injected.prototype.getUniqueStyleProperties_ = function(style) {
+ var properties = [];
+ var foundProperties = {};
+
+ for (var i = 0; i < style.length; ++i) {
+ var property = style[i];
+ if (property in foundProperties) {
+ continue;
+ }
+ foundProperties[property] = true;
+ properties.push(property);
+ }
+ return properties;
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector.css b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector.css
new file mode 100644
index 0000000..2653781
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector.css
@@ -0,0 +1,3104 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+body {
+ cursor: default;
+ height: 100%;
+ width: 100%;
+ overflow: hidden;
+ font-family: Lucida Grande, sans-serif;
+ font-size: 10px;
+ margin: 0;
+ -webkit-text-size-adjust: none;
+ -webkit-user-select: none;
+}
+
+* {
+ -webkit-box-sizing: border-box;
+}
+
+:focus {
+ outline: none;
+}
+
+input[type="search"]:focus, input[type="text"]:focus {
+ outline: auto 5px -webkit-focus-ring-color;
+}
+
+iframe, a img {
+ border: none;
+}
+
+img {
+ -webkit-user-drag: none;
+}
+
+.hidden {
+ display: none !important;
+}
+
+#toolbar {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 56px;
+ display: -webkit-box;
+ padding: 0 5px;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(191, 191, 191)), to(rgb(151, 151, 151)));
+ border-bottom: 1px solid rgb(80, 80, 80);
+ -webkit-box-orient: horizontal;
+ -webkit-background-origin: padding;
+ -webkit-background-clip: padding;
+}
+
+body.inactive #toolbar {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(233, 233, 233)), to(rgb(207, 207, 207)));
+ border-bottom: 1px solid rgb(64%, 64%, 64%);
+}
+
+body.detached.platform-mac-leopard #toolbar {
+ background: transparent !important;
+}
+
+body.attached #toolbar {
+ height: 34px;
+ border-top: 1px solid rgb(100, 100, 100);
+ cursor: row-resize;
+ padding-left: 0;
+}
+
+body.attached.inactive #toolbar {
+ border-top: 1px solid rgb(64%, 64%, 64%);
+}
+
+.toolbar-item {
+ display: -webkit-box;
+ padding: 4px 6px;
+ margin: 0;
+ background-color: transparent;
+ border-style: none;
+ border-color: transparent;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: center;
+ -webkit-box-pack: end;
+}
+
+.toolbar-item.toggleable.toggled-on {
+ border-width: 0 2px 0 2px;
+ padding: 4px 4px;
+ -webkit-border-image: url(Images/toolbarItemSelected.png) 0 2 0 2;
+}
+
+.toolbar-item.flexable-space {
+ -webkit-box-flex: 1;
+ visibility: hidden;
+}
+
+.toolbar-item input {
+ margin-bottom: 8px;
+}
+
+.toolbar-icon {
+ display: inline-block;
+ width: 32px;
+ height: 32px;
+ -webkit-background-size: 100% auto;
+}
+
+body.attached .toolbar-icon {
+ width: 24px;
+ height: 24px;
+ vertical-align: middle;
+}
+
+.toolbar-item:active .toolbar-icon {
+ background-position: 0 32px;
+}
+
+body.attached .toolbar-item:active .toolbar-icon {
+ background-position: 0 24px;
+}
+
+.toolbar-label {
+ font-size: 11px;
+ font-family: Lucida Grande, sans-serif;
+ text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0;
+}
+
+.toolbar-item.toggleable:active .toolbar-label {
+ text-shadow: none;
+}
+
+body.attached .toolbar-label {
+ display: inline-block;
+ vertical-align: middle;
+ margin-left: 3px;
+}
+
+body.attached #search-toolbar-label {
+ display: none;
+}
+
+#search {
+ width: 205px;
+ font-size: 16px;
+ margin-bottom: 5px;
+}
+
+body.attached #search {
+ font-size: 11px;
+ margin-bottom: 8px;
+}
+
+#search-results-matches {
+ font-size: 11px;
+ text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0;
+ margin-bottom: 22px;
+}
+
+body.attached #search-results-matches {
+ margin-bottom: 6px;
+}
+
+.toolbar-item.elements .toolbar-icon {
+ background-image: url(Images/elementsIcon.png);
+}
+
+.toolbar-item.resources .toolbar-icon {
+ background-image: url(Images/resourcesIcon.png);
+}
+
+.toolbar-item.scripts .toolbar-icon {
+ background-image: url(Images/scriptsIcon.png);
+}
+
+.toolbar-item.databases .toolbar-icon {
+ background-image: url(Images/databasesIcon.png);
+}
+
+.toolbar-item.profiles .toolbar-icon {
+ background-image: url(Images/profilesIcon.png);
+}
+
+#close-button {
+ width: 14px;
+ height: 14px;
+ background-image: url(Images/closeButtons.png);
+ background-position: 0 0;
+ background-color: transparent;
+ border: 0 none transparent;
+ margin: 5px 0;
+}
+
+#close-button:hover {
+ background-position: 14px 0;
+}
+
+#close-button:active {
+ background-position: 28px 0;
+}
+
+body.detached .toolbar-item.close {
+ display: none;
+}
+
+#main {
+ position: absolute;
+ z-index: 1;
+ top: 56px;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ overflow: hidden;
+ background-color: white;
+}
+
+body.attached #main {
+ top: 34px;
+}
+
+#main-panels {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 23px;
+ overflow: hidden;
+}
+
+#main-status-bar {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+}
+
+body.console-visible #main-status-bar {
+ height: 24px;
+ background-image: url(Images/statusbarResizerVertical.png), url(Images/statusbarBackground.png);
+ background-repeat: no-repeat, repeat-x;
+ background-position: right center, center;
+ cursor: row-resize;
+}
+
+body.console-visible #main-status-bar * {
+ cursor: default;
+}
+
+body.console-visible #main-panels {
+ bottom: 24px;
+}
+
+.status-bar {
+ background-color: rgb(235, 235, 235);
+ background-image: url(Images/statusbarBackground.png);
+ background-repeat: repeat-x;
+ white-space: nowrap;
+ height: 23px;
+ overflow: hidden;
+ z-index: 12;
+}
+
+.status-bar > div {
+ display: inline-block;
+ vertical-align: top;
+}
+
+.status-bar-item {
+ display: inline-block;
+ height: 24px;
+ padding: 0;
+ margin-left: -1px;
+ margin-right: 0;
+ vertical-align: top;
+ border: 0 transparent none;
+ background-color: transparent;
+}
+
+.status-bar-item:active {
+ position: relative;
+ z-index: 200;
+}
+
+button.status-bar-item {
+ width: 32px;
+ background-image: url(Images/statusbarButtons.png);
+ background-position: 0 0;
+}
+
+button.status-bar-item:active {
+ background-position: 32px 0;
+}
+
+button.status-bar-item:disabled {
+ opacity: 0.5;
+ background-position: 0 0 !important;
+}
+
+select.status-bar-item {
+ min-width: 48px;
+ border-width: 0 17px 0 2px;
+ padding: 0 2px 0 6px;
+ font-weight: bold;
+ color: rgb(48, 48, 48);
+ text-shadow: rgba(255, 255, 255, 0.75) 0 1px 0;
+ -webkit-border-image: url(Images/statusbarMenuButton.png) 0 17 0 2;
+ -webkit-border-radius: 0;
+ -webkit-appearance: none;
+}
+
+select.status-bar-item:active {
+ color: black;
+ -webkit-border-image: url(Images/statusbarMenuButtonSelected.png) 0 17 0 2;
+}
+
+#dock-status-bar-item {
+ background-image: url(Images/dockButtons.png);
+}
+
+body.attached #dock-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+body.detached #dock-status-bar-item {
+ background-position: 0 24px;
+}
+
+body.detached #dock-status-bar-item.toggled-on:active {
+ background-position: 32px 24px;
+}
+
+#console-status-bar-item {
+ background-image: url(Images/consoleButtons.png);
+}
+
+#console-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+#console-status-bar-item.toggled-on {
+ background-position: 0 24px;
+}
+
+#console-status-bar-item.toggled-on:active {
+ background-position: 32px 24px;
+}
+
+#clear-console-status-bar-item {
+ background-image: url(Images/clearConsoleButtons.png);
+}
+
+#clear-console-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+#error-warning-count {
+ position: absolute;
+ right: 16px;
+ top: 0;
+ cursor: pointer;
+ padding: 6px 2px;
+ font-size: 10px;
+ height: 19px;
+}
+
+#error-warning-count:hover {
+ border-bottom: 1px solid rgb(96, 96, 96);
+}
+
+#error-count::before {
+ content: url(Images/errorIcon.png);
+ width: 10px;
+ height: 10px;
+ vertical-align: -1px;
+ margin-right: 2px;
+}
+
+#error-count + #warning-count {
+ margin-left: 6px;
+}
+
+#warning-count::before {
+ content: url(Images/warningIcon.png);
+ width: 10px;
+ height: 10px;
+ vertical-align: -1px;
+ margin-right: 2px;
+}
+
+#console {
+ display: none;
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 200px;
+ background-color: white;
+ background-image: url(Images/statusbarBottomBackground.png);
+ background-repeat: repeat-x;
+ background-position: bottom;
+}
+
+body.console-visible #console {
+ display: block;
+}
+
+#console-status-bar {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: none;
+}
+
+#console-messages {
+ position: absolute;
+ z-index: 0;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 23px;
+ font-size: 10px;
+ font-family: Monaco, Lucida Console, monospace;
+ padding: 2px 0;
+ overflow-y: overlay;
+ -webkit-user-select: text;
+ -webkit-text-size-adjust: auto;
+}
+
+#console-prompt {
+ position: relative;
+ padding: 1px 22px 1px 24px;
+ min-height: 16px;
+ white-space: pre-wrap;
+ -webkit-user-modify: read-write-plaintext-only;
+}
+
+#console-prompt::before {
+ background-image: url(Images/userInputIcon.png);
+}
+
+.console-user-command-result.console-log-level::before {
+ background-image: url(Images/userInputResultIcon.png);
+}
+
+.console-message, .console-user-command {
+ position: relative;
+ border-bottom: 1px solid rgb(240, 240, 240);
+ padding: 1px 22px 1px 24px;
+ min-height: 16px;
+}
+
+.console-adjacent-user-command-result {
+ border-bottom: none;
+}
+
+.console-adjacent-user-command-result + .console-user-command-result.console-log-level::before {
+ background-image: none;
+}
+
+.console-message::before, .console-user-command::before, #console-prompt::before, .console-group-title-level::before {
+ position: absolute;
+ display: block;
+ content: "";
+ left: 7px;
+ top: 0.8em;
+ width: 10px;
+ height: 10px;
+ margin-top: -5px;
+ -webkit-user-select: none;
+}
+
+.console-message .bubble {
+ display: inline-block;
+ height: 14px;
+ background-color: rgb(128, 151, 189);
+ vertical-align: middle;
+ white-space: nowrap;
+ padding: 1px 4px;
+ margin-top: -2px;
+ margin-right: 4px;
+ text-align: left;
+ font-size: 11px;
+ font-family: Helvetia, Arial, sans-serif;
+ font-weight: bold;
+ text-shadow: none;
+ color: white;
+ -webkit-border-radius: 7px;
+}
+
+.console-message-text {
+ white-space: pre-wrap;
+}
+
+.repeated-message {
+ padding-left: 6px;
+}
+
+.repeated-message.console-error-level::before, .repeated-message.console-warning-level:before {
+ visibility: hidden;
+}
+
+.console-group .console-group > .console-group-messages {
+ margin-left: 16px;
+}
+
+.console-group-title-level {
+ font-weight: bold;
+}
+
+.console-group-title-level::before {
+ background-image: url(Images/disclosureTriangleSmallDown.png);
+ top: 0.6em;
+ width: 11px;
+ height: 12px;
+}
+
+.console-group.collapsed .console-group-title-level::before {
+ background-image: url(Images/disclosureTriangleSmallRight.png);
+}
+
+.console-group.collapsed > .console-group-messages {
+ display: none;
+}
+
+.console-error-level .console-message-text {
+ color: red;
+}
+
+.console-error-level::before {
+ background-image: url(Images/errorIcon.png);
+}
+
+.console-warning-level::before {
+ background-image: url(Images/warningIcon.png);
+}
+
+.console-user-command .console-message {
+ margin-left: -24px;
+ padding-right: 0;
+ border-bottom: none;
+}
+
+.console-user-command::before {
+ background-image: url(Images/userInputPreviousIcon.png);
+}
+
+.console-user-command > .console-message-text {
+ color: rgb(0, 128, 255);
+}
+
+#console-messages a {
+ color: rgb(33%, 33%, 33%);
+ cursor: pointer;
+}
+
+#console-messages a:hover {
+ color: rgb(15%, 15%, 15%);
+}
+
+.console-message-url {
+ float: right;
+}
+
+.console-group-messages .section {
+ margin: 0 0 0 12px !important;
+}
+
+.console-group-messages .section .header {
+ padding: 0 8px 0 0;
+ background-image: none;
+ border: none;
+ min-height: 0;
+}
+
+.console-group-messages .section .header::before {
+ position: absolute;
+ top: 1px;
+ left: 1px;
+ width: 8px;
+ height: 8px;
+ content: url(Images/treeRightTriangleBlack.png);
+}
+
+.console-group-messages .section.expanded .header::before {
+ content: url(Images/treeDownTriangleBlack.png);
+}
+
+.console-group-messages .section .header .title {
+ color: black;
+ font-weight: normal;
+}
+
+.console-group-messages .section .properties li .info {
+ padding-top: 0;
+ padding-bottom: 0;
+ color: rgb(60%, 60%, 60%);
+}
+
+.console-group-messages .outline-disclosure {
+ padding-left: 0;
+}
+
+.console-group-messages .outline-disclosure > ol {
+ padding: 0 0 0 12px !important;
+}
+
+.console-group-messages .outline-disclosure, .console-group-messages .outline-disclosure ol {
+ font-size: inherit;
+ line-height: 1em;
+}
+
+.console-group-messages .outline-disclosure.single-node li {
+ padding-left: 2px;
+}
+
+.console-group-messages .outline-disclosure li .selection {
+ margin-left: -6px;
+ margin-right: -6px;
+}
+
+.console-formatted-object, .console-formatted-node {
+ position: relative;
+ display: inline-block;
+ vertical-align: top;
+}
+
+.console-formatted-object .section, .console-formatted-node .section {
+ position: static;
+}
+
+.console-formatted-object .properties, .console-formatted-node .properties {
+ padding-left: 0 !important;
+}
+
+.error-message {
+ color: red;
+}
+
+.auto-complete-text {
+ color: rgb(128, 128, 128);
+ -webkit-user-select: none;
+ -webkit-user-modify: read-only;
+}
+
+.panel {
+ display: none;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+
+.panel.visible {
+ display: block;
+}
+
+.resource-view {
+ display: none;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ overflow: hidden;
+}
+
+.resource-view.visible {
+ display: block;
+}
+
+.resource-view.headers-visible {
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+.resource-view-headers {
+ display: none;
+ padding: 6px;
+ border-bottom: 1px solid rgb(64%, 64%, 64%);
+ background-color: white;
+ -webkit-user-select: text;
+}
+
+.resource-view-headers .outline-disclosure .parent {
+ -webkit-user-select: none;
+ font-weight: bold;
+}
+
+.resource-view.headers-visible .resource-view-headers {
+ display: block;
+}
+
+.resource-view-headers .outline-disclosure .children li {
+ white-space: nowrap;
+}
+
+.resource-view-headers .outline-disclosure li.expanded .header-count {
+ display: none;
+}
+
+.resource-view-headers .outline-disclosure .header-name {
+ color: rgb(33%, 33%, 33%);
+ display: inline-block;
+ width: 105px;
+ text-align: right;
+ margin-right: 0.5em;
+ font-weight: bold;
+ vertical-align: top;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.resource-view-headers .outline-disclosure .header-value {
+ display: inline-block;
+ white-space: normal;
+ word-break: break-word;
+ vertical-align: top;
+ margin-right: 100px;
+}
+
+.resource-view .resource-view-content {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 0;
+ bottom: 0;
+}
+
+.resource-view.headers-visible .resource-view-content {
+ position: relative;
+ top: auto;
+ right: auto;
+ left: auto;
+ bottom: auto;
+}
+
+.resource-view.headers-visible .source-view-frame {
+ height: auto;
+ vertical-align: top;
+}
+
+.webkit-line-gutter-backdrop {
+ /* Keep this in sync with view-source.css (.webkit-line-gutter-backdrop) */
+ width: 31px;
+ background-color: rgb(240, 240, 240);
+ border-right: 1px solid rgb(187, 187, 187);
+ position: absolute;
+ z-index: -1;
+ left: 0;
+ top: 0;
+ height: 100%
+}
+
+.resource-view.font .resource-view-content {
+ font-size: 60px;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+ text-align: center;
+ padding: 15px;
+}
+
+.resource-view.image .resource-view-content > .image {
+ padding: 20px 20px 10px 20px;
+ text-align: center;
+}
+
+.resource-view.image .resource-view-content > .info {
+ padding-bottom: 10px;
+ font-size: 11px;
+ -webkit-user-select: text;
+}
+
+.resource-view.image img {
+ max-width: 100%;
+ max-height: 1000px;
+ background-image: url(Images/checker.png);
+ -webkit-box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.5);
+ -webkit-user-select: text;
+ -webkit-user-drag: auto;
+}
+
+.resource-view.image .title {
+ text-align: center;
+ font-size: 13px;
+}
+
+.resource-view.image .infoList {
+ margin: 0;
+}
+
+.resource-view.image .infoList dt {
+ font-weight: bold;
+ display: inline-block;
+ width: 50%;
+ text-align: right;
+ color: rgb(76, 76, 76);
+}
+
+.resource-view.image .infoList dd {
+ display: inline-block;
+ padding-left: 8px;
+ width: 50%;
+ text-align: left;
+ margin: 0;
+}
+
+.resource-view.image .infoList dd::after {
+ white-space: pre;
+ content: "\A";
+}
+
+#elements-content {
+ display: block;
+ overflow: auto;
+ padding: 0;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 225px;
+ bottom: 0;
+}
+
+#elements-sidebar {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ width: 225px;
+ background-color: rgb(245, 245, 245);
+ border-left: 1px solid rgb(64%, 64%, 64%);
+ cursor: default;
+ overflow: auto;
+}
+
+.crumbs {
+ display: inline-block;
+ font-size: 11px;
+ line-height: 19px;
+ text-shadow: rgba(255, 255, 255, 0.75) 0 1px 0;
+ color: rgb(20, 20, 20);
+ margin-left: -1px;
+ padding-right: 12px;
+}
+
+.crumbs .crumb {
+ height: 24px;
+ border-width: 0 12px 0 2px;
+ -webkit-border-image: url(Images/segment.png) 0 12 0 2;
+ margin-right: -12px;
+ padding-left: 18px;
+ padding-right: 2px;
+ white-space: nowrap;
+ line-height: 23px;
+ float: right;
+}
+
+.crumbs .crumb.collapsed > * {
+ display: none;
+}
+
+.crumbs .crumb.collapsed::before {
+ content: "\2026";
+ font-weight: bold;
+}
+
+.crumbs .crumb.compact .extra {
+ display: none;
+}
+
+.crumbs .crumb.dimmed {
+ color: rgba(0, 0, 0, 0.45);
+}
+
+.crumbs .crumb.start {
+ padding-left: 7px;
+}
+
+.crumbs .crumb.end {
+ border-width: 0 2px 0 2px;
+ padding-right: 6px;
+ -webkit-border-image: url(Images/segmentEnd.png) 0 2 0 2;
+}
+
+.crumbs .crumb.selected {
+ -webkit-border-image: url(Images/segmentSelected.png) 0 12 0 2;
+ color: black;
+ text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0;
+}
+
+.crumbs .crumb.selected:hover {
+ -webkit-border-image: url(Images/segmentSelected.png) 0 12 0 2;
+}
+
+.crumbs .crumb.selected.end, .crumbs .crumb.selected.end:hover {
+ -webkit-border-image: url(Images/segmentSelectedEnd.png) 0 2 0 2;
+}
+
+.crumbs .crumb:hover {
+ -webkit-border-image: url(Images/segmentHover.png) 0 12 0 2;
+ color: black;
+}
+
+.crumbs .crumb.dimmed:hover {
+ -webkit-border-image: url(Images/segmentHover.png) 0 12 0 2;
+ color: rgba(0, 0, 0, 0.75);
+}
+
+.crumbs .crumb.end:hover {
+ -webkit-border-image: url(Images/segmentHoverEnd.png) 0 2 0 2;
+}
+
+.outline-disclosure li.hovered:not(.selected) .selection {
+ display: block;
+ left: 3px;
+ right: 3px;
+ background-color: rgba(56, 121, 217, 0.1);
+ -webkit-border-radius: 5px;
+}
+
+.outline-disclosure li.highlighted .highlight {
+ background-color: rgb(255, 230, 179);
+ -webkit-border-radius: 4px;
+ padding-bottom: 2px;
+ margin-bottom: -2px;
+}
+
+.outline-disclosure li.selected.highlighted .highlight {
+ background-color: transparent;
+ padding-bottom: 0;
+ margin-bottom: 0;
+}
+
+.outline-disclosure li .selection {
+ display: none;
+ position: absolute;
+ left: 0;
+ right: 0;
+ height: 15px;
+ z-index: -1;
+}
+
+.outline-disclosure li.selected .selection {
+ display: block;
+ background-color: rgb(212, 212, 212);
+}
+
+:focus .outline-disclosure li.selected .selection {
+ background-color: rgb(56, 121, 217);
+}
+
+.outline-disclosure > ol {
+ position: relative;
+ padding: 2px 6px !important;
+ margin: 0;
+ color: black;
+ cursor: default;
+ min-width: 100%;
+}
+
+.outline-disclosure, .outline-disclosure ol {
+ list-style-type: none;
+ font-size: 11px;
+ -webkit-padding-start: 12px;
+ margin: 0;
+}
+
+.outline-disclosure li {
+ padding: 0 0 2px 14px;
+ margin-top: 1px;
+ margin-bottom: 1px;
+ word-wrap: break-word;
+ text-indent: -2px
+}
+
+:focus .outline-disclosure li.selected {
+ color: white;
+}
+
+:focus .outline-disclosure li.selected * {
+ color: inherit;
+}
+
+.outline-disclosure li.parent {
+ text-indent: -12px
+}
+
+.outline-disclosure li .webkit-html-tag.close {
+ margin-left: -12px;
+}
+
+.outline-disclosure li.parent::before {
+ content: url(Images/treeRightTriangleBlack.png);
+ float: left;
+ width: 8px;
+ height: 8px;
+ margin-top: 1px;
+ padding-right: 2px;
+}
+
+.outline-disclosure li.parent::before {
+ content: url(Images/treeRightTriangleBlack.png);
+}
+
+:focus .outline-disclosure li.parent.selected::before {
+ content: url(Images/treeRightTriangleWhite.png);
+}
+
+.outline-disclosure li.parent.expanded::before {
+ content: url(Images/treeDownTriangleBlack.png);
+}
+
+:focus .outline-disclosure li.parent.expanded.selected::before {
+ content: url(Images/treeDownTriangleWhite.png);
+}
+
+.outline-disclosure ol.children {
+ display: none;
+}
+
+.outline-disclosure ol.children.expanded {
+ display: block;
+}
+
+.webkit-html-comment {
+ /* Keep this in sync with view-source.css (.webkit-html-comment) */
+ color: rgb(35, 110, 37);
+}
+
+.webkit-html-tag {
+ /* Keep this in sync with view-source.css (.webkit-html-tag) */
+ color: rgb(136, 18, 128);
+}
+
+.webkit-html-doctype {
+ /* Keep this in sync with view-source.css (.webkit-html-doctype) */
+ color: rgb(192, 192, 192);
+}
+
+.webkit-html-attribute-name {
+ /* Keep this in sync with view-source.css (.webkit-html-attribute-name) */
+ color: rgb(153, 69, 0);
+}
+
+.webkit-html-attribute-value {
+ /* Keep this in sync with view-source.css (.webkit-html-attribute-value) */
+ color: rgb(26, 26, 166);
+}
+
+.webkit-html-external-link, .webkit-html-resource-link {
+ /* Keep this in sync with view-source.css (.webkit-html-external-link, .webkit-html-resource-link) */
+ color: #00e;
+}
+
+.webkit-html-external-link {
+ /* Keep this in sync with view-source.css (.webkit-html-external-link) */
+ text-decoration: none;
+}
+
+.webkit-html-external-link:hover {
+ /* Keep this in sync with view-source.css (.webkit-html-external-link:hover) */
+ text-decoration: underline;
+}
+
+.placard {
+ position: relative;
+ margin-top: 1px;
+ padding: 3px 8px 4px 18px;
+ min-height: 18px;
+ white-space: nowrap;
+}
+
+.placard:nth-of-type(2n) {
+ background-color: rgb(234, 243, 255);
+}
+
+.placard.selected {
+ border-top: 1px solid rgb(145, 160, 192);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(162, 177, 207)), to(rgb(120, 138, 177)));
+ -webkit-background-origin: padding;
+ -webkit-background-clip: padding;
+}
+
+:focus .placard.selected {
+ border-top: 1px solid rgb(68, 128, 200);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(92, 147, 213)), to(rgb(21, 83, 170)));
+}
+
+body.inactive .placard.selected {
+ border-top: 1px solid rgb(151, 151, 151);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(180, 180, 180)), to(rgb(138, 138, 138)));
+}
+
+.placard .title {
+ color: black;
+ font-weight: normal;
+ word-wrap: break-word;
+ white-space: normal;
+}
+
+.placard.selected .title {
+ color: white;
+ font-weight: bold;
+}
+
+.placard .subtitle {
+ float: right;
+ font-size: 10px;
+ margin-left: 5px;
+ max-width: 55%;
+ color: rgba(0, 0, 0, 0.7);
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+.placard.selected .subtitle {
+ color: rgba(255, 255, 255, 0.7);
+}
+
+.placard .subtitle a {
+ color: inherit;
+}
+
+.section {
+ position: relative;
+ margin-top: 1px;
+}
+
+.section:nth-last-of-type(1) {
+ margin-bottom: 1px;
+}
+
+.section .header {
+ padding: 2px 8px 4px 18px;
+ border-top: 1px solid rgb(145, 160, 192);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(162, 177, 207)), to(rgb(120, 138, 177)));
+ min-height: 18px;
+ white-space: nowrap;
+ -webkit-background-origin: padding;
+ -webkit-background-clip: padding;
+}
+
+.section .header::before {
+ position: absolute;
+ top: 4px;
+ left: 7px;
+ width: 8px;
+ height: 8px;
+ content: url(Images/treeRightTriangleWhite.png);
+}
+
+.section.expanded .header::before {
+ content: url(Images/treeDownTriangleWhite.png);
+}
+
+.section .header .title {
+ color: white;
+ font-weight: bold;
+ word-wrap: break-word;
+ white-space: normal;
+}
+
+.section .header label {
+ display: none;
+}
+
+.section.expanded .header label {
+ display: inline;
+}
+
+.section .header input[type=checkbox] {
+ height: 10px;
+ width: 10px;
+ margin-left: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+ vertical-align: 2px;
+}
+
+.section .header .subtitle {
+ float: right;
+ font-size: 10px;
+ margin-left: 5px;
+ max-width: 55%;
+ color: rgba(255, 255, 255, 0.7);
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+.section .header .subtitle a {
+ color: inherit;
+}
+
+.section .properties {
+ display: none;
+ margin: 0;
+ padding: 2px 6px 3px;
+ list-style: none;
+ background-color: white;
+}
+
+.section.expanded .properties {
+ display: block;
+}
+
+.section .properties li {
+ margin-left: 12px;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ -webkit-user-select: text;
+ cursor: auto;
+}
+
+.section .properties li.parent {
+ margin-left: 1px;
+}
+
+.section .properties ol {
+ display: none;
+ margin: 0;
+ -webkit-padding-start: 12px;
+ list-style: none;
+}
+
+.section .properties ol.expanded {
+ display: block;
+}
+
+.section .properties li.parent::before {
+ content: url(Images/treeRightTriangleBlack.png);
+ opacity: 0.75;
+ float: left;
+ width: 8px;
+ height: 8px;
+ margin-top: 0;
+ padding-right: 3px;
+ -webkit-user-select: none;
+ cursor: default;
+}
+
+.section .properties li.parent.expanded::before {
+ content: url(Images/treeDownTriangleBlack.png);
+ margin-top: 1px;
+}
+
+.section .properties li .info {
+ padding-top: 4px;
+ padding-bottom: 3px;
+}
+
+.editing {
+ -webkit-user-select: text;
+ -webkit-box-shadow: rgba(0, 0, 0, .5) 3px 3px 4px;
+ outline: 1px solid rgb(66%, 66%, 66%) !important;
+ background-color: white;
+ -webkit-user-modify: read-write-plaintext-only;
+ text-overflow: clip;
+ padding-left: 2px;
+ margin-left: -2px;
+ padding-right: 2px;
+ margin-right: -2px;
+ margin-bottom: -1px;
+ padding-bottom: 1px;
+ opacity: 1.0 !important;
+}
+
+.editing, .editing * {
+ color: black !important;
+ text-decoration: none !important;
+}
+
+.section .properties li.editing {
+ margin-left: 10px;
+ text-overflow: clip;
+}
+
+li.editing .swatch, li.editing .enabled-button {
+ display: none !important;
+}
+
+.section .properties li.editing-sub-part {
+ padding: 3px 6px 8px 18px;
+ margin: -3px -6px -8px -6px;
+ text-overflow: clip;
+}
+
+.section .properties .overloaded, .section .properties .disabled {
+ text-decoration: line-through;
+}
+
+.section.computed-style .properties .disabled {
+ text-decoration: none;
+ opacity: 0.5;
+}
+
+.section .properties .implicit, .section .properties .inherited {
+ opacity: 0.5;
+}
+
+.section:not(.show-inherited) .properties .inherited {
+ display: none;
+}
+
+.section .properties .enabled-button {
+ display: none;
+ float: right;
+ font-size: 10px;
+ margin: 0 0 0 4px;
+ vertical-align: top;
+ position: relative;
+ z-index: 1;
+}
+
+.section:hover .properties .enabled-button {
+ display: block;
+}
+
+.section .properties .name {
+ color: rgb(136, 19, 145);
+}
+
+.section .properties .value.dimmed {
+ color: rgb(100, 100, 100);
+}
+
+.section .properties .number {
+ color: blue;
+}
+
+.section .properties .priority {
+ color: rgb(128, 0, 0);
+}
+
+.section .properties .keyword {
+ color: rgb(136, 19, 79);
+}
+
+.section .properties .color {
+ color: rgb(118, 15, 21);
+}
+
+.swatch {
+ display: inline-block;
+ vertical-align: baseline;
+ margin-left: 4px;
+ margin-bottom: -1px;
+ width: 1em;
+ height: 1em;
+ border: 1px solid rgb(180, 180, 180);
+}
+
+.pane:not(.expanded) + .pane, .pane:first-of-type {
+ margin-top: -1px;
+}
+
+.pane > .title {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(243, 243, 243)), color-stop(0.05, rgb(243, 243, 243)), color-stop(0.05, rgb(230, 230, 230)), to(rgb(209, 209, 209)));
+ height: 20px;
+ padding: 0 5px;
+ border-top: 1px solid rgb(189, 189, 189);
+ border-bottom: 1px solid rgb(189, 189, 189);
+ font-weight: bold;
+ font-size: 12px;
+ line-height: 18px;
+ color: rgb(110, 110, 110);
+ text-shadow: white 0 1px 0;
+ -webkit-background-origin: padding;
+ -webkit-background-clip: padding;
+}
+
+.pane > .title:active {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(231, 231, 231)), color-stop(0.05, rgb(231, 231, 231)), color-stop(0.05, rgb(207, 207, 207)), to(rgb(186, 186, 186)));
+ border-top: 1px solid rgb(178, 178, 178);
+ border-bottom: 1px solid rgb(178, 178, 178);
+}
+
+.pane > .title::before {
+ content: url(Images/disclosureTriangleSmallRightBlack.png);
+ float: left;
+ width: 11px;
+ height: 12px;
+ margin-right: 2px;
+ margin-top: 1px;
+}
+
+.pane.expanded > .title::before {
+ content: url(Images/disclosureTriangleSmallDownBlack.png);
+}
+
+.pane > .body {
+ position: relative;
+ display: none;
+ background-color: white;
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+.pane > .body .info {
+ text-align: center;
+ font-style: italic;
+ font-size: 10px;
+ padding: 6px;
+ color: gray;
+}
+
+.pane.expanded > .body, .pane.expanded > .growbar {
+ display: block;
+}
+
+.pane.expanded:nth-last-of-type(1) {
+ border-bottom: 1px solid rgb(189, 189, 189);
+}
+
+.pane > .growbar {
+ display: none;
+ background-image: url(Images/paneGrowHandleLine.png), url(Images/paneBottomGrow.png);
+ background-repeat: no-repeat, repeat-x;
+ background-position: center center, bottom;
+ height: 5px;
+}
+
+.metrics {
+ padding: 8px;
+ font-size: 10px;
+ text-align: center;
+ white-space: nowrap;
+}
+
+.metrics .label {
+ position: absolute;
+ margin-top: -10px;
+ font-size: 9px;
+ color: grey;
+ background-color: white;
+ margin-left: 3px;
+ padding-left: 2px;
+ padding-right: 2px;
+}
+
+.metrics .position {
+ border: 1px rgb(66%, 66%, 66%) dotted;
+ display: inline-block;
+ text-align: center;
+ padding: 3px;
+ margin: 3px;
+}
+
+.metrics .margin {
+ border: 1px dashed;
+ display: inline-block;
+ text-align: center;
+ vertical-align: middle;
+ padding: 3px;
+ margin: 3px;
+}
+
+.metrics .border {
+ border: 1px black solid;
+ display: inline-block;
+ text-align: center;
+ vertical-align: middle;
+ padding: 3px;
+ margin: 3px;
+}
+
+.metrics .padding {
+ border: 1px grey dashed;
+ display: inline-block;
+ text-align: center;
+ vertical-align: middle;
+ padding: 3px;
+ margin: 3px;
+}
+
+.metrics .content {
+ position: static;
+ border: 1px grey solid;
+ display: inline-block;
+ text-align: center;
+ vertical-align: middle;
+ padding: 3px;
+ margin: 3px;
+ min-width: 80px;
+ text-align: center;
+ overflow: visible;
+}
+
+.metrics .content span {
+ display: inline-block;
+}
+
+.metrics .editing {
+ position: relative;
+ z-index: 100;
+}
+
+.metrics .left {
+ display: inline-block;
+ vertical-align: middle;
+}
+
+.metrics .right {
+ display: inline-block;
+ vertical-align: middle;
+}
+
+.metrics .top {
+ display: inline-block;
+}
+
+.metrics .bottom {
+ display: inline-block;
+}
+
+.sidebar {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: 200px;
+ overflow-y: auto;
+ overflow-x: hidden;
+ background-color: rgb(214, 221, 229);
+ border-right: 1px solid rgb(64%, 64%, 64%);
+}
+
+body.inactive .sidebar {
+ background-color: rgb(232, 232, 232);
+}
+
+.database-sidebar-tree-item .icon {
+ content: url(Images/database.png);
+}
+
+.database-table-sidebar-tree-item .icon {
+ content: url(Images/databaseTable.png);
+}
+
+.domstorage-sidebar-tree-item .icon {
+ content: url(Images/domStorage.png);
+}
+
+#storage-views {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 200px;
+ bottom: 0;
+}
+
+.storage-view {
+ display: none;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+
+.storage-view.visible {
+ display: block;
+}
+
+.storage-view.table {
+ overflow: hidden;
+}
+
+.storage-view.table .data-grid {
+ border: none;
+ height: 100%;
+}
+
+.storage-view.table .storage-table-empty, .storage-view.table .storage-table-error {
+ position: absolute;
+ top: 0;
+ bottom: 25%;
+ left: 0;
+ right: 0;
+ font-size: 24px;
+ color: rgb(75%, 75%, 75%);
+ margin-top: auto;
+ margin-bottom: auto;
+ height: 50px;
+ line-height: 26px;
+ text-align: center;
+ font-weight: bold;
+ padding: 10px;
+ white-space: pre-wrap;
+}
+
+.storage-view.table .storage-table-error {
+ color: rgb(66%, 33%, 33%);
+}
+
+.data-grid {
+ position: relative;
+ border: 1px solid #aaa;
+}
+
+.data-grid .highlight {
+ background-color: rgb(255, 230, 179);
+}
+
+.data-grid tr.selected .highlight {
+ background-color: transparent;
+}
+
+.data-grid table {
+ table-layout: fixed;
+ border-spacing: 0;
+ border-collapse: collapse;
+ width: 100%;
+ font-size: 10px;
+ font-family: Lucida Grande, sans-serif;
+}
+
+.data-grid .data-container {
+ position: absolute;
+ top: 16px;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ padding-right: 14px;
+ overflow-x: hidden;
+ overflow-y: overlay;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(white), color-stop(0.5, white), color-stop(0.5, rgb(234, 243, 255)), to(rgb(234, 243, 255)));
+ -webkit-background-size: 1px 32px;
+}
+
+.data-grid.inline .data-container {
+ position: static;
+}
+
+.data-grid th {
+ text-align: left;
+ background-image: url(Images/glossyHeader.png);
+ background-repeat: repeat-x;
+ border-right: 1px solid rgb(179, 179, 179);
+ border-bottom: 1px solid rgb(179, 179, 179);
+ height: 15px;
+ font-weight: normal;
+ vertical-align: middle;
+ padding: 0 4px;
+ white-space: nowrap;
+}
+
+.data-grid th.corner {
+ width: 15px;
+ border-right: 0 none transparent;
+}
+
+.data-grid tr.filler {
+ display: table-row !important;
+ height: auto !important;
+}
+
+.data-grid tr.filler td {
+ height: auto !important;
+ padding: 0 !important;
+}
+
+.data-grid table.data {
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 16px;
+ bottom: 0;
+ height: 100%;
+ border-top: 0 none transparent;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(white), color-stop(0.5, white), color-stop(0.5, rgb(234, 243, 255)), to(rgb(234, 243, 255)));
+ -webkit-background-size: 1px 32px;
+}
+
+.data-grid.inline table.data {
+ position: static;
+}
+
+.data-grid table.data tr {
+ display: none;
+}
+
+.data-grid table.data tr.revealed {
+ display: table-row;
+}
+
+.data-grid td {
+ vertical-align: top;
+ height: 12px;
+ padding: 2px 4px;
+ white-space: nowrap;
+ border-right: 1px solid #aaa;
+ -webkit-user-select: text;
+}
+
+.data-grid td > div, .data-grid th > div {
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+.data-grid th.sortable div {
+ position: relative;
+}
+
+.data-grid th.sortable:active {
+ background-image: url(Images/glossyHeaderPressed.png);
+}
+
+.data-grid th.sort-ascending, .data-grid th.sort-descending {
+ border-right: 1px solid rgb(107, 140, 196);
+ border-bottom: 1px solid rgb(107, 140, 196);
+ background-image: url(Images/glossyHeaderSelected.png);
+ background-repeat: repeat-x;
+}
+
+.data-grid th.sortable.sort-ascending:active, .data-grid th.sortable.sort-descending:active {
+ background-image: url(Images/glossyHeaderSelectedPressed.png);
+}
+
+.data-grid th.sort-ascending div::after {
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 8px;
+ height: 8px;
+ content: url(Images/treeUpTriangleBlack.png);
+}
+
+.data-grid th.sort-descending div::after {
+ position: absolute;
+ top: 0;
+ right: 0;
+ margin-top: 1px;
+ width: 8px;
+ height: 8px;
+ content: url(Images/treeDownTriangleBlack.png);
+}
+
+body.inactive .data-grid th.sort-ascending, body.inactive .data-grid th.sort-descending {
+ background-image: url(Images/glossyHeader.png);
+ border-right: 1px solid rgb(179, 179, 179);
+ border-bottom: 1px solid rgb(179, 179, 179);
+}
+
+.data-grid tr.parent td.disclosure::before {
+ float: left;
+ content: url(Images/treeRightTriangleBlack.png);
+ width: 8px;
+ height: 8px;
+ margin-right: 2px;
+ -webkit-user-select: none;
+}
+
+.data-grid tr.expanded td.disclosure::before {
+ content: url(Images/treeDownTriangleBlack.png);
+ width: 8px;
+ height: 8px;
+ margin-top: 1px;
+}
+
+.data-grid tr.selected {
+ background-color: rgb(212, 212, 212);
+ color: inherit;
+}
+
+.data-grid:focus tr.selected {
+ background-color: rgb(56, 121, 217);
+ color: white;
+}
+
+.data-grid:focus tr.parent.selected td.disclosure::before {
+ content: url(Images/treeRightTriangleWhite.png);
+}
+
+.data-grid:focus tr.expanded.selected td.disclosure::before {
+ content: url(Images/treeDownTriangleWhite.png);
+}
+
+.data-grid tr:not(.parent) td.disclosure {
+ text-indent: 10px;
+}
+
+.storage-view.query {
+ font-size: 10px;
+ font-family: Monaco, Lucida Console, monospace;
+ padding: 2px 0;
+ overflow-y: overlay;
+ overflow-x: hidden;
+ -webkit-text-size-adjust: auto;
+}
+
+.database-query-prompt {
+ position: relative;
+ padding: 1px 22px 1px 24px;
+ min-height: 16px;
+ white-space: pre-wrap;
+ -webkit-user-modify: read-write-plaintext-only;
+ -webkit-user-select: text;
+}
+
+.database-user-query::before, .database-query-prompt::before, .database-query-result::before {
+ position: absolute;
+ display: block;
+ content: "";
+ left: 7px;
+ top: 0.8em;
+ width: 10px;
+ height: 10px;
+ margin-top: -5px;
+ -webkit-user-select: none;
+}
+
+.database-query-prompt::before {
+ background-image: url(Images/userInputIcon.png);
+}
+
+.database-user-query {
+ position: relative;
+ border-bottom: 1px solid rgb(245, 245, 245);
+ padding: 1px 22px 1px 24px;
+ min-height: 16px;
+}
+
+.database-user-query::before {
+ background-image: url(Images/userInputPreviousIcon.png);
+}
+
+.database-query-text {
+ color: rgb(0, 128, 255);
+ -webkit-user-select: text;
+}
+
+.database-query-result {
+ position: relative;
+ padding: 1px 22px 1px 24px;
+ min-height: 16px;
+ margin-left: -24px;
+ padding-right: 0;
+}
+
+.database-query-result.error {
+ color: red;
+ -webkit-user-select: text;
+}
+
+.database-query-result.error::before {
+ background-image: url(Images/errorIcon.png);
+}
+
+.panel-enabler-view {
+ z-index: 1000;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: white;
+ font-size: 13px;
+ text-align: center;
+ overflow-x: hidden;
+ overflow-y: overlay;
+ display: none;
+}
+
+.panel-enabler-view.visible {
+ display: block;
+}
+
+.panel-enabler-view .panel-enabler-view-content {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ max-height: 390px;
+ margin: auto;
+ white-space: nowrap;
+}
+
+.panel-enabler-view h1 {
+ color: rgb(110, 116, 128);
+ font-size: 16px;
+ line-height: 20px;
+ font-weight: normal;
+ margin-top: 0;
+}
+
+.panel-enabler-disclaimer {
+ font-size: 10px;
+ color: rgb(110, 116, 128);
+ margin-bottom: 12px;
+ margin-left: 20px;
+}
+
+.panel-enabler-disclaimer:empty {
+ display: none;
+}
+
+.panel-enabler-view img {
+ height: 100%;
+ min-height: 200px;
+ max-width: 100%;
+ top: 0;
+ bottom: 0;
+ padding: 20px 0 20px 20px;
+ margin: auto;
+ vertical-align: middle;
+}
+
+.panel-enabler-view img.hidden {
+ display: initial !important;
+ width: 0;
+}
+
+.panel-enabler-view form {
+ display: inline-block;
+ vertical-align: middle;
+ width: 330px;
+ margin: 0;
+ padding: 15px;
+ white-space: normal;
+}
+
+.panel-enabler-view label {
+ position: relative;
+ display: block;
+ text-align: left;
+ word-break: break-word;
+ margin: 0 0 5px 20px;
+}
+
+.panel-enabler-view button {
+ font-size: 13px;
+ margin: 6px 0 0 0;
+ padding: 3px 20px;
+ color: rgb(6, 6, 6);
+ height: 24px;
+ background-color: transparent;
+ border: 1px solid rgb(165, 165, 165);
+ background-color: rgb(237, 237, 237);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)));
+ -webkit-border-radius: 12px;
+ -webkit-appearance: none;
+}
+
+.panel-enabler-view button:active {
+ background-color: rgb(215, 215, 215);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(194, 194, 194)), to(rgb(239, 239, 239)));
+}
+
+body.inactive .panel-enabler-view button, .panel-enabler-view button:disabled {
+ color: rgb(130, 130, 130);
+ border-color: rgb(212, 212, 212);
+ background-color: rgb(239, 239, 239);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(250, 250, 250)), to(rgb(235, 235, 235)));
+}
+
+.panel-enabler-view input {
+ height: 17px;
+ width: 17px;
+ border: 1px solid rgb(165, 165, 165);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)));
+ -webkit-border-radius: 8px;
+ -webkit-appearance: none;
+ vertical-align: middle;
+ margin: 0 5px 5px 0;
+}
+
+.panel-enabler-view input:active {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(194, 194, 194)), to(rgb(239, 239, 239)));
+}
+
+.panel-enabler-view input:checked {
+ background: url(Images/radioDot.png) center no-repeat,
+ -webkit-gradient(linear, left top, left bottom, from(rgb(252, 252, 252)), to(rgb(223, 223, 223)));
+}
+
+.panel-enabler-view.resources img {
+ content: url(Images/scriptsSilhouette.png);
+}
+
+.panel-enabler-view.scripts img {
+ content: url(Images/scriptsSilhouette.png);
+}
+
+.panel-enabler-view.profiles img {
+ content: url(Images/profilesSilhouette.png);
+}
+
+button.enable-toggle-status-bar-item {
+ background-image: url(Images/enableButtons.png);
+}
+
+button.enable-toggle-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+button.enable-toggle-status-bar-item.toggled-on {
+ background-position: 0 24px;
+}
+
+button.enable-toggle-status-bar-item.toggled-on:active {
+ background-position: 32px 24px;
+}
+
+#scripts-pause-on-exceptions-status-bar-item {
+ background-image: url(Images/pauseOnExceptionButtons.png);
+}
+
+#scripts-pause-on-exceptions-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+#scripts-pause-on-exceptions-status-bar-item.toggled-on {
+ background-position: 0 24px;
+}
+
+#scripts-pause-on-exceptions-status-bar-item.toggled-on:active {
+ background-position: 32px 24px;
+}
+
+#scripts-status-bar {
+ position: absolute;
+ top: -1px;
+ left: 0;
+ right: 0;
+ height: 24px;
+}
+
+#scripts-files {
+ max-width: 250px;
+}
+
+#scripts-functions {
+ max-width: 150px;
+}
+
+#scripts-status-bar .status-bar-item img {
+ margin-top: 2px;
+}
+
+#scripts-back img {
+ content: url(Images/back.png);
+}
+
+#scripts-forward img {
+ content: url(Images/forward.png);
+}
+
+#scripts-pause img {
+ content: url(Images/debuggerPause.png);
+}
+
+#scripts-pause.paused img {
+ content: url(Images/debuggerContinue.png);
+}
+
+#scripts-step-over img {
+ content: url(Images/debuggerStepOver.png);
+}
+
+#scripts-step-into img {
+ content: url(Images/debuggerStepInto.png);
+}
+
+#scripts-step-out img {
+ content: url(Images/debuggerStepOut.png);
+}
+
+#scripts-debugger-status {
+ position: absolute;
+ line-height: 24px;
+ top: 0;
+ right: 8px;
+}
+
+#scripts-sidebar-resizer-widget {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ right: 225px;
+ width: 16px;
+ cursor: col-resize;
+ background-image: url(Images/statusbarResizerHorizontal.png);
+ background-repeat: no-repeat;
+ background-position: center;
+}
+
+#scripts-sidebar-buttons {
+ position: absolute;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ width: 225px;
+ overflow: hidden;
+ border-left: 1px solid rgb(64%, 64%, 64%);
+}
+
+#script-resource-views {
+ display: block;
+ overflow: auto;
+ padding: 0;
+ position: absolute;
+ top: 23px;
+ left: 0;
+ right: 225px;
+ bottom: 0;
+}
+
+.script-view {
+ display: none;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+
+.script-view.visible {
+ display: block;
+}
+
+#scripts-sidebar {
+ position: absolute;
+ top: 23px;
+ right: 0;
+ bottom: 0;
+ width: 225px;
+ background-color: rgb(245, 245, 245);
+ border-left: 1px solid rgb(64%, 64%, 64%);
+ cursor: default;
+ overflow: auto;
+}
+
+#resources-larger-resources-status-bar-item {
+ background-image: url(Images/largerResourcesButtons.png);
+}
+
+#resources-larger-resources-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+#resources-larger-resources-status-bar-item.toggled-on {
+ background-position: 0 24px;
+}
+
+#resources-larger-resources-status-bar-item.toggled-on:active {
+ background-position: 32px 24px;
+}
+
+#resources-container {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ border-right: 0 none transparent;
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+#resources-container.viewing-resource {
+ right: auto;
+ width: 200px;
+ border-right: 1px solid rgb(64%, 64%, 64%);
+}
+
+#resources-container.viewing-resource #resources-sidebar {
+ width: 100%;
+ border-right: 0 none transparent;
+}
+
+#resources-sidebar {
+ min-height: 100%;
+ bottom: auto;
+ overflow: visible;
+}
+
+#resources-container-content {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 200px;
+ min-height: 100%;
+}
+
+#resources-container.viewing-resource #resources-container-content {
+ display: none;
+}
+
+#resources-summary {
+ position: absolute;
+ padding-top: 20px;
+ top: 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)), to(rgba(0, 0, 0, 0.5)));
+ background-repeat: repeat-x;
+ background-position: bottom;
+ 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;
+}
+
+#resources-graph-legend {
+ margin-top: -10px;
+ padding-left: 15px;
+}
+
+.resources-graph-legend-item {
+ display: inline-block;
+ font-weight: bold;
+ margin-right: 15px;
+ vertical-align: top;
+}
+
+.resources-graph-legend-item.total {
+ margin-left: 10px;
+}
+
+.resources-graph-legend-label {
+ display: inline-block;
+ text-align: left;
+}
+
+.resources-graph-legend-header {
+ font-size: 12px;
+}
+
+.resources-graph-legend-value {
+ font-size: 10px;
+}
+
+.resources-graph-legend-swatch {
+ vertical-align: top;
+ margin-top: 1px;
+ margin-right: 3px;
+}
+
+#resources-dividers {
+ position: absolute;
+ left: 0;
+ right: 0;
+ height: 100%;
+ top: 0;
+ z-index: -100;
+}
+
+#resources-dividers-label-bar {
+ position: absolute;
+ top: 93px;
+ left: 0px;
+ right: 0;
+ background-color: rgba(255, 255, 255, 0.8);
+ background-clip: padding;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.3);
+ height: 20px;
+ z-index: 200;
+}
+
+.resources-divider {
+ position: absolute;
+ width: 1px;
+ top: 0;
+ bottom: 0;
+ background-color: rgba(0, 0, 0, 0.1);
+}
+
+.resources-divider.last {
+ background-color: transparent;
+}
+
+.resources-divider-label {
+ position: absolute;
+ top: 4px;
+ right: 3px;
+ font-size: 9px;
+ color: rgb(50%, 50%, 50%);
+ white-space: nowrap;
+}
+
+.resources-graph-label {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ margin: auto -7px;
+ height: 13px;
+ line-height: 13px;
+ font-size: 9px;
+ color: rgba(0, 0, 0, 0.75);
+ text-shadow: rgba(255, 255, 255, 0.25) 1px 0 0, rgba(255, 255, 255, 0.25) -1px 0 0, rgba(255, 255, 255, 0.333) 0 1px 0, rgba(255, 255, 255, 0.25) 0 -1px 0;
+ z-index: 150;
+ overflow: hidden;
+ text-align: center;
+ font-weight: bold;
+ opacity: 0;
+ -webkit-transition: opacity 250ms ease-in-out;
+}
+
+.resources-graph-side:hover .resources-graph-label {
+ opacity: 1;
+}
+
+.resources-graph-label:empty {
+ display: none;
+}
+
+.resources-graph-label.waiting {
+ margin-right: 5px;
+}
+
+.resources-graph-label.before {
+ color: rgba(0, 0, 0, 0.7);
+ text-shadow: none;
+ text-align: right;
+ margin-right: 2px;
+}
+
+.resources-graph-label.before::after {
+ padding-left: 2px;
+ height: 6px;
+ content: url(Images/graphLabelCalloutLeft.png);
+}
+
+.resources-graph-label.after {
+ color: rgba(0, 0, 0, 0.7);
+ text-shadow: none;
+ text-align: left;
+ margin-left: 2px;
+}
+
+.resources-graph-label.after::before {
+ padding-right: 2px;
+ height: 6px;
+ content: url(Images/graphLabelCalloutRight.png);
+}
+
+.resources-graph-bar {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ margin: auto -7px;
+ border-width: 6px 7px;
+ height: 13px;
+ min-width: 14px;
+ opacity: 0.65;
+ -webkit-border-image: url(Images/timelinePillGray.png) 6 7 6 7;
+}
+
+.resources-graph-bar.waiting {
+ opacity: 0.35;
+}
+
+.resource-cached .resources-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillGray.png) 6 7 6 7;
+}
+
+.resources-category-documents .resources-graph-bar {
+ -webkit-border-image: url(Images/timelinePillBlue.png) 6 7 6 7;
+}
+
+.resources-category-documents.resource-cached .resources-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillBlue.png) 6 7 6 7;
+}
+
+.resources-category-stylesheets .resources-graph-bar {
+ -webkit-border-image: url(Images/timelinePillGreen.png) 6 7 6 7;
+}
+
+.resources-category-stylesheets.resource-cached .resources-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillGreen.png) 6 7 6 7;
+}
+
+.resources-category-images .resources-graph-bar {
+ -webkit-border-image: url(Images/timelinePillPurple.png) 6 7 6 7;
+}
+
+.resources-category-images.resource-cached .resources-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillPurple.png) 6 7 6 7;
+}
+
+.resources-category-fonts .resources-graph-bar {
+ -webkit-border-image: url(Images/timelinePillRed.png) 6 7 6 7;
+}
+
+.resources-category-fonts.resource-cached .resources-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillRed.png) 6 7 6 7;
+}
+
+.resources-category-scripts .resources-graph-bar {
+ -webkit-border-image: url(Images/timelinePillOrange.png) 6 7 6 7;
+}
+
+.resources-category-scripts.resource-cached .resources-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillOrange.png) 6 7 6 7;
+}
+
+.resources-category-xhr .resources-graph-bar {
+ -webkit-border-image: url(Images/timelinePillYellow.png) 6 7 6 7;
+}
+
+.resources-category-xhr.resource-cached .resources-graph-bar {
+ -webkit-border-image: url(Images/timelineHollowPillYellow.png) 6 7 6 7;
+}
+
+.tip-button {
+ background-image: url(Images/tipIcon.png);
+ border: none;
+ width: 16px;
+ height: 16px;
+ float: right;
+ background-color: transparent;
+ margin-top: 1px;
+}
+
+.tip-button:active {
+ background-image: url(Images/tipIconPressed.png);
+}
+
+.tip-balloon {
+ position: absolute;
+ left: 145px;
+ top: -5px;
+ z-index: 1000;
+ border-width: 51px 15px 18px 37px;
+ -webkit-border-image: url(Images/tipBalloon.png) 51 15 18 37;
+ width: 265px;
+}
+
+.tip-balloon.bottom {
+ position: absolute;
+ left: 145px;
+ top: auto;
+ bottom: -7px;
+ z-index: 1000;
+ border-width: 18px 15px 51px 37px;
+ -webkit-border-image: url(Images/tipBalloonBottom.png) 18 15 51 37;
+}
+
+.tip-balloon-content {
+ margin-top: -40px;
+ margin-bottom: -2px;
+ margin-left: 2px;
+}
+
+.tip-balloon.bottom .tip-balloon-content {
+ margin-top: -10px;
+ margin-bottom: -35px;
+}
+
+#resource-views {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 200px;
+ bottom: 0;
+}
+
+.source-view-frame {
+ width: 100%;
+ height: 100%;
+}
+
+.sidebar-resizer-vertical {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ width: 5px;
+ z-index: 500;
+ cursor: col-resize;
+}
+
+.sidebar-tree, .sidebar-tree .children {
+ position: relative;
+ padding: 0;
+ margin: 0;
+ list-style: none;
+ font-size: 11px;
+}
+
+.sidebar-tree-section {
+ position: relative;
+ height: 18px;
+ padding: 4px 10px 6px 10px;
+ white-space: nowrap;
+ margin-top: 1px;
+ color: rgb(92, 110, 129);
+ font-weight: bold;
+ text-shadow: rgba(255, 255, 255, 0.75) 0 1px 0;
+}
+
+.sidebar-tree-item {
+ position: relative;
+ height: 36px;
+ padding: 0 5px 0 5px;
+ white-space: nowrap;
+ margin-top: 1px;
+ line-height: 34px;
+ border-top: 1px solid transparent;
+}
+
+.sidebar-tree .children {
+ display: none;
+}
+
+.sidebar-tree .children.expanded {
+ display: block;
+}
+
+.sidebar-tree-section + .children > .sidebar-tree-item {
+ padding-left: 10px !important;
+}
+
+.sidebar-tree-section + .children.small > .sidebar-tree-item {
+ padding-left: 17px !important;
+}
+
+.sidebar-tree > .children > .sidebar-tree-item {
+ padding-left: 37px;
+}
+
+.sidebar-tree > .children > .children > .sidebar-tree-item {
+ padding-left: 37px;
+}
+
+.sidebar-tree.hide-disclosure-buttons > .children {
+ display: none;
+}
+
+.sidebar-tree > .children.hide-disclosure-buttons > .children {
+ display: none;
+}
+
+.sidebar-tree.some-expandable:not(.hide-disclosure-buttons) > .sidebar-tree-item:not(.parent) .icon {
+ margin-left: 16px;
+}
+
+.sidebar-tree-item .disclosure-button {
+ float: left;
+ width: 16px;
+ height: 100%;
+ border: 0;
+ background-color: transparent;
+ background-image: url(Images/disclosureTriangleSmallRight.png);
+ background-repeat: no-repeat;
+ background-position: center;
+ -webkit-apearance: none;
+}
+
+.sidebar-tree.hide-disclosure-buttons .sidebar-tree-item .disclosure-button {
+ display: none;
+}
+
+body.inactive .sidebar-tree-item .disclosure-button {
+ background-image: url(Images/disclosureTriangleSmallRightBlack.png);
+}
+
+body.inactive .sidebar-tree-item.expanded .disclosure-button {
+ background-image: url(Images/disclosureTriangleSmallDownBlack.png);
+}
+
+body.inactive .sidebar-tree-item .disclosure-button:active {
+ background-image: url(Images/disclosureTriangleSmallRightDownBlack.png);
+}
+
+.sidebar-tree-item.selected .disclosure-button {
+ background-image: url(Images/disclosureTriangleSmallRightWhite.png) !important;
+}
+
+.sidebar-tree-item.expanded .disclosure-button {
+ background-image: url(Images/disclosureTriangleSmallDown.png);
+}
+
+.sidebar-tree-item.selected.expanded .disclosure-button {
+ background-image: url(Images/disclosureTriangleSmallDownWhite.png) !important;
+}
+
+.sidebar-tree-item.selected .disclosure-button:active {
+ background-image: url(Images/disclosureTriangleSmallRightDownWhite.png) !important;
+}
+
+.sidebar-tree-item .disclosure-button:active {
+ background-image: url(Images/disclosureTriangleSmallRightDown.png);
+}
+
+.sidebar-tree-item .icon {
+ float: left;
+ width: 32px;
+ height: 32px;
+ margin-top: 1px;
+ margin-right: 3px;
+}
+
+.sidebar-tree-item .status {
+ float: right;
+ height: 16px;
+ margin-top: 9px;
+ margin-left: 4px;
+ line-height: 1em;
+}
+
+.sidebar-tree-item .status:empty {
+ display: none;
+}
+
+.sidebar-tree-item .status .bubble {
+ display: inline-block;
+ height: 14px;
+ min-width: 16px;
+ margin-top: 1px;
+ background-color: rgb(128, 151, 189);
+ vertical-align: middle;
+ white-space: nowrap;
+ padding: 1px 4px;
+ text-align: center;
+ font-size: 11px;
+ font-family: Helvetia, Arial, sans-serif;
+ font-weight: bold;
+ text-shadow: none;
+ color: white;
+ -webkit-border-radius: 7px;
+}
+
+.sidebar-tree-item .status .bubble:empty {
+ display: none;
+}
+
+.sidebar-tree-item.selected .status .bubble {
+ background-color: white !important;
+ color: rgb(132, 154, 190) !important;
+}
+
+:focus .sidebar-tree-item.selected .status .bubble {
+ color: rgb(36, 98, 172) !important;
+}
+
+body.inactive .sidebar-tree-item.selected .status .bubble {
+ color: rgb(159, 159, 159) !important;
+}
+
+.sidebar-tree.small .sidebar-tree-item, .sidebar-tree .children.small .sidebar-tree-item, .sidebar-tree-item.small, .small .resources-graph-side {
+ height: 20px;
+}
+
+.sidebar-tree.small .sidebar-tree-item .icon, .sidebar-tree .children.small .sidebar-tree-item .icon, .sidebar-tree-item.small .icon {
+ width: 16px;
+ height: 16px;
+}
+
+.sidebar-tree.small .sidebar-tree-item .status, .sidebar-tree .children.small .sidebar-tree-item .status, .sidebar-tree-item.small .status {
+ margin-top: 1px;
+}
+
+.sidebar-tree-item.selected {
+ color: white;
+ border-top: 1px solid rgb(145, 160, 192);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(162, 177, 207)), to(rgb(120, 138, 177)));
+ text-shadow: rgba(0, 0, 0, 0.33) 0 1px 0;
+ font-weight: bold;
+ -webkit-background-origin: padding;
+ -webkit-background-clip: padding;
+}
+
+:focus .sidebar-tree-item.selected {
+ border-top: 1px solid rgb(68, 128, 200);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(92, 147, 213)), to(rgb(21, 83, 170)));
+}
+
+body.inactive .sidebar-tree-item.selected {
+ border-top: 1px solid rgb(151, 151, 151);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(180, 180, 180)), to(rgb(138, 138, 138)));
+}
+
+.sidebar-tree-item .titles {
+ position: relative;
+ top: 5px;
+ line-height: 11px;
+ padding-bottom: 1px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+}
+
+.sidebar-tree-item .titles.no-subtitle {
+ top: 10px;
+}
+
+.sidebar-tree.small .sidebar-tree-item .titles, .sidebar-tree .children.small .sidebar-tree-item .titles, .sidebar-tree-item.small .titles {
+ top: 2px;
+ line-height: normal;
+}
+
+.sidebar-tree:not(.small) .sidebar-tree-item:not(.small) .title::after, .sidebar-tree .children:not(.small) .sidebar-tree-item .title::after {
+ content: "\A";
+ white-space: pre;
+}
+
+.sidebar-tree-item .subtitle {
+ font-size: 9px;
+ color: rgba(0, 0, 0, 0.7);
+}
+
+.sidebar-tree.small .sidebar-tree-item .subtitle, .sidebar-tree .children.small .sidebar-tree-item .subtitle, .sidebar-tree-item.small .subtitle {
+ display: none;
+}
+
+.sidebar-tree-item.selected .subtitle {
+ color: rgba(255, 255, 255, 0.9);
+}
+
+#resources-graphs {
+ position: absolute;
+ left: 0;
+ right: 0;
+ max-height: 100%;
+ top: 112px;
+}
+
+.resources-graph-side {
+ position: relative;
+ height: 36px;
+ padding: 0 5px;
+ white-space: nowrap;
+ margin-top: 1px;
+ border-top: 1px solid transparent;
+ overflow: hidden;
+}
+
+.resources-graph-bar-area {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ right: 8px;
+ left: 9px;
+}
+
+#resources-container:not(.viewing-resource) .resource-sidebar-tree-item:nth-of-type(2n) {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+
+#resources-container:not(.viewing-resource) .resources-graph-side:nth-of-type(2n) {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+
+.resources-time-graph-sidebar-item .icon {
+ content: url(Images/resourcesTimeGraphIcon.png);
+}
+
+.resources-size-graph-sidebar-item .icon {
+ content: url(Images/resourcesSizeGraphIcon.png);
+}
+
+.resources-size-graph-sidebar-item .icon {
+ content: url(Images/resourcesSizeGraphIcon.png);
+}
+
+.resource-sidebar-tree-item .icon {
+ content: url(Images/resourcePlainIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item .icon {
+ content: url(Images/resourcePlainIconSmall.png);
+}
+
+.resource-sidebar-tree-item.resources-category-documents .icon {
+ content: url(Images/resourceDocumentIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-documents .icon {
+ content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.resource-sidebar-tree-item.resources-category-stylesheets .icon {
+ content: url(Images/resourceCSSIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-stylesheets .icon {
+ content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.resource-sidebar-tree-item.resources-category-images .icon {
+ position: relative;
+ background-image: url(Images/resourcePlainIcon.png);
+ background-repeat: no-repeat;
+ content: "";
+}
+
+.resource-sidebar-tree-item.resources-category-images .image-resource-icon-preview {
+ position: absolute;
+ margin: auto;
+ top: 3px;
+ bottom: 4px;
+ left: 5px;
+ right: 5px;
+ max-width: 18px;
+ max-height: 21px;
+ min-width: 1px;
+ min-height: 1px;
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-images .icon {
+ background-image: url(Images/resourcePlainIconSmall.png);
+ content: "";
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-images .image-resource-icon-preview {
+ top: 2px;
+ bottom: 1px;
+ left: 3px;
+ right: 3px;
+ max-width: 8px;
+ max-height: 11px;
+}
+
+.resource-sidebar-tree-item.resources-category-fonts .icon {
+ content: url(Images/resourcePlainIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-fonts .icon {
+ content: url(Images/resourcePlainIconSmall.png);
+}
+
+.resource-sidebar-tree-item.resources-category-scripts .icon {
+ content: url(Images/resourceJSIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-scripts .icon {
+ content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.resource-sidebar-tree-item.resources-category-xhr .icon {
+ content: url(Images/resourcePlainIcon.png);
+}
+
+.children.small .resource-sidebar-tree-item.resources-category-xhr .icon {
+ content: url(Images/resourceDocumentIconSmall.png);
+}
+
+.bubble.warning, .console-warning-level .bubble {
+ background-color: rgb(232, 164, 0) !important;
+}
+
+.bubble.error, .console-error-level .bubble {
+ background-color: rgb(216, 35, 35) !important;
+}
+
+.bubble.search-matches {
+ background-image: url(Images/searchSmallWhite.png);
+ background-repeat: no-repeat;
+ background-position: 3px 2px;
+ padding-left: 13px !important;
+}
+
+.sidebar-tree-item.selected .bubble.search-matches {
+ background-image: url(Images/searchSmallBlue.png);
+}
+
+:focus .sidebar-tree-item.selected .bubble.search-matches {
+ background-image: url(Images/searchSmallBrightBlue.png);
+}
+
+body.inactive .sidebar-tree-item.selected .bubble.search-matches {
+ background-image: url(Images/searchSmallGray.png);
+}
+
+/* Profiler Style */
+
+#profile-views {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 200px;
+ bottom: 0;
+}
+
+#profile-view-status-bar-items {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 200px;
+ overflow: hidden;
+ border-left: 1px solid rgb(184, 184, 184);
+ margin-left: -1px;
+}
+
+.profile-sidebar-tree-item .icon {
+ content: url(Images/profileIcon.png);
+}
+
+.profile-sidebar-tree-item.small .icon {
+ content: url(Images/profileSmallIcon.png);
+}
+
+.profile-group-sidebar-tree-item .icon {
+ content: url(Images/profileGroupIcon.png);
+}
+
+.profile-view {
+ display: none;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+
+.profile-view.visible {
+ display: block;
+}
+
+.profile-view .data-grid {
+ border: none;
+ height: 100%;
+}
+
+.profile-view .data-grid th.average-column {
+ text-align: center;
+}
+
+.profile-view .data-grid td.average-column {
+ text-align: right;
+}
+
+.profile-view .data-grid th.self-column {
+ text-align: center;
+}
+
+.profile-view .data-grid td.self-column {
+ text-align: right;
+}
+
+.profile-view .data-grid th.total-column {
+ text-align: center;
+}
+
+.profile-view .data-grid td.total-column {
+ text-align: right;
+}
+
+.profile-view .data-grid .calls-column {
+ text-align: center;
+}
+
+.profile-node-file {
+ float: right;
+ color: gray;
+ margin-top: -1px;
+}
+
+.data-grid tr.selected .profile-node-file {
+ color: rgb(33%, 33%, 33%);
+}
+
+.data-grid:focus tr.selected .profile-node-file {
+ color: white;
+}
+
+#record-profile-status-bar-item {
+ background-image: url(Images/recordButtons.png);
+}
+
+#record-profile-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+#record-profile-status-bar-item.toggled-on {
+ background-position: 0 24px;
+}
+
+#record-profile-status-bar-item.toggled-on:active {
+ background-position: 32px 24px;
+}
+
+#node-search-status-bar-item {
+ background-image: url(Images/nodeSearchButtons.png);
+}
+
+#node-search-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+#node-search-status-bar-item.toggled-on {
+ background-position: 0 24px;
+}
+
+#node-search-status-bar-item.toggled-on:active {
+ background-position: 32px 24px;
+}
+
+.percent-time-status-bar-item {
+ background-image: url(Images/percentButtons.png) !important;
+}
+
+.percent-time-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+.percent-time-status-bar-item.toggled-on {
+ background-position: 0 24px;
+}
+
+.percent-time-status-bar-item.toggled-on:active {
+ background-position: 32px 24px;
+}
+
+.focus-profile-node-status-bar-item {
+ background-image: url(Images/focusButtons.png) !important;
+}
+
+.focus-profile-node-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+.exclude-profile-node-status-bar-item {
+ background-image: url(Images/excludeButtons.png) !important;
+}
+
+.exclude-profile-node-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+.reset-profile-status-bar-item {
+ background-image: url(Images/reloadButtons.png) !important;
+}
+
+.reset-profile-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+.delete-storage-status-bar-item {
+ background-image: url(Images/excludeButtons.png) !important;
+}
+
+.delete-storage-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+#storage-view-status-bar-items {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 200px;
+ overflow: hidden;
+ border-left: 1px solid rgb(184, 184, 184);
+ margin-left: -1px;
+}
+
+.refresh-storage-status-bar-item {
+ background-image: url(Images/reloadButtons.png) !important;
+}
+
+.refresh-storage-status-bar-item:active {
+ background-position: 32px 0;
+}
+
+#storage-view-status-bar-items {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 200px;
+ overflow: hidden;
+ border-left: 1px solid rgb(184, 184, 184);
+ margin-left: -1px;
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector.html b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector.html
new file mode 100644
index 0000000..184bb45
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector.html
@@ -0,0 +1,97 @@
+<!--
+Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <link rel="stylesheet" type="text/css" href="inspector.css">
+ <script type="text/javascript" src="utilities.js"></script>
+ <script type="text/javascript" src="treeoutline.js"></script>
+ <script type="text/javascript" src="inspector.js"></script>
+ <script type="text/javascript" src="Object.js"></script>
+ <script type="text/javascript" src="TextPrompt.js"></script>
+ <script type="text/javascript" src="Placard.js"></script>
+ <script type="text/javascript" src="View.js"></script>
+ <script type="text/javascript" src="Console.js"></script>
+ <script type="text/javascript" src="Resource.js"></script>
+ <script type="text/javascript" src="ResourceCategory.js"></script>
+ <script type="text/javascript" src="Database.js"></script>
+ <script type="text/javascript" src="DOMStorage.js"></script>
+ <script type="text/javascript" src="DOMStorageItemsView.js"></script>
+ <script type="text/javascript" src="DataGrid.js"></script>
+ <script type="text/javascript" src="DOMStorageDataGrid.js"></script>
+ <script type="text/javascript" src="Script.js"></script>
+ <script type="text/javascript" src="Breakpoint.js"></script>
+ <script type="text/javascript" src="SidebarPane.js"></script>
+ <script type="text/javascript" src="ElementsTreeOutline.js"></script>
+ <script type="text/javascript" src="SidebarTreeElement.js"></script>
+ <script type="text/javascript" src="PropertiesSection.js"></script>
+ <script type="text/javascript" src="ObjectPropertiesSection.js"></script>
+ <script type="text/javascript" src="BreakpointsSidebarPane.js"></script>
+ <script type="text/javascript" src="CallStackSidebarPane.js"></script>
+ <script type="text/javascript" src="ScopeChainSidebarPane.js"></script>
+ <script type="text/javascript" src="MetricsSidebarPane.js"></script>
+ <script type="text/javascript" src="PropertiesSidebarPane.js"></script>
+ <script type="text/javascript" src="StylesSidebarPane.js"></script>
+ <script type="text/javascript" src="Panel.js"></script>
+ <script type="text/javascript" src="PanelEnablerView.js"></script>
+ <script type="text/javascript" src="ElementsPanel.js"></script>
+ <script type="text/javascript" src="ResourcesPanel.js"></script>
+ <script type="text/javascript" src="ScriptsPanel.js"></script>
+ <script type="text/javascript" src="DatabasesPanel.js"></script>
+ <script type="text/javascript" src="ProfilesPanel.js"></script>
+ <script type="text/javascript" src="ResourceView.js"></script>
+ <script type="text/javascript" src="SourceFrame.js"></script>
+ <script type="text/javascript" src="SourceView.js"></script>
+ <script type="text/javascript" src="FontView.js"></script>
+ <script type="text/javascript" src="ImageView.js"></script>
+ <script type="text/javascript" src="DatabaseTableView.js"></script>
+ <script type="text/javascript" src="DatabaseQueryView.js"></script>
+ <script type="text/javascript" src="ScriptView.js"></script>
+ <script type="text/javascript" src="ProfileDataGridTree.js"></script>
+ <script type="text/javascript" src="BottomUpProfileDataGridTree.js"></script>
+ <script type="text/javascript" src="TopDownProfileDataGridTree.js"></script>
+ <script type="text/javascript" src="ProfileView.js"></script>
+</head>
+<body class="detached">
+ <div id="toolbar">
+ <div class="toolbar-item close"><button id="close-button"></button></div>
+ <div class="toolbar-item flexable-space"></div>
+ <div class="toolbar-item hidden" id="search-results-matches"></div>
+ <div class="toolbar-item"><input id="search" type="search" incremental results="0"><div id="search-toolbar-label" class="toolbar-label"></div></div>
+ </div>
+ <div id="main">
+ <div id="main-panels" tabindex="0"></div>
+ <div id="main-status-bar" class="status-bar"><div id="anchored-status-bar-items"><button id="dock-status-bar-item" class="status-bar-item toggled"></button><button id="console-status-bar-item" class="status-bar-item"></button><div id="error-warning-count" class="hidden"></div></div></div>
+ </div>
+ <div id="console">
+ <div id="console-messages"><div id="console-prompt"><br></div></div>
+ <div id="console-status-bar" class="status-bar"><div id="other-console-status-bar-items"><button id="clear-console-status-bar-item" class="status-bar-item"></button></div></div>
+ </div>
+</body>
+</html>
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector.js
new file mode 100644
index 0000000..9d5bac0
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector.js
@@ -0,0 +1,1381 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+var Preferences = {
+ ignoreWhitespace: true,
+ showUserAgentStyles: true,
+ maxInlineTextChildLength: 80,
+ minConsoleHeight: 75,
+ minSidebarWidth: 100,
+ minElementsSidebarWidth: 200,
+ minScriptsSidebarWidth: 200,
+ showInheritedComputedStyleProperties: false,
+ styleRulesExpandedState: {},
+ showMissingLocalizedStrings: false
+}
+
+var WebInspector = {
+ resources: {},
+ resourceURLMap: {},
+ missingLocalizedStrings: {},
+
+ get previousFocusElement()
+ {
+ return this._previousFocusElement;
+ },
+
+ get currentFocusElement()
+ {
+ return this._currentFocusElement;
+ },
+
+ set currentFocusElement(x)
+ {
+ if (this._currentFocusElement !== x)
+ this._previousFocusElement = this._currentFocusElement;
+ this._currentFocusElement = x;
+
+ if (this._currentFocusElement) {
+ this._currentFocusElement.focus();
+
+ // Make a caret selection inside the new element if there isn't a range selection and
+ // there isn't already a caret selection inside.
+ var selection = window.getSelection();
+ if (selection.isCollapsed && !this._currentFocusElement.isInsertionCaretInside()) {
+ var selectionRange = document.createRange();
+ selectionRange.setStart(this._currentFocusElement, 0);
+ selectionRange.setEnd(this._currentFocusElement, 0);
+
+ selection.removeAllRanges();
+ selection.addRange(selectionRange);
+ }
+ } else if (this._previousFocusElement)
+ this._previousFocusElement.blur();
+ },
+
+ get currentPanel()
+ {
+ return this._currentPanel;
+ },
+
+ set currentPanel(x)
+ {
+ if (this._currentPanel === x)
+ return;
+
+ if (this._currentPanel)
+ this._currentPanel.hide();
+
+ this._currentPanel = x;
+
+ this.updateSearchLabel();
+
+ if (x) {
+ x.show();
+
+ if (this.currentQuery) {
+ if (x.performSearch) {
+ function performPanelSearch()
+ {
+ this.updateSearchMatchesCount();
+
+ x.currentQuery = this.currentQuery;
+ x.performSearch(this.currentQuery);
+ }
+
+ // Perform the search on a timeout so the panel switches fast.
+ setTimeout(performPanelSearch.bind(this), 0);
+ } else {
+ // Update to show Not found for panels that can't be searched.
+ this.updateSearchMatchesCount();
+ }
+ }
+ }
+ },
+
+ get attached()
+ {
+ return this._attached;
+ },
+
+ set attached(x)
+ {
+ if (this._attached === x)
+ return;
+
+ this._attached = x;
+
+ this.updateSearchLabel();
+
+ var dockToggleButton = document.getElementById("dock-status-bar-item");
+ var body = document.body;
+
+ if (x) {
+ InspectorController.attach();
+ body.removeStyleClass("detached");
+ body.addStyleClass("attached");
+ dockToggleButton.title = WebInspector.UIString("Undock into separate window.");
+ } else {
+ InspectorController.detach();
+ body.removeStyleClass("attached");
+ body.addStyleClass("detached");
+ dockToggleButton.title = WebInspector.UIString("Dock to main window.");
+ }
+ },
+
+ get errors()
+ {
+ return this._errors || 0;
+ },
+
+ set errors(x)
+ {
+ x = Math.max(x, 0);
+
+ if (this._errors === x)
+ return;
+ this._errors = x;
+ this._updateErrorAndWarningCounts();
+ },
+
+ get warnings()
+ {
+ return this._warnings || 0;
+ },
+
+ set warnings(x)
+ {
+ x = Math.max(x, 0);
+
+ if (this._warnings === x)
+ return;
+ this._warnings = x;
+ this._updateErrorAndWarningCounts();
+ },
+
+ _updateErrorAndWarningCounts: function()
+ {
+ var errorWarningElement = document.getElementById("error-warning-count");
+ if (!errorWarningElement)
+ return;
+
+ if (!this.errors && !this.warnings) {
+ errorWarningElement.addStyleClass("hidden");
+ return;
+ }
+
+ errorWarningElement.removeStyleClass("hidden");
+
+ errorWarningElement.removeChildren();
+
+ if (this.errors) {
+ var errorElement = document.createElement("span");
+ errorElement.id = "error-count";
+ errorElement.textContent = this.errors;
+ errorWarningElement.appendChild(errorElement);
+ }
+
+ if (this.warnings) {
+ var warningsElement = document.createElement("span");
+ warningsElement.id = "warning-count";
+ warningsElement.textContent = this.warnings;
+ errorWarningElement.appendChild(warningsElement);
+ }
+
+ if (this.errors) {
+ if (this.warnings) {
+ if (this.errors == 1) {
+ if (this.warnings == 1)
+ errorWarningElement.title = WebInspector.UIString("%d error, %d warning", this.errors, this.warnings);
+ else
+ errorWarningElement.title = WebInspector.UIString("%d error, %d warnings", this.errors, this.warnings);
+ } else if (this.warnings == 1)
+ errorWarningElement.title = WebInspector.UIString("%d errors, %d warning", this.errors, this.warnings);
+ else
+ errorWarningElement.title = WebInspector.UIString("%d errors, %d warnings", this.errors, this.warnings);
+ } else if (this.errors == 1)
+ errorWarningElement.title = WebInspector.UIString("%d error", this.errors);
+ else
+ errorWarningElement.title = WebInspector.UIString("%d errors", this.errors);
+ } else if (this.warnings == 1)
+ errorWarningElement.title = WebInspector.UIString("%d warning", this.warnings);
+ else if (this.warnings)
+ errorWarningElement.title = WebInspector.UIString("%d warnings", this.warnings);
+ else
+ errorWarningElement.title = null;
+ },
+
+ get hoveredDOMNode()
+ {
+ return this._hoveredDOMNode;
+ },
+
+ set hoveredDOMNode(x)
+ {
+ if (objectsAreSame(this._hoveredDOMNode, x))
+ return;
+
+ this._hoveredDOMNode = x;
+
+ if (this._hoveredDOMNode)
+ this._updateHoverHighlightSoon(this.showingDOMNodeHighlight ? 50 : 500);
+ else
+ this._updateHoverHighlight();
+ },
+
+ _updateHoverHighlightSoon: function(delay)
+ {
+ if ("_updateHoverHighlightTimeout" in this)
+ clearTimeout(this._updateHoverHighlightTimeout);
+ this._updateHoverHighlightTimeout = setTimeout(this._updateHoverHighlight.bind(this), delay);
+ },
+
+ _updateHoverHighlight: function()
+ {
+ if ("_updateHoverHighlightTimeout" in this) {
+ clearTimeout(this._updateHoverHighlightTimeout);
+ delete this._updateHoverHighlightTimeout;
+ }
+
+ if (this._hoveredDOMNode) {
+ InspectorController.highlightDOMNode(this._hoveredDOMNode);
+ this.showingDOMNodeHighlight = true;
+ } else {
+ InspectorController.hideDOMNodeHighlight();
+ this.showingDOMNodeHighlight = false;
+ }
+ }
+}
+
+WebInspector.loaded = function()
+{
+ var platform = InspectorController.platform();
+ document.body.addStyleClass("platform-" + platform);
+
+ this.console = new WebInspector.Console();
+
+ this.panels = {};
+ var hiddenPanels = (InspectorController.hiddenPanels() || "").split(',');
+ if (hiddenPanels.indexOf("elements") === -1)
+ this.panels.elements = new WebInspector.ElementsPanel();
+ if (hiddenPanels.indexOf("resources") === -1)
+ this.panels.resources = new WebInspector.ResourcesPanel();
+ if (hiddenPanels.indexOf("scripts") === -1)
+ this.panels.scripts = new WebInspector.ScriptsPanel();
+ if (hiddenPanels.indexOf("profiles") === -1)
+ this.panels.profiles = new WebInspector.ProfilesPanel();
+ if (hiddenPanels.indexOf("databases") === -1)
+ this.panels.databases = new WebInspector.DatabasesPanel();
+
+ var toolbarElement = document.getElementById("toolbar");
+ var previousToolbarItem = toolbarElement.children[0];
+
+ for (var panelName in this.panels) {
+ var panel = this.panels[panelName];
+ var panelToolbarItem = panel.toolbarItem;
+ panelToolbarItem.addEventListener("click", this._toolbarItemClicked.bind(this));
+ if (previousToolbarItem)
+ toolbarElement.insertBefore(panelToolbarItem, previousToolbarItem.nextSibling);
+ else
+ toolbarElement.insertBefore(panelToolbarItem, toolbarElement.firstChild);
+ previousToolbarItem = panelToolbarItem;
+ }
+
+ this.currentPanel = this.panels.elements;
+
+ this.resourceCategories = {
+ documents: new WebInspector.ResourceCategory(WebInspector.UIString("Documents"), "documents"),
+ stylesheets: new WebInspector.ResourceCategory(WebInspector.UIString("Stylesheets"), "stylesheets"),
+ images: new WebInspector.ResourceCategory(WebInspector.UIString("Images"), "images"),
+ scripts: new WebInspector.ResourceCategory(WebInspector.UIString("Scripts"), "scripts"),
+ xhr: new WebInspector.ResourceCategory(WebInspector.UIString("XHR"), "xhr"),
+ fonts: new WebInspector.ResourceCategory(WebInspector.UIString("Fonts"), "fonts"),
+ other: new WebInspector.ResourceCategory(WebInspector.UIString("Other"), "other")
+ };
+
+ this.Tips = {
+ ResourceNotCompressed: {id: 0, message: WebInspector.UIString("You could save bandwidth by having your web server compress this transfer with gzip or zlib.")}
+ };
+
+ this.Warnings = {
+ IncorrectMIMEType: {id: 0, message: WebInspector.UIString("Resource interpreted as %s but transferred with MIME type %s.")}
+ };
+
+ this.addMainEventListeners(document);
+
+ window.addEventListener("unload", this.windowUnload.bind(this), true);
+ window.addEventListener("resize", this.windowResize.bind(this), true);
+
+ document.addEventListener("focus", this.focusChanged.bind(this), true);
+ document.addEventListener("keydown", this.documentKeyDown.bind(this), true);
+ document.addEventListener("keyup", this.documentKeyUp.bind(this), true);
+ document.addEventListener("beforecopy", this.documentCanCopy.bind(this), true);
+ document.addEventListener("copy", this.documentCopy.bind(this), true);
+
+ var mainPanelsElement = document.getElementById("main-panels");
+ mainPanelsElement.handleKeyEvent = this.mainKeyDown.bind(this);
+ mainPanelsElement.handleKeyUpEvent = this.mainKeyUp.bind(this);
+ mainPanelsElement.handleCopyEvent = this.mainCopy.bind(this);
+
+ // Focus the mainPanelsElement in a timeout so it happens after the initial focus,
+ // so it doesn't get reset to the first toolbar button. This initial focus happens
+ // on Mac when the window is made key and the WebHTMLView becomes the first responder.
+ setTimeout(function() { WebInspector.currentFocusElement = mainPanelsElement }, 0);
+
+ var dockToggleButton = document.getElementById("dock-status-bar-item");
+ dockToggleButton.addEventListener("click", this.toggleAttach.bind(this), false);
+
+ if (this.attached)
+ dockToggleButton.title = WebInspector.UIString("Undock into separate window.");
+ else
+ dockToggleButton.title = WebInspector.UIString("Dock to main window.");
+
+ var errorWarningCount = document.getElementById("error-warning-count");
+ errorWarningCount.addEventListener("click", this.console.show.bind(this.console), false);
+ this._updateErrorAndWarningCounts();
+
+ var searchField = document.getElementById("search");
+ searchField.addEventListener("keydown", this.searchKeyDown.bind(this), false);
+ searchField.addEventListener("keyup", this.searchKeyUp.bind(this), false);
+ searchField.addEventListener("search", this.performSearch.bind(this), false); // when the search is emptied
+
+ document.getElementById("toolbar").addEventListener("mousedown", this.toolbarDragStart, true);
+ document.getElementById("close-button").addEventListener("click", this.close, true);
+
+ InspectorController.loaded();
+}
+
+var windowLoaded = function()
+{
+ var localizedStringsURL = InspectorController.localizedStringsURL();
+ if (localizedStringsURL) {
+ var localizedStringsScriptElement = document.createElement("script");
+ localizedStringsScriptElement.addEventListener("load", WebInspector.loaded.bind(WebInspector), false);
+ localizedStringsScriptElement.type = "text/javascript";
+ localizedStringsScriptElement.src = localizedStringsURL;
+ document.getElementsByTagName("head").item(0).appendChild(localizedStringsScriptElement);
+ } else
+ WebInspector.loaded();
+
+ window.removeEventListener("load", windowLoaded, false);
+ delete windowLoaded;
+};
+
+window.addEventListener("load", windowLoaded, false);
+
+WebInspector.dispatch = function() {
+ var methodName = arguments[0];
+ var parameters = Array.prototype.slice.call(arguments, 1);
+ WebInspector[methodName].apply(this, parameters);
+}
+
+WebInspector.windowUnload = function(event)
+{
+ InspectorController.windowUnloading();
+}
+
+WebInspector.windowResize = function(event)
+{
+ if (this.currentPanel && this.currentPanel.resize)
+ this.currentPanel.resize();
+}
+
+WebInspector.windowFocused = function(event)
+{
+ if (event.target.nodeType === Node.DOCUMENT_NODE)
+ document.body.removeStyleClass("inactive");
+}
+
+WebInspector.windowBlured = function(event)
+{
+ if (event.target.nodeType === Node.DOCUMENT_NODE)
+ document.body.addStyleClass("inactive");
+}
+
+WebInspector.focusChanged = function(event)
+{
+ this.currentFocusElement = event.target;
+}
+
+WebInspector.setAttachedWindow = function(attached)
+{
+ this.attached = attached;
+}
+
+WebInspector.close = function(event)
+{
+ InspectorController.closeWindow();
+}
+
+WebInspector.documentClick = function(event)
+{
+ var anchor = event.target.enclosingNodeOrSelfWithNodeName("a");
+ if (!anchor)
+ return;
+
+ // Prevent the link from navigating, since we don't do any navigation by following links normally.
+ event.preventDefault();
+
+ function followLink()
+ {
+ // FIXME: support webkit-html-external-link links here.
+ if (anchor.href in WebInspector.resourceURLMap) {
+ if (anchor.hasStyleClass("webkit-html-external-link")) {
+ anchor.removeStyleClass("webkit-html-external-link");
+ anchor.addStyleClass("webkit-html-resource-link");
+ }
+
+ WebInspector.showResourceForURL(anchor.href, anchor.lineNumber, anchor.preferredPanel);
+ } else {
+ var profileStringRegEx = new RegExp("webkit-profile://.+/([0-9]+)");
+ var profileString = profileStringRegEx.exec(anchor.href);
+ if (profileString)
+ WebInspector.showProfileById(profileString[1])
+ }
+ }
+
+ if (WebInspector.followLinkTimeout)
+ clearTimeout(WebInspector.followLinkTimeout);
+
+ if (anchor.preventFollowOnDoubleClick) {
+ // Start a timeout if this is the first click, if the timeout is canceled
+ // before it fires, then a double clicked happened or another link was clicked.
+ if (event.detail === 1)
+ WebInspector.followLinkTimeout = setTimeout(followLink, 333);
+ return;
+ }
+
+ followLink();
+}
+
+WebInspector.documentKeyDown = function(event)
+{
+ if (!this.currentFocusElement)
+ return;
+ if (this.currentFocusElement.handleKeyEvent)
+ this.currentFocusElement.handleKeyEvent(event);
+ else if (this.currentFocusElement.id && this.currentFocusElement.id.length && WebInspector[this.currentFocusElement.id + "KeyDown"])
+ WebInspector[this.currentFocusElement.id + "KeyDown"](event);
+
+ if (!event.handled) {
+ var isMac = InspectorController.platform().indexOf("mac-") === 0;
+
+ switch (event.keyIdentifier) {
+ case "U+001B": // Escape key
+ this.console.visible = !this.console.visible;
+ event.preventDefault();
+ break;
+
+ case "U+0046": // F key
+ if (isMac)
+ var isFindKey = event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey;
+ else
+ var isFindKey = event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey;
+
+ if (isFindKey) {
+ var searchField = document.getElementById("search");
+ searchField.focus();
+ searchField.select();
+ event.preventDefault();
+ }
+
+ break;
+
+ case "U+0047": // G key
+ if (isMac)
+ var isFindAgainKey = event.metaKey && !event.ctrlKey && !event.altKey;
+ else
+ var isFindAgainKey = event.ctrlKey && !event.metaKey && !event.altKey;
+
+ if (isFindAgainKey) {
+ if (event.shiftKey) {
+ if (this.currentPanel.jumpToPreviousSearchResult)
+ this.currentPanel.jumpToPreviousSearchResult();
+ } else if (this.currentPanel.jumpToNextSearchResult)
+ this.currentPanel.jumpToNextSearchResult();
+ event.preventDefault();
+ }
+
+ break;
+ }
+ }
+}
+
+WebInspector.documentKeyUp = function(event)
+{
+ if (!this.currentFocusElement || !this.currentFocusElement.handleKeyUpEvent)
+ return;
+ this.currentFocusElement.handleKeyUpEvent(event);
+}
+
+WebInspector.documentCanCopy = function(event)
+{
+ if (!this.currentFocusElement)
+ return;
+ // Calling preventDefault() will say "we support copying, so enable the Copy menu".
+ if (this.currentFocusElement.handleCopyEvent)
+ event.preventDefault();
+ else if (this.currentFocusElement.id && this.currentFocusElement.id.length && WebInspector[this.currentFocusElement.id + "Copy"])
+ event.preventDefault();
+}
+
+WebInspector.documentCopy = function(event)
+{
+ if (!this.currentFocusElement)
+ return;
+ if (this.currentFocusElement.handleCopyEvent)
+ this.currentFocusElement.handleCopyEvent(event);
+ else if (this.currentFocusElement.id && this.currentFocusElement.id.length && WebInspector[this.currentFocusElement.id + "Copy"])
+ WebInspector[this.currentFocusElement.id + "Copy"](event);
+}
+
+WebInspector.mainKeyDown = function(event)
+{
+ if (this.currentPanel && this.currentPanel.handleKeyEvent)
+ this.currentPanel.handleKeyEvent(event);
+}
+
+WebInspector.mainKeyUp = function(event)
+{
+ if (this.currentPanel && this.currentPanel.handleKeyUpEvent)
+ this.currentPanel.handleKeyUpEvent(event);
+}
+
+WebInspector.mainCopy = function(event)
+{
+ if (this.currentPanel && this.currentPanel.handleCopyEvent)
+ this.currentPanel.handleCopyEvent(event);
+}
+
+WebInspector.animateStyle = function(animations, duration, callback, complete)
+{
+ if (complete === undefined)
+ complete = 0;
+ var slice = (1000 / 30); // 30 frames per second
+
+ var defaultUnit = "px";
+ var propertyUnit = {opacity: ""};
+
+ for (var i = 0; i < animations.length; ++i) {
+ var animation = animations[i];
+ var element = null;
+ var start = null;
+ var current = null;
+ var end = null;
+ for (key in animation) {
+ if (key === "element")
+ element = animation[key];
+ else if (key === "start")
+ start = animation[key];
+ else if (key === "current")
+ current = animation[key];
+ else if (key === "end")
+ end = animation[key];
+ }
+
+ if (!element || !end)
+ continue;
+
+ var computedStyle = element.ownerDocument.defaultView.getComputedStyle(element);
+ if (!start) {
+ start = {};
+ for (key in end)
+ start[key] = parseInt(computedStyle.getPropertyValue(key));
+ animation.start = start;
+ } else if (complete == 0)
+ for (key in start)
+ element.style.setProperty(key, start[key] + (key in propertyUnit ? propertyUnit[key] : defaultUnit));
+
+ if (!current) {
+ current = {};
+ for (key in start)
+ current[key] = start[key];
+ animation.current = current;
+ }
+
+ function cubicInOut(t, b, c, d)
+ {
+ if ((t/=d/2) < 1) return c/2*t*t*t + b;
+ return c/2*((t-=2)*t*t + 2) + b;
+ }
+
+ var style = element.style;
+ for (key in end) {
+ var startValue = start[key];
+ var currentValue = current[key];
+ var endValue = end[key];
+ if ((complete + slice) < duration) {
+ var delta = (endValue - startValue) / (duration / slice);
+ var newValue = cubicInOut(complete, startValue, endValue - startValue, duration);
+ style.setProperty(key, newValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit));
+ current[key] = newValue;
+ } else {
+ style.setProperty(key, endValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit));
+ }
+ }
+ }
+
+ if (complete < duration)
+ setTimeout(WebInspector.animateStyle, slice, animations, duration, callback, complete + slice);
+ else if (callback)
+ callback();
+}
+
+WebInspector.updateSearchLabel = function()
+{
+ if (!this.currentPanel)
+ return;
+
+ var newLabel = WebInspector.UIString("Search %s", this.currentPanel.toolbarItemLabel);
+ if (this.attached)
+ document.getElementById("search").setAttribute("placeholder", newLabel);
+ else {
+ document.getElementById("search").removeAttribute("placeholder");
+ document.getElementById("search-toolbar-label").textContent = newLabel;
+ }
+}
+
+WebInspector.toggleAttach = function()
+{
+ this.attached = !this.attached;
+}
+
+WebInspector.toolbarDragStart = function(event)
+{
+ if (!WebInspector.attached && InspectorController.platform() !== "mac-leopard")
+ return;
+
+ var target = event.target;
+ if (target.hasStyleClass("toolbar-item") && target.hasStyleClass("toggleable"))
+ return;
+
+ var toolbar = document.getElementById("toolbar");
+ if (target !== toolbar && !target.hasStyleClass("toolbar-item"))
+ return;
+
+ toolbar.lastScreenX = event.screenX;
+ toolbar.lastScreenY = event.screenY;
+
+ WebInspector.elementDragStart(toolbar, WebInspector.toolbarDrag, WebInspector.toolbarDragEnd, event, (WebInspector.attached ? "row-resize" : "default"));
+}
+
+WebInspector.toolbarDragEnd = function(event)
+{
+ var toolbar = document.getElementById("toolbar");
+
+ WebInspector.elementDragEnd(event);
+
+ delete toolbar.lastScreenX;
+ delete toolbar.lastScreenY;
+}
+
+WebInspector.toolbarDrag = function(event)
+{
+ var toolbar = document.getElementById("toolbar");
+
+ if (WebInspector.attached) {
+ var height = window.innerHeight - (event.screenY - toolbar.lastScreenY);
+
+ InspectorController.setAttachedWindowHeight(height);
+ } else {
+ var x = event.screenX - toolbar.lastScreenX;
+ var y = event.screenY - toolbar.lastScreenY;
+
+ // We cannot call window.moveBy here because it restricts the movement
+ // of the window at the edges.
+ InspectorController.moveByUnrestricted(x, y);
+ }
+
+ toolbar.lastScreenX = event.screenX;
+ toolbar.lastScreenY = event.screenY;
+
+ event.preventDefault();
+}
+
+WebInspector.elementDragStart = function(element, dividerDrag, elementDragEnd, event, cursor)
+{
+ if (this._elementDraggingEventListener || this._elementEndDraggingEventListener)
+ this.elementDragEnd(event);
+
+ this._elementDraggingEventListener = dividerDrag;
+ this._elementEndDraggingEventListener = elementDragEnd;
+
+ document.addEventListener("mousemove", dividerDrag, true);
+ document.addEventListener("mouseup", elementDragEnd, true);
+
+ document.body.style.cursor = cursor;
+
+ event.preventDefault();
+}
+
+WebInspector.elementDragEnd = function(event)
+{
+ document.removeEventListener("mousemove", this._elementDraggingEventListener, true);
+ document.removeEventListener("mouseup", this._elementEndDraggingEventListener, true);
+
+ document.body.style.removeProperty("cursor");
+
+ delete this._elementDraggingEventListener;
+ delete this._elementEndDraggingEventListener;
+
+ event.preventDefault();
+}
+
+WebInspector.showConsole = function()
+{
+ this.console.show();
+}
+
+WebInspector.showElementsPanel = function()
+{
+ this.currentPanel = this.panels.elements;
+}
+
+WebInspector.showResourcesPanel = function()
+{
+ this.currentPanel = this.panels.resources;
+}
+
+WebInspector.showScriptsPanel = function()
+{
+ this.currentPanel = this.panels.scripts;
+}
+
+WebInspector.showProfilesPanel = function()
+{
+ this.currentPanel = this.panels.profiles;
+}
+
+WebInspector.showDatabasesPanel = function()
+{
+ this.currentPanel = this.panels.databases;
+}
+
+WebInspector.addResource = function(identifier, payload)
+{
+ var resource = new WebInspector.Resource(
+ payload.requestHeaders,
+ payload.requestURL,
+ payload.host,
+ payload.path,
+ payload.lastPathComponent,
+ identifier,
+ payload.isMainResource,
+ payload.cached);
+ this.resources[identifier] = resource;
+ this.resourceURLMap[resource.url] = resource;
+
+ if (resource.mainResource) {
+ this.mainResource = resource;
+ this.panels.elements.reset();
+ }
+
+ if (this.panels.resources)
+ this.panels.resources.addResource(resource);
+}
+
+WebInspector.updateResource = function(identifier, payload)
+{
+ var resource = this.resources[identifier];
+ if (!resource)
+ return;
+
+ if (payload.didRequestChange) {
+ resource.url = payload.url;
+ resource.domain = payload.domain;
+ resource.path = payload.path;
+ resource.lastPathComponent = payload.lastPathComponent;
+ resource.requestHeaders = payload.requestHeaders;
+ resource.mainResource = payload.mainResource;
+ }
+
+ if (payload.didResponseChange) {
+ resource.mimeType = payload.mimeType;
+ resource.suggestedFilename = payload.suggestedFilename;
+ resource.expectedContentLength = payload.expectedContentLength;
+ resource.statusCode = payload.statusCode;
+ resource.suggestedFilename = payload.suggestedFilename;
+ resource.responseHeaders = payload.responseHeaders;
+ }
+
+ if (payload.didTypeChange) {
+ resource.type = payload.type;
+ }
+
+ if (payload.didLengthChange) {
+ resource.contentLength = payload.contentLength;
+ }
+
+ if (payload.didCompletionChange) {
+ resource.failed = payload.failed;
+ resource.finished = payload.finished;
+ }
+
+ if (payload.didTimingChange) {
+ if (payload.startTime)
+ resource.startTime = payload.startTime;
+ if (payload.responseReceivedTime)
+ resource.responseReceivedTime = payload.responseReceivedTime;
+ if (payload.endTime)
+ resource.endTime = payload.endTime;
+ }
+}
+
+WebInspector.removeResource = function(identifier)
+{
+ var resource = this.resources[identifier];
+ if (!resource)
+ return;
+
+ resource.category.removeResource(resource);
+ delete this.resourceURLMap[resource.url];
+ delete this.resources[identifier];
+
+ if (this.panels.resources)
+ this.panels.resources.removeResource(resource);
+}
+
+WebInspector.addDatabase = function(payload)
+{
+ var database = new WebInspector.Database(
+ payload.database,
+ payload.domain,
+ payload.name,
+ payload.version);
+ this.panels.databases.addDatabase(database);
+}
+
+WebInspector.addDOMStorage = function(payload)
+{
+ var domStorage = new WebInspector.DOMStorage(
+ payload.domStorage,
+ payload.host,
+ payload.isLocalStorage);
+ this.panels.databases.addDOMStorage(domStorage);
+}
+
+WebInspector.resourceTrackingWasEnabled = function()
+{
+ this.panels.resources.resourceTrackingWasEnabled();
+}
+
+WebInspector.resourceTrackingWasDisabled = function()
+{
+ this.panels.resources.resourceTrackingWasDisabled();
+}
+
+WebInspector.attachDebuggerWhenShown = function()
+{
+ this.panels.scripts.attachDebuggerWhenShown();
+}
+
+WebInspector.debuggerWasEnabled = function()
+{
+ this.panels.scripts.debuggerWasEnabled();
+}
+
+WebInspector.debuggerWasDisabled = function()
+{
+ this.panels.scripts.debuggerWasDisabled();
+}
+
+WebInspector.profilerWasEnabled = function()
+{
+ this.panels.profiles.profilerWasEnabled();
+}
+
+WebInspector.profilerWasDisabled = function()
+{
+ this.panels.profiles.profilerWasDisabled();
+}
+
+WebInspector.parsedScriptSource = function(sourceID, sourceURL, source, startingLine)
+{
+ this.panels.scripts.addScript(sourceID, sourceURL, source, startingLine);
+}
+
+WebInspector.failedToParseScriptSource = function(sourceURL, source, startingLine, errorLine, errorMessage)
+{
+ this.panels.scripts.addScript(null, sourceURL, source, startingLine, errorLine, errorMessage);
+}
+
+WebInspector.pausedScript = function()
+{
+ this.panels.scripts.debuggerPaused();
+}
+
+WebInspector.resumedScript = function()
+{
+ this.panels.scripts.debuggerResumed();
+}
+
+WebInspector.populateInterface = function()
+{
+ for (var panelName in this.panels) {
+ var panel = this.panels[panelName];
+ if ("populateInterface" in panel)
+ panel.populateInterface();
+ }
+}
+
+WebInspector.reset = function()
+{
+ for (var panelName in this.panels) {
+ var panel = this.panels[panelName];
+ if ("reset" in panel)
+ panel.reset();
+ }
+
+ for (var category in this.resourceCategories)
+ this.resourceCategories[category].removeAllResources();
+
+ this.resources = {};
+ this.resourceURLMap = {};
+ this.hoveredDOMNode = null;
+
+ delete this.mainResource;
+
+ this.console.clearMessages();
+}
+
+WebInspector.inspectedWindowCleared = function(inspectedWindow)
+{
+ this.panels.elements.inspectedWindowCleared(inspectedWindow);
+}
+
+WebInspector.resourceURLChanged = function(resource, oldURL)
+{
+ delete this.resourceURLMap[oldURL];
+ this.resourceURLMap[resource.url] = resource;
+}
+
+WebInspector.addMessageToConsole = function(payload)
+{
+ var consoleMessage = new WebInspector.ConsoleMessage(
+ payload.source,
+ payload.level,
+ payload.line,
+ payload.url,
+ payload.groupLevel,
+ payload.repeatCount);
+ consoleMessage.setMessageBody(Array.prototype.slice.call(arguments, 1));
+ this.console.addMessage(consoleMessage);
+}
+
+WebInspector.addProfile = function(profile)
+{
+ this.panels.profiles.addProfile(profile);
+}
+
+WebInspector.setRecordingProfile = function(isProfiling)
+{
+ this.panels.profiles.setRecordingProfile(isProfiling);
+}
+
+WebInspector.drawLoadingPieChart = function(canvas, percent) {
+ var g = canvas.getContext("2d");
+ var darkColor = "rgb(122, 168, 218)";
+ var lightColor = "rgb(228, 241, 251)";
+ var cx = 8;
+ var cy = 8;
+ var r = 7;
+
+ g.beginPath();
+ g.arc(cx, cy, r, 0, Math.PI * 2, false);
+ g.closePath();
+
+ g.lineWidth = 1;
+ g.strokeStyle = darkColor;
+ g.fillStyle = lightColor;
+ g.fill();
+ g.stroke();
+
+ var startangle = -Math.PI / 2;
+ var endangle = startangle + (percent * Math.PI * 2);
+
+ g.beginPath();
+ g.moveTo(cx, cy);
+ g.arc(cx, cy, r, startangle, endangle, false);
+ g.closePath();
+
+ g.fillStyle = darkColor;
+ g.fill();
+}
+
+WebInspector.updateFocusedNode = function(node)
+{
+ if (!node)
+ // FIXME: Should we deselect if null is passed in?
+ return;
+
+ this.currentPanel = this.panels.elements;
+ this.panels.elements.focusedDOMNode = node;
+}
+
+WebInspector.displayNameForURL = function(url)
+{
+ if (!url)
+ return "";
+ var resource = this.resourceURLMap[url];
+ if (resource)
+ return resource.displayName;
+ return url.trimURL(WebInspector.mainResource ? WebInspector.mainResource.domain : "");
+}
+
+WebInspector.resourceForURL = function(url)
+{
+ if (url in this.resourceURLMap)
+ return this.resourceURLMap[url];
+
+ // No direct match found. Search for resources that contain
+ // a substring of the URL.
+ for (var resourceURL in this.resourceURLMap) {
+ if (resourceURL.hasSubstring(url))
+ return this.resourceURLMap[resourceURL];
+ }
+
+ return null;
+}
+
+WebInspector.showResourceForURL = function(url, line, preferredPanel)
+{
+ var resource = this.resourceForURL(url);
+ if (!resource)
+ return false;
+
+ if (preferredPanel && preferredPanel in WebInspector.panels) {
+ var panel = this.panels[preferredPanel];
+ if (!("showResource" in panel))
+ panel = null;
+ else if ("canShowResource" in panel && !panel.canShowResource(resource))
+ panel = null;
+ }
+
+ this.currentPanel = panel || this.panels.resources;
+ if (!this.currentPanel)
+ return false;
+ this.currentPanel.showResource(resource, line);
+ return true;
+}
+
+WebInspector.linkifyStringAsFragment = function(string)
+{
+ var container = document.createDocumentFragment();
+ var linkStringRegEx = new RegExp("(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}://|www\\.)[\\w$\\-_+*'=\\|/\\\\(){}[\\]%@&#~,:;.!?]{2,}[\\w$\\-_+*=\\|/\\\\({%@&#~]");
+
+ while (string) {
+ var linkString = linkStringRegEx.exec(string);
+ if (!linkString)
+ break;
+
+ linkString = linkString[0];
+ var title = linkString;
+ var linkIndex = string.indexOf(linkString);
+ var nonLink = string.substring(0, linkIndex);
+ container.appendChild(document.createTextNode(nonLink));
+
+ var profileStringRegEx = new RegExp("webkit-profile://(.+)/[0-9]+");
+ var profileStringMatches = profileStringRegEx.exec(title);
+ var profileTitle;
+ if (profileStringMatches)
+ profileTitle = profileStringMatches[1];
+ if (profileTitle)
+ title = WebInspector.panels.profiles.displayTitleForProfileLink(profileTitle);
+
+ var realURL = (linkString.indexOf("www.") === 0 ? "http://" + linkString : linkString);
+ container.appendChild(WebInspector.linkifyURLAsNode(realURL, title, null, (realURL in WebInspector.resourceURLMap)));
+ string = string.substring(linkIndex + linkString.length, string.length);
+ }
+
+ if (string)
+ container.appendChild(document.createTextNode(string));
+
+ return container;
+}
+
+WebInspector.showProfileById = function(uid) {
+ WebInspector.showProfilesPanel();
+ WebInspector.panels.profiles.showProfileById(uid);
+}
+
+WebInspector.linkifyURLAsNode = function(url, linkText, classes, isExternal)
+{
+ if (!linkText)
+ linkText = url;
+ classes = (classes ? classes + " " : "");
+ classes += isExternal ? "webkit-html-external-link" : "webkit-html-resource-link";
+
+ var a = document.createElement("a");
+ a.href = url;
+ a.className = classes;
+ a.title = url;
+ a.target = "_blank";
+ a.textContent = linkText;
+
+ return a;
+}
+
+WebInspector.linkifyURL = function(url, linkText, classes, isExternal)
+{
+ // Use the DOM version of this function so as to avoid needing to escape attributes.
+ // FIXME: Get rid of linkifyURL entirely.
+ return WebInspector.linkifyURLAsNode(url, linkText, classes, isExternal).outerHTML;
+}
+
+WebInspector.addMainEventListeners = function(doc)
+{
+ doc.defaultView.addEventListener("focus", this.windowFocused.bind(this), true);
+ doc.defaultView.addEventListener("blur", this.windowBlured.bind(this), true);
+ doc.addEventListener("click", this.documentClick.bind(this), true);
+}
+
+WebInspector.searchKeyDown = function(event)
+{
+ if (event.keyIdentifier !== "Enter")
+ return;
+
+ // Call preventDefault since this was the Enter key. This prevents a "search" event
+ // from firing for key down. We handle the Enter key on key up in searchKeyUp. This
+ // stops performSearch from being called twice in a row.
+ event.preventDefault();
+}
+
+WebInspector.searchKeyUp = function(event)
+{
+ if (event.keyIdentifier !== "Enter")
+ return;
+
+ // Select all of the text so the user can easily type an entirely new query.
+ event.target.select();
+
+ // Only call performSearch if the Enter key was pressed. Otherwise the search
+ // performance is poor because of searching on every key. The search field has
+ // the incremental attribute set, so we still get incremental searches.
+ this.performSearch(event);
+}
+
+WebInspector.performSearch = function(event)
+{
+ var query = event.target.value;
+ var forceSearch = event.keyIdentifier === "Enter";
+
+ if (!query || !query.length || (!forceSearch && query.length < 3)) {
+ delete this.currentQuery;
+
+ for (var panelName in this.panels) {
+ var panel = this.panels[panelName];
+ if (panel.currentQuery && panel.searchCanceled)
+ panel.searchCanceled();
+ delete panel.currentQuery;
+ }
+
+ this.updateSearchMatchesCount();
+
+ return;
+ }
+
+ if (query === this.currentPanel.currentQuery && this.currentPanel.currentQuery === this.currentQuery) {
+ // When this is the same query and a forced search, jump to the next
+ // search result for a good user experience.
+ if (forceSearch && this.currentPanel.jumpToNextSearchResult)
+ this.currentPanel.jumpToNextSearchResult();
+ return;
+ }
+
+ this.currentQuery = query;
+
+ this.updateSearchMatchesCount();
+
+ if (!this.currentPanel.performSearch)
+ return;
+
+ this.currentPanel.currentQuery = query;
+ this.currentPanel.performSearch(query);
+}
+
+WebInspector.updateSearchMatchesCount = function(matches, panel)
+{
+ if (!panel)
+ panel = this.currentPanel;
+
+ panel.currentSearchMatches = matches;
+
+ if (panel !== this.currentPanel)
+ return;
+
+ if (!this.currentPanel.currentQuery) {
+ document.getElementById("search-results-matches").addStyleClass("hidden");
+ return;
+ }
+
+ if (matches) {
+ if (matches === 1)
+ var matchesString = WebInspector.UIString("1 match");
+ else
+ var matchesString = WebInspector.UIString("%d matches", matches);
+ } else
+ var matchesString = WebInspector.UIString("Not Found");
+
+ var matchesToolbarElement = document.getElementById("search-results-matches");
+ matchesToolbarElement.removeStyleClass("hidden");
+ matchesToolbarElement.textContent = matchesString;
+}
+
+WebInspector.UIString = function(string)
+{
+ if (window.localizedStrings && string in window.localizedStrings)
+ string = window.localizedStrings[string];
+ else {
+ if (!(string in this.missingLocalizedStrings)) {
+ console.error("Localized string \"" + string + "\" not found.");
+ this.missingLocalizedStrings[string] = true;
+ }
+
+ if (Preferences.showMissingLocalizedStrings)
+ string += " (not localized)";
+ }
+
+ return String.vsprintf(string, Array.prototype.slice.call(arguments, 1));
+}
+
+WebInspector.isBeingEdited = function(element)
+{
+ return element.__editing;
+}
+
+WebInspector.startEditing = function(element, committedCallback, cancelledCallback, context)
+{
+ if (element.__editing)
+ return;
+ element.__editing = true;
+
+ var oldText = element.textContent;
+ var oldHandleKeyEvent = element.handleKeyEvent;
+
+ element.addStyleClass("editing");
+
+ var oldTabIndex = element.tabIndex;
+ if (element.tabIndex < 0)
+ element.tabIndex = 0;
+
+ function blurEventListener() {
+ editingCommitted.call(element);
+ }
+
+ function cleanUpAfterEditing() {
+ delete this.__editing;
+
+ this.removeStyleClass("editing");
+ this.tabIndex = oldTabIndex;
+ this.scrollTop = 0;
+ this.scrollLeft = 0;
+
+ this.handleKeyEvent = oldHandleKeyEvent;
+ element.removeEventListener("blur", blurEventListener, false);
+
+ if (element === WebInspector.currentFocusElement || element.isAncestor(WebInspector.currentFocusElement))
+ WebInspector.currentFocusElement = WebInspector.previousFocusElement;
+ }
+
+ function editingCancelled() {
+ this.innerText = oldText;
+
+ cleanUpAfterEditing.call(this);
+
+ cancelledCallback(this, context);
+ }
+
+ function editingCommitted() {
+ cleanUpAfterEditing.call(this);
+
+ committedCallback(this, this.textContent, oldText, context);
+ }
+
+ element.handleKeyEvent = function(event) {
+ if (oldHandleKeyEvent)
+ oldHandleKeyEvent(event);
+ if (event.handled)
+ return;
+
+ if (event.keyIdentifier === "Enter") {
+ editingCommitted.call(element);
+ event.preventDefault();
+ } else if (event.keyCode === 27) { // Escape key
+ editingCancelled.call(element);
+ event.preventDefault();
+ event.handled = true;
+ }
+ }
+
+ element.addEventListener("blur", blurEventListener, false);
+
+ WebInspector.currentFocusElement = element;
+}
+
+WebInspector._toolbarItemClicked = function(event)
+{
+ var toolbarItem = event.currentTarget;
+ this.currentPanel = toolbarItem.panel;
+}
+
+// This table maps MIME types to the Resource.Types which are valid for them.
+// The following line:
+// "text/html": {0: 1},
+// means that text/html is a valid MIME type for resources that have type
+// WebInspector.Resource.Type.Document (which has a value of 0).
+WebInspector.MIMETypes = {
+ "text/html": {0: true},
+ "text/xml": {0: true},
+ "text/plain": {0: true},
+ "application/xhtml+xml": {0: true},
+ "text/css": {1: true},
+ "text/xsl": {1: true},
+ "image/jpeg": {2: true},
+ "image/png": {2: true},
+ "image/gif": {2: true},
+ "image/bmp": {2: true},
+ "image/vnd.microsoft.icon": {2: true},
+ "image/x-icon": {2: true},
+ "image/x-xbitmap": {2: true},
+ "font/ttf": {3: true},
+ "font/opentype": {3: true},
+ "application/x-font-type1": {3: true},
+ "application/x-font-ttf": {3: true},
+ "application/x-truetype-font": {3: true},
+ "text/javascript": {4: true},
+ "text/ecmascript": {4: true},
+ "application/javascript": {4: true},
+ "application/ecmascript": {4: true},
+ "application/x-javascript": {4: true},
+ "text/javascript1.1": {4: true},
+ "text/javascript1.2": {4: true},
+ "text/javascript1.3": {4: true},
+ "text/jscript": {4: true},
+ "text/livescript": {4: true},
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector_controller.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector_controller.js
new file mode 100644
index 0000000..5401b49
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector_controller.js
@@ -0,0 +1,430 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Stub implementation of the InspectorController API.
+ * This stub class is supposed to make front-end a standalone WebApp
+ * that can be implemented/refactored in isolation from the Web browser
+ * backend. Clients need to subclass it in order to wire calls to the
+ * non-stub backends.
+ */
+goog.provide('devtools.InspectorController');
+
+
+/**
+ * Creates inspector controller stub instance.
+ * @constructor.
+ */
+devtools.InspectorController = function() {
+ /**
+ * @type {boolean}
+ */
+ this.searchingForNode_ = false;
+
+ /**
+ * @type {boolean}
+ */
+ this.windowVisible_ = true;
+
+ /**
+ * @type {number}
+ */
+ this.attachedWindowHeight_ = 0;
+
+ /**
+ * @type {boolean}
+ */
+ this.debuggerEnabled_ = true;
+
+ /**
+ * @type {boolean}
+ */
+ this.profilerEnabled_ = true;
+
+ /**
+ * @type {boolean}
+ */
+ this.resourceTrackingEnabled_ = false;
+};
+
+
+/**
+ * Wraps javascript callback.
+ * @param {function():undefined} func The callback to wrap.
+ * @return {function():undefined} Callback wrapper.
+ */
+devtools.InspectorController.prototype.wrapCallback = function f(func) {
+ // Just return as is.
+ return func;
+};
+
+
+/**
+ * @return {boolean} True iff inspector window is currently visible.
+ */
+devtools.InspectorController.prototype.isWindowVisible = function() {
+ return this.windowVisible_;
+};
+
+
+/**
+ * @return {string} Platform identifier.
+ */
+devtools.InspectorController.prototype.platform = function() {
+ return 'windows';
+};
+
+
+/**
+ * Closes inspector window.
+ */
+devtools.InspectorController.prototype.closeWindow = function() {
+ this.windowVisible_ = false;
+};
+
+
+/**
+ * Attaches frontend to the backend.
+ */
+devtools.InspectorController.prototype.attach = function() {
+};
+
+
+/**
+ * Detaches frontend from the backend.
+ */
+devtools.InspectorController.prototype.detach = function() {
+};
+
+
+/**
+ * Clears console message log in the backend.
+ */
+devtools.InspectorController.prototype.clearMessages = function() {
+};
+
+
+/**
+ * Returns true iff browser is currently in the search for node mode.
+ * @return {boolean} True is currently searching for a node.
+ */
+devtools.InspectorController.prototype.searchingForNode = function() {
+ return this.searchingForNode_;
+};
+
+
+/**
+ * Initiates search for a given query starting on a given row.
+ * @param {number} sourceRow Row to start searching from.
+ * @param {string} query Query string for search for.
+ */
+devtools.InspectorController.prototype.search = function(sourceRow, query) {
+};
+
+
+/**
+ * Toggles node search mode on/off.
+ */
+devtools.InspectorController.prototype.toggleNodeSearch = function() {
+ this.searchingForNode_ = !this.searchingForNode_;
+};
+
+
+/**
+ * Sets the inspector window height while in the attached mode.
+ * @param {number} height Window height being set.
+ */
+devtools.InspectorController.prototype.setAttachedWindowHeight =
+ function(height) {
+ this.attachedWindowHeight_ = height;
+};
+
+
+/**
+ * Moves window by the given offset.
+ * @param {number} x X offset.
+ * @param {number} y Y offset.
+ */
+devtools.InspectorController.prototype.moveByUnrestricted = function(x, y) {
+};
+
+
+/**
+ * Adds resource with given identifier into the given iframe element.
+ * @param {number} identifier Identifier of the resource to add into the frame.
+ * @param {Element} element Element to add resource content to.
+ */
+devtools.InspectorController.prototype.addResourceSourceToFrame =
+ function(identifier, element) {
+};
+
+
+/**
+ * Adds given source of a given mimeType into the given iframe element.
+ * @param {string} mimeType MIME type of the content to be added.
+ * @param {string} source String content to be added.
+ * @param {Element} element Element to add resource content to.
+ */
+devtools.InspectorController.prototype.addSourceToFrame =
+ function(mimeType, source, element) {
+ return false;
+};
+
+
+/**
+ * Returns document node corresponding to the resource with given id.
+ * @return {Node} Node containing the resource.
+ */
+devtools.InspectorController.prototype.getResourceDocumentNode =
+ function(identifier) {
+ return undefined;
+};
+
+
+/**
+ * Highlights the given node on the page.
+ * @param {Node} node Node to highlight.
+ */
+devtools.InspectorController.prototype.highlightDOMNode = function(node) {
+ // Does nothing in stub.
+};
+
+
+/**
+ * Clears current highlight.
+ */
+devtools.InspectorController.prototype.hideDOMNodeHighlight = function() {
+ // Does nothing in stub.
+};
+
+
+/**
+ * @return {window} Inspectable window instance.
+ */
+devtools.InspectorController.prototype.inspectedWindow = function() {
+ return window;
+};
+
+
+/**
+ * Notifies backend that the frontend has been successfully loaded.
+ */
+devtools.InspectorController.prototype.loaded = function() {
+ // Does nothing in stub.
+};
+
+
+/**
+ * @return {string} Url of the i18n-ed strings map.
+ */
+devtools.InspectorController.prototype.localizedStringsURL = function() {
+ return undefined;
+};
+
+
+/**
+ * @return {boolean} True iff window is currently unloading.
+ */
+devtools.InspectorController.prototype.windowUnloading = function() {
+ return false;
+};
+
+
+/**
+ * @return {string} Identifiers of the panels that should be hidden.
+ */
+devtools.InspectorController.prototype.hiddenPanels = function() {
+ return '';
+};
+
+
+/**
+ * @return {boolean} True iff debugger is enabled.
+ */
+devtools.InspectorController.prototype.debuggerEnabled = function() {
+ return this.debuggerEnabled_;
+};
+
+
+/**
+ * Enables resource tracking.
+ */
+devtools.InspectorController.prototype.enableResourceTracking = function() {
+ this.resourceTrackingEnabled_ = true;
+ WebInspector.resourceTrackingWasEnabled();
+};
+
+
+/**
+ * Disables resource tracking.
+ */
+devtools.InspectorController.prototype.disableResourceTracking = function() {
+ this.resourceTrackingEnabled_ = false;
+ WebInspector.resourceTrackingWasDisabled();
+};
+
+
+/**
+ * @return {boolean} True iff resource tracking is enabled.
+ */
+devtools.InspectorController.prototype.resourceTrackingEnabled = function() {
+ return this.resourceTrackingEnabled_;
+};
+
+
+/**
+ * Enables debugger.
+ */
+devtools.InspectorController.prototype.enableDebugger = function() {
+ this.debuggerEnabled_ = true;
+};
+
+
+/**
+ * Disables debugger.
+ */
+devtools.InspectorController.prototype.disableDebugger = function() {
+ this.debuggerEnabled_ = false;
+};
+
+
+/**
+ * Adds breakpoint to the given line of the source with given ID.
+ * @param {string} sourceID Source Id to add breakpoint to.
+ * @param {number} line Line number to add breakpoint to.
+ */
+devtools.InspectorController.prototype.addBreakpoint =
+ function(sourceID, line) {
+};
+
+
+/**
+ * Removes breakpoint from the given line of the source with given ID.
+ * @param {string} sourceID Source Id to remove breakpoint from.
+ * @param {number} line Line number to remove breakpoint from.
+ */
+devtools.InspectorController.prototype.removeBreakpoint =
+ function(sourceID, line) {
+};
+
+
+/**
+ * Tells backend to pause in the debugger.
+ */
+devtools.InspectorController.prototype.pauseInDebugger = function() {
+ // Does nothing in stub.
+};
+
+
+/**
+ * @return {boolean} True iff the debugger will pause execution on the
+ * exceptions.
+ */
+devtools.InspectorController.prototype.pauseOnExceptions = function() {
+ // Does nothing in stub.
+ return false;
+};
+
+
+/**
+ * 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.InspectorController.prototype.setPauseOnExceptions = function(value) {
+};
+
+
+/**
+ * Tells backend to resume execution.
+ */
+devtools.InspectorController.prototype.resumeDebugger = function() {
+};
+
+
+/**
+ * @return {boolean} True iff profiler is enabled.
+ */
+devtools.InspectorController.prototype.profilerEnabled = function() {
+ return true;
+};
+
+
+/**
+ * Enables profiler.
+ */
+devtools.InspectorController.prototype.enableProfiler = function() {
+ this.profilerEnabled_ = true;
+};
+
+
+/**
+ * Disables profiler.
+ */
+devtools.InspectorController.prototype.disableProfiler = function() {
+ this.profilerEnabled_ = false;
+};
+
+
+/**
+ * Returns given callframe while on a debugger break.
+ * @return {Object} Current call frame.
+ */
+devtools.InspectorController.prototype.currentCallFrame = function() {
+ return undefined;
+};
+
+
+/**
+ * Tells backend to start collecting profiler data.
+ */
+devtools.InspectorController.prototype.startProfiling = function() {
+};
+
+
+/**
+ * Tells backend to stop collecting profiler data.
+ */
+devtools.InspectorController.prototype.stopProfiling = function() {
+};
+
+
+/**
+ * @return {Array.<Object>} Profile snapshots array.
+ */
+devtools.InspectorController.prototype.profiles = function() {
+ return [];
+};
+
+
+/**
+ * @return {Array.<string>} Database table names available offline.
+ */
+devtools.InspectorController.prototype.databaseTableNames =
+ function(database) {
+ return [];
+};
+
+
+/**
+ * Tells backend to step into the function in debugger.
+ */
+devtools.InspectorController.prototype.stepIntoStatementInDebugger =
+ function() {
+};
+
+
+/**
+ * Tells backend to step out of the function in debugger.
+ */
+devtools.InspectorController.prototype.stepOutOfFunctionInDebugger =
+ function() {};
+
+
+/**
+ * Tells backend to step over the statement in debugger.
+ */
+devtools.InspectorController.prototype.stepOverStatementInDebugger =
+ function() {
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector_controller_impl.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector_controller_impl.js
new file mode 100644
index 0000000..d04b16a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/inspector_controller_impl.js
@@ -0,0 +1,203 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview DevTools' implementation of the InspectorController API.
+ */
+goog.require('devtools.InspectorController');
+
+goog.provide('devtools.InspectorControllerImpl');
+
+devtools.InspectorControllerImpl = function() {
+ devtools.InspectorController.call(this);
+ this.frame_element_id_ = 1;
+};
+goog.inherits(devtools.InspectorControllerImpl,
+ devtools.InspectorController);
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorController.prototype.platform = function() {
+ return DevToolsHost.getPlatform();
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorController.prototype.clearMessages = function() {
+ RemoteToolsAgent.ClearConsoleMessages();
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorControllerImpl.prototype.hiddenPanels = function() {
+ return 'databases';
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorController.prototype.search = function(sourceRow, query) {
+ return DevToolsHost.search(sourceRow, query);
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorControllerImpl.prototype.addSourceToFrame =
+ function(mimeType, source, element) {
+ return DevToolsHost.addSourceToFrame(mimeType, source, element);
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorControllerImpl.prototype.addResourceSourceToFrame =
+ function(identifier, element) {
+ var resource = WebInspector.resources[identifier];
+ if (!resource) {
+ return;
+ }
+ DevToolsHost.addResourceSourceToFrame(identifier, resource.mimeType, element);
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorControllerImpl.prototype.hideDOMNodeHighlight = function() {
+ RemoteToolsAgent.HideDOMNodeHighlight();
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorControllerImpl.prototype.highlightDOMNode =
+ function(hoveredNode) {
+ RemoteToolsAgent.HighlightDOMNode(hoveredNode.id_);
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorControllerImpl.prototype.inspectedWindow = function() {
+ return devtools.tools.getDomAgent().getWindow();
+};
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorController.prototype.enableResourceTracking =
+ function(always) {
+ devtools.tools.setResourceTrackingEnabled(true, always);
+}
+
+
+/**
+ * {@inheritDoc}.
+ */
+devtools.InspectorController.prototype.disableResourceTracking =
+ function(always) {
+ devtools.tools.setResourceTrackingEnabled(false, always);
+};
+
+
+/**
+ * @override
+ */
+devtools.InspectorControllerImpl.prototype.debuggerEnabled = function() {
+ return true;
+};
+
+
+devtools.InspectorControllerImpl.prototype.currentCallFrame = function() {
+ return devtools.tools.getDebuggerAgent().getCurrentCallFrame();
+};
+
+
+devtools.InspectorControllerImpl.prototype.addBreakpoint = function(
+ sourceID, line) {
+ devtools.tools.getDebuggerAgent().addBreakpoint(sourceID, line);
+};
+
+
+devtools.InspectorControllerImpl.prototype.removeBreakpoint = function(
+ sourceID, line) {
+ devtools.tools.getDebuggerAgent().removeBreakpoint(sourceID, line);
+};
+
+
+devtools.InspectorController.prototype.pauseInDebugger = function() {
+ devtools.tools.getDebuggerAgent().pauseExecution();
+};
+
+
+devtools.InspectorControllerImpl.prototype.resumeDebugger = function() {
+ devtools.tools.getDebuggerAgent().resumeExecution();
+};
+
+
+devtools.InspectorControllerImpl.prototype.stepIntoStatementInDebugger =
+ function() {
+ devtools.tools.getDebuggerAgent().stepIntoStatement();
+};
+
+
+devtools.InspectorControllerImpl.prototype.stepOutOfFunctionInDebugger =
+ function() {
+ devtools.tools.getDebuggerAgent().stepOutOfFunction();
+};
+
+
+devtools.InspectorControllerImpl.prototype.stepOverStatementInDebugger =
+ function() {
+ devtools.tools.getDebuggerAgent().stepOverStatement();
+};
+
+
+/**
+ * @override
+ */
+devtools.InspectorControllerImpl.prototype.pauseOnExceptions = function() {
+ return devtools.tools.getDebuggerAgent().pauseOnExceptions();
+};
+
+
+/**
+ * @override
+ */
+devtools.InspectorControllerImpl.prototype.setPauseOnExceptions = function(
+ value) {
+ return devtools.tools.getDebuggerAgent().setPauseOnExceptions(value);
+};
+
+
+/**
+ * @override
+ */
+devtools.InspectorControllerImpl.prototype.startProfiling = function() {
+ devtools.tools.getDebuggerAgent().startProfiling();
+};
+
+
+/**
+ * @override
+ */
+devtools.InspectorControllerImpl.prototype.stopProfiling = function() {
+ devtools.tools.getDebuggerAgent().stopProfiling();
+};
+
+
+var InspectorController = new devtools.InspectorControllerImpl();
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/profile.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/profile.js
new file mode 100644
index 0000000..614c635
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/profile.js
@@ -0,0 +1,605 @@
+// Copyright 2009 the V8 project authors. 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.
+
+
+// Initlialize namespaces
+var devtools = devtools || {};
+devtools.profiler = devtools.profiler || {};
+
+
+/**
+ * Creates a profile object for processing profiling-related events
+ * and calculating function execution times.
+ *
+ * @constructor
+ */
+devtools.profiler.Profile = function() {
+ this.codeMap_ = new devtools.profiler.CodeMap();
+ this.topDownTree_ = new devtools.profiler.CallTree();
+ this.bottomUpTree_ = new devtools.profiler.CallTree();
+};
+
+
+/**
+ * Returns whether a function with the specified name must be skipped.
+ * Should be overriden by subclasses.
+ *
+ * @param {string} name Function name.
+ */
+devtools.profiler.Profile.prototype.skipThisFunction = function(name) {
+ return false;
+};
+
+
+/**
+ * Enum for profiler operations that involve looking up existing
+ * code entries.
+ *
+ * @enum {number}
+ */
+devtools.profiler.Profile.Operation = {
+ MOVE: 0,
+ DELETE: 1,
+ TICK: 2
+};
+
+
+/**
+ * Called whenever the specified operation has failed finding a function
+ * containing the specified address. Should be overriden by subclasses.
+ * See the devtools.profiler.Profile.Operation enum for the list of
+ * possible operations.
+ *
+ * @param {number} operation Operation.
+ * @param {number} addr Address of the unknown code.
+ * @param {number} opt_stackPos If an unknown address is encountered
+ * during stack strace processing, specifies a position of the frame
+ * containing the address.
+ */
+devtools.profiler.Profile.prototype.handleUnknownCode = function(
+ operation, addr, opt_stackPos) {
+};
+
+
+/**
+ * Registers static (library) code entry.
+ *
+ * @param {string} name Code entry name.
+ * @param {number} startAddr Starting address.
+ * @param {number} endAddr Ending address.
+ */
+devtools.profiler.Profile.prototype.addStaticCode = function(
+ name, startAddr, endAddr) {
+ var entry = new devtools.profiler.CodeMap.CodeEntry(
+ endAddr - startAddr, name);
+ this.codeMap_.addStaticCode(startAddr, entry);
+ return entry;
+};
+
+
+/**
+ * Registers dynamic (JIT-compiled) code entry.
+ *
+ * @param {string} type Code entry type.
+ * @param {string} name Code entry name.
+ * @param {number} start Starting address.
+ * @param {number} size Code entry size.
+ */
+devtools.profiler.Profile.prototype.addCode = function(
+ type, name, start, size) {
+ var entry = new devtools.profiler.Profile.DynamicCodeEntry(size, type, name);
+ this.codeMap_.addCode(start, entry);
+ return entry;
+};
+
+
+/**
+ * Reports about moving of a dynamic code entry.
+ *
+ * @param {number} from Current code entry address.
+ * @param {number} to New code entry address.
+ */
+devtools.profiler.Profile.prototype.moveCode = function(from, to) {
+ try {
+ this.codeMap_.moveCode(from, to);
+ } catch (e) {
+ this.handleUnknownCode(devtools.profiler.Profile.Operation.MOVE, from);
+ }
+};
+
+
+/**
+ * Reports about deletion of a dynamic code entry.
+ *
+ * @param {number} start Starting address.
+ */
+devtools.profiler.Profile.prototype.deleteCode = function(start) {
+ try {
+ this.codeMap_.deleteCode(start);
+ } catch (e) {
+ this.handleUnknownCode(devtools.profiler.Profile.Operation.DELETE, start);
+ }
+};
+
+
+/**
+ * Records a tick event. Stack must contain a sequence of
+ * addresses starting with the program counter value.
+ *
+ * @param {Array<number>} stack Stack sample.
+ */
+devtools.profiler.Profile.prototype.recordTick = function(stack) {
+ var processedStack = this.resolveAndFilterFuncs_(stack);
+ this.bottomUpTree_.addPath(processedStack);
+ processedStack.reverse();
+ this.topDownTree_.addPath(processedStack);
+};
+
+
+/**
+ * Translates addresses into function names and filters unneeded
+ * functions.
+ *
+ * @param {Array<number>} stack Stack sample.
+ */
+devtools.profiler.Profile.prototype.resolveAndFilterFuncs_ = function(stack) {
+ var result = [];
+ for (var i = 0; i < stack.length; ++i) {
+ var entry = this.codeMap_.findEntry(stack[i]);
+ if (entry) {
+ var name = entry.getName();
+ if (!this.skipThisFunction(name)) {
+ result.push(name);
+ }
+ } else {
+ this.handleUnknownCode(
+ devtools.profiler.Profile.Operation.TICK, stack[i], i);
+ }
+ }
+ return result;
+};
+
+
+/**
+ * Performs a BF traversal of the top down call graph.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ */
+devtools.profiler.Profile.prototype.traverseTopDownTree = function(f) {
+ this.topDownTree_.traverse(f);
+};
+
+
+/**
+ * Performs a BF traversal of the bottom up call graph.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ */
+devtools.profiler.Profile.prototype.traverseBottomUpTree = function(f) {
+ this.bottomUpTree_.traverse(f);
+};
+
+
+/**
+ * Calculates a top down profile for a node with the specified label.
+ * If no name specified, returns the whole top down calls tree.
+ *
+ * @param {string} opt_label Node label.
+ */
+devtools.profiler.Profile.prototype.getTopDownProfile = function(opt_label) {
+ return this.getTreeProfile_(this.topDownTree_, opt_label);
+};
+
+
+/**
+ * Calculates a bottom up profile for a node with the specified label.
+ * If no name specified, returns the whole bottom up calls tree.
+ *
+ * @param {string} opt_label Node label.
+ */
+devtools.profiler.Profile.prototype.getBottomUpProfile = function(opt_label) {
+ return this.getTreeProfile_(this.bottomUpTree_, opt_label);
+};
+
+
+/**
+ * Helper function for calculating a tree profile.
+ *
+ * @param {devtools.profiler.Profile.CallTree} tree Call tree.
+ * @param {string} opt_label Node label.
+ */
+devtools.profiler.Profile.prototype.getTreeProfile_ = function(tree, opt_label) {
+ if (!opt_label) {
+ tree.computeTotalWeights();
+ return tree;
+ } else {
+ var subTree = tree.cloneSubtree(opt_label);
+ subTree.computeTotalWeights();
+ return subTree;
+ }
+};
+
+
+/**
+ * Calculates a flat profile of callees starting from a node with
+ * the specified label. If no name specified, starts from the root.
+ *
+ * @param {string} opt_label Starting node label.
+ */
+devtools.profiler.Profile.prototype.getFlatProfile = function(opt_label) {
+ var counters = new devtools.profiler.CallTree();
+ var rootLabel = opt_label || devtools.profiler.CallTree.ROOT_NODE_LABEL;
+ var precs = {};
+ precs[rootLabel] = 0;
+ var root = counters.findOrAddChild(rootLabel);
+
+ this.topDownTree_.computeTotalWeights();
+ this.topDownTree_.traverseInDepth(
+ function onEnter(node) {
+ if (!(node.label in precs)) {
+ precs[node.label] = 0;
+ }
+ var nodeLabelIsRootLabel = node.label == rootLabel;
+ if (nodeLabelIsRootLabel || precs[rootLabel] > 0) {
+ if (precs[rootLabel] == 0) {
+ root.selfWeight += node.selfWeight;
+ root.totalWeight += node.totalWeight;
+ } else {
+ var rec = root.findOrAddChild(node.label);
+ rec.selfWeight += node.selfWeight;
+ if (nodeLabelIsRootLabel || precs[node.label] == 0) {
+ rec.totalWeight += node.totalWeight;
+ }
+ }
+ precs[node.label]++;
+ }
+ },
+ function onExit(node) {
+ if (node.label == rootLabel || precs[rootLabel] > 0) {
+ precs[node.label]--;
+ }
+ },
+ null);
+
+ if (!opt_label) {
+ // If we have created a flat profile for the whole program, we don't
+ // need an explicit root in it. Thus, replace the counters tree
+ // root with the node corresponding to the whole program.
+ counters.root_ = root;
+ } else {
+ // Propagate weights so percents can be calculated correctly.
+ counters.getRoot().selfWeight = root.selfWeight;
+ counters.getRoot().totalWeight = root.totalWeight;
+ }
+ return counters;
+};
+
+
+/**
+ * Creates a dynamic code entry.
+ *
+ * @param {number} size Code size.
+ * @param {string} type Code type.
+ * @param {string} name Function name.
+ * @constructor
+ */
+devtools.profiler.Profile.DynamicCodeEntry = function(size, type, name) {
+ devtools.profiler.CodeMap.CodeEntry.call(this, size, name);
+ this.type = type;
+};
+
+
+/**
+ * Returns node name.
+ */
+devtools.profiler.Profile.DynamicCodeEntry.prototype.getName = function() {
+ var name = this.name;
+ if (name.length == 0) {
+ name = '<anonymous>';
+ } else if (name.charAt(0) == ' ') {
+ // An anonymous function with location: " aaa.js:10".
+ name = '<anonymous>' + name;
+ }
+ return this.type + ': ' + name;
+};
+
+
+/**
+ * Constructs a call graph.
+ *
+ * @constructor
+ */
+devtools.profiler.CallTree = function() {
+ this.root_ = new devtools.profiler.CallTree.Node(
+ devtools.profiler.CallTree.ROOT_NODE_LABEL);
+};
+
+
+/**
+ * The label of the root node.
+ */
+devtools.profiler.CallTree.ROOT_NODE_LABEL = '';
+
+
+/**
+ * @private
+ */
+devtools.profiler.CallTree.prototype.totalsComputed_ = false;
+
+
+/**
+ * Returns the tree root.
+ */
+devtools.profiler.CallTree.prototype.getRoot = function() {
+ return this.root_;
+};
+
+
+/**
+ * Adds the specified call path, constructing nodes as necessary.
+ *
+ * @param {Array<string>} path Call path.
+ */
+devtools.profiler.CallTree.prototype.addPath = function(path) {
+ if (path.length == 0) {
+ return;
+ }
+ var curr = this.root_;
+ for (var i = 0; i < path.length; ++i) {
+ curr = curr.findOrAddChild(path[i]);
+ }
+ curr.selfWeight++;
+ this.totalsComputed_ = false;
+};
+
+
+/**
+ * Finds an immediate child of the specified parent with the specified
+ * label, creates a child node if necessary. If a parent node isn't
+ * specified, uses tree root.
+ *
+ * @param {string} label Child node label.
+ */
+devtools.profiler.CallTree.prototype.findOrAddChild = function(label) {
+ return this.root_.findOrAddChild(label);
+};
+
+
+/**
+ * Creates a subtree by cloning and merging all subtrees rooted at nodes
+ * with a given label. E.g. cloning the following call tree on label 'A'
+ * will give the following result:
+ *
+ * <A>--<B> <B>
+ * / /
+ * <root> == clone on 'A' ==> <root>--<A>
+ * \ \
+ * <C>--<A>--<D> <D>
+ *
+ * And <A>'s selfWeight will be the sum of selfWeights of <A>'s from the
+ * source call tree.
+ *
+ * @param {string} label The label of the new root node.
+ */
+devtools.profiler.CallTree.prototype.cloneSubtree = function(label) {
+ var subTree = new devtools.profiler.CallTree();
+ this.traverse(function(node, parent) {
+ if (!parent && node.label != label) {
+ return null;
+ }
+ var child = (parent ? parent : subTree).findOrAddChild(node.label);
+ child.selfWeight += node.selfWeight;
+ return child;
+ });
+ return subTree;
+};
+
+
+/**
+ * Computes total weights in the call graph.
+ */
+devtools.profiler.CallTree.prototype.computeTotalWeights = function() {
+ if (this.totalsComputed_) {
+ return;
+ }
+ this.root_.computeTotalWeight();
+ this.totalsComputed_ = true;
+};
+
+
+/**
+ * Traverses the call graph in preorder. This function can be used for
+ * building optionally modified tree clones. This is the boilerplate code
+ * for this scenario:
+ *
+ * callTree.traverse(function(node, parentClone) {
+ * var nodeClone = cloneNode(node);
+ * if (parentClone)
+ * parentClone.addChild(nodeClone);
+ * return nodeClone;
+ * });
+ *
+ * @param {function(devtools.profiler.CallTree.Node, *)} f Visitor function.
+ * The second parameter is the result of calling 'f' on the parent node.
+ */
+devtools.profiler.CallTree.prototype.traverse = function(f) {
+ var pairsToProcess = new ConsArray();
+ pairsToProcess.concat([{node: this.root_, param: null}]);
+ while (!pairsToProcess.atEnd()) {
+ var pair = pairsToProcess.next();
+ var node = pair.node;
+ var newParam = f(node, pair.param);
+ var morePairsToProcess = [];
+ node.forEachChild(function (child) {
+ morePairsToProcess.push({node: child, param: newParam}); });
+ pairsToProcess.concat(morePairsToProcess);
+ }
+};
+
+
+/**
+ * Performs an indepth call graph traversal.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} enter A function called
+ * prior to visiting node's children.
+ * @param {function(devtools.profiler.CallTree.Node)} exit A function called
+ * after visiting node's children.
+ */
+devtools.profiler.CallTree.prototype.traverseInDepth = function(enter, exit) {
+ function traverse(node) {
+ enter(node);
+ node.forEachChild(traverse);
+ exit(node);
+ }
+ traverse(this.root_);
+};
+
+
+/**
+ * Constructs a call graph node.
+ *
+ * @param {string} label Node label.
+ * @param {devtools.profiler.CallTree.Node} opt_parent Node parent.
+ */
+devtools.profiler.CallTree.Node = function(label, opt_parent) {
+ this.label = label;
+ this.parent = opt_parent;
+ this.children = {};
+};
+
+
+/**
+ * Node self weight (how many times this node was the last node in
+ * a call path).
+ * @type {number}
+ */
+devtools.profiler.CallTree.Node.prototype.selfWeight = 0;
+
+
+/**
+ * Node total weight (includes weights of all children).
+ * @type {number}
+ */
+devtools.profiler.CallTree.Node.prototype.totalWeight = 0;
+
+
+/**
+ * Adds a child node.
+ *
+ * @param {string} label Child node label.
+ */
+devtools.profiler.CallTree.Node.prototype.addChild = function(label) {
+ var child = new devtools.profiler.CallTree.Node(label, this);
+ this.children[label] = child;
+ return child;
+};
+
+
+/**
+ * Computes node's total weight.
+ */
+devtools.profiler.CallTree.Node.prototype.computeTotalWeight =
+ function() {
+ var totalWeight = this.selfWeight;
+ this.forEachChild(function(child) {
+ totalWeight += child.computeTotalWeight(); });
+ return this.totalWeight = totalWeight;
+};
+
+
+/**
+ * Returns all node's children as an array.
+ */
+devtools.profiler.CallTree.Node.prototype.exportChildren = function() {
+ var result = [];
+ this.forEachChild(function (node) { result.push(node); });
+ return result;
+};
+
+
+/**
+ * Finds an immediate child with the specified label.
+ *
+ * @param {string} label Child node label.
+ */
+devtools.profiler.CallTree.Node.prototype.findChild = function(label) {
+ return this.children[label] || null;
+};
+
+
+/**
+ * Finds an immediate child with the specified label, creates a child
+ * node if necessary.
+ *
+ * @param {string} label Child node label.
+ */
+devtools.profiler.CallTree.Node.prototype.findOrAddChild = function(label) {
+ return this.findChild(label) || this.addChild(label);
+};
+
+
+/**
+ * Calls the specified function for every child.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ */
+devtools.profiler.CallTree.Node.prototype.forEachChild = function(f) {
+ for (var c in this.children) {
+ f(this.children[c]);
+ }
+};
+
+
+/**
+ * Walks up from the current node up to the call tree root.
+ *
+ * @param {function(devtools.profiler.CallTree.Node)} f Visitor function.
+ */
+devtools.profiler.CallTree.Node.prototype.walkUpToRoot = function(f) {
+ for (var curr = this; curr != null; curr = curr.parent) {
+ f(curr);
+ }
+};
+
+
+/**
+ * Tries to find a node with the specified path.
+ *
+ * @param {Array<string>} labels The path.
+ * @param {function(devtools.profiler.CallTree.Node)} opt_f Visitor function.
+ */
+devtools.profiler.CallTree.Node.prototype.descendToChild = function(
+ labels, opt_f) {
+ for (var pos = 0, curr = this; pos < labels.length && curr != null; pos++) {
+ var child = curr.findChild(labels[pos]);
+ if (opt_f) {
+ opt_f(child, pos);
+ }
+ curr = child;
+ }
+ return curr;
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/profile_view.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/profile_view.js
new file mode 100644
index 0000000..bdea631
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/profile_view.js
@@ -0,0 +1,224 @@
+// Copyright 2009 the V8 project authors. 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.
+
+
+// Initlialize namespaces
+var devtools = devtools || {};
+devtools.profiler = devtools.profiler || {};
+
+
+/**
+ * Creates a Profile View builder object.
+ *
+ * @param {number} samplingRate Number of ms between profiler ticks.
+ * @constructor
+ */
+devtools.profiler.ViewBuilder = function(samplingRate) {
+ this.samplingRate = samplingRate;
+};
+
+
+/**
+ * Builds a profile view for the specified call tree.
+ *
+ * @param {devtools.profiler.CallTree} callTree A call tree.
+ * @param {boolean} opt_bottomUpViewWeights Whether remapping
+ * of self weights for a bottom up view is needed.
+ */
+devtools.profiler.ViewBuilder.prototype.buildView = function(
+ callTree, opt_bottomUpViewWeights) {
+ var head;
+ var samplingRate = this.samplingRate;
+ var createViewNode = this.createViewNode;
+ callTree.traverse(function(node, viewParent) {
+ var totalWeight = node.totalWeight * samplingRate;
+ var selfWeight = node.selfWeight * samplingRate;
+ if (opt_bottomUpViewWeights === true) {
+ if (viewParent === head) {
+ selfWeight = totalWeight;
+ } else {
+ selfWeight = 0;
+ }
+ }
+ var viewNode = createViewNode(node.label, totalWeight, selfWeight, head);
+ if (viewParent) {
+ viewParent.addChild(viewNode);
+ } else {
+ head = viewNode;
+ }
+ return viewNode;
+ });
+ var view = this.createView(head);
+ return view;
+};
+
+
+/**
+ * Factory method for a profile view.
+ *
+ * @param {devtools.profiler.ProfileView.Node} head View head node.
+ * @return {devtools.profiler.ProfileView} Profile view.
+ */
+devtools.profiler.ViewBuilder.prototype.createView = function(head) {
+ return new devtools.profiler.ProfileView(head);
+};
+
+
+/**
+ * Factory method for a profile view node.
+ *
+ * @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.
+ * @return {devtools.profiler.ProfileView.Node} Profile view node.
+ */
+devtools.profiler.ViewBuilder.prototype.createViewNode = function(
+ funcName, totalTime, selfTime, head) {
+ return new devtools.profiler.ProfileView.Node(
+ funcName, totalTime, selfTime, head);
+};
+
+
+/**
+ * Creates a Profile View object. It allows to perform sorting
+ * and filtering actions on the profile.
+ *
+ * @param {devtools.profiler.ProfileView.Node} head Head (root) node.
+ * @constructor
+ */
+devtools.profiler.ProfileView = function(head) {
+ this.head = head;
+};
+
+
+/**
+ * Sorts the profile view using the specified sort function.
+ *
+ * @param {function(devtools.profiler.ProfileView.Node,
+ * devtools.profiler.ProfileView.Node):number} sortFunc A sorting
+ * functions. Must comply with Array.sort sorting function requirements.
+ */
+devtools.profiler.ProfileView.prototype.sort = function(sortFunc) {
+ this.traverse(function (node) {
+ node.sortChildren(sortFunc);
+ });
+};
+
+
+/**
+ * Traverses profile view nodes in preorder.
+ *
+ * @param {function(devtools.profiler.ProfileView.Node)} f Visitor function.
+ */
+devtools.profiler.ProfileView.prototype.traverse = function(f) {
+ var nodesToTraverse = new ConsArray();
+ nodesToTraverse.concat([this.head]);
+ while (!nodesToTraverse.atEnd()) {
+ var node = nodesToTraverse.next();
+ f(node);
+ nodesToTraverse.concat(node.children);
+ }
+};
+
+
+/**
+ * Constructs a Profile View node object. Each node object corresponds to
+ * a function call.
+ *
+ * @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.ProfileView.Node = function(
+ internalFuncName, totalTime, selfTime, head) {
+ this.internalFuncName = internalFuncName;
+ this.totalTime = totalTime;
+ this.selfTime = selfTime;
+ this.head = head;
+ this.parent = null;
+ this.children = [];
+};
+
+
+/**
+ * Returns a share of the function's total time in application's total time.
+ */
+devtools.profiler.ProfileView.Node.prototype.__defineGetter__(
+ 'totalPercent',
+ function() { return this.totalTime /
+ (this.head ? this.head.totalTime : this.totalTime) * 100.0; });
+
+
+/**
+ * Returns a share of the function's self time in application's total time.
+ */
+devtools.profiler.ProfileView.Node.prototype.__defineGetter__(
+ 'selfPercent',
+ function() { return this.selfTime /
+ (this.head ? this.head.totalTime : this.totalTime) * 100.0; });
+
+
+/**
+ * Returns a share of the function's total time in its parent's total time.
+ */
+devtools.profiler.ProfileView.Node.prototype.__defineGetter__(
+ 'parentTotalPercent',
+ function() { return this.totalTime /
+ (this.parent ? this.parent.totalTime : this.totalTime) * 100.0; });
+
+
+/**
+ * Adds a child to the node.
+ *
+ * @param {devtools.profiler.ProfileView.Node} node Child node.
+ */
+devtools.profiler.ProfileView.Node.prototype.addChild = function(node) {
+ node.parent = this;
+ this.children.push(node);
+};
+
+
+/**
+ * Sorts all the node's children recursively.
+ *
+ * @param {function(devtools.profiler.ProfileView.Node,
+ * devtools.profiler.ProfileView.Node):number} sortFunc A sorting
+ * functions. Must comply with Array.sort sorting function requirements.
+ */
+devtools.profiler.ProfileView.Node.prototype.sortChildren = function(
+ sortFunc) {
+ this.children.sort(sortFunc);
+};
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/profiler_processor.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/profiler_processor.js
new file mode 100644
index 0000000..3c4778e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/profiler_processor.js
@@ -0,0 +1,395 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @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.
+ */
+goog.provide('devtools.profiler.Processor');
+
+
+/**
+ * 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);
+};
+goog.inherits(devtools.profiler.WebKitViewBuilder,
+ devtools.profiler.ViewBuilder);
+
+
+/**
+ * @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;
+};
+goog.inherits(devtools.profiler.WebKitViewNode,
+ devtools.profiler.ProfileView.Node);
+
+
+/**
+ * RegEx for stripping V8's prefixes of compiled functions.
+ */
+devtools.profiler.WebKitViewNode.FUNC_NAME_STRIP_RE =
+ /^(?:LazyCompile|Function): (.*)$/;
+
+
+/**
+ * RegEx for extracting script source URL and line number.
+ */
+devtools.profiler.WebKitViewNode.FUNC_NAME_PARSE_RE = /^([^ ]+) (.*):(\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];
+ 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);
+};
+goog.inherits(devtools.profiler.JsProfile, devtools.profiler.Profile);
+
+
+/**
+ * RegExp that leaves only JS functions.
+ * @type {RegExp}
+ */
+devtools.profiler.JsProfile.JS_FUNC_RE = /^(LazyCompile|Function|Script):/;
+
+/**
+ * RegExp that filters out native code (ending with "native src.js:xxx").
+ * @type {RegExp}
+ */
+devtools.profiler.JsProfile.JS_NATIVE_FUNC_RE = /\ native\ \w+\.js:\d+$/;
+
+/**
+ * RegExp that filters out native scripts.
+ * @type {RegExp}
+ */
+devtools.profiler.JsProfile.JS_NATIVE_SCRIPT_RE = /^Script:\ native/;
+
+
+/**
+ * @override
+ */
+devtools.profiler.JsProfile.prototype.skipThisFunction = function(name) {
+ return !devtools.profiler.JsProfile.JS_FUNC_RE.test(name) ||
+ // To profile V8's natives comment out two lines below and '||' above.
+ devtools.profiler.JsProfile.JS_NATIVE_FUNC_RE.test(name) ||
+ devtools.profiler.JsProfile.JS_NATIVE_SCRIPT_RE.test(name);
+};
+
+
+/**
+ * Profiler processor. Consumes profiler log and builds profile views.
+ *
+ * @param {function(devtools.profiler.ProfileView)} newProfileCallback Callback
+ * that receives a new processed profile.
+ * @constructor
+ */
+devtools.profiler.Processor = function() {
+ /**
+ * Callback that is called when a new profile is encountered in the log.
+ * @type {function()}
+ */
+ this.startedProfileProcessing_ = 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;
+};
+
+
+/**
+ * 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, finished) {
+ this.startedProfileProcessing_ = started;
+ 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;
+
+
+/**
+ * A dispatch table for V8 profiler event log records.
+ * @private
+ */
+devtools.profiler.Processor.RecordsDispatch_ = {
+ 'code-creation': { parsers: [null, parseInt, parseInt, null],
+ processor: 'processCodeCreation_', needsProfile: true },
+ 'code-move': { parsers: [parseInt, parseInt],
+ processor: 'processCodeMove_', needsProfile: true },
+ 'code-delete': { parsers: [parseInt],
+ processor: 'processCodeDelete_', needsProfile: true },
+ 'tick': { parsers: [parseInt, parseInt, parseInt, 'var-args'],
+ processor: 'processTick_', needsProfile: true },
+ 'profiler': { parsers: [null, 'var-args'], processor: 'processProfiler_',
+ needsProfile: false },
+ // Not used in DevTools Profiler.
+ 'shared-library': null,
+ // Obsolete row types.
+ 'code-allocate': null,
+ 'begin-code-region': null,
+ 'end-code-region': null
+};
+
+
+/**
+ * Sets new profile callback.
+ * @param {function(devtools.profiler.ProfileView)} callback Callback function.
+ */
+devtools.profiler.Processor.prototype.setNewProfileCallback = function(
+ callback) {
+ this.newProfileCallback_ = callback;
+};
+
+
+/**
+ * Processes a portion of V8 profiler event log.
+ *
+ * @param {string} chunk A portion of log.
+ */
+devtools.profiler.Processor.prototype.processLogChunk = function(chunk) {
+ this.processLog_(chunk.split('\n'));
+};
+
+
+/**
+ * Processes a log lines.
+ *
+ * @param {Array<string>} lines Log lines.
+ * @private
+ */
+devtools.profiler.Processor.prototype.processLog_ = function(lines) {
+ var csvParser = new devtools.profiler.CsvParser();
+ try {
+ for (var i = 0, n = lines.length; i < n; ++i) {
+ var line = lines[i];
+ if (!line) {
+ continue;
+ }
+ var fields = csvParser.parseLine(line);
+ this.dispatchLogRow_(fields);
+ }
+ } catch (e) {
+ debugPrint('line ' + (i + 1) + ': ' + (e.message || e));
+ throw e;
+ }
+};
+
+
+/**
+ * Does a dispatch of a log record.
+ *
+ * @param {Array<string>} fields Log record.
+ * @private
+ */
+devtools.profiler.Processor.prototype.dispatchLogRow_ = function(fields) {
+ // Obtain the dispatch.
+ var command = fields[0];
+ if (!(command in devtools.profiler.Processor.RecordsDispatch_)) {
+ throw new Error('unknown command: ' + command);
+ }
+ var dispatch = devtools.profiler.Processor.RecordsDispatch_[command];
+
+ if (dispatch === null ||
+ (dispatch.needsProfile && this.currentProfile_ == null)) {
+ return;
+ }
+
+ // Parse fields.
+ var parsedFields = [];
+ for (var i = 0; i < dispatch.parsers.length; ++i) {
+ var parser = dispatch.parsers[i];
+ if (parser === null) {
+ parsedFields.push(fields[1 + i]);
+ } else if (typeof parser == 'function') {
+ parsedFields.push(parser(fields[1 + i]));
+ } else {
+ // var-args
+ parsedFields.push(fields.slice(1 + i));
+ break;
+ }
+ }
+
+ // Run the processor.
+ this[dispatch.processor].apply(this, parsedFields);
+};
+
+
+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_();
+ }
+ }
+ break;
+ case 'pause':
+ if (this.currentProfile_ != 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;
+ // This event is valid but isn't used.
+ case 'end': break;
+ default:
+ throw new Error('unknown profiler state: ' + state);
+ }
+};
+
+
+devtools.profiler.Processor.prototype.processCodeCreation_ = function(
+ type, start, size, name) {
+ this.currentProfile_.addCode(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.processTick_ = function(
+ pc, sp, vmState, stack) {
+ var fullStack = [pc];
+ for (var i = 0, n = stack.length; i < n; ++i) {
+ var frame = stack[i];
+ // Leave only numbers starting with 0x. Filter possible 'overflow' string.
+ if (frame.charAt(0) == '0') {
+ fullStack.push(parseInt(frame, 16));
+ }
+ }
+ // see the comment for devtools.profiler.Processor.PROGRAM_ENTRY
+ fullStack.push(devtools.profiler.Processor.PROGRAM_ENTRY);
+ this.currentProfile_.recordTick(fullStack);
+};
+
+
+/**
+ * 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/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/splaytree.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/splaytree.js
new file mode 100644
index 0000000..7b3af8b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/splaytree.js
@@ -0,0 +1,322 @@
+// Copyright 2009 the V8 project authors. 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.
+
+
+// A namespace stub. It will become more clear how to declare it properly
+// during integration of this script into Dev Tools.
+var goog = goog || {};
+goog.structs = goog.structs || {};
+
+
+/**
+ * Constructs a Splay tree. A splay tree is a self-balancing binary
+ * search tree with the additional property that recently accessed
+ * elements are quick to access again. It performs basic operations
+ * such as insertion, look-up and removal in O(log(n)) amortized time.
+ *
+ * @constructor
+ */
+goog.structs.SplayTree = function() {
+};
+
+
+/**
+ * Pointer to the root node of the tree.
+ *
+ * @type {goog.structs.SplayTree.Node}
+ * @private
+ */
+goog.structs.SplayTree.prototype.root_ = null;
+
+
+/**
+ * @return {boolean} Whether the tree is empty.
+ */
+goog.structs.SplayTree.prototype.isEmpty = function() {
+ return !this.root_;
+};
+
+
+
+/**
+ * Inserts a node into the tree with the specified key and value if
+ * the tree does not already contain a node with the specified key. If
+ * the value is inserted, it becomes the root of the tree.
+ *
+ * @param {number} key Key to insert into the tree.
+ * @param {*} value Value to insert into the tree.
+ */
+goog.structs.SplayTree.prototype.insert = function(key, value) {
+ if (this.isEmpty()) {
+ this.root_ = new goog.structs.SplayTree.Node(key, value);
+ return;
+ }
+ // Splay on the key to move the last node on the search path for
+ // the key to the root of the tree.
+ this.splay_(key);
+ if (this.root_.key == key) {
+ return;
+ }
+ var node = new goog.structs.SplayTree.Node(key, value);
+ if (key > this.root_.key) {
+ node.left = this.root_;
+ node.right = this.root_.right;
+ this.root_.right = null;
+ } else {
+ node.right = this.root_;
+ node.left = this.root_.left;
+ this.root_.left = null;
+ }
+ this.root_ = node;
+};
+
+
+/**
+ * Removes a node with the specified key from the tree if the tree
+ * contains a node with this key. The removed node is returned. If the
+ * key is not found, an exception is thrown.
+ *
+ * @param {number} key Key to find and remove from the tree.
+ * @return {goog.structs.SplayTree.Node} The removed node.
+ */
+goog.structs.SplayTree.prototype.remove = function(key) {
+ if (this.isEmpty()) {
+ throw Error('Key not found: ' + key);
+ }
+ this.splay_(key);
+ if (this.root_.key != key) {
+ throw Error('Key not found: ' + key);
+ }
+ var removed = this.root_;
+ if (!this.root_.left) {
+ this.root_ = this.root_.right;
+ } else {
+ var right = this.root_.right;
+ this.root_ = this.root_.left;
+ // Splay to make sure that the new root has an empty right child.
+ this.splay_(key);
+ // Insert the original right child as the right child of the new
+ // root.
+ this.root_.right = right;
+ }
+ return removed;
+};
+
+
+/**
+ * Returns the node having the specified key or null if the tree doesn't contain
+ * a node with the specified key.
+ *
+ * @param {number} key Key to find in the tree.
+ * @return {goog.structs.SplayTree.Node} Node having the specified key.
+ */
+goog.structs.SplayTree.prototype.find = function(key) {
+ if (this.isEmpty()) {
+ return null;
+ }
+ this.splay_(key);
+ return this.root_.key == key ? this.root_ : null;
+};
+
+
+/**
+ * @return {goog.structs.SplayTree.Node} Node having the minimum key value.
+ */
+goog.structs.SplayTree.prototype.findMin = function() {
+ if (this.isEmpty()) {
+ return null;
+ }
+ var current = this.root_;
+ while (current.left) {
+ current = current.left;
+ }
+ return current;
+};
+
+
+/**
+ * @return {goog.structs.SplayTree.Node} Node having the maximum key value.
+ */
+goog.structs.SplayTree.prototype.findMax = function(opt_startNode) {
+ if (this.isEmpty()) {
+ return null;
+ }
+ var current = opt_startNode || this.root_;
+ while (current.right) {
+ current = current.right;
+ }
+ return current;
+};
+
+
+/**
+ * @return {goog.structs.SplayTree.Node} Node having the maximum key value that
+ * is less or equal to the specified key value.
+ */
+goog.structs.SplayTree.prototype.findGreatestLessThan = function(key) {
+ if (this.isEmpty()) {
+ return null;
+ }
+ // Splay on the key to move the node with the given key or the last
+ // node on the search path to the top of the tree.
+ this.splay_(key);
+ // Now the result is either the root node or the greatest node in
+ // the left subtree.
+ if (this.root_.key <= key) {
+ return this.root_;
+ } else if (this.root_.left) {
+ return this.findMax(this.root_.left);
+ } else {
+ return null;
+ }
+};
+
+
+/**
+ * @return {Array<*>} An array containing all the values of tree's nodes.
+ */
+goog.structs.SplayTree.prototype.exportValues = function() {
+ var result = [];
+ this.traverse_(function(node) { result.push(node.value); });
+ return result;
+};
+
+
+/**
+ * Perform the splay operation for the given key. Moves the node with
+ * the given key to the top of the tree. If no node has the given
+ * key, the last node on the search path is moved to the top of the
+ * tree. This is the simplified top-down splaying algorithm from:
+ * "Self-adjusting Binary Search Trees" by Sleator and Tarjan
+ *
+ * @param {number} key Key to splay the tree on.
+ * @private
+ */
+goog.structs.SplayTree.prototype.splay_ = function(key) {
+ if (this.isEmpty()) {
+ return;
+ }
+ // Create a dummy node. The use of the dummy node is a bit
+ // counter-intuitive: The right child of the dummy node will hold
+ // the L tree of the algorithm. The left child of the dummy node
+ // will hold the R tree of the algorithm. Using a dummy node, left
+ // and right will always be nodes and we avoid special cases.
+ var dummy, left, right;
+ dummy = left = right = new goog.structs.SplayTree.Node(null, null);
+ var current = this.root_;
+ while (true) {
+ if (key < current.key) {
+ if (!current.left) {
+ break;
+ }
+ if (key < current.left.key) {
+ // Rotate right.
+ var tmp = current.left;
+ current.left = tmp.right;
+ tmp.right = current;
+ current = tmp;
+ if (!current.left) {
+ break;
+ }
+ }
+ // Link right.
+ right.left = current;
+ right = current;
+ current = current.left;
+ } else if (key > current.key) {
+ if (!current.right) {
+ break;
+ }
+ if (key > current.right.key) {
+ // Rotate left.
+ var tmp = current.right;
+ current.right = tmp.left;
+ tmp.left = current;
+ current = tmp;
+ if (!current.right) {
+ break;
+ }
+ }
+ // Link left.
+ left.right = current;
+ left = current;
+ current = current.right;
+ } else {
+ break;
+ }
+ }
+ // Assemble.
+ left.right = current.left;
+ right.left = current.right;
+ current.left = dummy.right;
+ current.right = dummy.left;
+ this.root_ = current;
+};
+
+
+/**
+ * Performs a preorder traversal of the tree.
+ *
+ * @param {function(goog.structs.SplayTree.Node)} f Visitor function.
+ * @private
+ */
+goog.structs.SplayTree.prototype.traverse_ = function(f) {
+ var nodesToVisit = [this.root_];
+ while (nodesToVisit.length > 0) {
+ var node = nodesToVisit.shift();
+ if (node == null) {
+ continue;
+ }
+ f(node);
+ nodesToVisit.push(node.left);
+ nodesToVisit.push(node.right);
+ }
+};
+
+
+/**
+ * Constructs a Splay tree node.
+ *
+ * @param {number} key Key.
+ * @param {*} value Value.
+ */
+goog.structs.SplayTree.Node = function(key, value) {
+ this.key = key;
+ this.value = value;
+};
+
+
+/**
+ * @type {goog.structs.SplayTree.Node}
+ */
+goog.structs.SplayTree.Node.prototype.left = null;
+
+
+/**
+ * @type {goog.structs.SplayTree.Node}
+ */
+goog.structs.SplayTree.Node.prototype.right = null;
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/tests.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/tests.js
new file mode 100644
index 0000000..2507ed6
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/tests.js
@@ -0,0 +1,210 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+/**
+ * @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.
+ */
+
+if (window.domAutomationController) {
+
+
+/**
+ * Test suite for interactive UI tests.
+ * @constructor
+ */
+TestSuite = function() {
+};
+
+
+/**
+ * Reports test failure.
+ * @param {string} message Failure description.
+ */
+TestSuite.prototype.fail = function(message) {
+ throw message;
+};
+
+
+/**
+ * Equals assertion tests that expected == actual.
+ * @param {Object} expected Expected object.
+ * @param {Object} actual Actual object.
+ */
+TestSuite.prototype.assertEquals = function(expected, actual) {
+ if (expected != actual) {
+ this.fail('Expected: "' + expected + '", but was "' + actual + '"');
+ }
+};
+
+
+/**
+ * True assertion tests that value == true.
+ * @param {Object} expected Expected object.
+ * @param {Object} value Actual object.
+ */
+TestSuite.prototype.assertTrue = function(value) {
+ this.assertEquals(true, value);
+};
+
+
+/**
+ * Runs all global functions starting with 'test' as unit tests.
+ */
+TestSuite.prototype.runAllTests = function() {
+ // For debugging purposes.
+ for (var name in this) {
+ if (name.substring(0, 4) == 'test' &&
+ typeof this[name] == 'function') {
+ this.runTest(name);
+ }
+ }
+};
+
+
+/**
+ * Async tests use this one to report that they are completed.
+ */
+TestSuite.prototype.reportOk = function() {
+ window.domAutomationController.send('[OK]');
+};
+
+
+/**
+ * Manual controller for async tests.
+ * @constructor.
+ */
+TestSuite.Controller = function() {
+ this.controlTaken_ = false;
+ this.timerId_ = -1;
+};
+
+
+/**
+ * Takes control over execution.
+ */
+TestSuite.Controller.prototype.takeControl = function() {
+ this.controlTaken_ = true;
+ // Set up guard timer.
+ var self = this;
+ this.timerId_ = setTimeout(function() {
+ self.reportFailure('Timeout exceeded: 20 sec');
+ }, 20000);
+};
+
+
+/**
+ * Async tests use this one to report that they are completed.
+ */
+TestSuite.Controller.prototype.reportOk = function() {
+ if (this.timerId_ != -1) {
+ this.timerId_ = -1;
+ clearTimeout(this.timerId_);
+ }
+ window.domAutomationController.send('[OK]');
+};
+
+
+/**
+ * Async tests use this one to report failures.
+ */
+TestSuite.Controller.prototype.reportFailure = function(error) {
+ if (this.timerId_ != -1) {
+ this.timerId_ = -1;
+ clearTimeout(this.timerId_);
+ }
+ window.domAutomationController.send('[FAILED] ' + error);
+};
+
+
+/**
+ * Runs all global functions starting with 'test' as unit tests.
+ */
+TestSuite.prototype.runTest = function(testName) {
+ var controller = new TestSuite.Controller();
+ try {
+ this[testName](controller);
+ if (!controller.controlTaken_) {
+ controller.reportOk();
+ }
+ } catch (e) {
+ controller.reportFailure(e);
+ }
+};
+
+
+// UI Tests
+
+
+/**
+ * Tests that the real injected host is present in the context.
+ */
+TestSuite.prototype.testHostIsPresent = function() {
+ var domAgent = devtools.tools.getDomAgent();
+ var doc = domAgent.getDocument();
+ this.assertTrue(typeof DevToolsHost == 'object' && !DevToolsHost.isStub);
+ this.assertTrue(!!doc.documentElement);
+};
+
+
+/**
+ * Tests elements tree has an 'HTML' root.
+ */
+TestSuite.prototype.testElementsTreeRoot = function() {
+ var domAgent = devtools.tools.getDomAgent();
+ var doc = domAgent.getDocument();
+ 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(controller) {
+ WebInspector.panels.elements.hide();
+ WebInspector.panels.resources.show();
+
+ var test = this;
+ var oldAddResource = WebInspector.addResource;
+ WebInspector.addResource = function(identifier, payload) {
+ WebInspector.addResource = oldAddResource;
+ oldAddResource.call(this, identifier, payload);
+ test.assertEquals('simple_page.html', payload.lastPathComponent);
+ WebInspector.panels.resources.refresh();
+ WebInspector.resources[identifier]._resourcesTreeElement.select();
+
+ controller.reportOk();
+ };
+
+ // 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.
+ controller.takeControl();
+};
+
+
+var uiTests = new TestSuite();
+
+
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/treeoutline.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/treeoutline.js
new file mode 100644
index 0000000..579e7fb
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/treeoutline.js
@@ -0,0 +1,846 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+function TreeOutline(listNode)
+{
+ this.children = [];
+ this.selectedTreeElement = null;
+ this._childrenListNode = listNode;
+ this._childrenListNode.removeChildren();
+ this._knownTreeElements = [];
+ this._treeElementsExpandedState = [];
+ this.expandTreeElementsWhenArrowing = false;
+ this.root = true;
+ this.hasChildren = false;
+ this.expanded = true;
+ this.selected = false;
+ this.treeOutline = this;
+}
+
+TreeOutline._knownTreeElementNextIdentifier = 1;
+
+TreeOutline._appendChild = function(child)
+{
+ if (!child)
+ throw("child can't be undefined or null");
+
+ var lastChild = this.children[this.children.length - 1];
+ if (lastChild) {
+ lastChild.nextSibling = child;
+ child.previousSibling = lastChild;
+ } else {
+ child.previousSibling = null;
+ child.nextSibling = null;
+ }
+
+ this.children.push(child);
+ this.hasChildren = true;
+ child.parent = this;
+ child.treeOutline = this.treeOutline;
+ child.treeOutline._rememberTreeElement(child);
+
+ var current = child.children[0];
+ while (current) {
+ current.treeOutline = this.treeOutline;
+ current.treeOutline._rememberTreeElement(current);
+ current = current.traverseNextTreeElement(false, child, true);
+ }
+
+ if (child.hasChildren && child.treeOutline._treeElementsExpandedState[child.identifier] !== undefined)
+ child.expanded = child.treeOutline._treeElementsExpandedState[child.identifier];
+
+ if (!this._childrenListNode) {
+ this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
+ this._childrenListNode.parentTreeElement = this;
+ this._childrenListNode.addStyleClass("children");
+ if (this.hidden)
+ this._childrenListNode.addStyleClass("hidden");
+ }
+
+ child._attach();
+}
+
+TreeOutline._insertChild = function(child, index)
+{
+ if (!child)
+ throw("child can't be undefined or null");
+
+ var previousChild = (index > 0 ? this.children[index - 1] : null);
+ if (previousChild) {
+ previousChild.nextSibling = child;
+ child.previousSibling = previousChild;
+ } else {
+ child.previousSibling = null;
+ }
+
+ var nextChild = this.children[index];
+ if (nextChild) {
+ nextChild.previousSibling = child;
+ child.nextSibling = nextChild;
+ } else {
+ child.nextSibling = null;
+ }
+
+ this.children.splice(index, 0, child);
+ this.hasChildren = true;
+ child.parent = this;
+ child.treeOutline = this.treeOutline;
+ child.treeOutline._rememberTreeElement(child);
+
+ var current = child.children[0];
+ while (current) {
+ current.treeOutline = this.treeOutline;
+ current.treeOutline._rememberTreeElement(current);
+ current = current.traverseNextTreeElement(false, child, true);
+ }
+
+ if (child.hasChildren && child.treeOutline._treeElementsExpandedState[child.identifier] !== undefined)
+ child.expanded = child.treeOutline._treeElementsExpandedState[child.identifier];
+
+ if (!this._childrenListNode) {
+ this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
+ this._childrenListNode.parentTreeElement = this;
+ this._childrenListNode.addStyleClass("children");
+ if (this.hidden)
+ this._childrenListNode.addStyleClass("hidden");
+ }
+
+ child._attach();
+}
+
+TreeOutline._removeChildAtIndex = function(childIndex)
+{
+ if (childIndex < 0 || childIndex >= this.children.length)
+ throw("childIndex out of range");
+
+ var child = this.children[childIndex];
+ this.children.splice(childIndex, 1);
+
+ child.deselect();
+
+ if (child.previousSibling)
+ child.previousSibling.nextSibling = child.nextSibling;
+ if (child.nextSibling)
+ child.nextSibling.previousSibling = child.previousSibling;
+
+ if (child.treeOutline) {
+ child.treeOutline._forgetTreeElement(child);
+ child.treeOutline._forgetChildrenRecursive(child);
+ }
+
+ child._detach();
+ child.treeOutline = null;
+ child.parent = null;
+ child.nextSibling = null;
+ child.previousSibling = null;
+}
+
+TreeOutline._removeChild = function(child)
+{
+ if (!child)
+ throw("child can't be undefined or null");
+
+ var childIndex = this.children.indexOf(child);
+ if (childIndex === -1)
+ throw("child not found in this node's children");
+
+ TreeOutline._removeChildAtIndex.call(this, childIndex);
+}
+
+TreeOutline._removeChildren = function()
+{
+ for (var i = 0; i < this.children.length; ++i) {
+ var child = this.children[i];
+ child.deselect();
+
+ if (child.treeOutline) {
+ child.treeOutline._forgetTreeElement(child);
+ child.treeOutline._forgetChildrenRecursive(child);
+ }
+
+ child._detach();
+ child.treeOutline = null;
+ child.parent = null;
+ child.nextSibling = null;
+ child.previousSibling = null;
+ }
+
+ this.children = [];
+}
+
+TreeOutline._removeChildrenRecursive = function()
+{
+ var childrenToRemove = this.children;
+
+ var child = this.children[0];
+ while (child) {
+ if (child.children.length)
+ childrenToRemove = childrenToRemove.concat(child.children);
+ child = child.traverseNextTreeElement(false, this, true);
+ }
+
+ for (var i = 0; i < childrenToRemove.length; ++i) {
+ var child = childrenToRemove[i];
+ child.deselect();
+ if (child.treeOutline)
+ child.treeOutline._forgetTreeElement(child);
+ child._detach();
+ child.children = [];
+ child.treeOutline = null;
+ child.parent = null;
+ child.nextSibling = null;
+ child.previousSibling = null;
+ }
+
+ this.children = [];
+}
+
+TreeOutline.prototype._rememberTreeElement = function(element)
+{
+ if (!this._knownTreeElements[element.identifier])
+ this._knownTreeElements[element.identifier] = [];
+
+ // check if the element is already known
+ var elements = this._knownTreeElements[element.identifier];
+ if (elements.indexOf(element) !== -1)
+ return;
+
+ // add the element
+ elements.push(element);
+}
+
+TreeOutline.prototype._forgetTreeElement = function(element)
+{
+ if (this._knownTreeElements[element.identifier])
+ this._knownTreeElements[element.identifier].remove(element, true);
+}
+
+TreeOutline.prototype._forgetChildrenRecursive = function(parentElement)
+{
+ var child = parentElement.children[0];
+ while (child) {
+ this._forgetTreeElement(child);
+ child = child.traverseNextTreeElement(false, this, true);
+ }
+}
+
+TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent, equal)
+{
+ if (!representedObject)
+ return null;
+
+ if (!equal)
+ equal = function(a, b) { return a === b };
+
+ if ("__treeElementIdentifier" in representedObject) {
+ // If this representedObject has a tree element identifier, and it is a known TreeElement
+ // in our tree we can just return that tree element.
+ var elements = this._knownTreeElements[representedObject.__treeElementIdentifier];
+ if (elements) {
+ for (var i = 0; i < elements.length; ++i)
+ if (equal(elements[i].representedObject, representedObject))
+ return elements[i];
+ }
+ }
+
+ if (!isAncestor || !(isAncestor instanceof Function) || !getParent || !(getParent instanceof Function))
+ return null;
+
+ // The representedObject isn't know, so we start at the top of the tree and work down to find the first
+ // tree element that represents representedObject or one of its ancestors.
+ var item;
+ var found = false;
+ for (var i = 0; i < this.children.length; ++i) {
+ item = this.children[i];
+ if (equal(item.representedObject, representedObject) || isAncestor(item.representedObject, representedObject)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ return null;
+
+ // Make sure the item that we found is connected to the root of the tree.
+ // Build up a list of representedObject's ancestors that aren't already in our tree.
+ var ancestors = [];
+ var currentObject = representedObject;
+ while (currentObject) {
+ ancestors.unshift(currentObject);
+ if (equal(currentObject, item.representedObject))
+ break;
+ currentObject = getParent(currentObject);
+ }
+
+ // For each of those ancestors we populate them to fill in the tree.
+ for (var i = 0; i < ancestors.length; ++i) {
+ // Make sure we don't call findTreeElement with the same representedObject
+ // again, to prevent infinite recursion.
+ if (equal(ancestors[i], representedObject))
+ continue;
+ // FIXME: we could do something faster than findTreeElement since we will know the next
+ // ancestor exists in the tree.
+ item = this.findTreeElement(ancestors[i], isAncestor, getParent, equal);
+ if (item && item.onpopulate)
+ item.onpopulate(item);
+ }
+
+ // Now that all the ancestors are populated, try to find the representedObject again. This time
+ // without the isAncestor and getParent functions to prevent an infinite recursion if it isn't found.
+ return this.findTreeElement(representedObject, null, null, equal);
+}
+
+TreeOutline.prototype.treeElementFromPoint = function(x, y)
+{
+ var node = this._childrenListNode.ownerDocument.elementFromPoint(x, y);
+ var listNode = node.enclosingNodeOrSelfWithNodeNameInArray(["ol", "li"]);
+ if (listNode)
+ return listNode.parentTreeElement || listNode.treeElement;
+ return null;
+}
+
+TreeOutline.prototype.handleKeyEvent = function(event)
+{
+ if (!this.selectedTreeElement || event.shiftKey || event.metaKey || event.ctrlKey)
+ return false;
+
+ var handled = false;
+ var nextSelectedElement;
+ if (event.keyIdentifier === "Up" && !event.altKey) {
+ nextSelectedElement = this.selectedTreeElement.traversePreviousTreeElement(true);
+ while (nextSelectedElement && !nextSelectedElement.selectable)
+ nextSelectedElement = nextSelectedElement.traversePreviousTreeElement(!this.expandTreeElementsWhenArrowing);
+ handled = nextSelectedElement ? true : false;
+ } else if (event.keyIdentifier === "Down" && !event.altKey) {
+ nextSelectedElement = this.selectedTreeElement.traverseNextTreeElement(true);
+ while (nextSelectedElement && !nextSelectedElement.selectable)
+ nextSelectedElement = nextSelectedElement.traverseNextTreeElement(!this.expandTreeElementsWhenArrowing);
+ handled = nextSelectedElement ? true : false;
+ } else if (event.keyIdentifier === "Left") {
+ if (this.selectedTreeElement.expanded) {
+ if (event.altKey)
+ this.selectedTreeElement.collapseRecursively();
+ else
+ this.selectedTreeElement.collapse();
+ handled = true;
+ } else if (this.selectedTreeElement.parent && !this.selectedTreeElement.parent.root) {
+ handled = true;
+ if (this.selectedTreeElement.parent.selectable) {
+ nextSelectedElement = this.selectedTreeElement.parent;
+ handled = nextSelectedElement ? true : false;
+ } else if (this.selectedTreeElement.parent)
+ this.selectedTreeElement.parent.collapse();
+ }
+ } else if (event.keyIdentifier === "Right") {
+ if (!this.selectedTreeElement.revealed()) {
+ this.selectedTreeElement.reveal();
+ handled = true;
+ } else if (this.selectedTreeElement.hasChildren) {
+ handled = true;
+ if (this.selectedTreeElement.expanded) {
+ nextSelectedElement = this.selectedTreeElement.children[0];
+ handled = nextSelectedElement ? true : false;
+ } else {
+ if (event.altKey)
+ this.selectedTreeElement.expandRecursively();
+ else
+ this.selectedTreeElement.expand();
+ }
+ }
+ }
+
+ if (nextSelectedElement) {
+ nextSelectedElement.reveal();
+ nextSelectedElement.select();
+ }
+
+ if (handled) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+
+ return handled;
+}
+
+TreeOutline.prototype.expand = function()
+{
+ // this is the root, do nothing
+}
+
+TreeOutline.prototype.collapse = function()
+{
+ // this is the root, do nothing
+}
+
+TreeOutline.prototype.revealed = function()
+{
+ return true;
+}
+
+TreeOutline.prototype.reveal = function()
+{
+ // this is the root, do nothing
+}
+
+TreeOutline.prototype.appendChild = TreeOutline._appendChild;
+TreeOutline.prototype.insertChild = TreeOutline._insertChild;
+TreeOutline.prototype.removeChild = TreeOutline._removeChild;
+TreeOutline.prototype.removeChildAtIndex = TreeOutline._removeChildAtIndex;
+TreeOutline.prototype.removeChildren = TreeOutline._removeChildren;
+TreeOutline.prototype.removeChildrenRecursive = TreeOutline._removeChildrenRecursive;
+
+function TreeElement(title, representedObject, hasChildren)
+{
+ this._title = title;
+ this.representedObject = (representedObject || {});
+
+ if (this.representedObject.__treeElementIdentifier)
+ this.identifier = this.representedObject.__treeElementIdentifier;
+ else {
+ this.identifier = TreeOutline._knownTreeElementNextIdentifier++;
+ this.representedObject.__treeElementIdentifier = this.identifier;
+ }
+
+ this._hidden = false;
+ this.expanded = false;
+ this.selected = false;
+ this.hasChildren = hasChildren;
+ this.children = [];
+ this.treeOutline = null;
+ this.parent = null;
+ this.previousSibling = null;
+ this.nextSibling = null;
+ this._listItemNode = null;
+}
+
+TreeElement.prototype = {
+ selectable: true,
+ arrowToggleWidth: 10,
+
+ get listItemElement() {
+ return this._listItemNode;
+ },
+
+ get childrenListElement() {
+ return this._childrenListNode;
+ },
+
+ get title() {
+ return this._title;
+ },
+
+ set title(x) {
+ this._title = x;
+ if (this._listItemNode)
+ this._listItemNode.innerHTML = x;
+ },
+
+ get tooltip() {
+ return this._tooltip;
+ },
+
+ set tooltip(x) {
+ this._tooltip = x;
+ if (this._listItemNode)
+ this._listItemNode.title = x ? x : "";
+ },
+
+ get hasChildren() {
+ return this._hasChildren;
+ },
+
+ set hasChildren(x) {
+ if (this._hasChildren === x)
+ return;
+
+ this._hasChildren = x;
+
+ if (!this._listItemNode)
+ return;
+
+ if (x)
+ this._listItemNode.addStyleClass("parent");
+ else {
+ this._listItemNode.removeStyleClass("parent");
+ this.collapse();
+ }
+ },
+
+ get hidden() {
+ return this._hidden;
+ },
+
+ set hidden(x) {
+ if (this._hidden === x)
+ return;
+
+ this._hidden = x;
+
+ if (x) {
+ if (this._listItemNode)
+ this._listItemNode.addStyleClass("hidden");
+ if (this._childrenListNode)
+ this._childrenListNode.addStyleClass("hidden");
+ } else {
+ if (this._listItemNode)
+ this._listItemNode.removeStyleClass("hidden");
+ if (this._childrenListNode)
+ this._childrenListNode.removeStyleClass("hidden");
+ }
+ },
+
+ get shouldRefreshChildren() {
+ return this._shouldRefreshChildren;
+ },
+
+ set shouldRefreshChildren(x) {
+ this._shouldRefreshChildren = x;
+ if (x && this.expanded)
+ this.expand();
+ }
+}
+
+TreeElement.prototype.appendChild = TreeOutline._appendChild;
+TreeElement.prototype.insertChild = TreeOutline._insertChild;
+TreeElement.prototype.removeChild = TreeOutline._removeChild;
+TreeElement.prototype.removeChildAtIndex = TreeOutline._removeChildAtIndex;
+TreeElement.prototype.removeChildren = TreeOutline._removeChildren;
+TreeElement.prototype.removeChildrenRecursive = TreeOutline._removeChildrenRecursive;
+
+TreeElement.prototype._attach = function()
+{
+ if (!this._listItemNode || this.parent._shouldRefreshChildren) {
+ if (this._listItemNode && this._listItemNode.parentNode)
+ this._listItemNode.parentNode.removeChild(this._listItemNode);
+
+ this._listItemNode = this.treeOutline._childrenListNode.ownerDocument.createElement("li");
+ this._listItemNode.treeElement = this;
+ this._listItemNode.innerHTML = this._title;
+ this._listItemNode.title = this._tooltip ? this._tooltip : "";
+
+ if (this.hidden)
+ this._listItemNode.addStyleClass("hidden");
+ if (this.hasChildren)
+ this._listItemNode.addStyleClass("parent");
+ if (this.expanded)
+ this._listItemNode.addStyleClass("expanded");
+ if (this.selected)
+ this._listItemNode.addStyleClass("selected");
+
+ this._listItemNode.addEventListener("mousedown", TreeElement.treeElementSelected, false);
+ this._listItemNode.addEventListener("click", TreeElement.treeElementToggled, false);
+ this._listItemNode.addEventListener("dblclick", TreeElement.treeElementDoubleClicked, false);
+
+ if (this.onattach)
+ this.onattach(this);
+ }
+
+ var nextSibling = null;
+ if (this.nextSibling && this.nextSibling._listItemNode && this.nextSibling._listItemNode.parentNode === this.parent._childrenListNode)
+ nextSibling = this.nextSibling._listItemNode;
+ this.parent._childrenListNode.insertBefore(this._listItemNode, nextSibling);
+ if (this._childrenListNode)
+ this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
+ if (this.selected)
+ this.select();
+ if (this.expanded)
+ this.expand();
+}
+
+TreeElement.prototype._detach = function()
+{
+ if (this._listItemNode && this._listItemNode.parentNode)
+ this._listItemNode.parentNode.removeChild(this._listItemNode);
+ if (this._childrenListNode && this._childrenListNode.parentNode)
+ this._childrenListNode.parentNode.removeChild(this._childrenListNode);
+}
+
+TreeElement.treeElementSelected = function(event)
+{
+ var element = event.currentTarget;
+ if (!element || !element.treeElement || !element.treeElement.selectable)
+ return;
+
+ if (element.treeElement.isEventWithinDisclosureTriangle(event))
+ return;
+
+ element.treeElement.select();
+}
+
+TreeElement.treeElementToggled = function(event)
+{
+ var element = event.currentTarget;
+ if (!element || !element.treeElement)
+ return;
+
+ if (!element.treeElement.isEventWithinDisclosureTriangle(event))
+ return;
+
+ if (element.treeElement.expanded) {
+ if (event.altKey)
+ element.treeElement.collapseRecursively();
+ else
+ element.treeElement.collapse();
+ } else {
+ if (event.altKey)
+ element.treeElement.expandRecursively();
+ else
+ element.treeElement.expand();
+ }
+}
+
+TreeElement.treeElementDoubleClicked = function(event)
+{
+ var element = event.currentTarget;
+ if (!element || !element.treeElement)
+ return;
+
+ if (element.treeElement.ondblclick)
+ element.treeElement.ondblclick(element.treeElement, event);
+ else if (element.treeElement.hasChildren && !element.treeElement.expanded)
+ element.treeElement.expand();
+}
+
+TreeElement.prototype.collapse = function()
+{
+ if (this._listItemNode)
+ this._listItemNode.removeStyleClass("expanded");
+ if (this._childrenListNode)
+ this._childrenListNode.removeStyleClass("expanded");
+
+ this.expanded = false;
+ if (this.treeOutline)
+ this.treeOutline._treeElementsExpandedState[this.identifier] = true;
+
+ if (this.oncollapse)
+ this.oncollapse(this);
+}
+
+TreeElement.prototype.collapseRecursively = function()
+{
+ var item = this;
+ while (item) {
+ if (item.expanded)
+ item.collapse();
+ item = item.traverseNextTreeElement(false, this, true);
+ }
+}
+
+TreeElement.prototype.expand = function()
+{
+ if (!this.hasChildren || (this.expanded && !this._shouldRefreshChildren && this._childrenListNode))
+ return;
+
+ if (this.treeOutline && (!this._childrenListNode || this._shouldRefreshChildren)) {
+ if (this._childrenListNode && this._childrenListNode.parentNode)
+ this._childrenListNode.parentNode.removeChild(this._childrenListNode);
+
+ this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
+ this._childrenListNode.parentTreeElement = this;
+ this._childrenListNode.addStyleClass("children");
+
+ if (this.hidden)
+ this._childrenListNode.addStyleClass("hidden");
+
+ if (this.onpopulate)
+ this.onpopulate(this);
+
+ for (var i = 0; i < this.children.length; ++i)
+ this.children[i]._attach();
+
+ delete this._shouldRefreshChildren;
+ }
+
+ if (this._listItemNode) {
+ this._listItemNode.addStyleClass("expanded");
+ if (this._childrenListNode && this._childrenListNode.parentNode != this._listItemNode.parentNode)
+ this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
+ }
+
+ if (this._childrenListNode)
+ this._childrenListNode.addStyleClass("expanded");
+
+ this.expanded = true;
+ if (this.treeOutline)
+ this.treeOutline._treeElementsExpandedState[this.identifier] = true;
+
+ if (this.onexpand)
+ this.onexpand(this);
+}
+
+TreeElement.prototype.expandRecursively = function(maxDepth)
+{
+ var item = this;
+ var info = {};
+ var depth = 0;
+
+ // The Inspector uses TreeOutlines to represents object properties, so recursive expansion
+ // in some case can be infinite, since JavaScript objects can hold circular references.
+ // So default to a recursion cap of 3 levels, since that gives fairly good results.
+ if (typeof maxDepth === "undefined" || typeof maxDepth === "null")
+ maxDepth = 3;
+
+ while (item) {
+ if (depth < maxDepth)
+ item.expand();
+ item = item.traverseNextTreeElement(false, this, (depth >= maxDepth), info);
+ depth += info.depthChange;
+ }
+}
+
+TreeElement.prototype.hasAncestor = function(ancestor) {
+ if (!ancestor)
+ return false;
+
+ var currentNode = this.parent;
+ while (currentNode) {
+ if (ancestor === currentNode)
+ return true;
+ currentNode = currentNode.parent;
+ }
+
+ return false;
+}
+
+TreeElement.prototype.reveal = function()
+{
+ var currentAncestor = this.parent;
+ while (currentAncestor && !currentAncestor.root) {
+ if (!currentAncestor.expanded)
+ currentAncestor.expand();
+ currentAncestor = currentAncestor.parent;
+ }
+
+ if (this.onreveal)
+ this.onreveal(this);
+}
+
+TreeElement.prototype.revealed = function()
+{
+ var currentAncestor = this.parent;
+ while (currentAncestor && !currentAncestor.root) {
+ if (!currentAncestor.expanded)
+ return false;
+ currentAncestor = currentAncestor.parent;
+ }
+
+ return true;
+}
+
+TreeElement.prototype.select = function(supressOnSelect)
+{
+ if (!this.treeOutline || !this.selectable || this.selected)
+ return;
+
+ if (this.treeOutline.selectedTreeElement)
+ this.treeOutline.selectedTreeElement.deselect();
+
+ this.selected = true;
+ this.treeOutline.selectedTreeElement = this;
+ if (this._listItemNode)
+ this._listItemNode.addStyleClass("selected");
+
+ if (this.onselect && !supressOnSelect)
+ this.onselect(this);
+}
+
+TreeElement.prototype.deselect = function(supressOnDeselect)
+{
+ if (!this.treeOutline || this.treeOutline.selectedTreeElement !== this || !this.selected)
+ return;
+
+ this.selected = false;
+ this.treeOutline.selectedTreeElement = null;
+ if (this._listItemNode)
+ this._listItemNode.removeStyleClass("selected");
+
+ if (this.ondeselect && !supressOnDeselect)
+ this.ondeselect(this);
+}
+
+TreeElement.prototype.traverseNextTreeElement = function(skipHidden, stayWithin, dontPopulate, info)
+{
+ if (!dontPopulate && this.hasChildren && this.onpopulate)
+ this.onpopulate(this);
+
+ if (info)
+ info.depthChange = 0;
+
+ var element = skipHidden ? (this.revealed() ? this.children[0] : null) : this.children[0];
+ if (element && (!skipHidden || (skipHidden && this.expanded))) {
+ if (info)
+ info.depthChange = 1;
+ return element;
+ }
+
+ if (this === stayWithin)
+ return null;
+
+ element = skipHidden ? (this.revealed() ? this.nextSibling : null) : this.nextSibling;
+ if (element)
+ return element;
+
+ element = this;
+ while (element && !element.root && !(skipHidden ? (element.revealed() ? element.nextSibling : null) : element.nextSibling) && element.parent !== stayWithin) {
+ if (info)
+ info.depthChange -= 1;
+ element = element.parent;
+ }
+
+ if (!element)
+ return null;
+
+ return (skipHidden ? (element.revealed() ? element.nextSibling : null) : element.nextSibling);
+}
+
+TreeElement.prototype.traversePreviousTreeElement = function(skipHidden, dontPopulate)
+{
+ var element = skipHidden ? (this.revealed() ? this.previousSibling : null) : this.previousSibling;
+ if (!dontPopulate && element && element.hasChildren && element.onpopulate)
+ element.onpopulate(element);
+
+ while (element && (skipHidden ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.children[element.children.length - 1])) {
+ if (!dontPopulate && element.hasChildren && element.onpopulate)
+ element.onpopulate(element);
+ element = (skipHidden ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.children[element.children.length - 1]);
+ }
+
+ if (element)
+ return element;
+
+ if (!this.parent || this.parent.root)
+ return null;
+
+ return this.parent;
+}
+
+TreeElement.prototype.isEventWithinDisclosureTriangle = function(event)
+{
+ var left = this._listItemNode.totalOffsetLeft;
+ return event.pageX >= left && event.pageX <= left + this.arrowToggleWidth && this.hasChildren;
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/utilities.js b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/utilities.js
new file mode 100644
index 0000000..8fb50e2
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/inspector/utilities.js
@@ -0,0 +1,1136 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+Object.type = function(obj, win)
+{
+ if (obj === null)
+ return "null";
+
+ var type = typeof obj;
+ if (type !== "object" && type !== "function")
+ return type;
+
+ win = win || window;
+
+ if (obj instanceof win.Node)
+ return "node";
+ if (obj instanceof win.String)
+ return "string";
+ if (obj instanceof win.Array)
+ return "array";
+ if (obj instanceof win.Boolean)
+ return "boolean";
+ if (obj instanceof win.Number)
+ return "number";
+ if (obj instanceof win.Date)
+ return "date";
+ if (obj instanceof win.RegExp)
+ return "regexp";
+ if (obj instanceof win.Error)
+ return "error";
+ return type;
+}
+
+Object.hasProperties = function(obj)
+{
+ if (typeof obj === "undefined" || typeof obj === "null")
+ return false;
+ for (var name in obj)
+ return true;
+ return false;
+}
+
+Object.describe = function(obj, abbreviated)
+{
+ var type1 = Object.type(obj);
+ var type2 = Object.prototype.toString.call(obj).replace(/^\[object (.*)\]$/i, "$1");
+
+ switch (type1) {
+ case "object":
+ case "node":
+ return type2;
+ case "array":
+ return "[" + obj.toString() + "]";
+ case "string":
+ if (obj.length > 100)
+ return "\"" + obj.substring(0, 100) + "\u2026\"";
+ return "\"" + obj + "\"";
+ case "function":
+ var objectText = String(obj);
+ if (!/^function /.test(objectText))
+ objectText = (type2 == "object") ? type1 : type2;
+ else if (abbreviated)
+ objectText = /.*/.exec(obj)[0].replace(/ +$/g, "");
+ return objectText;
+ case "regexp":
+ return String(obj).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1);
+ default:
+ return String(obj);
+ }
+}
+
+Object.sortedProperties = function(obj)
+{
+ var properties = [];
+ for (var prop in obj)
+ properties.push(prop);
+ properties.sort();
+ return properties;
+}
+
+Function.prototype.bind = function(thisObject)
+{
+ var func = this;
+ var args = Array.prototype.slice.call(arguments, 1);
+ return function() { return func.apply(thisObject, args.concat(Array.prototype.slice.call(arguments, 0))) };
+}
+
+Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, direction)
+{
+ var startNode;
+ var startOffset = 0;
+ var endNode;
+ var endOffset = 0;
+
+ if (!stayWithinNode)
+ stayWithinNode = this;
+
+ if (!direction || direction === "backward" || direction === "both") {
+ var node = this;
+ while (node) {
+ if (node === stayWithinNode) {
+ if (!startNode)
+ startNode = stayWithinNode;
+ break;
+ }
+
+ if (node.nodeType === Node.TEXT_NODE) {
+ var start = (node === this ? (offset - 1) : (node.nodeValue.length - 1));
+ for (var i = start; i >= 0; --i) {
+ if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
+ startNode = node;
+ startOffset = i + 1;
+ break;
+ }
+ }
+ }
+
+ if (startNode)
+ break;
+
+ node = node.traversePreviousNode(false, stayWithinNode);
+ }
+
+ if (!startNode) {
+ startNode = stayWithinNode;
+ startOffset = 0;
+ }
+ } else {
+ startNode = this;
+ startOffset = offset;
+ }
+
+ if (!direction || direction === "forward" || direction === "both") {
+ node = this;
+ while (node) {
+ if (node === stayWithinNode) {
+ if (!endNode)
+ endNode = stayWithinNode;
+ break;
+ }
+
+ if (node.nodeType === Node.TEXT_NODE) {
+ var start = (node === this ? offset : 0);
+ for (var i = start; i < node.nodeValue.length; ++i) {
+ if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
+ endNode = node;
+ endOffset = i;
+ break;
+ }
+ }
+ }
+
+ if (endNode)
+ break;
+
+ node = node.traverseNextNode(false, stayWithinNode);
+ }
+
+ if (!endNode) {
+ endNode = stayWithinNode;
+ endOffset = stayWithinNode.nodeType === Node.TEXT_NODE ? stayWithinNode.nodeValue.length : stayWithinNode.childNodes.length;
+ }
+ } else {
+ endNode = this;
+ endOffset = offset;
+ }
+
+ var result = this.ownerDocument.createRange();
+ result.setStart(startNode, startOffset);
+ result.setEnd(endNode, endOffset);
+
+ return result;
+}
+
+Element.prototype.removeStyleClass = function(className)
+{
+ // Test for the simple case before using a RegExp.
+ if (this.className === className) {
+ this.className = "";
+ return;
+ }
+
+ this.removeMatchingStyleClasses(className.escapeForRegExp());
+}
+
+Element.prototype.removeMatchingStyleClasses = function(classNameRegex)
+{
+ var regex = new RegExp("(^|\\s+)" + classNameRegex + "($|\\s+)");
+ if (regex.test(this.className))
+ this.className = this.className.replace(regex, " ");
+}
+
+Element.prototype.addStyleClass = function(className)
+{
+ if (className && !this.hasStyleClass(className))
+ this.className += (this.className.length ? " " + className : className);
+}
+
+Element.prototype.hasStyleClass = function(className)
+{
+ if (!className)
+ return false;
+ // Test for the simple case before using a RegExp.
+ if (this.className === className)
+ return true;
+ var regex = new RegExp("(^|\\s)" + className.escapeForRegExp() + "($|\\s)");
+ return regex.test(this.className);
+}
+
+Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray)
+{
+ for (var node = this; node && !objectsAreSame(node, this.ownerDocument); node = node.parentNode)
+ for (var i = 0; i < nameArray.length; ++i)
+ if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase())
+ return node;
+ return null;
+}
+
+Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName)
+{
+ return this.enclosingNodeOrSelfWithNodeNameInArray([nodeName]);
+}
+
+Node.prototype.enclosingNodeOrSelfWithClass = function(className)
+{
+ for (var node = this; node && !objectsAreSame(node, this.ownerDocument); node = node.parentNode)
+ if (node.nodeType === Node.ELEMENT_NODE && node.hasStyleClass(className))
+ return node;
+ return null;
+}
+
+Node.prototype.enclosingNodeWithClass = function(className)
+{
+ if (!this.parentNode)
+ return null;
+ return this.parentNode.enclosingNodeOrSelfWithClass(className);
+}
+
+Element.prototype.query = function(query)
+{
+ return this.ownerDocument.evaluate(query, this, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
+}
+
+Element.prototype.removeChildren = function()
+{
+ while (this.firstChild)
+ this.removeChild(this.firstChild);
+}
+
+Element.prototype.isInsertionCaretInside = function()
+{
+ var selection = window.getSelection();
+ if (!selection.rangeCount || !selection.isCollapsed)
+ return false;
+ var selectionRange = selection.getRangeAt(0);
+ return selectionRange.startContainer === this || selectionRange.startContainer.isDescendant(this);
+}
+
+Element.prototype.__defineGetter__("totalOffsetLeft", function()
+{
+ var total = 0;
+ for (var element = this; element; element = element.offsetParent)
+ total += element.offsetLeft;
+ return total;
+});
+
+Element.prototype.__defineGetter__("totalOffsetTop", function()
+{
+ var total = 0;
+ for (var element = this; element; element = element.offsetParent)
+ total += element.offsetTop;
+ return total;
+});
+
+Element.prototype.firstChildSkippingWhitespace = firstChildSkippingWhitespace;
+Element.prototype.lastChildSkippingWhitespace = lastChildSkippingWhitespace;
+
+Node.prototype.isWhitespace = isNodeWhitespace;
+Node.prototype.nodeTypeName = nodeTypeName;
+Node.prototype.displayName = nodeDisplayName;
+Node.prototype.contentPreview = nodeContentPreview;
+Node.prototype.isAncestor = isAncestorNode;
+Node.prototype.isDescendant = isDescendantNode;
+Node.prototype.firstCommonAncestor = firstCommonNodeAncestor;
+Node.prototype.nextSiblingSkippingWhitespace = nextSiblingSkippingWhitespace;
+Node.prototype.previousSiblingSkippingWhitespace = previousSiblingSkippingWhitespace;
+Node.prototype.traverseNextNode = traverseNextNode;
+Node.prototype.traversePreviousNode = traversePreviousNode;
+Node.prototype.onlyTextChild = onlyTextChild;
+
+String.prototype.hasSubstring = function(string, caseInsensitive)
+{
+ if (!caseInsensitive)
+ return this.indexOf(string) !== -1;
+ return this.match(new RegExp(string.escapeForRegExp(), "i"));
+}
+
+String.prototype.escapeCharacters = function(chars)
+{
+ var foundChar = false;
+ for (var i = 0; i < chars.length; ++i) {
+ if (this.indexOf(chars.charAt(i)) !== -1) {
+ foundChar = true;
+ break;
+ }
+ }
+
+ if (!foundChar)
+ return this;
+
+ var result = "";
+ for (var i = 0; i < this.length; ++i) {
+ if (chars.indexOf(this.charAt(i)) !== -1)
+ result += "\\";
+ result += this.charAt(i);
+ }
+
+ return result;
+}
+
+String.prototype.escapeForRegExp = function()
+{
+ return this.escapeCharacters("^[]{}()\\.$*+?|");
+}
+
+String.prototype.escapeHTML = function()
+{
+ return this.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
+}
+
+String.prototype.collapseWhitespace = function()
+{
+ return this.replace(/[\s\xA0]+/g, " ");
+}
+
+String.prototype.trimLeadingWhitespace = function()
+{
+ return this.replace(/^[\s\xA0]+/g, "");
+}
+
+String.prototype.trimTrailingWhitespace = function()
+{
+ return this.replace(/[\s\xA0]+$/g, "");
+}
+
+String.prototype.trimWhitespace = function()
+{
+ return this.replace(/^[\s\xA0]+|[\s\xA0]+$/g, "");
+}
+
+String.prototype.trimURL = function(baseURLDomain)
+{
+ var result = this.replace(new RegExp("^http[s]?:\/\/", "i"), "");
+ if (baseURLDomain)
+ result = result.replace(new RegExp("^" + baseURLDomain.escapeForRegExp(), "i"), "");
+ return result;
+}
+
+function getStyleTextWithShorthands(style)
+{
+ var cssText = "";
+ var foundProperties = {};
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ var shorthandProperty = style.getPropertyShorthand(individualProperty);
+ var propertyName = (shorthandProperty || individualProperty);
+
+ if (propertyName in foundProperties)
+ continue;
+
+ if (shorthandProperty) {
+ var value = getShorthandValue(style, shorthandProperty);
+ var priority = getShorthandPriority(style, shorthandProperty);
+ } else {
+ var value = style.getPropertyValue(individualProperty);
+ var priority = style.getPropertyPriority(individualProperty);
+ }
+
+ foundProperties[propertyName] = true;
+
+ cssText += propertyName + ": " + value;
+ if (priority)
+ cssText += " !" + priority;
+ cssText += "; ";
+ }
+
+ return cssText;
+}
+
+function getShorthandValue(style, shorthandProperty)
+{
+ var value = style.getPropertyValue(shorthandProperty);
+ if (!value) {
+ // Some shorthands (like border) return a null value, so compute a shorthand value.
+ // FIXME: remove this when http://bugs.webkit.org/show_bug.cgi?id=15823 is fixed.
+
+ var foundProperties = {};
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (individualProperty in foundProperties || style.getPropertyShorthand(individualProperty) !== shorthandProperty)
+ continue;
+
+ var individualValue = style.getPropertyValue(individualProperty);
+ if (style.isPropertyImplicit(individualProperty) || individualValue === "initial")
+ continue;
+
+ foundProperties[individualProperty] = true;
+
+ if (!value)
+ value = "";
+ else if (value.length)
+ value += " ";
+ value += individualValue;
+ }
+ }
+ return value;
+}
+
+function getShorthandPriority(style, shorthandProperty)
+{
+ var priority = style.getPropertyPriority(shorthandProperty);
+ if (!priority) {
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (style.getPropertyShorthand(individualProperty) !== shorthandProperty)
+ continue;
+ priority = style.getPropertyPriority(individualProperty);
+ break;
+ }
+ }
+ return priority;
+}
+
+function getLonghandProperties(style, shorthandProperty)
+{
+ var properties = [];
+ var foundProperties = {};
+
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (individualProperty in foundProperties || style.getPropertyShorthand(individualProperty) !== shorthandProperty)
+ continue;
+ foundProperties[individualProperty] = true;
+ properties.push(individualProperty);
+ }
+
+ return properties;
+}
+
+function getUniqueStyleProperties(style)
+{
+ var properties = [];
+ var foundProperties = {};
+
+ for (var i = 0; i < style.length; ++i) {
+ var property = style[i];
+ if (property in foundProperties)
+ continue;
+ foundProperties[property] = true;
+ properties.push(property);
+ }
+
+ return properties;
+}
+
+function isNodeWhitespace()
+{
+ if (!this || this.nodeType !== Node.TEXT_NODE)
+ return false;
+ if (!this.nodeValue.length)
+ return true;
+ return this.nodeValue.match(/^[\s\xA0]+$/);
+}
+
+function nodeTypeName()
+{
+ if (!this)
+ return "(unknown)";
+
+ switch (this.nodeType) {
+ case Node.ELEMENT_NODE: return "Element";
+ case Node.ATTRIBUTE_NODE: return "Attribute";
+ case Node.TEXT_NODE: return "Text";
+ case Node.CDATA_SECTION_NODE: return "Character Data";
+ case Node.ENTITY_REFERENCE_NODE: return "Entity Reference";
+ case Node.ENTITY_NODE: return "Entity";
+ case Node.PROCESSING_INSTRUCTION_NODE: return "Processing Instruction";
+ case Node.COMMENT_NODE: return "Comment";
+ case Node.DOCUMENT_NODE: return "Document";
+ case Node.DOCUMENT_TYPE_NODE: return "Document Type";
+ case Node.DOCUMENT_FRAGMENT_NODE: return "Document Fragment";
+ case Node.NOTATION_NODE: return "Notation";
+ }
+
+ return "(unknown)";
+}
+
+function nodeDisplayName()
+{
+ if (!this)
+ return "";
+
+ switch (this.nodeType) {
+ case Node.DOCUMENT_NODE:
+ return "Document";
+
+ case Node.ELEMENT_NODE:
+ var name = "<" + this.nodeName.toLowerCase();
+
+ if (this.hasAttributes()) {
+ var value = this.getAttribute("id");
+ if (value)
+ name += " id=\"" + value + "\"";
+ value = this.getAttribute("class");
+ if (value)
+ name += " class=\"" + value + "\"";
+ if (this.nodeName.toLowerCase() === "a") {
+ value = this.getAttribute("name");
+ if (value)
+ name += " name=\"" + value + "\"";
+ value = this.getAttribute("href");
+ if (value)
+ name += " href=\"" + value + "\"";
+ } else if (this.nodeName.toLowerCase() === "img") {
+ value = this.getAttribute("src");
+ if (value)
+ name += " src=\"" + value + "\"";
+ } else if (this.nodeName.toLowerCase() === "iframe") {
+ value = this.getAttribute("src");
+ if (value)
+ name += " src=\"" + value + "\"";
+ } else if (this.nodeName.toLowerCase() === "input") {
+ value = this.getAttribute("name");
+ if (value)
+ name += " name=\"" + value + "\"";
+ value = this.getAttribute("type");
+ if (value)
+ name += " type=\"" + value + "\"";
+ } else if (this.nodeName.toLowerCase() === "form") {
+ value = this.getAttribute("action");
+ if (value)
+ name += " action=\"" + value + "\"";
+ }
+ }
+
+ return name + ">";
+
+ case Node.TEXT_NODE:
+ if (isNodeWhitespace.call(this))
+ return "(whitespace)";
+ return "\"" + this.nodeValue + "\"";
+
+ case Node.COMMENT_NODE:
+ return "<!--" + this.nodeValue + "-->";
+
+ case Node.DOCUMENT_TYPE_NODE:
+ var docType = "<!DOCTYPE " + this.nodeName;
+ if (this.publicId) {
+ docType += " PUBLIC \"" + this.publicId + "\"";
+ if (this.systemId)
+ docType += " \"" + this.systemId + "\"";
+ } else if (this.systemId)
+ docType += " SYSTEM \"" + this.systemId + "\"";
+ if (this.internalSubset)
+ docType += " [" + this.internalSubset + "]";
+ return docType + ">";
+ }
+
+ return this.nodeName.toLowerCase().collapseWhitespace();
+}
+
+function nodeContentPreview()
+{
+ if (!this || !this.hasChildNodes || !this.hasChildNodes())
+ return "";
+
+ var limit = 0;
+ var preview = "";
+
+ // always skip whitespace here
+ var currentNode = traverseNextNode.call(this, true, this);
+ while (currentNode) {
+ if (currentNode.nodeType === Node.TEXT_NODE)
+ preview += currentNode.nodeValue.escapeHTML();
+ else
+ preview += nodeDisplayName.call(currentNode).escapeHTML();
+
+ currentNode = traverseNextNode.call(currentNode, true, this);
+
+ if (++limit > 4) {
+ preview += "&#x2026;"; // ellipsis
+ break;
+ }
+ }
+
+ return preview.collapseWhitespace();
+}
+
+function objectsAreSame(a, b)
+{
+ // FIXME: Make this more generic so is works with any wrapped object, not just nodes.
+ // This function is used to compare nodes that might be JSInspectedObjectWrappers, since
+ // JavaScript equality is not true for JSInspectedObjectWrappers of the same node wrapped
+ // with different global ExecStates, we use isSameNode to compare them.
+ if (a === b)
+ return true;
+ if (!a || !b)
+ return false;
+ if (a.isSameNode && b.isSameNode)
+ return a.isSameNode(b);
+ return false;
+}
+
+function isAncestorNode(ancestor)
+{
+ if (!this || !ancestor)
+ return false;
+
+ var currentNode = ancestor.parentNode;
+ while (currentNode) {
+ if (objectsAreSame(this, currentNode))
+ return true;
+ currentNode = currentNode.parentNode;
+ }
+
+ return false;
+}
+
+function isDescendantNode(descendant)
+{
+ return isAncestorNode.call(descendant, this);
+}
+
+function firstCommonNodeAncestor(node)
+{
+ if (!this || !node)
+ return;
+
+ var node1 = this.parentNode;
+ var node2 = node.parentNode;
+
+ if ((!node1 || !node2) || !objectsAreSame(node1, node2))
+ return null;
+
+ while (node1 && node2) {
+ if (!node1.parentNode || !node2.parentNode)
+ break;
+ if (!objectsAreSame(node1, node2))
+ break;
+
+ node1 = node1.parentNode;
+ node2 = node2.parentNode;
+ }
+
+ return node1;
+}
+
+function nextSiblingSkippingWhitespace()
+{
+ if (!this)
+ return;
+ var node = this.nextSibling;
+ while (node && node.nodeType === Node.TEXT_NODE && isNodeWhitespace.call(node))
+ node = node.nextSibling;
+ return node;
+}
+
+function previousSiblingSkippingWhitespace()
+{
+ if (!this)
+ return;
+ var node = this.previousSibling;
+ while (node && node.nodeType === Node.TEXT_NODE && isNodeWhitespace.call(node))
+ node = node.previousSibling;
+ return node;
+}
+
+function firstChildSkippingWhitespace()
+{
+ if (!this)
+ return;
+ var node = this.firstChild;
+ while (node && node.nodeType === Node.TEXT_NODE && isNodeWhitespace.call(node))
+ node = nextSiblingSkippingWhitespace.call(node);
+ return node;
+}
+
+function lastChildSkippingWhitespace()
+{
+ if (!this)
+ return;
+ var node = this.lastChild;
+ while (node && node.nodeType === Node.TEXT_NODE && isNodeWhitespace.call(node))
+ node = previousSiblingSkippingWhitespace.call(node);
+ return node;
+}
+
+function traverseNextNode(skipWhitespace, stayWithin)
+{
+ if (!this)
+ return;
+
+ var node = skipWhitespace ? firstChildSkippingWhitespace.call(this) : this.firstChild;
+ if (node)
+ return node;
+
+ if (stayWithin && objectsAreSame(this, stayWithin))
+ return null;
+
+ node = skipWhitespace ? nextSiblingSkippingWhitespace.call(this) : this.nextSibling;
+ if (node)
+ return node;
+
+ node = this;
+ while (node && !(skipWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling) && (!stayWithin || !node.parentNode || !objectsAreSame(node.parentNode, stayWithin)))
+ node = node.parentNode;
+ if (!node)
+ return null;
+
+ return skipWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling;
+}
+
+function traversePreviousNode(skipWhitespace, stayWithin)
+{
+ if (!this)
+ return;
+ if (stayWithin && objectsAreSame(this, stayWithin))
+ return null;
+ var node = skipWhitespace ? previousSiblingSkippingWhitespace.call(this) : this.previousSibling;
+ while (node && (skipWhitespace ? lastChildSkippingWhitespace.call(node) : node.lastChild) )
+ node = skipWhitespace ? lastChildSkippingWhitespace.call(node) : node.lastChild;
+ if (node)
+ return node;
+ return this.parentNode;
+}
+
+function onlyTextChild(ignoreWhitespace)
+{
+ if (!this)
+ return null;
+
+ var firstChild = ignoreWhitespace ? firstChildSkippingWhitespace.call(this) : this.firstChild;
+ if (!firstChild || firstChild.nodeType !== Node.TEXT_NODE)
+ return null;
+
+ var sibling = ignoreWhitespace ? nextSiblingSkippingWhitespace.call(firstChild) : firstChild.nextSibling;
+ return sibling ? null : firstChild;
+}
+
+function nodeTitleInfo(hasChildren, linkify)
+{
+ var info = {title: "", hasChildren: hasChildren};
+
+ switch (this.nodeType) {
+ case Node.DOCUMENT_NODE:
+ info.title = "Document";
+ break;
+
+ case Node.ELEMENT_NODE:
+ info.title = "<span class=\"webkit-html-tag\">&lt;" + this.nodeName.toLowerCase().escapeHTML();
+
+ if (this.hasAttributes()) {
+ for (var i = 0; i < this.attributes.length; ++i) {
+ var attr = this.attributes[i];
+ info.title += " <span class=\"webkit-html-attribute\"><span class=\"webkit-html-attribute-name\">" + attr.name.escapeHTML() + "</span>=&#8203;\"";
+
+ var value = attr.value;
+ if (linkify && (attr.name === "src" || attr.name === "href")) {
+ var value = value.replace(/([\/;:\)\]\}])/g, "$1\u200B");
+ info.title += linkify(attr.value, value, "webkit-html-attribute-value", this.nodeName.toLowerCase() == "a");
+ } else {
+ var value = value.escapeHTML();
+ value = value.replace(/([\/;:\)\]\}])/g, "$1&#8203;");
+ info.title += "<span class=\"webkit-html-attribute-value\">" + value + "</span>";
+ }
+ info.title += "\"</span>";
+ }
+ }
+ info.title += "&gt;</span>&#8203;";
+
+ // If this element only has a single child that is a text node,
+ // just show that text and the closing tag inline rather than
+ // create a subtree for them
+
+ var textChild = onlyTextChild.call(this, Preferences.ignoreWhitespace);
+ var showInlineText = textChild && textChild.textContent.length < Preferences.maxInlineTextChildLength;
+
+ if (showInlineText) {
+ info.title += "<span class=\"webkit-html-text-node\">" + textChild.nodeValue.escapeHTML() + "</span>&#8203;<span class=\"webkit-html-tag\">&lt;/" + this.nodeName.toLowerCase().escapeHTML() + "&gt;</span>";
+ info.hasChildren = false;
+ }
+ break;
+
+ case Node.TEXT_NODE:
+ if (isNodeWhitespace.call(this))
+ info.title = "(whitespace)";
+ else
+ info.title = "\"<span class=\"webkit-html-text-node\">" + this.nodeValue.escapeHTML() + "</span>\"";
+ break
+
+ case Node.COMMENT_NODE:
+ info.title = "<span class=\"webkit-html-comment\">&lt;!--" + this.nodeValue.escapeHTML() + "--&gt;</span>";
+ break;
+
+ case Node.DOCUMENT_TYPE_NODE:
+ info.title = "<span class=\"webkit-html-doctype\">&lt;!DOCTYPE " + this.nodeName;
+ if (this.publicId) {
+ info.title += " PUBLIC \"" + this.publicId + "\"";
+ if (this.systemId)
+ info.title += " \"" + this.systemId + "\"";
+ } else if (this.systemId)
+ info.title += " SYSTEM \"" + this.systemId + "\"";
+ if (this.internalSubset)
+ info.title += " [" + this.internalSubset + "]";
+ info.title += "&gt;</span>";
+ break;
+ default:
+ info.title = this.nodeName.toLowerCase().collapseWhitespace().escapeHTML();
+ }
+
+ return info;
+}
+
+function getDocumentForNode(node) {
+ return node.nodeType == Node.DOCUMENT_NODE ? node : node.ownerDocument;
+}
+
+function parentNodeOrFrameElement(node) {
+ var parent = node.parentNode;
+ if (parent)
+ return parent;
+
+ return getDocumentForNode(node).defaultView.frameElement;
+}
+
+function isAncestorIncludingParentFrames(a, b) {
+ if (objectsAreSame(a, b))
+ return false;
+ for (var node = b; node; node = getDocumentForNode(node).defaultView.frameElement)
+ if (objectsAreSame(a, node) || isAncestorNode.call(a, node))
+ return true;
+ return false;
+}
+
+Number.secondsToString = function(seconds, formatterFunction, higherResolution)
+{
+ if (!formatterFunction)
+ formatterFunction = String.sprintf;
+
+ var ms = seconds * 1000;
+ if (higherResolution && ms < 1000)
+ return formatterFunction("%.3fms", ms);
+ else if (ms < 1000)
+ return formatterFunction("%.0fms", ms);
+
+ if (seconds < 60)
+ return formatterFunction("%.2fs", seconds);
+
+ var minutes = seconds / 60;
+ if (minutes < 60)
+ return formatterFunction("%.1fmin", minutes);
+
+ var hours = minutes / 60;
+ if (hours < 24)
+ return formatterFunction("%.1fhrs", hours);
+
+ var days = hours / 24;
+ return formatterFunction("%.1f days", days);
+}
+
+Number.bytesToString = function(bytes, formatterFunction)
+{
+ if (!formatterFunction)
+ formatterFunction = String.sprintf;
+
+ if (bytes < 1024)
+ return formatterFunction("%.0fB", bytes);
+
+ var kilobytes = bytes / 1024;
+ if (kilobytes < 1024)
+ return formatterFunction("%.2fKB", kilobytes);
+
+ var megabytes = kilobytes / 1024;
+ return formatterFunction("%.3fMB", megabytes);
+}
+
+Number.constrain = function(num, min, max)
+{
+ if (num < min)
+ num = min;
+ else if (num > max)
+ num = max;
+ return num;
+}
+
+HTMLTextAreaElement.prototype.moveCursorToEnd = function()
+{
+ var length = this.value.length;
+ this.setSelectionRange(length, length);
+}
+
+Array.prototype.remove = function(value, onlyFirst)
+{
+ if (onlyFirst) {
+ var index = this.indexOf(value);
+ if (index !== -1)
+ this.splice(index, 1);
+ return;
+ }
+
+ var length = this.length;
+ for (var i = 0; i < length; ++i) {
+ if (this[i] === value)
+ this.splice(i, 1);
+ }
+}
+
+function insertionIndexForObjectInListSortedByFunction(anObject, aList, aFunction)
+{
+ // indexOf returns (-lowerBound - 1). Taking (-result - 1) works out to lowerBound.
+ return (-indexOfObjectInListSortedByFunction(anObject, aList, aFunction) - 1);
+}
+
+function indexOfObjectInListSortedByFunction(anObject, aList, aFunction)
+{
+ var first = 0;
+ var last = aList.length - 1;
+ var floor = Math.floor;
+ var mid, c;
+
+ while (first <= last) {
+ mid = floor((first + last) / 2);
+ c = aFunction(anObject, aList[mid]);
+
+ if (c > 0)
+ first = mid + 1;
+ else if (c < 0)
+ last = mid - 1;
+ else {
+ // Return the first occurance of an item in the list.
+ while (mid > 0 && aFunction(anObject, aList[mid - 1]) === 0)
+ mid--;
+ first = mid;
+ break;
+ }
+ }
+
+ // By returning 1 less than the negative lower search bound, we can reuse this function
+ // for both indexOf and insertionIndexFor, with some simple arithmetic.
+ return (-first - 1);
+}
+
+String.sprintf = function(format)
+{
+ return String.vsprintf(format, Array.prototype.slice.call(arguments, 1));
+}
+
+String.tokenizeFormatString = function(format)
+{
+ var tokens = [];
+ var substitutionIndex = 0;
+
+ function addStringToken(str)
+ {
+ tokens.push({ type: "string", value: str });
+ }
+
+ function addSpecifierToken(specifier, precision, substitutionIndex)
+ {
+ tokens.push({ type: "specifier", specifier: specifier, precision: precision, substitutionIndex: substitutionIndex });
+ }
+
+ var index = 0;
+ for (var precentIndex = format.indexOf("%", index); precentIndex !== -1; precentIndex = format.indexOf("%", index)) {
+ addStringToken(format.substring(index, precentIndex));
+ index = precentIndex + 1;
+
+ if (format[index] === "%") {
+ addStringToken("%");
+ ++index;
+ continue;
+ }
+
+ if (!isNaN(format[index])) {
+ // The first character is a number, it might be a substitution index.
+ var number = parseInt(format.substring(index));
+ while (!isNaN(format[index]))
+ ++index;
+ // If the number is greater than zero and ends with a "$",
+ // then this is a substitution index.
+ if (number > 0 && format[index] === "$") {
+ substitutionIndex = (number - 1);
+ ++index;
+ }
+ }
+
+ var precision = -1;
+ if (format[index] === ".") {
+ // This is a precision specifier. If no digit follows the ".",
+ // then the precision should be zero.
+ ++index;
+ precision = parseInt(format.substring(index));
+ if (isNaN(precision))
+ precision = 0;
+ while (!isNaN(format[index]))
+ ++index;
+ }
+
+ addSpecifierToken(format[index], precision, substitutionIndex);
+
+ ++substitutionIndex;
+ ++index;
+ }
+
+ addStringToken(format.substring(index));
+
+ return tokens;
+}
+
+String.standardFormatters = {
+ d: function(substitution)
+ {
+ substitution = parseInt(substitution);
+ return !isNaN(substitution) ? substitution : 0;
+ },
+
+ f: function(substitution, token)
+ {
+ substitution = parseFloat(substitution);
+ if (substitution && token.precision > -1)
+ substitution = substitution.toFixed(token.precision);
+ return !isNaN(substitution) ? substitution : (token.precision > -1 ? Number(0).toFixed(token.precision) : 0);
+ },
+
+ s: function(substitution)
+ {
+ return substitution;
+ },
+};
+
+String.vsprintf = function(format, substitutions)
+{
+ return String.format(format, substitutions, String.standardFormatters, "", function(a, b) { return a + b; }).formattedResult;
+}
+
+String.format = function(format, substitutions, formatters, initialValue, append)
+{
+ if (!format || !substitutions || !substitutions.length)
+ return { formattedResult: append(initialValue, format), unusedSubstitutions: substitutions };
+
+ function prettyFunctionName()
+ {
+ return "String.format(\"" + format + "\", \"" + substitutions.join("\", \"") + "\")";
+ }
+
+ function warn(msg)
+ {
+ console.warn(prettyFunctionName() + ": " + msg);
+ }
+
+ function error(msg)
+ {
+ console.error(prettyFunctionName() + ": " + msg);
+ }
+
+ var result = initialValue;
+ var tokens = String.tokenizeFormatString(format);
+ var usedSubstitutionIndexes = {};
+
+ for (var i = 0; i < tokens.length; ++i) {
+ var token = tokens[i];
+
+ if (token.type === "string") {
+ result = append(result, token.value);
+ continue;
+ }
+
+ if (token.type !== "specifier") {
+ error("Unknown token type \"" + token.type + "\" found.");
+ continue;
+ }
+
+ if (token.substitutionIndex >= substitutions.length) {
+ // If there are not enough substitutions for the current substitutionIndex
+ // just output the format specifier literally and move on.
+ error("not enough substitution arguments. Had " + substitutions.length + " but needed " + (token.substitutionIndex + 1) + ", so substitution was skipped.");
+ result = append(result, "%" + (token.precision > -1 ? token.precision : "") + token.specifier);
+ continue;
+ }
+
+ usedSubstitutionIndexes[token.substitutionIndex] = true;
+
+ if (!(token.specifier in formatters)) {
+ // Encountered an unsupported format character, treat as a string.
+ warn("unsupported format character \u201C" + token.specifier + "\u201D. Treating as a string.");
+ result = append(result, substitutions[token.substitutionIndex]);
+ continue;
+ }
+
+ result = append(result, formatters[token.specifier](substitutions[token.substitutionIndex], token));
+ }
+
+ var unusedSubstitutions = [];
+ for (var i = 0; i < substitutions.length; ++i) {
+ if (i in usedSubstitutionIndexes)
+ continue;
+ unusedSubstitutions.push(substitutions[i]);
+ }
+
+ return { formattedResult: result, unusedSubstitutions: unusedSubstitutions };
+}
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/linkCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/linkCursor.png
new file mode 100644
index 0000000..e5e2749
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/linkCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/missingImage.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/missingImage.png
new file mode 100644
index 0000000..5c24d20
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/missingImage.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/moveCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/moveCursor.png
new file mode 100644
index 0000000..4ca8d70
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/moveCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/nav.pdf b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/nav.pdf
new file mode 100644
index 0000000..9edaaa4
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/nav.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/newtab.pdf b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/newtab.pdf
new file mode 100644
index 0000000..b348a49
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/newtab.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/noDropCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/noDropCursor.png
new file mode 100644
index 0000000..54463fc
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/noDropCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/noneCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/noneCursor.png
new file mode 100644
index 0000000..bd1ff35
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/noneCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northEastResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northEastResizeCursor.png
new file mode 100644
index 0000000..0e89639
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northEastResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northEastSouthWestResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northEastSouthWestResizeCursor.png
new file mode 100644
index 0000000..9904c7b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northEastSouthWestResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northResizeCursor.png
new file mode 100644
index 0000000..0d020db
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northSouthResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northSouthResizeCursor.png
new file mode 100644
index 0000000..92400e9
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northSouthResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northWestResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northWestResizeCursor.png
new file mode 100644
index 0000000..6723f61
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northWestResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northWestSouthEastResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northWestSouthEastResizeCursor.png
new file mode 100644
index 0000000..b8de34c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/northWestSouthEastResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/notAllowedCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/notAllowedCursor.png
new file mode 100644
index 0000000..f3a5f4d
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/notAllowedCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_globe.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_globe.png
new file mode 100644
index 0000000..0fc4331
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_globe.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_history.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_history.png
new file mode 100644
index 0000000..72af696
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_history.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_more.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_more.png
new file mode 100644
index 0000000..61dfd29
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_more.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_search.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_search.png
new file mode 100644
index 0000000..441001e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_search.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_star.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_star.png
new file mode 100644
index 0000000..5919bb7b
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/o2_star.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/progressCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/progressCursor.png
new file mode 100644
index 0000000..25d7021
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/progressCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/reload.pdf b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/reload.pdf
new file mode 100644
index 0000000..907b0be
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/reload.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/renderer.sb b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/renderer.sb
new file mode 100644
index 0000000..baa851c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/renderer.sb
@@ -0,0 +1,28 @@
+;;
+;; Copyright (c) 2009 The Chromium Authors. All rights reserved.
+;; Use of this source code is governed by a BSD-style license that can be
+;; found in the LICENSE file.
+;;
+(version 1)
+(deny default)
+
+; Needed for full-page-zoomed checkboxes etc -- http://crbug.com/11325
+(allow sysctl-read)
+
+
+; Each line is marked with the System version that needs it.
+; This profile is tested with the following system versions:
+; 10.5.6, 10.6 seed release
+
+; Allow following symlinks
+(allow file-read-metadata) ; 10.5.6
+; Allow reading files out of /System/Library
+(allow file-read-data (regex #"^/System/Library")) ; 10.5.6
+
+; Needed for Fonts
+(allow mach-lookup (global-name "com.apple.FontObjectsServer")) ; 10.5.6
+(allow mach-lookup (global-name "com.apple.FontServer")) ; 10.6 seed release
+(allow file-read-data (regex #"^/Library/Fonts")) ; 10.6 seed release
+
+; Needed for IPC on 10.6
+(allow ipc-posix-shm)
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/sadtab.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/sadtab.png
new file mode 100644
index 0000000..4421311
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/sadtab.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/southEastResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/southEastResizeCursor.png
new file mode 100644
index 0000000..415aa633
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/southEastResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/southResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/southResizeCursor.png
new file mode 100644
index 0000000..60cf722
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/southResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/southWestResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/southWestResizeCursor.png
new file mode 100644
index 0000000..8dc5cdc
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/southWestResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/star.pdf b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/star.pdf
new file mode 100644
index 0000000..25dd2dd
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/star.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/starred.pdf b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/starred.pdf
new file mode 100644
index 0000000..693a05a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/starred.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/stop.pdf b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/stop.pdf
new file mode 100644
index 0000000..4bc5ff7
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/stop.pdf
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/theme.pak b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/theme.pak
new file mode 100644
index 0000000..7e14675
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/theme.pak
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/throbber.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/throbber.png
new file mode 100644
index 0000000..6ca1fdd
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/throbber.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/throbber_waiting.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/throbber_waiting.png
new file mode 100644
index 0000000..c36e929
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/throbber_waiting.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/verticalTextCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/verticalTextCursor.png
new file mode 100644
index 0000000..0f2877c
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/verticalTextCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/waitCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/waitCursor.png
new file mode 100644
index 0000000..91412b8
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/waitCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/westResizeCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/westResizeCursor.png
new file mode 100644
index 0000000..544439a
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/westResizeCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/zoomInCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/zoomInCursor.png
new file mode 100644
index 0000000..feec9bc
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/zoomInCursor.png
Binary files differ
diff --git a/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/zoomOutCursor.png b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/zoomOutCursor.png
new file mode 100644
index 0000000..f4a954e
--- /dev/null
+++ b/chrome/tools/test/reference_build/chrome_mac/Google Chrome.app/Contents/Resources/zoomOutCursor.png
Binary files differ