Skip to content

Commit

Permalink
Add tab identifier and browser context (close #1142) (close #815)
Browse files Browse the repository at this point in the history
  • Loading branch information
igneel64 committed Jan 23, 2023
1 parent 50fb7ea commit 08ca527
Show file tree
Hide file tree
Showing 17 changed files with 600 additions and 168 deletions.
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@snowplow/browser-tracker-core",
"comment": "Add browser context and ability to generate tab identifier.",
"type": "none"
}
],
"packageName": "@snowplow/browser-tracker-core"
}
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@snowplow/browser-tracker",
"comment": "Add tracker.getTabId() API.",
"type": "none"
}
],
"packageName": "@snowplow/browser-tracker"
}
43 changes: 0 additions & 43 deletions libraries/browser-tracker-core/src/detectors.ts
Expand Up @@ -73,46 +73,3 @@ export function localStorageAccessible() {
return false;
}
}

/**
* Gets the current viewport.
*
* Code based on:
* - http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/
* - http://responsejs.com/labs/dimensions/
*/
export function detectViewport() {
var width, height;

if ('innerWidth' in window) {
width = window['innerWidth'];
height = window['innerHeight'];
} else {
const e = document.documentElement || document.body;
width = e['clientWidth'];
height = e['clientHeight'];
}

if (width >= 0 && height >= 0) {
return width + 'x' + height;
} else {
return null;
}
}

/**
* Gets the dimensions of the current
* document.
*
* Code based on:
* - http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/
*/
export function detectDocumentSize() {
var de = document.documentElement, // Alias
be = document.body,
// document.body may not have rendered, so check whether be.offsetHeight is null
bodyHeight = be ? Math.max(be.offsetHeight, be.scrollHeight) : 0;
var w = Math.max(de.clientWidth, de.offsetWidth, de.scrollWidth);
var h = Math.max(de.clientHeight, de.offsetHeight, de.scrollHeight, bodyHeight);
return isNaN(w) || isNaN(h) ? '' : w + 'x' + h;
}
59 changes: 59 additions & 0 deletions libraries/browser-tracker-core/src/helpers/browser_props.ts
@@ -0,0 +1,59 @@
export function getBrowserProperties() {
return {
viewport: detectViewport(),
documentSize: detectDocumentSize(),
resolution: screen.width + 'x' + screen.height,
colorDepth: screen.colorDepth,
devicePixelRatio: window.devicePixelRatio,
cookiesEnabled: window.navigator.cookieEnabled,
online: window.navigator.onLine,
browserLanguage: navigator.language || (navigator as any).userLanguage,
documentLanguage: document.documentElement.lang,
webdriver: window.navigator.webdriver,
deviceMemory: (window.navigator as any).deviceMemory,
hardwareConcurrency: (window.navigator as any).hardwareConcurrency,
};
}

/**
* Gets the current viewport.
*
* Code based on:
* - http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/
* - http://responsejs.com/labs/dimensions/
*/
function detectViewport() {
var width, height;

if ('innerWidth' in window) {
width = window['innerWidth'];
height = window['innerHeight'];
} else {
const e = document.documentElement || document.body;
width = e['clientWidth'];
height = e['clientHeight'];
}

if (width >= 0 && height >= 0) {
return width + 'x' + height;
} else {
return null;
}
}

/**
* Gets the dimensions of the current
* document.
*
* Code based on:
* - http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/
*/
function detectDocumentSize() {
var de = document.documentElement, // Alias
be = document.body,
// document.body may not have rendered, so check whether be.offsetHeight is null
bodyHeight = be ? Math.max(be.offsetHeight, be.scrollHeight) : 0;
var w = Math.max(de.clientWidth, de.offsetWidth, de.scrollWidth);
var h = Math.max(de.clientHeight, de.offsetHeight, de.scrollHeight, bodyHeight);
return isNaN(w) || isNaN(h) ? '' : w + 'x' + h;
}
Expand Up @@ -28,6 +28,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

export * from './storage';

