UNPKG

19.2 kBPlain TextView Raw
1/*
2 Licensed under the Apache License, Version 2.0 (the "License");
3 you may not use this file except in compliance with the License.
4 You may obtain a copy of the License at
5
6 http://www.apache.org/licenses/LICENSE-2.0
7
8 Unless required by applicable law or agreed to in writing, software
9 distributed under the License is distributed on an "AS IS" BASIS,
10 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 See the License for the specific language governing permissions and
12 limitations under the License.
13*/
14
15using System;
16using System.Diagnostics;
17using System.IO;
18using System.Runtime.Serialization;
19using System.Windows;
20using System.Windows.Controls;
21using System.Windows.Media;
22using Microsoft.Phone.Controls;
23using Microsoft.Phone.Shell;
24
25#if WP8
26using System.Threading.Tasks;
27using Windows.ApplicationModel;
28using Windows.Storage;
29using Windows.System;
30
31//Use alias in case Cordova File Plugin is enabled. Then the File class will be declared in both and error will occur.
32using IOFile = System.IO.File;
33#else
34using Microsoft.Phone.Tasks;
35#endif
36
37namespace WPCordovaClassLib.Cordova.Commands
38{
39 [DataContract]
40 public class BrowserOptions
41 {
42 [DataMember]
43 public string url;
44
45 [DataMember]
46 public bool isGeolocationEnabled;
47 }
48
49 public class InAppBrowser : BaseCommand
50 {
51
52 private static WebBrowser browser;
53 private static ApplicationBarIconButton backButton;
54 private static ApplicationBarIconButton fwdButton;
55
56 protected ApplicationBar AppBar;
57
58 protected bool ShowLocation {get;set;}
59 protected bool StartHidden {get;set;}
60
61 protected string NavigationCallbackId { get; set; }
62
63 public void open(string options)
64 {
65 // reset defaults on ShowLocation + StartHidden features
66 ShowLocation = true;
67 StartHidden = false;
68
69 string[] args = JSON.JsonHelper.Deserialize<string[]>(options);
70 //BrowserOptions opts = JSON.JsonHelper.Deserialize<BrowserOptions>(options);
71 string urlLoc = args[0];
72 string target = args[1];
73 string featString = args[2];
74 this.NavigationCallbackId = args[3];
75
76 if (!string.IsNullOrEmpty(featString))
77 {
78 string[] features = featString.Split(',');
79 foreach (string str in features)
80 {
81 try
82 {
83 string[] split = str.Split('=');
84 switch (split[0])
85 {
86 case "location":
87 ShowLocation = split[1].StartsWith("yes", StringComparison.OrdinalIgnoreCase);
88 break;
89 case "hidden":
90 StartHidden = split[1].StartsWith("yes", StringComparison.OrdinalIgnoreCase);
91 break;
92 }
93 }
94 catch (Exception)
95 {
96 // some sort of invalid param was passed, moving on ...
97 }
98 }
99 }
100 /*
101 _self - opens in the Cordova WebView if url is in the white-list, else it opens in the InAppBrowser
102 _blank - always open in the InAppBrowser
103 _system - always open in the system web browser
104 */
105 switch (target)
106 {
107 case "_blank":
108 ShowInAppBrowser(urlLoc);
109 break;
110 case "_self":
111 ShowCordovaBrowser(urlLoc);
112 break;
113 case "_system":
114 ShowSystemBrowser(urlLoc);
115 break;
116 }
117 }
118
119 public void show(string options)
120 {
121 string[] args = JSON.JsonHelper.Deserialize<string[]>(options);
122
123
124 if (browser != null)
125 {
126 Deployment.Current.Dispatcher.BeginInvoke(() =>
127 {
128 browser.Visibility = Visibility.Visible;
129 AppBar.IsVisible = true;
130 });
131 }
132 }
133
134 public void hide(string options)
135 {
136 string[] args = JSON.JsonHelper.Deserialize<string[]>(options);
137
138
139 if (browser != null)
140 {
141 Deployment.Current.Dispatcher.BeginInvoke(() =>
142 {
143 browser.Visibility = Visibility.Collapsed;
144 AppBar.IsVisible = false;
145 });
146 }
147 }
148
149 public void injectScriptCode(string options)
150 {
151 string[] args = JSON.JsonHelper.Deserialize<string[]>(options);
152
153 bool bCallback = false;
154 if (bool.TryParse(args[1], out bCallback)) { };
155
156 string callbackId = args[2];
157
158 if (browser != null)
159 {
160 Deployment.Current.Dispatcher.BeginInvoke(() =>
161 {
162 var res = browser.InvokeScript("eval", new string[] { args[0] });
163
164 if (bCallback)
165 {
166 PluginResult result = new PluginResult(PluginResult.Status.OK, res.ToString());
167 result.KeepCallback = false;
168 this.DispatchCommandResult(result);
169 }
170
171 });
172 }
173 }
174
175 public void injectScriptFile(string options)
176 {
177 Debug.WriteLine("Error : Windows Phone cordova-plugin-inappbrowser does not currently support executeScript");
178 string[] args = JSON.JsonHelper.Deserialize<string[]>(options);
179 // throw new NotImplementedException("Windows Phone does not currently support 'executeScript'");
180 }
181
182 public void injectStyleCode(string options)
183 {
184 Debug.WriteLine("Error : Windows Phone cordova-plugin-inappbrowser does not currently support insertCSS");
185 return;
186
187 //string[] args = JSON.JsonHelper.Deserialize<string[]>(options);
188 //bool bCallback = false;
189 //if (bool.TryParse(args[1], out bCallback)) { };
190
191 //string callbackId = args[2];
192
193 //if (browser != null)
194 //{
195 //Deployment.Current.Dispatcher.BeginInvoke(() =>
196 //{
197 // if (bCallback)
198 // {
199 // string cssInsertString = "try{(function(doc){var c = '<style>body{background-color:#ffff00;}</style>'; doc.head.innerHTML += c;})(document);}catch(ex){alert('oops : ' + ex.message);}";
200 // //cssInsertString = cssInsertString.Replace("_VALUE_", args[0]);
201 // Debug.WriteLine("cssInsertString = " + cssInsertString);
202 // var res = browser.InvokeScript("eval", new string[] { cssInsertString });
203 // if (bCallback)
204 // {
205 // PluginResult result = new PluginResult(PluginResult.Status.OK, res.ToString());
206 // result.KeepCallback = false;
207 // this.DispatchCommandResult(result);
208 // }
209 // }
210
211 //});
212 //}
213 }
214
215 public void injectStyleFile(string options)
216 {
217 Debug.WriteLine("Error : Windows Phone cordova-plugin-inappbrowser does not currently support insertCSS");
218 return;
219
220 //string[] args = JSON.JsonHelper.Deserialize<string[]>(options);
221 //throw new NotImplementedException("Windows Phone does not currently support 'insertCSS'");
222 }
223
224 private void ShowCordovaBrowser(string url)
225 {
226 Uri loc = new Uri(url, UriKind.RelativeOrAbsolute);
227 Deployment.Current.Dispatcher.BeginInvoke(() =>
228 {
229 PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame;
230 if (frame != null)
231 {
232 PhoneApplicationPage page = frame.Content as PhoneApplicationPage;
233 if (page != null)
234 {
235 CordovaView cView = page.FindName("CordovaView") as CordovaView;
236 if (cView != null)
237 {
238 WebBrowser br = cView.Browser;
239 br.Navigate2(loc);
240 }
241 }
242
243 }
244 });
245 }
246
247#if WP8
248 private async void ShowSystemBrowser(string url)
249 {
250 var pathUri = new Uri(url, UriKind.Absolute);
251 if (pathUri.Scheme == Uri.UriSchemeHttp || pathUri.Scheme == Uri.UriSchemeHttps)
252 {
253 await Launcher.LaunchUriAsync(pathUri);
254 return;
255 }
256
257 var file = await GetFile(pathUri.AbsolutePath.Replace('/', Path.DirectorySeparatorChar));
258 if (file != null)
259 {
260 await Launcher.LaunchFileAsync(file);
261 }
262 else
263 {
264 Debug.WriteLine("File not found.");
265 }
266 }
267
268 private async Task<StorageFile> GetFile(string fileName)
269 {
270 //first try to get the file from the isolated storage
271 var localFolder = ApplicationData.Current.LocalFolder;
272 if (IOFile.Exists(Path.Combine(localFolder.Path, fileName)))
273 {
274 return await localFolder.GetFileAsync(fileName);
275 }
276
277 //if file is not found try to get it from the xap
278 var filePath = Path.Combine(Package.Current.InstalledLocation.Path, fileName);
279 if (IOFile.Exists(filePath))
280 {
281 return await StorageFile.GetFileFromPathAsync(filePath);
282 }
283
284 return null;
285 }
286#else
287 private void ShowSystemBrowser(string url)
288 {
289 WebBrowserTask webBrowserTask = new WebBrowserTask();
290 webBrowserTask.Uri = new Uri(url, UriKind.Absolute);
291 webBrowserTask.Show();
292 }
293#endif
294
295 private void ShowInAppBrowser(string url)
296 {
297 Uri loc = new Uri(url, UriKind.RelativeOrAbsolute);
298
299 Deployment.Current.Dispatcher.BeginInvoke(() =>
300 {
301 if (browser != null)
302 {
303 //browser.IsGeolocationEnabled = opts.isGeolocationEnabled;
304 browser.Navigate2(loc);
305 }
306 else
307 {
308 PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame;
309 if (frame != null)
310 {
311 PhoneApplicationPage page = frame.Content as PhoneApplicationPage;
312
313 string baseImageUrl = "Images/";
314
315 if (page != null)
316 {
317 Grid grid = page.FindName("LayoutRoot") as Grid;
318 if (grid != null)
319 {
320 browser = new WebBrowser();
321 browser.IsScriptEnabled = true;
322 browser.LoadCompleted += new System.Windows.Navigation.LoadCompletedEventHandler(browser_LoadCompleted);
323
324 browser.Navigating += new EventHandler<NavigatingEventArgs>(browser_Navigating);
325 browser.NavigationFailed += new System.Windows.Navigation.NavigationFailedEventHandler(browser_NavigationFailed);
326 browser.Navigated += new EventHandler<System.Windows.Navigation.NavigationEventArgs>(browser_Navigated);
327 browser.Navigate2(loc);
328
329 if (StartHidden)
330 {
331 browser.Visibility = Visibility.Collapsed;
332 }
333
334 //browser.IsGeolocationEnabled = opts.isGeolocationEnabled;
335 grid.Children.Add(browser);
336 }
337
338 ApplicationBar bar = new ApplicationBar();
339 bar.BackgroundColor = Colors.Gray;
340 bar.IsMenuEnabled = false;
341
342 backButton = new ApplicationBarIconButton();
343 backButton.Text = "Back";
344
345 backButton.IconUri = new Uri(baseImageUrl + "appbar.back.rest.png", UriKind.Relative);
346 backButton.Click += new EventHandler(backButton_Click);
347 bar.Buttons.Add(backButton);
348
349
350 fwdButton = new ApplicationBarIconButton();
351 fwdButton.Text = "Forward";
352 fwdButton.IconUri = new Uri(baseImageUrl + "appbar.next.rest.png", UriKind.Relative);
353 fwdButton.Click += new EventHandler(fwdButton_Click);
354 bar.Buttons.Add(fwdButton);
355
356 ApplicationBarIconButton closeBtn = new ApplicationBarIconButton();
357 closeBtn.Text = "Close";
358 closeBtn.IconUri = new Uri(baseImageUrl + "appbar.close.rest.png", UriKind.Relative);
359 closeBtn.Click += new EventHandler(closeBtn_Click);
360 bar.Buttons.Add(closeBtn);
361
362 page.ApplicationBar = bar;
363 bar.IsVisible = !StartHidden;
364 AppBar = bar;
365
366 page.BackKeyPress += page_BackKeyPress;
367
368 }
369
370 }
371 }
372 });
373 }
374
375 void page_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
376 {
377#if WP8
378 if (browser.CanGoBack)
379 {
380 browser.GoBack();
381 }
382 else
383 {
384 close();
385 }
386 e.Cancel = true;
387#else
388 browser.InvokeScript("execScript", "history.back();");
389#endif
390 }
391
392 void browser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
393 {
394
395 }
396
397 void fwdButton_Click(object sender, EventArgs e)
398 {
399 if (browser != null)
400 {
401 try
402 {
403#if WP8
404 browser.GoForward();
405#else
406 browser.InvokeScript("execScript", "history.forward();");
407#endif
408 }
409 catch (Exception)
410 {
411
412 }
413 }
414 }
415
416 void backButton_Click(object sender, EventArgs e)
417 {
418 if (browser != null)
419 {
420 try
421 {
422#if WP8
423 browser.GoBack();
424#else
425 browser.InvokeScript("execScript", "history.back();");
426#endif
427 }
428 catch (Exception)
429 {
430
431 }
432 }
433 }
434
435 void closeBtn_Click(object sender, EventArgs e)
436 {
437 this.close();
438 }
439
440
441 public void close(string options = "")
442 {
443 if (browser != null)
444 {
445 Deployment.Current.Dispatcher.BeginInvoke(() =>
446 {
447 PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame;
448 if (frame != null)
449 {
450 PhoneApplicationPage page = frame.Content as PhoneApplicationPage;
451 if (page != null)
452 {
453 Grid grid = page.FindName("LayoutRoot") as Grid;
454 if (grid != null)
455 {
456 grid.Children.Remove(browser);
457 }
458 page.ApplicationBar = null;
459 page.BackKeyPress -= page_BackKeyPress;
460 }
461 }
462
463 browser = null;
464 string message = "{\"type\":\"exit\"}";
465 PluginResult result = new PluginResult(PluginResult.Status.OK, message);
466 result.KeepCallback = false;
467 this.DispatchCommandResult(result, NavigationCallbackId);
468 });
469 }
470 }
471
472 void browser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
473 {
474#if WP8
475 if (browser != null)
476 {
477 backButton.IsEnabled = browser.CanGoBack;
478 fwdButton.IsEnabled = browser.CanGoForward;
479
480 }
481#endif
482 string message = "{\"type\":\"loadstop\", \"url\":\"" + e.Uri.OriginalString + "\"}";
483 PluginResult result = new PluginResult(PluginResult.Status.OK, message);
484 result.KeepCallback = true;
485 this.DispatchCommandResult(result, NavigationCallbackId);
486 }
487
488 void browser_NavigationFailed(object sender, System.Windows.Navigation.NavigationFailedEventArgs e)
489 {
490 string message = "{\"type\":\"error\",\"url\":\"" + e.Uri.OriginalString + "\"}";
491 PluginResult result = new PluginResult(PluginResult.Status.ERROR, message);
492 result.KeepCallback = true;
493 this.DispatchCommandResult(result, NavigationCallbackId);
494 }
495
496 void browser_Navigating(object sender, NavigatingEventArgs e)
497 {
498 string message = "{\"type\":\"loadstart\",\"url\":\"" + e.Uri.OriginalString + "\"}";
499 PluginResult result = new PluginResult(PluginResult.Status.OK, message);
500 result.KeepCallback = true;
501 this.DispatchCommandResult(result, NavigationCallbackId);
502 }
503
504 }
505
506 internal static class WebBrowserExtensions
507 {
508 /// <summary>
509 /// Improved method to initiate request to the provided URI. Supports 'data:text/html' urls.
510 /// </summary>
511 /// <param name="browser">The browser instance</param>
512 /// <param name="uri">The requested uri</param>
513 internal static void Navigate2(this WebBrowser browser, Uri uri)
514 {
515 // IE10 does not support data uri so we use NavigateToString method instead
516 if (uri.Scheme == "data")
517 {
518 // we should remove the scheme identifier and unescape the uri
519 string uriString = Uri.UnescapeDataString(uri.AbsoluteUri);
520 // format is 'data:text/html, ...'
521 string html = new System.Text.RegularExpressions.Regex("^data:text/html,").Replace(uriString, "");
522 browser.NavigateToString(html);
523 }
524 else
525 {
526 browser.Navigate(uri);
527 }
528 }
529 }
530}