1 | import Cookies from "js-cookie";
|
2 | import { UAParser } from "ua-parser-js";
|
3 | export { UAParser };
|
4 |
|
5 | import { BrowserCompatibility } from "./browserCompatibility";
|
6 |
|
7 | export namespace BrowserHelper {
|
8 | |
9 |
|
10 |
|
11 | interface Browser {
|
12 | name?: string;
|
13 | version?: string;
|
14 | }
|
15 |
|
16 | |
17 |
|
18 |
|
19 | interface CPU {
|
20 | architecture?: string;
|
21 | }
|
22 |
|
23 | |
24 |
|
25 |
|
26 | interface Device {
|
27 | model?: string;
|
28 | vendor?: string;
|
29 |
|
30 | type?: string;
|
31 | }
|
32 |
|
33 | |
34 |
|
35 |
|
36 | interface Engine {
|
37 | name?: string;
|
38 | version?: string;
|
39 | }
|
40 |
|
41 | |
42 |
|
43 |
|
44 | interface OS {
|
45 | name?: string;
|
46 | version?: string;
|
47 | }
|
48 |
|
49 | |
50 |
|
51 |
|
52 | export const userAgentInfo: {
|
53 | getBrowser(): Browser;
|
54 | getOS(): OS;
|
55 | getEngine(): Engine;
|
56 | getDevice(): Device;
|
57 | getCPU(): CPU;
|
58 | getUA(): string;
|
59 | setUA(uastring: string): void;
|
60 | } = new UAParser(navigator.userAgent);
|
61 |
|
62 | |
63 |
|
64 |
|
65 | export const canvas: HTMLCanvasElement = document.createElement("canvas");
|
66 |
|
67 | |
68 |
|
69 |
|
70 | export function checkBrowserCompatibility(): BrowserCompatibility {
|
71 | function objectHasPropertyWithType(object: object, propertyNames: string[], propertyType: string): boolean {
|
72 |
|
73 | const objectProperty: any = (<any>object)[propertyNames[0]];
|
74 | if (objectProperty == null) {
|
75 | return false;
|
76 | }
|
77 | if (propertyNames.length === 1) {
|
78 | return typeof objectProperty === propertyType;
|
79 | } else {
|
80 | return (
|
81 | (typeof objectProperty === "function" || typeof objectProperty === "object") &&
|
82 | objectHasPropertyWithType(objectProperty, propertyNames.slice(1), propertyType)
|
83 | );
|
84 | }
|
85 | }
|
86 |
|
87 | function isBrokenWebAssemblyOS(os: OS): boolean {
|
88 | return os.name === "iOS" && os.version != null && ["11.2.2", "11.2.5", "11.2.6"].includes(os.version);
|
89 | }
|
90 |
|
91 | let fullSupport: boolean = true;
|
92 | let scannerSupport: boolean = true;
|
93 | const missingFeatures: BrowserCompatibility.Feature[] = [];
|
94 |
|
95 | if (
|
96 | !objectHasPropertyWithType(navigator, ["mediaDevices", "getUserMedia"], "function") &&
|
97 | !objectHasPropertyWithType(navigator, ["enumerateDevices"], "function") &&
|
98 | !objectHasPropertyWithType(window, ["MediaStreamTrack", "getSources"], "function")
|
99 | ) {
|
100 | missingFeatures.push(BrowserCompatibility.Feature.MEDIA_DEVICES);
|
101 | fullSupport = false;
|
102 | }
|
103 |
|
104 | if (!objectHasPropertyWithType(window, ["Worker"], "function")) {
|
105 | missingFeatures.push(BrowserCompatibility.Feature.WEB_WORKERS);
|
106 | fullSupport = scannerSupport = false;
|
107 | }
|
108 |
|
109 | if (!objectHasPropertyWithType(window, ["WebAssembly"], "object")) {
|
110 | missingFeatures.push(BrowserCompatibility.Feature.WEB_ASSEMBLY);
|
111 | fullSupport = scannerSupport = false;
|
112 | }
|
113 |
|
114 | if (!objectHasPropertyWithType(window, ["Blob"], "function")) {
|
115 | missingFeatures.push(BrowserCompatibility.Feature.BLOB);
|
116 | fullSupport = scannerSupport = false;
|
117 | }
|
118 |
|
119 | if (!objectHasPropertyWithType(window, ["URL", "createObjectURL"], "function")) {
|
120 | missingFeatures.push(BrowserCompatibility.Feature.URL_OBJECT);
|
121 | fullSupport = scannerSupport = false;
|
122 | }
|
123 |
|
124 | if (!objectHasPropertyWithType(window, ["OffscreenCanvas"], "function")) {
|
125 | missingFeatures.push(BrowserCompatibility.Feature.OFFSCREEN_CANVAS);
|
126 | }
|
127 |
|
128 | try {
|
129 | if (
|
130 | !objectHasPropertyWithType(window, ["WebGLRenderingContext"], "function") ||
|
131 | (canvas.getContext("webgl") == null && canvas.getContext("experimental-webgl") == null)
|
132 | ) {
|
133 | throw new Error();
|
134 | }
|
135 | } catch {
|
136 | missingFeatures.push(BrowserCompatibility.Feature.WEBGL);
|
137 | }
|
138 |
|
139 | const userAgentOS: OS = userAgentInfo.getOS();
|
140 | if (isBrokenWebAssemblyOS(userAgentOS)) {
|
141 | missingFeatures.push(BrowserCompatibility.Feature.WEB_ASSEMBLY_ERROR_FREE);
|
142 | fullSupport = scannerSupport = false;
|
143 | }
|
144 |
|
145 | return {
|
146 | fullSupport,
|
147 | scannerSupport,
|
148 | missingFeatures
|
149 | };
|
150 | }
|
151 |
|
152 | |
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 | export function getDeviceId(): string {
|
161 | const cookieKey: string = "scandit-device-id";
|
162 | const storedDeviceId: string | undefined = Cookies.get("scandit-device-id");
|
163 | if (storedDeviceId != null && storedDeviceId !== "") {
|
164 | return storedDeviceId;
|
165 | }
|
166 | const hexCharacters: string = "0123456789abcdef";
|
167 | let randomDeviceId: string = "";
|
168 | for (let i: number = 0; i < 40; ++i) {
|
169 |
|
170 | randomDeviceId += hexCharacters.charAt(Math.floor(Math.random() * 16));
|
171 | }
|
172 | Cookies.set(cookieKey, randomDeviceId, { expires: 3650 });
|
173 |
|
174 | return randomDeviceId;
|
175 | }
|
176 |
|
177 | |
178 |
|
179 |
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 | export function isValidHTMLElement(object: any): boolean {
|
187 | return (
|
188 | object instanceof HTMLElement ||
|
189 | (object != null && typeof object === "object" && typeof object.tagName === "string")
|
190 | );
|
191 | }
|
192 | }
|