├── HEAD
├── sample1
├── .gitignore
├── manifest.json
├── README.md
├── .classpath
├── .project
├── build.xml
├── demo
│ └── sample1.html
└── src
│ └── org
│ └── webpki
│ └── w2nb
│ └── sample1
│ └── NativeClient.java
├── .gitattributes
├── proxy
├── install
│ ├── apps
│ │ ├── org.webpki.w2nb.sample1
│ │ │ ├── manifest.json
│ │ │ └── org.webpki.w2nb.sample1.jar
│ │ └── org.webpki.webpay.wallet3
│ │ │ ├── manifest.json
│ │ │ └── org.webpki.webpay.wallet3.jar
│ ├── logs
│ │ └── .gitignore
│ ├── libs
│ │ ├── proxy-support.jar
│ │ ├── bcprov-jdk15on-151.jar
│ │ └── webpki.org-libext-1.0.0.jar
│ ├── org.webpki.w2nb.moz.json
│ ├── uninstall_proxy.bat
│ ├── org.webpki.w2nb.json
│ ├── install_proxy.bat
│ ├── uninstall_proxy.sh
│ └── install_proxy.sh
├── windows-build
│ ├── w2nb-proxy.suo
│ ├── w2nb-proxy.v12.suo
│ ├── Debug
│ │ └── w2nb-proxy.exe
│ ├── w2nb-proxy
│ │ ├── w2nb-proxy.vcxproj.user
│ │ ├── w2nb-proxy.vcxproj.filters
│ │ └── w2nb-proxy.vcxproj
│ └── w2nb-proxy.sln
├── .gitignore
├── common.properties
├── .classpath
├── README.md
├── .project
├── java-build.xml
├── src.java
│ └── org
│ │ └── webpki
│ │ └── w2nbproxy
│ │ ├── LoggerConfiguration.java
│ │ ├── StdoutJSONPipe.java
│ │ ├── StdinJSONPipe.java
│ │ ├── BrowserWindow.java
│ │ └── ExtensionPositioning.java
└── src.cpp
│ └── w2nb-proxy.cpp
├── extension
├── debug
│ ├── icon-128.png
│ ├── manifest.json
│ ├── content.js
│ ├── inject.js
│ └── extension.js
├── release
│ ├── icon-128.png
│ ├── manifest.json
│ ├── content.js
│ ├── inject.js
│ └── extension.js
├── .project
├── README.md
└── release-build.xml
├── firefox
├── extension
│ ├── icon-128.png
│ ├── manifest.json
│ ├── content.js
│ ├── inject.js
│ └── extension.js
├── install
│ ├── xpi
│ │ └── web2native_bridge_emulator-1.0.xpi
│ ├── uninstall_proxy.bat
│ ├── install_proxy.bat
│ ├── uninstall_proxy.sh
│ └── install_proxy.sh
└── .project
├── config
├── README.md
└── AR2.xml
/HEAD:
--------------------------------------------------------------------------------
1 | ref: refs/heads/master
2 |
--------------------------------------------------------------------------------
/sample1/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | .tmp/
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Disable LF normalization for all files
2 | * -text
--------------------------------------------------------------------------------
/sample1/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "callableFrom": ["*://*/*", "file:///*"]
3 | }
--------------------------------------------------------------------------------
/proxy/install/apps/org.webpki.w2nb.sample1/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "callableFrom": ["*://*/*", "file:///*"]
3 | }
--------------------------------------------------------------------------------
/proxy/install/logs/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore everything in this directory
2 | *
3 | # Except this file
4 | !.gitignore
--------------------------------------------------------------------------------
/proxy/install/apps/org.webpki.webpay.wallet3/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "callableFrom": ["*://*/*", "file:///*"]
3 | }
4 |
--------------------------------------------------------------------------------
/extension/debug/icon-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyberphone/web2native-bridge/master/extension/debug/icon-128.png
--------------------------------------------------------------------------------
/extension/release/icon-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyberphone/web2native-bridge/master/extension/release/icon-128.png
--------------------------------------------------------------------------------
/firefox/extension/icon-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyberphone/web2native-bridge/master/firefox/extension/icon-128.png
--------------------------------------------------------------------------------
/proxy/install/libs/proxy-support.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyberphone/web2native-bridge/master/proxy/install/libs/proxy-support.jar
--------------------------------------------------------------------------------
/proxy/windows-build/w2nb-proxy.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyberphone/web2native-bridge/master/proxy/windows-build/w2nb-proxy.suo
--------------------------------------------------------------------------------
/config:
--------------------------------------------------------------------------------
1 | [core]
2 | symlinks = false
3 | repositoryformatversion = 0
4 | filemode = false
5 | bare = true
6 | logallrefupdates = false
7 |
--------------------------------------------------------------------------------
/proxy/windows-build/w2nb-proxy.v12.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyberphone/web2native-bridge/master/proxy/windows-build/w2nb-proxy.v12.suo
--------------------------------------------------------------------------------
/proxy/install/libs/bcprov-jdk15on-151.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyberphone/web2native-bridge/master/proxy/install/libs/bcprov-jdk15on-151.jar
--------------------------------------------------------------------------------
/proxy/windows-build/Debug/w2nb-proxy.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyberphone/web2native-bridge/master/proxy/windows-build/Debug/w2nb-proxy.exe
--------------------------------------------------------------------------------
/proxy/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/
2 | .tmp/
3 | /install/*.exe
4 | /windows-build/w2nb-proxy/Debug
5 | /windows-build/w2nb-proxy.sdf
6 | /install/logs/*.*
7 |
--------------------------------------------------------------------------------
/proxy/install/libs/webpki.org-libext-1.0.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyberphone/web2native-bridge/master/proxy/install/libs/webpki.org-libext-1.0.0.jar
--------------------------------------------------------------------------------
/proxy/common.properties:
--------------------------------------------------------------------------------
1 | webpki-libext.jar=webpki.org-libext-1.0.0.jar
2 |
3 | common.app.dir=../proxy/install/apps
4 | common.lib.dir=../proxy/install/libs
5 |
--------------------------------------------------------------------------------
/firefox/install/xpi/web2native_bridge_emulator-1.0.xpi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyberphone/web2native-bridge/master/firefox/install/xpi/web2native_bridge_emulator-1.0.xpi
--------------------------------------------------------------------------------
/proxy/windows-build/w2nb-proxy/w2nb-proxy.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/proxy/install/apps/org.webpki.w2nb.sample1/org.webpki.w2nb.sample1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyberphone/web2native-bridge/master/proxy/install/apps/org.webpki.w2nb.sample1/org.webpki.w2nb.sample1.jar
--------------------------------------------------------------------------------
/proxy/install/apps/org.webpki.webpay.wallet3/org.webpki.webpay.wallet3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cyberphone/web2native-bridge/master/proxy/install/apps/org.webpki.webpay.wallet3/org.webpki.webpay.wallet3.jar
--------------------------------------------------------------------------------
/proxy/install/org.webpki.w2nb.moz.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "org.webpki.w2nb.moz",
3 | "description": "Web2Native Bridge emulator",
4 | "path": "w2nb-proxy.exe",
5 | "type": "stdio",
6 | "allowed_extensions": ["w2nb@webpki.org"]
7 | }
8 |
--------------------------------------------------------------------------------
/extension/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | extension
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/firefox/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | firefox
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/extension/README.md:
--------------------------------------------------------------------------------
1 | ###Chrome Extension Source
2 | This project holds the part of the Web2Native Bridge that must be installed
3 | in Chrome or Chromium to make it work.
4 |
5 | Note that there are no restrictions on domains or protocols, you can even
6 | launch this extension from a local HTML file.
--------------------------------------------------------------------------------
/proxy/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/sample1/README.md:
--------------------------------------------------------------------------------
1 | ###Sample 1
2 | This project holds a miniscule application which high-lights
3 | the Web2Native Bridge API and technology.
4 |
5 | The application consists of two parts:
6 | * A Web page referring to a native application
7 | * The native application (in the emulator required to be in Java)
8 |
9 | Rebuilding the sample require **JDK 7** or **JDK 8** and **Ant**.
10 |
--------------------------------------------------------------------------------
/proxy/README.md:
--------------------------------------------------------------------------------
1 | ###The Proxy
2 | This project holds all pieces of a "proxy" which must be installed in the native platform.
3 |
4 | The proxy is the component that makes it possible for the Web2Native Bridge breaking away from
5 | Native Messaging's single application model.
6 |
7 | The proxy would be a part of a "genuine" Web2Native Bridge implementation as well. It would
8 | typically be a part of the operating system.
--------------------------------------------------------------------------------
/proxy/install/uninstall_proxy.bat:
--------------------------------------------------------------------------------
1 | :: Copyright 2014 The Chromium Authors. All rights reserved.
2 | :: Use of this source code is governed by a BSD-style license that can be
3 | :: found in the LICENSE file.
4 |
5 | :: Adapted for the Web2Native Bridge emulator by A.Rundgren
6 |
7 | :: Deletes the entries created by install_proxy.bat
8 | REG DELETE "HKCU\Software\Google\Chrome\NativeMessagingHosts\org.webpki.w2nb" /f
9 |
--------------------------------------------------------------------------------
/firefox/install/uninstall_proxy.bat:
--------------------------------------------------------------------------------
1 | :: Copyright 2014 The Chromium Authors. All rights reserved.
2 | :: Use of this source code is governed by a BSD-style license that can be
3 | :: found in the LICENSE file.
4 |
5 | :: Adapted for the Web2Native Bridge emulator fo Firefox by A.Rundgren
6 |
7 | :: Deletes the entries created by install_proxy.bat
8 | REG DELETE "HKCU\Software\Mozilla\NativeMessagingHosts\org.webpki.w2nb.moz" /f
9 |
--------------------------------------------------------------------------------
/sample1/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/sample1/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | sample1
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.jdt.core.javanature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/proxy/install/org.webpki.w2nb.json:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | {
6 | "name": "org.webpki.w2nb",
7 | "description": "Web2Native Bridge emulator",
8 | "path": "w2nb-proxy.exe",
9 | "type": "stdio",
10 | "allowed_origins": ["chrome-extension://jphfmfbdedghfhhjijaogeloiehomfni/"]
11 | }
12 |
--------------------------------------------------------------------------------
/proxy/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | proxy
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.jdt.core.javanature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/proxy/install/install_proxy.bat:
--------------------------------------------------------------------------------
1 | :: Copyright 2014 The Chromium Authors. All rights reserved.
2 | :: Use of this source code is governed by a BSD-style license that can be
3 | :: found in the LICENSE file.
4 |
5 | :: Adapted for the Web2Native Bridge emulator by A.Rundgren
6 |
7 | :: Change HKCU to HKLM if you want to install globally.
8 | :: %~dp0 is the directory containing this bat script and ends with a backslash.
9 | REG ADD "HKCU\Software\Google\Chrome\NativeMessagingHosts\org.webpki.w2nb" /ve /t REG_SZ /d "%~dp0org.webpki.w2nb.json" /f
10 | COPY /Y "%~dp0..\windows-build\Debug\w2nb-proxy.exe" "%~dp0"
11 |
--------------------------------------------------------------------------------
/extension/debug/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Web2Native Bridge emulator",
3 | "version": "1.0",
4 | "manifest_version": 2,
5 | "description": "Chrome Extension for emulating the Web2Native Bridge scheme",
6 | "icons": {
7 | "128": "icon-128.png"
8 | },
9 | "content_scripts": [{
10 | "matches": ["*://*/*", "file:///*"],
11 | "js": ["content.js"],
12 | "run_at": "document_end"
13 | }],
14 | "background": {
15 | "scripts": ["extension.js"]
16 | },
17 | "web_accessible_resources": ["inject.js"],
18 | "permissions": ["nativeMessaging"],
19 | "short_name": "w2nb"
20 | }
21 |
--------------------------------------------------------------------------------
/extension/release/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Web2Native Bridge emulator",
3 | "version": "1.0",
4 | "manifest_version": 2,
5 | "description": "Chrome Extension for emulating the Web2Native Bridge scheme",
6 | "icons": {
7 | "128": "icon-128.png"
8 | },
9 | "content_scripts": [{
10 | "matches": ["*://*/*", "file:///*"],
11 | "js": ["content.js"],
12 | "run_at": "document_end"
13 | }],
14 | "background": {
15 | "scripts": ["extension.js"]
16 | },
17 | "web_accessible_resources": ["inject.js"],
18 | "permissions": ["nativeMessaging"],
19 | "short_name": "w2nb"
20 | }
21 |
--------------------------------------------------------------------------------
/firefox/install/install_proxy.bat:
--------------------------------------------------------------------------------
1 | :: Copyright 2014 The Chromium Authors. All rights reserved.
2 | :: Use of this source code is governed by a BSD-style license that can be
3 | :: found in the LICENSE file.
4 |
5 | :: Adapted for the Web2Native Bridge emulator fo Firefox by A.Rundgren
6 |
7 | :: Change HKCU to HKLM if you want to install globally.
8 | :: %~dp0 is the directory containing this bat script and ends with a backslash.
9 | REG ADD "HKCU\Software\Mozilla\NativeMessagingHosts\org.webpki.w2nb.moz" /ve /t REG_SZ /d "%~dp0..\..\proxy\install\org.webpki.w2nb.moz.json" /f
10 | COPY /Y "%~dp0..\..\proxy\windows-build\Debug\w2nb-proxy.exe" "%~dp0..\..\proxy\install"
11 |
--------------------------------------------------------------------------------
/extension/release-build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/firefox/extension/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Web2Native Bridge emulator",
3 | "version": "1.0",
4 | "manifest_version": 2,
5 | "description": "Firefox Extension for emulating the Web2Native Bridge scheme",
6 | "icons": {
7 | "128": "icon-128.png"
8 | },
9 | "content_scripts": [{
10 | "matches": ["*://*/*", "file:///*"],
11 | "js": ["content.js"],
12 | "run_at": "document_end"
13 | }],
14 | "background": {
15 | "scripts": ["extension.js"]
16 | },
17 | "web_accessible_resources": ["inject.js"],
18 | "permissions": ["nativeMessaging"],
19 | "short_name": "w2nb",
20 | "applications": {
21 | "gecko": {
22 | "id": "w2nb@webpki.org",
23 | "strict_min_version": "50.0"
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/firefox/install/uninstall_proxy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Copyright 2013 The Chromium Authors. All rights reserved.
3 | # Use of this source code is governed by a BSD-style license that can be
4 | # found in the LICENSE file.
5 |
6 | # Adapted for the Web2Native Bridge for Firefox by Anders Rundgren
7 |
8 | set -e
9 |
10 | DIR="$( cd "$( dirname "$0" )" && pwd )"
11 | if [ "$(uname -s)" = "Darwin" ]; then
12 | if [ "$(whoami)" = "root" ]; then
13 | TARGET_DIR="/Library/Mozilla/NativeMessagingHosts"
14 | else
15 | TARGET_DIR="$HOME/Library/Application Support/Mozilla/NativeMessagingHosts"
16 | fi
17 | else
18 | # Only local user support at the moment
19 | TARGET_DIR="$HOME/.mozilla/native-messaging-hosts"
20 | fi
21 |
22 | HOST_NAME=org.webpki.w2nb.moz
23 | MANIFEST=$HOST_NAME.json
24 |
25 | rm "$TARGET_DIR/$MANIFEST"
26 | echo "Native messaging host $TARGET_DIR/$MANIFEST has been uninstalled."
27 |
28 |
--------------------------------------------------------------------------------
/proxy/windows-build/w2nb-proxy.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 11.00
3 | # Visual C++ Express 2010
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "w2nb-proxy", "w2nb-proxy\w2nb-proxy.vcxproj", "{F1D8380D-1477-4341-BFD2-9706D40EDC3A}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Win32 = Debug|Win32
9 | Release|Win32 = Release|Win32
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {F1D8380D-1477-4341-BFD2-9706D40EDC3A}.Debug|Win32.ActiveCfg = Debug|Win32
13 | {F1D8380D-1477-4341-BFD2-9706D40EDC3A}.Debug|Win32.Build.0 = Debug|Win32
14 | {F1D8380D-1477-4341-BFD2-9706D40EDC3A}.Release|Win32.ActiveCfg = Release|Win32
15 | {F1D8380D-1477-4341-BFD2-9706D40EDC3A}.Release|Win32.Build.0 = Release|Win32
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/proxy/windows-build/w2nb-proxy/w2nb-proxy.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 |
--------------------------------------------------------------------------------
/proxy/java-build.xml:
--------------------------------------------------------------------------------
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 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/proxy/install/uninstall_proxy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Copyright 2013 The Chromium Authors. All rights reserved.
3 | # Use of this source code is governed by a BSD-style license that can be
4 | # found in the LICENSE file.
5 |
6 | # Adapted for the Web2Native Bridge by Anders Rundgren
7 |
8 | set -e
9 |
10 | DIR="$( cd "$( dirname "$0" )" && pwd )"
11 | if [ "$(uname -s)" = "Darwin" ]; then
12 | if [ "$(whoami)" = "root" ]; then
13 | TARGET_DIR="/Library/Google/Chrome/NativeMessagingHosts"
14 | else
15 | TARGET_DIR="$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts"
16 | fi
17 | else
18 | if [ "$(whoami)" = "root" ]; then
19 | TARGET_DIR="/etc/opt/chrome/native-messaging-hosts"
20 | else
21 | if [ -d "$HOME/.config/google-chrome" ]; then
22 | CHROME_VARIANT=google-chrome
23 | if [ -d "$HOME/.config/chromium" ]; then
24 | echo "You have both Chrome and Chromium installed. Please patch the script!"
25 | exit 1
26 | fi
27 | else
28 | if [ -d "$HOME/.config/chromium" ]; then
29 | CHROME_VARIANT=chromium
30 | else
31 | echo "Can't find any Chrome variant!"
32 | exit 1
33 | fi
34 | fi
35 | TARGET_DIR="$HOME/.config/$CHROME_VARIANT/NativeMessagingHosts"
36 | fi
37 | fi
38 |
39 | HOST_NAME=org.webpki.w2nb
40 | MANIFEST=$HOST_NAME.json
41 |
42 | rm "$TARGET_DIR/$MANIFEST"
43 | echo "Native messaging host $TARGET_DIR/$MANIFEST has been uninstalled."
44 |
45 |
--------------------------------------------------------------------------------
/proxy/src.java/org/webpki/w2nbproxy/LoggerConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006-2016 WebPKI.org (http://webpki.org).
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | package org.webpki.w2nbproxy;
19 |
20 | import java.io.File;
21 |
22 | import java.util.logging.FileHandler;
23 | import java.util.logging.Logger;
24 | import java.util.logging.SimpleFormatter;
25 |
26 | final public class LoggerConfiguration {
27 |
28 | private LoggerConfiguration() {}
29 |
30 | public static void init(Logger logger, String[] args) {
31 | try {
32 | logger.setUseParentHandlers(false);
33 | FileHandler fh = new FileHandler(args[0] + File.separator + "logs" + File.separator + args[1] + ".log");
34 | logger.addHandler(fh);
35 | SimpleFormatter formatter = new SimpleFormatter();
36 | fh.setFormatter(formatter);
37 | } catch (Exception e) {
38 | System.exit(3);
39 | }
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/firefox/install/install_proxy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Copyright 2013 The Chromium Authors. All rights reserved.
3 | # Use of this source code is governed by a BSD-style license that can be
4 | # found in the LICENSE file.
5 |
6 | # Adapted for the Web2Native Bridge for Firefox by Anders Rundgren
7 |
8 | set -e
9 |
10 | DIR="$( cd "$( dirname "$0" )" && pwd )"
11 | if [ "$(uname -s)" = "Darwin" ]; then
12 | CPP=clang
13 | CPP_OPTION=-lc++
14 | if [ "$(whoami)" = "root" ]; then
15 | TARGET_DIR="/Library/Mozilla/NativeMessagingHosts"
16 | else
17 | TARGET_DIR="$HOME/Library/Application Support/Mozilla/NativeMessagingHosts"
18 | fi
19 | else
20 | # Only local user support at the moment
21 | CPP=g++
22 | CPP_OPTION=
23 | TARGET_DIR="$HOME/.mozilla/native-messaging-hosts"
24 | fi
25 |
26 | HOST_NAME=org.webpki.w2nb.moz
27 | EXECUTABLE=w2nb-proxy
28 | HOST_PATH=$DIR/../../proxy/install/$EXECUTABLE
29 | MANIFEST=$HOST_NAME.json
30 |
31 | echo "Compiling proxy source to $HOST_PATH"
32 | $CPP $CPP_OPTION -w -o $HOST_PATH $DIR/../../proxy/src.cpp/$EXECUTABLE.cpp
33 |
34 | # Create directory to store native messaging host.
35 | mkdir -p "$TARGET_DIR"
36 |
37 | # Copy native messaging host manifest.
38 | cp "$DIR/../../proxy/install/$MANIFEST" "$TARGET_DIR"
39 |
40 | # Update host path in the manifest.
41 | sed -i -e "s%$EXECUTABLE.exe%$HOST_PATH%" "$TARGET_DIR/$MANIFEST"
42 |
43 | # Set permissions for the manifest so that all users can read it.
44 | chmod o+r "$TARGET_DIR/$MANIFEST"
45 |
46 | echo "Native messaging host $TARGET_DIR/$MANIFEST has been installed"
47 |
--------------------------------------------------------------------------------
/proxy/src.java/org/webpki/w2nbproxy/StdoutJSONPipe.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006-2016 WebPKI.org (http://webpki.org).
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | package org.webpki.w2nbproxy;
19 |
20 | import java.io.IOException;
21 |
22 | import org.webpki.json.JSONObjectWriter;
23 | import org.webpki.json.JSONOutputFormats;
24 |
25 | public class StdoutJSONPipe {
26 |
27 | public String writeJSONObject (JSONObjectWriter ow) throws IOException {
28 | byte[] utf8 = ow.serializeToBytes(JSONOutputFormats.NORMALIZED);
29 | int l = utf8.length;
30 | // Code only works for little-endian machines
31 | // Network order, heard of that Google?
32 | byte[] blob = new byte[l + 4];
33 | blob[0] = (byte) l;
34 | blob[1] = (byte) (l >>> 8);
35 | blob[2] = (byte) (l >>> 16);
36 | blob[3] = (byte) (l >>> 24);
37 | for (int i = 0; i < l; i++) {
38 | blob[4 + i] = utf8[i];
39 | }
40 | System.out.write(blob);
41 | return new String(utf8, "UTF-8");
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/sample1/build.xml:
--------------------------------------------------------------------------------
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 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/proxy/src.java/org/webpki/w2nbproxy/StdinJSONPipe.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006-2016 WebPKI.org (http://webpki.org).
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | package org.webpki.w2nbproxy;
19 |
20 | import java.io.DataInputStream;
21 | import java.io.IOException;
22 |
23 | import org.webpki.json.JSONObjectReader;
24 | import org.webpki.json.JSONParser;
25 |
26 | public class StdinJSONPipe {
27 |
28 | String jsonString;
29 |
30 | DataInputStream dis;
31 |
32 | public StdinJSONPipe() {
33 | dis = new DataInputStream(System.in);
34 | }
35 |
36 | public JSONObjectReader readJSONObject() throws IOException {
37 | byte[] byteBuffer = new byte[4];
38 | dis.readFully(byteBuffer, 0, 4);
39 | // Code only works for little-endian machines
40 | // Network order, heard of that Google?
41 | int l = (byteBuffer[3]) << 24 | (byteBuffer[2] & 0xff) << 16 |
42 | (byteBuffer[1] & 0xff) << 8 | (byteBuffer[0] & 0xff);
43 | if (l > 100000)
44 | System.exit(3);
45 | byte[] utf8 = new byte[l];
46 | dis.readFully(utf8);
47 | jsonString = new String(utf8, "UTF-8");
48 | return JSONParser.parse(utf8);
49 | }
50 |
51 | public String getJSONString () {
52 | return jsonString;
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/proxy/install/install_proxy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Copyright 2013 The Chromium Authors. All rights reserved.
3 | # Use of this source code is governed by a BSD-style license that can be
4 | # found in the LICENSE file.
5 |
6 | # Adapted for the Web2Native Bridge by Anders Rundgren
7 |
8 | set -e
9 |
10 | DIR="$( cd "$( dirname "$0" )" && pwd )"
11 | if [ "$(uname -s)" = "Darwin" ]; then
12 | CPP=clang
13 | CPP_OPTION=-lc++
14 | if [ "$(whoami)" = "root" ]; then
15 | TARGET_DIR="/Library/Google/Chrome/NativeMessagingHosts"
16 | else
17 | TARGET_DIR="$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts"
18 | fi
19 | else
20 | CPP=g++
21 | CPP_OPTION=
22 | if [ "$(whoami)" = "root" ]; then
23 | TARGET_DIR="/etc/opt/chrome/native-messaging-hosts"
24 | else
25 | if [ -d "$HOME/.config/google-chrome" ]; then
26 | CHROME_VARIANT=google-chrome
27 | if [ -d "$HOME/.config/chromium" ]; then
28 | echo "You have both Chrome and Chromium installed. Please patch the script!"
29 | exit 1
30 | fi
31 | else
32 | if [ -d "$HOME/.config/chromium" ]; then
33 | CHROME_VARIANT=chromium
34 | else
35 | echo "Can't find any Chrome variant!"
36 | exit 1
37 | fi
38 | fi
39 | TARGET_DIR="$HOME/.config/$CHROME_VARIANT/NativeMessagingHosts"
40 | fi
41 | fi
42 |
43 | HOST_NAME=org.webpki.w2nb
44 | EXECUTABLE=w2nb-proxy
45 | HOST_PATH=$DIR/$EXECUTABLE
46 | MANIFEST=$HOST_NAME.json
47 |
48 | echo "Compiling proxy source to $HOST_PATH"
49 | $CPP $CPP_OPTION -w -o $HOST_PATH $DIR/../src.cpp/$EXECUTABLE.cpp
50 |
51 | # Create directory to store native messaging host.
52 | mkdir -p "$TARGET_DIR"
53 |
54 | # Copy native messaging host manifest.
55 | cp "$DIR/$MANIFEST" "$TARGET_DIR"
56 |
57 | # Update host path in the manifest.
58 | sed -i -e "s%$EXECUTABLE.exe%$HOST_PATH%" "$TARGET_DIR/$MANIFEST"
59 |
60 | # Set permissions for the manifest so that all users can read it.
61 | chmod o+r "$TARGET_DIR/$MANIFEST"
62 |
63 | echo "Native messaging host $TARGET_DIR/$MANIFEST has been installed"
64 |
--------------------------------------------------------------------------------
/extension/release/content.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006-2015 WebPKI.org (http://webpki.org).
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | "use strict";
19 |
20 | // DEBUG
21 |
22 | // Forward the message from inject.js to extension.js
23 | window.addEventListener("message", function(event) {
24 | // We only accept messages from ourselves
25 | if (event.source !== window || !event.data.src)
26 | return;
27 |
28 | // and forward to extension
29 | if (event.data.src === 'openreq') {
30 | // DEBUG
31 | chrome.runtime.sendMessage(event.data, function(response) {
32 | window.postMessage({res:response,src:'openres'}, '*');
33 | // DEBUG
34 | });
35 | } else if (event.data.src === 'webdis') {
36 | // DEBUG
37 | chrome.runtime.sendMessage(event.data);
38 | } else if (event.data.src === 'webmsg') {
39 | // DEBUG
40 | chrome.runtime.sendMessage(event.data);
41 | } else if (event.data.src === 'natmsg' || event.data.src === 'natdis') {
42 | // DEBUG
43 | } else {
44 | // DEBUG
45 | }
46 | });
47 |
48 | // post messages from extension to injected page
49 | chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
50 | // DEBUG
51 | window.postMessage({req:request,src:request.message ? 'natmsg' : 'natdis'}, '*');
52 | });
53 |
54 | // Inject inject.js to the DOM of every page. A horrible idea but it wasn't mine :-)
55 | var s = document.createElement('script');
56 | s.src = chrome.extension.getURL('inject.js');
57 |
58 | // remove script tag after script itself has loaded
59 | s.onload = function() {this.parentNode.removeChild(this);};
60 | (document.head || document.documentElement).appendChild(s);
--------------------------------------------------------------------------------
/firefox/extension/content.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006-2015 WebPKI.org (http://webpki.org).
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | "use strict";
19 |
20 | // DEBUG
21 |
22 | // Forward the message from inject.js to extension.js
23 | window.addEventListener("message", function(event) {
24 | // We only accept messages from ourselves
25 | if (event.source !== window || !event.data.src)
26 | return;
27 |
28 | // and forward to extension
29 | if (event.data.src === 'openreq') {
30 | // DEBUG
31 | browser.runtime.sendMessage(event.data, function(response) {
32 | window.postMessage({res:response,src:'openres'}, '*');
33 | // DEBUG
34 | });
35 | } else if (event.data.src === 'webdis') {
36 | // DEBUG
37 | browser.runtime.sendMessage(event.data);
38 | } else if (event.data.src === 'webmsg') {
39 | // DEBUG
40 | browser.runtime.sendMessage(event.data);
41 | } else if (event.data.src === 'natmsg' || event.data.src === 'natdis') {
42 | // DEBUG
43 | } else {
44 | // DEBUG
45 | }
46 | });
47 |
48 | // post messages from extension to injected page
49 | browser.runtime.onMessage.addListener(function(request, sender, sendResponse) {
50 | // DEBUG
51 | window.postMessage({req:request,src:request.message ? 'natmsg' : 'natdis'}, '*');
52 | });
53 |
54 | // Inject inject.js to the DOM of every page. A horrible idea but it wasn't mine :-)
55 | var s = document.createElement('script');
56 | s.src = browser.extension.getURL('inject.js');
57 |
58 | // remove script tag after script itself has loaded
59 | s.onload = function() {this.parentNode.removeChild(this);};
60 | (document.head || document.documentElement).appendChild(s);
--------------------------------------------------------------------------------
/proxy/src.java/org/webpki/w2nbproxy/BrowserWindow.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006-2016 WebPKI.org (http://webpki.org).
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | package org.webpki.w2nbproxy;
19 |
20 | import java.io.IOException;
21 |
22 | import org.webpki.json.JSONObjectReader;
23 | import org.webpki.json.JSONParser;
24 |
25 | import org.webpki.util.Base64URL;
26 |
27 | // This class represents the calling window argument provided by naigator.nativeConnect
28 | // It must match "inject.js"
29 |
30 | public class BrowserWindow {
31 |
32 | public double screenWidth;
33 |
34 | public double screenHeight;
35 |
36 | public double x;
37 |
38 | public double y;
39 |
40 | public double outerWidth;
41 |
42 | public double outerHeight;
43 |
44 | public double innerWidth;
45 |
46 | public double innerHeight;
47 |
48 | JSONObjectReader browserWindow;
49 |
50 | public BrowserWindow(String base64UrlEncodedParameters) throws IOException {
51 | browserWindow = JSONParser.parse(Base64URL.decode(base64UrlEncodedParameters));
52 | if (browserWindow.hasProperty("screenWidth")) {
53 | screenWidth = browserWindow.getDouble("screenWidth");
54 | screenHeight = browserWindow.getDouble("screenHeight");
55 | x = browserWindow.getDouble("windowX");
56 | y = browserWindow.getDouble("windowY");
57 | outerWidth = browserWindow.getDouble("windowOuterWidth");
58 | outerHeight = browserWindow.getDouble("windowOuterHeight");
59 | innerWidth = browserWindow.getDouble("windowInnerWidth");
60 | innerHeight = browserWindow.getDouble("windowInnerHeight");
61 | }
62 | browserWindow.checkForUnread();
63 | }
64 |
65 | @Override
66 | public String toString() {
67 | return browserWindow.toString();
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/extension/debug/content.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006-2015 WebPKI.org (http://webpki.org).
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | "use strict";
19 |
20 | console.debug('Content script loaded');
21 |
22 | // Forward the message from inject.js to extension.js
23 | window.addEventListener("message", function(event) {
24 | // We only accept messages from ourselves
25 | if (event.source !== window || !event.data.src)
26 | return;
27 |
28 | // and forward to extension
29 | if (event.data.src === 'openreq') {
30 | console.debug('got open request');
31 | chrome.runtime.sendMessage(event.data, function(response) {
32 | window.postMessage({res:response,src:'openres'}, '*');
33 | console.debug('sent!');
34 | });
35 | } else if (event.data.src === 'webdis') {
36 | console.debug('disconnect-gotit!');
37 | chrome.runtime.sendMessage(event.data);
38 | } else if (event.data.src === 'webmsg') {
39 | console.debug('webmsg-gotit!');
40 | chrome.runtime.sendMessage(event.data);
41 | } else if (event.data.src === 'natmsg' || event.data.src === 'natdis') {
42 | console.debug('request-gotit:' + chrome.runtime.id);
43 | } else {
44 | console.debug('content-other' + event.data.src);
45 | }
46 | });
47 |
48 | // post messages from extension to injected page
49 | chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
50 | console.debug('Got incoming:' + JSON.stringify(request));
51 | window.postMessage({req:request,src:request.message ? 'natmsg' : 'natdis'}, '*');
52 | });
53 |
54 | // Inject inject.js to the DOM of every page. A horrible idea but it wasn't mine :-)
55 | var s = document.createElement('script');
56 | s.src = chrome.extension.getURL('inject.js');
57 |
58 | // remove script tag after script itself has loaded
59 | s.onload = function() {this.parentNode.removeChild(this);};
60 | (document.head || document.documentElement).appendChild(s);
--------------------------------------------------------------------------------
/sample1/demo/sample1.html:
--------------------------------------------------------------------------------
1 |
2 |
Sample #1
80 |
Web2Native Bridge "Emulator" - Sample #1
81 |
82 |
83 |
84 |
85 |
Messages:
86 |
87 |
The extension should launch in this corner
88 |
--------------------------------------------------------------------------------
/extension/release/inject.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006-2015 WebPKI.org (http://webpki.org).
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | "use strict";
19 |
20 | // DEBUG
21 |
22 | var _promise;
23 |
24 | var ports = [];
25 |
26 | var org = org || {};
27 | org.webpki = org.webpki || {};
28 |
29 | org.webpki.port = function(tabid) {
30 | this.tabid = tabid;
31 | ports[tabid] = this;
32 | };
33 |
34 | org.webpki.port.prototype.addMessageListener = function(callback) {
35 | this.messageCallback = callback;
36 | };
37 |
38 | org.webpki.port.prototype.addDisconnectListener = function(callback) {
39 | this.disconnectCallback = callback;
40 | };
41 |
42 | org.webpki.port.prototype.disconnect = function() {
43 | var msg = {};
44 | msg.src = 'webdis';
45 | msg.tabid = this.tabid;
46 | window.postMessage(msg, '*');
47 | };
48 |
49 | org.webpki.port.prototype.postMessage = function(message) {
50 | var msg = {};
51 | msg.src = 'webmsg';
52 | msg.tabid = this.tabid;
53 | msg.message = message;
54 | window.postMessage(msg, '*');
55 | };
56 |
57 | // Forward the message from extension.js to inject.js
58 | window.addEventListener("message", function(event) {
59 | // We only accept messages from ourselves
60 | if (event.source !== window || !event.data.src)
61 | return;
62 |
63 | // and forward to extension
64 | if (event.data.src === "openres") {
65 | // DEBUG
66 | if (event.data.res.success) {
67 | _promise.resolve(new org.webpki.port(event.data.res.success));
68 | } else if (event.data.res.err) {
69 | _promise.reject(event.data.res.err);
70 | } else {
71 | _promise.reject("Internal error");
72 | }
73 | delete document._promise;
74 | } else if (event.data.src === "natmsg") {
75 | // DEBUG
76 | if (ports[event.data.req.tabid].messageCallback) {
77 | ports[event.data.req.tabid].messageCallback(event.data.req.message);
78 | } else {
79 | // DEBUG
80 | }
81 | } else if (event.data.src === "natdis") {
82 | // DEBUG
83 | if (ports[event.data.req.tabid].disconnectCallback) {
84 | ports[event.data.req.tabid].disconnectCallback();
85 | } else {
86 | // DEBUG
87 | }
88 | } else if (event.data.src !== "webdis") {
89 | // DEBUG
90 | }
91 | });
92 |
93 | navigator.nativeConnect = function(applicationName, optionalArguments) {
94 | return new Promise(function(resolve, reject) {
95 | var msg = {};
96 | msg.src = 'openreq';
97 | msg.origin = location.href;
98 | msg.application = applicationName;
99 | msg.window = {screenWidth: window.screen.width,
100 | screenHeight: window.screen.height,
101 | windowX: window.screenX,
102 | windowY: window.screenY,
103 | windowOuterWidth: window.outerWidth,
104 | windowOuterHeight: window.outerHeight,
105 | windowInnerWidth: window.innerWidth,
106 | windowInnerHeight: window.innerHeight};
107 | msg.arguments = optionalArguments ? optionalArguments : {};
108 | window.postMessage(msg, '*');
109 | _promise = {resolve: resolve, reject: reject};
110 | });
111 | };
112 |
113 |
--------------------------------------------------------------------------------
/firefox/extension/inject.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006-2015 WebPKI.org (http://webpki.org).
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | "use strict";
19 |
20 | // DEBUG
21 |
22 | var _promise;
23 |
24 | var ports = [];
25 |
26 | var org = org || {};
27 | org.webpki = org.webpki || {};
28 |
29 | org.webpki.port = function(tabid) {
30 | this.tabid = tabid;
31 | ports[tabid] = this;
32 | };
33 |
34 | org.webpki.port.prototype.addMessageListener = function(callback) {
35 | this.messageCallback = callback;
36 | };
37 |
38 | org.webpki.port.prototype.addDisconnectListener = function(callback) {
39 | this.disconnectCallback = callback;
40 | };
41 |
42 | org.webpki.port.prototype.disconnect = function() {
43 | var msg = {};
44 | msg.src = 'webdis';
45 | msg.tabid = this.tabid;
46 | window.postMessage(msg, '*');
47 | };
48 |
49 | org.webpki.port.prototype.postMessage = function(message) {
50 | var msg = {};
51 | msg.src = 'webmsg';
52 | msg.tabid = this.tabid;
53 | msg.message = message;
54 | window.postMessage(msg, '*');
55 | };
56 |
57 | // Forward the message from extension.js to inject.js
58 | window.addEventListener("message", function(event) {
59 | // We only accept messages from ourselves
60 | if (event.source !== window || !event.data.src)
61 | return;
62 |
63 | // and forward to extension
64 | if (event.data.src === "openres") {
65 | // DEBUG
66 | if (event.data.res.success) {
67 | _promise.resolve(new org.webpki.port(event.data.res.success));
68 | } else if (event.data.res.err) {
69 | _promise.reject(event.data.res.err);
70 | } else {
71 | _promise.reject("Internal error");
72 | }
73 | delete document._promise;
74 | } else if (event.data.src === "natmsg") {
75 | // DEBUG
76 | if (ports[event.data.req.tabid].messageCallback) {
77 | ports[event.data.req.tabid].messageCallback(event.data.req.message);
78 | } else {
79 | // DEBUG
80 | }
81 | } else if (event.data.src === "natdis") {
82 | // DEBUG
83 | if (ports[event.data.req.tabid].disconnectCallback) {
84 | ports[event.data.req.tabid].disconnectCallback();
85 | } else {
86 | // DEBUG
87 | }
88 | } else if (event.data.src !== "webdis") {
89 | // DEBUG
90 | }
91 | });
92 |
93 | navigator.nativeConnect = function(applicationName, optionalArguments) {
94 | return new Promise(function(resolve, reject) {
95 | var msg = {};
96 | msg.src = 'openreq';
97 | msg.origin = location.href;
98 | msg.application = applicationName;
99 | msg.window = {screenWidth: window.screen.width,
100 | screenHeight: window.screen.height,
101 | windowX: window.screenX,
102 | windowY: window.screenY,
103 | windowOuterWidth: window.outerWidth,
104 | windowOuterHeight: window.outerHeight,
105 | windowInnerWidth: window.innerWidth,
106 | windowInnerHeight: window.innerHeight};
107 | msg.arguments = optionalArguments ? optionalArguments : {};
108 | window.postMessage(msg, '*');
109 | _promise = {resolve: resolve, reject: reject};
110 | });
111 | };
112 |
113 |
--------------------------------------------------------------------------------
/extension/debug/inject.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006-2015 WebPKI.org (http://webpki.org).
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | "use strict";
19 |
20 | console.debug('Injected page loaded');
21 |
22 | var _promise;
23 |
24 | var ports = [];
25 |
26 | var org = org || {};
27 | org.webpki = org.webpki || {};
28 |
29 | org.webpki.port = function(tabid) {
30 | this.tabid = tabid;
31 | ports[tabid] = this;
32 | };
33 |
34 | org.webpki.port.prototype.addMessageListener = function(callback) {
35 | this.messageCallback = callback;
36 | };
37 |
38 | org.webpki.port.prototype.addDisconnectListener = function(callback) {
39 | this.disconnectCallback = callback;
40 | };
41 |
42 | org.webpki.port.prototype.disconnect = function() {
43 | var msg = {};
44 | msg.src = 'webdis';
45 | msg.tabid = this.tabid;
46 | window.postMessage(msg, '*');
47 | };
48 |
49 | org.webpki.port.prototype.postMessage = function(message) {
50 | var msg = {};
51 | msg.src = 'webmsg';
52 | msg.tabid = this.tabid;
53 | msg.message = message;
54 | window.postMessage(msg, '*');
55 | };
56 |
57 | // Forward the message from extension.js to inject.js
58 | window.addEventListener("message", function(event) {
59 | // We only accept messages from ourselves
60 | if (event.source !== window || !event.data.src)
61 | return;
62 |
63 | // and forward to extension
64 | if (event.data.src === "openres") {
65 | console.debug('got open return');
66 | if (event.data.res.success) {
67 | _promise.resolve(new org.webpki.port(event.data.res.success));
68 | } else if (event.data.res.err) {
69 | _promise.reject(event.data.res.err);
70 | } else {
71 | _promise.reject("Internal error");
72 | }
73 | delete document._promise;
74 | } else if (event.data.src === "natmsg") {
75 | console.debug('inject req:' + JSON.stringify(event.data.req));
76 | if (ports[event.data.req.tabid].messageCallback) {
77 | ports[event.data.req.tabid].messageCallback(event.data.req.message);
78 | } else {
79 | console.debug('missing listener: ' + JSON.stringify(event.data.req));
80 | }
81 | } else if (event.data.src === "natdis") {
82 | console.debug('inject disconnect:' + JSON.stringify(event.data.req));
83 | if (ports[event.data.req.tabid].disconnectCallback) {
84 | ports[event.data.req.tabid].disconnectCallback();
85 | } else {
86 | console.debug('missing listener: ' + JSON.stringify(event.data.req));
87 | }
88 | } else if (event.data.src !== "webdis") {
89 | console.debug('page-other: ' + event.data.src);
90 | }
91 | });
92 |
93 | navigator.nativeConnect = function(applicationName, optionalArguments) {
94 | return new Promise(function(resolve, reject) {
95 | var msg = {};
96 | msg.src = 'openreq';
97 | msg.origin = location.href;
98 | msg.application = applicationName;
99 | msg.window = {screenWidth: window.screen.width,
100 | screenHeight: window.screen.height,
101 | windowX: window.screenX,
102 | windowY: window.screenY,
103 | windowOuterWidth: window.outerWidth,
104 | windowOuterHeight: window.outerHeight,
105 | windowInnerWidth: window.innerWidth,
106 | windowInnerHeight: window.innerHeight};
107 | msg.arguments = optionalArguments ? optionalArguments : {};
108 | window.postMessage(msg, '*');
109 | _promise = {resolve: resolve, reject: reject};
110 | });
111 | };
112 |
113 |
--------------------------------------------------------------------------------
/proxy/windows-build/w2nb-proxy/w2nb-proxy.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 |
15 |
16 |
17 | {F1D8380D-1477-4341-BFD2-9706D40EDC3A}
18 | Win32Proj
19 | w2nbproxy
20 |
21 |
22 |
23 | Application
24 | true
25 | Unicode
26 | v140
27 |
28 |
29 | Application
30 | false
31 | true
32 | Unicode
33 | v140
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | false
47 |
48 |
49 | false
50 |
51 |
52 |
53 | NotUsing
54 | Level3
55 | Disabled
56 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
57 | MultiThreaded
58 | None
59 | false
60 |
61 |
62 | Console
63 | false
64 | $(OutDir)$(TargetName)$(TargetExt)
65 | NoErrorReport
66 |
67 |
68 |
69 |
70 | Level3
71 | NotUsing
72 | MaxSpeed
73 | true
74 | true
75 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
76 |
77 |
78 | Console
79 | true
80 | true
81 | true
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/extension/release/extension.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006-2015 WebPKI.org (http://webpki.org).
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | "use strict";
19 |
20 | console.log("Extension loaded");
21 |
22 | var web2native_bridge = 'org.webpki.w2nb';
23 |
24 | var ports = [];
25 |
26 | var BASE64URL =
27 | ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
28 | 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
29 | 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
30 | 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','-','_'];
31 |
32 | function json2B64(jsonObject) {
33 | var string = JSON.stringify(jsonObject);
34 | var binArray = [];
35 | for (var n = 0; n < string.length; n++) {
36 | binArray.push(string.charCodeAt(n) & 0xFF);
37 | }
38 | var encoded = new String();
39 | var i = 0;
40 | var modulo3 = binArray.length % 3;
41 | while (i < binArray.length - modulo3) {
42 | encoded += BASE64URL[(binArray[i] >>> 2) & 0x3F];
43 | encoded += BASE64URL[((binArray[i++] << 4) & 0x30) | ((binArray[i] >>> 4) & 0x0F)];
44 | encoded += BASE64URL[((binArray[i++] << 2) & 0x3C) | ((binArray[i] >>> 6) & 0x03)];
45 | encoded += BASE64URL[binArray[i++] & 0x3F];
46 | }
47 | if (modulo3 == 1) {
48 | encoded += BASE64URL[(binArray[i] >>> 2) & 0x3F];
49 | encoded += BASE64URL[(binArray[i] << 4) & 0x30];
50 | }
51 | else if (modulo3 == 2) {
52 | encoded += BASE64URL[(binArray[i] >>> 2) & 0x3F];
53 | encoded += BASE64URL[((binArray[i++] << 4) & 0x30) | ((binArray[i] >>> 4) & 0x0F)];
54 | encoded += BASE64URL[(binArray[i] << 2) & 0x3C];
55 | }
56 | return encoded;
57 | }
58 |
59 | // Test that the native proxy is alive and kicking
60 | chrome.runtime.onStartup.addListener(function() {
61 | chrome.runtime.sendNativeMessage(web2native_bridge, {proxyVersion:"1.00"}, function(response) {
62 | if (response) {
63 | console.log("Extension successfully verified");
64 | } else {
65 | alert('Web2Native Bridge library issue: ' + chrome.runtime.lastError.message);
66 | }
67 | });
68 | });
69 |
70 | function getPort(sender) {
71 | var port = ports[sender.tab.id];
72 | if (!port) {
73 | alert('Missing port for: ' + sender.tab.id);
74 | }
75 | return port;
76 | }
77 |
78 | function getDisconnectPort(sender) {
79 | var port = getPort(sender);
80 | if (port) {
81 | delete ports[sender.tab.id];
82 | }
83 | return port;
84 | }
85 |
86 | // When message is received from page send it to native
87 | chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
88 | if(sender.id !== chrome.runtime.id || !sender.tab) {
89 | alert('Internal error');
90 | return;
91 | }
92 | if (request.src === 'openreq') {
93 | var port = chrome.runtime.connectNative(web2native_bridge);
94 | ports[sender.tab.id] = port;
95 | port.onMessage.addListener(function(message) {
96 | // DEBUG
97 | chrome.tabs.sendMessage(sender.tab.id, {message:message,tabid:sender.tab.id});
98 | });
99 | port.onDisconnect.addListener(function() {
100 | // DEBUG
101 | getDisconnectPort(sender);
102 | chrome.tabs.sendMessage(sender.tab.id, {disconnect:true,tabid:sender.tab.id});
103 | });
104 | // DEBUG
105 | port.postMessage({url:request.origin,
106 | application:request.application,
107 | windowB64:json2B64(request.window),
108 | argumentsB64:json2B64(request.arguments)});
109 | sendResponse({success:sender.tab.id});
110 | } else if (request.src === 'webdis') {
111 | // DEBUG
112 | getDisconnectPort(sender).disconnect();
113 | } else if (request.src === 'webmsg') {
114 | // DEBUG
115 | getPort(sender).postMessage(request.message);
116 | } else {
117 | sendResponse({err:{}});
118 | }
119 | });
120 |
--------------------------------------------------------------------------------
/firefox/extension/extension.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006-2015 WebPKI.org (http://webpki.org).
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | "use strict";
19 |
20 | console.log("Extension loaded");
21 |
22 | var web2native_bridge = 'org.webpki.w2nb.moz';
23 |
24 | var ports = [];
25 |
26 | var BASE64URL =
27 | ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
28 | 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
29 | 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
30 | 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','-','_'];
31 |
32 | function json2B64(jsonObject) {
33 | var string = JSON.stringify(jsonObject);
34 | var binArray = [];
35 | for (var n = 0; n < string.length; n++) {
36 | binArray.push(string.charCodeAt(n) & 0xFF);
37 | }
38 | var encoded = new String();
39 | var i = 0;
40 | var modulo3 = binArray.length % 3;
41 | while (i < binArray.length - modulo3) {
42 | encoded += BASE64URL[(binArray[i] >>> 2) & 0x3F];
43 | encoded += BASE64URL[((binArray[i++] << 4) & 0x30) | ((binArray[i] >>> 4) & 0x0F)];
44 | encoded += BASE64URL[((binArray[i++] << 2) & 0x3C) | ((binArray[i] >>> 6) & 0x03)];
45 | encoded += BASE64URL[binArray[i++] & 0x3F];
46 | }
47 | if (modulo3 == 1) {
48 | encoded += BASE64URL[(binArray[i] >>> 2) & 0x3F];
49 | encoded += BASE64URL[(binArray[i] << 4) & 0x30];
50 | }
51 | else if (modulo3 == 2) {
52 | encoded += BASE64URL[(binArray[i] >>> 2) & 0x3F];
53 | encoded += BASE64URL[((binArray[i++] << 4) & 0x30) | ((binArray[i] >>> 4) & 0x0F)];
54 | encoded += BASE64URL[(binArray[i] << 2) & 0x3C];
55 | }
56 | return encoded;
57 | }
58 |
59 | // Test that the native proxy is alive and kicking
60 | browser.runtime.sendNativeMessage(web2native_bridge, {proxyVersion:"1.00"}, function(response) {
61 | if (response) {
62 | console.log("Extension successfully verified");
63 | } else {
64 | console.log('Web2Native Bridge library issue: ' + browser.runtime.lastError.message);
65 | }
66 | });
67 |
68 | function getPort(sender) {
69 | var port = ports[sender.tab.id];
70 | if (!port) {
71 | console.log('Missing port for: ' + sender.tab.id);
72 | }
73 | return port;
74 | }
75 |
76 | function getDisconnectPort(sender) {
77 | var port = getPort(sender);
78 | if (port) {
79 | delete ports[sender.tab.id];
80 | }
81 | return port;
82 | }
83 |
84 | // When message is received from page send it to native
85 | browser.runtime.onMessage.addListener(function(request, sender, sendResponse) {
86 |
87 | /*
88 | console.log('sender='+ JSON.stringify(sender) + '\n' + JSON.stringify(browser.runtime));
89 |
90 | if(sender.id !== browser.runtime.id) {
91 | console.log('Internal error');
92 | return;
93 | }
94 | */
95 | if (request.src === 'openreq') {
96 | var port = browser.runtime.connectNative(web2native_bridge);
97 | ports[sender.tab.id] = port;
98 | port.onMessage.addListener(function(message) {
99 | // DEBUG
100 | browser.tabs.sendMessage(sender.tab.id, {message:message,tabid:sender.tab.id});
101 | });
102 | port.onDisconnect.addListener(function() {
103 | // DEBUG
104 | // getDisconnectPort(sender);
105 | browser.tabs.sendMessage(sender.tab.id, {disconnect:true,tabid:sender.tab.id});
106 | });
107 | // DEBUG
108 | port.postMessage({url:request.origin,
109 | application:request.application,
110 | windowB64:json2B64(request.window),
111 | argumentsB64:json2B64(request.arguments)});
112 | sendResponse({success:sender.tab.id});
113 | } else if (request.src === 'webdis') {
114 | // DEBUG
115 | getDisconnectPort(sender).disconnect();
116 | } else if (request.src === 'webmsg') {
117 | // DEBUG
118 | getPort(sender).postMessage(request.message);
119 | } else {
120 | sendResponse({err:{}});
121 | }
122 | });
123 |
--------------------------------------------------------------------------------
/extension/debug/extension.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006-2015 WebPKI.org (http://webpki.org).
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | "use strict";
19 |
20 | console.log("Extension loaded");
21 |
22 | var web2native_bridge = 'org.webpki.w2nb';
23 |
24 | var ports = [];
25 |
26 | var BASE64URL =
27 | ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
28 | 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
29 | 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
30 | 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','-','_'];
31 |
32 | function json2B64(jsonObject) {
33 | var string = JSON.stringify(jsonObject);
34 | var binArray = [];
35 | for (var n = 0; n < string.length; n++) {
36 | binArray.push(string.charCodeAt(n) & 0xFF);
37 | }
38 | var encoded = new String();
39 | var i = 0;
40 | var modulo3 = binArray.length % 3;
41 | while (i < binArray.length - modulo3) {
42 | encoded += BASE64URL[(binArray[i] >>> 2) & 0x3F];
43 | encoded += BASE64URL[((binArray[i++] << 4) & 0x30) | ((binArray[i] >>> 4) & 0x0F)];
44 | encoded += BASE64URL[((binArray[i++] << 2) & 0x3C) | ((binArray[i] >>> 6) & 0x03)];
45 | encoded += BASE64URL[binArray[i++] & 0x3F];
46 | }
47 | if (modulo3 == 1) {
48 | encoded += BASE64URL[(binArray[i] >>> 2) & 0x3F];
49 | encoded += BASE64URL[(binArray[i] << 4) & 0x30];
50 | }
51 | else if (modulo3 == 2) {
52 | encoded += BASE64URL[(binArray[i] >>> 2) & 0x3F];
53 | encoded += BASE64URL[((binArray[i++] << 4) & 0x30) | ((binArray[i] >>> 4) & 0x0F)];
54 | encoded += BASE64URL[(binArray[i] << 2) & 0x3C];
55 | }
56 | return encoded;
57 | }
58 |
59 | // Test that the native proxy is alive and kicking
60 | chrome.runtime.onStartup.addListener(function() {
61 | chrome.runtime.sendNativeMessage(web2native_bridge, {proxyVersion:"1.00"}, function(response) {
62 | if (response) {
63 | console.log("Extension successfully verified");
64 | } else {
65 | alert('Web2Native Bridge library issue: ' + chrome.runtime.lastError.message);
66 | }
67 | });
68 | });
69 |
70 | function getPort(sender) {
71 | var port = ports[sender.tab.id];
72 | if (!port) {
73 | alert('Missing port for: ' + sender.tab.id);
74 | }
75 | return port;
76 | }
77 |
78 | function getDisconnectPort(sender) {
79 | var port = getPort(sender);
80 | if (port) {
81 | delete ports[sender.tab.id];
82 | }
83 | return port;
84 | }
85 |
86 | // When message is received from page send it to native
87 | chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
88 | if(sender.id !== chrome.runtime.id || !sender.tab) {
89 | alert('Internal error');
90 | return;
91 | }
92 | if (request.src === 'openreq') {
93 | var port = chrome.runtime.connectNative(web2native_bridge);
94 | ports[sender.tab.id] = port;
95 | port.onMessage.addListener(function(message) {
96 | console.debug('rec: ' + JSON.stringify(message));
97 | chrome.tabs.sendMessage(sender.tab.id, {message:message,tabid:sender.tab.id});
98 | });
99 | port.onDisconnect.addListener(function() {
100 | console.debug('native disconnect');
101 | getDisconnectPort(sender);
102 | chrome.tabs.sendMessage(sender.tab.id, {disconnect:true,tabid:sender.tab.id});
103 | });
104 | console.debug('connect: ' + JSON.stringify(request));
105 | port.postMessage({url:request.origin,
106 | application:request.application,
107 | windowB64:json2B64(request.window),
108 | argumentsB64:json2B64(request.arguments)});
109 | sendResponse({success:sender.tab.id});
110 | } else if (request.src === 'webdis') {
111 | console.debug('web disconnect');
112 | getDisconnectPort(sender).disconnect();
113 | } else if (request.src === 'webmsg') {
114 | console.debug('web message');
115 | getPort(sender).postMessage(request.message);
116 | } else {
117 | sendResponse({err:{}});
118 | }
119 | });
120 |
--------------------------------------------------------------------------------
/proxy/src.java/org/webpki/w2nbproxy/ExtensionPositioning.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006-2016 WebPKI.org (http://webpki.org).
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package org.webpki.w2nbproxy;
18 |
19 | import java.io.IOException;
20 |
21 | import org.webpki.json.JSONObjectReader;
22 | import org.webpki.json.JSONParser;
23 |
24 | import org.webpki.util.Base64URL;
25 |
26 | public class ExtensionPositioning {
27 |
28 | public class TargetRectangle {
29 |
30 | public double left;
31 | public double top;
32 | public double width;
33 | public double height;
34 |
35 | TargetRectangle(double left, double top, double width, double height) {
36 | this.left = left;
37 | this.top = top;
38 | this.width = width;
39 | this.height = height;
40 | }
41 | }
42 |
43 | JSONObjectReader positioningArguments;
44 |
45 | public static enum HORIZONTAL_ALIGNMENT {Left, Right, Center};
46 | public static enum VERTICAL_ALIGNMENT {Top, Bottom, Center};
47 |
48 | public static final String HORIZONTAL_ALIGNMENT_JSON = "horizontalAlignment";
49 | public static final String VERTICAL_ALIGNMENT_JSON = "verticalAlignment";
50 |
51 | public static final String TARGET_RECTANGLE_JSON = "targetRectangle";
52 |
53 | public static final String TARGET_LEFT_JSON = "left";
54 | public static final String TARGET_TOP_JSON = "top";
55 | public static final String TARGET_WIDTH_JSON = "width";
56 | public static final String TARGET_HEIGHT_JSON = "height";
57 |
58 | public HORIZONTAL_ALIGNMENT horizontalAlignment;
59 | public VERTICAL_ALIGNMENT verticalAlignment;
60 |
61 | public TargetRectangle targetRectangle; // Optional (may be null)
62 |
63 | public ExtensionPositioning(String base64UrlEncodedArguments) throws IOException {
64 | positioningArguments = JSONParser.parse(Base64URL.decode(base64UrlEncodedArguments));
65 | if (positioningArguments.hasProperty(HORIZONTAL_ALIGNMENT_JSON)) {
66 | horizontalAlignment = HORIZONTAL_ALIGNMENT.valueOf(
67 | positioningArguments.getString(HORIZONTAL_ALIGNMENT_JSON));
68 | verticalAlignment = VERTICAL_ALIGNMENT.valueOf(
69 | positioningArguments.getString(VERTICAL_ALIGNMENT_JSON));
70 | if (positioningArguments.hasProperty(TARGET_RECTANGLE_JSON)) {
71 | JSONObjectReader values = positioningArguments.getObject(TARGET_RECTANGLE_JSON);
72 | targetRectangle = new TargetRectangle(values.getDouble(TARGET_LEFT_JSON),
73 | values.getDouble(TARGET_TOP_JSON),
74 | values.getDouble(TARGET_WIDTH_JSON),
75 | values.getDouble(TARGET_HEIGHT_JSON));
76 | }
77 | }
78 | positioningArguments.checkForUnread();
79 | }
80 |
81 | public static String encode(HORIZONTAL_ALIGNMENT horizontalAlignment,
82 | VERTICAL_ALIGNMENT verticalAlignment,
83 | String optionalTargetElementId) {
84 | return "setExtensionPosition('" + horizontalAlignment.toString() +
85 | "', '" + verticalAlignment.toString() + "'" +
86 | (optionalTargetElementId == null ? "" : ", '" + optionalTargetElementId + "'") + ")";
87 | }
88 |
89 | public static final String SET_EXTENSION_POSITION_FUNCTION_TEXT =
90 | "function setExtensionPosition(hAlign, vAlign, optionalId) {\n" +
91 | " var result = {" + HORIZONTAL_ALIGNMENT_JSON + ":hAlign, " +
92 | VERTICAL_ALIGNMENT_JSON + ":vAlign}\n" +
93 | " if (optionalId) {\n" +
94 | " var input = document.getElementById(optionalId).getBoundingClientRect();\n" +
95 | " var rectangle = {};\n" +
96 | " rectangle." + TARGET_LEFT_JSON + " = input." + TARGET_LEFT_JSON + ";\n" +
97 | " rectangle." + TARGET_TOP_JSON + " = input." + TARGET_TOP_JSON + ";\n" +
98 | " rectangle." + TARGET_WIDTH_JSON + " = input." + TARGET_WIDTH_JSON + ";\n" +
99 | " rectangle." + TARGET_HEIGHT_JSON + " = input." + TARGET_HEIGHT_JSON + ";\n" +
100 | " result." + TARGET_RECTANGLE_JSON + " = rectangle;\n" +
101 | " }\n" +
102 | " return result;\n" +
103 | "}\n";
104 |
105 | @Override
106 | public String toString() {
107 | return positioningArguments.toString();
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Web2Native Bridge - Uniting the "Web" and "App" worlds
2 |
3 |
Note: this is a system in development, the specification may change anytime without notice
4 |
5 | This repository contains all code for building and testing an emulation of
6 | the Web2Native Bridge concept
7 | (https://cyberphone.github.io/doc/web/web2native-bridge.pdf)
8 | using the Google **Chrome** and Mozilla **Firefox** desktop browsers. It also runs on the Open Source **Chromium** browser.
9 |
10 | The emulator code exploits Chrome's native messaging (https://developer.chrome.com/extensions/nativeMessaging)
11 | featured in a single universal Chrome/Firefox extension.
12 |
13 | Applications callable by the Web2Native Bridge emulator must be written in Java and stored in a for the purpose
14 | dedicated directory.
15 |
16 | ## API
17 | The Web2Native Bridge emulator extends the navigator object by a *single* method
18 | nativeConnect('*Name of target application*' [, *optionalArgument*]) which
19 | returns a JavaScript Promise to a port object.
20 |
21 | The port object supports the following methods and events:
22 | * postMessage(*message*)
23 | * disconnect()
24 | * addMessageListener(function(*message*))
25 | * addDisconnectListener(function())
26 |
27 | *optionalArgument* and *message* **must** be valid JSON-serializable JavaScript objects.
28 |
29 | An example which could be hosted in an ordinary (*non-privileged*) web page:
30 | ```javascript
31 | navigator.nativeConnect('com.example.myapp').then(function(port) {
32 |
33 | port.addMessageListener(function(message) {
34 | // We got a message from the native application...
35 | });
36 |
37 | port.addDisconnectListener(function() {
38 | // Native application disconnected...
39 | });
40 |
41 | port.postMessage({greeting:'Native app, how are you doing?'});
42 | // Note: JavaScript serialization makes the above a genuine JSON object
43 |
44 | port.disonnect(); // Not much of a conversation going on here...
45 |
46 | }, function(err) {
47 | console.debug(err);
48 | });
49 | ```
50 | The argument to nativeConnect holds the name of the specifically adapted local application to invoke. The current scheme uses a Java-inspired dotted path pointing to a subdirectory and JAR-application having this name.
51 |
52 | ## Manifest
53 | For specifying access to native applications there **must** be a JSON-formatted *manifest* file associated with each application.
54 | The following *manifest* provides universal access to an application:
55 | ```json
56 | {
57 | "callableFrom": ["*://*/*", "file:///*"]
58 | }
59 | ```
60 | A more restrictive *manifest* could limit access to a single domain and https operation:
61 | ```json
62 | {
63 | "callableFrom": ["https://example.com/*", "https://*.example.com/*"]
64 | }
65 | ```
66 |
67 | ## Architecture
68 | The Web2Native Bridge emulator always invokes a central proxy located at proxy/install/w2nb-proxy.
69 |
70 | The proxy in turn dispatches a call to the specific target application located at
71 | proxy/install/apps/*dottedpath*/*dottedpath*.jar.
72 |
73 | The mandatory *manifest* file is stored at
74 | proxy/install/apps/*dottedpath*/manifest.json.
75 |
76 | Common Java libraries may be stored in proxy/install/libs.
77 |
78 | For debugging purposes there is also a logging system writing data in proxy/install/logs.
79 |
80 | All local I/O between the browser, proxy and the callable applications
81 | is performed through stdin and stdout.
82 |
83 | ## Native Application Interface
84 | Native applications (in the prototype Java applications hosted in JAR-files) are called as follows:
85 |
86 |
args[0]
Absolute path to the proxy/install directory
87 |
args[1]
Application name (dotted path)
88 |
args[2]
URL of calling web page
89 |
args[3]
Coordinates of calling web page
90 |
args[4]
Custom invocation data (OptionalArgument)
91 |
args[5...]
Chrome's Native Messaging arguments
92 |
93 | For detailed information about the format of these fields, turn to the code :-)
94 |
95 | ## Installation
96 | ### Prerequisites
97 | * You need to have **Java SE version 8** installed to run the Web2Native Bridge emulator
98 | * OS/X and Linux installations presume that **clang** respectively **g++** is available
99 | * Clone the **web2native-bridge** master repository or just download the ZIP via GitHub to any free directory
100 |
101 | Note: If you are using Oracle Java you must install the **Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files** as well.
102 |
103 | ### Chrome/Chromium specific steps
104 | 1. Start a terminal window and move to proxy/install. Then run the install-proxy script that suits your platform
105 | 2. Install the Web2Native Bridge browser extension from the Chrome Web Store:
106 | https://chrome.google.com/webstore/detail/web2native-bridge-emulato/jphfmfbdedghfhhjijaogeloiehomfni
107 | 3. In Chrome, go to Settings->Extensions and check "Allow access to file URLs" for the Web2Native Bridge extension
108 |
109 | ### Firefox specific steps
110 | 1. Start a terminal window and move to firefox/install. Then run the install-proxy script that suits your platform
111 | 2. Install the Web2Native Bridge browser extension from the file firefox/install/xpi/web2native_bridge_emulator-1.0.xpi using the Firefox menu option: *Add-ons->Extensions->Install Add-on from file*.
112 |
113 | ### Testing the installation
114 | Now you can try the two sample applications (see next sections) since they are installed by default.
115 |
116 | Please don't hesitate contacting me if you run into problems during installation or execution of the emulator!
117 |
118 | ## Basic Sample Application
119 | The HTML file sample1/demo/sample1.html does approximately
120 | the same thing as the application depicted in
121 | http://www.cnet.com/news/google-paves-over-hole-left-by-chrome-plug-in-ban/
122 | albeit with a few significant enhancements:
123 | * The sample application is invoked by an ordinary web page
124 | * The Web2Native Bridge browser extension is fully generic and can support any number of very different applications
125 | * The Web2Native Bridge adds positioning support enabling alignment UI-wise with the web
126 |
127 | The native part of the sample application resides in proxy/install/apps/org.webpki.w2nb.sample1/org.webpki.w2nb.sample1.jar.
128 |
129 | ## Single Page Application
130 | Although not a design goal, the Web2Native Bridge API is also compliant with the SPA concept:
131 | https://en.wikipedia.org/wiki/Single-page_application
132 |
133 | ## Security Considerations
134 | Since an emulator *by definition* isn't the "real thing" some limitations apply. That is, the Web2Native Bridge
135 | emulator is *not intended for production* since it doesn't support the following security measures:
136 | * Native application vetting infrastructure. An improperly designed native message extension could enable web access to the entire computer!
137 | * HTTPS information
138 | * Site-blocking support and associated administration
139 |
140 | Although not entirely comforting, Chrome's native messaging framework also lacks these qualities...
141 |
142 | In addition, the scheme injects code in every web page visited which is a core "feature" of Chrome extensions
143 | slowing down execution. It is probably wise disabling the extension (using Chrome *settings*) when not using it.
144 |
--------------------------------------------------------------------------------
/sample1/src/org/webpki/w2nb/sample1/NativeClient.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006-2016 WebPKI.org (http://webpki.org).
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package org.webpki.w2nb.sample1;
18 |
19 | import java.awt.Container;
20 | import java.awt.Dimension;
21 | import java.awt.Font;
22 | import java.awt.GridBagConstraints;
23 | import java.awt.GridBagLayout;
24 | import java.awt.Toolkit;
25 | import java.awt.Insets;
26 |
27 | import java.awt.event.ActionEvent;
28 | import java.awt.event.ActionListener;
29 | import java.awt.event.WindowEvent;
30 | import java.awt.event.WindowAdapter;
31 |
32 | import java.io.IOException;
33 |
34 | import java.util.GregorianCalendar;
35 |
36 | import java.util.logging.Logger;
37 | import java.util.logging.Level;
38 |
39 | import javax.swing.JButton;
40 | import javax.swing.JDialog;
41 | import javax.swing.JFrame;
42 | import javax.swing.JLabel;
43 | import javax.swing.JScrollPane;
44 | import javax.swing.JTextArea;
45 | import javax.swing.JTextField;
46 |
47 | import org.webpki.json.JSONObjectWriter;
48 |
49 | import org.webpki.util.ISODateTime;
50 |
51 | import org.webpki.w2nbproxy.BrowserWindow;
52 | import org.webpki.w2nbproxy.StdinJSONPipe;
53 | import org.webpki.w2nbproxy.StdoutJSONPipe;
54 | import org.webpki.w2nbproxy.LoggerConfiguration;
55 |
56 |
57 | //Simple Web2Native Bridge emulator application
58 |
59 | class ApplicationFrame extends Thread {
60 | StdinJSONPipe stdin = new StdinJSONPipe();
61 | StdoutJSONPipe stdout = new StdoutJSONPipe();
62 | JTextArea textArea;
63 | JTextField sendText;
64 |
65 | ApplicationFrame(Container pane) {
66 | int fontSize = Toolkit.getDefaultToolkit().getScreenResolution() / 7;
67 | JLabel msgLabel = new JLabel("Messages:");
68 | Font font = msgLabel.getFont();
69 | boolean macOS = System.getProperty("os.name").toLowerCase().contains("mac");
70 | if (font.getSize() > fontSize || macOS) {
71 | fontSize = font.getSize();
72 | }
73 | int stdInset = fontSize/3;
74 | msgLabel.setFont(new Font(font.getFontName(), font.getStyle(), fontSize));
75 | pane.setLayout(new GridBagLayout());
76 | GridBagConstraints c = new GridBagConstraints();
77 | c.weightx = 0.0;
78 | c.anchor = GridBagConstraints.WEST;
79 | c.fill = GridBagConstraints.NONE;
80 | c.gridx = 0;
81 | c.gridy = 0;
82 | c.gridwidth = 2;
83 | c.insets = new Insets(stdInset, stdInset, stdInset, stdInset);
84 | pane.add(msgLabel, c);
85 |
86 | textArea = new JTextArea();
87 | textArea.setRows(20);
88 | textArea.setFont(new Font("Courier", Font.PLAIN, fontSize));
89 | textArea.setEditable(false);
90 | JScrollPane scrollPane = new JScrollPane(textArea);
91 | c.fill = GridBagConstraints.BOTH;
92 | c.weightx = 1.0;
93 | c.weighty = 1.0;
94 | c.gridwidth = 2;
95 | c.gridy = 1;
96 | c.insets = new Insets(0, stdInset, 0, stdInset);
97 | pane.add(scrollPane , c);
98 |
99 | JButton sendBut = new JButton("\u00a0\u00a0\u00a0Send\u00a0\u00a0\u00a0");
100 | sendBut.setFont(new Font(font.getFontName(), font.getStyle(), fontSize));
101 | sendBut.addActionListener(new ActionListener() {
102 | @Override
103 | public void actionPerformed(ActionEvent event) {
104 | try {
105 | update(stdout.writeJSONObject(new JSONObjectWriter().setString("native",
106 | sendText.getText())));
107 | } catch (IOException e) {
108 | NativeClient.logger.log(Level.SEVERE, "Writing", e);
109 | System.exit(3);
110 | }
111 | }
112 | });
113 | c.fill = GridBagConstraints.NONE;
114 | c.weightx = 0.0;
115 | c.weighty = 0.0;
116 | c.gridwidth = 1;
117 | c.gridy = 2;
118 | c.insets = new Insets(stdInset, stdInset, stdInset, 0);
119 | pane.add(sendBut, c);
120 |
121 | sendText = new JTextField(50);
122 | sendText.setFont(new Font("Courier", Font.PLAIN, fontSize));
123 | c.fill = GridBagConstraints.HORIZONTAL;
124 | c.gridx = 1;
125 | c.insets = new Insets(stdInset, stdInset, stdInset, stdInset);
126 | pane.add(sendText, c);
127 | }
128 |
129 | void update(String text) {
130 | String localTime = ISODateTime.formatDateTime(new GregorianCalendar(), ISODateTime.LOCAL_NO_SUBSECONDS);
131 | textArea.setText(localTime.substring(0, 10) + " " + localTime.substring(11, 19) +
132 | " " + text + "\n" + textArea.getText());
133 | NativeClient.logger.info(text);
134 | }
135 |
136 | @Override
137 | public void run() {
138 | while (true) {
139 | try {
140 | stdin.readJSONObject(); // Just syntax checking used in our crude sample
141 | update(stdin.getJSONString());
142 | } catch (IOException e) {
143 | NativeClient.logger.log(Level.SEVERE, "Reading", e);
144 | System.exit(3);
145 | }
146 | }
147 | }
148 | }
149 |
150 | public class NativeClient {
151 | static Logger logger = Logger.getLogger("MyLog");
152 |
153 | public static void main(String[] args) {
154 | LoggerConfiguration.init(logger, args);
155 | for (int i = 0; i < args.length; i++) {
156 | logger.info("ARG[" + i + "]=" + args[i]);
157 | }
158 |
159 | BrowserWindow browserWindow = null;
160 | try {
161 | browserWindow = new BrowserWindow(args[3]);
162 | logger.info("Browser window: " + browserWindow);
163 | } catch (Exception e) {
164 | logger.log(Level.SEVERE, "nativeConnect argument errors", e);
165 | }
166 | JDialog frame = new JDialog(new JFrame(), "W2NB - Sample #1 [" + args[2] + "]");
167 | ApplicationFrame md = new ApplicationFrame(frame.getContentPane());
168 | frame.pack();
169 |
170 | if (browserWindow.screenHeight == 0) {
171 | frame.setLocationRelativeTo(null); // tapConnect invocation
172 | } else {
173 | // Put the extension window on top of the upper right of the calling (browser)window
174 | // The alignment varies a bit between platforms :-(
175 | Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
176 | Dimension extensionWindow = frame.getSize();
177 | double factor = screenDimension.height / browserWindow.screenHeight;
178 | double gutter = (browserWindow.outerWidth - browserWindow.innerWidth) / 2;
179 | double x = browserWindow.x + gutter;
180 | x += browserWindow.innerWidth - extensionWindow.width / factor;
181 | double y = browserWindow.y + browserWindow.outerHeight - browserWindow.innerHeight - gutter;
182 | frame.setLocation((int)(x * factor), (int)(y * factor));
183 | }
184 |
185 | frame.setAlwaysOnTop(true);
186 |
187 | frame.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
188 | frame.addWindowListener(new WindowAdapter() {
189 | @Override
190 | public void windowClosing(WindowEvent event) {
191 | System.exit(0);
192 | }
193 | });
194 | frame.setVisible(true);
195 | md.start();
196 | }
197 | }
--------------------------------------------------------------------------------
/proxy/src.cpp/w2nb-proxy.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2006-2015 WebPKI.org (http://webpki.org).
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 |
18 | //////////////////////////////////////////////////////////////////////////////////////////
19 | // w2nb-proxy.cpp //
20 | // //
21 | // This program emulates the proxy required on the native side by the Web2Native Bridge //
22 | // while still only relying on Chrome's Native Messaging. //
23 | // //
24 | // Note: The security features provided by the Web2Native Bridge are NOT supported! //
25 | // //
26 | // Author: Anders Rundgren //
27 | //////////////////////////////////////////////////////////////////////////////////////////
28 |
29 | #ifdef WIN32
30 | #define FILE_SEPARATOR '\\'
31 | #define _CRT_SECURE_NO_WARNINGS
32 | #define JAVA_PLAF " -Dswing.defaultlaf=com.sun.java.swing.plaf.windows.WindowsLookAndFeel"
33 | #define JAVA_LOG " \"-Djava.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s %5$s%6$s%n\""
34 | #else
35 | #define FILE_SEPARATOR '/'
36 | #define JAVA_LOG " \"-Djava.util.logging.SimpleFormatter.format=%1\\$tY-%1\\$tm-%1\\$td %1\\$tH:%1\\$tM:%1\\$tS %4\\$s %2\\$s %5\\$s%6\\$s%n\""
37 | #define JAVA_PLAF ""
38 | #endif
39 |
40 | #include
41 | #include
42 | #include
43 | #include
44 |
45 | #define PROXY_VERSION "1.00"
46 |
47 | #define MANIFEST_SIZE 1000
48 |
49 | static char *res;
50 |
51 | static FILE* logFile;
52 |
53 | static void loggedError(const char* format, ...) {
54 | if (logFile) {
55 | va_list args;
56 | va_start(args, format);
57 | vfprintf(logFile, format, args);
58 | va_end(args);
59 | fclose(logFile);
60 | }
61 | exit(EXIT_FAILURE);
62 | }
63 |
64 | // "Budget" JSON parser
65 | static char* getJSONProperty(char *property, char beginChar, char endChar) {
66 | char buffer[100] = "\"";
67 | strcat(buffer, property);
68 | strcat(buffer, "\":");
69 | char *start = strstr(res, buffer);
70 | if (!start) {
71 | loggedError("Property %s missing\nJSON=\n%s", property, res);
72 | }
73 | start += strlen(buffer);
74 | if (*start++ != beginChar) {
75 | loggedError("Expected: %c\nJSON=\n%s", beginChar, res);
76 | }
77 | char *end = strchr(start, endChar);
78 | if (!end) {
79 | loggedError("Expected: %c\nJSON=\n%s", endChar, res);
80 | }
81 | int length = end - start + 1;
82 | char *value = new char[length--];
83 | strncpy(value, start, length);
84 | value[length] = 0;
85 | return value;
86 | }
87 |
88 | static char* getJSONString(char *property) {
89 | return getJSONProperty(property, '\"', '\"');
90 | }
91 |
92 | static char* getJSONArray(char *property) {
93 | return getJSONProperty(property, '[', ']');
94 | }
95 |
96 | static bool matching(char* accessDescriptor, char* calledBy) {
97 | while (*accessDescriptor) {
98 | if (*accessDescriptor == '*') {
99 | accessDescriptor++;
100 | while (*calledBy != *accessDescriptor) {
101 | if (*calledBy) {
102 | calledBy++;
103 | } else {
104 | return false;
105 | }
106 | }
107 | } else {
108 | if (*calledBy != *accessDescriptor) {
109 | return false;
110 | }
111 | accessDescriptor++;
112 | calledBy++;
113 | }
114 | }
115 | return !*calledBy;
116 | }
117 |
118 | static void checkAccess(char* appPath, char* calledBy) {
119 | char manifest[MANIFEST_SIZE + 1];
120 | int c;
121 | int index = 0;
122 | bool quote = false;
123 |
124 | strcat(appPath, "manifest.json");
125 | FILE* manifestFile = fopen(appPath, "r");
126 | if (!manifestFile) {
127 | loggedError("Error: 'manifest.json' not found!");
128 | }
129 | while ((c = fgetc(manifestFile)) != EOF) {
130 | if (index == MANIFEST_SIZE) {
131 | loggedError("Error: manifest bigger than: %d", MANIFEST_SIZE);
132 | }
133 | if (c == '\"') {
134 | quote = !quote;
135 | }
136 | else if (c == '\\') {
137 | if (!quote || fgetc(manifestFile) != '\\') {
138 | loggedError("Error: unexpected \\ in manifest");
139 | }
140 | }
141 | else if (!quote && (c == ' ' || c == '\n' || c == '\t' || c == '\r')) {
142 | continue;
143 | }
144 | manifest[index++] = (char)c;
145 | }
146 | manifest[index] = (char)0;
147 | fclose(manifestFile);
148 | res = manifest;
149 | char* callableFrom = getJSONArray("callableFrom");
150 | index = 0;
151 | int arrayLength = strlen(callableFrom) - 4;
152 | bool next = false;
153 | while (index < arrayLength) {
154 | if (next) {
155 | if (callableFrom[index++] != ',') {
156 | loggedError("Error: missing ',' in manifest");
157 | }
158 | }
159 | next = true;
160 | if (callableFrom[index++] != '\"') {
161 | loggedError("Error: missing '\"' in manifest");
162 | }
163 | char* startString = callableFrom + index;
164 | char* endString = strchr(startString, '\"');
165 | if (!endString) {
166 | loggedError("Error: missing '\"' in manifest");
167 | }
168 | *endString = 0;
169 | if (matching(startString, calledBy)) {
170 | return;
171 | }
172 | index += strlen(startString) + 1;
173 | }
174 | loggedError("Error: not allowed: %s", calledBy);
175 | }
176 |
177 | int main(int argc, char *argv[]) {
178 | // Reading an initial JSON message which can be of two kinds:
179 | // 1. Proxy verification which consists of an object {"proxyVersion":"n.nn"}
180 | // 2. Java application call which consists of an object ("application":"dotted-path",
181 | // "url":"invocation-url",
182 | // "windowB64":"base64url-encoded-json-object",
183 | // "argumentsB64":"base64url-encoded-json-object"}
184 |
185 | // Chrome presumes message length in native order. Not very cool.
186 | // The following code therefore only runs on little-endian CPUs.
187 | int length = 0;
188 | for (int i = 0; i < 32; i += 8) {
189 | length += getchar() << i;
190 | }
191 |
192 | // We expect a tiny JSON object
193 | if (length > 10000) {
194 | exit(EXIT_FAILURE);
195 | }
196 |
197 | // OK. Read the JSON string
198 | res = new char[length + 1];
199 | for (int n = 0; n < length; n++) {
200 | res[n] = getchar();
201 | }
202 | res[length] = 0;
203 |
204 | // Are we doing proxy verification?
205 | if (strstr(res, "\"proxyVersion\":")) {
206 | if (strcmp(PROXY_VERSION, getJSONString("proxyVersion"))) {
207 | exit(EXIT_FAILURE);
208 | }
209 | char zeroObject[] = { 2,0,0,0,'{','}' };
210 | for (int n = 0; n < sizeof(zeroObject); n++) {
211 | putchar(zeroObject[n]);
212 | }
213 | fclose(stdout);
214 | exit(EXIT_SUCCESS);
215 | }
216 |
217 | // No, we are executing a Java target application
218 | char cmd[2000] = "java" JAVA_LOG JAVA_PLAF " -jar \"";
219 | char path[500];
220 | strcpy(path, argv[0]);
221 | int i = strlen(path);
222 | while (path[--i] != FILE_SEPARATOR)
223 | ;
224 | path[i] = 0;
225 | char fs[] = { FILE_SEPARATOR,0 };
226 |
227 | char *application = getJSONString("application");
228 |
229 | // Check that the caller isn't trying to get outside the sandbox
230 | i = 0;
231 | char c;
232 | while (c = application[i++]) {
233 | if ((c > 'Z' || c < 'A') && (c > 'z' || c < 'a') && (c > '9' || c < '0') && c != '.' && c != '_') {
234 | exit(EXIT_FAILURE);
235 | }
236 | }
237 |
238 | // Create a path to the application directory including /
239 | char appPath[500];
240 | strcpy(appPath, path);
241 | strcat(appPath, fs);
242 | strcat(appPath, "apps");
243 | strcat(appPath, fs);
244 | strcat(appPath, application);
245 | strcat(appPath, fs);
246 |
247 | // The actual JAR to call
248 | strcat(cmd, appPath);
249 | strcat(cmd, application);
250 | strcat(cmd, ".jar\" \"");
251 |
252 | // Parameters to called Java program
253 |
254 | // args[0] => Full path to proxy/install
255 | strcat(cmd, path);
256 | strcat(cmd, "\" ");
257 |
258 | // args[1] => Dotted path (=application name)
259 | strcat(cmd, application);
260 | strcat(cmd, " \"");
261 |
262 | // args[2] => invoking URL
263 | char* calledBy = getJSONString("url");
264 | strcat(cmd, calledBy);
265 | strcat(cmd, "\" ");
266 |
267 | // args[3] => Invoking window core data
268 | strcat(cmd, getJSONString("windowB64"));
269 | strcat(cmd, " ");
270 |
271 | // args[4] => Optional arguments to navigator.nativeConnect
272 | strcat(cmd, getJSONString("argumentsB64"));
273 |
274 | // args[5..n] => Chrome standard arguments
275 | for (int i = 1; i < argc; i++) {
276 | strcat(cmd, " ");
277 | strcat(cmd, argv[i]);
278 | }
279 |
280 | // Log file to last executed command
281 | char fileName[500];
282 | strcpy(fileName, path);
283 | strcat(fileName, fs);
284 | strcat(fileName, "logs");
285 | strcat(fileName, fs);
286 | strcat(fileName, "w2nb-proxy-init.log");
287 | logFile = fopen(fileName, "w");
288 | fprintf(logFile, "commmand: %s\n", cmd);
289 |
290 | // Read the manifest and verify that the caller is legitimate before calling application
291 | checkAccess(appPath, calledBy);
292 |
293 | // This is not the recommended solution for POSIX-compliant systems but hey, this is a PoC...
294 | int returnCode = system(cmd);
295 | if (returnCode) {
296 | fprintf(logFile, "Error: '%s' %d\n", strerror(returnCode), returnCode);
297 | }
298 | fclose(logFile);
299 | return 0;
300 | }
301 |
--------------------------------------------------------------------------------
/AR2.xml:
--------------------------------------------------------------------------------
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 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
--------------------------------------------------------------------------------