declare global {
interface EventTarget {
attachEvent?: (type: string, fn: EventListenerOrEventListenerObject) => void;
Expand Down Expand Up @@ -224,97 +226,6 @@ export function decorateQuerystring(url: string, name: string, value: string) {
return hashSplit.join('#');
}

/**
* Attempt to get a value from localStorage
*
* @param string - key
* @returns string The value obtained from localStorage, or
* undefined if localStorage is inaccessible
*/
export function attemptGetLocalStorage(key: string) {
try {
const localStorageAlias = window.localStorage,
exp = localStorageAlias.getItem(key + '.expires');
if (exp === null || +exp > Date.now()) {
return localStorageAlias.getItem(key);
} else {
localStorageAlias.removeItem(key);
localStorageAlias.removeItem(key + '.expires');
}
return undefined;
} catch (e) {
return undefined;
}
}

/**
* Attempt to write a value to localStorage
*
* @param string - key
* @param string - value
* @param number - ttl Time to live in seconds, defaults to 2 years from Date.now()
* @returns boolean Whether the operation succeeded
*/
export function attemptWriteLocalStorage(key: string, value: string, ttl = 63072000) {
try {
const localStorageAlias = window.localStorage,
t = Date.now() + ttl * 1000;
localStorageAlias.setItem(`${key}.expires`, t.toString());
localStorageAlias.setItem(key, value);
return true;
} catch (e) {
return false;
}
}

/**
* Attempt to delete a value from localStorage
*
* @param string - key
* @returns boolean Whether the operation succeeded
*/
export function attemptDeleteLocalStorage(key: string) {
try {
const localStorageAlias = window.localStorage;
localStorageAlias.removeItem(key);
localStorageAlias.removeItem(key + '.expires');
return true;
} catch (e) {
return false;
}
}

/**
* Attempt to get a value from sessionStorage
*
* @param string - key
* @returns string The value obtained from sessionStorage, or
* undefined if sessionStorage is inaccessible
*/
export function attemptGetSessionStorage(key: string) {
try {
return window.sessionStorage.getItem(key);
} catch (e) {
return undefined;
}
}

/**
* Attempt to write a value to sessionStorage
*
* @param string - key
* @param string - value
* @returns boolean Whether the operation succeeded
*/
export function attemptWriteSessionStorage(key: string, value: string) {
try {
window.sessionStorage.setItem(key, value);
return true;
} catch (e) {
return false;
}
}

/**
* Finds the root domain
*/
Expand Down
120 changes: 120 additions & 0 deletions libraries/browser-tracker-core/src/helpers/storage.ts
@@ -0,0 +1,120 @@
/*
* Copyright (c) 2022 Snowplow Analytics Ltd, 2010 Anthon Pang
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**
* Attempt to get a value from localStorage
*
* @param string - key
* @returns string The value obtained from localStorage, or
* undefined if localStorage is inaccessible
*/
export function attemptGetLocalStorage(key: string) {
try {
const localStorageAlias = window.localStorage,
exp = localStorageAlias.getItem(key + '.expires');
if (exp === null || +exp > Date.now()) {
return localStorageAlias.getItem(key);
} else {
localStorageAlias.removeItem(key);
localStorageAlias.removeItem(key + '.expires');
}
return undefined;
} catch (e) {
return undefined;
}
}

/**
* Attempt to write a value to localStorage
*
* @param string - key
* @param string - value
* @param number - ttl Time to live in seconds, defaults to 2 years from Date.now()
* @returns boolean Whether the operation succeeded
*/
export function attemptWriteLocalStorage(key: string, value: string, ttl = 63072000) {
try {
const localStorageAlias = window.localStorage,
t = Date.now() + ttl * 1000;
localStorageAlias.setItem(`${key}.expires`, t.toString());
localStorageAlias.setItem(key, value);
return true;
} catch (e) {
return false;
}
}

/**
* Attempt to delete a value from localStorage
*
* @param string - key
* @returns boolean Whether the operation succeeded
*/
export function attemptDeleteLocalStorage(key: string) {
try {
const localStorageAlias = window.localStorage;
localStorageAlias.removeItem(key);
localStorageAlias.removeItem(key + '.expires');
return true;
} catch (e) {
return false;
}
}

/**
* Attempt to get a value from sessionStorage
*
* @param string - key
* @returns string The value obtained from sessionStorage, or
* undefined if sessionStorage is inaccessible
*/
export function attemptGetSessionStorage(key: string) {
try {
return window.sessionStorage.getItem(key);
} catch (e) {
return undefined;
}
}

/**
* Attempt to write a value to sessionStorage
*
* @param string - key
* @param string - value
* @returns boolean Whether the operation succeeded
*/
export function attemptWriteSessionStorage(key: string, value: string) {
try {
window.sessionStorage.setItem(key, value);
return true;
} catch (e) {
return false;
}
}

0 comments on commit 08ca527

Please sign in to comment.