├── .eslintignore
├── .eslintrc
├── .gitignore
├── .jpmignore
├── .jshintrc
├── .travis.yml
├── README.md
├── chrome.manifest
├── chrome
├── content
│ ├── connections-window.xul
│ └── inspector-window.xul
├── icons
│ └── default
│ │ └── rdpinspectorconsole.ico
├── locale
│ ├── en-US
│ │ ├── connections.properties
│ │ ├── inspector.properties
│ │ └── toolbox.properties
│ ├── nl
│ │ ├── inspector.properties
│ │ └── toolbox.properties
│ ├── pt-BR
│ │ ├── inspector.properties
│ │ └── toolbox.properties
│ └── zh-CN
│ │ ├── inspector.properties
│ │ └── toolbox.properties
└── skin
│ └── classic
│ └── shared
│ ├── icon16.png
│ ├── icon32.png
│ ├── icon32.svg
│ ├── icon64.png
│ └── search.svg
├── data
├── .eslintrc
├── connection-list
│ ├── actions.js
│ ├── components
│ │ └── connection-list.js
│ ├── config.js
│ ├── containers
│ │ └── main-panel.js
│ ├── css
│ │ └── connection-list.css
│ ├── index.html
│ ├── index.js
│ ├── reducers.js
│ └── store.js
├── inspector
│ ├── actions
│ │ ├── actors.js
│ │ ├── global.js
│ │ ├── index.js
│ │ └── packets.js
│ ├── components
│ │ ├── actors-panel.js
│ │ ├── actors-toolbar.js
│ │ ├── factories.js
│ │ ├── main-tabbed-area.js
│ │ ├── packet-details.js
│ │ ├── packet-editor.js
│ │ ├── packet-list.js
│ │ ├── packet-stack-sidepanel.js
│ │ ├── packet.js
│ │ ├── packets-limit.js
│ │ ├── packets-message.js
│ │ ├── packets-panel.js
│ │ ├── packets-sidebar.js
│ │ ├── packets-summary.js
│ │ ├── packets-toolbar.js
│ │ ├── pools.js
│ │ ├── search-box.js
│ │ ├── stack-frame-rep.js
│ │ ├── text-with-tooltip.js
│ │ └── tree-editor-view.js
│ ├── config.js
│ ├── containers
│ │ └── app.js
│ ├── css
│ │ ├── actors-panel.css
│ │ ├── base.css
│ │ ├── packets-panel.css
│ │ ├── search-box.css
│ │ ├── toolbar.css
│ │ ├── toolbox.css
│ │ └── tree-editor-view.css
│ ├── frame-script.js
│ ├── main.html
│ ├── main.js
│ ├── reducers
│ │ ├── actors.js
│ │ ├── global.js
│ │ ├── index.js
│ │ └── packets.js
│ ├── res
│ │ ├── arrow.svg
│ │ ├── icon-16.png
│ │ ├── received-arrow-selected.png
│ │ ├── received-arrow.png
│ │ ├── sent-arrow-selected.png
│ │ └── sent-arrow.png
│ ├── search.js
│ └── store.js
├── lib
│ ├── bootstrap
│ │ ├── css
│ │ │ └── bootstrap.css
│ │ ├── fonts
│ │ │ ├── glyphicons-halflings-regular.eot
│ │ │ ├── glyphicons-halflings-regular.svg
│ │ │ ├── glyphicons-halflings-regular.ttf
│ │ │ ├── glyphicons-halflings-regular.woff
│ │ │ └── glyphicons-halflings-regular.woff2
│ │ └── js
│ │ │ └── bootstrap.js
│ ├── immutable
│ │ └── immutable.js
│ ├── jquery
│ │ └── jquery.js
│ ├── react-bootstrap
│ │ └── react-bootstrap.js
│ ├── react
│ │ ├── react-dom.js
│ │ └── react.js
│ ├── redux
│ │ ├── react-redux.js
│ │ └── redux.js
│ └── requirejs
│ │ └── require.js
└── shared
│ ├── rdp-inspector-window.js
│ ├── react-bootstrap-factories.js
│ ├── react-helpers.js
│ └── resizer.js
├── index.js
├── karma-tests
├── .eslintrc
├── components
│ ├── actors-panel-spec.js
│ ├── main-tabbed-area-spec.js
│ ├── packet-spec.js
│ ├── packets-panel-spec.js
│ ├── packets-sidebar-spec.js
│ └── packets-toolbar-spec.js
├── custom-react-matchers.js
├── lib
│ ├── firebug-sdk-shims.js
│ └── react-with-addons.js
└── test-main.js
├── karma.conf.js
├── lib
├── .eslintrc
├── connection-list-window.js
├── inspector-actor.js
├── inspector-front.js
├── inspector-service.js
├── inspector-window.js
├── main.js
├── start-button.js
├── toolbox-overlay.js
├── transport-observer.js
└── webide-connections-monitor.js
├── package.json
└── test
├── .eslintrc
└── test-inspector-service.js
/.eslintignore:
--------------------------------------------------------------------------------
1 | coverage/
2 | data/lib/
3 | karma-tests/lib/
4 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "indent": [2, 2], // check 2 space indentation
4 | "no-mixed-spaces-and-tabs": [2],
5 | "quotes": [2, "double"],
6 | "semi": [1, "always"],
7 |
8 | // disabled rule which enforce unix or windows line breaks
9 | "linebreak-style": [0],
10 |
11 | // disabled comma-dangle is safe for our use case
12 | "comma-dangle": [0],
13 |
14 | // disabled eqeqeq and no-use-before-define are safe if you use them correctly
15 | "eqeqeq": [0],
16 | "no-use-before-define": [0],
17 | },
18 | "env": {
19 | "es6": true
20 | },
21 | "globals": {
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Junk that could exist anywhere:
3 | .DS_Store
4 | *.swp
5 | *.tmp
6 | .*.gz
7 | *.patch
8 | *~
9 |
10 | # Temporary files created by Eclipse
11 | .tmp*
12 |
13 | # Editor junk
14 | *.project
15 | /.pydevproject
16 | /.settings/
17 | /.settings.xml
18 | /.settings.xml.old
19 | /.idea/
20 | *.iws
21 | *.ids
22 | *.iml
23 | *.ipr
24 |
25 | # Build Files
26 | /build/
27 | /release/
28 | *.graphml
29 | *.xpi
30 |
31 | # Files from NPM
32 | /node_modules/
33 |
34 | # Extensions
35 | /firebug@software.joehewitt.com
36 |
37 | # Bash
38 | *.sh
39 | *.bat
40 |
41 | # code coverage logs & reports
42 | /coverage/
43 |
44 | bootstrap.js
45 | install.rdf
46 | npm-debug.log
47 |
--------------------------------------------------------------------------------
/.jpmignore:
--------------------------------------------------------------------------------
1 | # Doc Files
2 | /docs/
3 | README.md
4 |
5 | # Test Files
6 | /test/
7 |
8 | karma.conf.js
9 | /karma-tests/
10 |
11 | # GIT
12 | /.git/
13 |
14 | # exclude hidden files
15 | .*
16 |
17 | # Existing packages
18 | *.xpi
19 |
20 | # npm debug log file
21 | npm-debug.log
22 |
23 | # Excludes npm devDependecies
24 | /node_modules/
25 |
26 | # Includes firebug.sdk
27 | !/node_modules/firebug.sdk
28 |
29 | # Code Coverage logs & reports
30 | /coverage/
31 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "esnext": "true",
3 | "predef": [ "require", "exports", "module" ],
4 | "curly": "true"
5 | }
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: node_js
3 | node_js:
4 | - "0.10"
5 | env:
6 | ## Firefox Developer Edition
7 | - FIREFOX_VERSION=aurora-latest
8 | - FIREFOX_VERSION=fx-team
9 |
10 | before_install:
11 | - "export DISPLAY=:99.0"
12 | - "sh -e /etc/init.d/xvfb start"
13 | - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 -extension RANDR"
14 | - npm install -g npm
15 | - npm --version
16 |
17 | before_script:
18 | - npm install jpm -g
19 | - '( [[ "$FIREFOX_VERSION" = "fx-team" ]] && npm install mozilla-download -g && mozilla-download --branch fx-team --product firefox $TRAVIS_BUILD_DIR/../ ) || echo "Building on release $FIREFOX_VERSION"'
20 | - '( [[ "$FIREFOX_VERSION" != "fx-team" ]] && wget "https://download.mozilla.org/?product=firefox-$FIREFOX_VERSION-ssl&os=linux64&lang=en-US" -O $TRAVIS_BUILD_DIR/../firefox.tar.bz2 && cd $TRAVIS_BUILD_DIR/../ && tar xvf firefox.tar.bz2 ) || echo "Building on release $FIREFOX_VERSION"'
21 | - cd $TRAVIS_BUILD_DIR
22 |
23 | script:
24 | - export JPM_FIREFOX_BINARY=$TRAVIS_BUILD_DIR/../firefox/firefox
25 | - export FIREFOX_BIN=$JPM_FIREFOX_BINARY
26 | - npm run travis-ci
27 | - npm run jpm-tests
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | RDP Inspector
2 | =============
3 | Remote debugger protocol inspector
4 |
5 | Instructions
6 | ------------
7 | You should see a new RDP Inspector button at the top-right corner of your
8 | browser window after installation. Click the icon to open RDP Inspector
9 | console and operate developer tools Toolbox to generate some traffic
10 | over RDP. Sent and received packets are visible in the console window.
11 |
12 | * [Learn more](https://github.com/firebug/rdp-inspector/wiki)
13 | * [Download](https://github.com/firebug/rdp-inspector/releases)
14 |
15 | Further Resources
16 | -----------------
17 | * Remote Debugging Protocol: https://wiki.mozilla.org/Remote_Debugging_Protocol
18 | * Add-on SDK: https://developer.mozilla.org/en-US/Add-ons/SDK
19 | * DevTools API: https://developer.mozilla.org/en-US/docs/Tools/DevToolsAPI
20 | * Coding Style: https://github.com/mozilla/addon-sdk/wiki/Coding-style-guide
21 | * DevTools Extension Examples: https://github.com/firebug/devtools-extension-examples
22 | * DevTools/Hacking: https://wiki.mozilla.org/DevTools/Hacking
23 |
--------------------------------------------------------------------------------
/chrome.manifest:
--------------------------------------------------------------------------------
1 | content rdpinspector chrome/content/
2 | skin rdpinspector classic/1.0 chrome/skin/classic/shared/
3 | skin rdpinspector-firebug.sdk classic/1.0 node_modules/firebug.sdk/skin/classic/shared/
4 |
5 | locale rdpinspector en-US chrome/locale/en-US/
6 | locale rdpinspector zh-CN chrome/locale/zh-CN/
7 | locale rdpinspector nl chrome/locale/nl/
8 | locale rdpinspector pt-BR chrome/locale/pt-BR/
9 |
10 | locale rdpinspector-firebug.sdk en-US node_modules/firebug.sdk/locale/en-US/
11 | locale rdpinspector-firebug.sdk zh-CN node_modules/firebug.sdk/locale/zh-CN/
12 | locale rdpinspector-firebug.sdk nl node_modules/firebug.sdk/locale/nl/
13 | locale rdpinspector-firebug.sdk pt-BR node_modules/firebug.sdk/locale/pt-BR/
14 |
--------------------------------------------------------------------------------
/chrome/content/connections-window.xul:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
15 |
16 |
17 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/chrome/content/inspector-window.xul:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
46 |
47 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/chrome/icons/default/rdpinspectorconsole.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebug/rdp-inspector/60b22d880d9ea334e638b14c69102e8ed5c5c1e6/chrome/icons/default/rdpinspectorconsole.ico
--------------------------------------------------------------------------------
/chrome/locale/en-US/connections.properties:
--------------------------------------------------------------------------------
1 | # LOCALIZATION NOTE (rdpConnections.tab.LocalTabs, rdpConnections.tab.WebIDE)
2 | # A label for "Connect To..." window tabs.
3 | rdpConnections.tab.LocalTabs=Local Tabs
4 | rdpConnections.tab.WebIDE=WebIDE
5 |
--------------------------------------------------------------------------------
/chrome/locale/en-US/inspector.properties:
--------------------------------------------------------------------------------
1 | # LOCALIZATION NOTE (rdpInspector.tab.Packets, rdpInspector.tab.Actors)
2 | # A label for main application tabs.
3 | rdpInspector.tab.Packets=Packets
4 | rdpInspector.tab.Actors=Actors
5 |
6 | # LOCALIZATION NOTE (rdpInspector.option.showInlineDetails,
7 | # rdpInspector.option.showInlineDetails): Label and
8 | # tooltip for an option that can be set within the Packets tab. If set to true
9 | # every packet display inline preview of packet properties (collapsed
10 | # by default)
11 | rdpInspector.option.showInlineDetails=Show Packet Details Inline
12 | rdpInspector.option.showInlineDetails.tip=Show a detailed tree view of the Packet content.
13 |
14 | # LOCALIZATION NOTE (rdpInspector.option.packetCacheEnabled, rdpInspector.options.packetCacheEnabled.tip): Label and
15 | # tooltip for an option that can be set within the Packets tab. If set to true
16 | # the inspector caches packets that are sent/received before the
17 | # inspector window is opened (to see also packets that happens
18 | # at the very beginning)
19 | rdpInspector.option.packetCacheEnabled=Packet Cache
20 | rdpInspector.option.packetCacheEnabled.tip=Store packets in a cache before the console is opened.
21 |
22 | # LOCALIZATION NOTE (rdpInspector.cmd.clear): Label for a toolbar button
23 | # in the Packets tab. This command clears the packet list.
24 | rdpInspector.cmd.clear=Clear
25 |
26 | # LOCALIZATION NOTE (rdpInspector.cmd.find): Label for a toolbar button
27 | # in the Packets tab. This command opens standard Find bar at the bottom
28 | # of the Inspector window.
29 | rdpInspector.cmd.find=Find
30 |
31 | # LOCALIZATION NOTE (rdpInspector.cmd.summary): Label for a toolbar button
32 | # in the Packets tab. This command inserts a summary separator in the
33 | # packets list.
34 | rdpInspector.cmd.summary=Summary
35 |
36 | # LOCALIZATION NOTE (rdpInspector.tooltip.sizeSent, rdpInspector.tooltip.sizeReceived,
37 | # rdpInspector.tooltip.packetsSent, rdpInspector.tooltip.packetsReceived):
38 | # A tooltip for summary info in the packet list.
39 | rdpInspector.tooltip.sizeSent=Total amount of data sent to the debugger server
40 | rdpInspector.tooltip.sizeReceived=Total amount of data received from the debugger server
41 | rdpInspector.tooltip.packetsSent=Number of packets sent to the debugger server
42 | rdpInspector.tooltip.packetsReceived=Number of packets received from the debugger server
43 |
44 | # LOCALIZATION NOTE (rdpInspector.label.packets, rdpInspector.label.data)
45 | # A label for summary info in the packet list.
46 | rdpInspector.label.packets=Packets
47 | rdpInspector.label.data=Data
48 |
49 | # LOCALIZATION NOTE (rdpInspector.cmd.refresh) A label used on Actor's
50 | # tab toolbar. It's used to refresh the tab's content.
51 | rdpInspector.cmd.refresh=Refresh
52 |
53 | # LOCALIZATION NOTE (rdpInspector.label.sent, rdpInspector.label.to,
54 | # rdpInspector.label.received, rdpInspector.label.from): A label for
55 | # packets displayed in the packet list.
56 | rdpInspector.label.sent=Sent
57 | rdpInspector.label.to=to
58 | rdpInspector.label.received=Received
59 | rdpInspector.label.from=from
60 |
61 | # LOCALIZATION NOTE (rdpInspector.label.outOfLimit) A label displayed
62 | # at the top of the packet list in case the number of displayed packets
63 | # reached maximum limit.
64 | rdpInspector.label.outOfLimit=packets removed
65 |
66 | # LOCALIZATION NOTE (rdpInspector.label.Paused, rdpInspector.label.Unpaused):
67 | # A label used for pause/unpause packet collecting. The label is for a message
68 | # that is printed into the packet list when the user click the Pause button
69 | # in the toolbar.
70 | rdpInspector.label.Paused=Paused
71 | rdpInspector.label.Unpaused=Unpaused
72 |
73 | # LOCALIZATION NOTE (rdpInspector.label.MainProcess, rdpInspector.label.ChildProcess,
74 | # rdpInspector.ActorsFactories):
75 | # Labels used for the actors sub-panel selector in the actors panel toolbar.
76 | rdpInspector.label.MainProcess=Main Process
77 | rdpInspector.label.ChildProcess=Child Process
78 | rdpInspector.label.ActorsFactories=Actors Factories
79 |
80 | # LOCALIZATION NOTE (rdpInspector.menu.File, rdpInspector.menu.Options,
81 | # rdpInspector.cmd.load, rdpInspector.cmd.save):
82 | # Labels for the dropdown menus in the packets panel toolbar.
83 | rdpInspector.menu.File=File
84 | rdpInspector.menu.Options=Options
85 | rdpInspector.cmd.load=Load
86 | rdpInspector.cmd.save=Save
87 |
--------------------------------------------------------------------------------
/chrome/locale/en-US/toolbox.properties:
--------------------------------------------------------------------------------
1 | # LOCALIZATION NOTE (rdpInspector.title): RDP Inspector extension title
2 | rdpInspector.title=RDP Inspector
3 |
4 | # LOCALIZATION NOTE (rdpInspector.button.title, rdpInspector.button.tip):
5 | # Label and a tooltip for RDP Inspector start button available in the
6 | # Firefox toolbar and Style Editor panel. This button opens RDP Inspector
7 | # window.
8 | rdpInspector.startButton.title=RDP Inspector
9 | rdpInspector.startButton.tip=Remote debugging protocol inspector.
10 |
11 | # LOCALIZATION NOTE (rdpInspector.menu.about.label, rdpInspector.menu.about.tip):
12 | # RDP Inspector menu label. The menu is available in RDP Inspector start
13 | # button located in Firefox toolbar.
14 | rdpInspector.menu.about.label=About RDP Inspector...
15 | rdpInspector.menu.about.tip=Information about RDP Inspector
16 |
17 | # LOCALIZATION NOTE (rdpInspector.menu.visitHomePage.label, rdpInspector.menu.visitHomePage.tip):
18 | # RDP Inspector menu label. The menu is available in RDP Inspector start
19 | # button located in Firefox toolbar.
20 | rdpInspector.menu.visitHomePage.label=Visit Home Page...
21 | rdpInspector.menu.visitHomePage.tip=Learn more about RDP Inspector
22 |
23 | # LOCALIZATION NOTE (rdpInspector.menu.reportIssue.label, rdpInspector.menu.reportIssue.tip):
24 | # RDP Inspector menu label. The menu is available in RDP Inspector start
25 | # button located in Firefox toolbar.
26 | rdpInspector.menu.reportIssue.label=Report Issue...
27 | rdpInspector.menu.reportIssue.tip=Did you find a bug or do you need a new feature? Let us know!
28 |
29 | # LOCALIZATION NOTE (rdpInspector.menu.group.label, rdpInspector.menu.group.tip):
30 | # RDP Inspector menu label. The menu is available in RDP Inspector start
31 | # button located in Firefox toolbar.
32 | rdpInspector.menu.group.label=Discussion Group...
33 | rdpInspector.menu.group.tip=Open the discussion group site (shared with Firebug)
34 |
35 | # LOCALIZATION NOTE (rdpInspector.menu.options.label):
36 | # RDP Inspector menu label. The menu is available in RDP Inspector start button locate in Firefox toolbar.
37 | rdpInspector.menu.options.label=Options
38 |
39 | # LOCALIZATION NOTE (rdpInspector.menu.packetCache.label,rdpInspector.menu.packetCache.tip):
40 | # RDP Inspector menu label. The menu is available in RDP Inspector start
41 | # button located in Firefox toolbar, inside the Options sub-menu.
42 | rdpInspector.menu.packetCache.label=Packet Cache
43 | rdpInspector.menu.packetCache.tip=Store packets in a cache before the console is opened.
44 |
45 | # LOCALIZATION NOTE (rdpInspector.menu.showInlineDetails.label,rdpInspector.menu.showInlineDetails.tip):
46 | # RDP Inspector menu label. The menu is available in RDP Inspector start
47 | # button located in Firefox toolbar, inside the Options sub-menu.
48 | rdpInspector.menu.showInlineDetails.label=Show Packet Details Inline
49 | rdpInspector.menu.showInlineDetails.tip=Show a detailed tree view of the Packet content.
50 |
51 | # LOCALIZATION NOTE (rdpInspector.menu.autoOpenOnWebIDEConnection.label,rdpInspector.menu.autoOpenOnWebIDEConnection.tip):
52 | # RDP Inspector menu label. The menu is available in RDP Inspector start
53 | # button located in Firefox toolbar, inside the Options sub-menu.
54 | rdpInspector.menu.autoOpenOnWebIDEConnection.label=Open automatically on new WebIDE connections
55 | rdpInspector.menu.autoOpenOnWebIDEConnection.tip=Open an RDP inspector window automatically on every new WebIDE connections.
56 |
57 | # LOCALIZATION NOTE (rdpInspector.menu.connectionList.label, rdpInspector.menu.connectionList.tip):
58 | # RDP Inspector menu label. The menu is available in RDP Inspector start
59 | # button located in Firefox toolbar.
60 | rdpInspector.menu.connectionList.label=Connect to...
61 | rdpInspector.menu.connectionList.tip=Open a dialog which lists all the RDP Connections available to the RDPInspector
62 |
--------------------------------------------------------------------------------
/chrome/locale/nl/inspector.properties:
--------------------------------------------------------------------------------
1 | rdpInspector.option.showInlineDetails=Pakketdetails inline weergeven
2 | rdpInspector.option.hideInlineDetails=Pakketdetails inline verbergen
3 | rdpInspector.option.cachePackets=Pakketten bufferen voordat de inspecteur wordt geopend
4 | rdpInspector.cmd.clear=Wissen
5 | rdpInspector.cmd.find=Zoeken
6 | rdpInspector.cmd.summary=Samenvatting
7 | rdpInspector.tooltip.sizeSent=Totaal aantal naar de foutopsporingsserver verstuurde gegevens
8 | rdpInspector.tooltip.sizeReceived=Totaal aantal van de foutopsporingsserver ontvangen gegevens
9 | rdpInspector.tooltip.packetsSent=Aantal naar de foutopsporingsserver verstuurde pakketten
10 | rdpInspector.tooltip.packetsReceived=Aantal van de foutopsporingsserver ontvangen pakketten
11 | rdpInspector.label.packets=Pakketten
12 | rdpInspector.label.data=Gegevens
13 | rdpInspector.cmd.refresh=Vernieuwen
14 |
--------------------------------------------------------------------------------
/chrome/locale/nl/toolbox.properties:
--------------------------------------------------------------------------------
1 | rdpInspector.title=RDP Inspector
2 | rdpInspector.startButton.title=RDP-inspecteur
3 | rdpInspector.startButton.tip=Protocolinspecteur voor foutopsporing op afstand.
4 | rdpInspector.menu.about.label=Over RDP Inspector…
5 | rdpInspector.menu.about.tip=Informatie over RDP Inspector
6 | rdpInspector.menu.visitHomePage.label=Startpagina bezoeken…
7 | rdpInspector.menu.visitHomePage.tip=Lees meer over RDP Inspector
8 | rdpInspector.menu.reportIssue.label=Probleem melden…
9 | rdpInspector.menu.reportIssue.tip=Hebt u een bug gevonden of zou u graag een nieuwe functie zien? Laat het ons weten!
10 | rdpInspector.menu.group.label=Discussiegroep…
11 | rdpInspector.menu.group.tip=De website van de discussiegroep (gedeeld met Firebug) openen
12 |
--------------------------------------------------------------------------------
/chrome/locale/pt-BR/inspector.properties:
--------------------------------------------------------------------------------
1 | rdpInspector.option.showInlineDetails=Exibir detalhes do pacote
2 | rdpInspector.option.hideInlineDetails=Ocultar detalhes do pacote
3 | rdpInspector.option.cachePackets=Pacotes da cache antes do inspector ser aberto
4 | rdpInspector.cmd.clear=Limpar
5 | rdpInspector.cmd.find=Procurar
6 | rdpInspector.cmd.summary=Resumo
7 | rdpInspector.tooltip.sizeSent=A quantidade total de dados enviado para o servidor depurador
8 | rdpInspector.tooltip.sizeReceived=Quantidade total de dados recebidos do servidor depurador
9 | rdpInspector.tooltip.packetsSent=O número de pacotes enviada para o servidor depurador
10 | rdpInspector.tooltip.packetsReceived=Número de pacotes recebidos a partir do servidor depurador
11 | rdpInspector.label.packets=Pacotes
12 | rdpInspector.label.data=Dados
13 | rdpInspector.cmd.refresh=Recarregar
14 |
--------------------------------------------------------------------------------
/chrome/locale/pt-BR/toolbox.properties:
--------------------------------------------------------------------------------
1 | rdpInspector.title=RDP Inspector
2 | rdpInspector.startButton.title=RDP Inspector
3 | rdpInspector.startButton.tip=Inspetor de protocolo de depuração remota.
4 | rdpInspector.menu.about.label=Sobre o RDP Inspector
5 | rdpInspector.menu.about.tip=Informações sobre o RDP Inspector
6 | rdpInspector.menu.visitHomePage.label=Visite a Página Principal…
7 | rdpInspector.menu.visitHomePage.tip=Saiba mais sobre o RDP Inspector
8 | rdpInspector.menu.reportIssue.label=Relatório do problema…
9 | rdpInspector.menu.reportIssue.tip=Encontrou um bug ou precisa de um novo recurso? Nos informe!
10 | rdpInspector.menu.group.label=Grupo de discussão…
11 | rdpInspector.menu.group.tip=Abrir o site do grupo de discussão (compartilhado com o Firebug)
12 |
--------------------------------------------------------------------------------
/chrome/locale/zh-CN/inspector.properties:
--------------------------------------------------------------------------------
1 | rdpInspector.option.showInlineDetails=显示数据包的详细信息
2 | rdpInspector.option.hideInlineDetails=隐藏数据包的详细信息
3 | rdpInspector.option.cachePackets=在探查器打开前缓存数据包
4 | rdpInspector.cmd.clear=清空
5 | rdpInspector.cmd.find=查找
6 | rdpInspector.cmd.summary=摘要
7 | rdpInspector.tooltip.sizeSent=向调试器服务器发送数据的总量
8 | rdpInspector.tooltip.sizeReceived=从调试器服务器接收数据的总量
9 | rdpInspector.tooltip.packetsSent=向调试器服务器发送的数据包数量
10 | rdpInspector.tooltip.packetsReceived=从调试器服务器接收的数据包数量
11 | rdpInspector.label.packets=数据包
12 | rdpInspector.label.data=数据
13 | rdpInspector.cmd.refresh=刷新
14 |
--------------------------------------------------------------------------------
/chrome/locale/zh-CN/toolbox.properties:
--------------------------------------------------------------------------------
1 | rdpInspector.title=RDP Inspector
2 | rdpInspector.startButton.title=RDP Inspector
3 | rdpInspector.startButton.tip=远程调试协议探查器。
4 | rdpInspector.menu.about.label=关于 RDP Inspector...
5 | rdpInspector.menu.about.tip=有关 RDP Inspector 的信息
6 | rdpInspector.menu.visitHomePage.label=访问主页...
7 | rdpInspector.menu.visitHomePage.tip=详细了解有关 RDP Inspector
8 | rdpInspector.menu.reportIssue.label=报告问题...
9 | rdpInspector.menu.reportIssue.tip=您遇到了 bug?或是有关于新功能的点子?告诉我们吧!
10 | rdpInspector.menu.group.label=讨论组...
11 | rdpInspector.menu.group.tip=打开讨论组网站 (与 Firebug 共享)
12 |
--------------------------------------------------------------------------------
/chrome/skin/classic/shared/icon16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebug/rdp-inspector/60b22d880d9ea334e638b14c69102e8ed5c5c1e6/chrome/skin/classic/shared/icon16.png
--------------------------------------------------------------------------------
/chrome/skin/classic/shared/icon32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebug/rdp-inspector/60b22d880d9ea334e638b14c69102e8ed5c5c1e6/chrome/skin/classic/shared/icon32.png
--------------------------------------------------------------------------------
/chrome/skin/classic/shared/icon64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebug/rdp-inspector/60b22d880d9ea334e638b14c69102e8ed5c5c1e6/chrome/skin/classic/shared/icon64.png
--------------------------------------------------------------------------------
/chrome/skin/classic/shared/search.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
87 |
--------------------------------------------------------------------------------
/data/.eslintrc:
--------------------------------------------------------------------------------
1 | // extends common eslintrc config with "javascript running in a content context" specific configs
2 | {
3 | "extends": "../.eslintrc",
4 | "plugins": [
5 | // prevents tab whitespace when 'indent' rule is disabled
6 | "no-tabs",
7 | "react"
8 | ],
9 | "env": {
10 | // enable browser & amd conventions
11 | "browser": true,
12 | "amd": true
13 | },
14 | "rules": {
15 | // disabled due to conflicts with special indentation in requirejs modules
16 | "indent": 0,
17 | // prevents any usage of tab whitespaces
18 | "no-tabs/at-all": [2],
19 |
20 | // force definition of displayName on React components
21 | "react/display-name": 2,
22 |
23 | // TODO: force propTypes on React Components
24 | "react/prop-types": 0,
25 |
26 | // disabled due to conflicts with capitalized React components names
27 | "new-cap": [0],
28 | },
29 | "globals": {}
30 | }
31 |
--------------------------------------------------------------------------------
/data/connection-list/actions.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports, module) {
4 |
5 | "use strict";
6 |
7 | const types = {
8 | SET_CONNECTIONS: "SET_CONNECTIONS"
9 | };
10 |
11 | // export actions types and action creators
12 | module.exports = {
13 | types,
14 |
15 | setConnections(connections) {
16 | return { type: types.SET_CONNECTIONS, connections };
17 | }
18 | };
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/data/connection-list/components/connection-list.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // ReactJS
8 | const React = require("react");
9 |
10 | // React Bootstrap factories
11 | const {
12 | ListGroup, ListGroupItem,
13 | Tabs, Tab
14 | } = require("shared/react-bootstrap-factories");
15 |
16 | const ConnectionsGroup = React.createClass({
17 | displayName: "ConnectionsGroup",
18 |
19 | render() {
20 | let connections = this.props.connections.map((conn) => {
21 | return ListGroupItem({
22 | style: { width: "100%" },
23 | onClick: (evt) => {
24 | this.props.onConnectionClick(conn, evt);
25 | }
26 | }, conn.name);
27 | });
28 |
29 | return ListGroup({ style: { width: "100%" } }, connections);
30 | }
31 | });
32 |
33 | exports.ConnectionList = React.createClass({
34 | displayName: "ConnectionList",
35 |
36 | render() {
37 | const connections = this.props.connections || {};
38 |
39 | // turn the first level (connections group) into a ConnectionsGroups components
40 | const connectionsGroups = Object.keys(connections).map((groupName, i) => {
41 | return Tab({
42 | key: groupName,
43 | title: connections[groupName].label,
44 | eventKey: i + 1,
45 | style: { overflow: "auto" }
46 | }, React.createElement(ConnectionsGroup, {
47 | onConnectionClick: this.props.onConnectionClick,
48 | connections: connections[groupName].connections
49 | }));
50 | });
51 |
52 | return Tabs({
53 | className: "mainTabbedArea",
54 | defaultActiveKey: 1, animation: false
55 | }, connectionsGroups);
56 | }
57 | });
58 |
59 | });
60 |
--------------------------------------------------------------------------------
/data/connection-list/config.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | /* globals requirejs */
4 |
5 | // RequireJS configuration
6 | require.config({
7 | baseUrl: ".",
8 | scriptType: "application/javascript;version=1.8",
9 | paths: {
10 | "shared": "../shared",
11 | "jquery": "../lib/jquery/jquery",
12 | "react": "../lib/react/react",
13 | "react-dom": "../lib/react/react-dom",
14 | "bootstrap": "../lib/bootstrap/js/bootstrap",
15 | "immutable": "../lib/immutable/immutable",
16 | "react-bootstrap": "../lib/react-bootstrap/react-bootstrap",
17 | "reps": "../../node_modules/firebug.sdk/lib/reps",
18 | "firebug.sdk": "../../node_modules/firebug.sdk",
19 | "redux": "../lib/redux/redux",
20 | "react-redux": "../lib/redux/react-redux",
21 | }
22 | });
23 |
24 | // Load the main panel module
25 | requirejs(["index"]);
26 |
--------------------------------------------------------------------------------
/data/connection-list/containers/main-panel.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // React & Redux
8 | const React = require("react");
9 | const { connect } = require("react-redux");
10 |
11 | // Connections List components
12 | const { ConnectionList } = require("../components/connection-list");
13 |
14 | const MainPanel = React.createClass({
15 | displayName: "MainPanel",
16 |
17 | render() {
18 | return React.createElement(ConnectionList, {
19 | connections: this.props.connections,
20 | onConnectionClick: this.props.onConnectionClick
21 | });
22 | }
23 | });
24 |
25 | function mapStoreToProps(state) {
26 | let { connections } = state;
27 | return { connections };
28 | }
29 |
30 | exports.MainPanel = connect(mapStoreToProps)(MainPanel);
31 |
32 | });
33 |
--------------------------------------------------------------------------------
/data/connection-list/css/connection-list.css:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | /******************************************************************************/
4 | /* Connection List Window */
5 |
6 | .tab-content .list-group-item {
7 | border-radius: 0;
8 | }
9 |
10 | .tab-content .list-group-item:first-child {
11 | border-top: 0;
12 | }
13 |
--------------------------------------------------------------------------------
/data/connection-list/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/data/connection-list/index.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require/*, exports, module*/) {
4 |
5 | "use strict";
6 |
7 | // React
8 | var ReactDOM = require("react-dom");
9 |
10 | // RDP Inspector
11 | const { Resizer } = require("shared/resizer");
12 | const { ReactLazyFactories } = require("shared/react-helpers");
13 | const { RDPConnectionList } = require("shared/rdp-inspector-window");
14 |
15 | // generate React Factories
16 | const { Provider } = ReactLazyFactories(require("react-redux"));
17 | const { MainPanel } = ReactLazyFactories(require("./containers/main-panel"));
18 |
19 | // actions & store
20 | const actions = require("./actions");
21 | const store = require("./store").configureStore();
22 |
23 | function render() {
24 | let content = document.querySelector("#content");
25 | let provider = Provider({ store }, MainPanel({
26 | onConnectionClick: (conn) => {
27 | RDPConnectionList.openRDPInspectorWindow(conn);
28 | }
29 | }));
30 | let app = ReactDOM.render(provider, content);
31 | return new Resizer(window, app);
32 | }
33 |
34 | function updateConnections() {
35 | let connections = RDPConnectionList.getConnectionsInfo();
36 | store.dispatch(actions.setConnections(connections));
37 | }
38 |
39 | render();
40 | updateConnections();
41 | RDPConnectionList.onConnectionsUpdated.addListener(updateConnections);
42 |
43 | });
44 |
--------------------------------------------------------------------------------
/data/connection-list/reducers.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // actions types
8 | const { types } = require("./actions");
9 |
10 | /**
11 | * Initial state definition
12 | */
13 | const initialState = {};
14 |
15 | function connections(state = initialState, action) {
16 | switch(action.type) {
17 | case types.SET_CONNECTIONS:
18 | return action.connections;
19 | default:
20 | return state;
21 | }
22 | }
23 |
24 | // Export combined reducers
25 |
26 | // Redux
27 | const { combineReducers } = require("redux");
28 |
29 | exports.rootReducer = combineReducers({
30 | connections
31 | });
32 |
33 | });
34 |
--------------------------------------------------------------------------------
/data/connection-list/store.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // Redux
8 | const { createStore } = require("redux");
9 |
10 | // RDP Inspector
11 | const { rootReducer } = require("./reducers");
12 |
13 | function configureStore(initialState) {
14 | return createStore(rootReducer, initialState);
15 | }
16 |
17 | // Exports from this module
18 | exports.configureStore = configureStore;
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/data/inspector/actions/actors.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports, module) {
4 |
5 | "use strict";
6 |
7 | const types = {
8 | SET_ACTORS: "SET_ACTORS",
9 | CLEAR_ACTORS: "CLEAR_ACTORS"
10 | };
11 |
12 | // export actions types and action creators
13 | module.exports = {
14 | types,
15 |
16 | setActors(actors) {
17 | return { type: types.SET_ACTORS, actors };
18 | },
19 |
20 | clearActors() {
21 | return { type: types.CLEAR_ACTORS };
22 | },
23 | };
24 |
25 | });
26 |
--------------------------------------------------------------------------------
/data/inspector/actions/global.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports, module) {
4 |
5 | "use strict";
6 |
7 | const types = {
8 | SET_SEARCH_FILTER: "SET_SEARCH_FILTER",
9 | };
10 |
11 | // export actions types and action creators
12 | module.exports = {
13 | types,
14 |
15 | setSearchFilter(filter) {
16 | return { type: types.SET_SEARCH_FILTER, filter };
17 | },
18 | };
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/data/inspector/actions/index.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports, module) {
4 |
5 | "use strict";
6 |
7 | const global = require("./global");
8 | const actors = require("./actors");
9 | const packets = require("./packets");
10 |
11 | module.exports = Object.assign({}, global, actors, packets, {
12 | types: Object.assign({}, actors.types, packets.types)
13 | });
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/data/inspector/actions/packets.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports, module) {
4 |
5 | "use strict";
6 |
7 | const types = {
8 | IMPORT_PACKETS_CACHE: "IMPORT_PACKETS_CACHE",
9 | IMPORT_PACKETS_FROMFILE: "IMPORTS_PACKETS_FROMFILE",
10 | INIT_PACKETLIST_OPTIONS: "INIT_PACKETLIST_OPTIONS",
11 | APPEND_PACKET: "APPEND_PACKET",
12 | APPEND_SUMMARY: "APPEND_SUMMARY",
13 | APPEND_MESSAGE: "APPEND_MESSAGE",
14 | EDIT_PACKET: "EDIT_PACKET",
15 | SELECT_PACKET: "SELECT_PACKET",
16 | CLEAR_PACKET_LIST: "CLEAR_PACKET_LIST",
17 | SET_PACKET_FILTER: "SET_PACKET_FILTER",
18 | TOGGLE_PACKETLIST_OPTION: "TOGGLE_PACKETLIST_OPTION",
19 | TOGGLE_PACKETLIST_PAUSE: "TOGGLE_PACKETLIST_PAUSE",
20 | SET_PACKETLIST_ERROR: "SET_PACKETLIST_ERROR",
21 | };
22 |
23 | // export actions types and action creators
24 | module.exports = {
25 | types,
26 |
27 | importPacketsCache(cache) {
28 | return { type: types.IMPORT_PACKETS_CACHE, cache };
29 | },
30 |
31 | importPacketsFromFile(data) {
32 | return { type: types.IMPORT_PACKETS_FROMFILE, data };
33 | },
34 |
35 | initPacketListOptions(options) {
36 | return { type: types.INIT_PACKETLIST_OPTIONS, options };
37 | },
38 |
39 | appendPacket(packetType, packetData) {
40 | return { type: types.APPEND_PACKET, packetType, packetData };
41 | },
42 |
43 | appendSummary() {
44 | let time = new Date();
45 | return { type: types.APPEND_SUMMARY, time };
46 | },
47 |
48 | appendMessage(message) {
49 | let time = new Date();
50 | return { type: types.APPEND_MESSAGE, message, time };
51 | },
52 |
53 | editPacket(packet) {
54 | return { type: types.EDIT_PACKET, packet };
55 | },
56 |
57 | selectPacket(packet) {
58 | return { type: types.SELECT_PACKET, packet };
59 | },
60 |
61 | clearPacketList() {
62 | return { type: types.CLEAR_PACKET_LIST };
63 | },
64 |
65 | togglePacketListOption(name) {
66 | return { type: types.TOGGLE_PACKETLIST_OPTION, name };
67 | },
68 |
69 | togglePacketListPause() {
70 | return { type: types.TOGGLE_PACKETLIST_PAUSE };
71 | },
72 |
73 | setPacketListError(error) {
74 | return { type: types.SET_PACKETLIST_ERROR, error };
75 | }
76 |
77 | };
78 |
79 | });
80 |
--------------------------------------------------------------------------------
/data/inspector/components/actors-panel.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // Dependencies
8 | const React = require("react");
9 |
10 | // RDP Inspector
11 | const { ActorsToolbar } = require("./actors-toolbar");
12 |
13 | const { Locale } = require("shared/rdp-inspector-window");
14 |
15 | // Shortcuts
16 | const { tr, td, table, tbody, thead, th, div, h4 } = React.DOM;
17 |
18 | const GLOBAL_ACTORS_POOLS = "global-actors-pool";
19 | const TAB_ACTORS_POOLS = "tab-actors-pool";
20 | const ACTORS_FACTORIES = "actors-factories";
21 |
22 | var PanelTypesLabels = {};
23 | PanelTypesLabels[GLOBAL_ACTORS_POOLS] = Locale.$STR("rdpInspector.label.MainProcess");
24 | PanelTypesLabels[TAB_ACTORS_POOLS] = Locale.$STR("rdpInspector.label.ChildProcess");
25 | PanelTypesLabels[ACTORS_FACTORIES] = Locale.$STR("rdpInspector.label.ActorsFactories");
26 |
27 | /**
28 | * @template This template renders 'Actors' tab body.
29 | */
30 | var ActorsPanel = React.createClass({
31 | /** @lends ActorsPanel */
32 |
33 | displayName: "ActorsPanel",
34 |
35 | getInitialState: function() {
36 | return {
37 | panelType: GLOBAL_ACTORS_POOLS
38 | };
39 | },
40 |
41 | render: function() {
42 | var { actors } = this.props;
43 | var { panelType } = this.state;
44 |
45 | var el;
46 |
47 | switch(panelType) {
48 | case GLOBAL_ACTORS_POOLS:
49 | el = ActorsPools({
50 | data: (actors && actors.global),
51 | key: "global",
52 | searchFilter: this.props.searchFilter
53 | });
54 | break;
55 | case TAB_ACTORS_POOLS:
56 | el = ActorsPools({
57 | data: (actors && actors.tab),
58 | key: "tab",
59 | searchFilter: this.props.searchFilter
60 | });
61 | break;
62 | case ACTORS_FACTORIES:
63 | el = ActorsFactories({
64 | key: "factories",
65 | data: {
66 | global: actors && actors.global,
67 | tab: actors && actors.tab
68 | },
69 | searchFilter: this.props.searchFilter
70 | });
71 | break;
72 | }
73 |
74 | return (
75 | div({ className: "actorsPanelBox" },
76 | ActorsToolbar({ actions: this.props.actions,
77 | currentPanelType: panelType,
78 | panelTypesLabels: PanelTypesLabels,
79 | onPanelTypeSelected: this.onPanelTypeSelected
80 | }),
81 | div({ className: "actorsScrollBox" }, el)
82 | )
83 | );
84 | },
85 |
86 | onPanelTypeSelected: function(panelType) {
87 | this.setState({
88 | panelType: panelType
89 | });
90 | }
91 | });
92 |
93 | /**
94 | * @template This template renders 'ActorsPools' list in the tab content.
95 | */
96 | var ActorsPools = React.createFactory(React.createClass({
97 | /** @lends ActorsPools */
98 |
99 | displayName: "ActorsPools",
100 |
101 | render: function() {
102 | var pools = [];
103 |
104 | if (this.props.data) {
105 | var { actorPool, extraPools } = this.props.data;
106 | pools = pools.concat(actorPool, extraPools);
107 | }
108 |
109 | var poolTables = pools.map((poolData) => {
110 | var pool = poolData.pool;
111 | var poolId = poolData.id;
112 | var actorClass = false;
113 |
114 | if (!Array.isArray(pool)) {
115 | pool = [pool];
116 | actorClass = true;
117 | }
118 |
119 | if (pool.length > 0) {
120 | return PoolTable({
121 | pool: pool,
122 | actorClass: actorClass,
123 | id: poolId,
124 | key: poolId,
125 | searchFilter: this.props.searchFilter
126 | });
127 | }
128 | }).filter((el) => el);
129 |
130 | return div({ className: "poolContainer" }, poolTables);
131 | }
132 | }));
133 |
134 | /**
135 | * @template This template renders 'PoolTable' which render a table related
136 | * to a single pool of actors.
137 | */
138 | var PoolTable = React.createFactory(React.createClass({
139 | /** @lends ActorsPanel */
140 |
141 | displayName: "PoolTable",
142 |
143 | render: function() {
144 | var rows = [];
145 |
146 | // Iterate array of actors.
147 | var actors = this.props.pool;
148 | for (var i in actors) {
149 | if (this.props.searchFilter &&
150 | JSON.stringify(actors[i]).toLowerCase()
151 | .indexOf(this.props.searchFilter.toLowerCase()) < 0) {
152 | // filter out packets which don't match the filter
153 | continue;
154 | }
155 | actors[i].key = actors[i].actorID;
156 | rows.push(PoolRow(actors[i]));
157 | }
158 |
159 | // Pools are mixed with Actor objects (created using CreateClass).
160 | var className = "poolTable";
161 | if (this.props.actorClass) {
162 | className += " actorClass";
163 | }
164 |
165 | var id = this.props.id ? "ID: " + this.props.id : "";
166 |
167 | return (
168 | div({},
169 | h4({}, "Pool" + id),
170 | table({className: className},
171 | thead({className: "poolRow"},
172 | th({width: "20%"}, "Actor ID"),
173 | th({width: "20%"}, "Prefix"),
174 | th({width: "20%"}, "TypeName"),
175 | th({width: "20%"}, "Parent"),
176 | th({width: "20%"}, "Constructor")
177 | ),
178 | tbody(null, rows)
179 | )
180 | )
181 | );
182 | }
183 | }));
184 |
185 | /**
186 | * @template This template renders a single row of the 'PoolTable' .
187 | */
188 | var PoolRow = React.createFactory(React.createClass({
189 | /** @lends PoolRow */
190 |
191 | displayName: "PoolRow",
192 |
193 | render: function() {
194 | var actor = this.props;
195 | return (
196 | tr({className: "poolRow"},
197 | td({}, actor.actorID),
198 | td({}, actor.actorPrefix),
199 | td({}, actor.typeName),
200 | td({}, actor.parentID),
201 | td({}, actor.constructor)
202 | )
203 | );
204 | }
205 | }));
206 |
207 | /**
208 | * @template This template renders a single 'FactoryTable' component.
209 | */
210 | var FactoryTable = React.createFactory(React.createClass({
211 | /** @lends FactoryTable */
212 |
213 | displayName: "FactoryTable",
214 |
215 | render: function() {
216 | var rows = [];
217 |
218 | var factories = this.props.factories;
219 | for (var i in factories) {
220 | if (this.props.searchFilter &&
221 | JSON.stringify(factories[i]).toLowerCase()
222 | .indexOf(this.props.searchFilter.toLowerCase()) < 0) {
223 | // filter out packets which don't match the filter
224 | continue;
225 | }
226 |
227 | factories[i].key = factories[i].prefix + factories[i].name;
228 | rows.push(FactoryRow(factories[i]));
229 | }
230 |
231 | return (
232 | table({className: "poolTable"},
233 | thead({className: "poolRow"},
234 | th({width: "33%"}, "Name"),
235 | th({width: "33%"}, "Prefix"),
236 | th({width: "33%"}, "Constructor")
237 | ),
238 | tbody(null, rows)
239 | )
240 | );
241 | }
242 | }));
243 |
244 | /**
245 | * @template This template renders the 'ActorsFactories' list of tables.
246 | */
247 | var ActorsFactories = React.createFactory(React.createClass({
248 | /** @lends ActorsFactories */
249 |
250 | displayName: "ActorsFactories",
251 |
252 | render: function() {
253 | var main = this.props.data.global || { factories: {} };
254 | var child = this.props.data.tab || { factories: {} };
255 | var searchFilter = this.props.searchFilter;
256 |
257 | return (
258 | div({className: "poolContainer"},
259 | h4(null, "Main Process - Global Factories"),
260 | FactoryTable({ factories: main.factories.global, searchFilter: searchFilter }),
261 | h4(null, "Main Process - Tab Factories"),
262 | FactoryTable({ factories: main.factories.tab, searchFilter: searchFilter }),
263 | h4(null, "Child Process - Global Factories"),
264 | FactoryTable({ factories: child.factories.global, searchFilter: searchFilter }),
265 | h4(null, "Child Process - Tab Factories"),
266 | FactoryTable({ factories: child.factories.tab, searchFilter: searchFilter })
267 | )
268 | );
269 | }
270 | }));
271 |
272 | /**
273 | * @template This template renders a single row of the 'FactoryTable'.
274 | */
275 | var FactoryRow = React.createFactory(React.createClass({
276 | /** @lends ActorsPanel */
277 |
278 | displayName: "FactoryRow",
279 |
280 | render: function() {
281 | var factory = this.props;
282 | return (
283 | tr({className: "poolRow"},
284 | td({}, factory.name),
285 | td({}, factory.prefix),
286 | td({}, factory.ctor)
287 | )
288 | );
289 | }
290 | }));
291 |
292 | // Exports from this module
293 | exports.ActorsPanel = React.createFactory(ActorsPanel);
294 | exports.ActorsPanelComponent = ActorsPanel;
295 |
296 | });
297 |
--------------------------------------------------------------------------------
/data/inspector/components/actors-toolbar.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // Dependencies
8 | var React = require("react");
9 |
10 | // Shortcuts
11 | const { ButtonToolbar, Button } = require("shared/react-bootstrap-factories");
12 |
13 | const { select, option } = React.DOM;
14 |
15 | // RDP Window injected APIs
16 | const { Locale } = require("shared/rdp-inspector-window");
17 |
18 | /**
19 | * @template This object is responsible for rendering the toolbar
20 | * in Actors tab
21 | */
22 | var ActorsToolbar = React.createClass({
23 | /** @lends ActorsToolbar */
24 |
25 | displayName: "ActorsToolbar",
26 |
27 | render: function() {
28 | var { panelTypesLabels, currentPanelType } = this.props;
29 |
30 | var options = Object.keys(panelTypesLabels).map((value) => {
31 | var label = panelTypesLabels[value];
32 | return option({ value: value, key: value }, label);
33 | });
34 |
35 | return (
36 | ButtonToolbar({className: "toolbar"},
37 | Button({bsSize: "xsmall", onClick: this.onRefresh},
38 | Locale.$STR("rdpInspector.cmd.refresh")
39 | ),
40 | select({ selected: currentPanelType, onChange: this.onChange },
41 | options
42 | )
43 | )
44 | );
45 | },
46 |
47 | // Commands
48 |
49 | onRefresh: function(/*event*/) {
50 | this.props.actions.getActors();
51 | },
52 |
53 | onChange: function(event) {
54 | var type = event.target.value;
55 | this.props.onPanelTypeSelected(type);
56 | }
57 | });
58 |
59 | // Exports from this module
60 | exports.ActorsToolbar = React.createFactory(ActorsToolbar);
61 | });
62 |
--------------------------------------------------------------------------------
/data/inspector/components/factories.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // Dependencies
8 | var React = require("react");
9 | var ReactDOM = require("react-dom");
10 |
11 | // Consts
12 | const { tr, td, table, tbody, thead, th, div, h4 } = React.DOM;
13 |
14 | // Templates
15 |
16 | /**
17 | * TODO docs
18 | */
19 | var FactoryRow = React.createFactory(React.createClass({
20 | /** @lends FactoryRow */
21 |
22 | displayName: "FactoryRow",
23 |
24 | render: function() {
25 | var factory = this.props;
26 | return (
27 | tr({className: "poolRow"},
28 | td({}, factory.name),
29 | td({}, factory.prefix),
30 | td({}, factory.ctor)
31 | )
32 | );
33 | }
34 | }));
35 |
36 | /**
37 | * TODO docs
38 | * xxxHonza: localization
39 | */
40 | var FactoryTable = React.createFactory(React.createClass({
41 | /** @lends FactoryTable */
42 |
43 | displayName: "FactoryTable",
44 |
45 | render: function() {
46 | var rows = [];
47 |
48 | var factories = this.props.factories;
49 | for (var i in factories) {
50 | if (this.props.searchFilter &&
51 | JSON.stringify(factories[i]).toLowerCase()
52 | .indexOf(this.props.searchFilter.toLowerCase()) < 0) {
53 | // filter out packets which don't match the filter
54 | continue;
55 | }
56 |
57 | factories[i].key = factories[i].prefix + factories[i].name;
58 | rows.push(FactoryRow(factories[i]));
59 | }
60 |
61 | return (
62 | table({className: "poolTable"},
63 | thead({className: "poolRow"},
64 | th({width: "33%"}, "Name"),
65 | th({width: "33%"}, "Prefix"),
66 | th({width: "33%"}, "Constructor")
67 | ),
68 | tbody(null, rows)
69 | )
70 | );
71 | }
72 | }));
73 |
74 | /**
75 | * TODO docs
76 | */
77 | var FactoryList = React.createFactory(React.createClass({
78 | /** @lends FactoryList */
79 |
80 | displayName: "FactoryList",
81 |
82 | getInitialState: function() {
83 | return {
84 | main: {factories: {}},
85 | child: {factories: {}},
86 | searchFilter: null
87 | };
88 | },
89 | render: function() {
90 | var main = this.state.main;
91 | var child = this.state.child;
92 | var searchFilter = this.state.searchFilter;
93 |
94 | // xxxHonza: localization
95 | return (
96 | div({className: "poolContainer"},
97 | h4(null, "Main Process - Global Factories"),
98 | FactoryTable({ factories: main.factories.global, searchFilter: searchFilter }),
99 | h4(null, "Main Process - Tab Factories"),
100 | FactoryTable({ factories: main.factories.tab, searchFilter: searchFilter }),
101 | h4(null, "Child Process - Global Factories"),
102 | FactoryTable({ factories: child.factories.global, searchFilter: searchFilter }),
103 | h4(null, "Child Process - Tab Factories"),
104 | FactoryTable({ factories: child.factories.tab, searchFilter: searchFilter })
105 | )
106 | );
107 | }
108 | }));
109 |
110 | // TODO: turn this into a more React approach
111 | var Factories = {
112 | render: function(parentNode) {
113 | return ReactDOM.render(FactoryList(), parentNode);
114 | }
115 | };
116 |
117 | // Exports from this module
118 | exports.Factories = Factories;
119 |
120 | });
121 |
--------------------------------------------------------------------------------
/data/inspector/components/main-tabbed-area.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports, module) {
4 |
5 | "use strict";
6 |
7 | // ReactJS
8 | var React = require("react");
9 | var ReactDOM = require("react-dom");
10 |
11 | // RDP Inspector
12 | const { ActorsPanel } = require("./actors-panel");
13 | const { PacketsPanel } = require("./packets-panel");
14 | const { SearchBox } = require("./search-box");
15 |
16 | // Constants
17 | const { Tabs, Tab, Alert } = require("shared/react-bootstrap-factories");
18 |
19 | // RDP Window injected APIs
20 | const { Locale } = require("shared/rdp-inspector-window");
21 |
22 | /**
23 | * @template This template is responsible for rendering the main
24 | * application UI. The UI consist from set of tabs (Packets and Actors)
25 | * displaying list of sent/received packets and list of registered
26 | * actors.
27 | */
28 | var MainTabbedArea = React.createClass({
29 | /** @lends MainTabbedArea */
30 |
31 | displayName: "MainTabbedArea",
32 |
33 | getInitialState: function() {
34 | return { packets: [] };
35 | },
36 |
37 | componentDidMount: function() {
38 | var tabbedArea = ReactDOM.findDOMNode(this.refs.tabbedArea);
39 | SearchBox.create(tabbedArea.querySelector(".nav-tabs"));
40 | },
41 |
42 | componentWillUnmount: function() {
43 | var tabbedArea = ReactDOM.findDOMNode(this.refs.tabbedArea);
44 | SearchBox.destroy(tabbedArea.querySelector(".nav-tabs"));
45 | },
46 |
47 | onErrorDismiss: function() {
48 | this.props.view.clearError();
49 | },
50 |
51 | render: function() {
52 | var packets = Locale.$STR("rdpInspector.tab.Packets");
53 | var actors = Locale.$STR("rdpInspector.tab.Actors");
54 | var { error } = this.props.packets;
55 |
56 | return (
57 | Tabs({className: "mainTabbedArea", defaultActiveKey: 1,
58 | animation: false, ref: "tabbedArea"},
59 | error ? Alert({
60 | bsStyle: "warning",
61 | onDismiss: this.onErrorDismiss,
62 | dismissAfter: 2000,
63 | style: {
64 | position: "absolute",
65 | width: "100%",
66 | zIndex: 999999
67 | }
68 | }, error.message) : null,
69 | Tab({ eventKey: 1, title: packets },
70 | PacketsPanel({
71 | packets: this.props.packets.filteredPackets,
72 | actions: this.props.view,
73 | selectedPacket: this.props.packets.selectedPacket,
74 | editedPacket: this.props.packets.editedPacket,
75 | searchFilter: this.props.global.searchFilter,
76 | showInlineDetails: this.props.packets.options.showInlineDetails,
77 | packetCacheEnabled: this.props.packets.options.packetCacheEnabled,
78 | removedPackets: this.props.packets.removedPackets,
79 | paused: this.props.packets.paused,
80 | actorIDs: this.props.actors.actorIDs
81 | })
82 | ),
83 | Tab({ eventKey: 2, title: actors },
84 | ActorsPanel({
85 | actions: this.props.view,
86 | actors: this.props.actors,
87 | searchFilter: this.props.global.searchFilter
88 | })
89 | )
90 | )
91 | );
92 | }
93 | });
94 |
95 | // Exports from this module
96 | module.exports = MainTabbedArea;
97 | });
98 |
--------------------------------------------------------------------------------
/data/inspector/components/packet-details.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // Dependencies
8 | const React = require("react");
9 |
10 | // Firebug SDK
11 | const { TreeView } = require("reps/tree-view");
12 |
13 | // Shortcuts
14 | const { div } = React.DOM;
15 |
16 | /**
17 | * @template This template represents a list of packets displayed
18 | * inside the panel content.
19 | */
20 | var PacketDetails = React.createClass({
21 | /** @lends PacketDetails */
22 |
23 | displayName: "PacketDetails",
24 |
25 | getInitialState: function() {
26 | return {
27 | selectedPacket: null
28 | };
29 | },
30 |
31 | render: function() {
32 | var selectedPacket = this.props.selectedPacket || {};
33 |
34 | return (
35 | div({className: "details"},
36 | TreeView({key: "packet-detail", data: selectedPacket.packet})
37 | )
38 | );
39 | }
40 | });
41 |
42 | // Exports from this module
43 | exports.PacketDetails = React.createFactory(PacketDetails);
44 | });
45 |
--------------------------------------------------------------------------------
/data/inspector/components/packet-editor.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // Dependencies
8 | const React = require("react");
9 |
10 | // Firebug SDK
11 | const { TreeEditorView } = require("./tree-editor-view");
12 |
13 | // Constants
14 | const { div } = React.DOM;
15 |
16 | const { ButtonToolbar, Button } = require("shared/react-bootstrap-factories");
17 |
18 | /**
19 | * @template This template represents the Packet Editor toolbar
20 | */
21 |
22 | var PacketEditorToolbar = React.createFactory(React.createClass({
23 | /** @lends PacketEditrView */
24 |
25 | displayName: "PacketEditorToolbar",
26 |
27 | render: function() {
28 | return ButtonToolbar({className: "toolbar"}, [
29 | Button({ onClick: this.props.onSend, key: "send",
30 | bsStyle: "primary", bsSize: "xsmall",
31 | style: { marginLeft: 12, color: "white" } }, "Send"),
32 |
33 | Button({ onClick: this.props.onRedo, key: "redo",
34 | className: "pull-right",
35 | disabled: !this.props.isRedoEnabled,
36 | bsStyle: "default", bsSize: "xsmall",
37 | style: { marginRight: 6 } }, "Redo"),
38 | Button({ onClick: this.props.onUndo, key: "undo",
39 | className: "pull-right",
40 | disabled: !this.props.isUndoEnabled,
41 | bsStyle: "default", bsSize: "xsmall",
42 | style: { marginRight: 6 } }, "Undo"),
43 | Button({ onClick: this.props.onClear, key: "clear",
44 | className: "pull-right",
45 | bsStyle: "danger", bsSize: "xsmall",
46 | style: { marginRight: 6, color: "white" } }, "Clear")
47 | ]);
48 | }
49 | }));
50 |
51 | /**
52 | * @template This template represents the PacketEditor sidebar
53 | */
54 | var PacketEditor = React.createClass({
55 | displayName: "PacketEditor",
56 |
57 | getInitialState: function() {
58 | return {
59 | editedPacket: null,
60 | defaultData: {
61 | to: "root",
62 | type: "requestTypes"
63 | }
64 | };
65 | },
66 |
67 | componentWillReceiveProps: function(nextProps) {
68 | this.setState({
69 | editedPacket: nextProps.editedPacket
70 | });
71 | },
72 |
73 | render: function() {
74 | var editedPacket = this.state.editedPacket || this.props.editedPacket;
75 | var { actorIDs } = this.props;
76 |
77 | return (
78 | div({className: "details editor"},
79 | PacketEditorToolbar({
80 | onClear: this.onClear,
81 | onSend: this.onSend,
82 | onUndo: this.onUndo,
83 | onRedo: this.onRedo,
84 | isUndoEnabled: true,
85 | isRedoEnabled: true
86 | }),
87 | TreeEditorView({
88 | ref: "editor",
89 | key: "packet-editor",
90 | data: editedPacket,
91 | defaultData: this.state.defaultData,
92 | handleAutocompletion: (suggestionType, keyPath, value) => {
93 | if (!actorIDs && suggestionType != "value") {
94 | return [];
95 | }
96 |
97 | try {
98 | var parsedValue;
99 |
100 | // remove starting and ending '"' if any
101 | parsedValue = typeof value == "string" ?
102 | value.replace(/^"|"$/g, "") : "";
103 |
104 | if(keyPath.length == 1 && keyPath[0] == "to") {
105 | // get a suggestion list by filtering actorIDs list
106 | return actorIDs.filter((suggestion) => {
107 | return suggestion.indexOf(parsedValue) >= 0;
108 | });
109 | }
110 | } catch(e) {
111 | //console.debug("exception on parsing autocompletion", e);
112 | }
113 |
114 | return [];
115 | }
116 | })
117 | )
118 | );
119 | },
120 |
121 | onUndo: function() {
122 | this.refs.editor.undo();
123 | },
124 |
125 | onRedo: function() {
126 | this.refs.editor.redo();
127 | },
128 |
129 | onClear: function() {
130 | this.refs.editor.clearData();
131 | },
132 |
133 | onSend: function() {
134 | this.props.actions.send(this.refs.editor.getData());
135 | }
136 | });
137 |
138 | // Exports from this module
139 | exports.PacketEditor = React.createFactory(PacketEditor);
140 |
141 | });
142 |
--------------------------------------------------------------------------------
/data/inspector/components/packet-list.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // Dependencies
8 | const React = require("react");
9 | const ReactDOM = require("react-dom");
10 |
11 | // RDP Inspector
12 | const { Packet } = require("./packet");
13 | const { PacketsSummary } = require("./packets-summary");
14 | const { PacketsLimit } = require("./packets-limit");
15 | const { PacketsMessage } = require("./packets-message");
16 |
17 | // Shortcuts
18 | const { div } = React.DOM;
19 |
20 | /**
21 | * @template This template represents a list of packets displayed
22 | * inside the panel content.
23 | */
24 | var PacketList = React.createClass({
25 | /** @lends PacketList */
26 |
27 | displayName: "PacketList",
28 |
29 | getInitialState: function() {
30 | return { data: [] };
31 | },
32 |
33 | componentWillUpdate: function() {
34 | var node = ReactDOM.findDOMNode(this);
35 | this.shouldScrollBottom = node.scrollTop +
36 | node.offsetHeight === node.scrollHeight;
37 | },
38 |
39 | componentDidUpdate: function() {
40 | if (this.shouldScrollBottom) {
41 | var node = ReactDOM.findDOMNode(this);
42 | node.scrollTop = node.scrollHeight;
43 | }
44 | },
45 |
46 | render: function() {
47 | var output = [];
48 | var filter = this.props.searchFilter;
49 | var removedPackets = this.props.removedPackets;
50 |
51 | if (removedPackets > 0) {
52 | output.push(PacketsLimit({
53 | removedPackets: removedPackets
54 | }));
55 | }
56 |
57 | var packets = this.props.data;
58 | for (var i in packets) {
59 | var packet = packets[i];
60 |
61 | // Render 'summary' packets.
62 | if (packet.type == "summary") {
63 | output.push(PacketsSummary({
64 | key: packet.id,
65 | data: packet
66 | }));
67 | continue;
68 | }
69 |
70 | // Render 'message' packets.
71 | if (packet.type == "message") {
72 | output.push(PacketsMessage({
73 | key: packet.id,
74 | data: packet
75 | }));
76 | continue;
77 | }
78 |
79 | // Filter out packets which don't match the search token.
80 | if (filter && packet.rawPacket.toLowerCase().indexOf(filter.toLowerCase()) < 0) {
81 | continue;
82 | }
83 |
84 | var selected = this.props.selectedPacket == packet;
85 |
86 | output.push(Packet({
87 | key: packet.id,
88 | data: packet,
89 | actions: this.props.actions,
90 | selected: selected,
91 | showInlineDetails: this.props.showInlineDetails
92 | }));
93 | }
94 |
95 | return (
96 | div({className: "list"},
97 | div({}, output)
98 | )
99 | );
100 | }
101 | });
102 |
103 | // Exports from this module
104 | exports.PacketList = React.createFactory(PacketList);
105 | exports.PacketListComponent = PacketList;
106 | });
107 |
--------------------------------------------------------------------------------
/data/inspector/components/packet-stack-sidepanel.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // Dependencies
8 | const React = require("react");
9 |
10 | // Firebug SDK
11 | const { TreeView } = require("reps/tree-view");
12 |
13 | // Shortcuts
14 | const { div } = React.DOM;
15 |
16 | /**
17 | * @template This template represents a side panel that displays
18 | * list of stack-frames for selected packet.
19 | */
20 | var PacketStackSidePanel = React.createClass({
21 | /** @lends PacketStackSidePanel */
22 |
23 | displayName: "PacketStackSidePanel",
24 |
25 | getInitialState: function() {
26 | return {
27 | selectedPacket: null
28 | };
29 | },
30 |
31 | render: function() {
32 | var selectedPacket = this.props.selectedPacket || {};
33 | var frames = selectedPacket.stack ? selectedPacket.stack.frames : [];
34 |
35 | // Customize TreeView logic that is responsible for
36 | // returning object properties. In case of StackFrames
37 | // only props (not functions) are returned.
38 | // Result of the function is used for computing children
39 | // nodes in the tree view.
40 | function getObjectProperties(obj, callback) {
41 | for (var p in obj) {
42 | try {
43 | if (typeof obj[p] != "function") {
44 | callback(p, obj[p]);
45 | }
46 | }
47 | catch (e) {
48 | /* eslint: no-empty-block: 0*/
49 | }
50 | }
51 | }
52 |
53 | return (
54 | div({className: "stackSidePanel"},
55 | TreeView({key: "packet-detail", data: frames,
56 | getObjectProperties: getObjectProperties})
57 | )
58 | );
59 | }
60 | });
61 |
62 | // Exports from this module
63 | exports.PacketStackSidePanel = React.createFactory(PacketStackSidePanel);
64 | });
65 |
--------------------------------------------------------------------------------
/data/inspector/components/packet.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports /*, module */) {
4 |
5 | "use strict";
6 |
7 | // ReactJS
8 | const React = require("react");
9 |
10 | // Firebug SDK
11 | const { TreeView } = require("reps/tree-view");
12 |
13 | // RDP Inspector
14 | //const { TextWithTooltip } = require("./text-with-tooltip");
15 |
16 | // Constants
17 | const { div, span, ul, li, a } = React.DOM;
18 |
19 | // RDP Window injected APIs
20 | const { Locale, Str } = require("shared/rdp-inspector-window");
21 |
22 | /**
23 | * @template This template is responsible for rendering a packet.
24 | * Packets are rendered within {@link PacketList} sorted by time.
25 | *
26 | * A packet displays basic information in the list and can also
27 | * display inline preview of all inner fields.
28 | */
29 | var Packet = React.createClass({
30 | /** @lends Packet */
31 |
32 | displayName: "Packet",
33 |
34 | /**
35 | * Packet needs to be re-rendered only if the selection or
36 | * 'show inline details' option changes. This is an optimization
37 | * the makes the packet-list rendering a lot faster.
38 | */
39 | shouldComponentUpdate: function(nextProps, nextState) {
40 | var { contextMenu: prevContextMenu } = this.state || {};
41 | var { contextMenu: nextContextMenu } = nextState || {};
42 |
43 | return (this.props.selected != nextProps.selected ||
44 | this.props.showInlineDetails != nextProps.showInlineDetails ||
45 | prevContextMenu != nextContextMenu);
46 | },
47 |
48 | render: function() {
49 | var data = this.props.data;
50 | var packet = data.packet;
51 | var type = packet.type ? packet.type : "";
52 | var mode = "tiny";
53 | var classNames = ["packetPanel", data.type];
54 | var size = Str.formatSize(data.size);
55 | var time = data.time;
56 | //var stack = data.stack;
57 |
58 | // Use String.formatTime, but how to access from the content?
59 | var timeText = time.toLocaleTimeString() + "." + time.getMilliseconds();
60 | var previewData = {
61 | packet: packet
62 | };
63 |
64 | // Error packets have its own styling
65 | if (packet.error) {
66 | classNames.push("error");
67 | }
68 |
69 | // Selected packets are highlighted
70 | if (this.props.selected) {
71 | classNames.push("selected");
72 | }
73 |
74 | /*var topFrame = stack.getTopFrame();
75 | var stackFrameUrl = topFrame ? topFrame.getUrl() : null;
76 | var stackFrame = topFrame ? topFrame.getLabel() : null;*/
77 |
78 | // Inline preview component
79 | var preview = this.props.showInlineDetails ? TreeView(
80 | {data: previewData, mode: mode}) : null;
81 |
82 | if (this.props.data.type == "send") {
83 | return (
84 | div({className: classNames.join(" "), onClick: this.onClick,
85 | onContextMenu: this.onContextMenu},
86 | div({className: "packetBox"},
87 | div({className: "packetContent"},
88 | div({className: "body"},
89 | span({className: "text"},
90 | Locale.$STR("rdpInspector.label.sent") + " "
91 | ),
92 | span({className: "type"}, type),
93 | span({className: "text"},
94 | " " + Locale.$STR("rdpInspector.label.to") + " "
95 | ),
96 | span({className: "to"}, packet.to),
97 | div({},
98 | /*TextWithTooltip({
99 | tooltip: stackFrameUrl, className: "stackFrameLabel",
100 | onClick: this.onViewSource.bind(this, topFrame)},
101 | stackFrame
102 | ),*/
103 | span({className: "info"}, timeText + ", " + size)
104 | ),
105 | div({className: "preview"},
106 | preview
107 | )
108 | ),
109 | div({className: "boxArrow"})
110 | )
111 | ),
112 | this.state && this.state.contextMenu &&
113 | ul({className: "dropdown-menu", role: "menu", ref: "contextMenu",
114 | onMouseLeave: this.onContextMenuMouseLeave,
115 | style: {
116 | display: "block",
117 | top: this.state.contextMenuTop,
118 | left: this.state.contextMenuLeft
119 | }},
120 | li({role: "presentation"},
121 | a({ref: "editAndResendAction", onClick: this.onEditAndResendClick},
122 | "Edit and Resend"))
123 | )
124 | )
125 | );
126 | } else {
127 | return (
128 | div({className: classNames.join(" "), onClick: this.onClick},
129 | div({className: "packetBox"},
130 | div({className: "packetContent"},
131 | div({className: "boxArrow"}),
132 | div({className: "body"},
133 | div({className: "from"},
134 | span({className: "text"},
135 | Locale.$STR("rdpInspector.label.received") + " "
136 | ),
137 | span({}, type),
138 | span({className: "text"},
139 | " " + Locale.$STR("rdpInspector.label.from") + " "),
140 | span({}, packet.from),
141 | div({},
142 | /*TextWithTooltip({
143 | tooltip: stackFrameUrl, className: "stackFrameLabel",
144 | onClick: this.onViewSource.bind(this, topFrame)},
145 | stackFrame
146 | ),*/
147 | span({className: "info"}, timeText + ", " + size)
148 | )
149 | ),
150 | // NOTE: on issue #44, a long "consoleAPICall" received packet
151 | // was wrongly turned into a "div.errorMessage"
152 | packet.error ? div({className: "errorMessage"},
153 | div({}, packet.error),
154 | div({}, packet.message)
155 | ) : null,
156 | div({className: "preview"},
157 | preview
158 | )
159 | )
160 | )
161 | )
162 | )
163 | );
164 | }
165 | },
166 |
167 | // Event Handlers
168 | onEditAndResendClick: function() {
169 | this.setState({
170 | contextMenu: false
171 | });
172 | this.props.actions.editPacket(this.props.data.packet);
173 | },
174 |
175 | onContextMenuMouseLeave: function() {
176 | this.setState({
177 | contextMenu: false
178 | });
179 | },
180 |
181 | onContextMenu: function(event) {
182 | event.stopPropagation();
183 | event.preventDefault();
184 |
185 | this.setState({
186 | contextMenu: true,
187 | contextMenuTop: event.clientY - 16,
188 | contextMenuLeft: event.clientX - 16
189 | });
190 | this.props.actions.selectPacket(this.props.data);
191 | },
192 |
193 | onClick: function(event) {
194 | var target = event.target;
195 |
196 | event.stopPropagation();
197 | event.preventDefault();
198 |
199 | // If a 'memberLabel' is clicked inside the inline preview
200 | // tree, let's process it by the tree, so expansion and
201 | // collapsing works. Otherwise just select the packet.
202 | if (!target.classList.contains("memberLabel")) {
203 | this.props.actions.selectPacket(this.props.data);
204 | }
205 | },
206 |
207 | onViewSource: function(topFrame, event) {
208 | event.stopPropagation();
209 | event.preventDefault();
210 |
211 | this.props.actions.onViewSource({
212 | url: topFrame.url,
213 | lineNumber: topFrame.lineNumber
214 | });
215 | }
216 | });
217 |
218 | // Exports from this module
219 | exports.Packet = React.createFactory(Packet);
220 | exports.PacketComponent = Packet;
221 | });
222 |
--------------------------------------------------------------------------------
/data/inspector/components/packets-limit.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // ReactJS
8 | const React = require("react");
9 |
10 | // Constants
11 | const { div, span } = React.DOM;
12 |
13 | // RDP Window injected APIs
14 | const { Locale } = require("shared/rdp-inspector-window");
15 |
16 | /**
17 | * @template This template is responsible for rendering a message
18 | * at the top of the packet list that informs the user about reaching
19 | * the maximum limit of displayed packets. The message also displays
20 | * number of packets removed from the list.
21 | */
22 | var PacketsLimit = React.createClass({
23 | /** @lends PacketsLimit */
24 |
25 | displayName: "PacketsLimit",
26 |
27 | render: function() {
28 | var removedPackets = this.props.removedPackets;
29 | var label = Locale.$STR("rdpInspector.label.outOfLimit");
30 |
31 | // Render summary info
32 | return (
33 | div({className: "packetsLimit"},
34 | span({className: "text"}, removedPackets + " " + label)
35 | )
36 | );
37 | }
38 | });
39 |
40 | // Exports from this module
41 | exports.PacketsLimit = React.createFactory(PacketsLimit);
42 | });
43 |
--------------------------------------------------------------------------------
/data/inspector/components/packets-message.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // ReactJS
8 | const React = require("react");
9 |
10 | // Constants
11 | const { div } = React.DOM;
12 |
13 | /**
14 | * @template This template renders a generic message within the
15 | * packet list.
16 | */
17 | var PacketsMessage = React.createClass({
18 | /** @lends PacketsMessage */
19 |
20 | displayName: "PacketsMessage",
21 |
22 | render: function() {
23 | var packet = this.props.data;
24 | var message = packet.message;
25 | var time = packet.time;
26 |
27 | var timeText = time.toLocaleTimeString() + "." + time.getMilliseconds();
28 |
29 | // Render summary info
30 | return (
31 | div({className: "packetsMessage"},
32 | div({className: "text"}, message),
33 | div({className: "time"}, timeText)
34 | )
35 | );
36 | }
37 | });
38 |
39 | // Exports from this module
40 | exports.PacketsMessage = React.createFactory(PacketsMessage);
41 | });
42 |
--------------------------------------------------------------------------------
/data/inspector/components/packets-panel.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // Dependencies
8 | const React = require("react");
9 |
10 | // Firebug SDK
11 | const { createFactories } = require("reps/rep-utils");
12 | const { Splitter } = createFactories(require("reps/splitter"));
13 |
14 | // RDP Inspector
15 | const { PacketList } = require("./packet-list");
16 | const { PacketsSidebar } = require("./packets-sidebar");
17 | const { PacketsToolbar } = require("./packets-toolbar");
18 |
19 | // Shortcuts
20 | const { div } = React.DOM;
21 |
22 | /**
23 | * @template This template renders 'Packets' tab body.
24 | */
25 | var PacketsPanel = React.createClass({
26 | /** @lends PacketPanel */
27 |
28 | displayName: "PacketsPanel",
29 |
30 | getInitialState: function() {
31 | return {
32 | packets: this.props.packets,
33 | selectedPacket: null
34 | };
35 | },
36 |
37 | render: function() {
38 | var leftPanel = div({className: "mainPanel"},
39 | PacketsToolbar({
40 | actions: this.props.actions,
41 | showInlineDetails: this.props.showInlineDetails,
42 | packetCacheEnabled: this.props.packetCacheEnabled,
43 | paused: this.props.paused
44 | }),
45 | PacketList({
46 | data: this.props.packets,
47 | actions: this.props.actions,
48 | selectedPacket: this.props.selectedPacket,
49 | searchFilter: this.props.searchFilter,
50 | showInlineDetails: this.props.showInlineDetails,
51 | removedPackets: this.props.removedPackets
52 | })
53 | );
54 |
55 | var rightPanel = div({className: "sidePanel"},
56 | PacketsSidebar({
57 | selectedPacket: this.props.selectedPacket,
58 | editedPacket: this.props.editedPacket,
59 | actions: this.props.actions,
60 | actorIDs: this.props.actorIDs
61 | })
62 | );
63 |
64 | return (
65 | div({className: "packetsPanelBox"},
66 | Splitter({
67 | mode: "vertical",
68 | min: 200,
69 | leftPanel: leftPanel,
70 | rightPanel: rightPanel,
71 | innerBox: div({className: "innerBox"})
72 | })
73 | )
74 | );
75 | }
76 | });
77 |
78 | // Exports from this module
79 | exports.PacketsPanel = React.createFactory(PacketsPanel);
80 | exports.PacketsPanelComponent = PacketsPanel;
81 |
82 | });
83 |
--------------------------------------------------------------------------------
/data/inspector/components/packets-sidebar.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // ReactJS
8 | const React = require("react");
9 |
10 | // RDP Inspector
11 | const { PacketDetails } = require("./packet-details");
12 | const { PacketEditor } = require("./packet-editor");
13 | const { PacketStackSidePanel } = require("./packet-stack-sidepanel");
14 |
15 | // Constants
16 | const { Tabs, Tab } = require("shared/react-bootstrap-factories");
17 |
18 | /**
19 | * @template This template represents a list of packets displayed
20 | * inside the panel content.
21 | */
22 | var PacketsSidebar = React.createClass({
23 | /** @lends PacketsSidebar */
24 |
25 | displayName: "PacketsSidebar",
26 |
27 | getInitialState: function() {
28 | return {
29 | activeKey: 1
30 | };
31 | },
32 |
33 | onTabSelected: function(key) {
34 | this.setState({
35 | activeKey: key
36 | });
37 | },
38 |
39 | componentDidMount: function() {
40 | window.addEventListener("rdpinspector:switchToPacketEditorTab",
41 | this.onSwitchToPacketEditorTab);
42 | },
43 |
44 | componentWillUnmount: function() {
45 | window.removeEventListener("rdpinspector:switchToPacketEditorTab", this.onSwitchToPacketEditorTab);
46 | },
47 |
48 | onSwitchToPacketEditorTab: function() {
49 | this.setState({ activeKey: 2 });
50 | },
51 |
52 | render: function() {
53 | // TODO xxxRpl: externalize and localize sidebar tab titles
54 | return (
55 | Tabs({
56 | className: "sideBarTabbedArea", animation: false,
57 | activeKey: this.state.activeKey,
58 | onSelect: this.onTabSelected
59 | },
60 | Tab({ eventKey: 1, title: "Packet Details" },
61 | PacketDetails({
62 | selectedPacket: this.props.selectedPacket
63 | })
64 | ),
65 | Tab({ eventKey: 2, title: "Send Packet" },
66 | PacketEditor({
67 | actions: this.props.actions,
68 | actorIDs: this.props.actorIDs,
69 | editedPacket: this.props.editedPacket
70 | })
71 | ),
72 | Tab({ eventKey: 3, title: "Stack" },
73 | PacketStackSidePanel({
74 | actions: this.props.actions,
75 | selectedPacket: this.props.selectedPacket
76 | })
77 | )
78 | )
79 | );
80 | }
81 | });
82 |
83 | // Exports from this module
84 | exports.PacketsSidebar = React.createFactory(PacketsSidebar);
85 | exports.PacketsSidebarComponent = PacketsSidebar;
86 | });
87 |
--------------------------------------------------------------------------------
/data/inspector/components/packets-summary.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // ReactJS
8 | const React = require("react");
9 |
10 | // RDP Inspector
11 | const { TextWithTooltip } = require("./text-with-tooltip");
12 |
13 | // RDP Window injected APIs
14 | const { Locale, Str } = require("shared/rdp-inspector-window");
15 |
16 |
17 | // Constants
18 | const { div } = React.DOM;
19 |
20 | /**
21 | * @template This template is responsible for rendering packet summary
22 | * information. The summary can be inserted into the list by clicking
23 | * on 'Summary' button. It displays number of sent and received packets
24 | * and total amount of sent and received data.
25 | */
26 | var PacketsSummary = React.createClass({
27 | /** @lends PacketsSummary */
28 |
29 | displayName: "PacketsSummary",
30 |
31 | render: function() {
32 | var summary = this.props.data;
33 | var time = summary.time;
34 |
35 | var timeText = time.toLocaleTimeString() + "." + time.getMilliseconds();
36 | var sizeReceived = Str.formatSize(summary.data.received);
37 | var sizeSent = Str.formatSize(summary.data.sent);
38 |
39 | // Tooltips
40 | var sizeSentTip = Locale.$STR("rdpInspector.tooltip.sizeSent");
41 | var sizeReceivedTip = Locale.$STR("rdpInspector.tooltip.sizeReceived");
42 | var packetsSentTip = Locale.$STR("rdpInspector.tooltip.packetsSent");
43 | var packetsReceivedTip = Locale.$STR("rdpInspector.tooltip.packetsReceived");
44 |
45 | // Labels
46 | var packetsText = Locale.$STR("rdpInspector.label.packets");
47 | var dataText = Locale.$STR("rdpInspector.label.data");
48 |
49 | // Render summary info
50 | return (
51 | div({className: "packetsSummary"},
52 | div({className: "text"}, packetsText + ": "),
53 | TextWithTooltip({tooltip: packetsSentTip}, summary.packets.sent),
54 | div({className: "slash"}, " / "),
55 | TextWithTooltip({tooltip: packetsReceivedTip}, summary.packets.received),
56 | div({className: "separator"}),
57 | div({className: "text"}, dataText + ": "),
58 | TextWithTooltip({tooltip: sizeSentTip}, sizeSent),
59 | div({className: "slash"}, " / "),
60 | TextWithTooltip({tooltip: sizeReceivedTip}, sizeReceived),
61 | div({className: "separator"}),
62 | div({className: "time"}, timeText)
63 | )
64 | );
65 | }
66 | });
67 |
68 | // Exports from this module
69 | exports.PacketsSummary = React.createFactory(PacketsSummary);
70 | exports.PacketsSummaryComponent = PacketsSummary;
71 | });
72 |
--------------------------------------------------------------------------------
/data/inspector/components/packets-toolbar.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // ReactJS
8 | var React = require("react");
9 |
10 | // Constants
11 | const {
12 | ButtonToolbar, Button,
13 | DropdownButton, MenuItem,
14 | OverlayTrigger, Tooltip
15 | } = require("shared/react-bootstrap-factories");
16 |
17 | const { span, input } = React.DOM;
18 |
19 | // RDP Window injected APIs
20 | const { Locale } = require("shared/rdp-inspector-window");
21 |
22 | /**
23 | * @template This object represents a template for a toolbar displayed
24 | * within the Packets tab
25 | */
26 | var PacketsToolbar = React.createClass({
27 | /** @lends PacketsToolbar */
28 |
29 | displayName: "PacketsToolbar",
30 |
31 | render: function() {
32 | var { showInlineDetails, packetCacheEnabled } = this.props;
33 |
34 | var labels = {};
35 | labels.inlineDetails = Locale.$STR("rdpInspector.option.showInlineDetails");
36 | labels.cachePackets = Locale.$STR("rdpInspector.option.packetCacheEnabled");
37 |
38 | var tooltips = {};
39 | tooltips.inlineDetails = Locale.$STR("rdpInspector.option.showInlineDetails.tip");
40 | tooltips.cachePackets = Locale.$STR("rdpInspector.option.packetCacheEnabled.tip");
41 |
42 | var paused = this.props.paused;
43 | var pauseClassName = paused ? "btn-warning" : "";
44 |
45 | return (
46 | ButtonToolbar({className: "toolbar"},
47 | DropdownButton({ bsSize: "xsmall", ref: "fileMenu", title: Locale.$STR("rdpInspector.menu.File")},
48 | MenuItem({key: "fileLoad", ref: "fileLoad", onClick: this.onLoadPacketsFromFile },
49 | Locale.$STR("rdpInspector.cmd.load")),
50 | MenuItem({key: "fileSave", ref: "fileSave", onClick: this.onSavePacketsFromFile },
51 | Locale.$STR("rdpInspector.cmd.save"))
52 | ),
53 | DropdownButton({
54 | bsSize: "xsmall", title: Locale.$STR("rdpInspector.menu.Options"),
55 | className: "pull-right", ref: "options"
56 | },
57 | OverlayTrigger({placement: "bottom", overlay: Tooltip({}, tooltips.inlineDetails)},
58 | MenuItem({key: "inlineDetails", ref: "optionShowInlineDetails", onClick: this.onShowInlineDetails},
59 | input({type: "checkbox", checked: showInlineDetails}), labels.inlineDetails
60 | )
61 | ),
62 | OverlayTrigger({placement: "bottom", overlay: Tooltip({}, tooltips.cachePackets)},
63 | MenuItem({key: "cachePackets", ref: "optionCachePackets", onClick: this.onCachePackets},
64 | input({type: "checkbox", checked: packetCacheEnabled}), labels.cachePackets
65 | )
66 | )
67 | ),
68 | Button({bsSize: "xsmall", onClick: this.onClear},
69 | Locale.$STR("rdpInspector.cmd.clear")
70 | ),
71 | Button({bsSize: "xsmall", onClick: this.onFind},
72 | Locale.$STR("rdpInspector.cmd.find")
73 | ),
74 | Button({bsSize: "xsmall", onClick: this.onSummary},
75 | Locale.$STR("rdpInspector.cmd.summary")
76 | ),
77 | Button({bsSize: "xsmall", className: pauseClassName,
78 | onClick: this.onPause},
79 | span({className: "glyphicon glyphicon-pause", "aria-hidden": true})
80 | )
81 | )
82 | );
83 | },
84 |
85 | // Commands
86 |
87 | onClear: function(/*event*/) {
88 | this.props.actions.clear();
89 | },
90 |
91 | onFind: function(/*event*/) {
92 | this.props.actions.find();
93 | },
94 |
95 | onSummary: function(/*event*/) {
96 | this.props.actions.appendSummary();
97 | },
98 |
99 | onShowInlineDetails: function() {
100 | this.props.actions.onShowInlineDetails();
101 | },
102 |
103 | onCachePackets: function() {
104 | this.props.actions.onPacketCacheEnabled();
105 | },
106 |
107 | onPause: function(/*event*/) {
108 | this.props.actions.onPause();
109 | },
110 |
111 | onLoadPacketsFromFile: function(/*event*/) {
112 | this.props.actions.loadPacketsFromFile();
113 | this.refs.fileMenu.setState({ open: false });
114 |
115 | },
116 |
117 | onSavePacketsFromFile: function(/*event*/) {
118 | this.props.actions.savePacketsToFile();
119 | this.refs.fileMenu.setState({ open: false });
120 | }
121 | });
122 |
123 | // Exports from this module
124 | exports.PacketsToolbar = React.createFactory(PacketsToolbar);
125 | exports.PacketsToolbarComponent = PacketsToolbar;
126 | });
127 |
--------------------------------------------------------------------------------
/data/inspector/components/pools.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // Dependencies
8 | const React = require("react");
9 | const { tr, td, table, tbody, thead, th, div, h4 } = React.DOM;
10 |
11 | // Templates
12 |
13 | /**
14 | * TODO docs
15 | */
16 | var PoolRow = React.createFactory(React.createClass({
17 | /** @lends PoolRow */
18 |
19 | displayName: "PoolRow",
20 |
21 | render: function() {
22 | var actor = this.props;
23 | return (
24 | tr({className: "poolRow"},
25 | td({}, actor.actorID),
26 | td({}, actor.actorPrefix),
27 | td({}, actor.typeName),
28 | td({}, actor.parentID),
29 | td({}, actor.constructor)
30 | )
31 | );
32 | }
33 | }));
34 |
35 | /**
36 | * TODO docs
37 | * xxxHonza: localization
38 | */
39 | var PoolTable = React.createFactory(React.createClass({
40 | /** @lends PoolTable */
41 |
42 | displayName: "PoolTable",
43 |
44 | render: function() {
45 | var rows = [];
46 |
47 | // Iterate array of actors.
48 | var actors = this.props.pool;
49 | for (var i in actors) {
50 | if (this.props.searchFilter &&
51 | JSON.stringify(actors[i]).toLowerCase()
52 | .indexOf(this.props.searchFilter.toLowerCase()) < 0) {
53 | // filter out packets which don't match the filter
54 | continue;
55 | }
56 | actors[i].key = actors[i].actorID;
57 | rows.push(PoolRow(actors[i]));
58 | }
59 |
60 | // Pools are mixed with Actor objects (created using CreateClass).
61 | var className = "poolTable";
62 | if (this.props.actorClass) {
63 | className += " actorClass";
64 | }
65 |
66 | var id = this.props.id ? "ID: " + this.props.id : "";
67 |
68 | return (
69 | div({},
70 | h4({}, "Pool" + id),
71 | table({className: className},
72 | thead({className: "poolRow"},
73 | th({width: "20%"}, "Actor ID"),
74 | th({width: "20%"}, "Prefix"),
75 | th({width: "20%"}, "TypeName"),
76 | th({width: "20%"}, "Parent"),
77 | th({width: "20%"}, "Constructor")
78 | ),
79 | tbody(null, rows)
80 | )
81 | )
82 | );
83 | }
84 | }));
85 |
86 | /**
87 | * TODO docs
88 | */
89 | var PoolList = React.createFactory(React.createClass({
90 | /** @lends PoolList */
91 |
92 | displayName: "PoolList",
93 |
94 | getInitialState: function() {
95 | return {
96 | pools: []
97 | };
98 | },
99 |
100 | render: function() {
101 | var pools = [];
102 |
103 | for (var i in this.state.pools) {
104 | var poolData = this.state.pools[i];
105 | var pool = poolData.pool;
106 | var poolId = poolData.id;
107 |
108 | var actorClass = false;
109 |
110 | // xxxHonza: there are actors stored as pools.
111 | // See also: https://bugzilla.mozilla.org/show_bug.cgi?id=1119790#c1
112 | if (!Array.isArray(pool)) {
113 | pool = [pool];
114 | actorClass = true;
115 | }
116 |
117 | pools.push(PoolTable({
118 | pool: pool,
119 | actorClass: actorClass,
120 | id: poolId,
121 | key: i,
122 | searchFilter: this.state.searchFilter
123 | }));
124 | }
125 |
126 | return (
127 | div({className: "poolContainer"},
128 | pools
129 | )
130 | );
131 | }
132 | }));
133 |
134 | var Pools = {
135 | render: function(parentNode) {
136 | return React.render(PoolList(), parentNode);
137 | }
138 | };
139 |
140 | // Exports from this module
141 | exports.Pools = Pools;
142 |
143 | });
144 |
--------------------------------------------------------------------------------
/data/inspector/components/search-box.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | /**
8 | * TODO docs xxxHonza: can we use ReactJS?
9 | */
10 | var SearchBox =
11 | /** @lends SearchBox */
12 | {
13 | create: function(parentNode) {
14 | var doc = parentNode.ownerDocument;
15 | var tabArea = doc.querySelector(".mainTabbedArea [role=tablist] .nav-tabs");
16 | var item = doc.createElement("li");
17 | tabArea.appendChild(item);
18 |
19 | // Search box
20 | var searchBox = doc.createElement("input");
21 | searchBox.setAttribute("class", "searchBox");
22 | searchBox.setAttribute("type", "search");
23 | searchBox.setAttribute("results", "true");
24 | item.appendChild(searchBox);
25 |
26 | searchBox.addEventListener("command", this.onChange.bind(this, searchBox), false);
27 | searchBox.addEventListener("input", this.onChange.bind(this, searchBox), false);
28 | searchBox.addEventListener("keypress", this.onKeyPress.bind(this, searchBox), false);
29 | },
30 |
31 | destroy: function(parentNode) {
32 | var doc = parentNode.ownerDocument;
33 | var searchBox = doc.querySelector(".searchBox");
34 | searchBox.remove();
35 | },
36 |
37 | onKeyPress: function(searchBox/*, event*/) {
38 | this.onSearch(searchBox);
39 | },
40 |
41 | onChange: function(searchBox/*, event*/) {
42 | this.onSearch(searchBox);
43 | },
44 |
45 | onSearch: function(searchBox) {
46 | var win = searchBox.ownerDocument.defaultView;
47 | var event = new win.MessageEvent("search", {
48 | data: searchBox.value
49 | });
50 | win.dispatchEvent(event);
51 | }
52 | };
53 |
54 | // Exports from this module
55 | exports.SearchBox = SearchBox;
56 | });
57 |
--------------------------------------------------------------------------------
/data/inspector/components/stack-frame-rep.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports /*, module */) {
4 |
5 | "use strict";
6 |
7 | // ReactJS
8 | const React = require("react");
9 |
10 | // Firebug SDK
11 | const { Reps } = require("reps/reps");
12 | const { ObjectBox } = require("reps/object-box");
13 |
14 | // Constants
15 | const { span } = React.DOM;
16 |
17 | // RDP Window injected APIs
18 | const { postChromeMessage } = require("shared/rdp-inspector-window");
19 |
20 | /**
21 | * This component is responsible for rendering a stack frame.
22 | */
23 | var StackFrameRep = React.createClass({
24 | /** @lends StackFrameRep */
25 |
26 | displayName: "StackFrameRep",
27 |
28 | render: function() {
29 | var stackFrame = this.props.object;
30 | var name = stackFrame.name;
31 | var label = stackFrame.getLabel();
32 |
33 | return (
34 | ObjectBox({className: "stackFrame"},
35 | span({className: "stackName"}, name + "()"),
36 | span({className: "stackLabel", onClick: this.onViewSource}, label)
37 | )
38 | );
39 | },
40 |
41 | onViewSource: function(event) {
42 | event.stopPropagation();
43 | event.preventDefault();
44 |
45 | // xxxHonza: how to get reference to the action list?
46 | /*this.props.actions.onViewSource({
47 | url: topFrame.fileName,
48 | lineNumber: topFrame.lineNumber
49 | });*/
50 |
51 | var frame = this.props.object;
52 | postChromeMessage("view-source", {
53 | url: frame.url,
54 | lineNumber: frame.lineNumber
55 | });
56 | }
57 | });
58 |
59 | // Registration
60 |
61 | function supportsObject(object/*, type*/) {
62 | return object instanceof StackFrame;
63 | }
64 |
65 | Reps.registerRep({
66 | rep: React.createFactory(StackFrameRep),
67 | supportsObject: supportsObject
68 | });
69 |
70 | // helper classes using in the packets reducers
71 |
72 | // StackTrace
73 |
74 | // xxxHonza: revisit frame filtering should and find solid way.
75 | function StackTrace(frames, packetType) {
76 | // Remove all frames before 'EventEmitter_emit()' frame.
77 | // These are part of the infrastructure (always there).
78 | if (packetType == "send") {
79 | //frames = filterFrames(frames, "DebuggerClient.requester/<");
80 | //frames = filterFrames(frames, "EventEmitter_emit");
81 | //frames = filterFrames(frames, "makeInfallible/<", true);
82 | }
83 |
84 | // Filter out empty frames
85 | frames = frames.filter(frame => !!frame.name);
86 |
87 | // Create StackFrame instances, so the right rep is used for
88 | // rendering (see {@StackFrameRep}.
89 | this.frames = frames.map(frame => new StackFrame(frame));
90 | }
91 |
92 | StackTrace.prototype = {
93 | hasFrames: function() {
94 | return this.frames.length > 0;
95 | },
96 |
97 | getTopFrame: function() {
98 | return this.hasFrames() ? this.frames[0] : null;
99 | },
100 | };
101 |
102 | // StackFrame
103 |
104 | function StackFrame(frame) {
105 | this.url = frame.fileName;
106 | this.lineNumber = frame.lineNumber;
107 | this.columnNumber = frame.columnNumber;
108 | this.name = frame.name;
109 | }
110 |
111 | StackFrame.prototype = {
112 | getLabel: function() {
113 | var path = this.url;
114 | var index = path ? path.lastIndexOf("/") : -1;
115 | var label = (index == -1) ? path : path.substr(index + 1);
116 |
117 | if (this.lineNumber) {
118 | label += ":" + this.lineNumber;
119 | }
120 |
121 | if (this.columnNumber) {
122 | label += ":" + this.columnNumber;
123 | }
124 |
125 | return label;
126 | },
127 |
128 | getUrl: function() {
129 | return this.url;
130 | }
131 | };
132 |
133 | // Helpers
134 |
135 | /* NOTE: currently unused */
136 | /*
137 | function filterFrames(frames, pivot, onlyFirst) {
138 | var frame;
139 |
140 | if (onlyFirst) {
141 | for (frame of frames) {
142 | if (frame.name == pivot) {
143 | frames.shift();
144 | } else {
145 | break;
146 | }
147 | }
148 | return frames;
149 | }
150 |
151 | var newFrames = [];
152 | var remove = true;
153 | for (frame of frames) {
154 | if (!remove) {
155 | newFrames.push(frame);
156 | }
157 |
158 | if (frame.name == pivot) {
159 | remove = false;
160 | }
161 | }
162 |
163 | // The pivot frame wasn't found.
164 | if (remove) {
165 | newFrames = frames;
166 | }
167 |
168 | return newFrames;
169 | }
170 | */
171 |
172 |
173 | // Exports from this module
174 | exports.StackFrameRep = StackFrameRep;
175 | exports.StackTrace = StackTrace;
176 | exports.StackFrame = StackFrame;
177 |
178 | });
179 |
--------------------------------------------------------------------------------
/data/inspector/components/text-with-tooltip.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // ReactJS
8 | const React = require("react");
9 |
10 | // Constants
11 | const { Tooltip, OverlayTrigger } = require("shared/react-bootstrap-factories");
12 |
13 | const { div } = React.DOM;
14 |
15 | /**
16 | * @template Helper template responsible for rendering a tooltip.
17 | */
18 | const TextWithTooltip = React.createFactory(React.createClass({
19 | displayName: "TextWithTooltip",
20 |
21 | render: function() {
22 | var tooltip = Tooltip({}, this.props.tooltip);
23 | return (
24 | OverlayTrigger({placement: "top", overlay: tooltip, delayShow: 200,
25 | delayHide: 150},
26 | div({className: this.props.className, onClick: this.props.onClick},
27 | this.props.children
28 | )
29 | )
30 | );
31 | }
32 | }));
33 |
34 | // Exports from this module
35 | exports.TextWithTooltip = TextWithTooltip;
36 | });
37 |
--------------------------------------------------------------------------------
/data/inspector/config.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | /* globals requirejs */
4 |
5 | // RequireJS configuration
6 | require.config({
7 | baseUrl: ".",
8 | scriptType: "application/javascript;version=1.8",
9 | paths: {
10 | "shared": "../shared",
11 | "jquery": "../lib/jquery/jquery",
12 | "react": "../lib/react/react",
13 | "react-dom": "../lib/react/react-dom",
14 | "bootstrap": "../lib/bootstrap/js/bootstrap",
15 | "immutable": "../lib/immutable/immutable",
16 | "react-bootstrap": "../lib/react-bootstrap/react-bootstrap",
17 | "reps": "../../node_modules/firebug.sdk/lib/reps",
18 | "firebug.sdk": "../../node_modules/firebug.sdk",
19 | "redux": "../lib/redux/redux",
20 | "react-redux": "../lib/redux/react-redux",
21 | }
22 | });
23 |
24 | // Load the main panel module
25 | requirejs(["main"]);
26 |
--------------------------------------------------------------------------------
/data/inspector/containers/app.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // React & Redux
8 | const React = require("react");
9 | const { connect } = require("react-redux");
10 |
11 | // Connections List components
12 | const MainTabbedArea = require("../components/main-tabbed-area");
13 |
14 | const App = React.createClass({
15 | displayName: "App",
16 |
17 | render() {
18 | return React.createElement(MainTabbedArea, {
19 | view: this.props.view,
20 | global: this.props.global,
21 | actors: this.props.actors,
22 | packets: this.props.packets,
23 | });
24 | }
25 | });
26 |
27 | function mapStoreToProps(state) {
28 | let { global, actors, packets } = state;
29 | return { global, actors, packets };
30 | }
31 |
32 | exports.App = connect(mapStoreToProps)(App);
33 |
34 | });
35 |
--------------------------------------------------------------------------------
/data/inspector/css/actors-panel.css:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | /******************************************************************************/
4 | /* Actors Panel */
5 |
6 | .poolContainer {
7 | font-size: 12px;
8 | }
9 |
10 | .poolTable {
11 | border: 1px solid rgb(221, 221, 221);
12 | width: 100%;
13 | margin-bottom: 10px;
14 | }
15 |
16 | .poolRow TD,
17 | .poolRow TH {
18 | border-bottom: 1px solid rgb(221, 221, 221);
19 | padding-left: 10px;
20 | }
21 |
22 | .poolTable.actorClass {
23 | background-color: rgb(247, 247, 247);
24 | }
25 |
--------------------------------------------------------------------------------
/data/inspector/css/base.css:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | /******************************************************************************/
4 | /* General */
5 |
6 | body {
7 | background-color: white;
8 | padding: 0;
9 | margin: 0;
10 | height: 100%;
11 | }
12 |
13 | *:focus {
14 | outline: none !important;
15 | }
16 |
17 | #content {
18 | height: 100%;
19 | }
20 |
21 | #content > DIV {
22 | height: 100%;
23 | }
24 |
--------------------------------------------------------------------------------
/data/inspector/css/packets-panel.css:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | /******************************************************************************/
4 | /* Packets Panel */
5 |
6 | .packetPanel {
7 | margin-bottom: 6px;
8 | font-size: 11px;
9 | font-family: Lucida Grande, Tahoma, sans-serif;
10 | line-height: 15px;
11 | }
12 |
13 | .packetPanel .packetBox {
14 | display: inline-block;
15 | max-width: 90%;
16 | }
17 |
18 | .packetPanel .packetContent {
19 | display: flex;
20 | }
21 |
22 | .packetPanel.receive .boxArrow {
23 | background-image: url("../res/received-arrow.png");
24 | background-repeat: no-repeat;
25 | background-position: 0 center;
26 | margin-right: -1px;
27 | order: 1;
28 | width: 8px;
29 | z-index: 2;
30 | min-width: 8px;
31 | }
32 |
33 | .packetPanel.receive.selected .boxArrow {
34 | background-image: url("../res/received-arrow-selected.png");
35 | }
36 |
37 | .packetPanel.send .boxArrow {
38 | background-image: url("../res/sent-arrow.png");
39 | background-repeat: no-repeat;
40 | background-position: 0 center;
41 | margin-left: -1px;
42 | order: 3;
43 | width: 9px;
44 | min-width: 9px;
45 | z-index: 2;
46 | }
47 |
48 | .packetPanel.send.selected .boxArrow {
49 | background-image: url("../res/sent-arrow-selected.png");
50 | }
51 |
52 | .packetPanel .body {
53 | display: inline-block;
54 | padding: 2px 5px 2px 5px;
55 | border: 1px solid #bfccd1;
56 | border-radius: 3px;
57 | min-width: 270px;
58 | background-image: linear-gradient(rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.0));
59 | order: 2;
60 | z-index: 1;
61 | }
62 |
63 | .packetPanel.receive .body {
64 | background-color: rgb(252, 248, 227);
65 | }
66 |
67 | .packetPanel.send .body {
68 | background-color: rgb(223, 240, 216);
69 | text-align: left;
70 | }
71 |
72 | .packetPanel.send {
73 | text-align: left;
74 | }
75 |
76 | .packetPanel.send {
77 | text-align: right;
78 | }
79 |
80 | .packetPanel .body .text {
81 | color: gray;
82 | }
83 |
84 | .packetPanel.error .body {
85 | background-color: rgb(255, 221, 221);
86 | }
87 |
88 | .packetPanel.selected .body {
89 | border-color: rgb(0, 170, 214);
90 | background-color: rgb(173, 211, 232);
91 | }
92 |
93 | .packetPanel .type,
94 | .packetPanel .to,
95 | .packetPanel .from {
96 | color: red;
97 | font-family: monospace;
98 | }
99 |
100 | .packetPanel .info {
101 | color: gray;
102 | font-size: 10px;
103 | text-align: right;
104 | margin-left: 20px;
105 | display: inline-flex;
106 | font-family: monospace;
107 | float: right;
108 | padding-top: 4px;
109 | }
110 |
111 | .packetPanel .stack:hover {
112 | text-decoration: underline;
113 | }
114 |
115 | .packetPanel .arrow {
116 | margin: 0 5px 0 5px;
117 | }
118 |
119 | .packetPanel .arrow.hide {
120 | display: none;
121 | }
122 | .packetPanel .from {
123 | padding-bottom: 5px;}
124 |
125 | .packetPanel .errorMessage {
126 | color: red;
127 | margin-bottom: 5px;
128 | }
129 |
130 | /******************************************************************************/
131 | /* Inline Packet Details Preview */
132 |
133 | .packetPanel .preview {
134 | overflow: auto;
135 | width: 100%;
136 | }
137 |
138 | .packetPanel .memberRow:hover {
139 | background-color: transparent;
140 | }
141 |
142 | .packetPanel .domTable > tbody > tr > td {
143 | border-bottom: transparent;
144 | }
145 |
146 | /******************************************************************************/
147 |
148 | .packetsPanelBox {
149 | height: 100%;
150 | }
151 |
152 | .packetsPanelBox TD {
153 | vertical-align: top;
154 | }
155 |
156 | .packetsPanelBox .list {
157 | /* xxxHonza: minus the toolbar height*/
158 | height: calc(100% - 30px);
159 | overflow: auto;
160 | padding: 10px;
161 | }
162 |
163 | .packetsPanelBox .details {
164 | border-left: 1px solid #EFEFEF;
165 | height: 100%;
166 | overflow: auto;
167 | }
168 |
169 | .tabPacketsPane {
170 | height: 100%;
171 | padding: 0px;
172 | }
173 |
174 | /******************************************************************************/
175 | /* Packets Summary */
176 |
177 | .packetsSummary {
178 | color: gray;
179 | font-size: 10px;
180 | border-top: 1px dotted #EFEFEF;
181 | margin: 10px 0 20px 0;
182 | padding: 2px 0 2px 0;
183 | }
184 |
185 | .packetsSummary DIV {
186 | display: inline-block;
187 | }
188 |
189 | .packetsSummary .time {
190 | float: right;
191 | font-family: monospace;
192 | }
193 |
194 | .packetsSummary .separator {
195 | width: 20px;
196 | }
197 |
198 | .packetsSummary .text {
199 | padding-right: 3px;
200 | }
201 |
202 | .packetsSummary .slash {
203 | width: 10px;
204 | text-align: center;
205 | }
206 |
207 | .tooltip-inner {
208 | max-width: 110px;
209 | }
210 |
211 | /******************************************************************************/
212 | /* Packets Limit */
213 |
214 | .packetsLimit {
215 | text-align: center;
216 | margin: 10px 0 20px 0;
217 | }
218 |
219 | .packetsLimit .text {
220 | padding: 2px 3px 2px 3px;
221 | color: gray;
222 | font-size: 12px;
223 | border: 1px solid #bfccd1;
224 | border-radius: 3px;
225 | background-color: rgb(219, 234, 249) !important;
226 | background-image: linear-gradient(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.2));
227 | }
228 |
229 | /******************************************************************************/
230 | /* Packets Message */
231 |
232 | .packetsMessage {
233 | color: gray;
234 | font-size: 10px;
235 | border-top: 1px dotted #EFEFEF;
236 | margin: 10px 0 20px 0;
237 | padding: 2px 0 2px 0;
238 | }
239 |
240 | .packetsMessage DIV {
241 | display: inline-block;
242 | }
243 |
244 | .packetsMessage .time {
245 | float: right;
246 | font-family: monospace;
247 | }
248 |
249 | .packetsMessage .text {
250 | padding-right: 3px;
251 | }
252 |
253 | /******************************************************************************/
254 | /* StackFrame */
255 |
256 | .stackSidePanel {
257 | height: 100%;
258 | overflow: auto;
259 | }
260 |
261 | .stackSidePanel .preview {
262 | overflow: auto;
263 | width: 100%;
264 | }
265 |
266 | .stackSidePanel .objectBox-stackFrame .stackName {
267 | display: inline-flex;
268 | font-family: monospace;
269 | float: left;
270 | text-align: left;
271 | }
272 |
273 | .packetPanel .stackFrameLabel,
274 | .stackSidePanel .objectBox-stackFrame .stackLabel {
275 | color: blue;
276 | text-align: right;
277 | display: inline-flex;
278 | font-family: monospace;
279 | float: right;
280 | cursor: pointer;
281 | margin-right: 4px;
282 | }
283 |
284 | .packetPanel .stackFrameLabel {
285 | font-size: 10px;
286 | margin-top: 4px;
287 | float: left;
288 | }
289 |
--------------------------------------------------------------------------------
/data/inspector/css/search-box.css:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | /******************************************************************************/
4 | /* Search Box */
5 |
6 | .searchBox {
7 | height: 21px;
8 | font-size: 12px;
9 | margin-top: 2px;
10 | border: 1px solid rgb(170, 188, 207);
11 | width: 200px;
12 | position: fixed; /* xxxHonza: how to avoid fixed position? */
13 | right: 5px;
14 | background-image: url("chrome://rdpinspector/skin/search.svg");
15 | background-repeat: no-repeat;
16 | background-position: 2px center;
17 | padding-left: 20px;
18 | }
19 |
--------------------------------------------------------------------------------
/data/inspector/css/toolbar.css:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | /******************************************************************************/
4 | /* Toolbar */
5 |
6 | .toolbar {
7 | height: 30px;
8 | padding: 4px;
9 | border-bottom: 1px solid rgb(170, 188, 207);
10 | background-color: rgb(219, 234, 249) !important;
11 | background-image: linear-gradient(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.2));
12 | }
13 |
14 | .toolbar .btn {
15 | border-radius: 2px;
16 | color: #141414;
17 | }
18 |
19 | .toolbar select {
20 | margin-left: 3px;
21 | line-height: 1.0;
22 | font-size: 12px;
23 | }
24 |
25 | .toolbar input[type="checkbox"] {
26 | margin-right: 8px;
27 | }
28 |
29 | /******************************************************************************/
30 | /* Tooltip */
31 |
32 | .tooltip .tooltip-inner {
33 | background-color: #EEE1B3;
34 | color: black;
35 | max-width: 300px;
36 | }
37 | .tooltip.bottom .tooltip-arrow {
38 | border-bottom-color: #EEE1B3;
39 | color: black;
40 | }
41 |
--------------------------------------------------------------------------------
/data/inspector/css/toolbox.css:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | /******************************************************************************/
4 | /* Main Tabs */
5 |
6 | .mainTabbedArea {
7 | background-color: rgb(219, 234, 249);
8 | background-image: linear-gradient(rgba(253, 253, 253, 0.2), rgba(253, 253, 253, 0));
9 | }
10 |
11 | .mainTabbedArea li a {
12 | padding: 3px 8px;
13 | font-weight: bold;
14 | color: #565656;
15 | }
16 |
17 | .mainTabbedArea li.active a,
18 | .mainTabbedArea li.active a:focus {
19 | background-color: rgb(247, 251, 254);
20 | border: 1px solid rgb(170, 188, 207);
21 | border-bottom-color: transparent;
22 | }
23 |
24 | .mainTabbedArea li:hover a {
25 | border: 1px solid #C8C8C8;
26 | border-bottom: 1px solid transparent;
27 | background-color: transparent !important;
28 | }
29 |
30 | .mainTabbedArea li.active:hover a {
31 | border: 1px solid rgb(170, 188, 207) !important;
32 | background-color: rgb(247, 251, 254) !important;
33 | border-bottom-color: transparent !important;
34 | }
35 |
36 | .mainTabbedArea .nav-tabs {
37 | padding-top: 3px;
38 | padding-left: 3px;
39 | height: 30px;
40 | border-bottom-color: rgb(170, 188, 207);
41 | background-color: rgb(219, 234, 249) !important;
42 | background-image: linear-gradient(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.2));
43 | }
44 |
45 | .tab-content {
46 | /* xxxHonza: minus the height of the tab bar */
47 | height: calc(100% - 31px);
48 | }
49 |
50 | .tab-pane {
51 | height: 100%;
52 | padding: 0px;
53 | background-color: white;
54 | }
55 |
56 | /******************************************************************************/
57 | /* SideBar */
58 |
59 | .sideBarTabbedArea {
60 | height: 30px;
61 | border-bottom: 1px solid rgb(170, 188, 207);
62 | background-color: rgb(219, 234, 249) !important;
63 | background-image: linear-gradient(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.2));
64 | }
65 |
66 | .sideBarTabbedArea li a {
67 | padding: 4px 9px;
68 | font-weight: normal;
69 | font-size: 12px;
70 | font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
71 | color: #141414;
72 | }
73 |
74 | .sideBarTabbedArea li.active a,
75 | .sideBarTabbedArea li.active a:focus {
76 | background-color: white;
77 | border: 1px solid rgb(170, 188, 207);
78 | border-bottom-color: transparent;
79 | color: #141414;
80 | }
81 |
82 | .sideBarTabbedArea li:hover a {
83 | border-color: #C8C8C8;
84 | background-color: transparent;
85 | }
86 |
87 | .sideBarTabbedArea li.active:hover a {
88 | border: 1px solid rgb(170, 188, 207) !important;
89 | border-bottom-color: transparent !important;
90 | color: #141414 !important;
91 | }
92 |
93 | .sideBarTabbedArea.nav-tabs {
94 | padding-top: 3px;
95 | padding-left: 3px;
96 | }
97 |
98 | /******************************************************************************/
99 | /* Panels */
100 |
101 | .mainPanel {
102 | height: 100%;
103 | }
104 |
105 | .sidePanel {
106 | height: 100%;
107 | }
108 |
109 | .sidePanel > DIV {
110 | height: 100%;
111 | }
112 |
113 | /******************************************************************************/
114 | /* Actors Panels */
115 |
116 | .actorsPanelBox {
117 | height: calc(100% - 30px);
118 | }
119 |
120 | .actorsScrollBox {
121 | height: 100%;
122 | padding: 10px;
123 | overflow: auto;
124 | }
125 |
--------------------------------------------------------------------------------
/data/inspector/css/tree-editor-view.css:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | /******************************************************************************/
4 | /* Tree Editor View */
5 |
6 | /* remove button on editable field */
7 | .domTable.editable .memberRow .closeButton {
8 | display: none;
9 | position: absolute;
10 | right: 2px;
11 | }
12 |
13 | .domTable.editable .memberRow:hover .closeButton {
14 | display: inline-block;
15 | }
16 |
17 | /* new field row */
18 | .domTable.editable .memberRow.newRow {
19 | background: #FFFEE1;
20 | }
21 |
22 | .domTable.editable .memberRow.newRow input {
23 | border: none;
24 | background: transparent;
25 | width: 100%;
26 | }
27 |
28 | .domTable.editable .memberRow.editRow input {
29 | border: 1px groove;
30 | width: 100%;
31 | }
32 |
33 | .domTable.editable .memberRow.editRow input.valid {
34 | border-color: green;
35 | background-color: rgba(0,210,0,0.2);
36 | }
37 |
38 | .domTable.editable .memberRow.editRow input.invalid {
39 | border-color: red;
40 | background-color: rgba(210,0,0,0.2);
41 | }
42 |
43 | .domTable.editable ul.suggestions {
44 | position: absolute;
45 | z-index: 9999;
46 | padding: 0;
47 | margin: 0;
48 | background-color: white;
49 | color: black;
50 | border: 1px solid buttonshadow;
51 | cursor: default;
52 | text-align: left;
53 | list-style-type: none;
54 | overflow: hidden;
55 | }
56 |
57 | .domTable.editable ul.suggestions:hover {
58 | overflow: auto;
59 | }
60 |
61 | .domTable.editable ul.suggestions li {
62 | padding: 2px;
63 | }
64 |
65 | .domTable.editable ul.suggestions li:hover {
66 | background: yellow;
67 | color: black;
68 | }
69 |
70 | /* FIX: missing close button on hover */
71 | .closeButton:hover {
72 | filter: url("resource://rdpinspector-at-getfirebug-dot-com/node_modules/firebug.sdk/skin/classic/shared/filters.svg#darken") !important;
73 | }
74 |
--------------------------------------------------------------------------------
/data/inspector/frame-script.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | (function(global) {
4 |
5 | "use strict";
6 |
7 | const {
8 | Components,
9 | content,
10 | addEventListener,
11 | sendAsyncMessage,
12 | addMessageListener,
13 | /*removeMessageListener,*/
14 | } = global;
15 |
16 | const Cu = Components.utils;
17 | /*const Cc = Components.classes;
18 | const Ci = Components.interfaces;*/
19 |
20 | /*const document = content.document;*/
21 | const window = content;
22 |
23 | /**
24 | * Listener for message from the chrome scope. It's further distributed
25 | * as DOM event, so it can be handled by the page content script.
26 | */
27 | function messageListener(message) {
28 | const { type, data, origin, bubbles, cancelable } = message.data;
29 |
30 | const event = new window.MessageEvent(type, {
31 | bubbles: bubbles,
32 | cancelable: cancelable,
33 | data: data,
34 | origin: origin,
35 | target: window,
36 | source: window
37 | });
38 |
39 | window.dispatchEvent(event);
40 | }
41 |
42 | addMessageListener("rdpinspector/event/message", messageListener);
43 |
44 | /**
45 | * Send a message back to the parent panel (chrome scope).
46 | */
47 | function postChromeMessage(type, args, objects) {
48 | let data = {
49 | type: type,
50 | args: args
51 | };
52 |
53 | sendAsyncMessage("message", data, objects);
54 | }
55 |
56 | /**
57 | * Export 'postChromeMessage' function to the frame content as soon
58 | * as it's loaded. This function allows sending messages from the
59 | * frame's content directly to the chrome scope.
60 | */
61 | addEventListener("DOMContentLoaded", function onContentLoaded(/*event*/) {
62 | removeEventListener("DOMContentLoaded", onContentLoaded, true);
63 |
64 | Cu.exportFunction(postChromeMessage, window, {
65 | defineAs: "postChromeMessage"
66 | });
67 | }, true);
68 |
69 | // End of scope
70 | })(this);
71 |
--------------------------------------------------------------------------------
/data/inspector/main.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/data/inspector/main.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require/*, exports, module*/) {
4 |
5 | "use strict";
6 |
7 | // ReactJS
8 | var ReactDOM = require("react-dom");
9 |
10 | // RDP Inspector
11 | const { Resizer } = require("shared/resizer");
12 | const { ReactLazyFactories } = require("shared/react-helpers");
13 |
14 | // generate React Factories
15 | const { Provider } = ReactLazyFactories(require("react-redux"));
16 | const { App } = ReactLazyFactories(require("./containers/app"));
17 |
18 | // Reps
19 | require("./components/stack-frame-rep");
20 |
21 | // Search
22 | var { Search } = require("./search");
23 |
24 | // RDP Window injected APIs
25 | var { postChromeMessage, RDPInspectorView } = require("shared/rdp-inspector-window");
26 |
27 | // actions & store
28 | const store = window.store = require("./store").configureStore();
29 | const actions = require("./actions/index.js");
30 |
31 | const view = new RDPInspectorView({
32 | window, actions, store,
33 | });
34 |
35 | /**
36 | * Render the main application component. It's the main tab bar displayed
37 | * at the top of the window. This component also represents ReactJS root.
38 | */
39 | view.render = function() {
40 | let content = document.querySelector("#content");
41 | let provider = Provider({ store }, App({ view }));
42 | let app = ReactDOM.render(provider, content);
43 |
44 | /* eslint-disable no-new */
45 | new Resizer(window, app);
46 | new Search(window, store);
47 | /* eslint-enable */
48 | };
49 |
50 | view.render();
51 | // Send notification about initialization being done.
52 | postChromeMessage("initialized");
53 |
54 | // End of main.js
55 | });
56 |
--------------------------------------------------------------------------------
/data/inspector/reducers/actors.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports, module) {
4 |
5 | "use strict";
6 |
7 | // actions types
8 | const { types } = require("../actions/actors");
9 |
10 | /**
11 | * Initial state definition
12 | */
13 | const initialState = {};
14 |
15 | function actorsReducer(state = initialState, action) {
16 | switch(action.type) {
17 | case types.SET_ACTORS:
18 | return setActors(state, action.actors);
19 | case types.CLEAR_ACTORS:
20 | return clearActors(state);
21 | default:
22 | return state;
23 | }
24 | }
25 |
26 | module.exports = actorsReducer;
27 |
28 | // helpers
29 | function clearActors() {
30 | return {};
31 | }
32 |
33 | function setActors(state, actors) {
34 | let { tab, global } = actors;
35 | let actorIDs = collectActorIDs([
36 | tab.actorPool,
37 | tab.extraPools,
38 | global.actorPool,
39 | global.extraPools
40 | ], []);
41 |
42 | return Object.assign({}, state, {
43 | tab, global, actorIDs
44 | });
45 | }
46 |
47 | function collectActorIDs(data, res) {
48 | if (data instanceof Array) {
49 | data.forEach((item) => {
50 | collectActorIDs(item, res);
51 | });
52 | } else if (data instanceof Object) {
53 | if (data.pool) {
54 | collectActorIDs(data.pool, res);
55 | } else if (data.actorID) {
56 | var { actorID } = data;
57 | if (res.indexOf(actorID) < 0) {
58 | res.push(actorID);
59 | }
60 | }
61 | }
62 |
63 | return res;
64 | }
65 | });
66 |
--------------------------------------------------------------------------------
/data/inspector/reducers/global.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports, module) {
4 |
5 | "use strict";
6 |
7 | // actions types
8 | const { types } = require("../actions/global");
9 |
10 | /**
11 | * Initial state definition
12 | */
13 | const initialState = {};
14 |
15 | function globalReducer(state = initialState, action) {
16 | switch(action.type) {
17 | case types.SET_SEARCH_FILTER:
18 | return setSearchFilter(state, action.filter);
19 | default:
20 | return state;
21 | }
22 | }
23 |
24 | module.exports = globalReducer;
25 |
26 |
27 | function setSearchFilter(state, filter) {
28 | return Object.assign({}, state, {
29 | searchFilter: filter
30 | });
31 | }
32 |
33 | });
34 |
--------------------------------------------------------------------------------
/data/inspector/reducers/index.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // Redux
8 | const { combineReducers } = require("redux");
9 |
10 | // RDP Inspector
11 | const global = require("./global");
12 | const actors = require("./actors");
13 | const packets = require("./packets");
14 |
15 | var rootReducer = combineReducers({ global, actors, packets });
16 |
17 | // Exports from this module
18 | exports.rootReducer = rootReducer;
19 | });
20 |
--------------------------------------------------------------------------------
/data/inspector/reducers/packets.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports, module) {
4 |
5 | "use strict";
6 |
7 | // RDP Window injected APIs
8 | const { Options, Locale } = require("shared/rdp-inspector-window");
9 | const { StackTrace } = require("../components/stack-frame-rep");
10 |
11 | // actions types
12 | const { types } = require("../actions/packets");
13 |
14 | /**
15 | * Initial state definition
16 | */
17 | const initialState = {
18 | paused: false,
19 | uniqueId: 0,
20 | options: {},
21 | filter: null,
22 | editedPacket: null,
23 | selectedPacket: null,
24 | removedPackets: 0,
25 | filteredPackets: [],
26 | packets: [],
27 | summary: {
28 | data: { sent: 0, received: 0},
29 | packets: { sent: 0, received: 0}
30 | },
31 | error: null,
32 | };
33 |
34 | function packetsReducer(state = initialState, action) {
35 | switch(action.type) {
36 | case types.IMPORT_PACKETS_FROMFILE:
37 | return importPacketsFromFile(state, action.data);
38 | case types.IMPORT_PACKETS_CACHE:
39 | return importPacketsCache(state, action.cache);
40 | case types.INIT_PACKETLIST_OPTIONS:
41 | return initPacketListOptions(state, action.options);
42 | case types.TOGGLE_PACKETLIST_OPTION:
43 | return togglePacketListOption(state, action.name);
44 | case types.TOGGLE_PACKETLIST_PAUSE:
45 | return togglePacketListPause(state);
46 | case types.APPEND_PACKET:
47 | return appendPacket(state, action.packetType, action.packetData);
48 | case types.APPEND_SUMMARY:
49 | return appendSummary(state, action.time);
50 | case types.APPEND_MESSAGE:
51 | return appendMessage(state, action.message, action.time);
52 | case types.SELECT_PACKET:
53 | return selectPacket(state, action.packet);
54 | case types.EDIT_PACKET:
55 | return editPacket(state, action.packet);
56 | case types.CLEAR_PACKET_LIST:
57 | return clearPacketList(state);
58 | case types.SET_PACKETLIST_ERROR:
59 | return setPacketListError(state, action.error);
60 | default:
61 | return state;
62 | }
63 | }
64 |
65 | module.exports = packetsReducer;
66 |
67 | // helpers
68 |
69 | function importPacketsFromFile(state, data) {
70 | let removedPackets = data.removedPackets || 0;
71 | let newState = clearPacketList(state);
72 |
73 | if (data.packets && data.packets.length > 0) {
74 | for (let packet of data.packets) {
75 | newState = appendToCollectedPackets(newState, packet);
76 | }
77 | }
78 |
79 | return Object.assign({}, newState, { removedPackets });
80 | }
81 |
82 | function importPacketsCache(state, cache) {
83 | let removedPackets = cache.removedPackets || 0;
84 | let newState = state;
85 |
86 | if (cache.packets && cache.packets.length > 0) {
87 | for (let packet of cache.packets) {
88 | // TODO: Trace errors
89 | newState = appendPacket(newState, packet.type, packet);
90 | }
91 | }
92 |
93 | return Object.assign({}, newState, { removedPackets });
94 | }
95 |
96 | function initPacketListOptions(state, options) {
97 | return Object.assign({}, state, {
98 | options
99 | });
100 | }
101 |
102 | function togglePacketListOption(state, name) {
103 | let options = JSON.parse(JSON.stringify(state.options));
104 | options[name] = !options[name];
105 |
106 | return Object.assign({}, state, {
107 | options
108 | });
109 | }
110 |
111 | function togglePacketListPause(state) {
112 | let paused = !state.paused;
113 | let newState;
114 |
115 | if (paused) {
116 | newState = appendMessage(state, Locale.$STR("rdpInspector.label.Paused"), new Date());
117 | } else {
118 | newState = appendMessage(state, Locale.$STR("rdpInspector.label.Unpaused"), new Date());
119 | }
120 |
121 | return Object.assign({}, newState, {
122 | paused
123 | });
124 | }
125 |
126 | function appendToCollectedPackets(state, packet) {
127 | let limit = Options.getPref("extensions.rdpinspector.packetLimit");
128 |
129 | if (state.packets.length >= limit) {
130 | state.packets.shift();
131 | }
132 |
133 | let summary = JSON.parse(JSON.stringify(state.summary));
134 |
135 | switch (packet.type) {
136 | case "send":
137 | summary.data.sent += packet.size;
138 | summary.packets.sent += 1;
139 | break;
140 | case "receive":
141 | summary.data.received += packet.size;
142 | summary.packets.received += 1;
143 | break;
144 | }
145 |
146 | packet.id = ++state.uniqueId;
147 |
148 | let packets = [ ...state.packets, packet];
149 | let filteredPackets = filterRDPInspectPackets(packets);
150 |
151 | return Object.assign({}, state, {
152 | summary, packets, filteredPackets
153 | });
154 | }
155 |
156 | function appendPacket(state, packetType, packetData) {
157 | let rawPacket = JSON.stringify(packetData.packet);
158 | let packet = {
159 | type: packetType,
160 | packet: packetData.packet,
161 | rawPacket,
162 | size: rawPacket.length,
163 | time: new Date(packetData.time),
164 | stack: new StackTrace(packetData.stack, packetType)
165 | };
166 |
167 | return appendToCollectedPackets(state, packet);
168 | }
169 |
170 | function appendSummary(state, time) {
171 | return appendToCollectedPackets(state, {
172 | type: "summary",
173 | time,
174 | data: {
175 | sent: state.summary.data.sent,
176 | received: state.summary.data.received
177 | },
178 | packets: {
179 | sent: state.summary.packets.sent,
180 | received: state.summary.packets.received
181 | }
182 | });
183 | }
184 |
185 | function appendMessage(state, message, time) {
186 | return appendToCollectedPackets(state, {
187 | type: "message", time, message
188 | });
189 | }
190 |
191 | function selectPacket(state, packet) {
192 | return Object.assign({}, state, {
193 | selectedPacket: packet
194 | });
195 | }
196 |
197 | function editPacket(state, packet) {
198 | return Object.assign({}, state, {
199 | editedPacket: packet
200 | });
201 | }
202 |
203 | function clearPacketList(state) {
204 | return Object.assign({}, state, {
205 | selectedPacket: null,
206 | packets: [],
207 | filteredPackets: [],
208 | summary: JSON.parse(JSON.stringify(initialState.summary))
209 | });
210 | }
211 |
212 | function setPacketListError(state, error) {
213 | // TODO: Trace errors
214 | return Object.assign({}, state, { error });
215 | }
216 |
217 | function filterRDPInspectPackets(packets) {
218 | var filterFrom = {};
219 |
220 | return packets.filter((packet) => {
221 | var actorId = packet.packet ? (packet.packet.to || packet.packet.from) : null;
222 |
223 | // filter our all the RDPi actorInspector actor
224 | if (actorId && actorId.indexOf("actorInspector") > 0) {
225 | return false;
226 | }
227 |
228 | if (packet.type == "send") {
229 | // filter sent RDP packets needed to register the RDPi actorInspector actor
230 | if (packet.packet.rdpInspectorInternals) {
231 | filterFrom[packet.packet.to] = filterFrom[packet.packet.to] || 0;
232 | filterFrom[packet.packet.to] += 1;
233 |
234 | return false;
235 | }
236 |
237 | // filter sent RDP packets needed to register the RDPi actorInspector actor
238 | if (packet.packet.type == "registerActor" &&
239 | packet.packet.filename.indexOf("rdpinspector-at-getfirebug-dot-com") > 0) {
240 | filterFrom[packet.packet.to] = filterFrom[packet.packet.to] || 0;
241 | filterFrom[packet.packet.to] += 1;
242 | return false;
243 | }
244 | }
245 |
246 | // filter received RDP packets needed to register the RDPi actorInspector actor
247 | if (packet.type == "receive" && filterFrom[packet.packet.from] > 0) {
248 | filterFrom[packet.packet.from] -= 1;
249 | return false;
250 | }
251 |
252 | return true;
253 | });
254 | }
255 |
256 | });
257 |
--------------------------------------------------------------------------------
/data/inspector/res/arrow.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
78 |
--------------------------------------------------------------------------------
/data/inspector/res/icon-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebug/rdp-inspector/60b22d880d9ea334e638b14c69102e8ed5c5c1e6/data/inspector/res/icon-16.png
--------------------------------------------------------------------------------
/data/inspector/res/received-arrow-selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebug/rdp-inspector/60b22d880d9ea334e638b14c69102e8ed5c5c1e6/data/inspector/res/received-arrow-selected.png
--------------------------------------------------------------------------------
/data/inspector/res/received-arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebug/rdp-inspector/60b22d880d9ea334e638b14c69102e8ed5c5c1e6/data/inspector/res/received-arrow.png
--------------------------------------------------------------------------------
/data/inspector/res/sent-arrow-selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebug/rdp-inspector/60b22d880d9ea334e638b14c69102e8ed5c5c1e6/data/inspector/res/sent-arrow-selected.png
--------------------------------------------------------------------------------
/data/inspector/res/sent-arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebug/rdp-inspector/60b22d880d9ea334e638b14c69102e8ed5c5c1e6/data/inspector/res/sent-arrow.png
--------------------------------------------------------------------------------
/data/inspector/search.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | const actions = require("./actions/index");
8 |
9 | /**
10 | * This object is responsible for listening search events
11 | * and updating application state (the root RJS component).
12 | */
13 | function Search(win, store) {
14 | this.win = win;
15 | this.store = store;
16 |
17 | this.win.addEventListener("search", this.onSearch.bind(this));
18 | }
19 |
20 | Search.prototype =
21 | /** @lends Search */
22 | {
23 | onSearch: function(event) {
24 | var value = event.data;
25 | this.store.dispatch(actions.setSearchFilter(value));
26 | }
27 | };
28 |
29 | // Exports from this module
30 | exports.Search = Search;
31 | });
32 |
--------------------------------------------------------------------------------
/data/inspector/store.js:
--------------------------------------------------------------------------------
1 | /* See license.txt for terms of usage */
2 |
3 | define(function(require, exports/*, module*/) {
4 |
5 | "use strict";
6 |
7 | // Redux
8 | const { createStore } = require("redux");
9 |
10 | // RDP Inspector
11 | const { rootReducer } = require("./reducers/index");
12 |
13 | function configureStore(initialState) {
14 | return createStore(rootReducer, initialState);
15 | }
16 |
17 | // Exports from this module
18 | exports.configureStore = configureStore;
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/data/lib/bootstrap/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebug/rdp-inspector/60b22d880d9ea334e638b14c69102e8ed5c5c1e6/data/lib/bootstrap/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/data/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebug/rdp-inspector/60b22d880d9ea334e638b14c69102e8ed5c5c1e6/data/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/data/lib/bootstrap/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebug/rdp-inspector/60b22d880d9ea334e638b14c69102e8ed5c5c1e6/data/lib/bootstrap/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/data/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebug/rdp-inspector/60b22d880d9ea334e638b14c69102e8ed5c5c1e6/data/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/data/lib/react/react-dom.js:
--------------------------------------------------------------------------------
1 | /**
2 | * ReactDOM v0.14.2
3 | *
4 | * Copyright 2013-2015, Facebook, Inc.
5 | * All rights reserved.
6 | *
7 | * This source code is licensed under the BSD-style license found in the
8 | * LICENSE file in the root directory of this source tree. An additional grant
9 | * of patent rights can be found in the PATENTS file in the same directory.
10 | *
11 | */
12 | // Based off https://github.com/ForbesLindesay/umd/blob/master/template.js
13 | ;(function(f) {
14 | // CommonJS
15 | if (typeof exports === "object" && typeof module !== "undefined") {
16 | module.exports = f(require('react'));
17 |
18 | // RequireJS
19 | } else if (typeof define === "function" && define.amd) {
20 | define(['react'], f);
21 |
22 | //