diff options
author | slightlyoff@chromium.org <slightlyoff@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-24 05:11:58 +0000 |
---|---|---|
committer | slightlyoff@chromium.org <slightlyoff@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-24 05:11:58 +0000 |
commit | f781782dd67077478e117c61dca4ea5eefce3544 (patch) | |
tree | 4801f724123cfdcbb69c4e7fe40a565b331723ae /chrome_frame/tools | |
parent | 63cf4759efa2373e33436fb5df6849f930081226 (diff) | |
download | chromium_src-f781782dd67077478e117c61dca4ea5eefce3544.zip chromium_src-f781782dd67077478e117c61dca4ea5eefce3544.tar.gz chromium_src-f781782dd67077478e117c61dca4ea5eefce3544.tar.bz2 |
Initial import of the Chrome Frame codebase. Integration in chrome.gyp coming in a separate CL.
BUG=None
TEST=None
Review URL: http://codereview.chromium.org/218019
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27042 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/tools')
276 files changed, 35493 insertions, 0 deletions
diff --git a/chrome_frame/tools/test/page_cycler/cf_cycler.py b/chrome_frame/tools/test/page_cycler/cf_cycler.py new file mode 100644 index 0000000..fd49ae8 --- /dev/null +++ b/chrome_frame/tools/test/page_cycler/cf_cycler.py @@ -0,0 +1,99 @@ +# 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.
+
+"""Automates IE to visit a list of web sites while running CF in full tab mode.
+
+The page cycler automates IE and navigates it to a series of URLs. It is
+designed to be run with Chrome Frame configured to load every URL inside
+CF full tab mode.
+
+TODO(robertshield): Make use of the python unittest module as per
+review comments.
+"""
+
+import optparse
+import sys
+import time
+import win32com.client
+import win32gui
+
+def LoadSiteList(path):
+ """Loads a list of URLs from |path|.
+
+ Expects the URLs to be separated by newlines, with no leading or trailing
+ whitespace.
+
+ Args:
+ path: The path to a file containing a list of new-line separated URLs.
+
+ Returns:
+ A list of strings, each one a URL.
+ """
+ f = open(path)
+ urls = f.readlines()
+ f.close()
+ return urls
+
+def LaunchIE():
+ """Starts up IE, makes it visible and returns the automation object.
+
+ Returns:
+ The IE automation object.
+ """
+ ie = win32com.client.Dispatch("InternetExplorer.Application")
+ ie.visible = 1
+ win32gui.SetForegroundWindow(ie.HWND)
+ return ie
+
+def RunTest(url, ie):
+ """Loads |url| into the InternetExplorer.Application instance in |ie|.
+
+ Waits for the Document object to be created and then waits for
+ the document ready state to reach READYSTATE_COMPLETE.
+ Args:
+ url: A string containing the url to navigate to.
+ ie: The IE automation object to navigate.
+ """
+
+ print "Navigating to " + url
+ ie.Navigate(url)
+ timer = 0
+
+ READYSTATE_COMPLETE = 4
+
+ last_ready_state = -1
+ for retry in xrange(60):
+ try:
+ # TODO(robertshield): Become an event sink instead of polling for
+ # changes to the ready state.
+ last_ready_state = ie.Document.ReadyState
+ if last_ready_state == READYSTATE_COMPLETE:
+ break
+ except:
+ # TODO(robertshield): Find the precise exception related to ie.Document
+ # being not accessible and handle it here.
+ print "Unexpected error:", sys.exc_info()[0]
+ raise
+ time.sleep(1)
+
+ if last_ready_state != READYSTATE_COMPLETE:
+ print "Timeout waiting for " + url
+
+def main():
+ parser = optparse.OptionParser()
+ parser.add_option('-u', '--url_list', default='urllist',
+ help='The path to the list of URLs')
+ (opts, args) = parser.parse_args()
+
+ urls = LoadSiteList(opts.url_list)
+ ie = LaunchIE()
+ for url in urls:
+ RunTest(url, ie)
+ time.sleep(1)
+ ie.visible = 0
+ ie.Quit()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chrome_frame/tools/test/page_cycler/urllist b/chrome_frame/tools/test/page_cycler/urllist new file mode 100644 index 0000000..3242774 --- /dev/null +++ b/chrome_frame/tools/test/page_cycler/urllist @@ -0,0 +1,500 @@ +http://www.yahoo.com +http://www.msn.com +http://www.google.com +http://www.youtube.com +http://www.live.com +http://www.myspace.com +http://www.baidu.com +http://www.orkut.com +http://www.wikipedia.org +http://www.qq.com +http://www.yahoo.co.jp +http://www.microsoft.com +http://www.megaupload.com +http://www.sina.com.cn +http://www.hi5.com +http://www.blogger.com +http://www.facebook.com +http://www.rapidshare.com +http://www.ebay.com +http://www.fotolog.net +http://www.friendster.com +http://www.sohu.com +http://www.163.com +http://www.google.co.uk +http://www.mail.ru +http://www.google.fr +http://www.google.com.br +http://www.google.de +http://www.passport.net +http://www.taobao.com +http://www.amazon.com +http://www.skyblog.com +http://www.yahoo.com.cn +http://www.google.cl +http://www.bbc.co.uk +http://www.google.es +http://www.google.cn +http://www.google.pl +http://www.imdb.com +http://www.tom.com +http://www.yandex.ru +http://www.wretch.cc +http://www.google.co.jp +http://www.uol.com.br +http://www.flickr.com +http://www.photobucket.com +http://www.craigslist.org +http://www.go.com +http://www.onet.pl +http://www.imageshack.us +http://www.google.com.sa +http://www.google.com.mx +http://www.aol.com +http://www.google.com.tr +http://www.dailymotion.com +http://www.allegro.pl +http://www.rambler.ru +http://www.fc2.com +http://www.xunlei.com +http://www.ebay.co.uk +http://www.google.com.ar +http://www.google.ca +http://www.seznam.cz +http://www.mixi.jp +http://www.free.fr +http://www.imagevenue.com +http://www.google.com.pe +http://www.google.it +http://www.google.co.in +http://www.terra.com.br +http://www.cnn.com +http://www.livejournal.com +http://www.skyrock.com +http://www.ebay.de +http://www.geocities.com +http://www.adultfriendfinder.com +http://www.wp.pl +http://www.googlesyndication.com +http://www.adobe.com +http://www.google.co.ve +http://www.bebo.com +http://www.xanga.com +http://www.globo.com +http://www.google.com.co +http://www.google.com.eg +http://www.one.lt +http://www.wordpress.com +http://www.rakuten.co.jp +http://www.uwants.com +http://www.sendspace.com +http://www.apple.com +http://www.google.com.vn +http://www.discuss.com.hk +http://www.deviantart.com +http://www.digg.com +http://www.tagged.com +http://www.livedoor.com +http://www.vnexpress.net +http://www.eastmoney.com +http://www.soso.com +http://www.starware.com +http://www.badongo.com +http://www.google.co.th +http://www.naver.com +http://www.rediff.com +http://www.iwiw.hu +http://www.icq.com +http://www.vnet.cn +http://www.ig.com.br +http://www.badoo.com +http://www.alibaba.com +http://www.google.com.au +http://www.maktoob.com +http://www.newsgroup.la +http://www.about.com +http://www.download.com +http://www.kooora.com +http://www.google.co.il +http://www.comcast.net +http://www.google.nl +http://www.google.be +http://www.megarotic.com +http://www.sexyono.com +http://www.sourceforge.net +http://www.walla.co.il +http://www.fotka.pl +http://www.pchome.com.tw +http://www.theplanet.com +http://www.google.ae +http://www.orange.fr +http://www.interia.pl +http://www.invisionfree.com +http://www.rapidshare.de +http://www.tudou.com +http://www.statcounter.com +http://www.56.com +http://www.netlog.com +http://www.4shared.com +http://www.mywebsearch.com +http://www.digitalpoint.com +http://www.mininova.org +http://www.dantri.com.vn +http://www.126.com +http://www.goo.ne.jp +http://www.dell.com +http://www.google.co.hu +http://www.google.pt +http://www.information.com +http://www.youporn.com +http://www.metacafe.com +http://www.google.lt +http://www.google.ro +http://www.nba.com +http://www.metroflog.com +http://www.miniclip.com +http://www.cnet.com +http://www.sogou.com +http://www.ebay.fr +http://www.weather.com +http://www.depositfiles.com +http://www.hp.com +http://www.google.ru +http://www.51.com +http://www.infoseek.co.jp +http://www.linkedin.com +http://www.gmx.net +http://www.xinhuanet.com +http://www.narod.ru +http://www.multiply.com +http://www.pomoho.com +http://www.nytimes.com +http://www.yourfilehost.com +http://www.gamespot.com +http://www.typepad.com +http://www.ask.com +http://www.89.com +http://www.geocities.jp +http://www.yam.com +http://www.neopets.com +http://www.mercadolivre.com.br +http://www.centrum.cz +http://www.mapquest.com +http://www.univision.com +http://www.zol.com.cn +http://www.veoh.com +http://www.amazon.co.jp +http://www.6park.com +http://www.24h.com.vn +http://www.china.com +http://www.minijuegos.com +http://www.sh3bwah.com +http://www.mop.com +http://www.miarroba.com +http://www.tianya.cn +http://www.ign.com +http://www.technorati.com +http://www.yesky.com +http://www.pornotube.com +http://www.google.hr +http://www.cmfu.com +http://www.aebn.net +http://www.mynet.com +http://www.nifty.com +http://www.livejasmin.com +http://www.wwe.com +http://www.daum.net +http://www.nastydollars.com +http://www.filefront.com +http://www.bangbros1.com +http://www.doubleclick.com +http://www.torrentspy.com +http://www.zaycev.net +http://www.chinaren.com +http://www.youku.com +http://www.altavista.com +http://www.spiegel.de +http://www.icio.us +http://www.hinet.net +http://www.anonym.to +http://www.usercash.com +http://www.gamer.com.tw +http://www.sapo.pt +http://www.2ch.net +http://www.tripod.com +http://www.reference.com +http://www.blogchina.com +http://www.piczo.com +http://www.startimes2.com +http://www.zshare.net +http://www.uusee.com +http://www.dada.net +http://www.amazon.co.uk +http://www.panet.co.il +http://www.6rb.com +http://www.smileycentral.com +http://www.juggcrew.com +http://www.liveinternet.ru +http://www.google.com.my +http://www.mercadolibre.com.ar +http://www.sakura.ne.jp +http://www.gamefaqs.com +http://www.jrj.com.cn +http://www.fanfiction.net +http://www.libero.it +http://www.google.se +http://www.milliyet.com.tr +http://www.imeem.com +http://www.archive.org +http://www.mediafire.com +http://www.google.com.sg +http://www.blogfa.com +http://www.filefactory.com +http://www.softonic.com +http://www.homeway.com.cn +http://www.google.com.tw +http://www.pconline.com.cn +http://www.blog.cz +http://www.symantec.com +http://www.biglobe.ne.jp +http://www.mlb.com +http://www.webshots.com +http://www.hatena.ne.jp +http://www.phoenixtv.com +http://www.google.co.cr +http://www.nate.com +http://www.google.gr +http://www.mobile.de +http://www.pornaccess.com +http://www.ynet.co.il +http://www.amazon.de +http://www.imagefap.com +http://www.whenu.com +http://www.vietnamnet.vn +http://www.ebay.it +http://www.hurriyet.com.tr +http://www.freewebs.com +http://www.tuoitre.com.vn +http://www.php.net +http://www.broadcaster.com +http://www.google.at +http://www.xnxx.com +http://www.studiverzeichnis.com +http://www.elmundo.es +http://www.it168.com +http://www.lide.cz +http://www.wikimedia.org +http://www.wefong.com +http://www.mercadolibre.com.mx +http://www.thepiratebay.org +http://www.istockphoto.com +http://www.sanook.com +http://www.petardas.com +http://www.answers.com +http://www.no-ip.com +http://www.match.com +http://www.ebay.com.au +http://www.payserve.com +http://www.soufun.com +http://www.flurl.com +http://www.alice.it +http://www.globalsearch.cz +http://www.888.com +http://www.isohunt.com +http://www.poco.cn +http://www.ameblo.jp +http://www.heise.de +http://www.6rbtop.com +http://www.google.co.id +http://www.godaddy.com +http://www.google.fi +http://www.bala.com.cn +http://www.break.com +http://www.stumbleupon.com +http://www.feedburner.com +http://www.ngoisao.net +http://www.atnext.com +http://www.screensavers.com +http://www.17173.com +http://www.domaintools.com +http://www.nih.gov +http://www.novinky.cz +http://www.freeones.com +http://www.last.fm +http://www.skype.com +http://www.google.bg +http://www.21cn.com +http://www.o2.pl +http://www.musica.com +http://www.pplive.com +http://www.hkjc.com +http://www.grono.net +http://www.bramjnet.com +http://www.adbrite.com +http://www.divx.com +http://www.pcpop.com +http://www.verycd.com +http://www.cnfol.com +http://www.google.ch +http://www.myway.com +http://www.wangyou.com +http://www.gazeta.pl +http://www.milta1980.co.uk +http://www.prizee.com +http://www.livescore.com +http://www.facebox.com +http://www.overture.com +http://www.google.com.ua +http://www.cartoonnetwork.com +http://www.nicovideo.jp +http://www.ku6.com +http://www.it.com.cn +http://www.one.lv +http://www.t-online.de +http://www.kooxoo.com +http://www.super.cz +http://www.google.co.ma +http://www.xuite.net +http://www.qihoo.com +http://www.freelotto.com +http://www.sedoparking.com +http://www.monografias.com +http://www.dmoz.org +http://www.foxsports.com +http://www.mocxi.com +http://www.google.sk +http://www.as7apcool.com +http://www.igw.net.sa +http://www.slide.com +http://www.zhanzuo.com +http://www.idnes.cz +http://www.mobile9.com +http://www.hawaaworld.com +http://www.aljazeera.net +http://www.nana.co.il +http://www.seesaa.net +http://www.51job.com +http://www.abv.bg +http://www.paipai.com +http://www.real.com +http://www.cctv.com +http://www.tv.com +http://www.terra.cl +http://www.google.com.ph +http://www.wannawatch.com +http://www.thottbot.com +http://www.4399.com +http://www.5show.com +http://www.vkontakte.ru +http://www.cricinfo.com +http://www.hyves.nl +http://www.google.ie +http://www.cnnic.cn +http://www.tinypic.com +http://www.forumer.com +http://www.demonoid.com +http://www.ouou.com +http://www.mozilla.com +http://www.naukri.com +http://www.volam.com.vn +http://www.torrentz.com +http://www.google.co.za +http://www.google.jo +http://www.dvd4arab.com +http://www.msn.ca +http://www.clarin.com +http://www.rincondelvago.com +http://www.dmm.co.jp +http://www.1ting.com +http://www.everythinggirl.com +http://www.freemail.hu +http://www.xtube.com +http://www.4399.net +http://www.ocn.ne.jp +http://www.aweber.com +http://www.monster.com +http://www.chinaz.com +http://www.careerbuilder.com +http://www.megaclick.com +http://www.jeeran.com +http://www.w3.org +http://www.uume.com +http://www.sitepoint.com +http://www.people.com.cn +http://www.google.com.uy +http://www.mybloglog.com +http://www.9you.com +http://www.ebay.com.cn +http://www.zedo.com +http://www.juegosjuegos.com +http://www.sweetim.com +http://www.ikea.com +http://www.walmart.com +http://www.earthlink.net +http://www.turboupload.com +http://www.crunchyroll.com +http://www.google.com.bh +http://www.flogao.com.br +http://www.usps.com +http://www.6arab.com +http://www.target.com +http://www.wordreference.com +http://www.perfspot.com +http://www.gigasize.com +http://www.mercadolibre.com.ve +http://www.stockstar.com +http://www.3721.com +http://www.upspiral.com +http://www.clubbox.co.kr +http://www.trademe.co.nz +http://www.nokia.com +http://www.met-art.com +http://www.ppstream.com +http://www.ibm.com +http://www.qianlong.com +http://www.softpedia.com +http://www.adultadworld.com +http://www.webmasterworld.com +http://www.ifolder.ru +http://www.mofile.com +http://www.delfi.lt +http://www.sina.com.hk +http://www.google.com.bo +http://www.excite.co.jp +http://www.myfreepaysite.com +http://www.ev1servers.net +http://www.dyndns.org +http://www.wordpress.org +http://www.drivecleaner.com +http://www.google.co.nz +http://www.people.com +http://www.expedia.com +http://www.sonyericsson.com +http://www.msn.com.cn +http://www.hubotv.com +http://www.bangbros.com +http://www.mediaplex.com +http://www.google.com.qa +http://www.videosz.com +http://www.leo.org +http://www.atlas.cz +http://www.kinghost.com +http://www.aljayyash.net +http://www.irc-galleria.net +http://www.xiaonei.com +http://www.nnm.ru +http://www.tv-links.co.uk +http://www.indiatimes.com +http://www.icbc.com.cn +http://www.draugiem.lv +http://www.6rooms.com +http://www.hc360.com +http://www.focus.cn +http://www.atdmt.com +http://www.chilewarez.org +http://www.tripadvisor.com +http://www.mcanime.net +http://www.esnips.com +http://www.chinamobile.com +http://www.ebay.ca +http://www.im.tv diff --git a/chrome_frame/tools/test/reference_build/chrome/First Run b/chrome_frame/tools/test/reference_build/chrome/First Run new file mode 100644 index 0000000..852ad16 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/First Run @@ -0,0 +1 @@ +krome
diff --git a/chrome_frame/tools/test/reference_build/chrome/avcodec-52.dll b/chrome_frame/tools/test/reference_build/chrome/avcodec-52.dll Binary files differnew file mode 100644 index 0000000..9b55506 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/avcodec-52.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/avformat-52.dll b/chrome_frame/tools/test/reference_build/chrome/avformat-52.dll Binary files differnew file mode 100644 index 0000000..33d3dcf --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/avformat-52.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/avutil-50.dll b/chrome_frame/tools/test/reference_build/chrome/avutil-50.dll Binary files differnew file mode 100644 index 0000000..63f4d2d --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/avutil-50.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/chrome.dll b/chrome_frame/tools/test/reference_build/chrome/chrome.dll Binary files differnew file mode 100644 index 0000000..bc17fe4 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/chrome.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/chrome.exe b/chrome_frame/tools/test/reference_build/chrome/chrome.exe Binary files differnew file mode 100644 index 0000000..040fbaa --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/chrome.exe diff --git a/chrome_frame/tools/test/reference_build/chrome/chrome_dll.pdb b/chrome_frame/tools/test/reference_build/chrome/chrome_dll.pdb Binary files differnew file mode 100644 index 0000000..203f157 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/chrome_dll.pdb diff --git a/chrome_frame/tools/test/reference_build/chrome/chrome_exe.pdb b/chrome_frame/tools/test/reference_build/chrome/chrome_exe.pdb Binary files differnew file mode 100644 index 0000000..5d79f8b --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/chrome_exe.pdb diff --git a/chrome_frame/tools/test/reference_build/chrome/crash_service.exe b/chrome_frame/tools/test/reference_build/chrome/crash_service.exe Binary files differnew file mode 100644 index 0000000..1eac8ee --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/crash_service.exe diff --git a/chrome_frame/tools/test/reference_build/chrome/gears.dll b/chrome_frame/tools/test/reference_build/chrome/gears.dll Binary files differnew file mode 100644 index 0000000..db6d864 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/gears.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/icudt42.dll b/chrome_frame/tools/test/reference_build/chrome/icudt42.dll Binary files differnew file mode 100644 index 0000000..40a49c1 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/icudt42.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/ar.dll b/chrome_frame/tools/test/reference_build/chrome/locales/ar.dll Binary files differnew file mode 100644 index 0000000..d925ac3 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/ar.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/bg.dll b/chrome_frame/tools/test/reference_build/chrome/locales/bg.dll Binary files differnew file mode 100644 index 0000000..90d4933 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/bg.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/bn.dll b/chrome_frame/tools/test/reference_build/chrome/locales/bn.dll Binary files differnew file mode 100644 index 0000000..3364aaa --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/bn.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/ca.dll b/chrome_frame/tools/test/reference_build/chrome/locales/ca.dll Binary files differnew file mode 100644 index 0000000..9d8a07a --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/ca.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/cs.dll b/chrome_frame/tools/test/reference_build/chrome/locales/cs.dll Binary files differnew file mode 100644 index 0000000..c4b5d1c --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/cs.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/da.dll b/chrome_frame/tools/test/reference_build/chrome/locales/da.dll Binary files differnew file mode 100644 index 0000000..239cf00 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/da.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/de.dll b/chrome_frame/tools/test/reference_build/chrome/locales/de.dll Binary files differnew file mode 100644 index 0000000..44da5d3 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/de.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/el.dll b/chrome_frame/tools/test/reference_build/chrome/locales/el.dll Binary files differnew file mode 100644 index 0000000..4afbade --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/el.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/en-GB.dll b/chrome_frame/tools/test/reference_build/chrome/locales/en-GB.dll Binary files differnew file mode 100644 index 0000000..a3cc174 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/en-GB.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/en-US.dll b/chrome_frame/tools/test/reference_build/chrome/locales/en-US.dll Binary files differnew file mode 100644 index 0000000..6b4db3c --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/en-US.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/es-419.dll b/chrome_frame/tools/test/reference_build/chrome/locales/es-419.dll Binary files differnew file mode 100644 index 0000000..58ee8bc --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/es-419.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/es.dll b/chrome_frame/tools/test/reference_build/chrome/locales/es.dll Binary files differnew file mode 100644 index 0000000..96168ad --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/es.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/et.dll b/chrome_frame/tools/test/reference_build/chrome/locales/et.dll Binary files differnew file mode 100644 index 0000000..237750df --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/et.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/fi.dll b/chrome_frame/tools/test/reference_build/chrome/locales/fi.dll Binary files differnew file mode 100644 index 0000000..579a2a2 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/fi.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/fil.dll b/chrome_frame/tools/test/reference_build/chrome/locales/fil.dll Binary files differnew file mode 100644 index 0000000..12cc22e --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/fil.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/fr.dll b/chrome_frame/tools/test/reference_build/chrome/locales/fr.dll Binary files differnew file mode 100644 index 0000000..87003ac --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/fr.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/gu.dll b/chrome_frame/tools/test/reference_build/chrome/locales/gu.dll Binary files differnew file mode 100644 index 0000000..0fdc291 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/gu.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/he.dll b/chrome_frame/tools/test/reference_build/chrome/locales/he.dll Binary files differnew file mode 100644 index 0000000..332fa93 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/he.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/hi.dll b/chrome_frame/tools/test/reference_build/chrome/locales/hi.dll Binary files differnew file mode 100644 index 0000000..1eee966 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/hi.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/hr.dll b/chrome_frame/tools/test/reference_build/chrome/locales/hr.dll Binary files differnew file mode 100644 index 0000000..debe9d0 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/hr.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/hu.dll b/chrome_frame/tools/test/reference_build/chrome/locales/hu.dll Binary files differnew file mode 100644 index 0000000..8f6a8c2 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/hu.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/id.dll b/chrome_frame/tools/test/reference_build/chrome/locales/id.dll Binary files differnew file mode 100644 index 0000000..3c78bcc --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/id.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/it.dll b/chrome_frame/tools/test/reference_build/chrome/locales/it.dll Binary files differnew file mode 100644 index 0000000..25c39f7 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/it.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/ja.dll b/chrome_frame/tools/test/reference_build/chrome/locales/ja.dll Binary files differnew file mode 100644 index 0000000..1378e47 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/ja.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/kn.dll b/chrome_frame/tools/test/reference_build/chrome/locales/kn.dll Binary files differnew file mode 100644 index 0000000..6154988 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/kn.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/ko.dll b/chrome_frame/tools/test/reference_build/chrome/locales/ko.dll Binary files differnew file mode 100644 index 0000000..bbe62ed --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/ko.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/lt.dll b/chrome_frame/tools/test/reference_build/chrome/locales/lt.dll Binary files differnew file mode 100644 index 0000000..fd9069e --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/lt.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/lv.dll b/chrome_frame/tools/test/reference_build/chrome/locales/lv.dll Binary files differnew file mode 100644 index 0000000..a402aec --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/lv.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/ml.dll b/chrome_frame/tools/test/reference_build/chrome/locales/ml.dll Binary files differnew file mode 100644 index 0000000..6902ead --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/ml.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/mr.dll b/chrome_frame/tools/test/reference_build/chrome/locales/mr.dll Binary files differnew file mode 100644 index 0000000..d63aafe --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/mr.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/nb.dll b/chrome_frame/tools/test/reference_build/chrome/locales/nb.dll Binary files differnew file mode 100644 index 0000000..7043aa6 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/nb.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/nl.dll b/chrome_frame/tools/test/reference_build/chrome/locales/nl.dll Binary files differnew file mode 100644 index 0000000..52fbf1d --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/nl.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/or.dll b/chrome_frame/tools/test/reference_build/chrome/locales/or.dll Binary files differnew file mode 100644 index 0000000..34428ad --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/or.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/pl.dll b/chrome_frame/tools/test/reference_build/chrome/locales/pl.dll Binary files differnew file mode 100644 index 0000000..2836731 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/pl.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/pt-BR.dll b/chrome_frame/tools/test/reference_build/chrome/locales/pt-BR.dll Binary files differnew file mode 100644 index 0000000..5aa52e8 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/pt-BR.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/pt-PT.dll b/chrome_frame/tools/test/reference_build/chrome/locales/pt-PT.dll Binary files differnew file mode 100644 index 0000000..cc523c9 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/pt-PT.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/ro.dll b/chrome_frame/tools/test/reference_build/chrome/locales/ro.dll Binary files differnew file mode 100644 index 0000000..0ee4d70 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/ro.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/ru.dll b/chrome_frame/tools/test/reference_build/chrome/locales/ru.dll Binary files differnew file mode 100644 index 0000000..3fbfcfe --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/ru.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/sk.dll b/chrome_frame/tools/test/reference_build/chrome/locales/sk.dll Binary files differnew file mode 100644 index 0000000..da49806 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/sk.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/sl.dll b/chrome_frame/tools/test/reference_build/chrome/locales/sl.dll Binary files differnew file mode 100644 index 0000000..186d2f0 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/sl.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/sr.dll b/chrome_frame/tools/test/reference_build/chrome/locales/sr.dll Binary files differnew file mode 100644 index 0000000..9278069 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/sr.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/sv.dll b/chrome_frame/tools/test/reference_build/chrome/locales/sv.dll Binary files differnew file mode 100644 index 0000000..29ff6bf --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/sv.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/ta.dll b/chrome_frame/tools/test/reference_build/chrome/locales/ta.dll Binary files differnew file mode 100644 index 0000000..711739a --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/ta.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/te.dll b/chrome_frame/tools/test/reference_build/chrome/locales/te.dll Binary files differnew file mode 100644 index 0000000..5468bed --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/te.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/th.dll b/chrome_frame/tools/test/reference_build/chrome/locales/th.dll Binary files differnew file mode 100644 index 0000000..bb41ca2 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/th.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/tr.dll b/chrome_frame/tools/test/reference_build/chrome/locales/tr.dll Binary files differnew file mode 100644 index 0000000..5a9333c --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/tr.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/uk.dll b/chrome_frame/tools/test/reference_build/chrome/locales/uk.dll Binary files differnew file mode 100644 index 0000000..830904a --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/uk.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/vi.dll b/chrome_frame/tools/test/reference_build/chrome/locales/vi.dll Binary files differnew file mode 100644 index 0000000..3c3c425 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/vi.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/zh-CN.dll b/chrome_frame/tools/test/reference_build/chrome/locales/zh-CN.dll Binary files differnew file mode 100644 index 0000000..0a09475 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/zh-CN.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/locales/zh-TW.dll b/chrome_frame/tools/test/reference_build/chrome/locales/zh-TW.dll Binary files differnew file mode 100644 index 0000000..237c46c --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/locales/zh-TW.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/mini_installer.pdb b/chrome_frame/tools/test/reference_build/chrome/mini_installer.pdb Binary files differnew file mode 100644 index 0000000..111f61d --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/mini_installer.pdb diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/BottomUpProfileDataGridTree.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/BottomUpProfileDataGridTree.js new file mode 100644 index 0000000..89b4ddc --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/Breakpoint.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Breakpoint.js new file mode 100644 index 0000000..292975a --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Breakpoint.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.Breakpoint = function(url, line, sourceID, condition) +{ + this.url = url; + this.line = line; + this.sourceID = sourceID; + this._enabled = true; + this._sourceText = ""; + this._condition = condition || ""; +} + +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"); + }, + + get sourceText() + { + return this._sourceText; + }, + + set sourceText(text) + { + this._sourceText = text; + this.dispatchEventToListeners("text-changed"); + }, + + get label() + { + var displayName = (this.url ? WebInspector.displayNameForURL(this.url) : WebInspector.UIString("(program)")); + return displayName + ":" + this.line; + }, + + get id() + { + return this.sourceID + ":" + this.line; + }, + + get condition() + { + return this._condition; + }, + + set condition(c) + { + c = c || ""; + if (this._condition === c) + return; + + this._condition = c; + this.dispatchEventToListeners("condition-changed"); + + if (this.enabled) + InspectorController.updateBreakpoint(this.sourceID, this.line, c); + } +} + +WebInspector.Breakpoint.prototype.__proto__ = WebInspector.Object.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/BreakpointsSidebarPane.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/BreakpointsSidebarPane.js new file mode 100644 index 0000000..e6edece --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/BreakpointsSidebarPane.js @@ -0,0 +1,167 @@ +/* + * 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.listElement = document.createElement("ol"); + this.listElement.className = "breakpoint-list"; + + 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) + { + if (this.breakpoints[breakpoint.id]) + return; + + this.breakpoints[breakpoint.id] = breakpoint; + + breakpoint.addEventListener("enabled", this._breakpointEnableChanged, this); + breakpoint.addEventListener("disabled", this._breakpointEnableChanged, this); + breakpoint.addEventListener("text-changed", this._breakpointTextChanged, this); + + this._appendBreakpointElement(breakpoint); + + if (this.emptyElement.parentElement) { + this.bodyElement.removeChild(this.emptyElement); + this.bodyElement.appendChild(this.listElement); + } + + if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID) + return; + + if (breakpoint.enabled) + InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.condition); + }, + + _appendBreakpointElement: function(breakpoint) + { + function checkboxClicked() + { + breakpoint.enabled = !breakpoint.enabled; + } + + function labelClicked() + { + var script = WebInspector.panels.scripts.scriptOrResourceForID(breakpoint.sourceID); + if (script) + WebInspector.panels.scripts.showScript(script, breakpoint.line); + } + + var breakpointElement = document.createElement("li"); + breakpoint._breakpointListElement = breakpointElement; + breakpointElement._breakpointObject = breakpoint; + + var checkboxElement = document.createElement("input"); + checkboxElement.className = "checkbox-elem"; + checkboxElement.type = "checkbox"; + checkboxElement.checked = breakpoint.enabled; + checkboxElement.addEventListener("click", checkboxClicked, false); + breakpointElement.appendChild(checkboxElement); + + var labelElement = document.createElement("a"); + labelElement.textContent = breakpoint.label; + labelElement.addEventListener("click", labelClicked, false); + breakpointElement.appendChild(labelElement); + + var sourceTextElement = document.createElement("div"); + sourceTextElement.textContent = breakpoint.sourceText; + sourceTextElement.className = "source-text"; + breakpointElement.appendChild(sourceTextElement); + + var currentElement = this.listElement.firstChild; + while (currentElement) { + var currentBreak = currentElement._breakpointObject; + if (currentBreak.url > breakpoint.url) { + this.listElement.insertBefore(breakpointElement, currentElement); + return; + } else if (currentBreak.url == breakpoint.url && currentBreak.line > breakpoint.line) { + this.listElement.insertBefore(breakpointElement, currentElement); + return; + } + currentElement = currentElement.nextSibling; + } + this.listElement.appendChild(breakpointElement); + }, + + removeBreakpoint: function(breakpoint) + { + if (!this.breakpoints[breakpoint.id]) + return; + delete this.breakpoints[breakpoint.id]; + + breakpoint.removeEventListener("enabled", null, this); + breakpoint.removeEventListener("disabled", null, this); + breakpoint.removeEventListener("text-changed", null, this); + + var element = breakpoint._breakpointListElement; + element.parentElement.removeChild(element); + + if (!this.listElement.firstChild) { + this.bodyElement.removeChild(this.listElement); + this.bodyElement.appendChild(this.emptyElement); + } + + if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID) + return; + + InspectorController.removeBreakpoint(breakpoint.sourceID, breakpoint.line); + }, + + _breakpointEnableChanged: function(event) + { + var breakpoint = event.target; + + var checkbox = breakpoint._breakpointListElement.firstChild; + checkbox.checked = breakpoint.enabled; + + if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID) + return; + + if (breakpoint.enabled) + InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.condition); + else + InspectorController.removeBreakpoint(breakpoint.sourceID, breakpoint.line); + }, + + _breakpointTextChanged: function(event) + { + var breakpoint = event.target; + + var sourceTextElement = breakpoint._breakpointListElement.firstChild.nextSibling.nextSibling; + sourceTextElement.textContent = breakpoint.sourceText; + } +} + +WebInspector.BreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/CallStackSidebarPane.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/CallStackSidebarPane.js new file mode 100644 index 0000000..2fe4315 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/CallStackSidebarPane.js @@ -0,0 +1,166 @@ +/* + * 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")); + + this._shortcuts = {}; + + var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Period, + WebInspector.KeyboardShortcut.Modifiers.Ctrl); + this._shortcuts[shortcut] = this._selectNextCallFrameOnStack.bind(this); + + var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Comma, + WebInspector.KeyboardShortcut.Modifiers.Ctrl); + this._shortcuts[shortcut] = this._selectPreviousCallFrameOnStack.bind(this); +} + +WebInspector.CallStackSidebarPane.prototype = { + update: function(callFrames, sourceIDMap) + { + this.bodyElement.removeChildren(); + + this.placards = []; + delete this._selectedCallFrame; + + if (!callFrames) { + 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; + + for (var i = 0; i < callFrames.length; ++i) { + var callFrame = callFrames[i]; + 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); + } + }, + + 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"); + }, + + handleKeyEvent: function(event) + { + var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event); + var handler = this._shortcuts[shortcut]; + if (handler) { + handler(event); + event.preventDefault(); + event.handled = true; + } + }, + + _selectNextCallFrameOnStack: function() + { + var index = this._selectedCallFrameIndex(); + if (index == -1) + return; + this._selectedPlacardByIndex(index + 1); + }, + + _selectPreviousCallFrameOnStack: function() + { + var index = this._selectedCallFrameIndex(); + if (index == -1) + return; + this._selectedPlacardByIndex(index - 1); + }, + + _selectedPlacardByIndex: function(index) + { + if (index < 0 || index >= this.placards.length) + return; + var placard = this.placards[index]; + this.selectedCallFrame = placard.callFrame + }, + + _selectedCallFrameIndex: function() + { + if (!this._selectedCallFrame) + return -1; + for (var i = 0; i < this.placards.length; ++i) { + var placard = this.placards[i]; + if (placard.callFrame === this._selectedCallFrame) + return i; + } + return -1; + }, + + _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_frame/tools/test/reference_build/chrome/resources/inspector/Callback.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Callback.js new file mode 100644 index 0000000..8ae7f95 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Callback.js @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +WebInspector.Callback = function() +{ + this._lastCallbackId = 1; + this._callbacks = {}; +} + +WebInspector.Callback.prototype = { + wrap: function(callback) + { + var callbackId = this._lastCallbackId++; + this._callbacks[callbackId] = callback || function() {}; + return callbackId; + }, + + 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]; + } +} + +WebInspector.Callback._INSTANCE = new WebInspector.Callback(); +WebInspector.Callback.wrap = WebInspector.Callback._INSTANCE.wrap.bind(WebInspector.Callback._INSTANCE); +WebInspector.Callback.processCallback = WebInspector.Callback._INSTANCE.processCallback.bind(WebInspector.Callback._INSTANCE); diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ChangesView.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ChangesView.js new file mode 100644 index 0000000..802fdba --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ChangesView.js @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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.ChangesView = function(drawer) +{ + WebInspector.View.call(this); + this.element.innerHTML = "<div style=\"bottom:25%;color:rgb(192,192,192);font-size:12px;height:65px;left:0px;margin:auto;position:absolute;right:0px;text-align:center;top:0px;\"><h1>Not Implemented Yet</h1></div>"; + + this.drawer = drawer; + + this.clearButton = document.createElement("button"); + this.clearButton.id = "clear-changes-status-bar-item"; + this.clearButton.title = WebInspector.UIString("Clear changes log."); + this.clearButton.className = "status-bar-item"; + this.clearButton.addEventListener("click", this._clearButtonClicked.bind(this), false); + + this.toggleChangesButton = document.getElementById("changes-status-bar-item"); + this.toggleChangesButton.title = WebInspector.UIString("Show changes view."); + this.toggleChangesButton.addEventListener("click", this._toggleChangesButtonClicked.bind(this), false); + var anchoredStatusBar = document.getElementById("anchored-status-bar-items"); + anchoredStatusBar.appendChild(this.toggleChangesButton); +} + +WebInspector.ChangesView.prototype = { + _clearButtonClicked: function() + { + // Not Implemented Yet + }, + + _toggleChangesButtonClicked: function() + { + this.drawer.visibleView = this; + }, + + attach: function(mainElement, statusBarElement) + { + mainElement.appendChild(this.element); + statusBarElement.appendChild(this.clearButton); + }, + + show: function() + { + this.toggleChangesButton.addStyleClass("toggled-on"); + this.toggleChangesButton.title = WebInspector.UIString("Hide changes view."); + }, + + hide: function() + { + this.toggleChangesButton.removeStyleClass("toggled-on"); + this.toggleChangesButton.title = WebInspector.UIString("Show changes view."); + } +} + +WebInspector.ChangesView.prototype.__proto__ = WebInspector.View.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Color.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Color.js new file mode 100644 index 0000000..9d9cd76 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Color.js @@ -0,0 +1,661 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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.Color = function(str) +{ + this.value = str; + this._parse(); +} + +WebInspector.Color.prototype = { + get shorthex() + { + if ("_short" in this) + return this._short; + + if (!this.simple) + return null; + + var hex = this.hex; + if (hex.charAt(0) === hex.charAt(1) && hex.charAt(2) === hex.charAt(3) && hex.charAt(4) === hex.charAt(5)) + this._short = hex.charAt(0) + hex.charAt(2) + hex.charAt(4); + else + this._short = hex; + + return this._short; + }, + + get hex() + { + if (!this.simple) + return null; + + return this._hex; + }, + + set hex(x) + { + this._hex = x; + }, + + get rgb() + { + if ("_rgb" in this) + return this._rgb; + + if (this.simple) + this._rgb = this._hexToRGB(this.hex); + else { + var rgba = this.rgba; + this._rgb = [rgba[0], rgba[1], rgba[2]]; + } + + return this._rgb; + }, + + set rgb(x) + { + this._rgb = x; + }, + + get hsl() + { + if ("_hsl" in this) + return this._hsl; + + this._hsl = this._rgbToHSL(this.rgb); + return this._hsl; + }, + + set hsl(x) + { + this._hsl = x; + }, + + get nickname() + { + if (typeof this._nickname !== "undefined") // would be set on parse if there was a nickname + return this._nickname; + else + return null; + }, + + set nickname(x) + { + this._nickname = x; + }, + + get rgba() + { + return this._rgba; + }, + + set rgba(x) + { + this._rgba = x; + }, + + get hsla() + { + return this._hsla; + }, + + set hsla(x) + { + this._hsla = x; + }, + + hasShortHex: function() + { + var shorthex = this.shorthex; + return (shorthex && shorthex.length === 3); + }, + + toString: function(format) + { + if (!format) + format = this.format; + + switch (format) { + case "rgb": + return "rgb(" + this.rgb.join(", ") + ")"; + case "rgba": + return "rgba(" + this.rgba.join(", ") + ")"; + case "hsl": + var hsl = this.hsl; + return "hsl(" + hsl[0] + ", " + hsl[1] + "%, " + hsl[2] + "%)"; + case "hsla": + var hsla = this.hsla; + return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " + hsla[3] + ")"; + case "hex": + return "#" + this.hex; + case "shorthex": + return "#" + this.shorthex; + case "nickname": + return this.nickname; + } + + throw "invalid color format"; + }, + + _rgbToHex: function(rgb) + { + var r = parseInt(rgb[0]).toString(16); + var g = parseInt(rgb[1]).toString(16); + var b = parseInt(rgb[2]).toString(16); + if (r.length === 1) + r = "0" + r; + if (g.length === 1) + g = "0" + g; + if (b.length === 1) + b = "0" + b; + + return (r + g + b).toUpperCase(); + }, + + _hexToRGB: function(hex) + { + var r = parseInt(hex.substring(0,2), 16); + var g = parseInt(hex.substring(2,4), 16); + var b = parseInt(hex.substring(4,6), 16); + + return [r, g, b]; + }, + + _rgbToHSL: function(rgb) + { + var r = parseInt(rgb[0]) / 255; + var g = parseInt(rgb[1]) / 255; + var b = parseInt(rgb[2]) / 255; + var max = Math.max(r, g, b); + var min = Math.min(r, g, b); + var diff = max - min; + var add = max + min; + + if (min === max) + var h = 0; + else if (r === max) + var h = ((60 * (g - b) / diff) + 360) % 360; + else if (g === max) + var h = (60 * (b - r) / diff) + 120; + else + var h = (60 * (r - g) / diff) + 240; + + var l = 0.5 * add; + + if (l === 0) + var s = 0; + else if (l === 1) + var s = 1; + else if (l <= 0.5) + var s = diff / add; + else + var s = diff / (2 - add); + + h = Math.round(h); + s = Math.round(s*100); + l = Math.round(l*100); + + return [h, s, l]; + }, + + _hslToRGB: function(hsl) + { + var h = parseFloat(hsl[0]) / 360; + var s = parseFloat(hsl[1]) / 100; + var l = parseFloat(hsl[2]) / 100; + + if (l <= 0.5) + var q = l * (1 + s); + else + var q = l + s - (l * s); + + var p = 2 * l - q; + + var tr = h + (1 / 3); + var tg = h; + var tb = h - (1 / 3); + + var r = Math.round(hueToRGB(p, q, tr) * 255); + var g = Math.round(hueToRGB(p, q, tg) * 255); + var b = Math.round(hueToRGB(p, q, tb) * 255); + return [r, g, b]; + + function hueToRGB(p, q, h) { + if (h < 0) + h += 1; + else if (h > 1) + h -= 1; + + if ((h * 6) < 1) + return p + (q - p) * h * 6; + else if ((h * 2) < 1) + return q; + else if ((h * 3) < 2) + return p + (q - p) * ((2 / 3) - h) * 6; + else + return p; + } + }, + + _rgbaToHSLA: function(rgba) + { + var alpha = rgba[3]; + var hsl = this._rgbToHSL(rgba) + hsl.push(alpha); + return hsl; + }, + + _hslaToRGBA: function(hsla) + { + var alpha = hsla[3]; + var rgb = this._hslToRGB(hsla); + rgb.push(alpha); + return rgb; + }, + + _parse: function() + { + // Special Values - Advanced but Must Be Parsed First - transparent + var value = this.value.toLowerCase().replace(/%|\s+/g, ""); + if (value in WebInspector.Color.AdvancedNickNames) { + this.format = "nickname"; + var set = WebInspector.Color.AdvancedNickNames[value]; + this.simple = false; + this.rgba = set[0]; + this.hsla = set[1]; + this.nickname = set[2]; + this.alpha = set[0][3]; + return; + } + + // Simple - #hex, rgb(), nickname, hsl() + var simple = /^(?:#([0-9a-f]{3,6})|rgb\(([^)]+)\)|(\w+)|hsl\(([^)]+)\))$/i; + var match = this.value.match(simple); + if (match) { + this.simple = true; + + if (match[1]) { // hex + var hex = match[1].toUpperCase(); + if (hex.length === 3) { + this.format = "shorthex"; + this.hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2); + } else { + this.format = "hex"; + this.hex = hex; + } + } else if (match[2]) { // rgb + this.format = "rgb"; + var rgb = match[2].split(/\s*,\s*/); + this.rgb = rgb; + this.hex = this._rgbToHex(rgb); + } else if (match[3]) { // nickname + var nickname = match[3].toLowerCase(); + if (nickname in WebInspector.Color.Nicknames) { + this.format = "nickname"; + this.hex = WebInspector.Color.Nicknames[nickname]; + } else // unknown name + throw "unknown color name"; + } else if (match[4]) { // hsl + this.format = "hsl"; + var hsl = match[4].replace(/%g/, "").split(/\s*,\s*/); + this.hsl = hsl; + this.rgb = this._hslToRGB(hsl); + this.hex = this._rgbToHex(this.rgb); + } + + // Fill in the values if this is a known hex color + var hex = this.hex; + if (hex && hex in WebInspector.Color.HexTable) { + var set = WebInspector.Color.HexTable[hex]; + this.rgb = set[0]; + this.hsl = set[1]; + this.nickname = set[2]; + } + + return; + } + + // Advanced - rgba(), hsla() + var advanced = /^(?:rgba\(([^)]+)\)|hsla\(([^)]+)\))$/; + match = this.value.match(advanced); + if (match) { + this.simple = false; + if (match[1]) { // rgba + this.format = "rgba"; + this.rgba = match[1].split(/\s*,\s*/); + this.hsla = this._rgbaToHSLA(this.rgba); + this.alpha = this.rgba[3]; + } else if (match[2]) { // hsla + this.format = "hsla"; + this.hsla = match[2].replace(/%/g, "").split(/\s*,\s*/); + this.rgba = this._hslaToRGBA(this.hsla); + this.alpha = this.hsla[3]; + } + + return; + } + + // Could not parse as a valid color + throw "could not parse color"; + } +} + +// Simple Values: [rgb, hsl, nickname] +WebInspector.Color.HexTable = { + "000000": [[0, 0, 0], [0, 0, 0], "black"], + "000080": [[0, 0, 128], [240, 100, 25], "navy"], + "00008B": [[0, 0, 139], [240, 100, 27], "darkBlue"], + "0000CD": [[0, 0, 205], [240, 100, 40], "mediumBlue"], + "0000FF": [[0, 0, 255], [240, 100, 50], "blue"], + "006400": [[0, 100, 0], [120, 100, 20], "darkGreen"], + "008000": [[0, 128, 0], [120, 100, 25], "green"], + "008080": [[0, 128, 128], [180, 100, 25], "teal"], + "008B8B": [[0, 139, 139], [180, 100, 27], "darkCyan"], + "00BFFF": [[0, 191, 255], [195, 100, 50], "deepSkyBlue"], + "00CED1": [[0, 206, 209], [181, 100, 41], "darkTurquoise"], + "00FA9A": [[0, 250, 154], [157, 100, 49], "mediumSpringGreen"], + "00FF00": [[0, 255, 0], [120, 100, 50], "lime"], + "00FF7F": [[0, 255, 127], [150, 100, 50], "springGreen"], + "00FFFF": [[0, 255, 255], [180, 100, 50], "cyan"], + "191970": [[25, 25, 112], [240, 64, 27], "midnightBlue"], + "1E90FF": [[30, 144, 255], [210, 100, 56], "dodgerBlue"], + "20B2AA": [[32, 178, 170], [177, 70, 41], "lightSeaGreen"], + "228B22": [[34, 139, 34], [120, 61, 34], "forestGreen"], + "2E8B57": [[46, 139, 87], [146, 50, 36], "seaGreen"], + "2F4F4F": [[47, 79, 79], [180, 25, 25], "darkSlateGray"], + "32CD32": [[50, 205, 50], [120, 61, 50], "limeGreen"], + "3CB371": [[60, 179, 113], [147, 50, 47], "mediumSeaGreen"], + "40E0D0": [[64, 224, 208], [174, 72, 56], "turquoise"], + "4169E1": [[65, 105, 225], [225, 73, 57], "royalBlue"], + "4682B4": [[70, 130, 180], [207, 44, 49], "steelBlue"], + "483D8B": [[72, 61, 139], [248, 39, 39], "darkSlateBlue"], + "48D1CC": [[72, 209, 204], [178, 60, 55], "mediumTurquoise"], + "4B0082": [[75, 0, 130], [275, 100, 25], "indigo"], + "556B2F": [[85, 107, 47], [82, 39, 30], "darkOliveGreen"], + "5F9EA0": [[95, 158, 160], [182, 25, 50], "cadetBlue"], + "6495ED": [[100, 149, 237], [219, 79, 66], "cornflowerBlue"], + "66CDAA": [[102, 205, 170], [160, 51, 60], "mediumAquaMarine"], + "696969": [[105, 105, 105], [0, 0, 41], "dimGray"], + "6A5ACD": [[106, 90, 205], [248, 53, 58], "slateBlue"], + "6B8E23": [[107, 142, 35], [80, 60, 35], "oliveDrab"], + "708090": [[112, 128, 144], [210, 13, 50], "slateGray"], + "778899": [[119, 136, 153], [210, 14, 53], "lightSlateGray"], + "7B68EE": [[123, 104, 238], [249, 80, 67], "mediumSlateBlue"], + "7CFC00": [[124, 252, 0], [90, 100, 49], "lawnGreen"], + "7FFF00": [[127, 255, 0], [90, 100, 50], "chartreuse"], + "7FFFD4": [[127, 255, 212], [160, 100, 75], "aquamarine"], + "800000": [[128, 0, 0], [0, 100, 25], "maroon"], + "800080": [[128, 0, 128], [300, 100, 25], "purple"], + "808000": [[128, 128, 0], [60, 100, 25], "olive"], + "808080": [[128, 128, 128], [0, 0, 50], "gray"], + "87CEEB": [[135, 206, 235], [197, 71, 73], "skyBlue"], + "87CEFA": [[135, 206, 250], [203, 92, 75], "lightSkyBlue"], + "8A2BE2": [[138, 43, 226], [271, 76, 53], "blueViolet"], + "8B0000": [[139, 0, 0], [0, 100, 27], "darkRed"], + "8B008B": [[139, 0, 139], [300, 100, 27], "darkMagenta"], + "8B4513": [[139, 69, 19], [25, 76, 31], "saddleBrown"], + "8FBC8F": [[143, 188, 143], [120, 25, 65], "darkSeaGreen"], + "90EE90": [[144, 238, 144], [120, 73, 75], "lightGreen"], + "9370D8": [[147, 112, 219], [260, 60, 65], "mediumPurple"], + "9400D3": [[148, 0, 211], [282, 100, 41], "darkViolet"], + "98FB98": [[152, 251, 152], [120, 93, 79], "paleGreen"], + "9932CC": [[153, 50, 204], [280, 61, 50], "darkOrchid"], + "9ACD32": [[154, 205, 50], [80, 61, 50], "yellowGreen"], + "A0522D": [[160, 82, 45], [19, 56, 40], "sienna"], + "A52A2A": [[165, 42, 42], [0, 59, 41], "brown"], + "A9A9A9": [[169, 169, 169], [0, 0, 66], "darkGray"], + "ADD8E6": [[173, 216, 230], [195, 53, 79], "lightBlue"], + "ADFF2F": [[173, 255, 47], [84, 100, 59], "greenYellow"], + "AFEEEE": [[175, 238, 238], [180, 65, 81], "paleTurquoise"], + "B0C4DE": [[176, 196, 222], [214, 41, 78], "lightSteelBlue"], + "B0E0E6": [[176, 224, 230], [187, 52, 80], "powderBlue"], + "B22222": [[178, 34, 34], [0, 68, 42], "fireBrick"], + "B8860B": [[184, 134, 11], [43, 89, 38], "darkGoldenRod"], + "BA55D3": [[186, 85, 211], [288, 59, 58], "mediumOrchid"], + "BC8F8F": [[188, 143, 143], [0, 25, 65], "rosyBrown"], + "BDB76B": [[189, 183, 107], [56, 38, 58], "darkKhaki"], + "C0C0C0": [[192, 192, 192], [0, 0, 75], "silver"], + "C71585": [[199, 21, 133], [322, 81, 43], "mediumVioletRed"], + "CD5C5C": [[205, 92, 92], [0, 53, 58], "indianRed"], + "CD853F": [[205, 133, 63], [30, 59, 53], "peru"], + "D2691E": [[210, 105, 30], [25, 75, 47], "chocolate"], + "D2B48C": [[210, 180, 140], [34, 44, 69], "tan"], + "D3D3D3": [[211, 211, 211], [0, 0, 83], "lightGrey"], + "D87093": [[219, 112, 147], [340, 60, 65], "paleVioletRed"], + "D8BFD8": [[216, 191, 216], [300, 24, 80], "thistle"], + "DA70D6": [[218, 112, 214], [302, 59, 65], "orchid"], + "DAA520": [[218, 165, 32], [43, 74, 49], "goldenRod"], + "DC143C": [[237, 164, 61], [35, 83, 58], "crimson"], + "DCDCDC": [[220, 220, 220], [0, 0, 86], "gainsboro"], + "DDA0DD": [[221, 160, 221], [300, 47, 75], "plum"], + "DEB887": [[222, 184, 135], [34, 57, 70], "burlyWood"], + "E0FFFF": [[224, 255, 255], [180, 100, 94], "lightCyan"], + "E6E6FA": [[230, 230, 250], [240, 67, 94], "lavender"], + "E9967A": [[233, 150, 122], [15, 72, 70], "darkSalmon"], + "EE82EE": [[238, 130, 238], [300, 76, 72], "violet"], + "EEE8AA": [[238, 232, 170], [55, 67, 80], "paleGoldenRod"], + "F08080": [[240, 128, 128], [0, 79, 72], "lightCoral"], + "F0E68C": [[240, 230, 140], [54, 77, 75], "khaki"], + "F0F8FF": [[240, 248, 255], [208, 100, 97], "aliceBlue"], + "F0FFF0": [[240, 255, 240], [120, 100, 97], "honeyDew"], + "F0FFFF": [[240, 255, 255], [180, 100, 97], "azure"], + "F4A460": [[244, 164, 96], [28, 87, 67], "sandyBrown"], + "F5DEB3": [[245, 222, 179], [39, 77, 83], "wheat"], + "F5F5DC": [[245, 245, 220], [60, 56, 91], "beige"], + "F5F5F5": [[245, 245, 245], [0, 0, 96], "whiteSmoke"], + "F5FFFA": [[245, 255, 250], [150, 100, 98], "mintCream"], + "F8F8FF": [[248, 248, 255], [240, 100, 99], "ghostWhite"], + "FA8072": [[250, 128, 114], [6, 93, 71], "salmon"], + "FAEBD7": [[250, 235, 215], [34, 78, 91], "antiqueWhite"], + "FAF0E6": [[250, 240, 230], [30, 67, 94], "linen"], + "FAFAD2": [[250, 250, 210], [60, 80, 90], "lightGoldenRodYellow"], + "FDF5E6": [[253, 245, 230], [39, 85, 95], "oldLace"], + "FF0000": [[255, 0, 0], [0, 100, 50], "red"], + "FF00FF": [[255, 0, 255], [300, 100, 50], "magenta"], + "FF1493": [[255, 20, 147], [328, 100, 54], "deepPink"], + "FF4500": [[255, 69, 0], [16, 100, 50], "orangeRed"], + "FF6347": [[255, 99, 71], [9, 100, 64], "tomato"], + "FF69B4": [[255, 105, 180], [330, 100, 71], "hotPink"], + "FF7F50": [[255, 127, 80], [16, 100, 66], "coral"], + "FF8C00": [[255, 140, 0], [33, 100, 50], "darkOrange"], + "FFA07A": [[255, 160, 122], [17, 100, 74], "lightSalmon"], + "FFA500": [[255, 165, 0], [39, 100, 50], "orange"], + "FFB6C1": [[255, 182, 193], [351, 100, 86], "lightPink"], + "FFC0CB": [[255, 192, 203], [350, 100, 88], "pink"], + "FFD700": [[255, 215, 0], [51, 100, 50], "gold"], + "FFDAB9": [[255, 218, 185], [28, 100, 86], "peachPuff"], + "FFDEAD": [[255, 222, 173], [36, 100, 84], "navajoWhite"], + "FFE4B5": [[255, 228, 181], [38, 100, 85], "moccasin"], + "FFE4C4": [[255, 228, 196], [33, 100, 88], "bisque"], + "FFE4E1": [[255, 228, 225], [6, 100, 94], "mistyRose"], + "FFEBCD": [[255, 235, 205], [36, 100, 90], "blanchedAlmond"], + "FFEFD5": [[255, 239, 213], [37, 100, 92], "papayaWhip"], + "FFF0F5": [[255, 240, 245], [340, 100, 97], "lavenderBlush"], + "FFF5EE": [[255, 245, 238], [25, 100, 97], "seaShell"], + "FFF8DC": [[255, 248, 220], [48, 100, 93], "cornsilk"], + "FFFACD": [[255, 250, 205], [54, 100, 90], "lemonChiffon"], + "FFFAF0": [[255, 250, 240], [40, 100, 97], "floralWhite"], + "FFFAFA": [[255, 250, 250], [0, 100, 99], "snow"], + "FFFF00": [[255, 255, 0], [60, 100, 50], "yellow"], + "FFFFE0": [[255, 255, 224], [60, 100, 94], "lightYellow"], + "FFFFF0": [[255, 255, 240], [60, 100, 97], "ivory"], + "FFFFFF": [[255, 255, 255], [0, 100, 100], "white"] +}; + +// Simple Values +WebInspector.Color.Nicknames = { + "aliceblue": "F0F8FF", + "antiquewhite": "FAEBD7", + "aqua": "00FFFF", + "aquamarine": "7FFFD4", + "azure": "F0FFFF", + "beige": "F5F5DC", + "bisque": "FFE4C4", + "black": "000000", + "blanchedalmond": "FFEBCD", + "blue": "0000FF", + "blueviolet": "8A2BE2", + "brown": "A52A2A", + "burlywood": "DEB887", + "cadetblue": "5F9EA0", + "chartreuse": "7FFF00", + "chocolate": "D2691E", + "coral": "FF7F50", + "cornflowerblue": "6495ED", + "cornsilk": "FFF8DC", + "crimson": "DC143C", + "cyan": "00FFFF", + "darkblue": "00008B", + "darkcyan": "008B8B", + "darkgoldenrod": "B8860B", + "darkgray": "A9A9A9", + "darkgreen": "006400", + "darkkhaki": "BDB76B", + "darkmagenta": "8B008B", + "darkolivegreen": "556B2F", + "darkorange": "FF8C00", + "darkorchid": "9932CC", + "darkred": "8B0000", + "darksalmon": "E9967A", + "darkseagreen": "8FBC8F", + "darkslateblue": "483D8B", + "darkslategray": "2F4F4F", + "darkturquoise": "00CED1", + "darkviolet": "9400D3", + "deeppink": "FF1493", + "deepskyblue": "00BFFF", + "dimgray": "696969", + "dodgerblue": "1E90FF", + "firebrick": "B22222", + "floralwhite": "FFFAF0", + "forestgreen": "228B22", + "fuchsia": "FF00FF", + "gainsboro": "DCDCDC", + "ghostwhite": "F8F8FF", + "gold": "FFD700", + "goldenrod": "DAA520", + "gray": "808080", + "green": "008000", + "greenyellow": "ADFF2F", + "honeydew": "F0FFF0", + "hotpink": "FF69B4", + "indianred": "CD5C5C", + "indigo": "4B0082", + "ivory": "FFFFF0", + "khaki": "F0E68C", + "lavender": "E6E6FA", + "lavenderblush": "FFF0F5", + "lawngreen": "7CFC00", + "lemonchiffon": "FFFACD", + "lightblue": "ADD8E6", + "lightcoral": "F08080", + "lightcyan": "E0FFFF", + "lightgoldenrodyellow": "FAFAD2", + "lightgreen": "90EE90", + "lightgrey": "D3D3D3", + "lightpink": "FFB6C1", + "lightsalmon": "FFA07A", + "lightseagreen": "20B2AA", + "lightskyblue": "87CEFA", + "lightslategray": "778899", + "lightsteelblue": "B0C4DE", + "lightyellow": "FFFFE0", + "lime": "00FF00", + "limegreen": "32CD32", + "linen": "FAF0E6", + "magenta": "FF00FF", + "maroon": "800000", + "mediumaquamarine": "66CDAA", + "mediumblue": "0000CD", + "mediumorchid": "BA55D3", + "mediumpurple": "9370D8", + "mediumseagreen": "3CB371", + "mediumslateblue": "7B68EE", + "mediumspringgreen": "00FA9A", + "mediumturquoise": "48D1CC", + "mediumvioletred": "C71585", + "midnightblue": "191970", + "mintcream": "F5FFFA", + "mistyrose": "FFE4E1", + "moccasin": "FFE4B5", + "navajowhite": "FFDEAD", + "navy": "000080", + "oldlace": "FDF5E6", + "olive": "808000", + "olivedrab": "6B8E23", + "orange": "FFA500", + "orangered": "FF4500", + "orchid": "DA70D6", + "palegoldenrod": "EEE8AA", + "palegreen": "98FB98", + "paleturquoise": "AFEEEE", + "palevioletred": "D87093", + "papayawhip": "FFEFD5", + "peachpuff": "FFDAB9", + "peru": "CD853F", + "pink": "FFC0CB", + "plum": "DDA0DD", + "powderblue": "B0E0E6", + "purple": "800080", + "red": "FF0000", + "rosybrown": "BC8F8F", + "royalblue": "4169E1", + "saddlebrown": "8B4513", + "salmon": "FA8072", + "sandybrown": "F4A460", + "seagreen": "2E8B57", + "seashell": "FFF5EE", + "sienna": "A0522D", + "silver": "C0C0C0", + "skyblue": "87CEEB", + "slateblue": "6A5ACD", + "slategray": "708090", + "snow": "FFFAFA", + "springgreen": "00FF7F", + "steelblue": "4682B4", + "tan": "D2B48C", + "teal": "008080", + "thistle": "D8BFD8", + "tomato": "FF6347", + "turquoise": "40E0D0", + "violet": "EE82EE", + "wheat": "F5DEB3", + "white": "FFFFFF", + "whitesmoke": "F5F5F5", + "yellow": "FFFF00", + "yellowgreen": "9ACD32" +}; + +// Advanced Values [rgba, hsla, nickname] +WebInspector.Color.AdvancedNickNames = { + "transparent": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"], + "rgba(0,0,0,0)": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"], + "hsla(0,0,0,0)": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"], +}; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ConsoleView.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ConsoleView.js new file mode 100644 index 0000000..fa9a363 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ConsoleView.js @@ -0,0 +1,970 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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.ConsoleView = function(drawer) +{ + WebInspector.View.call(this, document.getElementById("console-view")); + + this.messages = []; + this.drawer = drawer; + + 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.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.topGroup = new WebInspector.ConsoleGroup(null, 0); + this.messagesElement.insertBefore(this.topGroup.element, this.promptElement); + this.groupLevel = 0; + this.currentGroup = this.topGroup; + + this.toggleConsoleButton = document.getElementById("console-status-bar-item"); + this.toggleConsoleButton.title = WebInspector.UIString("Show console."); + this.toggleConsoleButton.addEventListener("click", this._toggleConsoleButtonClicked.bind(this), false); + + var anchoredStatusBar = document.getElementById("anchored-status-bar-items"); + anchoredStatusBar.appendChild(this.toggleConsoleButton); + + // Will hold the list of filter elements + this.filterBarElement = document.getElementById("console-filter"); + + function createFilterElement(category) { + var categoryElement = document.createElement("li"); + categoryElement.category = category; + + categoryElement.addStyleClass(categoryElement.category); + + var label = category.toString(); + categoryElement.appendChild(document.createTextNode(label)); + + categoryElement.addEventListener("click", this._updateFilter.bind(this), false); + + this.filterBarElement.appendChild(categoryElement); + return categoryElement; + } + + this.allElement = createFilterElement.call(this, "All"); + this.errorElement = createFilterElement.call(this, "Errors"); + this.warningElement = createFilterElement.call(this, "Warnings"); + this.logElement = createFilterElement.call(this, "Logs"); + + this.filter(this.allElement); +} + +WebInspector.ConsoleView.prototype = { + + _updateFilter: function(e) + { + this.filter(e.target); + }, + + filter: function(target) + { + if (target.category == "All") { + if (target.hasStyleClass("selected")) { + // We can't unselect all, so we break early here + return; + } + + this.errorElement.removeStyleClass("selected"); + this.warningElement.removeStyleClass("selected"); + this.logElement.removeStyleClass("selected"); + + document.getElementById("console-messages").removeStyleClass("filter-errors"); + document.getElementById("console-messages").removeStyleClass("filter-warnings"); + document.getElementById("console-messages").removeStyleClass("filter-logs"); + } else { + // Something other than all is being selected, so we want to unselect all + if (this.allElement.hasStyleClass("selected")) { + this.allElement.removeStyleClass("selected"); + document.getElementById("console-messages").removeStyleClass("filter-all"); + } + } + + if (target.hasStyleClass("selected")) { + target.removeStyleClass("selected"); + var newClass = "filter-" + target.category.toLowerCase(); + var filterElement = document.getElementById("console-messages"); + filterElement.removeStyleClass(newClass); + } else { + target.addStyleClass("selected"); + var newClass = "filter-" + target.category.toLowerCase(); + var filterElement = document.getElementById("console-messages"); + filterElement.addStyleClass(newClass); + } + }, + + _toggleConsoleButtonClicked: function() + { + this.drawer.visibleView = this; + }, + + attach: function(mainElement, statusBarElement) + { + mainElement.appendChild(this.element); + statusBarElement.appendChild(this.clearButton); + statusBarElement.appendChild(this.filterBarElement); + }, + + show: function() + { + this.toggleConsoleButton.addStyleClass("toggled-on"); + this.toggleConsoleButton.title = WebInspector.UIString("Hide console."); + if (!this.prompt.isCaretInsidePrompt()) + this.prompt.moveCaretToEndOfPrompt(); + }, + + afterShow: function() + { + WebInspector.currentFocusElement = this.promptElement; + }, + + hide: function() + { + this.toggleConsoleButton.removeStyleClass("toggled-on"); + this.toggleConsoleButton.title = WebInspector.UIString("Show console."); + }, + + 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.type === WebInspector.ConsoleMessage.MessageType.EndGroup) { + if (this.groupLevel < 1) + return; + + this.groupLevel--; + + this.currentGroup = this.currentGroup.parentGroup; + } else { + if (msg.type === WebInspector.ConsoleMessage.MessageType.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(false); + 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, completionsReadyCallback) + { + // 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 reportCompletions = this._reportCompletions.bind(this, bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix); + // Collect comma separated object properties for the completion. + + if (!expressionString) { + if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused) { + // Evaluate into properties in scope of the selected call frame. + reportCompletions(WebInspector.panels.scripts.variablesInSelectedCallFrame()); + return; + } else { + expressionString = "this"; + } + } + + var includeInspectorCommandLineAPI = (!dotNotation && !bracketNotation); + InjectedScriptAccess.getCompletions(expressionString, includeInspectorCommandLineAPI, reportCompletions); + }, + + _reportCompletions: function(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, result, isException) { + if (isException) + return; + + 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; + } + setTimeout(completionsReadyCallback, 0, results); + }, + + _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.id); + event.stopPropagation(); + event.preventDefault(); + }, + + _promptKeyDown: function(event) + { + switch (event.keyIdentifier) { + case "Enter": + this._enterKeyPressed(event); + return; + } + + this.prompt.handleKeyEvent(event); + }, + + evalInInspectedWindow: function(expression, callback) + { + if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused) { + WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, callback); + return; + } + this.doEvalInWindow(expression, callback); + }, + + doEvalInWindow: function(expression, callback) + { + if (!expression) { + // There is no expression, so the completion should happen against global properties. + expression = "this"; + } + + function evalCallback(result) + { + callback(result.value, result.isException); + }; + InjectedScriptAccess.evaluate(expression, evalCallback); + }, + + _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 self = this; + function printResult(result, exception) + { + self.prompt.history.push(str); + self.prompt.historyOffset = 0; + self.prompt.text = ""; + self.addMessage(new WebInspector.ConsoleCommandResult(result, exception, commandMessage)); + } + this.evalInInspectedWindow(str, printResult); + }, + + _format: function(output, forceObjectFormat) + { + var isProxy = (output != null && typeof output === "object"); + + if (forceObjectFormat) + var type = "object"; + else + var type = Object.proxyType(output); + + if (isProxy && type !== "object" && type !== "function" && type !== "array" && type !== "node") { + // Unwrap primitive value, skip decoration. + output = output.description; + type = "undecorated" + } + + // 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, + "undecorated": 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)); + }, + + _formatfunction: function(func, elem) + { + elem.appendChild(document.createTextNode(func.description)); + }, + + _formatdate: function(date, elem) + { + elem.appendChild(document.createTextNode(date)); + }, + + _formatstring: function(str, elem) + { + elem.appendChild(document.createTextNode("\"" + str + "\"")); + }, + + _formatregexp: function(re, elem) + { + var formatted = String(re.description).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1); + elem.appendChild(document.createTextNode(formatted)); + }, + + _formatarray: function(arr, elem) + { + var self = this; + function printResult(properties) + { + if (!properties) + return; + elem.appendChild(document.createTextNode("[")); + for (var i = 0; i < properties.length; ++i) { + var property = properties[i].value; + elem.appendChild(self._format(property)); + if (i < properties.length - 1) + elem.appendChild(document.createTextNode(", ")); + } + elem.appendChild(document.createTextNode("]")); + } + InjectedScriptAccess.getProperties(arr, false, printResult); + }, + + _formatnode: function(object, elem) + { + function printNode(nodeId) + { + if (!nodeId) + return; + var treeOutline = new WebInspector.ElementsTreeOutline(); + treeOutline.rootDOMNode = WebInspector.domAgent.nodeForId(nodeId); + treeOutline.element.addStyleClass("outline-disclosure"); + if (!treeOutline.children[0].hasChildren) + treeOutline.element.addStyleClass("single-node"); + elem.appendChild(treeOutline.element); + } + InjectedScriptAccess.pushNodeToFrontend(object, printNode); + }, + + _formatobject: function(obj, elem) + { + elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, obj.description, 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.ConsoleView.prototype.__proto__ = WebInspector.View.prototype; + +WebInspector.ConsoleMessage = function(source, type, level, line, url, groupLevel, repeatCount) +{ + this.source = source; + this.type = type; + this.level = level; + this.line = line; + this.url = url; + this.groupLevel = groupLevel; + this.repeatCount = repeatCount; + if (arguments.length > 7) + this.setMessageBody(Array.prototype.slice.call(arguments, 7)); +} + +WebInspector.ConsoleMessage.prototype = { + setMessageBody: function(args) + { + switch (this.type) { + case WebInspector.ConsoleMessage.MessageType.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.MessageType.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 (typeof parameters[0] === "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.Debug: + element.addStyleClass("console-debug-level"); + break; + case WebInspector.ConsoleMessage.MessageLevel.Warning: + element.addStyleClass("console-warning-level"); + break; + case WebInspector.ConsoleMessage.MessageLevel.Error: + element.addStyleClass("console-error-level"); + break; + } + + if (this.type === WebInspector.ConsoleMessage.MessageType.StartGroup) { + element.addStyleClass("console-group-title"); + } + + 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 typeString; + switch (this.type) { + case WebInspector.ConsoleMessage.MessageType.Log: + typeString = "Log"; + break; + case WebInspector.ConsoleMessage.MessageType.Object: + typeString = "Object"; + break; + case WebInspector.ConsoleMessage.MessageType.Trace: + typeString = "Trace"; + break; + case WebInspector.ConsoleMessage.MessageType.StartGroup: + typeString = "Start Group"; + break; + case WebInspector.ConsoleMessage.MessageType.EndGroup: + typeString = "End Group"; + 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.Debug: + levelString = "Debug"; + break; + case WebInspector.ConsoleMessage.MessageLevel.Error: + levelString = "Error"; + break; + } + + return sourceString + " " + typeString + " " + 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.type == msg.type) + && (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.MessageType = { + Log: 0, + Object: 1, + Trace: 2, + StartGroup: 3, + EndGroup: 4 +} + +WebInspector.ConsoleMessage.MessageLevel = { + Tip: 0, + Log: 1, + Warning: 2, + Error: 3, + Debug: 4 +} + +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.ConsoleTextMessage = function(text, level) +{ + level = level || WebInspector.ConsoleMessage.MessageLevel.Log; + WebInspector.ConsoleMessage.call(this, WebInspector.ConsoleMessage.MessageSource.JS, WebInspector.ConsoleMessage.MessageType.Log, level, 0, null, null, 1, text); +} + +WebInspector.ConsoleTextMessage.prototype.__proto__ = WebInspector.ConsoleMessage.prototype; + +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, WebInspector.ConsoleMessage.MessageType.Log, 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.type === WebInspector.ConsoleMessage.MessageType.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"); + 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_frame/tools/test/reference_build/chrome/resources/inspector/CookieItemsView.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/CookieItemsView.js new file mode 100644 index 0000000..f9604a4 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/CookieItemsView.js @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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.CookieItemsView = function() +{ + WebInspector.View.call(this); + + this.element.addStyleClass("storage-view"); + this.element.addStyleClass("table"); + + this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item"); + this.deleteButton.visible = false; + this.deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false); + + this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item"); + this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false); +} + +WebInspector.CookieItemsView.prototype = { + get statusBarItems() + { + return [this.refreshButton.element, this.deleteButton.element]; + }, + + show: function(parentElement) + { + WebInspector.View.prototype.show.call(this, parentElement); + this.update(); + }, + + hide: function() + { + WebInspector.View.prototype.hide.call(this); + this.deleteButton.visible = false; + }, + + update: function() + { + this.element.removeChildren(); + + var self = this; + function callback(cookies, isAdvanced) { + var dataGrid = (isAdvanced ? self.dataGridForCookies(cookies) : self.simpleDataGridForCookies(cookies)); + if (dataGrid) { + self._dataGrid = dataGrid; + self.element.appendChild(dataGrid.element); + if (isAdvanced) + self.deleteButton.visible = true; + } else { + var emptyMsgElement = document.createElement("div"); + emptyMsgElement.className = "storage-table-empty"; + emptyMsgElement.textContent = WebInspector.UIString("This site has no cookies."); + self.element.appendChild(emptyMsgElement); + self._dataGrid = null; + self.deleteButton.visible = false; + } + } + + WebInspector.Cookies.getCookiesAsync(callback); + }, + + dataGridForCookies: function(cookies) + { + if (!cookies.length) + return null; + + for (var i = 0; i < cookies.length; ++i) + cookies[i].expires = new Date(cookies[i].expires); + + var columns = { 0: {}, 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {} }; + columns[0].title = WebInspector.UIString("Name"); + columns[0].width = columns[0].title.length; + columns[1].title = WebInspector.UIString("Value"); + columns[1].width = columns[1].title.length; + columns[2].title = WebInspector.UIString("Domain"); + columns[2].width = columns[2].title.length; + columns[3].title = WebInspector.UIString("Path"); + columns[3].width = columns[3].title.length; + columns[4].title = WebInspector.UIString("Expires"); + columns[4].width = columns[4].title.length; + columns[5].title = WebInspector.UIString("Size"); + columns[5].width = columns[5].title.length; + columns[5].aligned = "right"; + columns[6].title = WebInspector.UIString("HTTP"); + columns[6].width = columns[6].title.length; + columns[6].aligned = "centered"; + columns[7].title = WebInspector.UIString("Secure"); + columns[7].width = columns[7].title.length; + columns[7].aligned = "centered"; + + function updateDataAndColumn(index, value) { + data[index] = value; + if (value.length > columns[index].width) + columns[index].width = value.length; + } + + var data; + var nodes = []; + for (var i = 0; i < cookies.length; ++i) { + var cookie = cookies[i]; + data = {}; + + updateDataAndColumn(0, cookie.name); + updateDataAndColumn(1, cookie.value); + updateDataAndColumn(2, cookie.domain); + updateDataAndColumn(3, cookie.path); + updateDataAndColumn(4, (cookie.session ? WebInspector.UIString("Session") : cookie.expires.toGMTString())); + updateDataAndColumn(5, Number.bytesToString(cookie.size, WebInspector.UIString)); + updateDataAndColumn(6, (cookie.httpOnly ? "\u2713" : "")); // Checkmark + updateDataAndColumn(7, (cookie.secure ? "\u2713" : "")); // Checkmark + + var node = new WebInspector.DataGridNode(data, false); + node.cookie = cookie; + node.selectable = true; + nodes.push(node); + } + + var totalColumnWidths = 0; + for (var columnIdentifier in columns) + totalColumnWidths += columns[columnIdentifier].width; + + // Enforce the Value column (the 2nd column) to be a max of 33% + // tweaking the raw total width because may massively outshadow the others + var valueColumnWidth = columns[1].width; + if (valueColumnWidth / totalColumnWidths > 0.33) { + totalColumnWidths -= valueColumnWidth; + totalColumnWidths *= 1.33; + columns[1].width = totalColumnWidths * 0.33; + } + + // Calculate the percentage width for the columns. + const minimumPrecent = 6; + 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. (need to narrow total percentage due to earlier additions) + while (recoupPercent > 0) { + for (var columnIdentifier in columns) { + if (columns[columnIdentifier].width > minimumPrecent) { + --columns[columnIdentifier].width; + --recoupPercent; + if (!recoupPercent) + break; + } + } + } + + 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]); + if (length > 0) + nodes[0].selected = true; + + return dataGrid; + }, + + simpleDataGridForCookies: function(cookies) + { + if (!cookies.length) + return null; + + var columns = {}; + columns[0] = {}; + columns[1] = {}; + columns[0].title = WebInspector.UIString("Name"); + columns[0].width = columns[0].title.length; + columns[1].title = WebInspector.UIString("Value"); + columns[1].width = columns[1].title.length; + + var nodes = []; + for (var i = 0; i < cookies.length; ++i) { + var cookie = cookies[i]; + var data = {}; + + var name = cookie.name; + data[0] = name; + if (name.length > columns[0].width) + columns[0].width = name.length; + + var value = cookie.value; + 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; + var width = Math.round((columns[0].width * 100) / totalColumnWidths); + const minimumPrecent = 20; + 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.DataGrid(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; + }, + + _deleteButtonClicked: function(event) + { + if (!this._dataGrid) + return; + + var cookie = this._dataGrid.selectedNode.cookie; + InspectorController.deleteCookie(cookie.name); + this.update(); + }, + + _refreshButtonClicked: function(event) + { + this.update(); + } +} + +WebInspector.CookieItemsView.prototype.__proto__ = WebInspector.View.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DOMAgent.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DOMAgent.js new file mode 100644 index 0000000..47c8041 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DOMAgent.js @@ -0,0 +1,650 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +WebInspector.DOMNode = function(doc, payload) { + this.ownerDocument = doc; + + this.id = payload.id; + this.nodeType = payload.nodeType; + this.nodeName = payload.nodeName; + this._nodeValue = payload.nodeValue; + this.textContent = this.nodeValue; + + this.attributes = []; + this._attributesMap = {}; + if (payload.attributes) + this._setAttributesPayload(payload.attributes); + + this._childNodeCount = payload.childNodeCount; + this.children = null; + + this.nextSibling = null; + this.prevSibling = null; + this.firstChild = null; + this.lastChild = null; + this.parentNode = null; + + if (payload.children) + this._setChildrenPayload(payload.children); + + this._computedStyle = null; + this.style = null; + this._matchedCSSRules = []; + + if (this.nodeType == Node.ELEMENT_NODE) { + if (this.nodeName == "HTML") + this.ownerDocument.documentElement = this; + if (this.nodeName == "BODY") + this.ownerDocument.body = this; + } +} + +WebInspector.DOMNode.prototype = { + hasAttributes: function() + { + return this.attributes.length > 0; + }, + + hasChildNodes: function() { + return this._childNodeCount > 0; + }, + + get nodeValue() { + return this._nodeValue; + }, + + set nodeValue(value) { + if (this.nodeType != Node.TEXT_NODE) + return; + var self = this; + var callback = function() + { + self._nodeValue = value; + self.textContent = value; + }; + this.ownerDocument._domAgent.setTextNodeValueAsync(this, value, callback); + }, + + getAttribute: function(name) + { + var attr = this._attributesMap[name]; + return attr ? attr.value : undefined; + }, + + setAttribute: function(name, value) + { + var self = this; + var callback = function() + { + var attr = self._attributesMap[name]; + if (attr) + attr.value = value; + else + attr = self._addAttribute(name, value); + }; + this.ownerDocument._domAgent.setAttributeAsync(this, name, value, callback); + }, + + removeAttribute: function(name) + { + var self = this; + var callback = 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; + } + } + }; + this.ownerDocument._domAgent.removeAttributeAsync(this, name, callback); + }, + + _setAttributesPayload: function(attrs) + { + for (var i = 0; i < attrs.length; i += 2) + this._addAttribute(attrs[i], attrs[i + 1]); + }, + + _insertChild: function(prev, payload) + { + var node = new WebInspector.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; + }, + + removeChild_: function(node) + { + this.children.splice(this.children.indexOf(node), 1); + node.parentNode = null; + this._renumber(); + }, + + _setChildrenPayload: function(payloads) + { + this.children = []; + for (var i = 0; i < payloads.length; ++i) { + var payload = payloads[i]; + var node = new WebInspector.DOMNode(this.ownerDocument, payload); + this.children.push(node); + } + this._renumber(); + }, + + _renumber: function() + { + this._childNodeCount = this.children.length; + if (this._childNodeCount == 0) { + this.firstChild = null; + this.lastChild = null; + return; + } + this.firstChild = this.children[0]; + this.lastChild = this.children[this._childNodeCount - 1]; + for (var i = 0; i < this._childNodeCount; ++i) { + var child = this.children[i]; + child.nextSibling = i + 1 < this._childNodeCount ? this.children[i + 1] : null; + child.prevSibling = i - 1 >= 0 ? this.children[i - 1] : null; + child.parentNode = this; + } + }, + + _addAttribute: function(name, value) + { + var attr = { + "name": name, + "value": value, + "_node": this + }; + this._attributesMap[name] = attr; + this.attributes.push(attr); + }, + + _setStyles: function(computedStyle, inlineStyle, styleAttributes, matchedCSSRules) + { + this._computedStyle = new WebInspector.CSSStyleDeclaration(computedStyle); + this.style = new WebInspector.CSSStyleDeclaration(inlineStyle); + + for (var name in styleAttributes) { + if (this._attributesMap[name]) + this._attributesMap[name].style = new WebInspector.CSSStyleDeclaration(styleAttributes[name]); + } + + this._matchedCSSRules = []; + for (var i = 0; i < matchedCSSRules.length; i++) + this._matchedCSSRules.push(WebInspector.CSSStyleDeclaration.parseRule(matchedCSSRules[i])); + }, + + _clearStyles: function() + { + this.computedStyle = null; + this.style = null; + for (var name in this._attributesMap) + this._attributesMap[name].style = null; + this._matchedCSSRules = null; + } +} + +WebInspector.DOMDocument = function(domAgent, defaultView, payload) +{ + WebInspector.DOMNode.call(this, this, payload); + this._listeners = {}; + this._domAgent = domAgent; + this.defaultView = defaultView; +} + +WebInspector.DOMDocument.prototype = { + + addEventListener: function(name, callback) + { + var listeners = this._listeners[name]; + if (!listeners) { + listeners = []; + this._listeners[name] = listeners; + } + listeners.push(callback); + }, + + removeEventListener: function(name, callback) + { + var listeners = this._listeners[name]; + if (!listeners) + return; + + var index = listeners.indexOf(callback); + if (index != -1) + listeners.splice(index, 1); + }, + + _fireDomEvent: function(name, event) + { + var listeners = this._listeners[name]; + if (!listeners) + return; + + for (var i = 0; i < listeners.length; ++i) { + var listener = listeners[i]; + listener.call(this, event); + } + } +} + +WebInspector.DOMDocument.prototype.__proto__ = WebInspector.DOMNode.prototype; + + +WebInspector.DOMWindow = function(domAgent) +{ + this._domAgent = domAgent; +} + +WebInspector.DOMWindow.prototype = { + get document() + { + return this._domAgent.document; + }, + + get Node() + { + return WebInspector.DOMNode; + }, + + get Element() + { + return WebInspector.DOMNode; + }, + + Object: function() + { + }, + + getComputedStyle: function(node) + { + return node._computedStyle; + }, + + getMatchedCSSRules: function(node, pseudoElement, authorOnly) + { + return node._matchedCSSRules; + } +} + +WebInspector.DOMAgent = function() { + this._window = new WebInspector.DOMWindow(this); + this._idToDOMNode = null; + this.document = null; + + // TODO: update ElementsPanel to not track embedded iframes - it is already being handled + // in the agent backend. + + // Whitespace is ignored in InspectorDOMAgent already -> no need to filter. + // TODO: Either remove all of its usages or push value into the agent backend. + Preferences.ignoreWhitespace = false; +} + +WebInspector.DOMAgent.prototype = { + get domWindow() + { + return this._window; + }, + + getChildNodesAsync: function(parent, callback) + { + var children = parent.children; + if (children) { + callback(children); + return; + } + function mycallback() { + callback(parent.children); + } + var callId = WebInspector.Callback.wrap(mycallback); + InspectorController.getChildNodes(callId, parent.id); + }, + + setAttributeAsync: function(node, name, value, callback) + { + var mycallback = this._didApplyDomChange.bind(this, node, callback); + InspectorController.setAttribute(WebInspector.Callback.wrap(mycallback), node.id, name, value); + }, + + removeAttributeAsync: function(node, name, callback) + { + var mycallback = this._didApplyDomChange.bind(this, node, callback); + InspectorController.removeAttribute(WebInspector.Callback.wrap(mycallback), node.id, name); + }, + + setTextNodeValueAsync: function(node, text, callback) + { + var mycallback = this._didApplyDomChange.bind(this, node, callback); + InspectorController.setTextNodeValue(WebInspector.Callback.wrap(mycallback), node.id, text); + }, + + _didApplyDomChange: function(node, callback, success) + { + if (!success) + return; + callback(); + // TODO(pfeldman): Fix this hack. + var elem = WebInspector.panels.elements.treeOutline.findTreeElement(node); + if (elem) { + elem._updateTitle(); + } + }, + + _attributesUpdated: function(nodeId, attrsArray) + { + var node = this._idToDOMNode[nodeId]; + node._setAttributesPayload(attrsArray); + }, + + nodeForId: function(nodeId) { + return this._idToDOMNode[nodeId]; + }, + + _setDocument: function(payload) + { + this.document = new WebInspector.DOMDocument(this, this._window, payload); + this._idToDOMNode = {}; + this._idToDOMNode[payload.id] = this.document; + this._bindNodes(this.document.children); + WebInspector.panels.elements.reset(); + }, + + _setDetachedRoot: function(payload) + { + var root = new WebInspector.DOMNode(this.document, payload); + this._idToDOMNode[payload.id] = root; + }, + + _setChildNodes: function(parentId, payloads) + { + var parent = this._idToDOMNode[parentId]; + parent._setChildrenPayload(payloads); + this._bindNodes(parent.children); + }, + + _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); + } + }, + + _childNodeCountUpdated: function(nodeId, newValue) + { + var node = this._idToDOMNode[nodeId]; + node._childNodeCount = newValue; + var outline = WebInspector.panels.elements.treeOutline; + var treeElement = outline.findTreeElement(node); + if (treeElement) { + treeElement.hasChildren = newValue; + treeElement.whitespaceIgnored = Preferences.ignoreWhitespace; + } + }, + + _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.document._fireDomEvent("DOMNodeInserted", event); + }, + + _childNodeRemoved: function(parentId, nodeId) + { + var parent = this._idToDOMNode[parentId]; + var node = this._idToDOMNode[nodeId]; + parent.removeChild_(node); + var event = { target : node, relatedNode : parent }; + this.document._fireDomEvent("DOMNodeRemoved", event); + delete this._idToDOMNode[nodeId]; + } +} + +WebInspector.Cookies = {} + +WebInspector.Cookies.getCookiesAsync = function(callback) +{ + function mycallback(cookies, cookiesString) { + if (cookiesString) + callback(WebInspector.Cookies.buildCookiesFromString(cookiesString), false); + else + callback(cookies, true); + } + var callId = WebInspector.Callback.wrap(mycallback); + InspectorController.getCookies(callId); +} + +WebInspector.Cookies.buildCookiesFromString = function(rawCookieString) +{ + var rawCookies = rawCookieString.split(/;\s*/); + var cookies = []; + + if (!(/^\s*$/.test(rawCookieString))) { + for (var i = 0; i < rawCookies.length; ++i) { + var cookie = rawCookies[i]; + var delimIndex = cookie.indexOf("="); + var name = cookie.substring(0, delimIndex); + var value = cookie.substring(delimIndex + 1); + var size = name.length + value.length; + cookies.push({ name: name, value: value, size: size }); + } + } + + return cookies; +} + +WebInspector.CSSStyleDeclaration = function(payload) +{ + this.id = payload.id; + this.width = payload.width; + this.height = payload.height; + this.__disabledProperties = payload.__disabledProperties; + this.__disabledPropertyValues = payload.__disabledPropertyValues; + this.__disabledPropertyPriorities = payload.__disabledPropertyPriorities; + this.uniqueStyleProperties = payload.uniqueStyleProperties; + this._shorthandValues = payload.shorthandValues; + this._propertyMap = {}; + this._longhandProperties = {}; + this.length = payload.properties.length; + + for (var i = 0; i < this.length; ++i) { + var property = payload.properties[i]; + var name = property.name; + this[i] = name; + this._propertyMap[name] = property; + } + + // Index longhand properties. + for (var i = 0; i < this.uniqueStyleProperties.length; ++i) { + var name = this.uniqueStyleProperties[i]; + var property = this._propertyMap[name]; + if (property.shorthand) { + var longhands = this._longhandProperties[property.shorthand]; + if (!longhands) { + longhands = []; + this._longhandProperties[property.shorthand] = longhands; + } + longhands.push(name); + } + } +} + +WebInspector.CSSStyleDeclaration.parseStyle = function(payload) +{ + return new WebInspector.CSSStyleDeclaration(payload); +} + +WebInspector.CSSStyleDeclaration.parseRule = function(payload) +{ + var rule = {}; + rule.id = payload.id; + rule.selectorText = payload.selectorText; + rule.style = new WebInspector.CSSStyleDeclaration(payload.style); + rule.style.parentRule = rule; + rule.isUserAgent = payload.isUserAgent; + rule.isUser = payload.isUser; + rule.isViaInspector = payload.isViaInspector; + if (payload.parentStyleSheet) + rule.parentStyleSheet = { href: payload.parentStyleSheet.href }; + + return rule; +} + +WebInspector.CSSStyleDeclaration.prototype = { + getPropertyValue: function(name) + { + var property = this._propertyMap[name]; + return property ? property.value : ""; + }, + + getPropertyPriority: function(name) + { + var property = this._propertyMap[name]; + return property ? property.priority : ""; + }, + + getPropertyShorthand: function(name) + { + var property = this._propertyMap[name]; + return property ? property.shorthand : ""; + }, + + isPropertyImplicit: function(name) + { + var property = this._propertyMap[name]; + return property ? property.implicit : ""; + }, + + styleTextWithShorthands: function() + { + var cssText = ""; + var foundProperties = {}; + for (var i = 0; i < this.length; ++i) { + var individualProperty = this[i]; + var shorthandProperty = this.getPropertyShorthand(individualProperty); + var propertyName = (shorthandProperty || individualProperty); + + if (propertyName in foundProperties) + continue; + + if (shorthandProperty) { + var value = this.getPropertyValue(shorthandProperty); + var priority = this.getShorthandPriority(shorthandProperty); + } else { + var value = this.getPropertyValue(individualProperty); + var priority = this.getPropertyPriority(individualProperty); + } + + foundProperties[propertyName] = true; + + cssText += propertyName + ": " + value; + if (priority) + cssText += " !" + priority; + cssText += "; "; + } + + return cssText; + }, + + getLonghandProperties: function(name) + { + return this._longhandProperties[name] || []; + }, + + getShorthandValue: function(shorthandProperty) + { + return this._shorthandValues[shorthandProperty]; + }, + + getShorthandPriority: function(shorthandProperty) + { + var priority = this.getPropertyPriority(shorthandProperty); + if (priority) + return priority; + + var longhands = this._longhandProperties[shorthandProperty]; + return longhands ? this.getPropertyPriority(longhands[0]) : null; + } +} + +WebInspector.attributesUpdated = function() +{ + this.domAgent._attributesUpdated.apply(this.domAgent, arguments); +} + +WebInspector.setDocument = function() +{ + this.domAgent._setDocument.apply(this.domAgent, arguments); +} + +WebInspector.setDetachedRoot = function() +{ + this.domAgent._setDetachedRoot.apply(this.domAgent, arguments); +} + +WebInspector.setChildNodes = function() +{ + this.domAgent._setChildNodes.apply(this.domAgent, arguments); +} + +WebInspector.childNodeCountUpdated = function() +{ + this.domAgent._childNodeCountUpdated.apply(this.domAgent, arguments); +} + +WebInspector.childNodeInserted = function() +{ + this.domAgent._childNodeInserted.apply(this.domAgent, arguments); +} + +WebInspector.childNodeRemoved = function() +{ + this.domAgent._childNodeRemoved.apply(this.domAgent, arguments); +} + +WebInspector.didGetCookies = WebInspector.Callback.processCallback; +WebInspector.didGetChildNodes = WebInspector.Callback.processCallback; +WebInspector.didPerformSearch = WebInspector.Callback.processCallback; +WebInspector.didApplyDomChange = WebInspector.Callback.processCallback; +WebInspector.didRemoveAttribute = WebInspector.Callback.processCallback; +WebInspector.didSetTextNodeValue = WebInspector.Callback.processCallback; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DOMStorage.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DOMStorage.js new file mode 100644 index 0000000..5207b69 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DOMStorage.js @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2008 Nokia 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 "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.DOMStorage = function(domStorage, domain, isLocalStorage) +{ + this.domStorage = domStorage; + this.domain = domain; + this.isLocalStorage = isLocalStorage; +} + +WebInspector.DOMStorage.prototype = { + get domStorage() + { + return this._domStorage; + }, + + set domStorage(x) + { + if (this._domStorage === x) + return; + this._domStorage = x; + }, + + get domain() + { + return this._domain; + }, + + set domain(x) + { + if (this._domain === x) + return; + this._domain = x; + }, + + get isLocalStorage() + { + return this._isLocalStorage; + }, + + set isLocalStorage(x) + { + if (this._isLocalStorage === x) + return; + this._isLocalStorage = x; + } +} diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DOMStorageDataGrid.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DOMStorageDataGrid.js new file mode 100644 index 0000000..efdd090 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DOMStorageDataGrid.js @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2009 Nokia 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.DOMStorageDataGrid = function(columns) +{ + WebInspector.DataGrid.call(this, columns); + this.dataTableBody.addEventListener("dblclick", this._ondblclick.bind(this), false); +} + +WebInspector.DOMStorageDataGrid.prototype = { + _ondblclick: function(event) + { + if (this._editing) + return; + if (this._editingNode) + return; + this._startEditing(event); + }, + + _startEditingColumnOfDataGridNode: function(node, column) + { + this._editing = true; + this._editingNode = node; + this._editingNode.select(); + WebInspector.panels.storage._unregisterStorageEventListener(); + + var element = this._editingNode._element.children[column]; + WebInspector.startEditing(element, this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent); + window.getSelection().setBaseAndExtent(element, 0, element, 1); + }, + + _startEditing: function(event) + { + var element = event.target.enclosingNodeOrSelfWithNodeName("td"); + if (!element) + return; + + this._editingNode = this.dataGridNodeFromEvent(event); + if (!this._editingNode) { + if (!this.creationNode) + return; + this._editingNode = this.creationNode; + } + + // Force editing the "Key" column when editing the creation node + if (this._editingNode.isCreationNode) + return this._startEditingColumnOfDataGridNode(this._editingNode, 0); + + this._editing = true; + WebInspector.panels.storage._unregisterStorageEventListener(); + WebInspector.startEditing(element, this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent); + window.getSelection().setBaseAndExtent(element, 0, element, 1); + }, + + _editingCommitted: function(element, newText, oldText, context, moveDirection) + { + var columnIdentifier = (element.hasStyleClass("0-column") ? 0 : 1); + var textBeforeEditing = this._editingNode.data[columnIdentifier]; + var currentEditingNode = this._editingNode; + + function moveToNextIfNeeded(wasChange) { + if (!moveDirection) + return; + + if (moveDirection === "forward") { + if (currentEditingNode.isCreationNode && columnIdentifier === 0 && !wasChange) + return; + + if (columnIdentifier === 0) + return this._startEditingColumnOfDataGridNode(currentEditingNode, 1); + + var nextDataGridNode = currentEditingNode.traverseNextNode(true, null, true); + if (nextDataGridNode) + return this._startEditingColumnOfDataGridNode(nextDataGridNode, 0); + if (currentEditingNode.isCreationNode && wasChange) { + addCreationNode(false); + return this._startEditingColumnOfDataGridNode(this.creationNode, 0); + } + return; + } + + if (moveDirection === "backward") { + if (columnIdentifier === 1) + return this._startEditingColumnOfDataGridNode(currentEditingNode, 0); + var nextDataGridNode = currentEditingNode.traversePreviousNode(true, null, true); + + if (nextDataGridNode) + return this._startEditingColumnOfDataGridNode(nextDataGridNode, 1); + return; + } + } + + if (textBeforeEditing == newText) { + this._editingCancelled(element); + moveToNextIfNeeded.call(this, false); + return; + } + + var domStorage = WebInspector.panels.storage.visibleView.domStorage.domStorage; + if (domStorage) { + if (columnIdentifier == 0) { + if (domStorage.getItem(newText) != null) { + element.textContent = this._editingNode.data[0]; + this._editingCancelled(element); + moveToNextIfNeeded.call(this, false); + return; + } + domStorage.removeItem(this._editingNode.data[0]); + domStorage.setItem(newText, this._editingNode.data[1]); + this._editingNode.data[0] = newText; + } else { + domStorage.setItem(this._editingNode.data[0], newText); + this._editingNode.data[1] = newText; + } + } + + if (this._editingNode.isCreationNode) + this.addCreationNode(false); + + this._editingCancelled(element); + moveToNextIfNeeded.call(this, true); + }, + + _editingCancelled: function(element, context) + { + delete this._editing; + this._editingNode = null; + WebInspector.panels.storage._registerStorageEventListener(); + }, + + deleteSelectedRow: function() + { + var node = this.selectedNode; + if (this.selectedNode.isCreationNode) + return; + + var domStorage = WebInspector.panels.storage.visibleView.domStorage.domStorage; + if (node && domStorage) + domStorage.removeItem(node.data[0]); + } +} + +WebInspector.DOMStorageDataGrid.prototype.__proto__ = WebInspector.DataGrid.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DOMStorageItemsView.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DOMStorageItemsView.js new file mode 100644 index 0000000..8617d60 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DOMStorageItemsView.js @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2008 Nokia 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 ``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.DOMStorageItemsView = function(domStorage) +{ + WebInspector.View.call(this); + + this.domStorage = domStorage; + + this.element.addStyleClass("storage-view"); + this.element.addStyleClass("table"); + + this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item"); + this.deleteButton.visible = false; + this.deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false); + + this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item"); + this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false); +} + +WebInspector.DOMStorageItemsView.prototype = { + get statusBarItems() + { + return [this.refreshButton.element, this.deleteButton.element]; + }, + + show: function(parentElement) + { + WebInspector.View.prototype.show.call(this, parentElement); + this.update(); + }, + + hide: function() + { + WebInspector.View.prototype.hide.call(this); + this.deleteButton.visible = false; + }, + + update: function() + { + this.element.removeChildren(); + var hasDOMStorage = this.domStorage; + if (hasDOMStorage) + hasDOMStorage = this.domStorage.domStorage; + + if (hasDOMStorage) { + var dataGrid = WebInspector.panels.storage.dataGridForDOMStorage(this.domStorage.domStorage); + if (!dataGrid) + hasDOMStorage = 0; + else { + this._dataGrid = dataGrid; + this.element.appendChild(dataGrid.element); + this._dataGrid.updateWidths(); + this.deleteButton.visible = true; + } + } + + if (!hasDOMStorage) { + var emptyMsgElement = document.createElement("div"); + emptyMsgElement.className = "storage-table-empty"; + if (this.domStorage) + emptyMsgElement.textContent = WebInspector.UIString("This storage is empty."); + this.element.appendChild(emptyMsgElement); + this._dataGrid = null; + this.deleteButton.visible = false; + } + }, + + resize: function() + { + if (this._dataGrid) + this._dataGrid.updateWidths(); + }, + + _deleteButtonClicked: function(event) + { + if (this._dataGrid) { + this._dataGrid.deleteSelectedRow(); + + this.show(); + } + }, + + _refreshButtonClicked: function(event) + { + this.update(); + } +} + +WebInspector.DOMStorageItemsView.prototype.__proto__ = WebInspector.View.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DataGrid.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DataGrid.js new file mode 100644 index 0000000..ce61548 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DataGrid.js @@ -0,0 +1,1041 @@ +/* + * 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); + + this.aligned = {}; + + 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"); + } + + if (column.aligned) { + cell.addStyleClass(column.aligned); + this.aligned[columnIdentifier] = column.aligned; + } + + headerRow.appendChild(cell); + + ++columnCount; + } + + columnGroup.span = columnCount; + + var cell = document.createElement("th"); + cell.className = "corner"; + headerRow.appendChild(cell); + + this._headerTableColumnGroup = columnGroup; + this._headerTable.appendChild(this._headerTableColumnGroup); + 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._dataTableColumnGroup = columnGroup.cloneNode(true); + this._dataTable.appendChild(this._dataTableColumnGroup); + 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; + this.resizers = []; + this.columnWidthsInitialized = false; +} + +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; + }, + + // Updates the widths of the table, including the positions of the column + // resizers. + // + // IMPORTANT: This function MUST be called once after the element of the + // DataGrid is attached to its parent element and every subsequent time the + // width of the parent element is changed in order to make it possible to + // resize the columns. + // + // If this function is not called after the DataGrid is attached to its + // parent element, then the DataGrid's columns will not be resizable. + updateWidths: function() + { + var headerTableColumns = this._headerTableColumnGroup.children; + + var left = 0; + var tableWidth = this._dataTable.offsetWidth; + var numColumns = headerTableColumns.length; + + if (!this.columnWidthsInitialized) { + // Give all the columns initial widths now so that during a resize, + // when the two columns that get resized get a percent value for + // their widths, all the other columns already have percent values + // for their widths. + for (var i = 0; i < numColumns; i++) { + var columnWidth = this.headerTableBody.rows[0].cells[i].offsetWidth; + var percentWidth = ((columnWidth / tableWidth) * 100) + "%"; + this._headerTableColumnGroup.children[i].style.width = percentWidth; + this._dataTableColumnGroup.children[i].style.width = percentWidth; + } + this.columnWidthsInitialized = true; + } + + // Make n - 1 resizers for n columns. + for (var i = 0; i < numColumns - 1; i++) { + var resizer = this.resizers[i]; + + if (!resizer) { + // This is the first call to updateWidth, so the resizers need + // to be created. + resizer = document.createElement("div"); + resizer.addStyleClass("data-grid-resizer"); + // This resizer is associated with the column to its right. + resizer.rightNeighboringColumnID = i + 1; + resizer.addEventListener("mousedown", this._startResizerDragging.bind(this), false); + this.element.appendChild(resizer); + this.resizers[i] = resizer; + } + + // Get the width of the cell in the first (and only) row of the + // header table in order to determine the width of the column, since + // it is not possible to query a column for its width. + left += this.headerTableBody.rows[0].cells[i].offsetWidth; + + resizer.style.left = left + "px"; + } + }, + + addCreationNode: function(hasChildren) + { + if (this.creationNode) + this.creationNode.makeNormal(); + + var emptyData = {}; + for (var column in this.columns) + emptyData[column] = ''; + this.creationNode = new WebInspector.CreationDataGridNode(emptyData, hasChildren); + this.appendChild(this.creationNode); + }, + + 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(); + } + }, + + _startResizerDragging: function(event) + { + this.currentResizer = event.target; + if (!this.currentResizer.rightNeighboringColumnID) + return; + WebInspector.elementDragStart(this.lastResizer, this._resizerDragging.bind(this), + this._endResizerDragging.bind(this), event, "col-resize"); + }, + + _resizerDragging: function(event) + { + var resizer = this.currentResizer; + if (!resizer) + return; + + // Constrain the dragpoint to be within the containing div of the + // datagrid. + var dragPoint = event.clientX - this.element.totalOffsetLeft; + // Constrain the dragpoint to be within the space made up by the + // column directly to the left and the column directly to the right. + var leftEdgeOfPreviousColumn = 0; + var firstRowCells = this.headerTableBody.rows[0].cells; + for (var i = 0; i < resizer.rightNeighboringColumnID - 1; i++) + leftEdgeOfPreviousColumn += firstRowCells[i].offsetWidth; + + var rightEdgeOfNextColumn = leftEdgeOfPreviousColumn + firstRowCells[resizer.rightNeighboringColumnID - 1].offsetWidth + firstRowCells[resizer.rightNeighboringColumnID].offsetWidth; + + // Give each column some padding so that they don't disappear. + var leftMinimum = leftEdgeOfPreviousColumn + this.ColumnResizePadding; + var rightMaximum = rightEdgeOfNextColumn - this.ColumnResizePadding; + + dragPoint = Number.constrain(dragPoint, leftMinimum, rightMaximum); + + resizer.style.left = (dragPoint - this.CenterResizerOverBorderAdjustment) + "px"; + + var percentLeftColumn = (((dragPoint - leftEdgeOfPreviousColumn) / this._dataTable.offsetWidth) * 100) + "%"; + this._headerTableColumnGroup.children[resizer.rightNeighboringColumnID - 1].style.width = percentLeftColumn; + this._dataTableColumnGroup.children[resizer.rightNeighboringColumnID - 1].style.width = percentLeftColumn; + + var percentRightColumn = (((rightEdgeOfNextColumn - dragPoint) / this._dataTable.offsetWidth) * 100) + "%"; + this._headerTableColumnGroup.children[resizer.rightNeighboringColumnID].style.width = percentRightColumn; + this._dataTableColumnGroup.children[resizer.rightNeighboringColumnID].style.width = percentRightColumn; + + event.preventDefault(); + }, + + _endResizerDragging: function(event) + { + WebInspector.elementDragEnd(event); + this.currentResizer = null; + }, + + ColumnResizePadding: 10, + + CenterResizerOverBorderAdjustment: 3, +} + +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 alignment = this.dataGrid.aligned[columnIdentifier]; + if (alignment) + cell.addStyleClass(alignment); + + 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; + +WebInspector.CreationDataGridNode = function(data, hasChildren) +{ + WebInspector.DataGridNode.call(this, data, hasChildren); + this.isCreationNode = true; +} + +WebInspector.CreationDataGridNode.prototype = { + makeNormal: function() + { + delete this.isCreationNode; + delete this.makeNormal; + } +} + +WebInspector.CreationDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Database.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Database.js new file mode 100644 index 0000000..dcab2ab --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Database.js @@ -0,0 +1,113 @@ +/* + * 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 = { + isDatabase: function(db) + { + return this._database === db; + }, + + 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); + }, + + getTableNames: function(callback) + { + var names = InspectorController.databaseTableNames(this._database); + function sortingCallback() + { + callback(names.sort()); + } + setTimeout(sortingCallback, 0); + }, + + executeSql: function(query, onSuccess, onError) + { + function successCallback(tx, result) + { + onSuccess(result); + } + + function errorCallback(tx, error) + { + onError(error); + } + + var self = this; + function queryTransaction(tx) + { + tx.executeSql(query, null, InspectorController.wrapCallback(successCallback.bind(self)), InspectorController.wrapCallback(errorCallback.bind(self))); + } + this._database.transaction(InspectorController.wrapCallback(queryTransaction.bind(this)), InspectorController.wrapCallback(errorCallback.bind(this))); + } +} diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DatabaseQueryView.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DatabaseQueryView.js new file mode 100644 index 0000000..6c5fa02 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DatabaseQueryView.js @@ -0,0 +1,195 @@ +/* + * 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, completionsReadyCallback) + { + 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; + } + } + + function tableNamesCallback(tableNames) + { + accumulateMatches(tableNames.map(function(name) { return name + " " })); + accumulateMatches(["SELECT ", "FROM ", "WHERE ", "LIMIT ", "DELETE FROM ", "CREATE ", "DROP ", "TABLE ", "INDEX ", "UPDATE ", "INSERT INTO ", "VALUES ("]); + + completionsReadyCallback(results); + } + this.database.getTableNames(tableNamesCallback); + }, + + _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 = ""; + + this.database.executeSql(query, this._queryFinished.bind(this, query), this._queryError.bind(this, query)); + }, + + _queryFinished: function(query, result) + { + var dataGrid = WebInspector.panels.storage.dataGridForResult(result); + if (!dataGrid) + return; + dataGrid.element.addStyleClass("inline"); + this._appendQueryResult(query, dataGrid.element); + + if (query.match(/^create /i) || query.match(/^drop table /i)) + WebInspector.panels.storage.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 occurred.", error.code); + + this._appendQueryResult(query, message, "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_frame/tools/test/reference_build/chrome/resources/inspector/DatabaseTableView.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DatabaseTableView.js new file mode 100644 index 0000000..aa76794f --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/DatabaseTableView.js @@ -0,0 +1,89 @@ +/* + * 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 = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-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() + { + this.database.executeSql("SELECT * FROM " + this.tableName, this._queryFinished.bind(this), this._queryError.bind(this)); + }, + + _queryFinished: function(result) + { + this.element.removeChildren(); + + var dataGrid = WebInspector.panels.storage.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(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_frame/tools/test/reference_build/chrome/resources/inspector/Drawer.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Drawer.js new file mode 100644 index 0000000..1b50f91 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Drawer.js @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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.Drawer = function() +{ + WebInspector.View.call(this, document.getElementById("drawer")); + + this.mainStatusBar = document.getElementById("main-status-bar"); + this.mainStatusBar.addEventListener("mousedown", this._startStatusBarDragging.bind(this), true); + this.viewStatusBar = document.getElementById("other-drawer-status-bar-items"); +} + +WebInspector.Drawer.prototype = { + get visibleView() + { + return this._visibleView; + }, + + set visibleView(x) + { + if (this._visibleView === x) { + this.visible = !this.visible; + return; + } + + var firstTime = !this._visibleView; + if (this._visibleView) + this._visibleView.hide(); + + this._visibleView = x; + + if (x && !firstTime) { + this._safelyRemoveChildren(); + this.viewStatusBar.removeChildren(); // optimize this? call old.detach() + x.attach(this.element, this.viewStatusBar); + x.show(); + this.visible = true; + } + }, + + showView: function(view) + { + if (!this.visible || this.visibleView !== view) + this.visibleView = view; + }, + + show: function() + { + if (this._animating || this.visible) + return; + + if (this.visibleView) + this.visibleView.show(); + + WebInspector.View.prototype.show.call(this); + + this._animating = true; + + document.body.addStyleClass("drawer-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-drawer-status-bar-items"), start: {opacity: 0}, end: {opacity: 1}} + ]; + + var consoleStatusBar = document.getElementById("drawer-status-bar"); + consoleStatusBar.insertBefore(anchoredItems, consoleStatusBar.firstChild); + + function animationFinished() + { + if ("updateStatusBarItems" in WebInspector.currentPanel) + WebInspector.currentPanel.updateStatusBarItems(); + if (this.visibleView.afterShow) + this.visibleView.afterShow(); + delete this._animating; + } + + WebInspector.animateStyle(animations, window.event && window.event.shiftKey ? 2000 : 250, animationFinished.bind(this)); + }, + + hide: function() + { + if (this._animating || !this.visible) + return; + + WebInspector.View.prototype.hide.call(this); + + if (this.visibleView) + this.visibleView.hide(); + + this._animating = true; + + 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("drawer-visible"); + if ("updateStatusBarItems" in WebInspector.currentPanel) + WebInspector.currentPanel.updateStatusBarItems(); + document.body.addStyleClass("drawer-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-drawer-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("drawer-visible"); + delete this._animating; + } + + WebInspector.animateStyle(animations, window.event && window.event.shiftKey ? 2000 : 250, animationFinished.bind(this)); + }, + + _safelyRemoveChildren: function() + { + var child = this.element.firstChild; + while (child) { + if (child.id !== "drawer-status-bar") { + var moveTo = child.nextSibling; + this.element.removeChild(child); + child = moveTo; + } else + child = child.nextSibling; + } + }, + + _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(); + } +} + +WebInspector.Drawer.prototype.__proto__ = WebInspector.View.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ElementsPanel.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ElementsPanel.js new file mode 100644 index 0000000..49a1188 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ElementsPanel.js @@ -0,0 +1,1045 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> + * Copyright (C) 2009 Joseph Pecoraro + * + * 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"); + } + if (this._focusedDOMNode) + InjectedScriptAccess.addInspectedNode(this._focusedDOMNode.id, function() {}); + }; + + 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 = new WebInspector.StatusBarButton(WebInspector.UIString("Select an element in the page to inspect it."), "node-search-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._changedStyles = {}; + + this.reset(); +} + +WebInspector.ElementsPanel.prototype = { + toolbarItemClass: "elements", + + get toolbarItemLabel() + { + return WebInspector.UIString("Elements"); + }, + + get statusBarItems() + { + return [this.nodeSearchButton.element, 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.toggled = false; + } + }, + + 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.toggled = false; + } + + this.recentlyModifiedNodes = []; + + delete this.currentQuery; + this.searchCanceled(); + + var domWindow = WebInspector.domAgent.domWindow; + if (!domWindow || !domWindow.document || !domWindow.document.firstChild) + 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; + + var inspectedRootDocument = domWindow.document; + inspectedRootDocument.addEventListener("DOMNodeInserted", this._nodeInserted.bind(this)); + inspectedRootDocument.addEventListener("DOMNodeRemoved", this._nodeRemoved.bind(this)); + + 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(); + } + }, + + searchCanceled: function() + { + if (this._searchResults) { + for (var i = 0; i < this._searchResults.length; ++i) { + var treeElement = this.treeOutline.findTreeElement(this._searchResults[i]); + if (treeElement) + treeElement.highlighted = false; + } + } + + WebInspector.updateSearchMatchesCount(0, this); + + this._currentSearchResultIndex = 0; + this._searchResults = []; + InjectedScriptAccess.searchCanceled(function() {}); + }, + + 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; + + this._updatedMatchCountOnce = false; + this._matchesCountUpdateTimeout = null; + + InjectedScriptAccess.performSearch(whitespaceTrimmedQuery, function() {}); + }, + + _updateMatchesCount: function() + { + WebInspector.updateSearchMatchesCount(this._searchResults.length, this); + this._matchesCountUpdateTimeout = null; + this._updatedMatchCountOnce = true; + }, + + _updateMatchesCountSoon: function() + { + if (!this._updatedMatchCountOnce) + return this._updateMatchesCount(); + if (this._matchesCountUpdateTimeout) + return; + // Update the matches count every half-second so it doesn't feel twitchy. + this._matchesCountUpdateTimeout = setTimeout(this._updateMatchesCount.bind(this), 500); + }, + + addNodesToSearchResult: function(nodeIds) + { + if (!nodeIds) + return; + + var nodeIdsArray = nodeIds.split(","); + for (var i = 0; i < nodeIdsArray.length; ++i) { + var nodeId = nodeIdsArray[i]; + var node = WebInspector.domAgent.nodeForId(nodeId); + if (!node) + continue; + + if (!this._searchResults.length) { + this._currentSearchResultIndex = 0; + this.focusedDOMNode = node; + } + + 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; + } + + this._updateMatchesCountSoon(); + }, + + 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]; + }, + + renameSelector: function(oldIdentifier, newIdentifier, oldSelector, newSelector) + { + // TODO: Implement Shifting the oldSelector, and its contents to a newSelector + }, + + addStyleChange: function(identifier, style, property) + { + if (!style.parentRule) + return; + + var selector = style.parentRule.selectorText; + if (!this._changedStyles[identifier]) + this._changedStyles[identifier] = {}; + + if (!this._changedStyles[identifier][selector]) + this._changedStyles[identifier][selector] = {}; + + if (!this._changedStyles[identifier][selector][property]) + WebInspector.styleChanges += 1; + + this._changedStyles[identifier][selector][property] = style.getPropertyValue(property); + }, + + removeStyleChange: function(identifier, style, property) + { + if (!style.parentRule) + return; + + var selector = style.parentRule.selectorText; + if (!this._changedStyles[identifier] || !this._changedStyles[identifier][selector]) + return; + + if (this._changedStyles[identifier][selector][property]) { + delete this._changedStyles[identifier][selector][property]; + WebInspector.styleChanges -= 1; + } + }, + + generateStylesheet: function() + { + if (!WebInspector.styleChanges) + return; + + // Merge Down to Just Selectors + var mergedSelectors = {}; + for (var identifier in this._changedStyles) { + for (var selector in this._changedStyles[identifier]) { + if (!mergedSelectors[selector]) + mergedSelectors[selector] = this._changedStyles[identifier][selector]; + else { // merge on selector + var merge = {}; + for (var property in mergedSelectors[selector]) + merge[property] = mergedSelectors[selector][property]; + for (var property in this._changedStyles[identifier][selector]) { + if (!merge[property]) + merge[property] = this._changedStyles[identifier][selector][property]; + else { // merge on property within a selector, include comment to notify user + var value1 = merge[property]; + var value2 = this._changedStyles[identifier][selector][property]; + + if (value1 === value2) + merge[property] = [value1]; + else if (value1 instanceof Array) + merge[property].push(value2); + else + merge[property] = [value1, value2]; + } + } + mergedSelectors[selector] = merge; + } + } + } + + var builder = []; + builder.push("/**"); + builder.push(" * Inspector Generated Stylesheet"); // UIString? + builder.push(" */\n"); + + var indent = " "; + function displayProperty(property, value, comment) { + if (comment) + return indent + "/* " + property + ": " + value + "; */"; + else + return indent + property + ": " + value + ";"; + } + + for (var selector in mergedSelectors) { + var psuedoStyle = mergedSelectors[selector]; + var properties = Object.properties(psuedoStyle); + if (properties.length) { + builder.push(selector + " {"); + for (var i = 0; i < properties.length; ++i) { + var property = properties[i]; + var value = psuedoStyle[property]; + if (!(value instanceof Array)) + builder.push(displayProperty(property, value)); + else { + if (value.length === 1) + builder.push(displayProperty(property, value) + " /* merged from equivalent edits */"); // UIString? + else { + builder.push(indent + "/* There was a Conflict... There were Multiple Edits for '" + property + "' */"); // UIString? + for (var j = 0; j < value.length; ++j) + builder.push(displayProperty(property, value, true)); + } + } + } + builder.push("}\n"); + } + } + + WebInspector.showConsole(); + WebInspector.console.addMessage(new WebInspector.ConsoleTextMessage(builder.join("\n"))); + }, + + 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; + }, + + _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); + if (parentNodeItem && !parentNodeItem.alreadyUpdatedChildren) { + parentNodeItem.updateChildren(replaced); + parentNodeItem.alreadyUpdatedChildren = true; + updatedParentTreeElements.push(parentNodeItem); + } + + if (!updateBreadcrumbs && (this.focusedDOMNode === parent || isAncestor(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 (crumb.representedObject === this.rootDOMNode) + foundRoot = true; + + if (foundRoot) + crumb.addStyleClass("dimmed"); + else + crumb.removeStyleClass("dimmed"); + + if (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 = current.parentNode) { + if (current.nodeType === Node.DOCUMENT_NODE) + continue; + + if (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 (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.drawer.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: + // TODO: Introduce InspectorController.copyEvent that pushes appropriate markup into the clipboard. + var data = null; + 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(); + + this.nodeSearchButton.toggled = InspectorController.searchingForNode(); + } +} + +WebInspector.ElementsPanel.prototype.__proto__ = WebInspector.Panel.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ElementsTreeOutline.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ElementsTreeOutline.js new file mode 100644 index 0000000..08ba1c2 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ElementsTreeOutline.js @@ -0,0 +1,742 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> + * Copyright (C) 2009 Joseph Pecoraro + * + * 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 (this._rootDOMNode === x) + return; + + this._rootDOMNode = x; + + this.update(); + }, + + get focusedDOMNode() + { + return this._focusedDOMNode; + }, + + set focusedDOMNode(x) + { + if (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 (this._focusedDOMNode === x) { + this.focusedNodeChanged(); + + if (x && !this.suppressSelectHighlight) { + InspectorController.highlightDOMNode(x.id); + + if ("_restorePreviousHighlightNodeTimeout" in this) + clearTimeout(this._restorePreviousHighlightNodeTimeout); + + function restoreHighlightToHoveredNode() + { + var hoveredNode = WebInspector.hoveredDOMNode; + if (hoveredNode) + InspectorController.highlightDOMNode(hoveredNode.id); + 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) + { + var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestorNode, parentNode); + 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, isAncestorNode, parentNode); + } + + 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 && 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 = 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); + + if (this.representedObject.nodeType == Node.ELEMENT_NODE) + this._canAddAttributes = true; +} + +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"); + if (this._canAddAttributes) + this.toggleNewAttributeButton(); + } + }, + + toggleNewAttributeButton: function() + { + function removeWhenEditing(event) + { + if (this._addAttributeElement && this._addAttributeElement.parentNode) + this._addAttributeElement.parentNode.removeChild(this._addAttributeElement); + delete this._addAttributeElement; + } + + if (!this._addAttributeElement && this._hovered && !this._editing) { + var span = document.createElement("span"); + span.className = "add-attribute"; + span.textContent = "\u2026"; + span.addEventListener("dblclick", removeWhenEditing.bind(this), false); + this._addAttributeElement = span; + + var tag = this.listItemElement.getElementsByClassName("webkit-html-tag")[0]; + this._insertInLastAttributePosition(tag, span); + } else if (!this._hovered && this._addAttributeElement) { + if (this._addAttributeElement.parentNode) + this._addAttributeElement.parentNode.removeChild(this._addAttributeElement); + delete this._addAttributeElement; + } + }, + + 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) + { + WebInspector.domAgent.getChildNodesAsync(this.representedObject, this._updateChildren.bind(this, fullRefresh)); + }, + + _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 || 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 (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 (currentParentNode === this.representedObject) + continue; + + var selectedTreeElement = this.treeOutline.selectedTreeElement; + if (selectedTreeElement && (selectedTreeElement === currentChild || selectedTreeElement.hasAncestor(currentChild))) + this.select(); + + this.removeChildAtIndex(i); + } + + 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\"></" + this.representedObject.nodeName.toLowerCase().escapeHTML() + "></span>"; + var item = new TreeElement(title, null, false); + item.selectable = false; + item.elementCloseTag = true; + this.appendChild(item); + } + }, + + onexpand: function() + { + this.treeOutline.updateSelection(); + }, + + 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, treeElement)) + return; + + if (this.treeOutline.panel) { + this.treeOutline.rootDOMNode = this.representedObject.parentNode; + this.treeOutline.focusedDOMNode = this.representedObject; + } + + if (this.hasChildren && !this.expanded) + this.expand(); + }, + + _insertInLastAttributePosition: function(tag, node) + { + if (tag.getElementsByClassName("webkit-html-attribute").length > 0) + tag.insertBefore(node, tag.lastChild); + else { + var nodeName = tag.textContent.match(/^<(.*?)>$/)[1]; + tag.textContent = ''; + tag.appendChild(document.createTextNode('<'+nodeName)); + tag.appendChild(node); + tag.appendChild(document.createTextNode('>')); + } + }, + + _startEditing: function(event, treeElement) + { + 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.target); + + var newAttribute = event.target.enclosingNodeOrSelfWithClass("add-attribute"); + if (newAttribute) + return this._addNewAttribute(treeElement.listItemElement); + + return false; + }, + + _addNewAttribute: function(listItemElement) + { + var attr = document.createElement("span"); + attr.className = "webkit-html-attribute"; + attr.style.marginLeft = "2px"; // overrides the .editing margin rule + attr.style.marginRight = "2px"; // overrides the .editing margin rule + var name = document.createElement("span"); + name.className = "webkit-html-attribute-name new-attribute"; + name.textContent = " "; + var value = document.createElement("span"); + value.className = "webkit-html-attribute-value"; + attr.appendChild(name); + attr.appendChild(value); + + var tag = listItemElement.getElementsByClassName("webkit-html-tag")[0]; + this._insertInLastAttributePosition(tag, attr); + return this._startEditingAttribute(attr, attr); + }, + + _triggerEditAttribute: function(attributeName) + { + var attributeElements = this.listItemElement.getElementsByClassName("webkit-html-attribute-name"); + for (var i = 0, len = attributeElements.length; i < len; ++i) { + if (attributeElements[i].textContent === attributeName) { + for (var elem = attributeElements[i].nextSibling; elem; elem = elem.nextSibling) { + if (elem.nodeType !== Node.ELEMENT_NODE) + continue; + + if (elem.hasStyleClass("webkit-html-attribute-value")) + return this._startEditingAttribute(attributeElements[i].parentNode, elem); + } + } + } + }, + + _startEditingAttribute: function(attribute, elementForSelection) + { + 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(elementForSelection, 0, elementForSelection, 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, moveDirection) + { + delete this._editing; + + // Before we do anything, determine where we should move + // next based on the current element's settings + var moveToAttribute; + var newAttribute; + if (moveDirection) { + var found = false; + var attributes = this.representedObject.attributes; + for (var i = 0, len = attributes.length; i < len; ++i) { + if (attributes[i].name === attributeName) { + found = true; + if (moveDirection === "backward" && i > 0) + moveToAttribute = attributes[i - 1].name; + else if (moveDirection === "forward" && i < attributes.length - 1) + moveToAttribute = attributes[i + 1].name; + else if (moveDirection === "forward" && i === attributes.length - 1) + newAttribute = true; + } + } + + if (!found && moveDirection === "backward") + moveToAttribute = attributes[attributes.length - 1].name; + else if (!found && moveDirection === "forward" && !/^\s*$/.test(newText)) + newAttribute = true; + } + + function moveToNextAttributeIfNeeded() { + if (moveToAttribute) + this._triggerEditAttribute(moveToAttribute); + else if (newAttribute) + this._addNewAttribute(this.listItemElement); + } + + var parseContainerElement = document.createElement("span"); + parseContainerElement.innerHTML = "<span " + newText + "></span>"; + var parseElement = parseContainerElement.firstChild; + + if (!parseElement) { + this._editingCancelled(element, attributeName); + moveToNextAttributeIfNeeded.call(this); + return; + } + + if (!parseElement.hasAttributes()) { + this.representedObject.removeAttribute(attributeName); + this._updateTitle(); + moveToNextAttributeIfNeeded.call(this); + return; + } + + var foundOriginalAttribute = false; + for (var i = 0; i < parseElement.attributes.length; ++i) { + var attr = parseElement.attributes[i]; + foundOriginalAttribute = foundOriginalAttribute || attr.name === attributeName; + try { + this.representedObject.setAttribute(attr.name, attr.value); + } catch(e) {} // ignore invalid attribute (innerHTML doesn't throw errors, but this can) + } + + if (!foundOriginalAttribute) + this.representedObject.removeAttribute(attributeName); + + this._updateTitle(); + + this.treeOutline.focusedNodeChanged(true); + + moveToNextAttributeIfNeeded.call(this); + }, + + _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_frame/tools/test/reference_build/chrome/resources/inspector/FontView.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/FontView.js new file mode 100644 index 0000000..4e1c931 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/ImageView.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ImageView.js new file mode 100644 index 0000000..001ffdd --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/InjectedScript.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/InjectedScript.js new file mode 100644 index 0000000..b3d9566 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/InjectedScript.js @@ -0,0 +1,1133 @@ +/* + * 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. + */ + +var InjectedScript = {}; + +// Called from within InspectorController on the 'inspected page' side. +InjectedScript.reset = function() +{ + InjectedScript._styles = {}; + InjectedScript._styleRules = {}; + InjectedScript._lastStyleId = 0; + InjectedScript._lastStyleRuleId = 0; + InjectedScript._searchResults = []; + InjectedScript._includedInSearchResultsPropertyName = "__includedInInspectorSearchResults"; +} + +InjectedScript.reset(); + +InjectedScript.dispatch = function(methodName, args) +{ + var result = InjectedScript[methodName].apply(InjectedScript, JSON.parse(args)); + return JSON.stringify(result); +} + +InjectedScript.getStyles = function(nodeId, authorOnly) +{ + var node = InjectedScript._nodeForId(nodeId); + if (!node) + return false; + var matchedRules = InjectedScript._window().getMatchedCSSRules(node, "", authorOnly); + var matchedCSSRules = []; + for (var i = 0; matchedRules && i < matchedRules.length; ++i) + matchedCSSRules.push(InjectedScript._serializeRule(matchedRules[i])); + + var styleAttributes = {}; + var attributes = node.attributes; + for (var i = 0; attributes && i < attributes.length; ++i) { + if (attributes[i].style) + styleAttributes[attributes[i].name] = InjectedScript._serializeStyle(attributes[i].style, true); + } + var result = {}; + result.inlineStyle = InjectedScript._serializeStyle(node.style, true); + result.computedStyle = InjectedScript._serializeStyle(InjectedScript._window().getComputedStyle(node)); + result.matchedCSSRules = matchedCSSRules; + result.styleAttributes = styleAttributes; + return result; +} + +InjectedScript.getComputedStyle = function(nodeId) +{ + var node = InjectedScript._nodeForId(nodeId); + if (!node) + return false; + return InjectedScript._serializeStyle(InjectedScript._window().getComputedStyle(node)); +} + +InjectedScript.getInlineStyle = function(nodeId) +{ + var node = InjectedScript._nodeForId(nodeId); + if (!node) + return false; + return InjectedScript._serializeStyle(node.style, true); +} + +InjectedScript.applyStyleText = function(styleId, styleText, propertyName) +{ + var style = InjectedScript._styles[styleId]; + if (!style) + return false; + + var styleTextLength = 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(propertyName)) { + var longhandProperties = InjectedScript._getLonghandProperties(style, propertyName); + for (var i = 0; i < longhandProperties.length; ++i) + style.removeProperty(longhandProperties[i]); + } else + style.removeProperty(propertyName); + } + + // Notify caller that the property was successfully deleted. + if (!styleTextLength) + return [null, [propertyName]]; + + if (!tempStyle.length) + 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 changedProperties = []; + var uniqueProperties = InjectedScript._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 = InjectedScript._getShorthandValue(tempStyle, shorthand); + var priority = InjectedScript._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); + changedProperties.push(shorthand || name); + } + return [InjectedScript._serializeStyle(style, true), changedProperties]; +} + +InjectedScript.setStyleText = function(style, cssText) +{ + style.cssText = cssText; +} + +InjectedScript.toggleStyleEnabled = function(styleId, propertyName, disabled) +{ + var style = InjectedScript._styles[styleId]; + if (!style) + return false; + + if (disabled) { + if (!style.__disabledPropertyValues || !style.__disabledPropertyPriorities) { + var inspectedWindow = InjectedScript._window(); + style.__disabledProperties = new inspectedWindow.Object; + style.__disabledPropertyValues = new inspectedWindow.Object; + style.__disabledPropertyPriorities = new inspectedWindow.Object; + } + + style.__disabledPropertyValues[propertyName] = style.getPropertyValue(propertyName); + style.__disabledPropertyPriorities[propertyName] = style.getPropertyPriority(propertyName); + + if (style.getPropertyShorthand(propertyName)) { + var longhandProperties = InjectedScript._getLonghandProperties(style, propertyName); + for (var i = 0; i < longhandProperties.length; ++i) { + style.__disabledProperties[longhandProperties[i]] = true; + style.removeProperty(longhandProperties[i]); + } + } else { + style.__disabledProperties[propertyName] = true; + style.removeProperty(propertyName); + } + } else if (style.__disabledProperties && style.__disabledProperties[propertyName]) { + var value = style.__disabledPropertyValues[propertyName]; + var priority = style.__disabledPropertyPriorities[propertyName]; + + style.setProperty(propertyName, value, priority); + delete style.__disabledProperties[propertyName]; + delete style.__disabledPropertyValues[propertyName]; + delete style.__disabledPropertyPriorities[propertyName]; + } + return InjectedScript._serializeStyle(style, true); +} + +InjectedScript.applyStyleRuleText = function(ruleId, newContent, selectedNodeId) +{ + var rule = InjectedScript._styleRules[ruleId]; + if (!rule) + return false; + + var selectedNode = InjectedScript._nodeForId(selectedNodeId); + + try { + var stylesheet = rule.parentStyleSheet; + stylesheet.addRule(newContent); + var newRule = stylesheet.cssRules[stylesheet.cssRules.length - 1]; + newRule.style.cssText = rule.style.cssText; + + var parentRules = stylesheet.cssRules; + for (var i = 0; i < parentRules.length; ++i) { + if (parentRules[i] === rule) { + rule.parentStyleSheet.removeRule(i); + break; + } + } + + return [InjectedScript._serializeRule(newRule), InjectedScript._doesSelectorAffectNode(newContent, selectedNode)]; + } catch(e) { + // Report invalid syntax. + return false; + } +} + +InjectedScript.addStyleSelector = function(newContent, selectedNodeId) +{ + var stylesheet = InjectedScript.stylesheet; + if (!stylesheet) { + var inspectedDocument = InjectedScript._window().document; + var head = inspectedDocument.getElementsByTagName("head")[0]; + var styleElement = inspectedDocument.createElement("style"); + styleElement.type = "text/css"; + head.appendChild(styleElement); + stylesheet = inspectedDocument.styleSheets[inspectedDocument.styleSheets.length - 1]; + InjectedScript.stylesheet = stylesheet; + } + + try { + stylesheet.addRule(newContent); + } catch (e) { + // Invalid Syntax for a Selector + return false; + } + + var selectedNode = InjectedScript._nodeForId(selectedNodeId); + var rule = stylesheet.cssRules[stylesheet.cssRules.length - 1]; + rule.__isViaInspector = true; + + return [ InjectedScript._serializeRule(rule), InjectedScript._doesSelectorAffectNode(newContent, selectedNode) ]; +} + +InjectedScript._doesSelectorAffectNode = function(selectorText, node) +{ + if (!node) + return false; + var nodes = node.ownerDocument.querySelectorAll(selectorText); + for (var i = 0; i < nodes.length; ++i) { + if (nodes[i] === node) { + return true; + } + } + return false; +} + +InjectedScript.setStyleProperty = function(styleId, name, value) +{ + var style = InjectedScript._styles[styleId]; + if (!style) + return false; + + style.setProperty(name, value, ""); + return true; +} + +InjectedScript._serializeRule = function(rule) +{ + var parentStyleSheet = rule.parentStyleSheet; + + var ruleValue = {}; + ruleValue.selectorText = rule.selectorText; + if (parentStyleSheet) { + ruleValue.parentStyleSheet = {}; + ruleValue.parentStyleSheet.href = parentStyleSheet.href; + } + ruleValue.isUserAgent = parentStyleSheet && !parentStyleSheet.ownerNode && !parentStyleSheet.href; + ruleValue.isUser = parentStyleSheet && parentStyleSheet.ownerNode && parentStyleSheet.ownerNode.nodeName == "#document"; + ruleValue.isViaInspector = !!rule.__isViaInspector; + + // Bind editable scripts only. + var doBind = !ruleValue.isUserAgent && !ruleValue.isUser; + ruleValue.style = InjectedScript._serializeStyle(rule.style, doBind); + + if (doBind) { + if (!rule.id) { + rule.id = InjectedScript._lastStyleRuleId++; + InjectedScript._styleRules[rule.id] = rule; + } + ruleValue.id = rule.id; + } + return ruleValue; +} + +InjectedScript._serializeStyle = function(style, doBind) +{ + var result = {}; + result.width = style.width; + result.height = style.height; + result.__disabledProperties = style.__disabledProperties; + result.__disabledPropertyValues = style.__disabledPropertyValues; + result.__disabledPropertyPriorities = style.__disabledPropertyPriorities; + result.properties = []; + result.shorthandValues = {}; + var foundShorthands = {}; + for (var i = 0; i < style.length; ++i) { + var property = {}; + var name = style[i]; + property.name = name; + property.priority = style.getPropertyPriority(name); + property.implicit = style.isPropertyImplicit(name); + var shorthand = style.getPropertyShorthand(name); + property.shorthand = shorthand; + if (shorthand && !(shorthand in foundShorthands)) { + foundShorthands[shorthand] = true; + result.shorthandValues[shorthand] = InjectedScript._getShorthandValue(style, shorthand); + } + property.value = style.getPropertyValue(name); + result.properties.push(property); + } + result.uniqueStyleProperties = InjectedScript._getUniqueStyleProperties(style); + + if (doBind) { + if (!style.id) { + style.id = InjectedScript._lastStyleId++; + InjectedScript._styles[style.id] = style; + } + result.id = style.id; + } + return result; +} + +InjectedScript._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; +} + + +InjectedScript._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; +} + +InjectedScript._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; +} + +InjectedScript._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; +} + +InjectedScript.getPrototypes = function(nodeId) +{ + var node = InjectedScript._nodeForId(nodeId); + if (!node) + return false; + + var result = []; + for (var prototype = node; prototype; prototype = prototype.__proto__) { + var title = Object.describe(prototype); + if (title.match(/Prototype$/)) { + title = title.replace(/Prototype$/, ""); + } + result.push(title); + } + return result; +} + +InjectedScript.getProperties = function(objectProxy, ignoreHasOwnProperty) +{ + var object = InjectedScript._resolveObject(objectProxy); + if (!object) + return false; + + var properties = []; + + // Go over properties, prepare results. + for (var propertyName in object) { + if (!ignoreHasOwnProperty && "hasOwnProperty" in object && !object.hasOwnProperty(propertyName)) + continue; + + var property = {}; + property.name = propertyName; + property.parentObjectProxy = objectProxy; + var isGetter = object["__lookupGetter__"] && object.__lookupGetter__(propertyName); + if (!property.isGetter) { + var childObject = object[propertyName]; + var childObjectProxy = new InjectedScript.createProxyObject(childObject, objectProxy.objectId, true); + childObjectProxy.path = objectProxy.path ? objectProxy.path.slice() : []; + childObjectProxy.path.push(propertyName); + childObjectProxy.protoDepth = objectProxy.protoDepth || 0; + property.value = childObjectProxy; + } else { + // FIXME: this should show something like "getter" (bug 16734). + property.value = { description: "\u2014" }; // em dash + property.isGetter = true; + } + properties.push(property); + } + return properties; +} + +InjectedScript.setPropertyValue = function(objectProxy, propertyName, expression) +{ + var object = InjectedScript._resolveObject(objectProxy); + if (!object) + return false; + + var expressionLength = expression.length; + if (!expressionLength) { + delete object[propertyName]; + return !(propertyName in object); + } + + 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. + + // There is a regression introduced here: eval is now happening against global object, + // not call frame while on a breakpoint. + // TODO: bring evaluation against call frame back. + var result = InjectedScript._window().eval("(" + expression + ")"); + // Store the result in the property. + object[propertyName] = result; + return true; + } catch(e) { + try { + var result = InjectedScript._window().eval("\"" + expression.escapeCharacters("\"") + "\""); + object[propertyName] = result; + return true; + } catch(e) { + return false; + } + } +} + + +InjectedScript.getCompletions = function(expression, includeInspectorCommandLineAPI) +{ + var props = {}; + try { + var expressionResult = InjectedScript._evaluateOn(InjectedScript._window().eval, InjectedScript._window(), expression); + for (var prop in expressionResult) + props[prop] = true; + if (includeInspectorCommandLineAPI) + for (var prop in InjectedScript._window()._inspectorCommandLineAPI) + if (prop.charAt(0) !== '_') + props[prop] = true; + } catch(e) { + } + return props; +} + + +InjectedScript.evaluate = function(expression) +{ + var result = {}; + try { + var value = InjectedScript._evaluateOn(InjectedScript._window().eval, InjectedScript._window(), expression); + if (value === null) + return { value: null }; + if (Object.type(value) === "error") { + result.value = Object.describe(value); + result.isException = true; + return result; + } + + var wrapper = InspectorController.wrapObject(value); + if (typeof wrapper === "object" && wrapper.exception) { + result.value = wrapper.exception; + result.isException = true; + } else { + result.value = wrapper; + } + } catch (e) { + result.value = e.toString(); + result.isException = true; + } + return result; +} + +InjectedScript._evaluateOn = function(evalFunction, object, expression) +{ + InjectedScript._ensureCommandLineAPIInstalled(); + // 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 evalFunction.call(object, expression); +} + +InjectedScript.addInspectedNode = function(nodeId) +{ + var node = InjectedScript._nodeForId(nodeId); + if (!node) + return false; + + InjectedScript._ensureCommandLineAPIInstalled(); + var inspectedNodes = InjectedScript._window()._inspectorCommandLineAPI._inspectedNodes; + inspectedNodes.unshift(node); + if (inspectedNodes.length >= 5) + inspectedNodes.pop(); + return true; +} + +InjectedScript.performSearch = function(whitespaceTrimmedQuery) +{ + 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 = whitespaceTrimmedQuery.escapeCharacters("'"); + const escapedTagNameQuery = (tagNameQuery ? tagNameQuery.escapeCharacters("'") : null); + const escapedWhitespaceTrimmedQuery = whitespaceTrimmedQuery.escapeCharacters("'"); + const searchResultsProperty = InjectedScript._includedInSearchResultsPropertyName; + + function addNodesToResults(nodes, length, getItem) + { + if (!length) + return; + + var nodeIds = []; + 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 (!InjectedScript._searchResults.length) { + InjectedScript._currentSearchResultIndex = 0; + } + + node[searchResultsProperty] = true; + InjectedScript._searchResults.push(node); + var nodeId = InspectorController.pushNodePathToFrontend(node, false); + nodeIds.push(nodeId); + } + InspectorController.addNodesToSearchResult(nodeIds.join(",")); + } + + 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 < InjectedScript._searchResults.length; ++i) + delete InjectedScript._searchResults[i][searchResultsProperty]; + } + + const mainFrameDocument = InjectedScript._window().document; + const searchDocuments = [mainFrameDocument]; + var searchFunctions; + if (tagNameQuery && startTagFound && endTagFound) + searchFunctions = [matchExactTagNames, matchPlainText]; + else if (tagNameQuery && startTagFound) + 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(). + 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. + searchFunctions = [matchPartialAttributeValues, matchPlainText]; + } else + searchFunctions = [matchExactItems, matchStyleSelector, matchPartialTagNamesAndAttributeValues, matchPlainText, matchXPathQuery]; + + // Find all frames, iframes and object elements to search their documents. + const querySelectorAllFunction = InjectedScript._window().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 = InjectedScript; + 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); + InjectedScript._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier; + return true; +} + +InjectedScript.searchCanceled = function() +{ + if (InjectedScript._searchResults) { + const searchResultsProperty = InjectedScript._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]; + } + } + + if (InjectedScript._currentSearchChunkIntervalIdentifier) { + clearInterval(InjectedScript._currentSearchChunkIntervalIdentifier); + delete InjectedScript._currentSearchChunkIntervalIdentifier; + } + InjectedScript._searchResults = []; + return true; +} + +InjectedScript.openInInspectedWindow = function(url) +{ + InjectedScript._window().open(url); +} + +InjectedScript.getCallFrames = function() +{ + var callFrame = InspectorController.currentCallFrame(); + if (!callFrame) + return false; + + var result = []; + var depth = 0; + do { + result.push(new InjectedScript.CallFrameProxy(depth++, callFrame)); + callFrame = callFrame.caller; + } while (callFrame); + return result; +} + +InjectedScript.evaluateInCallFrame = function(callFrameId, code) +{ + var callFrame = InjectedScript._callFrameForId(callFrameId); + if (!callFrame) + return false; + return InjectedScript._evaluateOn(callFrame.evaluate, callFrame, code); +} + +InjectedScript._callFrameForId = function(id) +{ + var callFrame = InspectorController.currentCallFrame(); + while (--id >= 0 && callFrame) + callFrame = callFrame.caller; + return callFrame; +} + +InjectedScript._clearConsoleMessages = function() +{ + InspectorController.clearMessages(true); +} + +InjectedScript._inspectObject = function(o) +{ + if (arguments.length === 0) + return; + + var inspectedWindow = InjectedScript._window(); + inspectedWindow.console.log(o); + if (Object.type(o) === "node") { + InspectorController.pushNodePathToFrontend(o, true); + } else { + switch (Object.describe(o)) { + case "Database": + InspectorController.selectDatabase(o); + break; + case "Storage": + InspectorController.selectDOMStorage(o); + break; + } + } +} + +InjectedScript._ensureCommandLineAPIInstalled = function(inspectedWindow) +{ + var inspectedWindow = InjectedScript._window(); + if (inspectedWindow._inspectorCommandLineAPI) + return; + + 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 (var k in o) a.push(k); return a; }, \ + values: function(o) { var a = []; for (var 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) }, \ + _inspectedNodes: [], \ + get $0() { return _inspectorCommandLineAPI._inspectedNodes[0] }, \ + get $1() { return _inspectorCommandLineAPI._inspectedNodes[1] }, \ + get $2() { return _inspectorCommandLineAPI._inspectedNodes[2] }, \ + get $3() { return _inspectorCommandLineAPI._inspectedNodes[3] }, \ + get $4() { return _inspectorCommandLineAPI._inspectedNodes[4] } \ + };"); + + inspectedWindow._inspectorCommandLineAPI.clear = InspectorController.wrapCallback(InjectedScript._clearConsoleMessages); + inspectedWindow._inspectorCommandLineAPI.inspect = InspectorController.wrapCallback(InjectedScript._inspectObject); +} + +InjectedScript._resolveObject = function(objectProxy) +{ + var object = InjectedScript._objectForId(objectProxy.objectId); + var path = objectProxy.path; + var protoDepth = objectProxy.protoDepth; + + // Follow the property path. + for (var i = 0; object && path && i < path.length; ++i) + object = object[path[i]]; + + // Get to the necessary proto layer. + for (var i = 0; object && protoDepth && i < protoDepth; ++i) + object = object.__proto__; + + return object; +} + +InjectedScript._window = function() +{ + // TODO: replace with 'return window;' once this script is injected into + // the page's context. + return InspectorController.inspectedWindow(); +} + +InjectedScript._nodeForId = function(nodeId) +{ + if (!nodeId) + return null; + return InspectorController.nodeForId(nodeId); +} + +InjectedScript._objectForId = function(objectId) +{ + // There are three types of object ids used: + // - numbers point to DOM Node via the InspectorDOMAgent mapping + // - strings point to console objects cached in InspectorController for lazy evaluation upon them + // - objects contain complex ids and are currently used for scoped objects + if (typeof objectId === "number") { + return InjectedScript._nodeForId(objectId); + } else if (typeof objectId === "string") { + return InspectorController.unwrapObject(objectId); + } else if (typeof objectId === "object") { + var callFrame = InjectedScript._callFrameForId(objectId.callFrame); + if (objectId.thisObject) + return callFrame.thisObject; + else + return callFrame.scopeChain[objectId.chainIndex]; + } + return objectId; +} + +InjectedScript.pushNodeToFrontend = function(objectProxy) +{ + var object = InjectedScript._resolveObject(objectProxy); + if (!object || Object.type(object) !== "node") + return false; + return InspectorController.pushNodePathToFrontend(object, false); +} + +// Called from within InspectorController on the 'inspected page' side. +InjectedScript.createProxyObject = function(object, objectId, abbreviate) +{ + var result = {}; + result.objectId = objectId; + result.type = Object.type(object); + + var type = typeof object; + if ((type === "object" && object !== null) || type === "function") { + for (var subPropertyName in object) { + result.hasChildren = true; + break; + } + } + try { + result.description = Object.describe(object, abbreviate); + } catch (e) { + result.exception = e.toString(); + } + return result; +} + +InjectedScript.CallFrameProxy = function(id, callFrame) +{ + this.id = id; + this.type = callFrame.type; + this.functionName = (this.type === "function" ? callFrame.functionName : ""); + this.sourceID = callFrame.sourceID; + this.line = callFrame.line; + this.scopeChain = this._wrapScopeChain(callFrame); +} + +InjectedScript.CallFrameProxy.prototype = { + _wrapScopeChain: function(callFrame) + { + var foundLocalScope = false; + var scopeChain = callFrame.scopeChain; + var scopeChainProxy = []; + for (var i = 0; i < scopeChain.length; ++i) { + var scopeObject = scopeChain[i]; + var scopeObjectProxy = InjectedScript.createProxyObject(scopeObject, { callFrame: this.id, chainIndex: i }); + + if (Object.prototype.toString.call(scopeObject) === "[object JSActivation]") { + if (!foundLocalScope) + scopeObjectProxy.thisObject = InjectedScript.createProxyObject(callFrame.thisObject, { callFrame: this.id, thisObject: true }); + else + scopeObjectProxy.isClosure = true; + foundLocalScope = true; + scopeObjectProxy.isLocal = true; + } else if (foundLocalScope && scopeObject instanceof InjectedScript._window().Element) + scopeObjectProxy.isElement = true; + else if (foundLocalScope && scopeObject instanceof InjectedScript._window().Document) + scopeObjectProxy.isDocument = true; + else if (!foundLocalScope) + scopeObjectProxy.isWithBlock = true; + scopeObjectProxy.properties = []; + try { + for (var propertyName in scopeObject) + scopeObjectProxy.properties.push(propertyName); + } catch (e) { + } + scopeChainProxy.push(scopeObjectProxy); + } + return scopeChainProxy; + } +} + +Object.type = function(obj) +{ + if (obj === null) + return "null"; + + var type = typeof obj; + if (type !== "object" && type !== "function") + return type; + + var win = InjectedScript._window(); + + if (obj instanceof win.Node) + return (obj.nodeType === undefined ? type : "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.className(obj); + + 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.className = function(obj) +{ + return Object.prototype.toString.call(obj).replace(/^\[object (.*)\]$/i, "$1") +} + +// Although Function.prototype.bind and String.prototype.escapeCharacters are defined in utilities.js they will soon become +// unavailable in the InjectedScript context. So we define them here for the local use. +// TODO: remove this comment once InjectedScript runs in a separate context. +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))) }; +} + +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; +} diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/InjectedScriptAccess.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/InjectedScriptAccess.js new file mode 100644 index 0000000..da85d03 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/InjectedScriptAccess.js @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +var InjectedScriptAccess = {}; + +InjectedScriptAccess._installHandler = function(methodName) +{ + InjectedScriptAccess[methodName] = function() + { + var allArgs = Array.prototype.slice.call(arguments); + var callback = allArgs[allArgs.length - 1]; + var argsString = JSON.stringify(Array.prototype.slice.call(allArgs, 0, allArgs.length - 1)); + + function myCallback(result, isException) + { + if (!isException) + callback(JSON.parse(result)); + else + WebInspector.console.addMessage(new WebInspector.ConsoleTextMessage("Error dispatching: " + methodName)); + } + var callId = WebInspector.Callback.wrap(myCallback); + InspectorController.dispatchOnInjectedScript(callId, methodName, argsString); + }; +} + +InjectedScriptAccess._installHandler("getStyles"); +InjectedScriptAccess._installHandler("getComputedStyle"); +InjectedScriptAccess._installHandler("getInlineStyle"); +InjectedScriptAccess._installHandler("applyStyleText"); +InjectedScriptAccess._installHandler("setStyleText"); +InjectedScriptAccess._installHandler("toggleStyleEnabled"); +InjectedScriptAccess._installHandler("applyStyleRuleText"); +InjectedScriptAccess._installHandler("addStyleSelector"); +InjectedScriptAccess._installHandler("setStyleProperty"); +InjectedScriptAccess._installHandler("getPrototypes"); +InjectedScriptAccess._installHandler("getProperties"); +InjectedScriptAccess._installHandler("setPropertyValue"); +InjectedScriptAccess._installHandler("getCompletions"); +InjectedScriptAccess._installHandler("evaluate"); +InjectedScriptAccess._installHandler("addInspectedNode"); +InjectedScriptAccess._installHandler("pushNodeToFrontend"); +InjectedScriptAccess._installHandler("evaluate"); +InjectedScriptAccess._installHandler("addInspectedNode"); +InjectedScriptAccess._installHandler("pushNodeToFrontend"); +InjectedScriptAccess._installHandler("performSearch"); +InjectedScriptAccess._installHandler("searchCanceled"); +InjectedScriptAccess._installHandler("openInInspectedWindow"); +InjectedScriptAccess._installHandler("evaluateInCallFrame"); + +WebInspector.didDispatchOnInjectedScript = WebInspector.Callback.processCallback; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/KeyboardShortcut.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/KeyboardShortcut.js new file mode 100644 index 0000000..ed28a48 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/KeyboardShortcut.js @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 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.KeyboardShortcut = function() +{ +}; + +/** + * Constants for encoding modifier key set as a bit mask. + * @see #_makeKeyFromCodeAndModifiers + */ +WebInspector.KeyboardShortcut.Modifiers = { + None: 0, // Constant for empty modifiers set. + Shift: 1, + Ctrl: 2, + Alt: 4, + Meta: 8 // Command key on Mac, Win key on other platforms. +}; + +WebInspector.KeyboardShortcut.KeyCodes = { + Esc: 27, + Space: 32, + PageUp: 33, // also NUM_NORTH_EAST + PageDown: 34, // also NUM_SOUTH_EAST + End: 35, // also NUM_SOUTH_WEST + Home: 36, // also NUM_NORTH_WEST + Left: 37, // also NUM_WEST + Up: 38, // also NUM_NORTH + Right: 39, // also NUM_EAST + Down: 40, // also NUM_SOUTH + F1: 112, + F2: 113, + F3: 114, + F4: 115, + F5: 116, + F6: 117, + F7: 118, + F8: 119, + F9: 120, + F10: 121, + F11: 122, + F12: 123, + Semicolon: 186, // ; + Comma: 188, // , + Period: 190, // . + Slash: 191, // / + Apostrophe: 192, // ` + SingleQuote: 222, // ' +}; + +/** + * Creates a number encoding keyCode in the lower 8 bits and modifiers mask in the higher 8 bits. + * It is usefull for matching pressed keys. + * @param {number} keyCode Code of the key. + * @param {number} optModifiers Optional list of modifiers passed as additional paramerters. + */ +WebInspector.KeyboardShortcut.makeKey = function(keyCode, optModifiers) +{ + var modifiers = WebInspector.KeyboardShortcut.Modifiers.None; + for (var i = 1; i < arguments.length; i++) + modifiers |= arguments[i]; + return WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyCode, modifiers); +}; + +WebInspector.KeyboardShortcut.makeKeyFromEvent = function(keyboardEvent) +{ + var modifiers = WebInspector.KeyboardShortcut.Modifiers.None; + if (keyboardEvent.shiftKey) + modifiers |= WebInspector.KeyboardShortcut.Modifiers.Shift; + if (keyboardEvent.ctrlKey) + modifiers |= WebInspector.KeyboardShortcut.Modifiers.Ctrl; + if (keyboardEvent.altKey) + modifiers |= WebInspector.KeyboardShortcut.Modifiers.Alt; + if (keyboardEvent.metaKey) + modifiers |= WebInspector.KeyboardShortcut.Modifiers.Meta; + return WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyboardEvent.keyCode, modifiers); +}; + +WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers = function(keyCode, modifiers) +{ + return (keyCode & 255) | (modifiers << 8); +}; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/MetricsSidebarPane.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/MetricsSidebarPane.js new file mode 100644 index 0000000..a33653b --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/MetricsSidebarPane.js @@ -0,0 +1,215 @@ +/* + * 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")); + this._inlineStyleId = null; +} + +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; + + if (node.nodeType !== Node.ELEMENT_NODE) + return; + + var self = this; + var callback = function(stylePayload) { + if (!stylePayload) + return; + var style = WebInspector.CSSStyleDeclaration.parseStyle(stylePayload); + self._update(node, body, style); + }; + InjectedScriptAccess.getComputedStyle(node.id, callback); + + var inlineStyleCallback = function(stylePayload) { + if (!stylePayload) + return; + self._inlineStyleId = stylePayload.id; + }; + InjectedScriptAccess.getInlineStyle(node.id, inlineStyleCallback); + }, + + _update: function(node, body, style) + { + 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"; + + var self = this; + var callback = function(success) { + if (!success) + return; + self.dispatchEventToListeners("metrics edited"); + self.update(); + }; + InjectedScriptAccess.setStyleProperty(this._inlineStyleId, context.styleProperty, userInput, callback); + } +} + +WebInspector.MetricsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Object.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Object.js new file mode 100644 index 0000000..80202b0 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/ObjectPropertiesSection.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ObjectPropertiesSection.js new file mode 100644 index 0000000..8bb4e35 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ObjectPropertiesSection.js @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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) +{ + 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 self = this; + var callback = function(properties) { + if (!properties) + return; + self.updateProperties(properties); + }; + InjectedScriptAccess.getProperties(this.object, this.ignoreHasOwnProperty, callback); + }, + + updateProperties: function(properties, rootTreeElementConstructor, rootPropertyComparer) + { + if (!rootTreeElementConstructor) + rootTreeElementConstructor = this.treeElementConstructor; + + if (!rootPropertyComparer) + rootPropertyComparer = WebInspector.ObjectPropertiesSection.CompareProperties; + + if (this.extraProperties) + for (var i = 0; i < this.extraProperties.length; ++i) + properties.push(this.extraProperties[i]); + + properties.sort(rootPropertyComparer); + + this.propertiesTreeOutline.removeChildren(); + + for (var i = 0; i < properties.length; ++i) + this.propertiesTreeOutline.appendChild(new rootTreeElementConstructor(properties[i])); + + 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.ObjectPropertiesSection.CompareProperties = function(propertyA, propertyB) +{ + var a = propertyA.name; + var b = propertyB.name; + + // if used elsewhere make sure to + // - convert a and b to strings (not needed here, properties are all strings) + // - check if a == b (not needed here, no two properties can be the same) + + var diff = 0; + var chunk = /^\d+|^\D+/; + var chunka, chunkb, anum, bnum; + while (diff === 0) { + if (!a && b) + return -1; + if (!b && a) + return 1; + chunka = a.match(chunk)[0]; + chunkb = b.match(chunk)[0]; + anum = !isNaN(chunka); + bnum = !isNaN(chunkb); + if (anum && !bnum) + return -1; + if (bnum && !anum) + return 1; + if (anum && bnum) { + diff = chunka - chunkb; + if (diff === 0 && chunka.length !== chunkb.length) { + if (!+chunka && !+chunkb) // chunks are strings of all 0s (special case) + return chunka.length - chunkb.length; + else + return chunkb.length - chunka.length; + } + } else if (chunka !== chunkb) + return (chunka < chunkb) ? -1 : 1; + a = a.substring(chunka.length); + b = b.substring(chunkb.length); + } + return diff; +} + +WebInspector.ObjectPropertyTreeElement = function(property) +{ + this.property = property; + + // Pass an empty title, the title gets made later in onattach. + TreeElement.call(this, "", null, false); +} + +WebInspector.ObjectPropertyTreeElement.prototype = { + onpopulate: function() + { + if (this.children.length && !this.shouldRefreshChildren) + return; + + var callback = function(properties) { + this.removeChildren(); + if (!properties) + return; + + properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties); + for (var i = 0; i < properties.length; ++i) { + this.appendChild(new this.treeOutline.section.treeElementConstructor(properties[i])); + } + }; + InjectedScriptAccess.getProperties(this.property.value, false, callback.bind(this)); + }, + + ondblclick: function(element, event) + { + this.startEditing(); + }, + + onattach: function() + { + this.update(); + }, + + update: function() + { + this.nameElement = document.createElement("span"); + this.nameElement.className = "name"; + this.nameElement.textContent = this.property.name; + + var separatorElement = document.createElement("span"); + separatorElement.className = "separator"; + separatorElement.textContent = ": "; + + this.valueElement = document.createElement("span"); + this.valueElement.className = "value"; + this.valueElement.textContent = this.property.value.description; + if (this.property.isGetter) + this.valueElement.addStyleClass("dimmed"); + + this.listItemElement.removeChildren(); + + this.listItemElement.appendChild(this.nameElement); + this.listItemElement.appendChild(separatorElement); + this.listItemElement.appendChild(this.valueElement); + this.hasChildren = this.property.value.hasChildren; + }, + + 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); + }, + + applyExpression: function(expression, updateInterface) + { + expression = expression.trimWhitespace(); + var expressionLength = expression.length; + var self = this; + var callback = function(success) { + if (!updateInterface) + return; + + if (!success) + self.update(); + + if (!expressionLength) { + // The property was deleted, so remove this tree element. + self.parent.removeChild(this); + } else { + // Call updateSiblings since their value might be based on the value that just changed. + self.updateSiblings(); + } + }; + InjectedScriptAccess.setPropertyValue(this.property.parentObjectProxy, this.property.name, expression.trimWhitespace(), callback); + } +} + +WebInspector.ObjectPropertyTreeElement.prototype.__proto__ = TreeElement.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ObjectProxy.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ObjectProxy.js new file mode 100644 index 0000000..03d16ab --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ObjectProxy.js @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +WebInspector.ObjectProxy = function(objectId, path, protoDepth, description, hasChildren) +{ + this.objectId = objectId; + this.path = path || []; + this.protoDepth = protoDepth || 0; + this.description = description; + this.hasChildren = hasChildren; +} + +WebInspector.ObjectPropertyProxy = function(name, value) +{ + this.name = name; + this.value = value; +} diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Panel.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Panel.js new file mode 100644 index 0000000..5046f6b --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/PanelEnablerView.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/PanelEnablerView.js new file mode 100644 index 0000000..fab6d76 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/Placard.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Placard.js new file mode 100644 index 0000000..69a168e --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/Popup.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Popup.js new file mode 100644 index 0000000..9c8ef24 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Popup.js @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This class provides a popup that can be shown relative to an anchor element + * or at an arbitrary absolute position. + * Points are Objects: {x: xValue, y: yValue}. + * Rectangles are Objects: {x: xValue, y: yValue, width: widthValue, height: heightValue}. + * + * element is an optional unparented visible element (style.display != "none" AND style.visibility != "hidden"). + * If the element is absent/undefined, it must have been set with the element(x) setter before the show() method invocation. + */ +WebInspector.Popup = function(element) +{ + if (element) + this.element = element; + this._keyHandler = this._keyEventHandler.bind(this); + this._mouseDownHandler = this._mouseDownEventHandler.bind(this); + this._visible = false; + this._autoHide = true; +} + +WebInspector.Popup.prototype = { + show: function() + { + if (this.visible) + return; + var ownerDocument = this._contentElement.ownerDocument; + if (!ownerDocument) + return; + + this._glasspaneElement = ownerDocument.createElement("div"); + this._glasspaneElement.className = "popup-glasspane"; + ownerDocument.body.appendChild(this._glasspaneElement); + + this._contentElement.positionAt(0, 0); + this._contentElement.removeStyleClass("hidden"); + ownerDocument.body.appendChild(this._contentElement); + + this.positionElement(); + this._visible = true; + ownerDocument.addEventListener("keydown", this._keyHandler, false); + ownerDocument.addEventListener("mousedown", this._mouseDownHandler, false); + }, + + hide: function() + { + if (this.visible) { + this._visible = false; + this._contentElement.ownerDocument.removeEventListener("keydown", this._keyHandler, false); + this._contentElement.ownerDocument.removeEventListener("mousedown", this._mouseDownHandler, false); + this._glasspaneElement.parentElement.removeChild(this._glasspaneElement); + this._contentElement.parentElement.removeChild(this._contentElement); + } + }, + + get visible() + { + return this._visible; + }, + + set element(x) + { + this._checkNotVisible(); + this._contentElement = x; + this._contentElement.addStyleClass("hidden"); + }, + + get element() + { + return this._contentElement; + }, + + positionElement: function() + { + var element = this._contentElement; + var anchorElement = this._anchorElement; + + var targetDocument = element.ownerDocument; + var targetDocumentBody = targetDocument.body; + var targetDocumentElement = targetDocument.documentElement; + var clippingBox = {x: 0, y: 0, width: targetDocumentElement.clientWidth, height: targetDocumentElement.clientHeight}; + var parentElement = element.offsetParent || element.parentElement; + + var anchorPosition = {x: anchorElement.totalOffsetLeft, y: anchorElement.totalOffsetTop}; + + // FIXME(apavlov@chromium.org): Translate anchorPosition to the element.ownerDocument frame when https://bugs.webkit.org/show_bug.cgi?id=28913 is fixed. + var anchorBox = {x: anchorPosition.x, y: anchorPosition.y, width: anchorElement.offsetWidth, height: anchorElement.offsetHeight}; + var elementBox = {x: element.totalOffsetLeft, y: element.totalOffsetTop, width: element.offsetWidth, height: element.offsetHeight}; + var newElementPosition = {x: 0, y: 0}; + + if (anchorBox.y - elementBox.height >= clippingBox.y) + newElementPosition.y = anchorBox.y - elementBox.height; + else + newElementPosition.y = Math.min(anchorBox.y + anchorBox.height, Math.max(clippingBox.y, clippingBox.y + clippingBox.height - elementBox.height)); + + if (anchorBox.x + elementBox.height <= clippingBox.x + clippingBox.height) + newElementPosition.x = anchorBox.x; + else + newElementPosition.x = Math.max(clippingBox.x, clippingBox.x + clippingBox.height - elementBox.height); + element.positionAt(newElementPosition.x, newElementPosition.y); + }, + + set anchor(x) + { + this._checkNotVisible(); + this._anchorElement = x; + }, + + get anchor() + { + return this._anchorElement; + }, + + set autoHide(x) + { + this._autoHide = x; + }, + + _checkNotVisible: function() + { + if (this.visible) + throw new Error("The popup must not be visible."); + }, + + _keyEventHandler: function(event) + { + // Escape hides the popup. + if (event.keyIdentifier == "U+001B") { + this.hide(); + event.preventDefault(); + event.handled = true; + } + }, + + _mouseDownEventHandler: function(event) + { + if (this._autoHide && event.originalTarget === this._glasspaneElement) + this.hide(); + } +} diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ProfileDataGridTree.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ProfileDataGridTree.js new file mode 100644 index 0000000..356f57d --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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), !Preferences.samplingCPUProfiler); + } + + 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_frame/tools/test/reference_build/chrome/resources/inspector/ProfileView.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ProfileView.js new file mode 100644 index 0000000..2b8c6ce --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ProfileView.js @@ -0,0 +1,539 @@ +/* + * 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 } }; + + if (Preferences.samplingCPUProfiler) { + delete columns.average; + delete columns.calls; + } + + 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 = new WebInspector.StatusBarButton("", "percent-time-status-bar-item"); + this.percentButton.addEventListener("click", this._percentClicked.bind(this), false); + + this.focusButton = new WebInspector.StatusBarButton(WebInspector.UIString("Focus selected function."), "focus-profile-node-status-bar-item"); + this.focusButton.disabled = true; + this.focusButton.addEventListener("click", this._focusClicked.bind(this), false); + + this.excludeButton = new WebInspector.StatusBarButton(WebInspector.UIString("Exclude selected function."), "exclude-profile-node-status-bar-item"); + this.excludeButton.disabled = true; + this.excludeButton.addEventListener("click", this._excludeClicked.bind(this), false); + + this.resetButton = new WebInspector.StatusBarButton(WebInspector.UIString("Restore all functions."), "reset-profile-status-bar-item"); + this.resetButton.visible = false; + 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.element, this.focusButton.element, this.excludeButton.element, this.resetButton.element]; + }, + + 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; + }, + + show: function(parentElement) + { + WebInspector.View.prototype.show.call(this, parentElement); + this.dataGrid.updateWidths(); + }, + + hide: function() + { + WebInspector.View.prototype.hide.call(this); + this._currentSearchResultIndex = -1; + }, + + resize: function() + { + if (this.dataGrid) + this.dataGrid.updateWidths(); + }, + + refresh: function() + { + 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.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; + + profileNode.refresh(); + } + } + + delete this._searchFinishedCallback; + this._currentSearchResultIndex = -1; + this._searchResults = []; + }, + + performSearch: function(query, finishedCallback) + { + // Call searchCanceled since it will reset everything we need before doing a new search. + this.searchCanceled(); + + query = query.trimWhitespace(); + + if (!query.length) + return; + + this._searchFinishedCallback = finishedCallback; + + var 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.profileDataGridTree.children[0]; + + while (current) { + if (matchesQuery(current)) { + this._searchResults.push({ profileNode: current }); + } + + current = current.traverseNextNode(false, null, false); + } + + 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 = searchResult.profileNode; + profileNode.reveal(); + profileNode.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.toggled = true; + } else { + this.percentButton.title = WebInspector.UIString("Show total and self times as percentages."); + this.percentButton.toggled = false; + } + }, + + _focusClicked: function(event) + { + if (!this.dataGrid.selectedNode) + return; + + this.resetButton.visible = true; + 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.visible = true; + this.profileDataGridTree.exclude(selectedNode); + this.refresh(); + this.refreshVisibleData(); + }, + + _resetClicked: function(event) + { + this.resetButton.visible = false; + 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_frame/tools/test/reference_build/chrome/resources/inspector/ProfilesPanel.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ProfilesPanel.js new file mode 100644 index 0000000..c010033 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ProfilesPanel.js @@ -0,0 +1,534 @@ +/* + * 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.profilesListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("CPU PROFILES"), null, true); + this.sidebarTree.appendChild(this.profilesListTreeElement); + this.profilesListTreeElement.expand(); + + this.snapshotsListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("HEAP SNAPSHOTS"), null, true); + if (Preferences.heapProfilerPresent) { + this.sidebarTree.appendChild(this.snapshotsListTreeElement); + this.snapshotsListTreeElement.expand(); + } + + this.profileViews = document.createElement("div"); + this.profileViews.id = "profile-views"; + this.element.appendChild(this.profileViews); + + this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item"); + this.enableToggleButton.addEventListener("click", this._toggleProfiling.bind(this), false); + + this.recordButton = new WebInspector.StatusBarButton(WebInspector.UIString("Start profiling."), "record-profile-status-bar-item"); + this.recordButton.addEventListener("click", this._recordClicked.bind(this), false); + + this.recording = false; + + this.snapshotButton = new WebInspector.StatusBarButton(WebInspector.UIString("Take heap snapshot."), "heap-snapshot-status-bar-item"); + this.snapshotButton.visible = Preferences.heapProfilerPresent; + this.snapshotButton.addEventListener("click", this._snapshotClicked.bind(this), 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.element, this.recordButton.element, this.snapshotButton.element, 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.profilesListTreeElement.removeChildren(); + this.snapshotsListTreeElement.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.profilesListTreeElement; + 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) + // The title is used in the console message announcing that a profile has started so it gets + // incremented twice as often as it's displayed + title += " " + WebInspector.UIString("Run %d", groupNumber / 2); + } + + 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.toggled = true; + this.recordButton.title = WebInspector.UIString("Stop profiling."); + } else { + this.recordButton.toggled = false; + this.recordButton.title = WebInspector.UIString("Start profiling."); + } + }, + + resize: function() + { + var visibleView = this.visibleView; + if (visibleView && "resize" in visibleView) + visibleView.resize(); + }, + + _updateInterface: function() + { + if (InspectorController.profilerEnabled()) { + this.enableToggleButton.title = WebInspector.UIString("Profiling enabled. Click to disable."); + this.enableToggleButton.toggled = true; + this.recordButton.visible = true; + if (Preferences.heapProfilerPresent) + this.snapshotButton.visible = true; + this.profileViewStatusBarItemsContainer.removeStyleClass("hidden"); + this.panelEnablerView.visible = false; + } else { + this.enableToggleButton.title = WebInspector.UIString("Profiling disabled. Click to enable."); + this.enableToggleButton.toggled = false; + this.recordButton.visible = false; + this.snapshotButton.visible = false; + this.profileViewStatusBarItemsContainer.addStyleClass("hidden"); + this.panelEnablerView.visible = true; + } + }, + + _recordClicked: function() + { + this.recording = !this.recording; + + if (this.recording) + InspectorController.startProfiling(); + else + InspectorController.stopProfiling(); + }, + + _snapshotClicked: function() + { + InspectorController.takeHeapSnapshot(); + }, + + _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"; + + var visibleView = this.visibleView; + if (visibleView && "resize" in visibleView) + visibleView.resize(); + } +} + +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_frame/tools/test/reference_build/chrome/resources/inspector/PropertiesSection.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/PropertiesSection.js new file mode 100644 index 0000000..a4b2fba --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/PropertiesSidebarPane.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/PropertiesSidebarPane.js new file mode 100644 index 0000000..ec08210 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/PropertiesSidebarPane.js @@ -0,0 +1,64 @@ +/* + * 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(node) + { + var body = this.bodyElement; + + body.removeChildren(); + + this.sections = []; + + if (!node) + return; + + var self = this; + var callback = function(prototypes) { + var body = self.bodyElement; + body.removeChildren(); + self.sections = []; + + // Get array of prototype user-friendly names. + for (var i = 0; i < prototypes.length; ++i) { + var prototype = new WebInspector.ObjectProxy(node.id, [], i); + var section = new WebInspector.ObjectPropertiesSection(prototype, prototypes[i], WebInspector.UIString("Prototype")); + self.sections.push(section); + body.appendChild(section.element); + } + }; + InjectedScriptAccess.getPrototypes(node.id, callback); + } +} + +WebInspector.PropertiesSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Resource.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Resource.js new file mode 100644 index 0000000..4dac093 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Resource.js @@ -0,0 +1,622 @@ +/* + * 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, requestMethod, requestFormData) +{ + 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.requestMethod = requestMethod || ""; + this.requestFormData = requestFormData || ""; + + 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 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.MessageType.Log, 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 msg; + switch (warning.id) { + case WebInspector.Warnings.IncorrectMIMEType.id: + if (!this._mimeTypeIsConsistentWithType()) + msg = new WebInspector.ConsoleMessage(WebInspector.ConsoleMessage.MessageSource.Other, + WebInspector.ConsoleMessage.MessageType.Log, + 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_frame/tools/test/reference_build/chrome/resources/inspector/ResourceCategory.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ResourceCategory.js new file mode 100644 index 0000000..fc508d0 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/ResourceView.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ResourceView.js new file mode 100644 index 0000000..d745920 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ResourceView.js @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) IBM Corp. 2009 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._decodeHover = WebInspector.UIString("Double-Click to toggle between URL encoded and decoded formats"); + this._decodeRequestParameters = true; + + this.queryStringTreeElement = new TreeElement("", null, true); + this.queryStringTreeElement.expanded = false; + this.queryStringTreeElement.selectable = false; + this.queryStringTreeElement.hidden = true; + this.headersTreeOutline.appendChild(this.queryStringTreeElement); + + this.formDataTreeElement = new TreeElement("", null, true); + this.formDataTreeElement.expanded = false; + this.formDataTreeElement.selectable = false; + this.formDataTreeElement.hidden = true; + this.headersTreeOutline.appendChild(this.formDataTreeElement); + + this.requestPayloadTreeElement = new TreeElement(WebInspector.UIString("Request Payload"), null, true); + this.requestPayloadTreeElement.expanded = false; + this.requestPayloadTreeElement.selectable = false; + this.requestPayloadTreeElement.hidden = true; + this.headersTreeOutline.appendChild(this.requestPayloadTreeElement); + + 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() + { + var url = this.resource.url; + this.urlTreeElement.title = this.resource.requestMethod + " " + url.escapeHTML(); + this._refreshQueryString(); + }, + + _refreshQueryString: function() + { + var url = this.resource.url; + var hasQueryString = url.indexOf("?") >= 0; + + if (!hasQueryString) { + this.queryStringTreeElement.hidden = true; + return; + } + + this.queryStringTreeElement.hidden = false; + var parmString = url.split("?", 2)[1]; + this._refreshParms(WebInspector.UIString("Query String Parameters"), parmString, this.queryStringTreeElement); + }, + + _refreshFormData: function() + { + this.formDataTreeElement.hidden = true; + this.requestPayloadTreeElement.hidden = true; + + var isFormData = this.resource.requestFormData; + if (!isFormData) + return; + + var isFormEncoded = false; + var requestContentType = this._getHeaderValue(this.resource.requestHeaders, "Content-Type"); + if (requestContentType == "application/x-www-form-urlencoded") + isFormEncoded = true; + + if (isFormEncoded) { + this.formDataTreeElement.hidden = false; + this._refreshParms(WebInspector.UIString("Form Data"), this.resource.requestFormData, this.formDataTreeElement); + } else { + this.requestPayloadTreeElement.hidden = false; + this._refreshRequestPayload(this.resource.requestFormData); + } + }, + + _refreshRequestPayload: function(formData) + { + this.requestPayloadTreeElement.removeChildren(); + + var title = "<div class=\"header-name\"> </div>"; + title += "<div class=\"raw-form-data header-value\">" + formData.escapeHTML() + "</div>"; + var parmTreeElement = new TreeElement(title, null, false); + this.requestPayloadTreeElement.appendChild(parmTreeElement); + }, + + _refreshParms: function(title, parmString, parmsTreeElement) + { + var parms = parmString.split("&"); + for (var i = 0; i < parms.length; ++i) { + var parm = parms[i]; + parm = parm.split("=", 2); + if (parm.length == 1) + parm.push(""); + parms[i] = parm; + } + + parmsTreeElement.removeChildren(); + + parmsTreeElement.title = title + "<span class=\"header-count\">" + WebInspector.UIString(" (%d)", parms.length) + "</span>"; + + for (var i = 0; i < parms.length; ++i) { + var key = parms[i][0]; + var val = parms[i][1]; + + if (val.indexOf("%") >= 0) + if (this._decodeRequestParameters) + val = decodeURIComponent(val).replace(/\+/g, " "); + + var title = "<div class=\"header-name\">" + key.escapeHTML() + ":</div>"; + title += "<div class=\"header-value\">" + val.escapeHTML() + "</div>"; + + var parmTreeElement = new TreeElement(title, null, false); + parmTreeElement.selectable = false; + parmTreeElement.tooltip = this._decodeHover; + parmTreeElement.ondblclick = this._toggleURLdecoding.bind(this); + parmsTreeElement.appendChild(parmTreeElement); + } + }, + + _toggleURLdecoding: function(treeElement, event) + { + this._decodeRequestParameters = !this._decodeRequestParameters; + this._refreshQueryString(); + this._refreshFormData(); + }, + + _getHeaderValue: function(headers, key) + { + var lowerKey = key.toLowerCase(); + for (var testKey in headers) { + if (testKey.toLowerCase() === lowerKey) + return headers[testKey]; + } + }, + + _refreshRequestHeaders: function() + { + this._refreshHeaders(WebInspector.UIString("Request Headers"), this.resource.sortedRequestHeaders, this.requestHeadersTreeElement); + this._refreshFormData(); + }, + + _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_frame/tools/test/reference_build/chrome/resources/inspector/ResourcesPanel.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ResourcesPanel.js new file mode 100644 index 0000000..680f66c --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ResourcesPanel.js @@ -0,0 +1,1462 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org> + * + * 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.filterBarElement = document.createElement("div"); + this.filterBarElement.id = "resources-filter"; + this.element.appendChild(this.filterBarElement); + + 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.summaryBar = new WebInspector.SummaryBar(this.categories); + this.summaryBar.element.id = "resources-summary"; + this.containerContentElement.appendChild(this.summaryBar.element); + + 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.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 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 = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item"); + this.enableToggleButton.addEventListener("click", this._toggleResourceTracking.bind(this), false); + + this.largerResourcesButton = new WebInspector.StatusBarButton(WebInspector.UIString("Use small resource rows."), "resources-larger-resources-status-bar-item"); + this.largerResourcesButton.toggled = true; + 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); + + var createFilterElement = function (category) { + var categoryElement = document.createElement("li"); + categoryElement.category = category; + categoryElement.addStyleClass(category); + var label = WebInspector.UIString("All"); + if (WebInspector.resourceCategories[category]) + label = WebInspector.resourceCategories[category].title; + categoryElement.appendChild(document.createTextNode(label)); + categoryElement.addEventListener("click", this._updateFilter.bind(this), false); + this.filterBarElement.appendChild(categoryElement); + return categoryElement; + }; + + var allElement = createFilterElement.call(this, "all"); + this.filter(allElement.category); + for (var category in this.categories) + createFilterElement.call(this, category); + + this.reset(); + + timeGraphItem.select(); +} + +WebInspector.ResourcesPanel.prototype = { + toolbarItemClass: "resources", + + get categories() + { + if (!this._categories) { + this._categories = {documents: {color: {r: 47, g: 102, b: 236}}, stylesheets: {color: {r: 157, g: 231, b: 119}}, images: {color: {r: 164, g: 60, b: 255}}, scripts: {color: {r: 255, g: 121, b: 0}}, xhr: {color: {r: 231, g: 231, b: 10}}, fonts: {color: {r: 255, g: 82, b: 62}}, other: {color: {r: 186, g: 186, b: 186}}}; + for (var category in this._categories) { + this._categories[category].title = WebInspector.resourceCategories[category].title; + } + } + return this._categories; + }, + + filter: function (category) { + if (this._filterCategory && this._filterCategory === category) + return; + + if (this._filterCategory) { + var filterElement = this.filterBarElement.getElementsByClassName(this._filterCategory)[0]; + filterElement.removeStyleClass("selected"); + var oldClass = "filter-" + this._filterCategory; + this.resourcesTreeElement.childrenListElement.removeStyleClass(oldClass); + this.resourcesGraphsElement.removeStyleClass(oldClass); + } + this._filterCategory = category; + var filterElement = this.filterBarElement.getElementsByClassName(this._filterCategory)[0]; + filterElement.addStyleClass("selected"); + var newClass = "filter-" + this._filterCategory; + this.resourcesTreeElement.childrenListElement.addStyleClass(newClass); + this.resourcesGraphsElement.addStyleClass(newClass); + }, + + _updateFilter: function (e) { + this.filter(e.target.category); + }, + + get toolbarItemLabel() + { + return WebInspector.UIString("Resources"); + }, + + get statusBarItems() + { + return [this.enableToggleButton.element, this.largerResourcesButton.element, 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.summaryBar.reset(); + + this._updateGraphDividersIfNeeded(true); + + if (InspectorController.resourceTrackingEnabled()) { + this.enableToggleButton.title = WebInspector.UIString("Resource tracking enabled. Click to disable."); + this.enableToggleButton.toggled = true; + this.largerResourcesButton.visible = true; + this.sortingSelectElement.removeStyleClass("hidden"); + this.panelEnablerView.visible = false; + } else { + this.enableToggleButton.title = WebInspector.UIString("Resource tracking disabled. Click to enable."); + this.enableToggleButton.toggled = false; + this.largerResourcesButton.visible = false; + 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); + }, + + _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); + } + }, + + _updateSummaryGraph: function() + { + this.summaryBar.update(this._resources); + }, + + _updateDividersLabelBarPosition: function() + { + var scrollTop = this.containerElement.scrollTop; + var dividersTop = (scrollTop < this.summaryBar.element.offsetHeight ? this.summaryBar.element.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.toggled = false; + this._adjustScrollPosition(); + } else { + this.resourcesGraphsElement.removeStyleClass("small"); + this.largerResourcesButton.title = WebInspector.UIString("Use small resource rows."); + this.largerResourcesButton.toggled = true; + } + }, + + _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 = this.summaryBar.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); + + var link = document.createElement("a"); + link.href = this.resource.url; + link.className = "invisible"; + while (this._listItemNode.firstChild) + link.appendChild(this._listItemNode.firstChild); + this._listItemNode.appendChild(link); + this._listItemNode.addStyleClass("resources-category-" + this.resource.category.name); + }, + + onselect: function() + { + WebInspector.panels.resources.showResource(this.resource); + }, + + ondblclick: function(treeElement, event) + { + InjectedScriptAccess.openInInspectedWindow(this.resource.url); + }, + + 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. + }, + + get selectable() + { + return WebInspector.panels.resources._filterCategory == "all" || WebInspector.panels.resources._filterCategory == this.resource.category.name; + }, + + 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_frame/tools/test/reference_build/chrome/resources/inspector/ScopeChainSidebarPane.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ScopeChainSidebarPane.js new file mode 100644 index 0000000..3875324 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ScopeChainSidebarPane.js @@ -0,0 +1,146 @@ +/* + * 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")); + this._expandedProperties = []; +} + +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; + } + + var foundLocalScope = false; + var scopeChain = callFrame.scopeChain; + for (var i = 0; i < scopeChain.length; ++i) { + var scopeObjectProxy = scopeChain[i]; + var title = null; + var subtitle = scopeObjectProxy.description; + var emptyPlaceholder = null; + var extraProperties = null; + + if (scopeObjectProxy.isLocal) { + if (scopeObjectProxy.thisObject) { + extraProperties = [ new WebInspector.ObjectPropertyProxy("this", scopeObjectProxy.thisObject) ]; + title = WebInspector.UIString("Local"); + } else + title = WebInspector.UIString("Closure"); + emptyPlaceholder = WebInspector.UIString("No Variables"); + subtitle = null; + foundLocalScope = true; + } else if (i === (scopeChain.length - 1)) + title = WebInspector.UIString("Global"); + else if (scopeObjectProxy.isElement) + title = WebInspector.UIString("Event Target"); + else if (scopeObjectProxy.isDocument) + title = WebInspector.UIString("Event Document"); + else if (scopeObjectProxy.isWithBlock) + title = WebInspector.UIString("With Block"); + + if (!title || title === subtitle) + subtitle = null; + + var section = new WebInspector.ObjectPropertiesSection(scopeObjectProxy, title, subtitle, emptyPlaceholder, true, extraProperties, WebInspector.ScopeVariableTreeElement); + section.editInSelectedCallFrameWhenPaused = true; + section.pane = this; + + if (!foundLocalScope || scopeObjectProxy.isLocal) + section.expanded = true; + + this.sections.push(section); + this.bodyElement.appendChild(section.element); + } + } +} + +WebInspector.ScopeChainSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; + +WebInspector.ScopeVariableTreeElement = function(property) +{ + WebInspector.ObjectPropertyTreeElement.call(this, property); +} + +WebInspector.ScopeVariableTreeElement.prototype = { + onattach: function() + { + WebInspector.ObjectPropertyTreeElement.prototype.onattach.call(this); + if (this.hasChildren && this.propertyIdentifier in this.treeOutline.section.pane._expandedProperties) + this.expand(); + }, + + onexpand: function() + { + this.treeOutline.section.pane._expandedProperties[this.propertyIdentifier] = true; + }, + + oncollapse: function() + { + delete this.treeOutline.section.pane._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.property.name + "." + result; + else + result = current.property.name; + current = current.parent; + } while (current && !current.root); + + this._propertyPath = result; + return result; + } +} + +WebInspector.ScopeVariableTreeElement.prototype.__proto__ = WebInspector.ObjectPropertyTreeElement.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Script.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Script.js new file mode 100644 index 0000000..e6413a9 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/Script.js @@ -0,0 +1,50 @@ +/* + * 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; + + // if no URL, look for "//@ sourceURL=" decorator + // note that this sourceURL comment decorator is behavior that FireBug added + // in it's 1.1 release as noted in the release notes: + // http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt + if (!sourceURL) { + // use of [ \t] rather than \s is to prevent \n from matching + var pattern = /^\s*\/\/[ \t]*@[ \t]*sourceURL[ \t]*=[ \t]*(\S+).*$/m; + var match = pattern.exec(source); + + if (match) + this.sourceURL = WebInspector.UIString("(program): %s", match[1]); + } +} + +WebInspector.Script.prototype = { +} diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ScriptView.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ScriptView.js new file mode 100644 index 0000000..124190c --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/ScriptsPanel.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ScriptsPanel.js new file mode 100644 index 0000000..04f27bb --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/ScriptsPanel.js @@ -0,0 +1,918 @@ +/* + * 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.filesSelectElement.handleKeyEvent = this.handleKeyEvent.bind(this); + 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.watchExpressions = new WebInspector.WatchExpressionsSidebarPane(); + 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); + + this.sidebarPanes.callstack.expanded = true; + this.sidebarPanes.callstack.addEventListener("call frame selected", this._callFrameSelected, this); + + this.sidebarPanes.scopechain.expanded = true; + this.sidebarPanes.breakpoints.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 = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item"); + this.enableToggleButton.addEventListener("click", this._toggleDebugging.bind(this), false); + + this.pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item"); + this.pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions.bind(this), false); + + this._breakpointsURLMap = {}; + + this._shortcuts = {}; + + var isMac = InspectorController.platform().indexOf("mac-") === 0; + var platformSpecificModifier = isMac ? WebInspector.KeyboardShortcut.Modifiers.Meta : WebInspector.KeyboardShortcut.Modifiers.Ctrl; + + // Continue. + var handler = this.pauseButton.click.bind(this.pauseButton); + var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F8); + this._shortcuts[shortcut] = handler; + var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Slash, platformSpecificModifier); + this._shortcuts[shortcut] = handler; + + // Step over. + var handler = this.stepOverButton.click.bind(this.stepOverButton); + var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F10); + this._shortcuts[shortcut] = handler; + var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.SingleQuote, platformSpecificModifier); + this._shortcuts[shortcut] = handler; + + // Step into. + var handler = this.stepIntoButton.click.bind(this.stepIntoButton); + var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F11); + this._shortcuts[shortcut] = handler; + var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Semicolon, platformSpecificModifier); + this._shortcuts[shortcut] = handler; + + // Step out. + var handler = this.stepOutButton.click.bind(this.stepOutButton); + var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F11, WebInspector.KeyboardShortcut.Modifiers.Shift); + this._shortcuts[shortcut] = handler; + var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Semicolon, WebInspector.KeyboardShortcut.Modifiers.Shift, platformSpecificModifier); + this._shortcuts[shortcut] = handler; + + this.reset(); +} + +WebInspector.ScriptsPanel.prototype = { + toolbarItemClass: "scripts", + + get toolbarItemLabel() + { + return WebInspector.UIString("Scripts"); + }, + + get statusBarItems() + { + return [this.enableToggleButton.element, this.pauseOnExceptionButton.element]; + }, + + 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.enableDebugger(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, breakpoint.condition); + } + } + } + + if (sourceID) + this._sourceIDMap[sourceID] = (resource || script); + + this._addScriptToFilesMenu(script); + }, + + scriptOrResourceForID: function(id) + { + return this._sourceIDMap[id]; + }, + + 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, callback) + { + var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame; + if (!this._paused || !selectedCallFrame) + return; + + if (typeof updateInterface === "undefined") + updateInterface = true; + + var self = this; + function updatingCallbackWrapper(result, exception) + { + callback(result, exception); + if (updateInterface) + self.sidebarPanes.scopechain.update(selectedCallFrame); + } + this.doEvalInCallFrame(selectedCallFrame, code, updatingCallbackWrapper); + }, + + doEvalInCallFrame: function(callFrame, code, callback) + { + function evalCallback(result) + { + if (result) + callback(result.value, result.isException); + } + InjectedScriptAccess.evaluateInCallFrame(callFrame.id, code, evalCallback); + }, + + variablesInSelectedCallFrame: 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 scopeObjectProperties = scopeChain[i].properties; + for (var j = 0; j < scopeObjectProperties.length; ++j) + result[scopeObjectProperties[j]] = true; + } + return result; + }, + + debuggerPaused: function(callFrames) + { + this._paused = true; + this._waitingToPause = false; + this._stepping = false; + + this._updateDebuggerButtons(); + + this.sidebarPanes.callstack.update(callFrames, this._sourceIDMap); + this.sidebarPanes.callstack.selectedCallFrame = callFrames[0]; + + 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.enableDebugger(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 = {}; + + this.sidebarPanes.watchExpressions.refreshExpressions(); + }, + + 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)); + }, + + handleKeyEvent: function(event) + { + var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event); + var handler = this._shortcuts[shortcut]; + if (handler) { + handler(event); + event.preventDefault(); + event.handled = true; + } else { + this.sidebarPanes.callstack.handleKeyEvent(event); + } + }, + + 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); + this.sidebarPanes.watchExpressions.refreshExpressions(); + + 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.toggled = true; + } else { + this.pauseOnExceptionButton.title = WebInspector.UIString("Pause on exceptions."); + this.pauseOnExceptionButton.toggled = false; + } + }, + + _updateDebuggerButtons: function() + { + if (InspectorController.debuggerEnabled()) { + this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable."); + this.enableToggleButton.toggled = true; + this.pauseOnExceptionButton.visible = true; + this.panelEnablerView.visible = false; + } else { + this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable."); + this.enableToggleButton.toggled = false; + this.pauseOnExceptionButton.visible = false; + 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.enableDebugger(!!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_frame/tools/test/reference_build/chrome/resources/inspector/SidebarPane.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/SidebarPane.js new file mode 100644 index 0000000..af9e5f9 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/SidebarTreeElement.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/SidebarTreeElement.js new file mode 100644 index 0000000..c08b0ef --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/SourceFrame.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/SourceFrame.js new file mode 100644 index 0000000..e364cb2 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/SourceFrame.js @@ -0,0 +1,906 @@ +/* + * 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._shortcuts = {}; + + 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("contextmenu", this._documentContextMenu.bind(this), true); + this.element.contentDocument.addEventListener("mousedown", this._documentMouseDown.bind(this), true); + this.element.contentDocument.addEventListener("keydown", this._documentKeyDown.bind(this), true); + this.element.contentDocument.addEventListener("keyup", WebInspector.documentKeyUp.bind(WebInspector), true); + this.element.contentDocument.addEventListener("webkitAnimationEnd", this._highlightLineEnds.bind(this), false); + + // Register 'eval' shortcut. + var isMac = InspectorController.platform().indexOf("mac-") === 0; + var platformSpecificModifier = isMac ? WebInspector.KeyboardShortcut.Modifiers.Meta : WebInspector.KeyboardShortcut.Modifiers.Ctrl; + var shortcut = WebInspector.KeyboardShortcut.makeKey(69 /* 'E' */, platformSpecificModifier | WebInspector.KeyboardShortcut.Modifiers.Shift); + this._shortcuts[shortcut] = this._evalSelectionInCallFrame.bind(this); + + 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-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(program-counter); }\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-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-breakpoint.webkit-breakpoint-conditional .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint-conditional); }\n"; + styleText += ".webkit-breakpoint-disabled.webkit-breakpoint-conditional .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint-disabled-conditional); }\n"; + styleText += ".webkit-breakpoint.webkit-breakpoint-conditional.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-conditional-program-counter); }\n"; + styleText += ".webkit-breakpoint-disabled.webkit-breakpoint-conditional.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-disabled-conditional-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"; + + // TODO: Move these styles into inspector.css once https://bugs.webkit.org/show_bug.cgi?id=28913 is fixed and popup moved into the top frame. + styleText += ".popup-content { position: absolute; z-index: 10000; padding: 4px; background-color: rgb(203, 226, 255); -webkit-border-radius: 7px; border: 2px solid rgb(169, 172, 203); }"; + styleText += ".popup-glasspane { position: absolute; top: 0; left: 0; height: 100%; width: 100%; opacity: 0; z-index: 9900; }"; + styleText += ".popup-message { background-color: transparent; font-family: Lucida Grande, sans-serif; font-weight: normal; font-size: 11px; text-align: left; text-shadow: none; color: rgb(85, 85, 85); cursor: default; margin: 0 0 2px 0; }"; + styleText += ".popup-content.breakpoint-condition { width: 90%; }"; + styleText += ".popup-content input#bp-condition { font-family: monospace; margin: 0; border: 1px inset rgb(190, 190, 190) !important; width: 100%; box-shadow: none !important; outline: none !important; -webkit-user-modify: read-write; }"; + // This class is already in inspector.css + styleText += ".hidden { display: none !important; }"; + + 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.positionAt = Element.prototype.positionAt; + this.element.contentWindow.Element.prototype.removeMatchingStyleClasses = Element.prototype.removeMatchingStyleClasses; + this.element.contentWindow.Element.prototype.hasStyleClass = Element.prototype.hasStyleClass; + this.element.contentWindow.Element.prototype.pageOffsetRelativeToWindow = Element.prototype.pageOffsetRelativeToWindow; + this.element.contentWindow.Element.prototype.__defineGetter__("totalOffsetLeft", Element.prototype.__lookupGetter__("totalOffsetLeft")); + this.element.contentWindow.Element.prototype.__defineGetter__("totalOffsetTop", Element.prototype.__lookupGetter__("totalOffsetTop")); + 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(); + }, + + _documentContextMenu: function(event) + { + if (!event.target.hasStyleClass("webkit-line-number")) + return; + var sourceRow = event.target.enclosingNodeOrSelfWithNodeName("tr"); + if (!sourceRow._breakpointObject && this.addBreakpointDelegate) + this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow)); + + var breakpoint = sourceRow._breakpointObject; + if (!breakpoint) + return; + + this._editBreakpointCondition(event.target, sourceRow, breakpoint); + event.preventDefault(); + }, + + _documentMouseDown: function(event) + { + if (!event.target.hasStyleClass("webkit-line-number")) + return; + if (event.button != 0 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) + return; + var sourceRow = event.target.enclosingNodeOrSelfWithNodeName("tr"); + if (sourceRow._breakpointObject && sourceRow._breakpointObject.enabled) + sourceRow._breakpointObject.enabled = false; + else if (sourceRow._breakpointObject) + WebInspector.panels.scripts.removeBreakpoint(sourceRow._breakpointObject); + else if (this.addBreakpointDelegate) + this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow)); + }, + + _editBreakpointCondition: function(eventTarget, sourceRow, breakpoint) + { + // TODO: Migrate the popup to the top-level document and remove the blur listener from conditionElement once https://bugs.webkit.org/show_bug.cgi?id=28913 is fixed. + var popupDocument = this.element.contentDocument; + this._showBreakpointConditionPopup(eventTarget, breakpoint.line, popupDocument); + + function committed(element, newText) + { + breakpoint.condition = newText; + if (breakpoint.condition) + sourceRow.addStyleClass("webkit-breakpoint-conditional"); + else + sourceRow.removeStyleClass("webkit-breakpoint-conditional"); + dismissed.call(this); + } + + function dismissed() + { + this._popup.hide(); + delete this._conditionEditorElement; + } + + var dismissedHandler = dismissed.bind(this); + this._conditionEditorElement.addEventListener("blur", dismissedHandler, false); + + WebInspector.startEditing(this._conditionEditorElement, committed.bind(this), dismissedHandler); + this._conditionEditorElement.value = breakpoint.condition; + this._conditionEditorElement.select(); + }, + + _showBreakpointConditionPopup: function(clickedElement, lineNumber, popupDocument) + { + var popupContentElement = this._createPopupElement(lineNumber, popupDocument); + var lineElement = clickedElement.enclosingNodeOrSelfWithNodeName("td").nextSibling; + if (this._popup) { + this._popup.hide(); + this._popup.element = popupContentElement; + } else { + this._popup = new WebInspector.Popup(popupContentElement); + this._popup.autoHide = true; + } + this._popup.anchor = lineElement; + this._popup.show(); + }, + + _createPopupElement: function(lineNumber, popupDocument) + { + var popupContentElement = popupDocument.createElement("div"); + popupContentElement.className = "popup-content breakpoint-condition"; + + var labelElement = document.createElement("label"); + labelElement.className = "popup-message"; + labelElement.htmlFor = "bp-condition"; + labelElement.appendChild(document.createTextNode(WebInspector.UIString("The breakpoint on line %d will stop only if this expression is true:", lineNumber))); + popupContentElement.appendChild(labelElement); + + var editorElement = document.createElement("input"); + editorElement.id = "bp-condition"; + editorElement.type = "text" + popupContentElement.appendChild(editorElement); + this._conditionEditorElement = editorElement; + + return popupContentElement; + }, + + _documentKeyDown: function(event) + { + var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event); + var handler = this._shortcuts[shortcut]; + if (handler) { + handler(event); + event.preventDefault(); + } else { + WebInspector.documentKeyDown(event); + } + }, + + _evalSelectionInCallFrame: function(event) + { + if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused) + return; + + var selection = this.element.contentWindow.getSelection(); + if (!selection.rangeCount) + return; + + var expression = selection.getRangeAt(0).toString().trimWhitespace(); + WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, function(result, exception) { + WebInspector.showConsole(); + var commandMessage = new WebInspector.ConsoleCommand(expression); + WebInspector.console.addMessage(commandMessage); + WebInspector.console.addMessage(new WebInspector.ConsoleCommandResult(result, exception, commandMessage)); + }); + }, + + _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; + + breakpoint.sourceText = sourceRow.getElementsByClassName('webkit-line-content')[0].textContent; + + this._drawBreakpointImagesIfNeeded(); + + sourceRow._breakpointObject = breakpoint; + + sourceRow.addStyleClass("webkit-breakpoint"); + if (!breakpoint.enabled) + sourceRow.addStyleClass("webkit-breakpoint-disabled"); + if (breakpoint.condition) + sourceRow.addStyleClass("webkit-breakpoint-conditional"); + }, + + _removeBreakpointFromSource: function(breakpoint) + { + var sourceRow = this.sourceRow(breakpoint.line); + if (!sourceRow) + return; + + delete sourceRow._breakpointObject; + + sourceRow.removeStyleClass("webkit-breakpoint"); + sourceRow.removeStyleClass("webkit-breakpoint-disabled"); + sourceRow.removeStyleClass("webkit-breakpoint-conditional"); + }, + + _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(conditional) + { + if (!this._needsBreakpointImages || !this.element.contentDocument) + return; + + function drawBreakpoint(ctx, disabled, conditional) + { + 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 = conditional ? "rgb(217, 142, 1)" : "rgb(1, 142, 217)"; + ctx.strokeStyle = conditional ? "rgb(205, 103, 0)" : "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(); + } + + + // Unconditional breakpoints. + + 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); + + + // Conditional breakpoints. + + var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-conditional", 26, 11); + ctx.clearRect(0, 0, 26, 11); + drawBreakpoint(ctx, false, true); + + var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-conditional-program-counter", 26, 11); + ctx.clearRect(0, 0, 26, 11); + drawBreakpoint(ctx, false, true); + ctx.clearRect(20, 0, 6, 11); + this._drawProgramCounterInContext(ctx, true); + + var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-disabled-conditional", 26, 11); + ctx.clearRect(0, 0, 26, 11); + drawBreakpoint(ctx, true, true); + + var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-disabled-conditional-program-counter", 26, 11); + ctx.clearRect(0, 0, 26, 11); + drawBreakpoint(ctx, true, 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_frame/tools/test/reference_build/chrome/resources/inspector/SourceView.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/SourceView.js new file mode 100644 index 0000000..97a5bd5 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/SourceView.js @@ -0,0 +1,311 @@ +/* + * 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.resource.mimeType === 'application/json' + || this.resource.mimeType === 'application/javascript' + || /\.js(on)?$/.test(this.resource.lastPathComponent) ) { + 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_frame/tools/test/reference_build/chrome/resources/inspector/StatusBarButton.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/StatusBarButton.js new file mode 100644 index 0000000..5c69ed5 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/StatusBarButton.js @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +WebInspector.StatusBarButton = function(title, className) +{ + this.element = document.createElement("button"); + this.element.className = className + " status-bar-item"; + this.element.addEventListener("click", this._clicked.bind(this), false); + + this.glyph = document.createElement("div"); + this.glyph.className = "glyph"; + this.element.appendChild(this.glyph); + + this.glyphShadow = document.createElement("div"); + this.glyphShadow.className = "glyph shadow"; + this.element.appendChild(this.glyphShadow); + + this.title = title; + this.disabled = false; + this._toggled = false; + this._visible = true; +} + +WebInspector.StatusBarButton.prototype = { + _clicked: function() + { + this.dispatchEventToListeners("click"); + }, + + get disabled() + { + return this._disabled; + }, + + set disabled(x) + { + if (this._disabled === x) + return; + this._disabled = x; + this.element.disabled = x; + }, + + get title() + { + return this._title; + }, + + set title(x) + { + if (this._title === x) + return; + this._title = x; + this.element.title = x; + }, + + get toggled() + { + return this._toggled; + }, + + set toggled(x) + { + if (this._toggled === x) + return; + + if (x) + this.element.addStyleClass("toggled-on"); + else + this.element.removeStyleClass("toggled-on"); + this._toggled = x; + }, + + get visible() + { + return this._visible; + }, + + set visible(x) + { + if (this._visible === x) + return; + + if (x) + this.element.removeStyleClass("hidden"); + else + this.element.addStyleClass("hidden"); + this._visible = x; + } +} + +WebInspector.StatusBarButton.prototype.__proto__ = WebInspector.Object.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/StoragePanel.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/StoragePanel.js new file mode 100644 index 0000000..aed0d06 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/StoragePanel.js @@ -0,0 +1,685 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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.StoragePanel = function(database) +{ + WebInspector.Panel.call(this); + + this.sidebarElement = document.createElement("div"); + this.sidebarElement.id = "storage-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.cookieListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("COOKIES"), {}, true); + this.sidebarTree.appendChild(this.cookieListTreeElement); + this.cookieListTreeElement.expand(); + + this.cookieTreeElement = new WebInspector.CookieSidebarTreeElement(); + this.cookieListTreeElement.appendChild(this.cookieTreeElement); + + 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.StoragePanel.prototype = { + toolbarItemClass: "storage", + + get toolbarItemLabel() + { + return WebInspector.UIString("Storage"); + }, + + get statusBarItems() + { + return [this.storageViewStatusBarItemsContainer]; + }, + + show: function() + { + WebInspector.Panel.prototype.show.call(this); + this._updateSidebarWidth(); + this._registerStorageEventListener(); + }, + + 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 = []; + + this._unregisterStorageEventListener(); + + 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 = []; + + delete this._cookieView; + + this.databasesListTreeElement.removeChildren(); + this.localStorageListTreeElement.removeChildren(); + this.sessionStorageListTreeElement.removeChildren(); + this.storageViews.removeChildren(); + + this.storageViewStatusBarItemsContainer.removeChildren(); + + if (this.sidebarTree.selectedTreeElement) + this.sidebarTree.selectedTreeElement.deselect(); + }, + + 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.isLocalStorage ? "local-storage" : "session-storage")); + domStorage._domStorageTreeElement = domStorageTreeElement; + if (domStorage.isLocalStorage) + this.localStorageListTreeElement.appendChild(domStorageTreeElement); + else + this.sessionStorageListTreeElement.appendChild(domStorageTreeElement); + }, + + selectDatabase: function(db) + { + var database; + for (var i = 0, len = this._databases.length; i < len; ++i) { + database = this._databases[i]; + if (database.isDatabase(db)) { + this.showDatabase(database); + database._databasesTreeElement.select(); + return; + } + } + }, + + selectDOMStorage: function(s) + { + var isLocalStorage = (s === InspectorController.inspectedWindow().localStorage); + for (var i = 0, len = this._domStorage.length; i < len; ++i) { + var storage = this._domStorage[i]; + if ( isLocalStorage === storage.isLocalStorage ) { + this.showDOMStorage(storage); + storage._domStorageTreeElement.select(); + return; + } + } + }, + + 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].element); + }, + + 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]); + }, + + showCookies: function() + { + if (this.visibleView) + this.visibleView.hide(); + + var view = this._cookieView; + if (!view) { + view = new WebInspector.CookieItemsView(); + this._cookieView = 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 self = this; + function tableNamesCallback(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 (self.visibleView === database._tableViews[tableName]) + self.closeVisibleView(); + delete database._tableViews[tableName]; + } + } + } + database.getTableNames(tableNamesCallback); + }, + + 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[1].title.length; + + var nodes = []; + + var length = domStorage.length; + for (var 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; + var 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]); + dataGrid.addCreationNode(false); + if (length > 0) + nodes[0].selected = true; + return dataGrid; + }, + + resize: function() + { + var visibleView = this.visibleView; + if (visibleView && "resize" in visibleView) + visibleView.resize(); + }, + + _registerStorageEventListener: function() + { + var inspectedWindow = InspectorController.inspectedWindow(); + if (!inspectedWindow || !inspectedWindow.document) + return; + + this._storageEventListener = InspectorController.wrapCallback(this._storageEvent.bind(this)); + inspectedWindow.addEventListener("storage", this._storageEventListener, true); + }, + + _unregisterStorageEventListener: function() + { + if (!this._storageEventListener) + return; + + var inspectedWindow = InspectorController.inspectedWindow(); + if (!inspectedWindow || !inspectedWindow.document) + return; + + inspectedWindow.removeEventListener("storage", this._storageEventListener, true); + delete this._storageEventListener; + }, + + _storageEvent: function(event) + { + if (!this._domStorage) + return; + + var isLocalStorage = (event.storageArea === InspectorController.inspectedWindow().localStorage); + var domStorageLength = this._domStorage.length; + for (var i = 0; i < domStorageLength; ++i) { + var domStorage = this._domStorage[i]; + if (isLocalStorage === domStorage.isLocalStorage) { + var view = domStorage._domStorageView; + if (this.visibleView && view === this.visibleView) + domStorage._domStorageView.update(); + } + } + }, + + _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"; + + var visibleView = this.visibleView; + if (visibleView && "resize" in visibleView) + visibleView.resize(); + } +} + +WebInspector.StoragePanel.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.storage.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 self = this; + function tableNamesCallback(tableNames) + { + var tableNamesLength = tableNames.length; + for (var i = 0; i < tableNamesLength; ++i) + self.appendChild(new WebInspector.SidebarDatabaseTableTreeElement(self.database, tableNames[i])); + } + this.database.getTableNames(tableNamesCallback); + }, + + 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.storage.showDatabase(this.database, this.tableName); + } +} + +WebInspector.SidebarDatabaseTableTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; + +WebInspector.DOMStorageSidebarTreeElement = function(domStorage, className) +{ + + this.domStorage = domStorage; + + WebInspector.SidebarTreeElement.call(this, "domstorage-sidebar-tree-item " + className, domStorage, "", null, false); + + this.refreshTitles(); +} + +WebInspector.DOMStorageSidebarTreeElement.prototype = { + onselect: function() + { + WebInspector.panels.storage.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; + +WebInspector.CookieSidebarTreeElement = function() +{ + WebInspector.SidebarTreeElement.call(this, "cookie-sidebar-tree-item", null, "", null, false); + + this.refreshTitles(); +} + +WebInspector.CookieSidebarTreeElement.prototype = { + onselect: function() + { + WebInspector.panels.storage.showCookies(); + }, + + get mainTitle() + { + return WebInspector.UIString("Cookies"); + }, + + set mainTitle(x) + { + // Do nothing. + }, + + get subtitle() + { + return ""; + }, + + set subtitle(x) + { + // Do nothing. + } +} + +WebInspector.CookieSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/StylesSidebarPane.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/StylesSidebarPane.js new file mode 100644 index 0000000..6185aff --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/StylesSidebarPane.js @@ -0,0 +1,1373 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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")); + + this.settingsSelectElement = document.createElement("select"); + + var option = document.createElement("option"); + option.value = "hex"; + option.action = this._changeColorFormat.bind(this); + if (Preferences.colorFormat === "hex") + option.selected = true; + option.label = WebInspector.UIString("Hex Colors"); + this.settingsSelectElement.appendChild(option); + + option = document.createElement("option"); + option.value = "rgb"; + option.action = this._changeColorFormat.bind(this); + if (Preferences.colorFormat === "rgb") + option.selected = true; + option.label = WebInspector.UIString("RGB Colors"); + this.settingsSelectElement.appendChild(option); + + option = document.createElement("option"); + option.value = "hsl"; + option.action = this._changeColorFormat.bind(this); + if (Preferences.colorFormat === "hsl") + option.selected = true; + option.label = WebInspector.UIString("HSL Colors"); + this.settingsSelectElement.appendChild(option); + + this.settingsSelectElement.appendChild(document.createElement("hr")); + + option = document.createElement("option"); + option.action = this._createNewRule.bind(this); + option.label = WebInspector.UIString("New Style Rule"); + this.settingsSelectElement.appendChild(option); + + this.settingsSelectElement.addEventListener("click", function(event) { event.stopPropagation() }, false); + this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false); + + this.titleElement.appendChild(this.settingsSelectElement); +} + +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 self = this; + function callback(styles) + { + if (!styles) + return; + node._setStyles(styles.computedStyle, styles.inlineStyle, styles.styleAttributes, styles.matchedCSSRules); + self._update(refresh, body, node, editedSection, forceUpdate); + } + + InjectedScriptAccess.getStyles(node.id, !Preferences.showUserAgentStyles, callback); + }, + + _update: function(refresh, body, node, editedSection, forceUpdate) + { + if (!refresh) { + body.removeChildren(); + this.sections = []; + } + + var styleRules = []; + + if (refresh) { + for (var i = 0; i < this.sections.length; ++i) { + var section = this.sections[i]; + if (section instanceof WebInspector.BlankStylePropertiesSection) + continue; + if (section.computedStyle) + section.styleRule.style = node.ownerDocument.defaultView.getComputedStyle(node); + var styleRule = { section: section, style: section.styleRule.style, computedStyle: section.computedStyle, rule: section.rule }; + 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); + } + } + + // Always Show element's Style Attributes + if (node.nodeType === Node.ELEMENT_NODE) { + var inlineStyle = { selectorText: WebInspector.UIString("Style Attribute"), style: node.style, isAttribute: true }; + 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, rule: rule }); + } + } + } + + 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; + if (styleRule.section && styleRule.section.noAffect) + 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 = style.uniqueStyleProperties; + 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; + + var isAttribute = styleRule.isAttribute; + delete styleRule.isAttribute; + + // 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 if (isAttribute && styleRule.style.length === 0) + section.collapse(true); + else + section.expand(true); + + body.appendChild(section.element); + this.sections.push(section); + } + } + }, + + _changeSetting: function(event) + { + var options = this.settingsSelectElement.options; + var selectedOption = options[this.settingsSelectElement.selectedIndex]; + selectedOption.action(event); + + // Select the correct color format setting again, since it needs to be selected. + var selectedIndex = 0; + for (var i = 0; i < options.length; ++i) { + if (options[i].value === Preferences.colorFormat) { + selectedIndex = i; + break; + } + } + + this.settingsSelectElement.selectedIndex = selectedIndex; + }, + + _changeColorFormat: function(event) + { + var selectedOption = this.settingsSelectElement[this.settingsSelectElement.selectedIndex]; + Preferences.colorFormat = selectedOption.value; + + InspectorController.setSetting("color-format", Preferences.colorFormat); + + for (var i = 0; i < this.sections.length; ++i) + this.sections[i].update(true); + }, + + _createNewRule: function(event) + { + this.addBlankSection().startEditingSelector(); + }, + + addBlankSection: function() + { + var blankSection = new WebInspector.BlankStylePropertiesSection(this.appropriateSelectorForNode()); + blankSection.pane = this; + + var elementStyleSection = this.sections[1]; + this.bodyElement.insertBefore(blankSection.element, elementStyleSection.element.nextSibling); + + this.sections.splice(2, 0, blankSection); + + return blankSection; + }, + + removeSection: function(section) + { + var index = this.sections.indexOf(section); + if (index === -1) + return; + this.sections.splice(index, 1); + if (section.element.parentNode) + section.element.parentNode.removeChild(section.element); + }, + + appropriateSelectorForNode: function() + { + var node = this.node; + if (!node) + return ""; + + var id = node.getAttribute("id"); + if (id) + return "#" + id; + + var className = node.getAttribute("class"); + if (className) + return "." + className.replace(/\s+/, "."); + + var nodeName = node.nodeName.toLowerCase(); + if (nodeName === "input" && node.getAttribute("type")) + return nodeName + "[type=\"" + node.getAttribute("type") + "\"]"; + + return nodeName; + } +} + +WebInspector.StylesSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; + +WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyle, usedProperties, editable) +{ + WebInspector.PropertiesSection.call(this, styleRule.selectorText); + + this.titleElement.addEventListener("click", function(e) { e.stopPropagation(); }, false); + this.titleElement.addEventListener("dblclick", this._dblclickSelector.bind(this), false); + this.element.addEventListener("dblclick", this._dblclickEmptySpace.bind(this), false); + + this.styleRule = styleRule; + this.rule = this.styleRule.rule; + this.computedStyle = computedStyle; + this.editable = (editable && !computedStyle); + + // Prevent editing the user agent and user rules. + var isUserAgent = this.rule && this.rule.isUserAgent; + var isUser = this.rule && this.rule.isUser; + var isViaInspector = this.rule && this.rule.isViaInspector; + + 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 if (isViaInspector) + subtitle = WebInspector.UIString("via inspector"); + 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 || this.noAffect) + 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 || this.noAffect) + 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 = this.styleRule.style.getLonghandProperties(property); + for (var j = 0; j < longhandProperties.length; ++j) { + var individualProperty = longhandProperties[j]; + if (individualProperty in this.usedProperties) + return false; + } + + return true; + }, + + isInspectorStylesheet: function() + { + return (this.styleRule.parentStyleSheet === WebInspector.panels.elements.stylesheet); + }, + + 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); + } + } + + if (this._afterUpdate) { + this._afterUpdate(this); + delete this._afterUpdate; + } + }, + + onpopulate: function() + { + var style = this.styleRule.style; + + var foundShorthands = {}; + var uniqueProperties = style.uniqueStyleProperties; + 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(this.styleRule, style, name, isShorthand, inherited, overloaded, disabled); + this.propertiesTreeOutline.appendChild(item); + } + }, + + findTreeElementWithName: function(name) + { + var treeElement = this.propertiesTreeOutline.children[0]; + while (treeElement) { + if (treeElement.name === name) + return treeElement; + treeElement = treeElement.traverseNextTreeElement(true, null, true); + } + return null; + }, + + addNewBlankProperty: function() + { + var item = new WebInspector.StylePropertyTreeElement(this.styleRule, this.styleRule.style, "", false, false, false, false); + this.propertiesTreeOutline.appendChild(item); + item.listItemElement.textContent = ""; + item._newProperty = true; + return item; + }, + + _dblclickEmptySpace: function(event) + { + this.expand(); + this.addNewBlankProperty().startEditing(); + }, + + _dblclickSelector: function(event) + { + if (!this.editable) + return; + + if (!this.rule && this.propertiesTreeOutline.children.length === 0) { + this.expand(); + this.addNewBlankProperty().startEditing(); + return; + } + + if (!this.rule) + return; + + this.startEditingSelector(); + event.stopPropagation(); + }, + + startEditingSelector: function() + { + var element = this.titleElement; + if (WebInspector.isBeingEdited(element)) + return; + + WebInspector.startEditing(this.titleElement, this.editingSelectorCommitted.bind(this), this.editingSelectorCancelled.bind(this), null); + window.getSelection().setBaseAndExtent(element, 0, element, 1); + }, + + editingSelectorCommitted: function(element, newContent, oldContent, context, moveDirection) + { + function moveToNextIfNeeded() { + if (!moveDirection || moveDirection !== "forward") + return; + + this.expand(); + if (this.propertiesTreeOutline.children.length === 0) + this.addNewBlankProperty().startEditing(); + else { + var item = this.propertiesTreeOutline.children[0] + item.startEditing(item.valueElement); + } + } + + if (newContent === oldContent) + return moveToNextIfNeeded.call(this); + + var self = this; + function callback(result) + { + if (!result) { + // Invalid Syntax for a Selector + moveToNextIfNeeded.call(self); + return; + } + + var newRulePayload = result[0]; + var doesAffectSelectedNode = result[1]; + if (!doesAffectSelectedNode) { + self.noAffect = true; + self.element.addStyleClass("no-affect"); + } else { + delete self.noAffect; + self.element.removeStyleClass("no-affect"); + } + + var newRule = WebInspector.CSSStyleDeclaration.parseRule(newRulePayload); + self.rule = newRule; + self.styleRule = { section: self, style: newRule.style, selectorText: newRule.selectorText, parentStyleSheet: newRule.parentStyleSheet, rule: newRule }; + + var oldIdentifier = this.identifier; + self.identifier = newRule.selectorText + ":" + self.subtitleElement.textContent; + + self.pane.update(); + + WebInspector.panels.elements.renameSelector(oldIdentifier, this.identifier, oldContent, newContent); + + moveToNextIfNeeded.call(self); + } + + InjectedScriptAccess.applyStyleRuleText(this.rule.id, newContent, this.pane.node.id, callback); + }, + + editingSelectorCancelled: function() + { + // Do nothing, this is overridden by BlankStylePropertiesSection. + } +} + +WebInspector.StylePropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype; + +WebInspector.BlankStylePropertiesSection = function(defaultSelectorText) +{ + WebInspector.StylePropertiesSection.call(this, {selectorText: defaultSelectorText, rule: {isViaInspector: true}}, "", false, {}, false); + + this.element.addStyleClass("blank-section"); +} + +WebInspector.BlankStylePropertiesSection.prototype = { + expand: function() + { + // Do nothing, blank sections are not expandable. + }, + + editingSelectorCommitted: function(element, newContent, oldContent, context) + { + var self = this; + function callback(result) + { + if (!result) { + // Invalid Syntax for a Selector + self.editingSelectorCancelled(); + return; + } + + var rule = result[0]; + var doesSelectorAffectSelectedNode = result[1]; + + var styleRule = WebInspector.CSSStyleDeclaration.parseRule(rule); + styleRule.rule = rule; + + self.makeNormal(styleRule); + + if (!doesSelectorAffectSelectedNode) { + self.noAffect = true; + self.element.addStyleClass("no-affect"); + } + + self.subtitleElement.textContent = WebInspector.UIString("via inspector"); + self.expand(); + + self.addNewBlankProperty().startEditing(); + } + + InjectedScriptAccess.addStyleSelector(newContent, this.pane.node.id, callback); + }, + + editingSelectorCancelled: function() + { + this.pane.removeSection(this); + }, + + makeNormal: function(styleRule) + { + this.element.removeStyleClass("blank-section"); + + this.styleRule = styleRule; + this.rule = styleRule.rule; + this.computedStyle = false; + this.editable = true; + this.identifier = styleRule.selectorText + ":via inspector"; + + this.__proto__ = WebInspector.StylePropertiesSection.prototype; + } +} + +WebInspector.BlankStylePropertiesSection.prototype.__proto__ = WebInspector.StylePropertiesSection.prototype; + +WebInspector.StylePropertyTreeElement = function(styleRule, style, name, shorthand, inherited, overloaded, disabled) +{ + this._styleRule = styleRule; + 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 ? this.style.getShorthandPriority(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 ? this.style.getShorthandValue(this.name) : this.style.getPropertyValue(this.name)); + }, + + onattach: function() + { + this.updateTitle(); + }, + + updateTitle: function() + { + var priority = this.priority; + var value = this.value; + + if (priority && !priority.length) + delete priority; + if (priority) + priority = "!" + priority; + + 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; + this.nameElement = nameElement; + + var valueElement = document.createElement("span"); + valueElement.className = "value"; + this.valueElement = valueElement; + + if (value) { + function processValue(regex, processor, nextProcessor, valueText) + { + var container = document.createDocumentFragment(); + + var items = valueText.replace(regex, "\0$1\0").split("\0"); + for (var i = 0; i < items.length; ++i) { + if ((i % 2) === 0) { + if (nextProcessor) + container.appendChild(nextProcessor(items[i])); + else + container.appendChild(document.createTextNode(items[i])); + } else { + var processedNode = processor(items[i]); + if (processedNode) + container.appendChild(processedNode); + } + } + + return container; + } + + function linkifyURL(url) + { + var container = document.createDocumentFragment(); + container.appendChild(document.createTextNode("url(")); + container.appendChild(WebInspector.linkifyURLAsNode(url, url, null, (url in WebInspector.resourceURLMap))); + container.appendChild(document.createTextNode(")")); + return container; + } + + function processColor(text) + { + try { + var color = new WebInspector.Color(text); + } catch (e) { + return document.createTextNode(text); + } + + var swatchElement = document.createElement("span"); + swatchElement.title = WebInspector.UIString("Click to change color format"); + swatchElement.className = "swatch"; + swatchElement.style.setProperty("background-color", text); + + swatchElement.addEventListener("click", changeColorDisplay, false); + swatchElement.addEventListener("dblclick", function(event) { event.stopPropagation() }, false); + + var format; + if (Preferences.showColorNicknames && color.nickname) + format = "nickname"; + else if (Preferences.colorFormat === "rgb") + format = (color.simple ? "rgb" : "rgba"); + else if (Preferences.colorFormat === "hsl") + format = (color.simple ? "hsl" : "hsla"); + else if (color.simple) + format = (color.hasShortHex() ? "shorthex" : "hex"); + else + format = "rgba"; + + var colorValueElement = document.createElement("span"); + colorValueElement.textContent = color.toString(format); + + function changeColorDisplay(event) + { + switch (format) { + case "rgb": + format = "hsl"; + break; + + case "shorthex": + format = "hex"; + break; + + case "hex": + format = "rgb"; + break; + + case "nickname": + if (color.simple) { + if (color.hasShortHex()) + format = "shorthex"; + else + format = "hex"; + break; + } + + format = "rgba"; + break; + + case "hsl": + if (color.nickname) + format = "nickname"; + else if (color.hasShortHex()) + format = "shorthex"; + else + format = "hex"; + break; + + case "rgba": + format = "hsla"; + break; + + case "hsla": + if (color.nickname) + format = "nickname"; + else + format = "rgba"; + break; + } + + colorValueElement.textContent = color.toString(format); + } + + var container = document.createDocumentFragment(); + container.appendChild(swatchElement); + container.appendChild(colorValueElement); + return container; + } + + var colorRegex = /((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3}|\b\w+\b)/g; + var colorProcessor = processValue.bind(window, colorRegex, processColor, null); + + valueElement.appendChild(processValue(/url\(([^)]+)\)/g, linkifyURL, colorProcessor, value)); + } + + 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(";")); + + this.tooltip = this.name + ": " + valueElement.textContent + (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; + + var self = this; + function callback(newPayload) + { + if (!newPayload) + return; + + self.style = WebInspector.CSSStyleDeclaration.parseStyle(newPayload); + self._styleRule.style = self.style; + + // Set the disabled property here, since the code above replies on it not changing + // until after the value and priority are retrieved. + self.disabled = disabled; + + if (self.treeOutline.section && self.treeOutline.section.pane) + self.treeOutline.section.pane.dispatchEventToListeners("style property toggled"); + + self.updateAll(true); + } + + InjectedScriptAccess.toggleStyleEnabled(this.style.id, this.name, disabled, callback); + }, + + 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 = this.style.getLonghandProperties(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._styleRule, this.style, name, false, inherited, overloaded); + this.appendChild(item); + } + }, + + ondblclick: function(element, event) + { + this.startEditing(event.target); + event.stopPropagation(); + }, + + 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 = this.style.styleTextWithShorthands(); + } 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. + InjectedScriptAccess.setStyleText(this.style.id, 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._newProperty) + this.treeOutline.removeChild(this); + else if (this.originalCSSText) { + InjectedScriptAccess.setStyleText(this.style.id, 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, moveDirection) + { + this.editingEnded(context); + + // Determine where to move to before making changes + var newProperty, moveToPropertyName, moveToSelector; + var moveTo = (moveDirection === "forward" ? this.nextSibling : this.previousSibling); + if (moveTo) + moveToPropertyName = moveTo.name; + else if (moveDirection === "forward") + newProperty = true; + else if (moveDirection === "backward" && this.treeOutline.section.rule) + moveToSelector = true; + + // Make the Changes and trigger the moveToNextCallback after updating + var blankInput = /^\s*$/.test(userInput); + if (userInput !== previousContent || (this._newProperty && blankInput)) { // only if something changed, or adding a new style and it was blank + this.treeOutline.section._afterUpdate = moveToNextCallback.bind(this, this._newProperty, !blankInput); + this.applyStyleText(userInput, true); + } else + moveToNextCallback(this._newProperty, false, this.treeOutline.section, false); + + // The Callback to start editing the next property + function moveToNextCallback(alreadyNew, valueChanged, section) + { + if (!moveDirection) + return; + + // User just tabbed through without changes + if (moveTo && moveTo.parent) { + moveTo.startEditing(moveTo.valueElement); + return; + } + + // User has made a change then tabbed, wiping all the original treeElements, + // recalculate the new treeElement for the same property we were going to edit next + if (moveTo && !moveTo.parent) { + var treeElement = section.findTreeElementWithName(moveToPropertyName); + if (treeElement) + treeElement.startEditing(treeElement.valueElement); + return; + } + + // Create a new attribute in this section + if (newProperty) { + if (alreadyNew && !valueChanged) + return; + + var item = section.addNewBlankProperty(); + item.startEditing(); + return; + } + + if (moveToSelector) + section.startEditingSelector(); + } + }, + + applyStyleText: function(styleText, updateInterface) + { + var section = this.treeOutline.section; + var elementsPanel = WebInspector.panels.elements; + var styleTextLength = styleText.trimWhitespace().length; + if (!styleTextLength && updateInterface) { + if (this._newProperty) { + // The user deleted everything, so remove the tree element and update. + this.parent.removeChild(this); + return; + } else { + delete section._afterUpdate; + } + } + + var self = this; + function callback(result) + { + if (!result) { + // The user typed something, but it didn't parse. Just abort and restore + // the original title for this property. If this was a new attribute and + // we couldn't parse, then just remove it. + if (self._newProperty) { + self.parent.removeChild(self); + return; + } + if (updateInterface) + self.updateTitle(); + return; + } + + var newPayload = result[0]; + var changedProperties = result[1]; + elementsPanel.removeStyleChange(section.identifier, self.style, self.name); + + if (!styleTextLength) { + // Do remove ourselves from UI when the property removal is confirmed. + self.parent.removeChild(self); + } else { + self.style = WebInspector.CSSStyleDeclaration.parseStyle(newPayload); + for (var i = 0; i < changedProperties.length; ++i) + elementsPanel.addStyleChange(section.identifier, self.style, changedProperties[i]); + self._styleRule.style = self.style; + } + + if (section && section.pane) + section.pane.dispatchEventToListeners("style edited"); + + if (updateInterface) + self.updateAll(true); + + if (!self.rule) + WebInspector.panels.elements.treeOutline.update(); + } + + InjectedScriptAccess.applyStyleText(this.style.id, styleText.trimWhitespace(), this.name, callback); + } +} + +WebInspector.StylePropertyTreeElement.prototype.__proto__ = TreeElement.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/SummaryBar.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/SummaryBar.js new file mode 100644 index 0000000..bbf2b1a --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/SummaryBar.js @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org> + * + * 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.SummaryBar = function(categories) +{ + this.categories = categories; + + this.element = document.createElement("div"); + this.element.className = "summary-bar"; + + this.graphElement = document.createElement("canvas"); + this.graphElement.setAttribute("width", "450"); + this.graphElement.setAttribute("height", "38"); + this.graphElement.className = "summary-graph"; + this.element.appendChild(this.graphElement); + + this.legendElement = document.createElement("div"); + this.legendElement.className = "summary-graph-legend"; + this.element.appendChild(this.legendElement); +} + +WebInspector.SummaryBar.prototype = { + + get calculator() { + return this._calculator; + }, + + set calculator(x) { + this._calculator = x; + }, + + reset: function() + { + this.legendElement.removeChildren(); + this._drawSummaryGraph(); + }, + + update: function(data) + { + var graphInfo = this.calculator.computeSummaryValues(data); + + var fillSegments = []; + + this.legendElement.removeChildren(); + + for (var category in this.categories) { + var size = graphInfo.categoryValues[category]; + if (!size) + continue; + + var color = this.categories[category].color; + var colorString = "rgb(" + color.r + ", " + color.g + ", " + color.b + ")"; + + var fillSegment = {color: colorString, value: size}; + fillSegments.push(fillSegment); + + var legendLabel = this._makeLegendElement(this.categories[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); + }, + + _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 (!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.graphElement.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); + }, + + _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(); + }, + + _makeLegendElement: function(label, value, color) + { + var legendElement = document.createElement("label"); + legendElement.className = "summary-graph-legend-item"; + + if (color) { + var swatch = document.createElement("canvas"); + swatch.className = "summary-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 = "summary-graph-legend-label"; + legendElement.appendChild(labelElement); + + var headerElement = document.createElement("div"); + headerElement.className = "summary-graph-legend-header"; + headerElement.textContent = label; + labelElement.appendChild(headerElement); + + var valueElement = document.createElement("div"); + valueElement.className = "summary-graph-legend-value"; + valueElement.textContent = value; + labelElement.appendChild(valueElement); + + return legendElement; + } +} + +WebInspector.SummaryBar.prototype.__proto__ = WebInspector.Object.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/TextPrompt.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/TextPrompt.js new file mode 100644 index 0000000..5ff774f --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/TextPrompt.js @@ -0,0 +1,319 @@ +/* + * 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": + case "End": + 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"); + this.completions(wordPrefixRange, auto, this._completionsReady.bind(this, selection, auto, wordPrefixRange)); + }, + + _completionsReady: function(selection, auto, originalWordPrefixRange, completions) + { + if (!completions || !completions.length) + return; + + var selectionRange = selection.getRangeAt(0); + + var fullWordRange = document.createRange(); + fullWordRange.setStart(originalWordPrefixRange.startContainer, originalWordPrefixRange.startOffset); + fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffset); + + if (originalWordPrefixRange.toString() + selectionRange.toString() != fullWordRange.toString()) + return; + + 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 = originalWordPrefixRange.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_frame/tools/test/reference_build/chrome/resources/inspector/TimelineAgent.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/TimelineAgent.js new file mode 100644 index 0000000..6d18732 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/TimelineAgent.js @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +WebInspector.TimelineAgent = function() { + // Not implemented. +} + +// Must be kept in sync with TimelineItem.h +WebInspector.TimelineAgent.ItemType = { + DOMDispatch : 0, + Layout : 1, + RecalculateStyles : 2, + Paint : 3, + ParseHTML : 4 +}; + +WebInspector.addItemToTimeline = function(record) { + // Not implemented. +} + +WebInspector.timelineWasEnabled = function() { + // Not implemented. +} + +WebInspector.timelineWasDisabled = function() { + // Not implemented. +} diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/TopDownProfileDataGridTree.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/TopDownProfileDataGridTree.js new file mode 100644 index 0000000..b9d8b94 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/View.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/View.js new file mode 100644 index 0000000..632a61ae --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/WatchExpressionsSidebarPane.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/WatchExpressionsSidebarPane.js new file mode 100644 index 0000000..b568939 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/WatchExpressionsSidebarPane.js @@ -0,0 +1,274 @@ +/* + * Copyright (C) IBM Corp. 2009 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 IBM Corp. 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. + */ + +WebInspector.WatchExpressionsSidebarPane = function() +{ + WebInspector.SidebarPane.call(this, WebInspector.UIString("Watch Expressions")); + + this.section = new WebInspector.WatchExpressionsSection(); + + this.bodyElement.appendChild(this.section.element); + + var addElement = document.createElement("button"); + addElement.setAttribute("type", "button"); + addElement.textContent = WebInspector.UIString("Add"); + addElement.addEventListener("click", this.section.addExpression.bind(this.section), false); + + var refreshElement = document.createElement("button"); + refreshElement.setAttribute("type", "button"); + refreshElement.textContent = WebInspector.UIString("Refresh"); + refreshElement.addEventListener("click", this.section.update.bind(this.section), false); + + var centerElement = document.createElement("div"); + centerElement.addStyleClass("watch-expressions-buttons-container"); + centerElement.appendChild(addElement); + centerElement.appendChild(refreshElement); + this.bodyElement.appendChild(centerElement); + + this.expanded = this.section.loadSavedExpressions().length > 0; + this.onexpand = this.refreshExpressions.bind(this); +} + +WebInspector.WatchExpressionsSidebarPane.prototype = { + refreshExpressions: function() + { + this.section.update(); + } +} + +WebInspector.WatchExpressionsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; + +WebInspector.WatchExpressionsSection = function() +{ + WebInspector.ObjectPropertiesSection.call(this); + + this.watchExpressions = this.loadSavedExpressions(); + + this.headerElement.className = "hidden"; + this.editable = true; + this.expanded = true; + this.propertiesElement.addStyleClass("watch-expressions"); +} + +WebInspector.WatchExpressionsSection.NewWatchExpression = "\xA0"; + +WebInspector.WatchExpressionsSection.prototype = { + update: function() + { + function appendResult(expression, watchIndex, result, exception) + { + // The null check catches some other cases, like null itself, and NaN + if ((typeof result !== "object") || (result == null)) + result = new WebInspector.ObjectProxy(null, [], 0, String(result), false); + + var property = new WebInspector.ObjectPropertyProxy(expression, result); + property.watchIndex = watchIndex; + + // For newly added, empty expressions, set description to "", + // since otherwise you get DOMWindow + if (property.name === WebInspector.WatchExpressionsSection.NewWatchExpression) + property.value.description = ""; + + // To clarify what's going on here: + // In the outer function, we calculate the number of properties + // that we're going to be updating, and set that in the + // propertyCount variable. + // In this function, we test to see when we are processing the + // last property, and then call the superclass's updateProperties() + // method to get all the properties refreshed at once. + properties.push(property); + + if (properties.length == propertyCount) + this.updateProperties(properties, WebInspector.WatchExpressionTreeElement, WebInspector.WatchExpressionsSection.CompareProperties); + } + + var properties = []; + + // Count the properties, so we known when to call this.updateProperties() + // in appendResult() + var propertyCount = 0; + for (var i = 0; i < this.watchExpressions.length; ++i) { + if (!this.watchExpressions[i]) + continue; + ++propertyCount; + } + + // Now process all the expressions, since we have the actual count, + // which is checked in the appendResult inner function. + for (var i = 0; i < this.watchExpressions.length; ++i) { + var expression = this.watchExpressions[i]; + if (!expression) + continue; + + WebInspector.console.evalInInspectedWindow("(" + expression + ")", appendResult.bind(this, expression, i)); + } + + // note this is setting the expansion of the tree, not the section; + // with no expressions, and expanded tree, we get some extra vertical + // white space + // FIXME: should change to use header buttons instead of the buttons + // at the bottom of the section, then we can add a "No Watch Expressions + // element when there are no watch expressions, and this issue should + // go away. + this.expanded = (propertyCount != 0); + }, + + addExpression: function() + { + this.watchExpressions.push(WebInspector.WatchExpressionsSection.NewWatchExpression); + this.update(); + + // After update(), the new empty expression to be edited + // will be in the tree, but we have to find it. + treeElement = this.findAddedTreeElement(); + if (treeElement) + treeElement.startEditing(); + }, + + updateExpression: function(element, value) + { + this.watchExpressions[element.property.watchIndex] = value; + this.saveExpressions(); + this.update(); + }, + + findAddedTreeElement: function() + { + var children = this.propertiesTreeOutline.children; + for (var i = 0; i < children.length; ++i) + if (children[i].property.name === WebInspector.WatchExpressionsSection.NewWatchExpression) + return children[i]; + }, + + loadSavedExpressions: function() + { + var json = InspectorController.setting("watchExpressions"); + if (!json) + return []; + + try { + json = JSON.parse(json); + } catch(e) { + return []; + } + + return json.expressions || []; + }, + + saveExpressions: function() + { + var toSave = []; + for (var i = 0; i < this.watchExpressions.length; i++) + if (this.watchExpressions[i]) + toSave.push(this.watchExpressions[i]); + + var json = JSON.stringify({expressions: toSave}); + InspectorController.setSetting("watchExpressions", json); + + return toSave.length; + } +} + +WebInspector.WatchExpressionsSection.prototype.__proto__ = WebInspector.ObjectPropertiesSection.prototype; + +WebInspector.WatchExpressionsSection.CompareProperties = function(propertyA, propertyB) +{ + if (propertyA.watchIndex == propertyB.watchIndex) + return 0; + else if (propertyA.watchIndex < propertyB.watchIndex) + return -1; + else + return 1; +} + +WebInspector.WatchExpressionTreeElement = function(property) +{ + WebInspector.ObjectPropertyTreeElement.call(this, property); +} + +WebInspector.WatchExpressionTreeElement.prototype = { + update: function() + { + WebInspector.ObjectPropertyTreeElement.prototype.update.call(this); + + var deleteButton = document.createElement("input"); + deleteButton.type = "button"; + deleteButton.title = WebInspector.UIString("Delete watch expression."); + deleteButton.addStyleClass("enabled-button"); + deleteButton.addStyleClass("delete-button"); + deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false); + + this.listItemElement.insertBefore(deleteButton, this.listItemElement.firstChild); + }, + + _deleteButtonClicked: function() + { + this.treeOutline.section.updateExpression(this, null); + }, + + startEditing: function() + { + if (WebInspector.isBeingEdited(this.nameElement) || !this.treeOutline.section.editable) + return; + + this.nameElement.textContent = this.property.name.trimWhitespace(); + + var context = { expanded: this.expanded }; + + // collapse temporarily, if required + this.hasChildren = false; + + this.listItemElement.addStyleClass("editing-sub-part"); + + WebInspector.startEditing(this.nameElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context); + }, + + editingCancelled: function(element, context) + { + if (!this.nameElement.textContent) + this.treeOutline.section.updateExpression(this, null); + + this.update(); + this.editingEnded(context); + }, + + applyExpression: function(expression, updateInterface) + { + expression = expression.trimWhitespace(); + + if (!expression) + expression = null; + + this.property.name = expression; + this.treeOutline.section.updateExpression(this, expression); + } +} + +WebInspector.WatchExpressionTreeElement.prototype.__proto__ = WebInspector.ObjectPropertyTreeElement.prototype; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/base.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/base.js new file mode 100644 index 0000000..1a76aee --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/codemap.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/codemap.js new file mode 100644 index 0000000..404127f --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/codemap.js @@ -0,0 +1,258 @@ +// 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 statically compiled code. + */ + this.statics_ = new goog.structs.SplayTree(); + + /** + * Libraries entries. Used for the whole static code libraries. + */ + this.libraries_ = 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 library entry. + * + * @param {number} start The starting address. + * @param {devtools.profiler.CodeMap.CodeEntry} codeEntry Code entry object. + */ +devtools.profiler.CodeMap.prototype.addLibrary = function( + start, codeEntry) { + this.markPages_(start, start + codeEntry.size); + this.libraries_.insert(start, codeEntry); +}; + + +/** + * 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.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_) { + // Static code entries can contain "holes" of unnamed code. + // In this case, the whole library is assigned to this address. + return this.findInTree_(this.statics_, addr) || + this.findInTree_(this.libraries_, 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. + */ +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(); +}; + + +/** + * Returns an array of all libraries entries. + */ +devtools.profiler.CodeMap.prototype.getAllLibrariesEntries = function() { + return this.libraries_.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_frame/tools/test/reference_build/chrome/resources/inspector/consarray.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/consarray.js new file mode 100644 index 0000000..c67abb7 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/csvparser.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/csvparser.js new file mode 100644 index 0000000..9e58dea --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/debugger_agent.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/debugger_agent.js new file mode 100644 index 0000000..1d566eb --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/debugger_agent.js @@ -0,0 +1,1490 @@ +// 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.SetContextId = + goog.bind(this.setContextId_, this); + RemoteDebuggerAgent.DidGetActiveProfilerModules = + goog.bind(this.didGetActiveProfilerModules_, 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 frames. + * @type {Array.<devtools.CallFrame>} + */ + this.callFrames_ = []; + + /** + * 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 the scripts list should be requested next time when context id is + * set. + * @type {boolean} + */ + this.requestScriptsWhenContextIdSet_ = false; + + /** + * Active profiler modules flags. + * @type {number} + */ + this.activeProfilerModules_ = + devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_NONE; + + /** + * Profiler processor instance. + * @type {devtools.profiler.Processor} + */ + this.profilerProcessor_ = new devtools.profiler.Processor(); + + /** + * Container of all breakpoints set using resource URL. These breakpoints + * survive page reload. Breakpoints set by script id(for scripts that don't + * have URLs) are stored in ScriptInfo objects. + * @type {Object} + */ + this.urlToBreakpoints_ = {}; + + + /** + * Exception message that is shown to user while on exception break. + * @type {WebInspector.ConsoleMessage} + */ + this.currentExceptionMessage_ = null; +}; + + +/** + * A copy of the scope types from v8/src/mirror-delay.js + * @enum {number} + */ +devtools.DebuggerAgent.ScopeType = { + Global: 0, + Local: 1, + With: 2, + Closure: 3, + Catch: 4 +}; + + +/** + * A copy of enum from include/v8.h + * @enum {number} + */ +devtools.DebuggerAgent.ProfilerModules = { + PROFILER_MODULE_NONE: 0, + PROFILER_MODULE_CPU: 1, + PROFILER_MODULE_HEAP_STATS: 1 << 1, + PROFILER_MODULE_JS_CONSTRUCTORS: 1 << 2, + PROFILER_MODULE_HEAP_SNAPSHOT: 1 << 16 +}; + + +/** + * Resets debugger agent to its initial state. + */ +devtools.DebuggerAgent.prototype.reset = function() { + this.contextId_ = null; + // No need to request scripts since they all will be pushed in AfterCompile + // events. + this.requestScriptsWhenContextIdSet_ = false; + this.parsedScripts_ = {}; + this.requestNumberToBreakpointInfo_ = {}; + this.callFrames_ = []; + 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. +}; + + +/** + * Initializes scripts UI. This method is called every time Scripts panel + * is shown. It will send request for context id if it's not set yet. + */ +devtools.DebuggerAgent.prototype.initUI = function() { + // There can be a number of scripts from after-compile events that are + // pending addition into the UI. + for (var scriptId in this.parsedScripts_) { + var script = this.parsedScripts_[scriptId]; + WebInspector.parsedScriptSource(scriptId, script.getUrl(), + undefined /* script source */, script.getLineOffset()); + } + + // Initialize scripts cache when Scripts panel is shown first time. + if (this.scriptsCacheInitialized_) { + return; + } + this.scriptsCacheInitialized_ = true; + if (this.contextId_) { + // We already have context id. This means that we are here from the + // very beginning of the page load cycle and hence will get all scripts + // via after-compile events. No need to request scripts for this session. + return; + } + // Script list should be requested only when current context id is known. + RemoteDebuggerAgent.GetContextId(); + this.requestScriptsWhenContextIdSet_ = true; +}; + + +/** + * Asynchronously requests the debugger for the script source. + * @param {number} scriptId Id of the script whose source should be resolved. + * @param {function(source:?string):void} callback Function that will be called + * when the source resolution is completed. 'source' parameter will be null + * if the resolution fails. + */ +devtools.DebuggerAgent.prototype.resolveScriptSource = function( + scriptId, callback) { + var script = this.parsedScripts_[scriptId]; + if (!script || script.isUnresolved()) { + callback(null); + return; + } + + var cmd = new devtools.DebugCommand('scripts', { + 'ids': [scriptId], + 'includeSource': true + }); + devtools.DebuggerAgent.sendCommand_(cmd); + // Force v8 execution so that it gets to processing the requested command. + RemoteToolsAgent.ExecuteVoidJavaScript(); + + 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. + * @param {?string} condition The breakpoint condition. + */ +devtools.DebuggerAgent.prototype.addBreakpoint = function( + sourceId, line, condition) { + var script = this.parsedScripts_[sourceId]; + if (!script) { + return; + } + + line = devtools.DebuggerAgent.webkitToV8LineNumber_(line); + + var commandArguments; + if (script.getUrl()) { + var breakpoints = this.urlToBreakpoints_[script.getUrl()]; + if (breakpoints && breakpoints[line]) { + return; + } + if (!breakpoints) { + breakpoints = {}; + this.urlToBreakpoints_[script.getUrl()] = breakpoints; + } + + var breakpointInfo = new devtools.BreakpointInfo(line); + breakpoints[line] = breakpointInfo; + + commandArguments = { + 'groupId': this.contextId_, + 'type': 'script', + 'target': script.getUrl(), + 'line': line, + 'condition': condition + }; + } else { + var breakpointInfo = script.getBreakpointInfo(line); + if (breakpointInfo) { + return; + } + + breakpointInfo = new devtools.BreakpointInfo(line); + script.addBreakpointInfo(breakpointInfo); + + commandArguments = { + 'groupId': this.contextId_, + 'type': 'scriptId', + 'target': sourceId, + 'line': line, + 'condition': condition + }; + } + + var cmd = new devtools.DebugCommand('setbreakpoint', commandArguments); + + this.requestNumberToBreakpointInfo_[cmd.getSequenceNumber()] = breakpointInfo; + + devtools.DebuggerAgent.sendCommand_(cmd); + // Force v8 execution so that it gets to processing the requested command. + // It is necessary for being able to change a breakpoint just after it + // has been created (since we need an existing breakpoint id for that). + RemoteToolsAgent.ExecuteVoidJavaScript(); +}; + + +/** + * @param {number} sourceId Id of the script for the breakpoint. + * @param {number} line Number of the line for the breakpoint. + */ +devtools.DebuggerAgent.prototype.removeBreakpoint = function(sourceId, line) { + var script = this.parsedScripts_[sourceId]; + if (!script) { + return; + } + + line = devtools.DebuggerAgent.webkitToV8LineNumber_(line); + + var breakpointInfo; + if (script.getUrl()) { + var breakpoints = this.urlToBreakpoints_[script.getUrl()]; + breakpointInfo = breakpoints[line]; + delete breakpoints[line]; + } else { + breakpointInfo = script.getBreakpointInfo(line); + if (breakpointInfo) { + script.removeBreakpointInfo(breakpointInfo); + } + } + + if (!breakpointInfo) { + return; + } + + breakpointInfo.markAsRemoved(); + + var id = breakpointInfo.getV8Id(); + + // If we don't know id of this breakpoint in the v8 debugger we cannot send + // 'clearbreakpoint' request. In that case it will be removed in + // 'setbreakpoint' response handler when we learn the id. + if (id != -1) { + this.requestClearBreakpoint_(id); + } +}; + + +/** + * @param {number} sourceId Id of the script for the breakpoint. + * @param {number} line Number of the line for the breakpoint. + * @param {?string} condition New breakpoint condition. + */ +devtools.DebuggerAgent.prototype.updateBreakpoint = function( + sourceId, line, condition) { + var script = this.parsedScripts_[sourceId]; + if (!script) { + return; + } + + line = devtools.DebuggerAgent.webkitToV8LineNumber_(line); + + var breakpointInfo; + if (script.getUrl()) { + var breakpoints = this.urlToBreakpoints_[script.getUrl()]; + breakpointInfo = breakpoints[line]; + } else { + breakpointInfo = script.getBreakpointInfo(line); + } + + var id = breakpointInfo.getV8Id(); + + // If we don't know id of this breakpoint in the v8 debugger we cannot send + // the 'changebreakpoint' request. + if (id != -1) { + // TODO(apavlov): make use of the real values for 'enabled' and + // 'ignoreCount' when appropriate. + this.requestChangeBreakpoint_(id, true, condition, null); + } +}; + + +/** + * Tells the v8 debugger to step into the next statement. + */ +devtools.DebuggerAgent.prototype.stepIntoStatement = function() { + this.stepCommand_('in'); +}; + + +/** + * Tells the v8 debugger to step out of current function. + */ +devtools.DebuggerAgent.prototype.stepOutOfFunction = function() { + this.stepCommand_('out'); +}; + + +/** + * Tells the v8 debugger to step over the next statement. + */ +devtools.DebuggerAgent.prototype.stepOverStatement = function() { + this.stepCommand_('next'); +}; + + +/** + * Tells the v8 debugger to continue execution after it has been stopped on a + * breakpoint or an exception. + */ +devtools.DebuggerAgent.prototype.resumeExecution = function() { + this.clearExceptionMessage_(); + var cmd = new devtools.DebugCommand('continue'); + devtools.DebuggerAgent.sendCommand_(cmd); +}; + + +/** + * Creates exception message and schedules it for addition to the resource upon + * backtrace availability. + * @param {string} url Resource url. + * @param {number} line Resource line number. + * @param {string} message Exception text. + */ +devtools.DebuggerAgent.prototype.createExceptionMessage_ = function( + url, line, message) { + this.currentExceptionMessage_ = new WebInspector.ConsoleMessage( + WebInspector.ConsoleMessage.MessageSource.JS, + WebInspector.ConsoleMessage.MessageType.Log, + WebInspector.ConsoleMessage.MessageLevel.Error, + line, + url, + 0 /* group level */, + 1 /* repeat count */, + '[Exception] ' + message); +}; + + +/** + * Shows pending exception message that is created with createExceptionMessage_ + * earlier. + */ +devtools.DebuggerAgent.prototype.showPendingExceptionMessage_ = function() { + if (!this.currentExceptionMessage_) { + return; + } + var msg = this.currentExceptionMessage_; + var resource = WebInspector.resourceURLMap[msg.url]; + if (resource) { + msg.resource = resource; + WebInspector.panels.resources.addMessageToResource(resource, msg); + } else { + this.currentExceptionMessage_ = null; + } +}; + + +/** + * Clears exception message from the resource. + */ +devtools.DebuggerAgent.prototype.clearExceptionMessage_ = function() { + if (this.currentExceptionMessage_) { + var messageElement = + this.currentExceptionMessage_._resourceMessageLineElement; + var bubble = messageElement.parentElement; + bubble.removeChild(messageElement); + if (!bubble.firstChild) { + // Last message in bubble removed. + bubble.parentElement.removeChild(bubble); + } + this.currentExceptionMessage_ = null; + } +}; + + +/** + * @return {boolean} True iff the debugger will pause execution on the + * exceptions. + */ +devtools.DebuggerAgent.prototype.pauseOnExceptions = function() { + return this.pauseOnExceptions_; +}; + + +/** + * Tells whether to pause in the debugger on the exceptions or not. + * @param {boolean} value True iff execution should be stopped in the debugger + * on the exceptions. + */ +devtools.DebuggerAgent.prototype.setPauseOnExceptions = function(value) { + this.pauseOnExceptions_ = value; +}; + + +/** + * Sends 'evaluate' request to the debugger. + * @param {Object} arguments Request arguments map. + * @param {function(devtools.DebuggerMessage)} callback Callback to be called + * when response is received. + */ +devtools.DebuggerAgent.prototype.requestEvaluate = function( + arguments, callback) { + var cmd = new devtools.DebugCommand('evaluate', arguments); + devtools.DebuggerAgent.sendCommand_(cmd); + this.requestSeqToCallback_[cmd.getSequenceNumber()] = callback; +}; + + +/** + * Sends 'lookup' request for each unresolved property of the object. When + * response is received the properties will be changed with their resolved + * values. + * @param {Object} object Object whose properties should be resolved. + * @param {function(devtools.DebuggerMessage)} Callback to be called when all + * children are resolved. + * @param {boolean} noIntrinsic Whether intrinsic properties should be included. + */ +devtools.DebuggerAgent.prototype.resolveChildren = function(object, callback, + noIntrinsic) { + if ('handle' in object) { + var result = []; + devtools.DebuggerAgent.formatObjectProperties_(object, result, + noIntrinsic); + callback(result); + } else { + this.requestLookup_([object.ref], function(msg) { + var result = []; + if (msg.isSuccess()) { + var handleToObject = msg.getBody(); + var resolved = handleToObject[object.ref]; + devtools.DebuggerAgent.formatObjectProperties_(resolved, result, + noIntrinsic); + callback(result); + } else { + callback([]); + } + }); + } +}; + + +/** + * Sends 'scope' request for the scope object to resolve its variables. + * @param {Object} scope Scope to be resolved. + * @param {function(Array.<WebInspector.ObjectPropertyProxy>)} callback + * Callback to be called when all scope variables are resolved. + */ +devtools.DebuggerAgent.prototype.resolveScope = function(scope, callback) { + var cmd = new devtools.DebugCommand('scope', { + 'frameNumber': scope.frameNumber, + 'number': scope.index, + 'compactFormat': true + }); + devtools.DebuggerAgent.sendCommand_(cmd); + this.requestSeqToCallback_[cmd.getSequenceNumber()] = function(msg) { + var result = []; + if (msg.isSuccess()) { + var scopeObjectJson = msg.getBody().object; + devtools.DebuggerAgent.formatObjectProperties_(scopeObjectJson, result, + true /* no intrinsic */); + } + callback(result); + }; +}; + + +/** + * 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', + WebInspector.UIString('Processing...'), + '', null, false); + var profilesSidebar = WebInspector.panels.profiles.sidebarTree; + + this.profilerProcessor_.setCallbacks( + function onProfileProcessingStarted() { + // Set visually empty string. Subtitle hiding is done via styles + // manipulation which doesn't play well with dynamic append / removal. + processingIcon.subtitle = ' '; + profilesSidebar.appendChild(processingIcon); + }, + function onProfileProcessingStatus(ticksCount) { + processingIcon.subtitle = + WebInspector.UIString('%d ticks processed', ticksCount); + }, + function onProfileProcessingFinished(profile) { + profilesSidebar.removeChild(processingIcon); + WebInspector.addProfile(profile); + // If no profile is currently shown, show the new one. + var profilesPanel = WebInspector.panels.profiles; + if (!profilesPanel.visibleView) { + profilesPanel.showProfile(profile); + } + } + ); +}; + + +/** + * Initializes profiling state. + */ +devtools.DebuggerAgent.prototype.initializeProfiling = function() { + this.setupProfilerProcessorCallbacks(); + RemoteDebuggerAgent.GetActiveProfilerModules(); +}; + + +/** + * Starts profiling. + * @param {number} modules List of modules to enable. + */ +devtools.DebuggerAgent.prototype.startProfiling = function(modules) { + RemoteDebuggerAgent.StartProfiling(modules); + if (modules & + devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_HEAP_SNAPSHOT) { + // Active modules will not change, instead, a snapshot will be logged. + RemoteDebuggerAgent.GetNextLogLines(); + } else { + RemoteDebuggerAgent.GetActiveProfilerModules(); + } +}; + + +/** + * Stops profiling. + */ +devtools.DebuggerAgent.prototype.stopProfiling = function(modules) { + RemoteDebuggerAgent.StopProfiling(modules); +}; + + +/** + * @param{number} scriptId + * @return {string} Type of the context of the script with specified id. + */ +devtools.DebuggerAgent.prototype.getScriptContextType = function(scriptId) { + return this.parsedScripts_[scriptId].getContextType(); +}; + + +/** + * Removes specified breakpoint from the v8 debugger. + * @param {number} breakpointId Id of the breakpoint in the v8 debugger. + */ +devtools.DebuggerAgent.prototype.requestClearBreakpoint_ = function( + breakpointId) { + var cmd = new devtools.DebugCommand('clearbreakpoint', { + 'breakpoint': breakpointId + }); + devtools.DebuggerAgent.sendCommand_(cmd); +}; + + +/** + * Changes breakpoint parameters in the v8 debugger. + * @param {number} breakpointId Id of the breakpoint in the v8 debugger. + * @param {boolean} enabled Whether to enable the breakpoint. + * @param {?string} condition New breakpoint condition. + * @param {number} ignoreCount New ignore count for the breakpoint. + */ +devtools.DebuggerAgent.prototype.requestChangeBreakpoint_ = function( + breakpointId, enabled, condition, ignoreCount) { + var cmd = new devtools.DebugCommand('changebreakpoint', { + 'breakpoint': breakpointId, + 'enabled': enabled, + 'condition': condition, + 'ignoreCount': ignoreCount + }); + devtools.DebuggerAgent.sendCommand_(cmd); +}; + + +/** + * Sends 'backtrace' request to v8. + */ +devtools.DebuggerAgent.prototype.requestBacktrace_ = function() { + var cmd = new devtools.DebugCommand('backtrace', { + 'compactFormat':true + }); + devtools.DebuggerAgent.sendCommand_(cmd); +}; + + +/** + * Sends command to v8 debugger. + * @param {devtools.DebugCommand} cmd Command to execute. + */ +devtools.DebuggerAgent.sendCommand_ = function(cmd) { + RemoteDebuggerCommandExecutor.DebuggerCommand(cmd.toJSONProtocol()); +}; + + +/** + * Tells the v8 debugger to make the next execution step. + * @param {string} action 'in', 'out' or 'next' action. + */ +devtools.DebuggerAgent.prototype.stepCommand_ = function(action) { + this.clearExceptionMessage_(); + var cmd = new devtools.DebugCommand('continue', { + 'stepaction': action, + 'stepcount': 1 + }); + devtools.DebuggerAgent.sendCommand_(cmd); +}; + + +/** + * Sends 'lookup' request to v8. + * @param {number} handle Handle to the object to lookup. + */ +devtools.DebuggerAgent.prototype.requestLookup_ = function(handles, callback) { + var cmd = new devtools.DebugCommand('lookup', { + 'compactFormat':true, + 'handles': handles + }); + devtools.DebuggerAgent.sendCommand_(cmd); + this.requestSeqToCallback_[cmd.getSequenceNumber()] = callback; +}; + + +/** + * Sets debugger context id for scripts filtering. + * @param {number} contextId Id of the inspected page global context. + */ +devtools.DebuggerAgent.prototype.setContextId_ = function(contextId) { + this.contextId_ = contextId; + + // If it's the first time context id is set request scripts list. + if (this.requestScriptsWhenContextIdSet_) { + this.requestScriptsWhenContextIdSet_ = false; + var cmd = new devtools.DebugCommand('scripts', { + 'includeSource': false + }); + devtools.DebuggerAgent.sendCommand_(cmd); + // Force v8 execution so that it gets to processing the requested command. + RemoteToolsAgent.ExecuteVoidJavaScript(); + + var debuggerAgent = this; + this.requestSeqToCallback_[cmd.getSequenceNumber()] = function(msg) { + // Handle the response iff the context id hasn't changed since the request + // was issued. Otherwise if the context id did change all up-to-date + // scripts will be pushed in after compile events and there is no need to + // handle the response. + if (contextId == debuggerAgent.contextId_) { + debuggerAgent.handleScriptsResponse_(msg); + } + }; + } +}; + + +/** + * 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.invokeCallbackForResponse_(msg); + } else if (msg.getCommand() == 'setbreakpoint') { + this.handleSetBreakpointResponse_(msg); + } else if (msg.getCommand() == 'clearbreakpoint') { + this.handleClearBreakpointResponse_(msg); + } else if (msg.getCommand() == 'backtrace') { + this.handleBacktraceResponse_(msg); + } else if (msg.getCommand() == 'lookup') { + this.invokeCallbackForResponse_(msg); + } else if (msg.getCommand() == 'evaluate') { + this.invokeCallbackForResponse_(msg); + } else if (msg.getCommand() == 'scope') { + this.invokeCallbackForResponse_(msg); + } + } +}; + + +/** + * @param {devtools.DebuggerMessage} msg + */ +devtools.DebuggerAgent.prototype.handleBreakEvent_ = function(msg) { + // Force scrips panel to be shown first. + WebInspector.currentPanel = WebInspector.panels.scripts; + + var body = msg.getBody(); + + var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(body.sourceLine); + this.requestBacktrace_(); +}; + + +/** + * @param {devtools.DebuggerMessage} msg + */ +devtools.DebuggerAgent.prototype.handleExceptionEvent_ = function(msg) { + // Force scrips panel to be shown first. + WebInspector.currentPanel = WebInspector.panels.scripts; + + var body = msg.getBody(); + if (this.pauseOnExceptions_) { + var body = msg.getBody(); + var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(body.sourceLine); + this.createExceptionMessage_(body.script.name, line, body.exception.text); + this.requestBacktrace_(); + } else { + this.resumeExecution(); + } +}; + + +/** + * @param {devtools.DebuggerMessage} msg + */ +devtools.DebuggerAgent.prototype.handleScriptsResponse_ = function(msg) { + var scripts = msg.getBody(); + for (var i = 0; i < scripts.length; i++) { + var script = scripts[i]; + + // Skip scripts from other tabs. + if (!this.isScriptFromInspectedContext_(script, msg)) { + continue; + } + + // We may already have received the info in an afterCompile event. + if (script.id in this.parsedScripts_) { + continue; + } + this.addScriptInfo_(script, msg); + } +}; + + +/** + * @param {Object} script Json object representing script. + * @param {devtools.DebuggerMessage} msg Debugger response. + */ +devtools.DebuggerAgent.prototype.isScriptFromInspectedContext_ = function( + script, msg) { + if (!script.context) { + // Always ignore scripts from the utility context. + return false; + } + var context = msg.lookup(script.context.ref); + var scriptContextId = context.data; + if (!goog.isDef(scriptContextId)) { + return false; // Always ignore scripts from the utility context. + } + if (this.contextId_ === null) { + return true; + } + return (scriptContextId.value == this.contextId_); +}; + + +/** + * @param {devtools.DebuggerMessage} msg + */ +devtools.DebuggerAgent.prototype.handleSetBreakpointResponse_ = function(msg) { + var requestSeq = msg.getRequestSeq(); + var breakpointInfo = this.requestNumberToBreakpointInfo_[requestSeq]; + if (!breakpointInfo) { + // TODO(yurys): handle this case + return; + } + delete this.requestNumberToBreakpointInfo_[requestSeq]; + if (!msg.isSuccess()) { + // TODO(yurys): handle this case + return; + } + var idInV8 = msg.getBody().breakpoint; + breakpointInfo.setV8Id(idInV8); + + if (breakpointInfo.isRemoved()) { + this.requestClearBreakpoint_(idInV8); + } +}; + + +/** + * @param {devtools.DebuggerMessage} msg + */ +devtools.DebuggerAgent.prototype.handleAfterCompileEvent_ = function(msg) { + if (!this.contextId_) { + // Ignore scripts delta if main request has not been issued yet. + return; + } + var script = msg.getBody().script; + + // Ignore scripts from other tabs. + if (!this.isScriptFromInspectedContext_(script, msg)) { + return; + } + this.addScriptInfo_(script, msg); +}; + + +/** + * Handles current profiler status. + * @param {number} modules List of active (started) modules. + */ +devtools.DebuggerAgent.prototype.didGetActiveProfilerModules_ = function( + modules) { + var profModules = devtools.DebuggerAgent.ProfilerModules; + var profModuleNone = profModules.PROFILER_MODULE_NONE; + if (modules != profModuleNone && + this.activeProfilerModules_ == profModuleNone) { + // Start to query log data. + RemoteDebuggerAgent.GetNextLogLines(); + } + this.activeProfilerModules_ = modules; + // Update buttons. + WebInspector.setRecordingProfile(modules & profModules.PROFILER_MODULE_CPU); + if (modules != profModuleNone) { + // Monitor profiler state. It can stop itself on buffer fill-up. + setTimeout( + function() { RemoteDebuggerAgent.GetActiveProfilerModules(); }, 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.activeProfilerModules_ == + devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_NONE) { + // 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. + * @param {devtools.DebuggerMessage} msg Debugger message containing the script + * data. + */ +devtools.DebuggerAgent.prototype.addScriptInfo_ = function(script, msg) { + var context = msg.lookup(script.context.ref); + var contextType = context.data.type; + this.parsedScripts_[script.id] = new devtools.ScriptInfo( + script.id, script.name, script.lineOffset, contextType); + if (WebInspector.panels.scripts.element.parentElement) { + // Only report script as parsed after scripts panel has been shown. + WebInspector.parsedScriptSource( + script.id, script.name, script.source, script.lineOffset); + } +}; + + +/** + * @param {devtools.DebuggerMessage} msg + */ +devtools.DebuggerAgent.prototype.handleClearBreakpointResponse_ = function( + msg) { + // Do nothing. +}; + + +/** + * Handles response to 'backtrace' command. + * @param {devtools.DebuggerMessage} msg + */ +devtools.DebuggerAgent.prototype.handleBacktraceResponse_ = function(msg) { + var frames = msg.getBody().frames; + this.callFrames_ = []; + for (var i = 0; i < frames.length; ++i) { + this.callFrames_.push(this.formatCallFrame_(frames[i])); + } + WebInspector.pausedScript(this.callFrames_); + this.showPendingExceptionMessage_(); + DevToolsHost.activateWindow(); +}; + + +/** + * Evaluates code on given callframe. + */ +devtools.DebuggerAgent.prototype.evaluateInCallFrame = function( + callFrameId, code, callback) { + var callFrame = this.callFrames_[callFrameId]; + callFrame.evaluate_(code, callback); +}; + + +/** + * Handles response to a command by invoking its callback (if any). + * @param {devtools.DebuggerMessage} msg + * @return {boolean} Whether a callback for the given message was found and + * excuted. + */ +devtools.DebuggerAgent.prototype.invokeCallbackForResponse_ = function(msg) { + var callback = this.requestSeqToCallback_[msg.getRequestSeq()]; + if (!callback) { + // It may happend if reset was called. + return false; + } + delete this.requestSeqToCallback_[msg.getRequestSeq()]; + callback(msg); + return true; +}; + + +/** + * @param {Object} stackFrame Frame json object from 'backtrace' response. + * @return {!devtools.CallFrame} Object containing information related to the + * call frame in the format expected by ScriptsPanel and its panes. + */ +devtools.DebuggerAgent.prototype.formatCallFrame_ = function(stackFrame) { + var func = stackFrame.func; + var sourceId = func.scriptId; + + // Add service script if it does not exist. + var existingScript = this.parsedScripts_[sourceId]; + if (!existingScript) { + this.parsedScripts_[sourceId] = new devtools.ScriptInfo( + sourceId, null /* name */, 0 /* line */, 'unknown' /* type */, + true /* unresolved */); + WebInspector.parsedScriptSource(sourceId, null, null, 0); + } + + var funcName = func.name || func.inferredName || '(anonymous function)'; + var line = devtools.DebuggerAgent.v8ToWwebkitLineNumber_(stackFrame.line); + + // Add basic scope chain info with scope variables. + var scopeChain = []; + var ScopeType = devtools.DebuggerAgent.ScopeType; + for (var i = 0; i < stackFrame.scopes.length; i++) { + var scope = stackFrame.scopes[i]; + scope.frameNumber = stackFrame.index; + var scopeObjectProxy = new WebInspector.ObjectProxy(scope, [], 0, '', true); + scopeObjectProxy.isScope = true; + scopeObjectProxy.properties = {}; // TODO(pfeldman): Fix autocomplete. + switch(scope.type) { + case ScopeType.Global: + scopeObjectProxy.isDocument = true; + break; + case ScopeType.Local: + scopeObjectProxy.isLocal = true; + scopeObjectProxy.thisObject = + devtools.DebuggerAgent.formatObjectProxy_(stackFrame.receiver); + break; + case ScopeType.With: + // Catch scope is treated as a regular with scope by WebKit so we + // also treat it this way. + case ScopeType.Catch: + scopeObjectProxy.isWithBlock = true; + break; + case ScopeType.Closure: + scopeObjectProxy.isClosure = true; + break; + } + scopeChain.push(scopeObjectProxy); + } + return new devtools.CallFrame(stackFrame.index, 'function', funcName, + sourceId, line, scopeChain); +}; + + +/** + * Collects properties for an object from the debugger response. + * @param {Object} object An object from the debugger protocol response. + * @param {Array.<WebInspector.ObjectPropertyProxy>} result An array to put the + * properties into. + * @param {boolean} noIntrinsic Whether intrinsic properties should be + * included. + */ +devtools.DebuggerAgent.formatObjectProperties_ = function(object, result, + noIntrinsic) { + devtools.DebuggerAgent.propertiesToProxies_(object.properties, result); + if (noIntrinsic) { + return; + } + + result.push(new WebInspector.ObjectPropertyProxy('__proto__', + devtools.DebuggerAgent.formatObjectProxy_(object.protoObject))); + result.push(new WebInspector.ObjectPropertyProxy('prototype', + devtools.DebuggerAgent.formatObjectProxy_(object.prototypeObject))); + result.push(new WebInspector.ObjectPropertyProxy('constructor', + devtools.DebuggerAgent.formatObjectProxy_(object.constructorFunction))); +}; + + +/** + * For each property in 'properties' creates its proxy representative. + * @param {Array.<Object>} properties Receiver properties or locals array from + * 'backtrace' response. + * @param {Array.<WebInspector.ObjectPropertyProxy>} Results holder. + */ +devtools.DebuggerAgent.propertiesToProxies_ = function(properties, result) { + var map = {}; + for (var i = 0; i < properties.length; ++i) { + var property = properties[i]; + var name = String(property.name); + if (name in map) { + continue; + } + map[name] = true; + var value = devtools.DebuggerAgent.formatObjectProxy_(property.value); + var propertyProxy = new WebInspector.ObjectPropertyProxy(name, value); + result.push(propertyProxy); + } +}; + + +/** + * @param {Object} v An object reference from the debugger response. + * @return {*} The value representation expected by ScriptsPanel. + */ +devtools.DebuggerAgent.formatObjectProxy_ = function(v) { + var description; + var hasChildren = false; + if (v.type == 'object') { + description = v.className; + hasChildren = true; + } else if (v.type == 'function') { + if (v.source) { + description = v.source; + } else { + description = 'function ' + v.name + '()'; + } + hasChildren = true; + } else if (goog.isDef(v.value)) { + description = v.value; + } else if (v.type == 'undefined') { + description = 'undefined'; + } else if (v.type == 'null') { + description = 'null'; + } else { + description = '<unresolved ref: ' + v.ref + ', type: ' + v.type + '>'; + } + var proxy = new WebInspector.ObjectProxy(v, [], 0, description, hasChildren); + proxy.type = v.type; + proxy.isV8Ref = true; + return proxy; +}; + + +/** + * Converts line number from Web Inspector UI(1-based) to v8(0-based). + * @param {number} line Resource line number in Web Inspector UI. + * @return {number} The line number in v8. + */ +devtools.DebuggerAgent.webkitToV8LineNumber_ = function(line) { + return line - 1; +}; + + +/** + * Converts line number from v8(0-based) to Web Inspector UI(1-based). + * @param {number} line Resource line number in v8. + * @return {number} The line number in Web Inspector. + */ +devtools.DebuggerAgent.v8ToWwebkitLineNumber_ = function(line) { + return line + 1; +}; + + +/** + * @param {number} scriptId Id of the script. + * @param {?string} url Script resource URL if any. + * @param {number} lineOffset First line 0-based offset in the containing + * document. + * @param {string} contextType Type of the script's context: + * "page" - regular script from html page + * "injected" - extension content script + * @param {bool} opt_isUnresolved If true, script will not be resolved. + * @constructor + */ +devtools.ScriptInfo = function( + scriptId, url, lineOffset, contextType, opt_isUnresolved) { + this.scriptId_ = scriptId; + this.lineOffset_ = lineOffset; + this.contextType_ = contextType; + this.url_ = url; + this.isUnresolved_ = opt_isUnresolved; + + this.lineToBreakpointInfo_ = {}; +}; + + +/** + * @return {number} + */ +devtools.ScriptInfo.prototype.getLineOffset = function() { + return this.lineOffset_; +}; + + +/** + * @return {string} + */ +devtools.ScriptInfo.prototype.getContextType = function() { + return this.contextType_; +}; + + +/** + * @return {?string} + */ +devtools.ScriptInfo.prototype.getUrl = function() { + return this.url_; +}; + + +/** + * @return {?bool} + */ +devtools.ScriptInfo.prototype.isUnresolved = function() { + return this.isUnresolved_; +}; + + +/** + * @param {number} line 0-based line number in the script. + * @return {?devtools.BreakpointInfo} Information on a breakpoint at the + * specified line in the script or undefined if there is no breakpoint at + * that line. + */ +devtools.ScriptInfo.prototype.getBreakpointInfo = function(line) { + return this.lineToBreakpointInfo_[line]; +}; + + +/** + * Adds breakpoint info to the script. + * @param {devtools.BreakpointInfo} breakpoint + */ +devtools.ScriptInfo.prototype.addBreakpointInfo = function(breakpoint) { + this.lineToBreakpointInfo_[breakpoint.getLine()] = breakpoint; +}; + + +/** + * @param {devtools.BreakpointInfo} breakpoint Breakpoint info to be removed. + */ +devtools.ScriptInfo.prototype.removeBreakpointInfo = function(breakpoint) { + var line = breakpoint.getLine(); + delete this.lineToBreakpointInfo_[line]; +}; + + + +/** + * @param {number} line Breakpoint 0-based line number in the containing script. + * @constructor + */ +devtools.BreakpointInfo = function(line) { + this.line_ = line; + this.v8id_ = -1; + this.removed_ = false; +}; + + +/** + * @return {number} + */ +devtools.BreakpointInfo.prototype.getLine = function(n) { + return this.line_; +}; + + +/** + * @return {number} Unique identifier of this breakpoint in the v8 debugger. + */ +devtools.BreakpointInfo.prototype.getV8Id = function(n) { + return this.v8id_; +}; + + +/** + * Sets id of this breakpoint in the v8 debugger. + * @param {number} id + */ +devtools.BreakpointInfo.prototype.setV8Id = function(id) { + this.v8id_ = id; +}; + + +/** + * Marks this breakpoint as removed from the front-end. + */ +devtools.BreakpointInfo.prototype.markAsRemoved = function() { + this.removed_ = true; +}; + + +/** + * @return {boolean} Whether this breakpoint has been removed from the + * front-end. + */ +devtools.BreakpointInfo.prototype.isRemoved = function() { + return this.removed_; +}; + + +/** + * Call stack frame data. + * @param {string} id CallFrame id. + * @param {string} type CallFrame type. + * @param {string} functionName CallFrame type. + * @param {string} sourceID Source id. + * @param {number} line Source line. + * @param {Array.<Object>} scopeChain Array of scoped objects. + * @construnctor + */ +devtools.CallFrame = function(id, type, functionName, sourceID, line, + scopeChain) { + this.id = id; + this.type = type; + this.functionName = functionName; + this.sourceID = sourceID; + this.line = line; + this.scopeChain = scopeChain; +}; + + +/** + * This method issues asynchronous evaluate request, reports result to the + * callback. + * @param {string} expression An expression to be evaluated in the context of + * this call frame. + * @param {function(Object):undefined} callback Callback to report result to. + */ +devtools.CallFrame.prototype.evaluate_ = function(expression, callback) { + devtools.tools.getDebuggerAgent().requestEvaluate({ + 'expression': expression, + 'frame': this.id, + 'global': false, + 'disable_break': false, + 'compactFormat': true + }, + function(response) { + var result = {}; + if (response.isSuccess()) { + result.value = devtools.DebuggerAgent.formatObjectProxy_( + response.getBody()); + } else { + result.value = response.getMessage(); + result.isException = true; + } + callback(result); + }); +}; + + +/** + * JSON based commands sent to v8 debugger. + * @param {string} command Name of the command to execute. + * @param {Object} opt_arguments Command-specific arguments map. + * @constructor + */ +devtools.DebugCommand = function(command, opt_arguments) { + this.command_ = command; + this.type_ = 'request'; + this.seq_ = ++devtools.DebugCommand.nextSeq_; + if (opt_arguments) { + this.arguments_ = opt_arguments; + } +}; + + +/** + * Next unique number to be used as debugger request sequence number. + * @type {number} + */ +devtools.DebugCommand.nextSeq_ = 1; + + +/** + * @return {number} + */ +devtools.DebugCommand.prototype.getSequenceNumber = function() { + return this.seq_; +}; + + +/** + * @return {string} + */ +devtools.DebugCommand.prototype.toJSONProtocol = function() { + var json = { + 'seq': this.seq_, + 'type': this.type_, + 'command': this.command_ + } + if (this.arguments_) { + json.arguments = this.arguments_; + } + return JSON.stringify(json); +}; + + +/** + * JSON messages sent from v8 debugger. See protocol definition for more + * details: http://code.google.com/p/v8/wiki/DebuggerProtocol + * @param {string} msg Raw protocol packet as JSON string. + * @constructor + */ +devtools.DebuggerMessage = function(msg) { + this.packet_ = JSON.parse(msg); + this.refs_ = []; + if (this.packet_.refs) { + for (var i = 0; i < this.packet_.refs.length; i++) { + this.refs_[this.packet_.refs[i].handle] = this.packet_.refs[i]; + } + } +}; + + +/** + * @return {string} The packet type. + */ +devtools.DebuggerMessage.prototype.getType = function() { + return this.packet_.type; +}; + + +/** + * @return {?string} The packet event if the message is an event. + */ +devtools.DebuggerMessage.prototype.getEvent = function() { + return this.packet_.event; +}; + + +/** + * @return {?string} The packet command if the message is a response to a + * command. + */ +devtools.DebuggerMessage.prototype.getCommand = function() { + return this.packet_.command; +}; + + +/** + * @return {number} The packet request sequence. + */ +devtools.DebuggerMessage.prototype.getRequestSeq = function() { + return this.packet_.request_seq; +}; + + +/** + * @return {number} Whether the v8 is running after processing the request. + */ +devtools.DebuggerMessage.prototype.isRunning = function() { + return this.packet_.running ? true : false; +}; + + +/** + * @return {boolean} Whether the request succeeded. + */ +devtools.DebuggerMessage.prototype.isSuccess = function() { + return this.packet_.success ? true : false; +}; + + +/** + * @return {string} + */ +devtools.DebuggerMessage.prototype.getMessage = function() { + return this.packet_.message; +}; + + +/** + * @return {Object} Parsed message body json. + */ +devtools.DebuggerMessage.prototype.getBody = function() { + return this.packet_.body; +}; + + +/** + * @param {number} handle Object handle. + * @return {?Object} Returns the object with the handle if it was sent in this + * message(some objects referenced by handles may be missing in the message). + */ +devtools.DebuggerMessage.prototype.lookup = function(handle) { + return this.refs_[handle]; +}; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/devtools.css b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/devtools.css new file mode 100644 index 0000000..eb649c5 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/devtools.css @@ -0,0 +1,99 @@ +#scripts-files option.injected { + color: rgb(70, 134, 240); +} + +.data-grid table { + line-height: 120%; +} + +body.attached #toolbar { + height: 34px; + border-top: 1px solid rgb(100, 100, 100); + cursor: default; /* overriden */ + padding-left: 0; +} + + +/* Chrome theme overrides */ +#toolbar { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(242, 247, 253)), to(rgb(223, 234, 248))); +} + + +/* Heap Profiler Styles */ + +#heap-snapshot-views { + position: absolute; + top: 0; + right: 0; + left: 200px; + bottom: 0; +} + +#heap-snapshot-status-bar-items { + position: absolute; + top: 0; + bottom: 0; + left: 200px; + overflow: hidden; + border-left: 1px solid rgb(184, 184, 184); + margin-left: -1px; +} + +.heap-snapshot-status-bar-item .glyph { + -webkit-mask-image: url(Images/focusButtonGlyph.png); +} + +.heap-snapshot-sidebar-tree-item .icon { + content: url(Images/profileIcon.png); +} + +.heap-snapshot-sidebar-tree-item.small .icon { + content: url(Images/profileSmallIcon.png); +} + +.heap-snapshot-view { + display: none; + overflow: hidden; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +.heap-snapshot-view.visible { + display: block; +} + +.heap-snapshot-view .data-grid { + border: none; + max-height: 100%; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 93px; +} + +#heap-snapshot-summary { + position: absolute; + padding-top: 20px; + bottom: 0; + left: 0; + right: 0; + height: 93px; + margin-left: -1px; + border-left: 1px solid rgb(102, 102, 102); + background-color: rgb(101, 111, 130); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0))); + background-repeat: repeat-x; + background-position: top; + text-align: center; + text-shadow: black 0 1px 1px; + white-space: nowrap; + color: white; + -webkit-background-size: 1px 6px; + -webkit-background-origin: padding; + -webkit-background-clip: padding; +} diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/devtools.html b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/devtools.html new file mode 100644 index 0000000..398bbed --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/devtools.html @@ -0,0 +1,142 @@ +<!-- +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"> + <link rel="stylesheet" type="text/css" href="devtools.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="inspector_controller.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="logreader.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="KeyboardShortcut.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="ChangesView.js"></script> + <script type="text/javascript" src="ConsoleView.js"></script> + <script type="text/javascript" src="Drawer.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="Callback.js"></script> + <script type="text/javascript" src="DOMAgent.js"></script> + <script type="text/javascript" src="TimelineAgent.js"></script> + <script type="text/javascript" src="InjectedScriptAccess.js"></script> + <script type="text/javascript" src="inspector_controller_impl.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="ObjectProxy.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="WatchExpressionsSidebarPane.js"></script> + <script type="text/javascript" src="MetricsSidebarPane.js"></script> + <script type="text/javascript" src="PropertiesSidebarPane.js"></script> + <script type="text/javascript" src="Color.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="StatusBarButton.js"></script> + <script type="text/javascript" src="SummaryBar.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="Popup.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="heap_profiler_panel.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 hidden"></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 class="toolbar-item close"><button id="close-button"></button></div> + </div> + <div id="main"> + <div id="main-panels" tabindex="0" spellcheck="false"></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"><div class="glyph"></div><div class="glyph shadow"></div></button><button id="console-status-bar-item" class="status-bar-item"><div class="glyph"></div><div class="glyph shadow"></div></button><button id="changes-status-bar-item" class="status-bar-item hidden"></button><div id="count-items"><div id="changes-count" class="hidden"></div><div id="error-warning-count" class="hidden"></div></div></div></div> + </div> + <div id="drawer"> + <div id="console-view"><div id="console-messages"><div id="console-prompt" spellcheck="false"><br></div></div></div> + <div id="drawer-status-bar" class="status-bar"><div id="other-drawer-status-bar-items"><button id="clear-console-status-bar-item" class="status-bar-item"><div class="glyph"></div><div class="glyph shadow"></div></button><div id="console-filter" class="status-bar-item"></div></div></div> + </div> +</body> +</html> diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/devtools.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/devtools.js new file mode 100644 index 0000000..5086f80 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/devtools.js @@ -0,0 +1,392 @@ +// 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'); + + +/** + * Dispatches raw message from the host. + * @param {string} remoteName + * @prama {string} methodName + * @param {string} param1, param2, param3 Arguments to dispatch. + */ +devtools$$dispatch = function(remoteName, methodName, param1, param2, param3) { + remoteName = 'Remote' + remoteName.substring(0, remoteName.length - 8); + var agent = window[remoteName]; + if (!agent) { + debugPrint('No remote agent "' + remoteName + '" found.'); + return; + } + var method = agent[methodName]; + if (!method) { + debugPrint('No method "' + remoteName + '.' + methodName + '" found.'); + return; + } + method.call(this, param1, param2, param3); +}; + + +devtools.ToolsAgent = function() { + RemoteToolsAgent.DidExecuteUtilityFunction = + devtools.Callback.processCallback; + RemoteToolsAgent.FrameNavigate = + goog.bind(this.frameNavigate_, this); + RemoteToolsAgent.DispatchOnClient = + goog.bind(this.dispatchOnClient_, this); + this.debuggerAgent_ = new devtools.DebuggerAgent(); +}; + + +/** + * Resets tools agent to its initial state. + */ +devtools.ToolsAgent.prototype.reset = function() { + DevToolsHost.reset(); + this.debuggerAgent_.reset(); +}; + + +/** + * @param {string} script Script exression to be evaluated in the context of the + * inspected page. + * @param {function(Object|string, boolean):undefined} opt_callback Function to + * call with the result. + */ +devtools.ToolsAgent.prototype.evaluateJavaScript = function(script, + opt_callback) { + InspectorController.evaluate(script, opt_callback || function() {}); +}; + + +/** + * @return {devtools.DebuggerAgent} Debugger agent instance. + */ +devtools.ToolsAgent.prototype.getDebuggerAgent = function() { + return this.debuggerAgent_; +}; + + +/** + * @param {string} url Url frame navigated to. + * @see tools_agent.h + * @private + */ +devtools.ToolsAgent.prototype.frameNavigate_ = function(url) { + this.reset(); + // Do not reset Profiles panel. + var profiles = null; + if ('profiles' in WebInspector.panels) { + profiles = WebInspector.panels['profiles']; + delete WebInspector.panels['profiles']; + } + WebInspector.reset(); + if (profiles != null) { + WebInspector.panels['profiles'] = profiles; + } +}; + + +/** + * @param {string} message Serialized call to be dispatched on WebInspector. + * @private + */ +devtools.ToolsAgent.prototype.dispatchOnClient_ = function(message) { + WebInspector.dispatch.apply(WebInspector, JSON.parse(message)); +}; + + +/** + * Evaluates js expression. + * @param {string} expr + */ +devtools.ToolsAgent.prototype.evaluate = function(expr) { + RemoteToolsAgent.evaluate(expr); +}; + + +/** + * Enables / disables resources panel in the ui. + * @param {boolean} enabled New panel status. + */ +WebInspector.setResourcesPanelEnabled = function(enabled) { + InspectorController.resourceTrackingEnabled_ = enabled; + WebInspector.panels.resources.reset(); +}; + + +/** + * Prints string to the inspector console or shows alert if the console doesn't + * exist. + * @param {string} text + */ +function debugPrint(text) { + var console = WebInspector.console; + if (console) { + console.addMessage(new WebInspector.ConsoleMessage( + WebInspector.ConsoleMessage.MessageSource.JS, + WebInspector.ConsoleMessage.MessageType.Log, + WebInspector.ConsoleMessage.MessageLevel.Log, + 1, 'chrome://devtools/<internal>', undefined, -1, text)); + } else { + alert(text); + } +} + + +/** + * Global instance of the tools agent. + * @type {devtools.ToolsAgent} + */ +devtools.tools = null; + + +var context = {}; // Used by WebCore's inspector routines. + +/////////////////////////////////////////////////////////////////////////////// +// Here and below are overrides to existing WebInspector methods only. +// TODO(pfeldman): Patch WebCore and upstream changes. +var oldLoaded = WebInspector.loaded; +WebInspector.loaded = function() { + devtools.tools = new devtools.ToolsAgent(); + devtools.tools.reset(); + + Preferences.ignoreWhitespace = false; + Preferences.samplingCPUProfiler = true; + oldLoaded.call(this); + + // Hide dock button on Mac OS. + // TODO(pfeldman): remove once Mac OS docking is implemented. + if (InspectorController.platform().indexOf('mac') == 0) { + document.getElementById('dock-status-bar-item').addStyleClass('hidden'); + } + + // Mute refresh action. + document.addEventListener("keydown", function(event) { + if (event.keyIdentifier == 'F5') { + event.preventDefault(); + } else if (event.keyIdentifier == 'U+0052' /* 'R' */ && + (event.ctrlKey || event.metaKey)) { + event.preventDefault(); + } + }, true); + + DevToolsHost.loaded(); +}; + + +/** + * This override is necessary for adding script source asynchronously. + * @override + */ +WebInspector.ScriptView.prototype.setupSourceFrameIfNeeded = function() { + if (!this._frameNeedsSetup) { + return; + } + + this.attach(); + + if (this.script.source) { + this.didResolveScriptSource_(); + } else { + var self = this; + devtools.tools.getDebuggerAgent().resolveScriptSource( + this.script.sourceID, + function(source) { + self.script.source = source || + WebInspector.UIString('<source is not available>'); + self.didResolveScriptSource_(); + }); + } +}; + + +/** + * Performs source frame setup when script source is aready resolved. + */ +WebInspector.ScriptView.prototype.didResolveScriptSource_ = function() { + 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(); +}; + + +/** + * @param {string} type Type of the the property value('object' or 'function'). + * @param {string} className Class name of the property value. + * @constructor + */ +WebInspector.UnresolvedPropertyValue = function(type, className) { + this.type = type; + this.className = className; +}; + + +/** + * 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_); + + +(function() { + var oldShow = WebInspector.ScriptsPanel.prototype.show; + WebInspector.ScriptsPanel.prototype.show = function() { + devtools.tools.getDebuggerAgent().initUI(); + this.enableToggleButton.visible = false; + oldShow.call(this); + }; +})(); + + +(function InterceptProfilesPanelEvents() { + var oldShow = WebInspector.ProfilesPanel.prototype.show; + WebInspector.ProfilesPanel.prototype.show = function() { + devtools.tools.getDebuggerAgent().initializeProfiling(); + this.enableToggleButton.visible = false; + oldShow.call(this); + // Show is called on every show event of a panel, so + // we only need to intercept it once. + WebInspector.ProfilesPanel.prototype.show = oldShow; + }; +})(); + + +/* + * @override + * TODO(mnaganov): Restore l10n when it will be agreed that it is needed. + */ +WebInspector.UIString = function(string) { + return String.vsprintf(string, Array.prototype.slice.call(arguments, 1)); +}; + + +// There is no clear way of setting frame title yet. So sniffing main resource +// load. +(function OverrideUpdateResource() { + var originalUpdateResource = WebInspector.updateResource; + WebInspector.updateResource = function(identifier, payload) { + originalUpdateResource.call(this, identifier, payload); + var resource = this.resources[identifier]; + if (resource && resource.mainResource && resource.finished) { + document.title = + WebInspector.UIString('Developer Tools - %s', resource.url); + } + }; +})(); + + +// Highlight extension content scripts in the scripts list. +(function () { + var original = WebInspector.ScriptsPanel.prototype._addScriptToFilesMenu; + WebInspector.ScriptsPanel.prototype._addScriptToFilesMenu = function(script) { + var result = original.apply(this, arguments); + var debuggerAgent = devtools.tools.getDebuggerAgent(); + var type = debuggerAgent.getScriptContextType(script.sourceID); + var option = script.filesSelectOption; + if (type == 'injected' && option) { + option.addStyleClass('injected'); + } + return result; + }; +})(); + + +/** Pending WebKit upstream by apavlov). Fixes iframe vs drag problem. */ +(function() { + var originalDragStart = WebInspector.elementDragStart; + WebInspector.elementDragStart = function(element) { + var glassPane = document.createElement("div"); + glassPane.style.cssText = + 'position:absolute;width:100%;height:100%;opacity:0;z-index:1'; + glassPane.id = 'glass-pane-for-drag'; + element.parentElement.appendChild(glassPane); + + originalDragStart.apply(this, arguments); + }; + + var originalDragEnd = WebInspector.elementDragEnd; + WebInspector.elementDragEnd = function() { + originalDragEnd.apply(this, arguments); + + var glassPane = document.getElementById('glass-pane-for-drag'); + glassPane.parentElement.removeChild(glassPane); + }; +})(); + + +(function() { + var originalCreatePanels = WebInspector._createPanels; + WebInspector._createPanels = function() { + originalCreatePanels.apply(this, arguments); + this.panels.heap = new WebInspector.HeapProfilerPanel(); + }; +})(); + + +(function () { +var orig = InjectedScriptAccess.getProperties; +InjectedScriptAccess.getProperties = function( + objectProxy, ignoreHasOwnProperty, callback) { + if (objectProxy.isScope) { + devtools.tools.getDebuggerAgent().resolveScope(objectProxy.objectId, + callback); + } else if (objectProxy.isV8Ref) { + devtools.tools.getDebuggerAgent().resolveChildren(objectProxy.objectId, + callback, true); + } else { + orig.apply(this, arguments); + } +}; +})() + + +WebInspector.resourceTrackingWasEnabled = function() +{ + InspectorController.resourceTrackingEnabled_ = true; + this.panels.resources.resourceTrackingWasEnabled(); +}; + +WebInspector.resourceTrackingWasDisabled = function() +{ + InspectorController.resourceTrackingEnabled_ = false; + this.panels.resources.resourceTrackingWasDisabled(); +}; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/devtools_callback.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/devtools_callback.js new file mode 100644 index 0000000..f252861 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/devtools_host_stub.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/devtools_host_stub.js new file mode 100644 index 0000000..2f3da60 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/devtools_host_stub.js @@ -0,0 +1,335 @@ +// 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.activeProfilerModules_ = + devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_NONE; + this.profileLogPos_ = 0; + this.heapProfSample_ = 0; + this.heapProfLog_ = ''; +}; + + +RemoteDebuggerAgentStub.prototype.DebugBreak = function() { +}; + + +RemoteDebuggerAgentStub.prototype.GetContextId = function() { + RemoteDebuggerAgent.SetContextId(3); +}; + + +RemoteDebuggerAgentStub.prototype.StopProfiling = function(modules) { + this.activeProfilerModules_ &= ~modules; +}; + + +RemoteDebuggerAgentStub.prototype.StartProfiling = function(modules) { + var profModules = devtools.DebuggerAgent.ProfilerModules; + if (modules & profModules.PROFILER_MODULE_HEAP_SNAPSHOT) { + if (modules & profModules.PROFILER_MODULE_HEAP_STATS) { + this.heapProfLog_ += + 'heap-sample-begin,"Heap","allocated",' + + (new Date()).getTime() + '\n' + + 'heap-sample-stats,"Heap","allocated",10000,1000\n'; + this.heapProfLog_ += + 'heap-sample-item,STRING_TYPE,100,1000\n' + + 'heap-sample-item,CODE_TYPE,10,200\n' + + 'heap-sample-item,MAP_TYPE,20,350\n'; + var sample = RemoteDebuggerAgentStub.HeapSamples[this.heapProfSample_]; + if (++this.heapProfSample_ == RemoteDebuggerAgentStub.HeapSamples.length) + this.heapProfSample_ = 0; + for (var obj in sample) { + this.heapProfLog_ += + 'heap-js-cons-item,"' + obj + '",' + sample[obj][0] + + ',' + sample[obj][1] + '\n'; + } + this.heapProfLog_ += + 'heap-sample-end,"Heap","allocated"\n'; + } + } else { + this.activeProfilerModules_ |= modules; + } +}; + + +RemoteDebuggerAgentStub.prototype.GetActiveProfilerModules = function() { + var self = this; + setTimeout(function() { + RemoteDebuggerAgent.DidGetActiveProfilerModules( + self.activeProfilerModules_); + }, 100); +}; + + +RemoteDebuggerAgentStub.prototype.GetNextLogLines = function() { + var profModules = devtools.DebuggerAgent.ProfilerModules; + var logLines = ''; + if (this.activeProfilerModules_ & profModules.PROFILER_MODULE_CPU) { + if (this.profileLogPos_ < RemoteDebuggerAgentStub.ProfilerLogBuffer.length) { + this.profileLogPos_ += RemoteDebuggerAgentStub.ProfilerLogBuffer.length; + logLines += RemoteDebuggerAgentStub.ProfilerLogBuffer; + } + } + if (this.heapProfLog_) { + logLines += this.heapProfLog_; + this.heapProfLog_ = ''; + } + setTimeout(function() { + RemoteDebuggerAgent.DidGetNextLogLines(logLines); + }, 100); +}; + + +/** + * @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, 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 + '(' + args + ')'); + } else if (functionName == 'evaluate') { + try { + result = [ window.eval(JSON.parse(args)[0]), false ]; + } catch (e) { + result = [ e.toString(), true ]; + } + } else if (functionName == 'InspectorController' || + functionName == 'InjectedScript') { + // do nothing; + } else { + alert('Unexpected utility function:' + functionName); + } + RemoteToolsAgent.DidExecuteUtilityFunction(callId, + JSON.stringify(result), ''); + }, 0); +}; + + +RemoteToolsAgentStub.prototype.ExecuteVoidJavaScript = 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'; + + +RemoteDebuggerAgentStub.HeapSamples = [ + {foo: [1, 100], bar: [20, 2000]}, + {foo: [2000, 200000], bar: [10, 1000]}, + {foo: [15, 1500], bar: [15, 1500]}, + {bar: [20, 2000]}, + {foo: [15, 1500], bar: [15, 1500]}, + {bar: [20, 2000], baz: [15, 1500]} +]; + + +/** + * @constructor + */ +RemoteDebuggerCommandExecutorStub = function() { +}; + + +RemoteDebuggerCommandExecutorStub.prototype.DebuggerCommand = function(cmd) { + if ('{"seq":2,"type":"request","command":"scripts","arguments":{"' + + 'includeSource":false}}' == cmd) { + var response1 = + '{"seq":5,"request_seq":2,"type":"response","command":"scripts","' + + 'success":true,"body":[{"handle":61,"type":"script","name":"' + + 'http://www/~test/t.js","id":59,"lineOffset":0,"columnOffset":0,' + + '"lineCount":1,"sourceStart":"function fib(n) {","sourceLength":300,' + + '"scriptType":2,"compilationType":0,"context":{"ref":60}}],"refs":[{' + + '"handle":60,"type":"context","data":{"type":"page","value":3}}],' + + '"running":false}'; + this.sendResponse_(response1); + } else if ('{"seq":3,"type":"request","command":"scripts","arguments":{' + + '"ids":[59],"includeSource":true}}' == cmd) { + this.sendResponse_( + '{"seq":8,"request_seq":3,"type":"response","command":"scripts",' + + '"success":true,"body":[{"handle":1,"type":"script","name":' + + '"http://www/~test/t.js","id":59,"lineOffset":0,"columnOffset":0,' + + '"lineCount":1,"source":"function fib(n) {return n+1;}",' + + '"sourceLength":244,"scriptType":2,"compilationType":0,"context":{' + + '"ref":0}}],"refs":[{"handle":0,"type":"context","data":{"type":' + + '"page","value":3}}],"running":false}'); + } else { + debugPrint('Unexpected command: ' + cmd); + } +}; + + +RemoteDebuggerCommandExecutorStub.prototype.sendResponse_ = function(response) { + setTimeout(function() { + RemoteDebuggerAgent.DebuggerOutput(response); + }, 0); +}; + + +/** + * @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() { + addDummyResource(); + uiTests.runAllTests(); +}; + + +DevToolsHostStub.prototype.reset = function() { +}; + + +DevToolsHostStub.prototype.getPlatform = function() { + return "windows"; +}; + + +DevToolsHostStub.prototype.addResourceSourceToFrame = function( + identifier, mimeType, element) { +}; + + +DevToolsHostStub.prototype.addSourceToFrame = function(mimeType, source, + element) { +}; + + +DevToolsHostStub.prototype.getApplicationLocale = function() { + return "en-US"; +}; + + +if (!window['DevToolsHost']) { + window['RemoteDebuggerAgent'] = new RemoteDebuggerAgentStub(); + window['RemoteDebuggerCommandExecutor'] = + new RemoteDebuggerCommandExecutorStub(); + window['RemoteToolsAgent'] = new RemoteToolsAgentStub(); + window['DevToolsHost'] = new DevToolsHostStub(); +} diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/heap_profiler_panel.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/heap_profiler_panel.js new file mode 100644 index 0000000..eb1dffa --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/heap_profiler_panel.js @@ -0,0 +1,680 @@ +// 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 Heap profiler panel implementation. + */ + +WebInspector.HeapProfilerPanel = function() { + WebInspector.Panel.call(this); + + this.element.addStyleClass("heap-profiler"); + + this.sidebarElement = document.createElement("div"); + this.sidebarElement.id = "heap-snapshot-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.snapshotViews = document.createElement("div"); + this.snapshotViews.id = "heap-snapshot-views"; + this.element.appendChild(this.snapshotViews); + + this.snapshotButton = new WebInspector.StatusBarButton(WebInspector.UIString("Take heap snapshot."), "heap-snapshot-status-bar-item"); + this.snapshotButton.addEventListener("click", this._snapshotClicked.bind(this), false); + + this.snapshotViewStatusBarItemsContainer = document.createElement("div"); + this.snapshotViewStatusBarItemsContainer.id = "heap-snapshot-status-bar-items"; + + this.reset(); +}; + +WebInspector.HeapProfilerPanel.prototype = { + toolbarItemClass: "heap-profiler", + + get toolbarItemLabel() { + return WebInspector.UIString("Heap"); + }, + + get statusBarItems() { + return [this.snapshotButton.element, this.snapshotViewStatusBarItemsContainer]; + }, + + show: function() { + WebInspector.Panel.prototype.show.call(this); + this._updateSidebarWidth(); + }, + + reset: function() { + if (this._snapshots) { + var snapshotsLength = this._snapshots.length; + for (var i = 0; i < snapshotsLength; ++i) { + var snapshot = this._snapshots[i]; + delete snapshot._snapshotView; + } + } + + this._snapshots = []; + + this.sidebarTreeElement.removeStyleClass("some-expandable"); + + this.sidebarTree.removeChildren(); + this.snapshotViews.removeChildren(); + + this.snapshotViewStatusBarItemsContainer.removeChildren(); + }, + + handleKeyEvent: function(event) { + this.sidebarTree.handleKeyEvent(event); + }, + + addSnapshot: function(snapshot) { + this._snapshots.push(snapshot); + snapshot.list = this._snapshots; + snapshot.listIndex = this._snapshots.length - 1; + + var snapshotsTreeElement = new WebInspector.HeapSnapshotSidebarTreeElement(snapshot); + snapshotsTreeElement.small = false; + snapshot._snapshotsTreeElement = snapshotsTreeElement; + + this.sidebarTree.appendChild(snapshotsTreeElement); + + this.dispatchEventToListeners("snapshot added"); + }, + + showSnapshot: function(snapshot) { + if (!snapshot) + return; + + if (this.visibleView) + this.visibleView.hide(); + var view = this.snapshotViewForSnapshot(snapshot); + view.show(this.snapshotViews); + this.visibleView = view; + + this.snapshotViewStatusBarItemsContainer.removeChildren(); + var statusBarItems = view.statusBarItems; + for (var i = 0; i < statusBarItems.length; ++i) + this.snapshotViewStatusBarItemsContainer.appendChild(statusBarItems[i]); + }, + + showView: function(view) + { + this.showSnapshot(view.snapshot); + }, + + snapshotViewForSnapshot: function(snapshot) + { + if (!snapshot) + return null; + if (!snapshot._snapshotView) + snapshot._snapshotView = new WebInspector.HeapSnapshotView(this, snapshot); + return snapshot._snapshotView; + }, + + closeVisibleView: function() + { + if (this.visibleView) + this.visibleView.hide(); + delete this.visibleView; + }, + + _snapshotClicked: function() { + devtools.tools.getDebuggerAgent().startProfiling( + devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_HEAP_SNAPSHOT | + devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_HEAP_STATS | + devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_JS_CONSTRUCTORS); + }, + + _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.snapshotViews.style.left = width + "px"; + this.snapshotViewStatusBarItemsContainer.style.left = width + "px"; + this.sidebarResizeElement.style.left = (width - 3) + "px"; + } +}; + +WebInspector.HeapProfilerPanel.prototype.__proto__ = WebInspector.Panel.prototype; + +WebInspector.HeapSnapshotView = function(parent, snapshot) +{ + WebInspector.View.call(this); + + this.element.addStyleClass("heap-snapshot-view"); + + this.parent = parent; + this.parent.addEventListener("snapshot added", this._updateBaseOptions, this); + + this.showCountAsPercent = true; + this.showSizeAsPercent = true; + this.showCountDeltaAsPercent = true; + this.showSizeDeltaAsPercent = true; + + this.summaryBar = new WebInspector.SummaryBar(this.categories); + this.summaryBar.element.id = "heap-snapshot-summary"; + this.summaryBar.calculator = new WebInspector.HeapSummaryCalculator(snapshot.used); + this.element.appendChild(this.summaryBar.element); + + var columns = { "cons": { title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true }, + "count": { title: WebInspector.UIString("Count"), width: "54px", sortable: true }, + "size": { title: WebInspector.UIString("Size"), width: "72px", sort: "descending", sortable: true }, + "countDelta": { title: WebInspector.UIString("\xb1 Count"), width: "72px", sortable: true }, + "sizeDelta": { title: WebInspector.UIString("\xb1 Size"), width: "72px", sortable: true } }; + + this.dataGrid = new WebInspector.DataGrid(columns); + this.dataGrid.addEventListener("sorting changed", this._sortData, this); + this.dataGrid.element.addEventListener("mousedown", this._mouseDownInDataGrid.bind(this), true); + this.element.appendChild(this.dataGrid.element); + + this.snapshot = snapshot; + + this.baseSelectElement = document.createElement("select"); + this.baseSelectElement.className = "status-bar-item"; + this.baseSelectElement.addEventListener("change", this._changeBase.bind(this), false); + this._updateBaseOptions(); + if (this.snapshot.listIndex > 0) + this.baseSelectElement.selectedIndex = this.snapshot.listIndex - 1; + else + this.baseSelectElement.selectedIndex = this.snapshot.listIndex; + this._resetDataGridList(); + + this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item status-bar-item"); + this.percentButton.addEventListener("click", this._percentClicked.bind(this), false); + + this.refresh(); + + this._updatePercentButton(); +}; + +WebInspector.HeapSnapshotView.prototype = { + + get categories() + { + return {code: {title: WebInspector.UIString("Code"), color: {r: 255, g: 121, b: 0}}, data: {title: WebInspector.UIString("Objects and Data"), color: {r: 47, g: 102, b: 236}}, other: {title: WebInspector.UIString("Other"), color: {r: 186, g: 186, b: 186}}}; + }, + + get statusBarItems() + { + return [this.baseSelectElement, this.percentButton.element]; + }, + + get snapshot() + { + return this._snapshot; + }, + + set snapshot(snapshot) + { + this._snapshot = snapshot; + }, + + show: function(parentElement) + { + WebInspector.View.prototype.show.call(this, parentElement); + this.dataGrid.updateWidths(); + }, + + resize: function() + { + if (this.dataGrid) + this.dataGrid.updateWidths(); + }, + + refresh: function() + { + this.dataGrid.removeChildren(); + + var children = this.snapshotDataGridList.children; + var count = children.length; + for (var index = 0; index < count; ++index) + this.dataGrid.appendChild(children[index]); + + this._updateSummaryGraph(); + }, + + refreshShowAsPercents: function() + { + this._updatePercentButton(); + this.refreshVisibleData(); + }, + + refreshVisibleData: function() + { + var child = this.dataGrid.children[0]; + while (child) { + child.refresh(); + child = child.traverseNextNode(false, null, true); + } + this._updateSummaryGraph(); + }, + + _changeBase: function() { + if (this.baseSnapshot === this.snapshot.list[this.baseSelectElement.selectedIndex]) + return; + + this._resetDataGridList(); + this.refresh(); + }, + + _createSnapshotDataGridList: function() + { + if (this._snapshotDataGridList) + delete this._snapshotDataGridList; + + this._snapshotDataGridList = new WebInspector.HeapSnapshotDataGridList(this, this.baseSnapshot.entries, this.snapshot.entries); + return this._snapshotDataGridList; + }, + + _mouseDownInDataGrid: function(event) + { + if (event.detail < 2) + return; + + var cell = event.target.enclosingNodeOrSelfWithNodeName("td"); + if (!cell || (!cell.hasStyleClass("count-column") && !cell.hasStyleClass("size-column") && !cell.hasStyleClass("countDelta-column") && !cell.hasStyleClass("sizeDelta-column"))) + return; + + if (cell.hasStyleClass("count-column")) + this.showCountAsPercent = !this.showCountAsPercent; + else if (cell.hasStyleClass("size-column")) + this.showSizeAsPercent = !this.showSizeAsPercent; + else if (cell.hasStyleClass("countDelta-column")) + this.showCountDeltaAsPercent = !this.showCountDeltaAsPercent; + else if (cell.hasStyleClass("sizeDelta-column")) + this.showSizeDeltaAsPercent = !this.showSizeDeltaAsPercent; + + this.refreshShowAsPercents(); + + event.preventDefault(); + event.stopPropagation(); + }, + + get _isShowingAsPercent() + { + return this.showCountAsPercent && this.showSizeAsPercent && this.showCountDeltaAsPercent && this.showSizeDeltaAsPercent; + }, + + _percentClicked: function(event) + { + var currentState = this._isShowingAsPercent; + this.showCountAsPercent = !currentState; + this.showSizeAsPercent = !currentState; + this.showCountDeltaAsPercent = !currentState; + this.showSizeDeltaAsPercent = !currentState; + this.refreshShowAsPercents(); + }, + + _resetDataGridList: function() + { + this.baseSnapshot = this.snapshot.list[this.baseSelectElement.selectedIndex]; + var lastComparator = WebInspector.HeapSnapshotDataGridList.propertyComparator("objectsSize", false); + if (this.snapshotDataGridList) { + lastComparator = this.snapshotDataGridList.lastComparator; + } + this.snapshotDataGridList = this._createSnapshotDataGridList(); + this.snapshotDataGridList.sort(lastComparator, true); + }, + + _sortData: function() + { + var sortAscending = this.dataGrid.sortOrder === "ascending"; + var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier; + var sortProperty = { + "cons": "constructorName", + "count": "objectsCount", + "size": "objectsSize", + "countDelta": this.showCountDeltaAsPercent ? "objectsCountDeltaPercent" : "objectsCountDelta", + "sizeDelta": this.showSizeDeltaAsPercent ? "objectsSizeDeltaPercent" : "objectsSizeDelta" + }[sortColumnIdentifier]; + + this.snapshotDataGridList.sort(WebInspector.HeapSnapshotDataGridList.propertyComparator(sortProperty, sortAscending)); + + this.refresh(); + }, + + _updateBaseOptions: function() + { + // We're assuming that snapshots can only be added. + if (this.baseSelectElement.length == this.snapshot.list.length) + return; + + for (var i = this.baseSelectElement.length, n = this.snapshot.list.length; i < n; ++i) { + var baseOption = document.createElement("option"); + baseOption.label = WebInspector.UIString("Compared to %s", this.snapshot.list[i].title); + this.baseSelectElement.appendChild(baseOption); + } + }, + + _updatePercentButton: function() + { + if (this._isShowingAsPercent) { + this.percentButton.title = WebInspector.UIString("Show absolute counts and sizes."); + this.percentButton.toggled = true; + } else { + this.percentButton.title = WebInspector.UIString("Show counts and sizes as percentages."); + this.percentButton.toggled = false; + } + }, + + _updateSummaryGraph: function() + { + this.summaryBar.calculator.showAsPercent = this._isShowingAsPercent; + this.summaryBar.update(this.snapshot.lowlevels); + } +}; + +WebInspector.HeapSnapshotView.prototype.__proto__ = WebInspector.View.prototype; + +WebInspector.HeapSummaryCalculator = function(total) +{ + this.total = total; +} + +WebInspector.HeapSummaryCalculator.prototype = { + computeSummaryValues: function(lowLevels) + { + function highFromLow(type) { + if (type == "CODE_TYPE" || type == "SHARED_FUNCTION_INFO_TYPE" || type == "SCRIPT_TYPE") return "code"; + if (type == "STRING_TYPE" || type == "HEAP_NUMBER_TYPE" || type.match(/^JS_/) || type.match(/_ARRAY_TYPE$/)) return "data"; + return "other"; + } + var highLevels = {data: 0, code: 0, other: 0}; + for (var item in lowLevels) { + var highItem = highFromLow(item); + highLevels[highItem] += lowLevels[item].size; + } + return {categoryValues: highLevels}; + }, + + formatValue: function(value) + { + if (this.showAsPercent) + return WebInspector.UIString("%.2f%%", value / this.total * 100.0); + else + return Number.bytesToString(value); + }, + + get showAsPercent() + { + return this._showAsPercent; + }, + + set showAsPercent(x) + { + this._showAsPercent = x; + } +} + +WebInspector.HeapSnapshotSidebarTreeElement = function(snapshot) +{ + this.snapshot = snapshot; + this.snapshot.title = WebInspector.UIString("Snapshot %d", this.snapshot.number); + + WebInspector.SidebarTreeElement.call(this, "heap-snapshot-sidebar-tree-item", "", "", snapshot, false); + + this.refreshTitles(); +}; + +WebInspector.HeapSnapshotSidebarTreeElement.prototype = { + onselect: function() + { + WebInspector.panels.heap.showSnapshot(this.snapshot); + }, + + get mainTitle() + { + if (this._mainTitle) + return this._mainTitle; + return this.snapshot.title; + }, + + set mainTitle(x) + { + this._mainTitle = x; + this.refreshTitles(); + }, + + get subtitle() + { + if (this._subTitle) + return this._subTitle; + return WebInspector.UIString("Used %s of %s (%.0f%%)", Number.bytesToString(this.snapshot.used, null, false), Number.bytesToString(this.snapshot.capacity, null, false), this.snapshot.used / this.snapshot.capacity * 100.0); + }, + + set subtitle(x) + { + this._subTitle = x; + this.refreshTitles(); + } +}; + +WebInspector.HeapSnapshotSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; + +WebInspector.HeapSnapshotDataGridNode = function(snapshotView, baseEntry, snapshotEntry, owningList) +{ + WebInspector.DataGridNode.call(this, null, false); + + this.snapshotView = snapshotView; + this.list = owningList; + + if (!snapshotEntry) + snapshotEntry = { cons: baseEntry.cons, count: 0, size: 0 }; + this.constructorName = snapshotEntry.cons; + this.objectsCount = snapshotEntry.count; + this.objectsSize = snapshotEntry.size; + + if (!baseEntry) + baseEntry = { count: 0, size: 0 }; + this.baseObjectsCount = baseEntry.count; + this.objectsCountDelta = this.objectsCount - this.baseObjectsCount; + this.baseObjectsSize = baseEntry.size; + this.objectsSizeDelta = this.objectsSize - this.baseObjectsSize; +}; + +WebInspector.HeapSnapshotDataGridNode.prototype = { + get data() + { + var data = {}; + + data["cons"] = this.constructorName; + + if (this.snapshotView.showCountAsPercent) + data["count"] = WebInspector.UIString("%.2f%%", this.objectsCountPercent); + else + data["count"] = this.objectsCount; + + if (this.snapshotView.showSizeAsPercent) + data["size"] = WebInspector.UIString("%.2f%%", this.objectsSizePercent); + else + data["size"] = Number.bytesToString(this.objectsSize); + + function signForDelta(delta) { + if (delta == 0) + return ""; + if (delta > 0) + return "+"; + else + // Math minus sign, same width as plus. + return "\u2212"; + } + + function showDeltaAsPercent(value) { + if (value === Number.POSITIVE_INFINITY) + return WebInspector.UIString("new"); + else if (value === Number.NEGATIVE_INFINITY) + return WebInspector.UIString("deleted"); + if (value > 1000.0) + return WebInspector.UIString("%s >1000%%", signForDelta(value)); + return WebInspector.UIString("%s%.2f%%", signForDelta(value), Math.abs(value)); + } + + if (this.snapshotView.showCountDeltaAsPercent) + data["countDelta"] = showDeltaAsPercent(this.objectsCountDeltaPercent); + else + data["countDelta"] = WebInspector.UIString("%s%d", signForDelta(this.objectsCountDelta), Math.abs(this.objectsCountDelta)); + + if (this.snapshotView.showSizeDeltaAsPercent) + data["sizeDelta"] = showDeltaAsPercent(this.objectsSizeDeltaPercent); + else + data["sizeDelta"] = WebInspector.UIString("%s%s", signForDelta(this.objectsSizeDelta), Number.bytesToString(Math.abs(this.objectsSizeDelta))); + + return data; + }, + + get objectsCountPercent() + { + return this.objectsCount / this.list.objectsCount * 100.0; + }, + + get objectsSizePercent() + { + return this.objectsSize / this.list.objectsSize * 100.0; + }, + + get objectsCountDeltaPercent() + { + if (this.baseObjectsCount > 0) { + if (this.objectsCount > 0) + return this.objectsCountDelta / this.baseObjectsCount * 100.0; + else + return Number.NEGATIVE_INFINITY; + } else + return Number.POSITIVE_INFINITY; + }, + + get objectsSizeDeltaPercent() + { + if (this.baseObjectsSize > 0) { + if (this.objectsSize > 0) + return this.objectsSizeDelta / this.baseObjectsSize * 100.0; + else + return Number.NEGATIVE_INFINITY; + } else + return Number.POSITIVE_INFINITY; + } +}; + +WebInspector.HeapSnapshotDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype; + +WebInspector.HeapSnapshotDataGridList = function(snapshotView, baseEntries, snapshotEntries) +{ + this.list = this; + this.snapshotView = snapshotView; + this.children = []; + this.lastComparator = null; + this.populateChildren(baseEntries, snapshotEntries); +}; + +WebInspector.HeapSnapshotDataGridList.prototype = { + appendChild: function(child) + { + this.insertChild(child, this.children.length); + }, + + insertChild: function(child, index) + { + this.children.splice(index, 0, child); + }, + + removeChildren: function() + { + this.children = []; + }, + + populateChildren: function(baseEntries, snapshotEntries) + { + for (var item in snapshotEntries) + this.appendChild(new WebInspector.HeapSnapshotDataGridNode(this.snapshotView, baseEntries[item], snapshotEntries[item], this)); + + for (item in baseEntries) { + if (!(item in snapshotEntries)) + this.appendChild(new WebInspector.HeapSnapshotDataGridNode(this.snapshotView, baseEntries[item], null, this)); + } + }, + + sort: function(comparator, force) { + if (!force && this.lastComparator === comparator) + return; + + this.children.sort(comparator); + this.lastComparator = comparator; + }, + + get objectsCount() { + if (!this._objectsCount) { + this._objectsCount = 0; + for (var i = 0, n = this.children.length; i < n; ++i) { + this._objectsCount += this.children[i].objectsCount; + } + } + return this._objectsCount; + }, + + get objectsSize() { + if (!this._objectsSize) { + this._objectsSize = 0; + for (var i = 0, n = this.children.length; i < n; ++i) { + this._objectsSize += this.children[i].objectsSize; + } + } + return this._objectsSize; + } +}; + +WebInspector.HeapSnapshotDataGridList.propertyComparators = [{}, {}]; + +WebInspector.HeapSnapshotDataGridList.propertyComparator = function(property, isAscending) +{ + var comparator = this.propertyComparators[(isAscending ? 1 : 0)][property]; + if (!comparator) { + comparator = function(lhs, rhs) { + var l = lhs[property], r = rhs[property]; + var result = l < r ? -1 : (l > r ? 1 : 0); + return isAscending ? result : -result; + }; + this.propertyComparators[(isAscending ? 1 : 0)][property] = comparator; + } + return comparator; +}; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/back.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/back.png Binary files differnew file mode 100644 index 0000000..9363960 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/back.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/checker.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/checker.png Binary files differnew file mode 100644 index 0000000..8349908 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/checker.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/clearConsoleButtonGlyph.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/clearConsoleButtonGlyph.png Binary files differnew file mode 100644 index 0000000..b1f9465 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/clearConsoleButtonGlyph.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/closeButtons.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/closeButtons.png Binary files differnew file mode 100644 index 0000000..28158a4 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/closeButtons.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/consoleButtonGlyph.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/consoleButtonGlyph.png Binary files differnew file mode 100644 index 0000000..d10d43c --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/consoleButtonGlyph.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/cookie.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/cookie.png Binary files differnew file mode 100644 index 0000000..90c3c15 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/cookie.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/database.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/database.png Binary files differnew file mode 100644 index 0000000..339efa6 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/database.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/databaseTable.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/databaseTable.png Binary files differnew file mode 100644 index 0000000..3718708 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/databaseTable.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/debuggerContinue.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/debuggerContinue.png Binary files differnew file mode 100644 index 0000000..d90a855 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/debuggerContinue.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/debuggerPause.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/debuggerPause.png Binary files differnew file mode 100644 index 0000000..97f958a --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/debuggerPause.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/debuggerStepInto.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/debuggerStepInto.png Binary files differnew file mode 100644 index 0000000..277f126 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/debuggerStepInto.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/debuggerStepOut.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/debuggerStepOut.png Binary files differnew file mode 100644 index 0000000..3032e32 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/debuggerStepOut.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/debuggerStepOver.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/debuggerStepOver.png Binary files differnew file mode 100644 index 0000000..7d47245 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/debuggerStepOver.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallDown.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallDown.png Binary files differnew file mode 100644 index 0000000..cffc835 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallDown.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallDownBlack.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallDownBlack.png Binary files differnew file mode 100644 index 0000000..4b49c13 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallDownBlack.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallDownWhite.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallDownWhite.png Binary files differnew file mode 100644 index 0000000..aebae12 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallDownWhite.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRight.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRight.png Binary files differnew file mode 100644 index 0000000..a3102ea --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRight.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRightBlack.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRightBlack.png Binary files differnew file mode 100644 index 0000000..2c45859 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRightBlack.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRightDown.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRightDown.png Binary files differnew file mode 100644 index 0000000..035c069 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRightDown.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRightDownBlack.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRightDownBlack.png Binary files differnew file mode 100644 index 0000000..86f67bd --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRightDownBlack.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRightDownWhite.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRightDownWhite.png Binary files differnew file mode 100644 index 0000000..972d794 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRightDownWhite.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRightWhite.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRightWhite.png Binary files differnew file mode 100644 index 0000000..a10168f --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/disclosureTriangleSmallRightWhite.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/dockButtonGlyph.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/dockButtonGlyph.png Binary files differnew file mode 100644 index 0000000..7052f4b --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/dockButtonGlyph.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/elementsIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/elementsIcon.png Binary files differnew file mode 100644 index 0000000..fde3db9 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/elementsIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/enableOutlineButtonGlyph.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/enableOutlineButtonGlyph.png Binary files differnew file mode 100644 index 0000000..85e0bd6 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/enableOutlineButtonGlyph.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/enableSolidButtonGlyph.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/enableSolidButtonGlyph.png Binary files differnew file mode 100644 index 0000000..25b2e96 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/enableSolidButtonGlyph.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/errorIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/errorIcon.png Binary files differnew file mode 100644 index 0000000..c697263 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/errorIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/errorMediumIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/errorMediumIcon.png Binary files differnew file mode 100644 index 0000000..6ca32bb --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/errorMediumIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/excludeButtonGlyph.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/excludeButtonGlyph.png Binary files differnew file mode 100644 index 0000000..5128576 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/excludeButtonGlyph.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/focusButtonGlyph.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/focusButtonGlyph.png Binary files differnew file mode 100644 index 0000000..b71807c --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/focusButtonGlyph.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/forward.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/forward.png Binary files differnew file mode 100644 index 0000000..ad70f3e --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/forward.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/glossyHeader.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/glossyHeader.png Binary files differnew file mode 100644 index 0000000..6cbefb7 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/glossyHeader.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/glossyHeaderPressed.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/glossyHeaderPressed.png Binary files differnew file mode 100644 index 0000000..1153506 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/glossyHeaderPressed.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/glossyHeaderSelected.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/glossyHeaderSelected.png Binary files differnew file mode 100644 index 0000000..71d5af6 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/glossyHeaderSelected.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/glossyHeaderSelectedPressed.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/glossyHeaderSelectedPressed.png Binary files differnew file mode 100644 index 0000000..7047dbe --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/glossyHeaderSelectedPressed.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/goArrow.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/goArrow.png Binary files differnew file mode 100644 index 0000000..f318a56 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/goArrow.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/graphLabelCalloutLeft.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/graphLabelCalloutLeft.png Binary files differnew file mode 100644 index 0000000..6426dbd --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/graphLabelCalloutLeft.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/graphLabelCalloutRight.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/graphLabelCalloutRight.png Binary files differnew file mode 100644 index 0000000..8c87eae --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/graphLabelCalloutRight.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/largerResourcesButtonGlyph.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/largerResourcesButtonGlyph.png Binary files differnew file mode 100644 index 0000000..71256d6 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/largerResourcesButtonGlyph.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/localStorage.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/localStorage.png Binary files differnew file mode 100644 index 0000000..44a3019 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/localStorage.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/nodeSearchButtonGlyph.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/nodeSearchButtonGlyph.png Binary files differnew file mode 100644 index 0000000..faf5df2 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/nodeSearchButtonGlyph.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/paneBottomGrow.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/paneBottomGrow.png Binary files differnew file mode 100644 index 0000000..d55b865 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/paneBottomGrow.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/paneBottomGrowActive.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/paneBottomGrowActive.png Binary files differnew file mode 100644 index 0000000..ef3f259 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/paneBottomGrowActive.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/paneGrowHandleLine.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/paneGrowHandleLine.png Binary files differnew file mode 100644 index 0000000..4eaf61b --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/paneGrowHandleLine.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/pauseOnExceptionButtonGlyph.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/pauseOnExceptionButtonGlyph.png Binary files differnew file mode 100644 index 0000000..c3cec5f --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/pauseOnExceptionButtonGlyph.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/percentButtonGlyph.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/percentButtonGlyph.png Binary files differnew file mode 100644 index 0000000..0ace3b7 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/percentButtonGlyph.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/profileGroupIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/profileGroupIcon.png Binary files differnew file mode 100644 index 0000000..44616d4 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/profileGroupIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/profileIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/profileIcon.png Binary files differnew file mode 100644 index 0000000..8008f9b --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/profileIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/profileSmallIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/profileSmallIcon.png Binary files differnew file mode 100644 index 0000000..7935520 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/profileSmallIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/profilesIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/profilesIcon.png Binary files differnew file mode 100644 index 0000000..ecd5b04 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/profilesIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/profilesSilhouette.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/profilesSilhouette.png Binary files differnew file mode 100644 index 0000000..42bb966 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/profilesSilhouette.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/radioDot.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/radioDot.png Binary files differnew file mode 100644 index 0000000..609878f --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/radioDot.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/recordButtonGlyph.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/recordButtonGlyph.png Binary files differnew file mode 100644 index 0000000..bfdad1a --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/recordButtonGlyph.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/recordToggledButtonGlyph.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/recordToggledButtonGlyph.png Binary files differnew file mode 100644 index 0000000..2c22f87 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/recordToggledButtonGlyph.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/reloadButtonGlyph.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/reloadButtonGlyph.png Binary files differnew file mode 100644 index 0000000..28e047a --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/reloadButtonGlyph.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourceCSSIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourceCSSIcon.png Binary files differnew file mode 100644 index 0000000..aead6a7 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourceCSSIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourceDocumentIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourceDocumentIcon.png Binary files differnew file mode 100644 index 0000000..1683a09 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourceDocumentIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourceDocumentIconSmall.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourceDocumentIconSmall.png Binary files differnew file mode 100644 index 0000000..468ced9 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourceDocumentIconSmall.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourceJSIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourceJSIcon.png Binary files differnew file mode 100644 index 0000000..9ef6ed0 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourceJSIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcePlainIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcePlainIcon.png Binary files differnew file mode 100644 index 0000000..0ed37b6 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcePlainIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcePlainIconSmall.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcePlainIconSmall.png Binary files differnew file mode 100644 index 0000000..0fa967d --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcePlainIconSmall.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcesIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcesIcon.png Binary files differnew file mode 100644 index 0000000..982424d --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcesIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcesSilhouette.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcesSilhouette.png Binary files differnew file mode 100644 index 0000000..9c8bb53 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcesSilhouette.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcesSizeGraphIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcesSizeGraphIcon.png Binary files differnew file mode 100644 index 0000000..e60dbe5 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcesSizeGraphIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcesTimeGraphIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcesTimeGraphIcon.png Binary files differnew file mode 100644 index 0000000..c6953e9 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/resourcesTimeGraphIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/scriptsIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/scriptsIcon.png Binary files differnew file mode 100644 index 0000000..213b31e --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/scriptsIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/scriptsSilhouette.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/scriptsSilhouette.png Binary files differnew file mode 100644 index 0000000..206396f --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/scriptsSilhouette.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/searchSmallBlue.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/searchSmallBlue.png Binary files differnew file mode 100644 index 0000000..9c990f4 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/searchSmallBlue.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/searchSmallBrightBlue.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/searchSmallBrightBlue.png Binary files differnew file mode 100644 index 0000000..b1d8055 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/searchSmallBrightBlue.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/searchSmallGray.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/searchSmallGray.png Binary files differnew file mode 100644 index 0000000..4f3c068 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/searchSmallGray.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/searchSmallWhite.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/searchSmallWhite.png Binary files differnew file mode 100644 index 0000000..85f430d --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/searchSmallWhite.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segment.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segment.png Binary files differnew file mode 100644 index 0000000..759266e --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segment.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segmentEnd.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segmentEnd.png Binary files differnew file mode 100644 index 0000000..72672ff --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segmentEnd.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segmentHover.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segmentHover.png Binary files differnew file mode 100644 index 0000000..c5017f4 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segmentHover.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segmentHoverEnd.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segmentHoverEnd.png Binary files differnew file mode 100644 index 0000000..d51363d --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segmentHoverEnd.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segmentSelected.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segmentSelected.png Binary files differnew file mode 100644 index 0000000..c92f584 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segmentSelected.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segmentSelectedEnd.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segmentSelectedEnd.png Binary files differnew file mode 100644 index 0000000..be5e0852 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/segmentSelectedEnd.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/sessionStorage.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/sessionStorage.png Binary files differnew file mode 100644 index 0000000..4d50e35 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/sessionStorage.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/splitviewDimple.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/splitviewDimple.png Binary files differnew file mode 100644 index 0000000..584ffd4 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/splitviewDimple.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/splitviewDividerBackground.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/splitviewDividerBackground.png Binary files differnew file mode 100644 index 0000000..1120a7f --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/splitviewDividerBackground.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarBackground.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarBackground.png Binary files differnew file mode 100644 index 0000000..b466a49 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarBackground.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarBottomBackground.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarBottomBackground.png Binary files differnew file mode 100644 index 0000000..fb5c9e4 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarBottomBackground.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarButtons.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarButtons.png Binary files differnew file mode 100644 index 0000000..e8090cb --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarButtons.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarMenuButton.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarMenuButton.png Binary files differnew file mode 100644 index 0000000..9b3abdd --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarMenuButton.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarMenuButtonSelected.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarMenuButtonSelected.png Binary files differnew file mode 100644 index 0000000..8189c43 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarMenuButtonSelected.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarResizerHorizontal.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarResizerHorizontal.png Binary files differnew file mode 100644 index 0000000..56deeab --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarResizerHorizontal.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarResizerVertical.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarResizerVertical.png Binary files differnew file mode 100644 index 0000000..7fc145277 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/statusbarResizerVertical.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/storageIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/storageIcon.png Binary files differnew file mode 100644 index 0000000..79c7bb3 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/storageIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillBlue.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillBlue.png Binary files differnew file mode 100644 index 0000000..c7c273b --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillBlue.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillGray.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillGray.png Binary files differnew file mode 100644 index 0000000..9ff37ef --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillGray.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillGreen.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillGreen.png Binary files differnew file mode 100644 index 0000000..cc5a8f3 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillGreen.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillOrange.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillOrange.png Binary files differnew file mode 100644 index 0000000..08a81e4 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillOrange.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillPurple.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillPurple.png Binary files differnew file mode 100644 index 0000000..565a05c --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillPurple.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillRed.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillRed.png Binary files differnew file mode 100644 index 0000000..c3a1b9b --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillRed.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillYellow.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillYellow.png Binary files differnew file mode 100644 index 0000000..780045b --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelineHollowPillYellow.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillBlue.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillBlue.png Binary files differnew file mode 100644 index 0000000..c897faa --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillBlue.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillGray.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillGray.png Binary files differnew file mode 100644 index 0000000..2128896 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillGray.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillGreen.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillGreen.png Binary files differnew file mode 100644 index 0000000..9b66125 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillGreen.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillOrange.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillOrange.png Binary files differnew file mode 100644 index 0000000..dd944fb --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillOrange.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillPurple.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillPurple.png Binary files differnew file mode 100644 index 0000000..21b96f7 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillPurple.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillRed.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillRed.png Binary files differnew file mode 100644 index 0000000..f5e213b --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillRed.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillYellow.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillYellow.png Binary files differnew file mode 100644 index 0000000..ae2a5a23 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/timelinePillYellow.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/tipBalloon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/tipBalloon.png Binary files differnew file mode 100644 index 0000000..4cdf738 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/tipBalloon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/tipBalloonBottom.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/tipBalloonBottom.png Binary files differnew file mode 100644 index 0000000..3317a5a --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/tipBalloonBottom.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/tipIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/tipIcon.png Binary files differnew file mode 100644 index 0000000..8ca6124 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/tipIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/tipIconPressed.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/tipIconPressed.png Binary files differnew file mode 100644 index 0000000..443e410 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/tipIconPressed.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/toolbarItemSelected.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/toolbarItemSelected.png Binary files differnew file mode 100644 index 0000000..bd681f18 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/toolbarItemSelected.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeDownTriangleBlack.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeDownTriangleBlack.png Binary files differnew file mode 100644 index 0000000..0821112 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeDownTriangleBlack.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeDownTriangleWhite.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeDownTriangleWhite.png Binary files differnew file mode 100644 index 0000000..1667b51 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeDownTriangleWhite.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeRightTriangleBlack.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeRightTriangleBlack.png Binary files differnew file mode 100644 index 0000000..90de820 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeRightTriangleBlack.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeRightTriangleWhite.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeRightTriangleWhite.png Binary files differnew file mode 100644 index 0000000..2b6a82f --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeRightTriangleWhite.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeUpTriangleBlack.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeUpTriangleBlack.png Binary files differnew file mode 100644 index 0000000..ef69dbc --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeUpTriangleBlack.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeUpTriangleWhite.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeUpTriangleWhite.png Binary files differnew file mode 100644 index 0000000..43ce4be --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/treeUpTriangleWhite.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/undockButtonGlyph.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/undockButtonGlyph.png Binary files differnew file mode 100644 index 0000000..eed2b65 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/undockButtonGlyph.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/userInputIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/userInputIcon.png Binary files differnew file mode 100644 index 0000000..325023f --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/userInputIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/userInputPreviousIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/userInputPreviousIcon.png Binary files differnew file mode 100644 index 0000000..068d572 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/userInputPreviousIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/userInputResultIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/userInputResultIcon.png Binary files differnew file mode 100644 index 0000000..794a5ca --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/userInputResultIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/warningIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/warningIcon.png Binary files differnew file mode 100644 index 0000000..d5e4c82 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/warningIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/warningMediumIcon.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/warningMediumIcon.png Binary files differnew file mode 100644 index 0000000..291e111 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/warningMediumIcon.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/warningsErrors.png b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/warningsErrors.png Binary files differnew file mode 100644 index 0000000..878b593 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/images/warningsErrors.png diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inject.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inject.js new file mode 100644 index 0000000..8a9b199 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inject.js @@ -0,0 +1,50 @@ +// 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() { +}; + + +/** + * Dispatches given method with given args on the host object. + * @param {string} method Method name. + */ +devtools.Injected.prototype.InspectorController = function(method, var_args) { + var args = Array.prototype.slice.call(arguments, 1); + return InspectorController[method].apply(InspectorController, args); +}; + + +/** + * Dispatches given method with given args on the InjectedScript. + * @param {string} method Method name. + */ +devtools.Injected.prototype.InjectedScript = function(method, var_args) { + var args = Array.prototype.slice.call(arguments, 1); + var result = InjectedScript[method].apply(InjectedScript, args); + return result; +}; + + +// Plugging into upstreamed support. +InjectedScript._window = function() { + return contentWindow; +}; + + +// Plugging into upstreamed support. +Object.className = function(obj) { + return (obj == null) ? "null" : obj.constructor.name; +}; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inspector.css b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inspector.css new file mode 100644 index 0000000..ea6f661 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inspector.css @@ -0,0 +1,3302 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2009 Anthony Ricaud <rik@webkit.org> + * + * 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.storage .toolbar-icon { + background-image: url(Images/storageIcon.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.drawer-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.drawer-visible #main-status-bar * { + cursor: default; +} + +body.drawer-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; +} + +.glyph { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.75); + z-index: 1; +} + +.glyph.shadow { + top: 1px; + background-color: white !important; + z-index: 0; +} + +button.status-bar-item { + position: relative; + width: 32px; + background-image: url(Images/statusbarButtons.png); + background-position: 0 0; +} + +button.status-bar-item:active { + background-position: 32px 0 !important; +} + +button.status-bar-item .glyph.shadow { + background-color: rgba(255, 255, 255, 0.33) !important; +} + +button.status-bar-item.toggled-on .glyph { + background-color: rgb(66, 129, 235); +} + +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 .glyph { + -webkit-mask-image: url(Images/undockButtonGlyph.png); +} + +body.detached #dock-status-bar-item .glyph { + -webkit-mask-image: url(Images/dockButtonGlyph.png); +} + +#console-status-bar-item .glyph { + -webkit-mask-image: url(Images/consoleButtonGlyph.png); +} + +#clear-console-status-bar-item .glyph { + -webkit-mask-image: url(Images/clearConsoleButtonGlyph.png); +} + +#changes-status-bar-item .glyph { + -webkit-mask-image: url(Images/consoleButtonGlyph.png); /* TODO: Needs Image for Changes Toggle Button */ +} + +#clear-changes-status-bar-item .glyph { + -webkit-mask-image: url(Images/clearConsoleButtonGlyph.png); +} + +#count-items { + position: absolute; + right: 16px; + top: 0; + cursor: pointer; + padding: 6px 2px; + font-size: 10px; + height: 19px; +} + +#changes-count, #error-warning-count { + display: inline; +} + +#error-warning-count:hover, #changes-count:hover { + border-bottom: 1px solid rgb(96, 96, 96); +} + +#style-changes-count::before { + content: url(Images/styleIcon.png); /* TODO: Needs Image for Style Changes Icon */ + width: 10px; + height: 10px; + vertical-align: -1px; + margin-right: 2px; +} + +#error-count::before { + content: url(Images/errorIcon.png); + width: 10px; + height: 10px; + vertical-align: -1px; + margin-right: 2px; +} + +#changes-count + #error-warning-count, #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; +} + +#drawer { + 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.drawer-visible #drawer { + display: block; +} + +#drawer-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: initial; + font-family: 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::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, .repeated-message.console-debug-level:before { + visibility: hidden; +} + +.console-group .console-group > .console-group-messages { + margin-left: 16px; +} + +.console-group-title { + font-weight: bold; +} + +.console-group-title::before { + background-image: url(Images/disclosureTriangleSmallDown.png); + top: 0.6em; + width: 11px; + height: 12px; +} + +.console-group.collapsed .console-group-title::before { + background-image: url(Images/disclosureTriangleSmallRight.png); +} + +.console-group.collapsed > .console-group-messages { + display: none; +} + +.console-error-level .console-message-text { + color: red; +} + +.console-debug-level .console-message-text { + color: blue; +} + +.console-debug-level::before { + background-image: url(Images/searchSmallBrightBlue.png); +} + +.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-group-messages .add-attribute { + display: none; +} + +.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-headers .outline-disclosure .raw-form-data { + white-space:pre-wrap; +} + +.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; +} + +.invisible { + color: inherit; + text-decoration: none; +} + +.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; +} + +.add-attribute { + margin-left: 1px; + margin-right: 1px; +} + +.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; +} + +.watch-expressions-buttons-container { + text-align: center; +} + +.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.no-affect .header { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(167, 167, 167)), to(rgb(123, 123, 123))) +} + +.section .header::before { + position: absolute; + top: 4px; + left: 7px; + width: 8px; + height: 8px; + content: url(Images/treeRightTriangleWhite.png); +} + +.section.blank-section .header::before { + display: none; +} + +.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 .title.blank-title { + font-style: italic; +} + +.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; + min-height: 18px; +} + +.section.no-affect .properties li { + opacity: 0.5; +} + +.section.no-affect .properties li.editing { + opacity: 1.0; +} + +.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, li.editing-sub-part .delete-button { + display: none !important; +} + +.watch-expressions > li.editing-sub-part .name { + display: block; + width: 100%; +} + +.watch-expressions > li.editing-sub-part .value, .watch-expressions > li.editing-sub-part .separator { + display: none; +} + +.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; +} + +/* FIXME: need a better icon (comment in bug 27514) */ +.section .properties .delete-button { + width: 10px; + height: 10px; + background-image: url(Images/errorIcon.png); + background-position: 0 0; + background-color: transparent; + background-repeat: no-repeat; + border: 0 none transparent; +} + +.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: 1px; + margin-right: 2px; + margin-bottom: -1px; + width: 1em; + height: 1em; + border: 1px solid rgba(128, 128, 128, 0.6); +} + +.swatch:hover { + border: 1px solid rgba(64, 64, 64, 0.8); +} + +.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 > .title > select { + display: none; + float: right; + width: 23px; + height: 17px; + color: transparent; + background-color: transparent; + border: none; + background-image: url(Images/paneSettingsButtons.png); + background-repeat: no-repeat; + margin: 1px 0 0 0; + padding: 0; + -webkit-border-radius: 0; + -webkit-appearance: none; +} + +.pane.expanded:hover > .title > select { + display: inline-block; +} + +.pane > .title > select:hover { + background-position: -23px 0px; +} + +.pane > .title > select:active { + background-position: -46px 0px; +} + +.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.local-storage .icon { + content: url(Images/localStorage.png); +} + +.domstorage-sidebar-tree-item.session-storage .icon { + content: url(Images/sessionStorage.png); +} + +.cookie-sidebar-tree-item .icon { + content: url(Images/cookie.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 .centered div { + text-align: center; +} + +.data-grid .right div { + text-align: right; +} + +.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; +} + +.data-grid-resizer { + position: absolute; + top: 0; + bottom: 0; + width: 5px; + z-index: 500; + cursor: col-resize; +} + +.storage-view.query { + font-size: initial; + font-family: 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/resourcesSilhouette.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 .glyph { + -webkit-mask-image: url(Images/enableOutlineButtonGlyph.png); +} + +button.enable-toggle-status-bar-item.toggled-on .glyph { + -webkit-mask-image: url(Images/enableSolidButtonGlyph.png); +} + +.scripts-pause-on-exceptions-status-bar-item .glyph { + -webkit-mask-image: url(Images/pauseOnExceptionButtonGlyph.png); +} + +#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 .glyph { + -webkit-mask-image: url(Images/largerResourcesButtonGlyph.png); +} + +#resources-filter { + height: 24px; + padding: 2px 10px 0; + background: -webkit-gradient(linear, left top, left bottom, from(rgb(233, 233, 233)), to(rgb(207, 207, 207))); + border-bottom: 1px solid rgb(177, 177, 177); + overflow: hidden; +} + +#console-filter { + height: 24px; + padding: 2px 10px 0; + overflow: hidden; +} + +#resources-filter li, #console-filter li { + display: inline-block; + margin: 1px 1px 0 0; + padding: 0 6px 3px; + font-size: 12px; + line-height: 12px; + font-weight: bold; + color: rgb(40, 40, 40); + border: 1px solid transparent; + border-bottom: 0; + background: transparent; + -webkit-border-radius: 8px; + text-shadow: rgba(255, 255, 255, 0.5) 1px 1px 0; +} + +#resources-filter li.selected, #resources-filter li:hover, #resources-filter li:active, +#console-filter li.selected, #console-filter li:hover, #console-filter li:active { + color: white; + text-shadow: rgb(80, 80, 80) 1px 1px 1px; + background: rgba(20, 20, 20, 0.4); + border-color: rgba(20, 20, 20, 0.2); + -webkit-box-shadow: 0 1px 0px rgba(255, 255, 255, 0.5); +} + +#resources-filter li:hover, +#console-filter li:hover { + background: rgba(20, 20, 20, 0.4); + border-color: transparent; + -webkit-box-shadow: none; +} + +#resources-filter li:active, +#console-filter li:active { + background: rgba(20, 20, 20, 0.6); +} + +#resources-container { + position: absolute; + top: 24px; + 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; +} + +.summary-graph-legend { + margin-top: -10px; + padding-left: 15px; +} + +.summary-graph-legend-item { + display: inline-block; + font-weight: bold; + margin-right: 15px; + vertical-align: top; +} + +.summary-graph-legend-item.total { + margin-left: 10px; +} + +.summary-graph-legend-label { + display: inline-block; + text-align: left; +} + +.summary-graph-legend-header { + font-size: 12px; +} + +.summary-graph-legend-value { + font-size: 10px; +} + +.summary-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-category-documents, .resources-category-stylesheets, .resources-category-images, +.resources-category-scripts, .resources-category-xhr, .resources-category-fonts, .resources-category-other { + display: none; +} + +.filter-all .resources-category-documents, .filter-documents .resources-category-documents, +.filter-all .resources-category-stylesheets, .filter-stylesheets .resources-category-stylesheets, +.filter-all .resources-category-images, .filter-images .resources-category-images, +.filter-all .resources-category-scripts, .filter-scripts .resources-category-scripts, +.filter-all .resources-category-xhr, .filter-xhr .resources-category-xhr, +.filter-all .resources-category-fonts, .filter-fonts .resources-category-fonts, +.filter-all .resources-category-other, .filter-other .resources-category-other, +.resource-sidebar-tree-item.selected { + display: list-item; +} + +.console-warning-level, .console-error-level, .console-log-level { + display: none; +} + +.filter-all .console-warning-level, .filter-warnings .console-warning-level, +.filter-all .console-error-level, .filter-errors .console-error-level, +.filter-all .console-log-level, .filter-logs .console-log-level { + display: block; +} + +.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: 24px; + 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; +} + +.resources .sidebar-resizer-vertical { + top: 24px; +} + +.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.debug, .console-debug-level .bubble { + background-color: rgb(0, 0, 255) !important; +} + +.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; +} + +button.enable-toggle-status-bar-item .glyph { +} + +.record-profile-status-bar-item .glyph { + -webkit-mask-image: url(Images/recordButtonGlyph.png); +} + +.record-profile-status-bar-item.toggled-on .glyph { + -webkit-mask-image: url(Images/recordToggledButtonGlyph.png); + background-color: rgb(216, 0, 0) !important; +} + +/* FIXME: should have its own glyph. */ +.heap-snapshot-status-bar-item .glyph { + -webkit-mask-image: url(Images/focusButtonGlyph.png); +} + +.node-search-status-bar-item .glyph { + -webkit-mask-image: url(Images/nodeSearchButtonGlyph.png); +} + +.percent-time-status-bar-item .glyph { + -webkit-mask-image: url(Images/percentButtonGlyph.png); +} + +.focus-profile-node-status-bar-item .glyph { + -webkit-mask-image: url(Images/focusButtonGlyph.png); +} + +.exclude-profile-node-status-bar-item .glyph { + -webkit-mask-image: url(Images/excludeButtonGlyph.png); +} + +.reset-profile-status-bar-item .glyph { + -webkit-mask-image: url(Images/reloadButtonGlyph.png); +} + +.delete-storage-status-bar-item .glyph { + -webkit-mask-image: url(Images/excludeButtonGlyph.png); +} + +#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 .glyph { + -webkit-mask-image: url(Images/reloadButtonGlyph.png); +} + +#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; +} + +ol.breakpoint-list { + -webkit-padding-start: 2px; + list-style: none; + margin: 0; +} + +.breakpoint-list li { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + margin: 4px 0; +} + +.breakpoint-list .checkbox-elem { + font-size: 10px; + margin: 0 4px; + vertical-align: top; + position: relative; + z-index: 1; +} + +.breakpoint-list .source-text { + font-family: monospace; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + margin: 2px 0 0px 20px; +} + +.breakpoint-list a { + color: rgb(33%, 33%, 33%); + cursor: pointer; +} + +.breakpoint-list a:hover { + color: rgb(15%, 15%, 15%); +} diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inspector.html b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inspector.html new file mode 100644 index 0000000..7f544fe --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inspector.html @@ -0,0 +1,112 @@ +<!-- +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="KeyboardShortcut.js"></script> + <script type="text/javascript" src="TextPrompt.js"></script> + <script type="text/javascript" src="Popup.js"></script> + <script type="text/javascript" src="Placard.js"></script> + <script type="text/javascript" src="View.js"></script> + <script type="text/javascript" src="Callback.js"></script> + <script type="text/javascript" src="Drawer.js"></script> + <script type="text/javascript" src="ChangesView.js"></script> + <script type="text/javascript" src="ConsoleView.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="CookieItemsView.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="ObjectProxy.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="WatchExpressionsSidebarPane.js"></script> + <script type="text/javascript" src="MetricsSidebarPane.js"></script> + <script type="text/javascript" src="PropertiesSidebarPane.js"></script> + <script type="text/javascript" src="Color.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="StatusBarButton.js"></script> + <script type="text/javascript" src="SummaryBar.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="StoragePanel.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> + <script type="text/javascript" src="DOMAgent.js"></script> + <script type="text/javascript" src="InjectedScript.js"></script> + <script type="text/javascript" src="InjectedScriptAccess.js"></script> + <script type="text/javascript" src="TimelineAgent.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" spellcheck="false"></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"><div class="glyph"></div><div class="glyph shadow"></div></button><button id="console-status-bar-item" class="status-bar-item"><div class="glyph"></div><div class="glyph shadow"></div></button><button id="changes-status-bar-item" class="status-bar-item hidden"></button><div id="count-items"><div id="changes-count" class="hidden"></div><div id="error-warning-count" class="hidden"></div></div></div></div> + </div> + <div id="drawer"> + <div id="console-view"><div id="console-messages"><div id="console-prompt" spellcheck="false"><br></div></div></div> + <div id="drawer-status-bar" class="status-bar"><div id="other-drawer-status-bar-items"><button id="clear-console-status-bar-item" class="status-bar-item"><div class="glyph"></div><div class="glyph shadow"></div></button><div id="console-filter" class="status-bar-item"></div></div></div> + </div> +</body> +</html> diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inspector.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inspector.js new file mode 100644 index 0000000..902dd94 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inspector.js @@ -0,0 +1,1553 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com). + * Copyright (C) 2009 Joseph Pecoraro + * + * 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, + heapProfilerPresent: false, + samplingCPUProfiler: false, + showColorNicknames: true, + colorFormat: "hex" +} + +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 = this._currentFocusElement.ownerDocument.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(); + } + } + } + + for (var panelName in WebInspector.panels) { + if (WebInspector.panels[panelName] == x) + InspectorController.storeLastActivePanel(panelName); + } + }, + + _createPanels: function() + { + 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("storage") === -1 && hiddenPanels.indexOf("databases") === -1) + this.panels.storage = new WebInspector.StoragePanel(); + }, + + 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 styleChanges() + { + return this._styleChanges; + }, + + set styleChanges(x) + { + x = Math.max(x, 0); + + if (this._styleChanges === x) + return; + this._styleChanges = x; + this._updateChangesCount(); + }, + + _updateChangesCount: function() + { + // TODO: Remove immediate return when enabling the Changes Panel + return; + + var changesElement = document.getElementById("changes-count"); + if (!changesElement) + return; + + if (!this.styleChanges) { + changesElement.addStyleClass("hidden"); + return; + } + + changesElement.removeStyleClass("hidden"); + changesElement.removeChildren(); + + if (this.styleChanges) { + var styleChangesElement = document.createElement("span"); + styleChangesElement.id = "style-changes-count"; + styleChangesElement.textContent = this.styleChanges; + changesElement.appendChild(styleChangesElement); + } + + if (this.styleChanges) { + if (this.styleChanges === 1) + changesElement.title = WebInspector.UIString("%d style change", this.styleChanges); + else + changesElement.title = WebInspector.UIString("%d style changes", this.styleChanges); + } + }, + + get hoveredDOMNode() + { + return this._hoveredDOMNode; + }, + + set hoveredDOMNode(x) + { + if (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.id); + this.showingDOMNodeHighlight = true; + } else { + InspectorController.hideDOMNodeHighlight(); + this.showingDOMNodeHighlight = false; + } + } +} + +WebInspector.loaded = function() +{ + var platform = InspectorController.platform(); + document.body.addStyleClass("platform-" + platform); + + var colorFormat = InspectorController.setting("color-format"); + if (colorFormat) + Preferences.colorFormat = colorFormat; + + this.drawer = new WebInspector.Drawer(); + this.console = new WebInspector.ConsoleView(this.drawer); + // TODO: Uncomment when enabling the Changes Panel + // this.changes = new WebInspector.ChangesView(this.drawer); + // TODO: Remove class="hidden" from inspector.html on button#changes-status-bar-item + this.drawer.visibleView = this.console; + this.domAgent = new WebInspector.DOMAgent(); + + 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.panels = {}; + this._createPanels(); + + var toolbarElement = document.getElementById("toolbar"); + var previousToolbarItem = toolbarElement.children[0]; + + this.panelOrder = []; + for (var panelName in this.panels) { + var panel = this.panels[panelName]; + var panelToolbarItem = panel.toolbarItem; + this.panelOrder.push(panel); + panelToolbarItem.addEventListener("click", this._toolbarItemClicked.bind(this)); + if (previousToolbarItem) + toolbarElement.insertBefore(panelToolbarItem, previousToolbarItem.nextSibling); + else + toolbarElement.insertBefore(panelToolbarItem, toolbarElement.firstChild); + previousToolbarItem = panelToolbarItem; + } + + 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); + document.addEventListener("contextmenu", this.contextMenu.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.showConsole.bind(this), false); + this._updateErrorAndWarningCounts(); + + this.styleChanges = 0; + // TODO: Uncomment when enabling the Changes Panel + // var changesElement = document.getElementById("changes-count"); + // changesElement.addEventListener("click", this.showChanges.bind(this), 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.drawer.visible = !this.drawer.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; + + case "U+005B": // [ key + if (isMac) + var isRotateLeft = event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey; + else + var isRotateLeft = event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey; + + if (isRotateLeft) { + var index = this.panelOrder.indexOf(this.currentPanel); + index = (index === 0) ? this.panelOrder.length - 1 : index - 1; + this.panelOrder[index].toolbarItem.click(); + event.preventDefault(); + } + + break; + + case "U+005D": // ] key + if (isMac) + var isRotateRight = event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey; + else + var isRotateRight = event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey; + + if (isRotateRight) { + var index = this.panelOrder.indexOf(this.currentPanel); + index = (index + 1) % this.panelOrder.length; + this.panelOrder[index].toolbarItem.click(); + 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.contextMenu = function(event) +{ + if (event.handled || event.target.hasStyleClass("popup-glasspane")) + event.preventDefault(); +} + +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; + var key = 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.drawer.showView(this.console); +} + +WebInspector.showChanges = function() +{ + this.drawer.showView(this.changes); +} + +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.showStoragePanel = function() +{ + this.currentPanel = this.panels.storage; +} + +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, + payload.requestMethod, + payload.requestFormData); + 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.clearConsoleMessages = function() +{ + WebInspector.console.clearMessages(false); +} + +WebInspector.selectDatabase = function(o) +{ + WebInspector.showStoragePanel(); + WebInspector.panels.storage.selectDatabase(o); +} + +WebInspector.selectDOMStorage = function(o) +{ + WebInspector.showStoragePanel(); + WebInspector.panels.storage.selectDOMStorage(o); +} + +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; + resource.requestMethod = payload.requestMethod; + resource.requestFormData = payload.requestFormData; + } + + 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.storage.addDatabase(database); +} + +WebInspector.addDOMStorage = function(payload) +{ + var domStorage = new WebInspector.DOMStorage( + payload.domStorage, + payload.host, + payload.isLocalStorage); + this.panels.storage.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(callFrames) +{ + this.panels.scripts.debuggerPaused(callFrames); +} + +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.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.type, + payload.level, + payload.line, + payload.url, + payload.groupLevel, + payload.repeatCount); + consoleMessage.setMessageBody(Array.prototype.slice.call(arguments, 1)); + this.console.addMessage(consoleMessage); +} + +WebInspector.log = function(message) +{ + var msg = new WebInspector.ConsoleMessage( + WebInspector.ConsoleMessage.MessageSource.Other, + WebInspector.ConsoleMessage.MessageType.Log, + WebInspector.ConsoleMessage.MessageLevel.Debug, + -1, + null, + null, + 1, + message); + this.console.addMessage(msg); +} + +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(nodeId) +{ + var node = WebInspector.domAgent.nodeForId(nodeId); + 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.addNodesToSearchResult = function(nodeIds) +{ + WebInspector.panels.elements.addNodesToSearchResult(nodeIds); +} + +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 = getContent(element); + var oldHandleKeyEvent = element.handleKeyEvent; + var moveDirection = ""; + + element.addStyleClass("editing"); + + var oldTabIndex = element.tabIndex; + if (element.tabIndex < 0) + element.tabIndex = 0; + + function blurEventListener() { + editingCommitted.call(element); + } + + function getContent(element) { + if (element.tagName === "INPUT" && element.type === "text") + return element.value; + else + return element.textContent; + } + + 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() { + if (this.tagName === "INPUT" && this.type === "text") + this.value = oldText; + else + this.textContent = oldText; + + cleanUpAfterEditing.call(this); + + if (cancelledCallback) + cancelledCallback(this, context); + } + + function editingCommitted() { + cleanUpAfterEditing.call(this); + + if (committedCallback) + committedCallback(this, getContent(this), oldText, context, moveDirection); + } + + 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; + } else if (event.keyIdentifier === "U+0009") // Tab key + moveDirection = (event.shiftKey ? "backward" : "forward"); + } + + 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_frame/tools/test/reference_build/chrome/resources/inspector/inspector_controller.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inspector_controller.js new file mode 100644 index 0000000..383cba4 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inspector_controller.js @@ -0,0 +1,506 @@ +// 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; + + /** + * @type {boolean} + */ + this.timelineEnabled_ = false; + + /** + * @type {Object} + */ + this.settings_ = {}; +}; + + +/** + * 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() { +}; + + +/** + * Tell host that the active panel has changed. + * @param {string} panel Panel name that was last active. + */ +devtools.InspectorController.prototype.storeLastActivePanel = function(panel) { +}; + + +/** + * 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 timeline. + */ +devtools.InspectorController.prototype.enableTimeline = function() { + this.timelineEnabled_ = true; + WebInspector.timelineWasEnabled(); +}; + + +/** + * Disables timeline. + */ +devtools.InspectorController.prototype.disableTimeline = function() { + this.timelineEnabled_ = false; + WebInspector.timelineWasDisabled(); +}; + +/** + * @return {boolean} True iff timeline is enabled. + */ +devtools.InspectorController.prototype.timelineEnabled = function() { + return this.timelineEnabled_; +}; + + +/** + * 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. + * @param {?string} condition The breakpoint condition. + */ +devtools.InspectorController.prototype.addBreakpoint = + function(sourceID, line, condition) { +}; + + +/** + * 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) { +}; + + +/** + * Sets a breakpoint condition given a line of the source and an ID. + * @param {string} sourceID Source Id to remove breakpoint from. + * @param {number} line Line number to remove breakpoint from. + * @param {?string} condition New breakpoint condition. + */ +devtools.InspectorController.prototype.updateBreakpoint = + function(sourceID, line, condition) { +}; + + +/** + * 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() { +}; + + +/** + * Sets a setting value in backend. + */ +devtools.InspectorController.prototype.setSetting = + function(setting, value) { + this.settings_[setting] = value; +}; + + +/** + * Retrieves a setting value stored in backend. + */ +devtools.InspectorController.prototype.setting = + function(setting) { + return this.settings_[setting]; +}; + + +var InspectorController = new devtools.InspectorController(); diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inspector_controller_impl.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inspector_controller_impl.js new file mode 100644 index 0000000..5bf19b7 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/inspector_controller_impl.js @@ -0,0 +1,286 @@ +// 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; + + this.installInspectorControllerDelegate_('clearMessages'); + this.installInspectorControllerDelegate_('storeLastActivePanel'); + this.installInspectorControllerDelegate_('highlightDOMNode'); + this.installInspectorControllerDelegate_('hideDOMNodeHighlight'); + this.installInspectorControllerDelegate_('getChildNodes'); + this.installInspectorControllerDelegate_('setAttribute'); + this.installInspectorControllerDelegate_('removeAttribute'); + this.installInspectorControllerDelegate_('setTextNodeValue'); + this.installInspectorControllerDelegate_('enableResourceTracking'); + this.installInspectorControllerDelegate_('disableResourceTracking'); + this.installInspectorControllerDelegate_('enableTimeline'); + this.installInspectorControllerDelegate_('disableTimeline'); + this.installInspectorControllerDelegate_('setting'); + this.installInspectorControllerDelegate_('setSetting'); +}; +goog.inherits(devtools.InspectorControllerImpl, + devtools.InspectorController); + + +/** + * {@inheritDoc}. + */ +devtools.InspectorControllerImpl.prototype.platform = function() { + return DevToolsHost.getPlatform(); +}; + + +/** + * {@inheritDoc}. + */ +devtools.InspectorControllerImpl.prototype.closeWindow = function() { + DevToolsHost.closeWindow(); +}; + + +/** + * {@inheritDoc}. + */ +devtools.InspectorControllerImpl.prototype.attach = function() { + DevToolsHost.dockWindow(); +}; + + +/** + * {@inheritDoc}. + */ +devtools.InspectorControllerImpl.prototype.detach = function() { + DevToolsHost.undockWindow(); +}; + + +/** + * {@inheritDoc}. + */ +devtools.InspectorControllerImpl.prototype.hiddenPanels = function() { + return 'databases'; +}; + + +/** + * {@inheritDoc}. + */ +devtools.InspectorControllerImpl.prototype.search = function(sourceRow, query) { + return DevToolsHost.search(sourceRow, query); +}; + + +/** + * {@inheritDoc}. + */ +devtools.InspectorControllerImpl.prototype.toggleNodeSearch = function() { + devtools.InspectorController.prototype.toggleNodeSearch.call(this); + DevToolsHost.toggleInspectElementMode(this.searchingForNode()); +}; + + +/** + * {@inheritDoc}. + */ +devtools.InspectorControllerImpl.prototype.localizedStringsURL = + function(opt_prefix) { + // l10n is turned off in test mode because delayed loading of strings + // causes test failures. + if (false) { + var locale = DevToolsHost.getApplicationLocale(); + locale = locale.replace('_', '-'); + return 'l10n/localizedStrings_' + locale + '.js'; + } else { + return undefined; + } +}; + + +/** + * {@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.inspectedWindow = function() { + return null; +}; + + +/** + * @override + */ +devtools.InspectorControllerImpl.prototype.debuggerEnabled = function() { + return true; +}; + + +devtools.InspectorControllerImpl.prototype.addBreakpoint = function( + sourceID, line, condition) { + devtools.tools.getDebuggerAgent().addBreakpoint(sourceID, line, condition); +}; + + +devtools.InspectorControllerImpl.prototype.removeBreakpoint = function( + sourceID, line) { + devtools.tools.getDebuggerAgent().removeBreakpoint(sourceID, line); +}; + +devtools.InspectorControllerImpl.prototype.updateBreakpoint = function( + sourceID, line, condition) { + devtools.tools.getDebuggerAgent().updateBreakpoint( + sourceID, line, condition); +}; + +devtools.InspectorControllerImpl.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( + devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_CPU); +}; + + +/** + * @override + */ +devtools.InspectorControllerImpl.prototype.stopProfiling = function() { + devtools.tools.getDebuggerAgent().stopProfiling( + devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_CPU); +}; + + +/** + * @override + */ +devtools.InspectorControllerImpl.prototype.evaluateInCallFrame = + function(callFrameId, code, callback) { + devtools.tools.getDebuggerAgent().evaluateInCallFrame(callFrameId, code, + callback); +}; + + +/** + * @override + */ +devtools.InspectorControllerImpl.prototype.dispatchOnInjectedScript = function( + callId, methodName, argsString) { + var callback = function(result, isException) { + WebInspector.didDispatchOnInjectedScript(callId, + isException ? result : JSON.parse(result), + isException); + }; + RemoteToolsAgent.ExecuteUtilityFunction( + devtools.Callback.wrap(callback), + 'InjectedScript', + JSON.stringify(['dispatch', methodName, argsString])); +}; + + +/** + * Installs delegating handler into the inspector controller. + * @param {string} methodName Method to install delegating handler for. + */ +devtools.InspectorControllerImpl.prototype.installInspectorControllerDelegate_ + = function(methodName) { + this[methodName] = goog.bind(this.callInspectorController_, this, + methodName); +}; + + +/** + * Bound function with the installInjectedScriptDelegate_ actual + * implementation. + */ +devtools.InspectorControllerImpl.prototype.callInspectorController_ = + function(methodName, var_arg) { + var args = Array.prototype.slice.call(arguments); + RemoteToolsAgent.ExecuteUtilityFunction( + devtools.Callback.wrap(function(){}), + 'InspectorController', JSON.stringify(args)); +}; + + +devtools.InspectorControllerImpl.parseWrap_ = function(callback) { + return devtools.Callback.wrap( + function(data) { + callback.call(this, JSON.parse(data)); + }); +}; + + +InspectorController = new devtools.InspectorControllerImpl(); diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/logreader.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/logreader.js new file mode 100644 index 0000000..88ab907 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/logreader.js @@ -0,0 +1,320 @@ +// 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. + +/** + * @fileoverview Log Reader is used to process log file produced by V8. + */ + +// Initlialize namespaces +var devtools = devtools || {}; +devtools.profiler = devtools.profiler || {}; + + +/** + * Base class for processing log files. + * + * @param {Array.<Object>} dispatchTable A table used for parsing and processing + * log records. + * @constructor + */ +devtools.profiler.LogReader = function(dispatchTable) { + /** + * @type {Array.<Object>} + */ + this.dispatchTable_ = dispatchTable; + this.dispatchTable_['alias'] = + { parsers: [null, null], processor: this.processAlias_ }; + this.dispatchTable_['repeat'] = + { parsers: [parseInt, 'var-args'], processor: this.processRepeat_, + backrefs: true }; + + /** + * A key-value map for aliases. Translates short name -> full name. + * @type {Object} + */ + this.aliases_ = {}; + + /** + * A key-value map for previous address values. + * @type {Object} + */ + this.prevAddresses_ = {}; + + /** + * A key-value map for events than can be backreference-compressed. + * @type {Object} + */ + this.backRefsCommands_ = {}; + this.initBackRefsCommands_(); + + /** + * Back references for decompression. + * @type {Array.<string>} + */ + this.backRefs_ = []; +}; + + +/** + * Creates a parser for an address entry. + * + * @param {string} addressTag Address tag to perform offset decoding. + * @return {function(string):number} Address parser. + */ +devtools.profiler.LogReader.prototype.createAddressParser = function( + addressTag) { + var self = this; + return (function (str) { + var value = parseInt(str, 16); + var firstChar = str.charAt(0); + if (firstChar == '+' || firstChar == '-') { + var addr = self.prevAddresses_[addressTag]; + addr += value; + self.prevAddresses_[addressTag] = addr; + return addr; + } else if (firstChar != '0' || str.charAt(1) != 'x') { + self.prevAddresses_[addressTag] = value; + } + return value; + }); +}; + + +/** + * Expands an alias symbol, if applicable. + * + * @param {string} symbol Symbol to expand. + * @return {string} Expanded symbol, or the input symbol itself. + */ +devtools.profiler.LogReader.prototype.expandAlias = function(symbol) { + return symbol in this.aliases_ ? this.aliases_[symbol] : symbol; +}; + + +/** + * Used for printing error messages. + * + * @param {string} str Error message. + */ +devtools.profiler.LogReader.prototype.printError = function(str) { + // Do nothing. +}; + + +/** + * Processes a portion of V8 profiler event log. + * + * @param {string} chunk A portion of log. + */ +devtools.profiler.LogReader.prototype.processLogChunk = function(chunk) { + this.processLog_(chunk.split('\n')); +}; + + +/** + * Processes stack record. + * + * @param {number} pc Program counter. + * @param {Array.<string>} stack String representation of a stack. + * @return {Array.<number>} Processed stack. + */ +devtools.profiler.LogReader.prototype.processStack = function(pc, stack) { + var fullStack = [pc]; + var prevFrame = pc; + for (var i = 0, n = stack.length; i < n; ++i) { + var frame = stack[i]; + var firstChar = frame.charAt(0); + if (firstChar == '+' || firstChar == '-') { + // An offset from the previous frame. + prevFrame += parseInt(frame, 16); + fullStack.push(prevFrame); + // Filter out possible 'overflow' string. + } else if (firstChar != 'o') { + fullStack.push(parseInt(frame, 16)); + } + } + return fullStack; +}; + + +/** + * Returns whether a particular dispatch must be skipped. + * + * @param {!Object} dispatch Dispatch record. + * @return {boolean} True if dispatch must be skipped. + */ +devtools.profiler.LogReader.prototype.skipDispatch = function(dispatch) { + return false; +}; + + +/** + * Does a dispatch of a log record. + * + * @param {Array.<string>} fields Log record. + * @private + */ +devtools.profiler.LogReader.prototype.dispatchLogRow_ = function(fields) { + // Obtain the dispatch. + var command = fields[0]; + if (!(command in this.dispatchTable_)) { + throw new Error('unknown command: ' + command); + } + var dispatch = this.dispatchTable_[command]; + + if (dispatch === null || this.skipDispatch(dispatch)) { + 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. + dispatch.processor.apply(this, parsedFields); +}; + + +/** + * Decompresses a line if it was backreference-compressed. + * + * @param {string} line Possibly compressed line. + * @return {string} Decompressed line. + * @private + */ +devtools.profiler.LogReader.prototype.expandBackRef_ = function(line) { + var backRefPos; + // Filter out case when a regexp is created containing '#'. + if (line.charAt(line.length - 1) != '"' + && (backRefPos = line.lastIndexOf('#')) != -1) { + var backRef = line.substr(backRefPos + 1); + var backRefIdx = parseInt(backRef, 10) - 1; + var colonPos = backRef.indexOf(':'); + var backRefStart = + colonPos != -1 ? parseInt(backRef.substr(colonPos + 1), 10) : 0; + line = line.substr(0, backRefPos) + + this.backRefs_[backRefIdx].substr(backRefStart); + } + this.backRefs_.unshift(line); + if (this.backRefs_.length > 10) { + this.backRefs_.length = 10; + } + return line; +}; + + +/** + * Initializes the map of backward reference compressible commands. + * @private + */ +devtools.profiler.LogReader.prototype.initBackRefsCommands_ = function() { + for (var event in this.dispatchTable_) { + var dispatch = this.dispatchTable_[event]; + if (dispatch && dispatch.backrefs) { + this.backRefsCommands_[event] = true; + } + } +}; + + +/** + * Processes alias log record. Adds an alias to a corresponding map. + * + * @param {string} symbol Short name. + * @param {string} expansion Long name. + * @private + */ +devtools.profiler.LogReader.prototype.processAlias_ = function( + symbol, expansion) { + if (expansion in this.dispatchTable_) { + this.dispatchTable_[symbol] = this.dispatchTable_[expansion]; + if (expansion in this.backRefsCommands_) { + this.backRefsCommands_[symbol] = true; + } + } else { + this.aliases_[symbol] = expansion; + } +}; + + +/** + * Processes log lines. + * + * @param {Array.<string>} lines Log lines. + * @private + */ +devtools.profiler.LogReader.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; + } + if (line.charAt(0) == '#' || + line.substr(0, line.indexOf(',')) in this.backRefsCommands_) { + line = this.expandBackRef_(line); + } + var fields = csvParser.parseLine(line); + this.dispatchLogRow_(fields); + } + } catch (e) { + // An error on the last line is acceptable since log file can be truncated. + if (i < n - 1) { + this.printError('line ' + (i + 1) + ': ' + (e.message || e)); + throw e; + } + } +}; + + +/** + * Processes repeat log record. Expands it according to calls count and + * invokes processing. + * + * @param {number} count Count. + * @param {Array.<string>} cmd Parsed command. + * @private + */ +devtools.profiler.LogReader.prototype.processRepeat_ = function(count, cmd) { + // Replace the repeat-prefixed command from backrefs list with a non-prefixed. + this.backRefs_[0] = cmd.join(','); + for (var i = 0; i < count; ++i) { + this.dispatchLogRow_(cmd); + } +}; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/profile.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/profile.js new file mode 100644 index 0000000..db4b542 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/profile.js @@ -0,0 +1,621 @@ +// 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 a library. + * + * @param {string} name Code entry name. + * @param {number} startAddr Starting address. + * @param {number} endAddr Ending address. + */ +devtools.profiler.Profile.prototype.addLibrary = function( + name, startAddr, endAddr) { + var entry = new devtools.profiler.CodeMap.CodeEntry( + endAddr - startAddr, name); + this.codeMap_.addLibrary(startAddr, entry); + return entry; +}; + + +/** + * Registers statically compiled 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_frame/tools/test/reference_build/chrome/resources/inspector/profile_view.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/profile_view.js new file mode 100644 index 0000000..bdea631 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/profiler_processor.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/profiler_processor.js new file mode 100644 index 0000000..13aeee7 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/profiler_processor.js @@ -0,0 +1,449 @@ +// 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+)( \{\d+\})?$/; + + +/** + * Inits 'functionName', 'url', and 'lineNumber' fields using 'internalFuncName' + * field. + * @private + */ +devtools.profiler.WebKitViewNode.prototype.initFuncInfo_ = function() { + var nodeAlias = devtools.profiler.WebKitViewNode; + this.functionName = this.internalFuncName; + + var strippedName = nodeAlias.FUNC_NAME_STRIP_RE.exec(this.functionName); + if (strippedName) { + this.functionName = strippedName[1]; + } + + var parsedName = nodeAlias.FUNC_NAME_PARSE_RE.exec(this.functionName); + if (parsedName) { + this.functionName = parsedName[1]; + if (parsedName[4]) { + this.functionName += parsedName[4]; + } + this.url = parsedName[2]; + this.lineNumber = parsedName[3]; + } else { + this.url = ''; + this.lineNumber = 0; + } +}; + + +/** + * Ancestor of a profile object that leaves out only JS-related functions. + * @constructor + */ +devtools.profiler.JsProfile = function() { + devtools.profiler.Profile.call(this); +}; +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/; + +/** + * RegExp that filters out devtools functions. See inject.js and + * inject_dispatch.js. + * @type {RegExp} + */ +devtools.profiler.JsProfile.JS_DEVTOOLS_FUNC_RE = + /^\w+:\ devtools(\$\$|\.Injected)/; + + +/** + * @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) || + devtools.profiler.JsProfile.JS_DEVTOOLS_FUNC_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() { + devtools.profiler.LogReader.call(this, { + 'code-creation': { + parsers: [null, this.createAddressParser('code'), parseInt, null], + processor: this.processCodeCreation_, backrefs: true, + needsProfile: true }, + 'code-move': { parsers: [this.createAddressParser('code'), + this.createAddressParser('code-move-to')], + processor: this.processCodeMove_, backrefs: true, + needsProfile: true }, + 'code-delete': { parsers: [this.createAddressParser('code')], + processor: this.processCodeDelete_, backrefs: true, + needsProfile: true }, + 'tick': { parsers: [this.createAddressParser('code'), + this.createAddressParser('stack'), parseInt, 'var-args'], + processor: this.processTick_, backrefs: true, needProfile: true }, + 'profiler': { parsers: [null, 'var-args'], + processor: this.processProfiler_, needsProfile: false }, + 'heap-sample-begin': { parsers: [null, null, parseInt], + processor: this.processHeapSampleBegin_ }, + 'heap-sample-stats': { parsers: [null, null, parseInt, parseInt], + processor: this.processHeapSampleStats_ }, + 'heap-sample-item': { parsers: [null, parseInt, parseInt], + processor: this.processHeapSampleItem_ }, + 'heap-js-cons-item': { parsers: [null, parseInt, parseInt], + processor: this.processHeapJsConsItem_ }, + 'heap-sample-end': { parsers: [null, null], + processor: this.processHeapSampleEnd_ }, + // Not used in DevTools Profiler. + 'shared-library': null, + 'heap-js-ret-item': null, + // Obsolete row types. + 'code-allocate': null, + 'begin-code-region': null, + 'end-code-region': null}); + + + /** + * Callback that is called when a new profile is encountered in the log. + * @type {function()} + */ + this.startedProfileProcessing_ = null; + + /** + * Callback that is called periodically to display processing status. + * @type {function()} + */ + this.profileProcessingStatus_ = null; + + /** + * Callback that is called when a profile has been processed and is ready + * to be shown. + * @type {function(devtools.profiler.ProfileView)} + */ + this.finishedProfileProcessing_ = null; + + /** + * The current profile. + * @type {devtools.profiler.JsProfile} + */ + this.currentProfile_ = null; + + /** + * Builder of profile views. Created during "profiler,begin" event processing. + * @type {devtools.profiler.WebKitViewBuilder} + */ + this.viewBuilder_ = null; + + /** + * Next profile id. + * @type {number} + */ + this.profileId_ = 1; + + /** + * Counter for processed ticks. + * @type {number} + */ + this.ticksCount_ = 0; + + /** + * The current heap snapshot. + * @type {string} + */ + this.currentHeapSnapshot_ = null; + + /** + * Next heap snapshot id. + * @type {number} + */ + this.heapSnapshotId_ = 1; +}; +goog.inherits(devtools.profiler.Processor, devtools.profiler.LogReader); + + +/** + * @override + */ +devtools.profiler.Processor.prototype.printError = function(str) { + debugPrint(str); +}; + + +/** + * @override + */ +devtools.profiler.Processor.prototype.skipDispatch = function(dispatch) { + return dispatch.needsProfile && this.currentProfile_ == null; +}; + + +/** + * Sets profile processing callbacks. + * + * @param {function()} started Started processing callback. + * @param {function(devtools.profiler.ProfileView)} finished Finished + * processing callback. + */ +devtools.profiler.Processor.prototype.setCallbacks = function( + started, processing, finished) { + this.startedProfileProcessing_ = started; + this.profileProcessingStatus_ = processing; + this.finishedProfileProcessing_ = finished; +}; + + +/** + * An address for the fake "(program)" entry. WebKit's visualisation + * has assumptions on how the top of the call tree should look like, + * and we need to add a fake entry as the topmost function. This + * address is chosen because it's the end address of the first memory + * page, which is never used for code or data, but only as a guard + * page for catching AV errors. + * + * @type {number} + */ +devtools.profiler.Processor.PROGRAM_ENTRY = 0xffff; +/** + * @type {string} + */ +devtools.profiler.Processor.PROGRAM_ENTRY_STR = '0xffff'; + + +/** + * Sets new profile callback. + * @param {function(devtools.profiler.ProfileView)} callback Callback function. + */ +devtools.profiler.Processor.prototype.setNewProfileCallback = function( + callback) { + this.newProfileCallback_ = callback; +}; + + +devtools.profiler.Processor.prototype.processProfiler_ = function( + state, params) { + var processingInterval = null; + switch (state) { + case 'resume': + if (this.currentProfile_ == null) { + this.currentProfile_ = new devtools.profiler.JsProfile(); + // see the comment for devtools.profiler.Processor.PROGRAM_ENTRY + this.currentProfile_.addCode( + 'Function', '(program)', + devtools.profiler.Processor.PROGRAM_ENTRY, 1); + if (this.startedProfileProcessing_) { + this.startedProfileProcessing_(); + } + this.ticksCount_ = 0; + var self = this; + if (this.profileProcessingStatus_) { + processingInterval = window.setInterval( + function() { self.profileProcessingStatus_(self.ticksCount_); }, + 1000); + } + } + break; + case 'pause': + if (this.currentProfile_ != null) { + window.clearInterval(processingInterval); + if (this.finishedProfileProcessing_) { + this.finishedProfileProcessing_(this.createProfileForView()); + } + this.currentProfile_ = null; + } + break; + case 'begin': + var samplingRate = NaN; + if (params.length > 0) { + samplingRate = parseInt(params[0]); + } + if (isNaN(samplingRate)) { + samplingRate = 1; + } + this.viewBuilder_ = new devtools.profiler.WebKitViewBuilder(samplingRate); + break; + // These events are valid but aren't used. + case 'compression': + case 'end': break; + default: + throw new Error('unknown profiler state: ' + state); + } +}; + + +devtools.profiler.Processor.prototype.processCodeCreation_ = function( + type, start, size, name) { + this.currentProfile_.addCode(this.expandAlias(type), name, start, size); +}; + + +devtools.profiler.Processor.prototype.processCodeMove_ = function(from, to) { + this.currentProfile_.moveCode(from, to); +}; + + +devtools.profiler.Processor.prototype.processCodeDelete_ = function(start) { + this.currentProfile_.deleteCode(start); +}; + + +devtools.profiler.Processor.prototype.processTick_ = function( + pc, sp, vmState, stack) { + // see the comment for devtools.profiler.Processor.PROGRAM_ENTRY + stack.push(devtools.profiler.Processor.PROGRAM_ENTRY_STR); + this.currentProfile_.recordTick(this.processStack(pc, stack)); + this.ticksCount_++; +}; + + +devtools.profiler.Processor.prototype.processHeapSampleBegin_ = function( + space, state, ticks) { + if (space != 'Heap') return; + this.currentHeapSnapshot_ = { + number: this.heapSnapshotId_++, + entries: {}, + lowlevels: {}, + ticks: ticks + }; +}; + + +devtools.profiler.Processor.prototype.processHeapSampleStats_ = function( + space, state, capacity, used) { + if (space != 'Heap') return; + this.currentHeapSnapshot_.capacity = capacity; + this.currentHeapSnapshot_.used = used; +}; + + +devtools.profiler.Processor.prototype.processHeapSampleItem_ = function( + item, number, size) { + if (!this.currentHeapSnapshot_) return; + this.currentHeapSnapshot_.lowlevels[item] = { + type: item, count: number, size: size + }; +}; + + +devtools.profiler.Processor.prototype.processHeapJsConsItem_ = function( + item, number, size) { + if (!this.currentHeapSnapshot_) return; + this.currentHeapSnapshot_.entries[item] = { + cons: item, count: number, size: size + }; +}; + + +devtools.profiler.Processor.prototype.processHeapSampleEnd_ = function( + space, state) { + if (space != 'Heap') return; + var snapshot = this.currentHeapSnapshot_; + this.currentHeapSnapshot_ = null; + // For some reason, 'used' from 'heap-sample-stats' sometimes differ from + // the sum of objects sizes. To avoid discrepancy, we re-calculate 'used'. + snapshot.used = 0; + for (var item in snapshot.lowlevels) { + snapshot.used += snapshot.lowlevels[item].size; + } + WebInspector.panels.heap.addSnapshot(snapshot); +}; + + +/** + * Creates a profile for further displaying in ProfileView. + */ +devtools.profiler.Processor.prototype.createProfileForView = function() { + var profile = this.viewBuilder_.buildView( + this.currentProfile_.getTopDownProfile()); + profile.uid = this.profileId_++; + profile.title = UserInitiatedProfileName + '.' + profile.uid; + return profile; +}; diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/splaytree.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/splaytree.js new file mode 100644 index 0000000..7b3af8b --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/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_frame/tools/test/reference_build/chrome/resources/inspector/tests.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/tests.js new file mode 100644 index 0000000..5691017 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/tests.js @@ -0,0 +1,628 @@ +// 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) { + +var ___interactiveUiTestsMode = true; + +/** + * Test suite for interactive UI tests. + * @constructor + */ +TestSuite = function() { + this.controlTaken_ = false; + this.timerId_ = -1; +}; + + +/** + * Reports test failure. + * @param {string} message Failure description. + */ +TestSuite.prototype.fail = function(message) { + if (this.controlTaken_) { + this.reportFailure_(message); + } else { + throw message; + } +}; + + +/** + * Equals assertion tests that expected == actual. + * @param {Object} expected Expected object. + * @param {Object} actual Actual object. + * @param {string} opt_message User message to print if the test fails. + */ +TestSuite.prototype.assertEquals = function(expected, actual, opt_message) { + if (expected != actual) { + var message = 'Expected: "' + expected + '", but was "' + actual + '"'; + if (opt_message) { + message = opt_message + '(' + message + ')'; + } + this.fail(message); + } +}; + + +/** + * True assertion tests that value == true. + * @param {Object} value Actual object. + * @param {string} opt_message User message to print if the test fails. + */ +TestSuite.prototype.assertTrue = function(value, opt_message) { + this.assertEquals(true, value, opt_message); +}; + + +/** + * Contains assertion tests that string contains substring. + * @param {string} string Outer. + * @param {string} substring Inner. + */ +TestSuite.prototype.assertContains = function(string, substring) { + if (string.indexOf(substring) == -1) { + this.fail('Expected to: "' + string + '" to contain "' + substring + '"'); + } +}; + + +/** + * Takes control over execution. + */ +TestSuite.prototype.takeControl = function() { + this.controlTaken_ = true; + // Set up guard timer. + var self = this; + this.timerId_ = setTimeout(function() { + self.reportFailure_('Timeout exceeded: 20 sec'); + }, 20000); +}; + + +/** + * Releases control over execution. + */ +TestSuite.prototype.releaseControl = function() { + if (this.timerId_ != -1) { + clearTimeout(this.timerId_); + this.timerId_ = -1; + } + this.reportOk_(); +}; + + +/** + * Async tests use this one to report that they are completed. + */ +TestSuite.prototype.reportOk_ = function() { + window.domAutomationController.send('[OK]'); +}; + + +/** + * Async tests use this one to report failures. + */ +TestSuite.prototype.reportFailure_ = function(error) { + if (this.timerId_ != -1) { + clearTimeout(this.timerId_); + this.timerId_ = -1; + } + window.domAutomationController.send('[FAILED] ' + error); +}; + + +/** + * Runs all global functions starting with 'test' as unit tests. + */ +TestSuite.prototype.runTest = function(testName) { + try { + this[testName](); + if (!this.controlTaken_) { + this.reportOk_(); + } + } catch (e) { + this.reportFailure_(e); + } +}; + + +/** + * @param {string} panelName Name of the panel to show. + */ +TestSuite.prototype.showPanel = function(panelName) { + // Open Scripts panel. + var toolbar = document.getElementById('toolbar'); + var button = toolbar.getElementsByClassName(panelName)[0]; + button.click(); + this.assertEquals(WebInspector.panels[panelName], + WebInspector.currentPanel); +}; + + +/** + * Overrides the method with specified name until it's called first time. + * @param {Object} receiver An object whose method to override. + * @param {string} methodName Name of the method to override. + * @param {Function} override A function that should be called right after the + * overriden method returns. + * @param {boolean} opt_sticky Whether restore original method after first run + * or not. + */ +TestSuite.prototype.addSniffer = function(receiver, methodName, override, + opt_sticky) { + var orig = receiver[methodName]; + if (typeof orig != 'function') { + this.fail('Cannot find method to override: ' + methodName); + } + var test = this; + receiver[methodName] = function(var_args) { + try { + var result = orig.apply(this, arguments); + } finally { + if (!opt_sticky) { + receiver[methodName] = orig; + } + } + // In case of exception the override won't be called. + try { + override.apply(this, arguments); + } catch (e) { + test.fail('Exception in overriden method "' + methodName + '": ' + e); + } + return result; + }; +}; + + +// UI Tests + + +/** + * Tests that the real injected host is present in the context. + */ +TestSuite.prototype.testHostIsPresent = function() { + this.assertTrue(typeof DevToolsHost == 'object' && !DevToolsHost.isStub); +}; + + +/** + * Tests elements tree has an 'HTML' root. + */ +TestSuite.prototype.testElementsTreeRoot = function() { + var doc = WebInspector.domAgent.document; + this.assertEquals('HTML', doc.documentElement.nodeName); + this.assertTrue(doc.documentElement.hasChildNodes()); +}; + + +/** + * Tests that main resource is present in the system and that it is + * the only resource. + */ +TestSuite.prototype.testMainResource = function() { + var tokens = []; + var resources = WebInspector.resources; + for (var id in resources) { + tokens.push(resources[id].lastPathComponent); + } + this.assertEquals('simple_page.html', tokens.join(',')); +}; + + +/** + * Tests that resources tab is enabled when corresponding item is selected. + */ +TestSuite.prototype.testEnableResourcesTab = function() { + this.showPanel('resources'); + + var test = this; + this.addSniffer(WebInspector, 'addResource', + function(identifier, payload) { + test.assertEquals('simple_page.html', payload.lastPathComponent); + WebInspector.panels.resources.refresh(); + WebInspector.resources[identifier]._resourcesTreeElement.select(); + + test.releaseControl(); + }); + + // Following call should lead to reload that we capture in the + // addResource override. + WebInspector.panels.resources._enableResourceTracking(); + + // We now have some time to report results to controller. + this.takeControl(); +}; + + +/** + * Tests resource headers. + */ +TestSuite.prototype.testResourceHeaders = function() { + this.showPanel('resources'); + + var test = this; + + var requestOk = false; + var responseOk = false; + var timingOk = false; + + this.addSniffer(WebInspector, 'addResource', + function(identifier, payload) { + var resource = this.resources[identifier]; + if (resource.mainResource) { + // We are only interested in secondary resources in this test. + return; + } + + var requestHeaders = JSON.stringify(resource.requestHeaders); + test.assertContains(requestHeaders, 'Accept'); + requestOk = true; + }, true); + + this.addSniffer(WebInspector, 'updateResource', + function(identifier, payload) { + var resource = this.resources[identifier]; + if (resource.mainResource) { + // We are only interested in secondary resources in this test. + return; + } + + if (payload.didResponseChange) { + var responseHeaders = JSON.stringify(resource.responseHeaders); + test.assertContains(responseHeaders, 'Content-type'); + test.assertContains(responseHeaders, 'Content-Length'); + test.assertTrue(typeof resource.responseReceivedTime != 'undefnied'); + responseOk = true; + } + + if (payload.didTimingChange) { + test.assertTrue(typeof resource.startTime != 'undefnied'); + timingOk = true; + } + + if (payload.didCompletionChange) { + test.assertTrue(requestOk); + test.assertTrue(responseOk); + test.assertTrue(timingOk); + test.assertTrue(typeof resource.endTime != 'undefnied'); + test.releaseControl(); + } + }, true); + + WebInspector.panels.resources._enableResourceTracking(); + this.takeControl(); +}; + + +/** + * Test that profiler works. + */ +TestSuite.prototype.testProfilerTab = function() { + this.showPanel('profiles'); + + var test = this; + this.addSniffer(WebInspector, 'addProfile', + function(profile) { + var panel = WebInspector.panels.profiles; + panel.showProfile(profile); + var node = panel.visibleView.profileDataGridTree.children[0]; + // Iterate over displayed functions and search for a function + // that is called 'fib' or 'eternal_fib'. If found, it will mean + // that we actually have profiled page's code. + while (node) { + if (node.functionName.indexOf('fib') != -1) { + test.releaseControl(); + } + node = node.traverseNextNode(true, null, true); + } + + test.fail(); + }); + var ticksCount = 0; + var tickRecord = '\nt,'; + this.addSniffer(RemoteDebuggerAgent, 'DidGetNextLogLines', + function(log) { + var pos = 0; + while ((pos = log.indexOf(tickRecord, pos)) != -1) { + pos += tickRecord.length; + ticksCount++; + } + if (ticksCount > 100) { + InspectorController.stopProfiling(); + } + }, true); + + InspectorController.startProfiling(); + this.takeControl(); +}; + + +/** + * Tests that scripts tab can be open and populated with inspected scripts. + */ +TestSuite.prototype.testShowScriptsTab = function() { + var parsedDebuggerTestPageHtml = false; + + // Intercept parsedScriptSource calls to check that all expected scripts are + // added to the debugger. + var test = this; + var receivedConsoleApiSource = false; + this.addSniffer(WebInspector, 'parsedScriptSource', + function(sourceID, sourceURL, source, startingLine) { + if (sourceURL == undefined) { + if (receivedConsoleApiSource) { + test.fail('Unexpected script without URL'); + } else { + receivedConsoleApiSource = true; + } + } else if (sourceURL.search(/debugger_test_page.html$/) != -1) { + if (parsedDebuggerTestPageHtml) { + test.fail('Unexpected parse event: ' + sourceURL); + } + parsedDebuggerTestPageHtml = true; + } else { + test.fail('Unexpected script URL: ' + sourceURL); + } + + if (!WebInspector.panels.scripts.visibleView) { + test.fail('No visible script view: ' + sourceURL); + } + + // There should be two scripts: one for the main page and another + // one which is source of console API(see + // InjectedScript._ensureCommandLineAPIInstalled). + if (parsedDebuggerTestPageHtml && receivedConsoleApiSource) { + test.releaseControl(); + } + }, true /* sticky */); + + this.showPanel('scripts'); + + // Wait until all scripts are added to the debugger. + this.takeControl(); +}; + + +/** + * Tests that a breakpoint can be set. + */ +TestSuite.prototype.testSetBreakpoint = function() { + var parsedDebuggerTestPageHtml = false; + var parsedDebuggerTestJs = false; + + this.showPanel('scripts'); + + var scriptUrl = null; + var breakpointLine = 12; + + var test = this; + var orig = devtools.DebuggerAgent.prototype.handleScriptsResponse_; + this.addSniffer(devtools.DebuggerAgent.prototype, 'handleScriptsResponse_', + function(msg) { + var scriptSelect = document.getElementById('scripts-files'); + var options = scriptSelect.options; + + // There should be console API source (see + // InjectedScript._ensureCommandLineAPIInstalled) and the page script. + test.assertEquals(2, options.length, 'Unexpected number of scripts.'); + + // Select page's script if it's not current option. + var scriptResource; + if (options[scriptSelect.selectedIndex].text == + 'debugger_test_page.html') { + scriptResource = + options[scriptSelect.selectedIndex].representedObject; + } else { + var pageScriptIndex = (1 - scriptSelect.selectedIndex); + test.assertEquals('debugger_test_page.html', + options[pageScriptIndex].text); + scriptResource = options[pageScriptIndex].representedObject; + // Current panel is 'Scripts'. + WebInspector.currentPanel._showScriptOrResource(scriptResource); + } + + test.assertTrue(scriptResource instanceof WebInspector.Resource, + 'Unexpected resource class.'); + test.assertTrue(!!scriptResource.url, 'Resource URL is null.'); + test.assertTrue( + scriptResource.url.search(/debugger_test_page.html$/) != -1, + 'Main HTML resource should be selected.'); + + // Store for access from setbreakpoint handler. + scriptUrl = scriptResource.url; + + var scriptsPanel = WebInspector.panels.scripts; + + var view = scriptsPanel.visibleView; + test.assertTrue(view instanceof WebInspector.SourceView); + + if (!view.sourceFrame._isContentLoaded()) { + test.addSniffer(view, '_sourceFrameSetupFinished', function(event) { + view._addBreakpoint(breakpointLine); + // Force v8 execution. + RemoteToolsAgent.ExecuteVoidJavaScript(); + }); + } else { + view._addBreakpoint(breakpointLine); + // Force v8 execution. + RemoteToolsAgent.ExecuteVoidJavaScript(); + } + }); + + this.addSniffer( + devtools.DebuggerAgent.prototype, + 'handleSetBreakpointResponse_', + function(msg) { + var bps = this.urlToBreakpoints_[scriptUrl]; + test.assertTrue(!!bps, 'No breakpoints for line ' + breakpointLine); + var line = devtools.DebuggerAgent.webkitToV8LineNumber_(breakpointLine); + test.assertTrue(!!bps[line].getV8Id(), + 'Breakpoint id was not assigned.'); + test.releaseControl(); + }); + + this.takeControl(); +}; + + +/** + * Tests 'Pause' button will pause debugger when a snippet is evaluated. + */ +TestSuite.prototype.testPauseInEval = function() { + this.showPanel('scripts'); + + var test = this; + + var pauseButton = document.getElementById('scripts-pause'); + pauseButton.click(); + + devtools.tools.evaluateJavaScript('fib(10)'); + + this.addSniffer(WebInspector, 'pausedScript', + function() { + test.releaseControl(); + }); + + test.takeControl(); +}; + + +/** + * Key event with given key identifier. + */ +TestSuite.KeyEvent = function(key) { + this.keyIdentifier = key; +}; +TestSuite.KeyEvent.prototype.preventDefault = function() {}; +TestSuite.KeyEvent.prototype.stopPropagation = function() {}; + + +/** + * Tests console eval. + */ +TestSuite.prototype.testConsoleEval = function() { + WebInspector.console.visible = true; + WebInspector.console.prompt.text = '123'; + WebInspector.console.promptElement.handleKeyEvent( + new TestSuite.KeyEvent('Enter')); + + var test = this; + this.addSniffer(WebInspector.ConsoleView.prototype, 'addMessage', + function(commandResult) { + test.assertEquals('123', commandResult.toMessageElement().textContent); + test.releaseControl(); + }); + + this.takeControl(); +}; + + +/** + * Tests console log. + */ +TestSuite.prototype.testConsoleLog = function() { + WebInspector.console.visible = true; + var messages = WebInspector.console.messages; + var index = 0; + + var test = this; + var assertNext = function(line, message, opt_class, opt_count, opt_substr) { + var elem = messages[index++].toMessageElement(); + var clazz = elem.getAttribute('class'); + var expectation = (opt_count || '') + 'console_test_page.html:' + + line + message; + if (opt_substr) { + test.assertContains(elem.textContent, expectation); + } else { + test.assertEquals(expectation, elem.textContent); + } + if (opt_class) { + test.assertContains(clazz, 'console-' + opt_class); + } + }; + + assertNext('5', 'log', 'log-level'); + assertNext('7', 'debug', 'log-level'); + assertNext('9', 'info', 'log-level'); + assertNext('11', 'warn', 'warning-level'); + assertNext('13', 'error', 'error-level'); + assertNext('15', 'Message format number 1, 2 and 3.5'); + assertNext('17', 'Message format for string'); + assertNext('19', 'Object Object'); + assertNext('22', 'repeated', 'log-level', 5); + assertNext('26', 'count: 1'); + assertNext('26', 'count: 2'); + assertNext('29', 'group', 'group-title'); + index++; + assertNext('33', 'timer:', 'log-level', '', true); +}; + + +/** + * Tests eval of global objects. + */ +TestSuite.prototype.testEvalGlobal = function() { + WebInspector.console.visible = true; + WebInspector.console.prompt.text = 'foo'; + WebInspector.console.promptElement.handleKeyEvent( + new TestSuite.KeyEvent('Enter')); + + var test = this; + this.addSniffer(WebInspector.ConsoleView.prototype, 'addMessage', + function(commandResult) { + test.assertEquals('fooValue', + commandResult.toMessageElement().textContent); + test.releaseControl(); + }); + + this.takeControl(); +}; + + +/** + * Tests eval on call frame. + */ +TestSuite.prototype.testEvalCallFrame = function() { +}; + + +/** + * Test runner for the test suite. + */ +var uiTests = {}; + + +/** + * Run each test from the test suit on a fresh instance of the suite. + */ +uiTests.runAllTests = function() { + // For debugging purposes. + for (var name in TestSuite.prototype) { + if (name.substring(0, 4) == 'test' && + typeof TestSuite.prototype[name] == 'function') { + uiTests.runTest(name); + } + } +}; + + +/** + * Run specified test on a fresh instance of the test suite. + * @param {string} name Name of a test method from TestSuite class. + */ +uiTests.runTest = function(name) { + new TestSuite().runTest(name); +}; + + +} diff --git a/chrome_frame/tools/test/reference_build/chrome/resources/inspector/treeoutline.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/treeoutline.js new file mode 100644 index 0000000..ecc322b --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/treeoutline.js @@ -0,0 +1,849 @@ +/* + * 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.getCachedTreeElement = function(representedObject) +{ + if (!representedObject) + return null; + + 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 (elements[i].representedObject === representedObject) + return elements[i]; + } + } + return null; +} + +TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent) +{ + if (!representedObject) + return null; + + var cachedElement = this.getCachedTreeElement(representedObject); + if (cachedElement) + return cachedElement; + + // 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 (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 (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 (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); + if (item && item.onpopulate) + item.onpopulate(item); + } + + return this.getCachedTreeElement(representedObject); +} + +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_frame/tools/test/reference_build/chrome/resources/inspector/utilities.js b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/utilities.js new file mode 100644 index 0000000..e831abd --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/resources/inspector/utilities.js @@ -0,0 +1,905 @@ +/* + * 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.proxyType = function(objectProxy) +{ + if (objectProxy === null) + return "null"; + + var type = typeof objectProxy; + if (type !== "object" && type !== "function") + return type; + + return objectProxy.type; +} + +Object.properties = function(obj) +{ + var properties = []; + for (var prop in obj) + properties.push(prop); + return properties; +} + +Object.sortedProperties = function(obj, sortFunc) +{ + return Object.properties(obj).sort(sortFunc); +} + +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); +} + +Element.prototype.positionAt = function(x, y) +{ + this.style.left = x + "px"; + this.style.top = y + "px"; +} + +Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray) +{ + for (var node = this; node && 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 && 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.offsetRelativeToWindow = function(targetWindow) +{ + var elementOffset = {x: 0, y: 0}; + var curElement = this; + var curWindow = this.ownerDocument.defaultView; + while (curWindow && curElement) { + elementOffset.x += curElement.totalOffsetLeft; + elementOffset.y += curElement.totalOffsetTop; + if (curWindow === targetWindow) + break; + + curElement = curWindow.frameElement; + curWindow = curWindow.parent; + } + + return elementOffset; +} + +Element.prototype.firstChildSkippingWhitespace = firstChildSkippingWhitespace; +Element.prototype.lastChildSkippingWhitespace = lastChildSkippingWhitespace; + +Node.prototype.isWhitespace = isNodeWhitespace; +Node.prototype.displayName = nodeDisplayName; +Node.prototype.isAncestor = function(node) +{ + return isAncestorNode(this, node); +}; +Node.prototype.isDescendant = isDescendantNode; +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, "&").replace(/</g, "<").replace(/>/g, ">"); +} + +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 isNodeWhitespace() +{ + if (!this || this.nodeType !== Node.TEXT_NODE) + return false; + if (!this.nodeValue.length) + return true; + return this.nodeValue.match(/^[\s\xA0]+$/); +} + +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 isAncestorNode(ancestor, node) +{ + if (!node || !ancestor) + return false; + + var currentNode = node.parentNode; + while (currentNode) { + if (ancestor === currentNode) + return true; + currentNode = currentNode.parentNode; + } + return false; +} + +function isDescendantNode(descendant) +{ + return isAncestorNode(descendant, this); +} + +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 && 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 || 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 && 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\"><" + 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>=​\""; + + 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​"); + info.title += "<span class=\"webkit-html-attribute-value\">" + value + "</span>"; + } + info.title += "\"</span>"; + } + } + info.title += "></span>​"; + + // 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>​<span class=\"webkit-html-tag\"></" + this.nodeName.toLowerCase().escapeHTML() + "></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\"><!--" + this.nodeValue.escapeHTML() + "--></span>"; + break; + + case Node.DOCUMENT_TYPE_NODE: + info.title = "<span class=\"webkit-html-doctype\"><!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 += "></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 parentNode(node) { + return node.parentNode; +} + +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, higherResolution) +{ + if (!formatterFunction) + formatterFunction = String.sprintf; + if (typeof higherResolution === "undefined") + higherResolution = true; + + if (bytes < 1024) + return formatterFunction("%.0fB", bytes); + + var kilobytes = bytes / 1024; + if (higherResolution && kilobytes < 1024) + return formatterFunction("%.2fKB", kilobytes); + else if (kilobytes < 1024) + return formatterFunction("%.0fKB", kilobytes); + + var megabytes = kilobytes / 1024; + if (higherResolution) + return formatterFunction("%.3fMB", megabytes); + else + return formatterFunction("%.0fMB", 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_frame/tools/test/reference_build/chrome/servers/chrome_launcher.exe b/chrome_frame/tools/test/reference_build/chrome/servers/chrome_launcher.exe Binary files differnew file mode 100644 index 0000000..a979e1b --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/servers/chrome_launcher.exe diff --git a/chrome_frame/tools/test/reference_build/chrome/servers/chrome_launcher.pdb b/chrome_frame/tools/test/reference_build/chrome/servers/chrome_launcher.pdb Binary files differnew file mode 100644 index 0000000..aaa155a --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/servers/chrome_launcher.pdb diff --git a/chrome_frame/tools/test/reference_build/chrome/servers/npchrome_tab.dll b/chrome_frame/tools/test/reference_build/chrome/servers/npchrome_tab.dll Binary files differnew file mode 100644 index 0000000..f7eca43 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/servers/npchrome_tab.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/servers/npchrome_tab.pdb b/chrome_frame/tools/test/reference_build/chrome/servers/npchrome_tab.pdb Binary files differnew file mode 100644 index 0000000..6326dce --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/servers/npchrome_tab.pdb diff --git a/chrome_frame/tools/test/reference_build/chrome/setup.pdb b/chrome_frame/tools/test/reference_build/chrome/setup.pdb Binary files differnew file mode 100644 index 0000000..046e7a1 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/setup.pdb diff --git a/chrome_frame/tools/test/reference_build/chrome/syncapi.dll b/chrome_frame/tools/test/reference_build/chrome/syncapi.dll Binary files differnew file mode 100644 index 0000000..e3f7e31 --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/syncapi.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/themes/default.dll b/chrome_frame/tools/test/reference_build/chrome/themes/default.dll Binary files differnew file mode 100644 index 0000000..0261aac --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/themes/default.dll diff --git a/chrome_frame/tools/test/reference_build/chrome/wow_helper.exe b/chrome_frame/tools/test/reference_build/chrome/wow_helper.exe Binary files differnew file mode 100644 index 0000000..f9bfb4b --- /dev/null +++ b/chrome_frame/tools/test/reference_build/chrome/wow_helper.exe |