Skip to content

Commit

Permalink
fix: set iframe deeplink target to _top (#5602)
Browse files Browse the repository at this point in the history
* fix: set iframe deeplink target to _top

* refactor: create openDeeplink util

* test: add tests for isIframe util
  • Loading branch information
zoruka authored Jan 17, 2025
1 parent f2bfda5 commit f8bd18a
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 6 deletions.
25 changes: 20 additions & 5 deletions packages/utils/src/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,11 +413,7 @@ export async function handleDeeplinkRedirect({
return;
}

if (link.startsWith("https://") || link.startsWith("http://")) {
window.open(link, "_blank", "noreferrer noopener");
} else {
window.open(link, isTelegram() ? "_blank" : "_self", "noreferrer noopener");
}
openDeeplink(link);
} else if (env === ENV_MAP.reactNative) {
// global.Linking is set by react-native-compat
if (typeof (global as any)?.Linking !== "undefined") {
Expand All @@ -444,6 +440,17 @@ export function formatDeeplinkUrl(deeplink: string, requestId: number, sessionTo
return link;
}

export function openDeeplink(url: string) {
let target = "_self";
if (isIframe()) {
target = "_top";
} else if (isTelegram() || url.startsWith("https://") || url.startsWith("http://")) {
target = "_blank";
}

window.open(url, target, "noreferrer noopener");
}

export async function getDeepLink(storage: IKeyValueStorage, key: string) {
let link: string | undefined = "";
try {
Expand Down Expand Up @@ -501,6 +508,14 @@ export function isTelegram() {
);
}

export function isIframe() {
try {
return window.self !== window.top;
} catch {
return false;
}
}

export function toBase64(input: string, removePadding = false): string {
const encoded = Buffer.from(input).toString("base64");
return removePadding ? encoded.replace(/[=]/g, "") : encoded;
Expand Down
83 changes: 82 additions & 1 deletion packages/utils/test/misc.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { afterAll, afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
calcExpiry,
formatDeeplinkUrl,
Expand All @@ -8,6 +8,8 @@ import {
hasOverlap,
isExpired,
toBase64,
openDeeplink,
isIframe,
} from "../src";

const RELAY_URL = "wss://relay.walletconnect.org";
Expand Down Expand Up @@ -189,5 +191,84 @@ describe("Misc", () => {
const decoded = atob(formatted.split("startapp=")[1]);
expect(decoded).to.eql(partToEncode);
});

describe("openDeeplink", () => {
const previousWindow = globalThis.window;

beforeEach(() => {
Object.assign(globalThis, {
window: {
open: vi.fn(),
},
});
});

afterAll(() => {
Object.assign(globalThis, {
window: previousWindow,
});
});

it("should target '_blank' if link starts with 'https://'", () => {
const url = "https://example.com";
openDeeplink(url);
expect(window.open).toHaveBeenCalledWith(url, "_blank", "noreferrer noopener");
});

it("should target '_blank' if link starts with 'http://'", () => {
const url = "http://example.com";
openDeeplink(url);
expect(window.open).toHaveBeenCalledWith(url, "_blank", "noreferrer noopener");
});

it("should target '_blank' for telegram deep link", () => {
Object.assign(window, {
Telegram: {},
});

const url = "scheme://example.com";
openDeeplink(url);
expect(window.open).toHaveBeenCalledWith(url, "_blank", "noreferrer noopener");

(window as any).Telegram = undefined;
});

it("should target '_top' if is an iframe", () => {
Object.assign(window, {
top: {},
});

const url = "scheme://example.com";
openDeeplink(url);
expect(window.open).toHaveBeenCalledWith(url, "_top", "noreferrer noopener");
});

it("should target '_self' for other cases", () => {
const url = "scheme://example.com";
openDeeplink(url);
expect(window.open).toHaveBeenCalledWith(url, "_self", "noreferrer noopener");
});
});
});

describe("isIframe", () => {
const previousWindow = globalThis.window;

afterEach(() => {
Object.assign(globalThis, { window: previousWindow });
});

it("should return true if window.top is not equal to window", () => {
Object.assign(globalThis, {
window: {
top: {},
},
});
expect(isIframe()).to.be.true;
});

it("should return false if window.top is equal to window", () => {
expect(isIframe()).to.be.false;
});
});
});

0 comments on commit f8bd18a

Please sign in to comment.