Skip to content

Commit

Permalink
Remove setUserAgent, and integrate behavior with addHeaders #7
Browse files Browse the repository at this point in the history
  • Loading branch information
EddyVerbruggen committed Mar 6, 2018
1 parent 5e2b296 commit e9268aa
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 70 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,9 @@ export function webViewLoaded(args: observable.EventData) {
```

### `setUserAgent`
You can set this as a header, but it seems to work better setting it in a different way,
so use this function if you want to override the user agent in your webview.
This method was removed in 2.0.0 because it caused bugs when `addHeaders` was used as well.

> Note for NativeScript-iOS versions older than 3.4: this will override the user agent header in *all* of your webviews within your app. This is usually not an issue, but if it is: upgrade to `tns-ios` 3.4 or newer.
You should now use `addHeaders` and set the `User-Agent` header:

```typescript
import { WebViewUtils } from 'nativescript-webview-utils';
Expand All @@ -94,7 +93,9 @@ import * as observable from 'tns-core-modules/data/observable';

export function webViewForUserAgentLoaded(args: observable.EventData) {
const wv: WebView = <WebView>args.object;
WebViewUtils.setUserAgent(wv, "My Super Duper User-Agent!");
const headers: Map<string, string> = new Map();
headers.set("User-Agent", "My Awesome User-Agent!"); // this line!
WebViewUtils.addHeaders(wv, headers);
}
```

Expand Down
8 changes: 2 additions & 6 deletions demo/app/main-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,12 @@ export function webViewLoaded(args: observable.EventData) {
}

const headers: Map<string, string> = new Map();
headers.set("Foo", "Bar :P");
headers.set("appname", "Bar :P");
headers.set("X-Custom-Header", "Set at " + new Date().toTimeString());
headers.set("User-Agent", "My Awesome User-Agent!");
WebViewUtils.addHeaders(wv, headers);
}

export function webViewForUserAgentLoaded(args: observable.EventData) {
const wv: WebView = <WebView>args.object;
WebViewUtils.setUserAgent(wv, "My Super Duper User-Agent!");
}

export function webViewLoadStarted(args: any) {
const wv: WebView = <WebView>args.object;
console.log(`>>>>>>>> webViewLoadStarted, navigationType for url: ${args.url} = ${args.navigationType}`);
Expand Down
5 changes: 1 addition & 4 deletions demo/app/main-page.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
<WebView height="320" src="https://httpbin.org/headers?wv=1"/>

<Label text="And now with custom headers:" class="t-20 text-center c-black" textWrap="true"/>
<WebView loaded="webViewLoaded" loadStarted="webViewLoadStarted" loadFinished="webViewLoadFinished" height="370" src="https://httpbin.org/headers?wv=2"/>

<Label text="Set custom User Agent (on iOS this affects ALL webviews of your app)" class="t-20 text-center c-black" textWrap="true"/>
<WebView loaded="webViewForUserAgentLoaded" height="320" src="https://httpbin.org/headers?wv=3"/>
<WebView loaded="addHeaders" loadStarted="webViewLoadStarted" loadFinished="webViewLoadFinished" height="370" src="whttps://httpbin.org/headers?wv=2"/>

</StackLayout>
</ScrollView>
Expand Down
13 changes: 0 additions & 13 deletions demo/app/tests/tests.js

This file was deleted.

36 changes: 36 additions & 0 deletions demo/app/tests/tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { WebView } from "tns-core-modules/ui/web-view";
import { WebViewUtils } from "nativescript-webview-utils";

describe("addHeaders", () => {
it("exists", () => {
expect(WebViewUtils.addHeaders).toBeDefined();
});

it("fires the loadStarted and loadFinished events once", done => {
// init the counters to keep track of those events
let loadStartedCounter = 0;
let loadFinishedCounter = 0;

// create a WebView and hook up the events
const webView = new WebView();
webView.on(WebView.loadStartedEvent, data => loadStartedCounter++);
webView.on(WebView.loadFinishedEvent, data => loadFinishedCounter++);

const headers: Map<string, string> = new Map();
headers.set("User-Agent", "My Awesome User-Agent!");
headers.set("Custom-Header", "Another header");

WebViewUtils.addHeaders(webView, headers);

// load a website
// (<any>webView)._loadUrl("https://httpbin.org/headers?testing=schmesting");
(<any>webView)._loadUrl("https://www.nu.nl");

setTimeout(() => {
// if both events fired once, it's ok
expect(loadStartedCounter).toEqual(1);
expect(loadFinishedCounter).toEqual(1);
done();
}, 4000);
});
});
9 changes: 5 additions & 4 deletions demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@
"tns-core-modules": "~3.4.0"
},
"devDependencies": {
"@types/jasmine": "~2.8.6",
"awesome-typescript-loader": "~3.1.3",
"babel-traverse": "6.12.0",
"babel-types": "6.11.1",
"babylon": "6.8.4",
"copy-webpack-plugin": "~4.0.1",
"extract-text-webpack-plugin": "~3.0.0",
"filewalker": "0.1.2",
"jasmine-core": "^2.8.0",
"karma": "^1.7.1",
"karma-jasmine": "^1.1.0",
"karma-nativescript-launcher": "^0.4.0",
"jasmine-core": "~2.8.0",
"karma": "~1.7.0",
"karma-jasmine": "~1.1.0",
"karma-nativescript-launcher": "~0.4.0",
"lazy": "1.0.11",
"nativescript-css-loader": "~0.26.0",
"nativescript-dev-typescript": "libs",
Expand Down
2 changes: 2 additions & 0 deletions demo/references.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
/// <reference path="./node_modules/tns-core-modules/tns-core-modules.d.ts" /> Needed for autocompletion and compilation.

/// <reference path="./node_modules/@types/jasmine/index.d.ts" />
1 change: 0 additions & 1 deletion src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ import { WebView } from "tns-core-modules/ui/web-view";

export const WebViewUtils: {
addHeaders: (wv: WebView, headers: Map<string, string>) => void;
setUserAgent: (wv: WebView, userAgent: string) => void;
};
2 changes: 1 addition & 1 deletion src/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nativescript-webview-utils",
"version": "1.3.0",
"version": "2.0.0",
"description": "Add custom headers to a NativeScript WebView. Perhaps more utils later.",
"main": "webview-utils",
"typings": "index.d.ts",
Expand Down
45 changes: 23 additions & 22 deletions src/webview-utils.android.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { WebView } from "tns-core-modules/ui/web-view";
import { onLoadStarted, onLoadFinished } from "./webview-utils-common";
import { onLoadFinished, onLoadStarted } from "./webview-utils-common";

export class WebViewUtils extends android.webkit.WebViewClient {
// Note that using a static property limits usage of multiple webviews on one page with different headers,
Expand All @@ -8,16 +8,12 @@ export class WebViewUtils extends android.webkit.WebViewClient {
private static wv: WebView;
private headersAddedTo: Set<string> = new Set<string>();

// hackilish flag to make sure we don't fire the onLoadFinished event twice
private isFirstLoad = true;
// hackilish flag to make sure we don't fire the onLoadFinished event multiple times
private startEventCount = 0;

private _view: any;
private _origClient: any; // WebViewClient

public static setUserAgent(wv: WebView, userAgent: string) {
wv.android.getSettings().setUserAgentString(userAgent);
}

public static addHeaders(wv: WebView, headers: Map<string, string>) {
WebViewUtils.wv = wv;
WebViewUtils.headers = headers;
Expand All @@ -39,31 +35,33 @@ export class WebViewUtils extends android.webkit.WebViewClient {
return global.__native(this);
}

// Note that this method is overloaded in Java (changed in Lollipop)
public shouldOverrideUrlLoading(view: android.webkit.WebView, urlOrWebResourceRequest: any /* string | android.webkit.WebResourceRequest */): boolean {
// Note that this method is overloaded in Java (changed in Lollipop - no longer used, from the looks of it)
public shouldOverrideUrlLoading(webView: android.webkit.WebView, urlOrWebResourceRequest: any /* string | android.webkit.WebResourceRequest */): boolean {
const url = typeof urlOrWebResourceRequest === "string" ? urlOrWebResourceRequest : urlOrWebResourceRequest.getUrl().toString();
(<any>view).loadUrl(url, this.getAdditionalHeadersForUrl(url));
(<any>webView).loadUrl(url, this.getAdditionalHeadersForUrl(webView, url));
return true;
}

public onPageStarted(view: android.webkit.WebView, url: string, favicon: android.graphics.Bitmap): void {
super.onPageStarted(view, url, favicon);
public onPageStarted(webView: any, url: string, favicon: android.graphics.Bitmap): void {
super.onPageStarted(webView, url, favicon);
const headersAdded = this.headersAddedTo.has(url);
if (this._view && url.indexOf("http") === 0 && !headersAdded) {
this._view.android.loadUrl(url, this.getAdditionalHeadersForUrl(url));
}
if (headersAdded && WebViewUtils.wv) {
onLoadStarted(WebViewUtils.wv, url, undefined);
if (url.indexOf("http") === 0 && !headersAdded) {
++this.startEventCount;
webView.loadUrl(url, this.getAdditionalHeadersForUrl(webView, url));
} else if (headersAdded && WebViewUtils.wv && url.indexOf("http") === 0) {
if (++this.startEventCount === 3) {
onLoadStarted(WebViewUtils.wv, url, undefined);
}
}
}

public onPageFinished(view: android.webkit.WebView, url: string) {
super.onPageFinished(view, url);
if (!this.isFirstLoad && WebViewUtils.wv) {
if (url.indexOf("http") === -1) {
return;
}
if (WebViewUtils.wv && this.startEventCount === 3) {
onLoadFinished(WebViewUtils.wv, url, undefined);
this.isFirstLoad = true;
} else {
this.isFirstLoad = false;
}
}

Expand Down Expand Up @@ -92,11 +90,14 @@ export class WebViewUtils extends android.webkit.WebViewClient {
}
}

private getAdditionalHeadersForUrl(url: string): java.util.Map<String, String> {
private getAdditionalHeadersForUrl(webView: android.webkit.WebView, url: string): java.util.Map<String, String> {
const headers: java.util.Map<String, String> = new java.util.HashMap();
if (!this.headersAddedTo.has(url)) {
WebViewUtils.headers.forEach((val, key) => {
headers.put(key, val);
if (key.toLowerCase() === "user-agent") {
webView.getSettings().setUserAgentString(val);
}
});
this.headersAddedTo.add(url);
}
Expand Down
28 changes: 13 additions & 15 deletions src/webview-utils.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ class WebviewUtilsWKNavigationDelegateImpl extends NSObject implements WKNavigat
areHeadersAdded = areHeadersAdded && navigationAction.request.valueForHTTPHeaderField(key) === val;
});

if (isHttpRequest && !areHeadersAdded) {
if (!isHttpRequest) {
decisionHandler(WKNavigationActionPolicy.Allow);
return;
}

if (!areHeadersAdded) {
decisionHandler(WKNavigationActionPolicy.Cancel);
const customRequest = new NSMutableURLRequest({
URL: navigationAction.request.URL,
Expand All @@ -35,10 +40,10 @@ class WebviewUtilsWKNavigationDelegateImpl extends NSObject implements WKNavigat
});

this.headers.forEach((val, key) => {
customRequest.setValueForHTTPHeaderField(val, key);
// the user agent is set as header, but also set this property:
if (key.toLowerCase() === "user-agent") {
webView.customUserAgent = val;
} else {
customRequest.setValueForHTTPHeaderField(val, key);
}
});

Expand Down Expand Up @@ -102,18 +107,6 @@ export class WebViewUtils extends NSObject implements UIWebViewDelegate {
private _owner: WeakRef<WebView>;
private _originalDelegate: any; // UIWebViewDelegateImpl

public static setUserAgent(wv: WebView, userAgent: string) {
if (WebViewUtils.isWKWebView(wv)) {
const headers: Map<string, string> = new Map();
headers.set("User-Agent", userAgent);
(<WKWebView>wv.ios).navigationDelegate = (<any>wv)._delegate = WebviewUtilsWKNavigationDelegateImpl.initWithOwnerAndHeaders(new WeakRef(wv), headers);
} else {
// note that this overrides the useragent for ALL webviews for the app, but that's prolly not a problem
NSUserDefaults.standardUserDefaults.registerDefaults(
NSDictionary.dictionaryWithObjectForKey(userAgent, "UserAgent"));
}
}

public static addHeaders(wv: WebView, headers: Map<string, string>) {
if (WebViewUtils.isWKWebView(wv)) {
(<WKWebView>wv.ios).navigationDelegate = (<any>wv)._delegate = WebviewUtilsWKNavigationDelegateImpl.initWithOwnerAndHeaders(new WeakRef(wv), headers);
Expand Down Expand Up @@ -162,6 +155,11 @@ export class WebViewUtils extends NSObject implements UIWebViewDelegate {

WebViewUtils.headers.forEach((val, key) => {
nsMutableURLRequest.setValueForHTTPHeaderField(val, key);
if (key.toLowerCase() === "user-agent") {
// note that this overrides the useragent for ALL webviews for the app, but that's prolly not a problem
NSUserDefaults.standardUserDefaults.registerDefaults(
NSDictionary.dictionaryWithObjectForKey(val, "UserAgent"));
}
});

webView.loadRequest(nsMutableURLRequest);
Expand Down

0 comments on commit e9268aa

Please sign in to comment.