Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Portable Browser Issues when deploying R Shiny App

I've built a complex Shiny interface that pulls from an internally networked ODBC table and allows a user to interact with the data through their browser. The company is on Windows 7 Enterprise and IT only supports IE 9. Some users have chrome installed in their user folders, some have firefox, some use IE 9. I followed a tutorial from R-Bloggers (here: http://www.r-bloggers.com/deploying-desktop-apps-with-r/) and it runs on my machine using a portable Chrome browser downloaded from PortableApps.com. Great. Unfortunately the interface has not started on ANYONE else's machine that has their own local Chrome browser installed.

Following the tutorial, I use the following vb script:

Rexe           = "R-Portable\App\R-Portable\bin\Rscript.exe"
Ropts          = "--no-save --no-environ --no-init-file --no-restore --no-Rconsole"
RScriptFile    = "runShinyApp.R"
Outfile        = "ShinyApp.log" 
strCommand     = Rexe & " " & Ropts & " " & RScriptFile & " 1> " & Outfile & " 2>&1"

intWindowStyle = 0     ' Hide the window and activate another window.'
bWaitOnReturn  = False ' continue running script after launching R   '

CreateObject("Wscript.Shell").Run strCommand, intWindowStyle, bWaitOnReturn

This script calls the following code in my R file:

message('library paths:\n', paste('... ', .libPaths(), sep='', collapse='\n'))
chrome.portable = file.path(getwd(),'GoogleChromePortable/App/Chrome-bin/chrome.exe')
launch.browser = function(appUrl, browser.path=chrome.portable) {
    message('Browser path: ', browser.path)
    shell(sprintf('"%s" --app=%s', browser.path, appUrl))
}
shiny::runApp('shiny', launch.browser=launch.browser)

It works on my computer just fine... I DO have chrome installed locally, but I'm calling the Portable Chrome executable. It worries me that the two are sharing prefs or something, e.g. I notice that a hash from the Preferences file in my installed version, specifically:

  "chrome_url_overrides": {
     "bookmarks": [ "chrome-extension://eemcgdkfndhakfknompkggombfjjjeno/main.html" ]
  },

...matches the same json entry from the Portable Chrome installation:

  "chrome_url_overrides": {
     "bookmarks": [ "chrome-extension://eemcgdkfndhakfknompkggombfjjjeno/main.html" ]
  }

Why do these long random strings match? Am I barking up the wrong tree for wondering about this? I don't know why these strings match if they are two separate installations of Chrome executables, one of which is supposed to run completely independently from anything on the machine.

Here's a set of errors from one machine:

.../Desktop/TestApp3/GoogleChromePortable/App/Chrome-bin/chrome.exe[9100:9408:0716/141934:ERROR:gpu_info_collector_win.cc(103)] Can't retrieve a valid WinSAT assessment.
[9100:9408:0716/141934:ERROR:component_loader.cc(138)] Failed to parse extension manifest.
[9100:1716:0716/141946:ERROR:get_updates_processor.cc(214)] PostClientToServerMessage() failed during GetUpdates

Here's a set of errors from a second machine:

.../Documents/TestApp3/GoogleChromePortable/App/Chrome-bin/chrome.exe
[5220:3384:0714/142128:ERROR:component_loader.cc(138)] Failed to parse extension     manifest.
[5220:7600:0714/142130:ERROR:external_registry_loader_win.cc(136)] File C:\Program     Files\Coupons.com CouponBar\chrome\Coupons.com.crx for key     
Software\Google\Chrome\Extensions\cnpkmcjgpcihgfnkcjapiaabbbplkcmf does not exist or is not readable.
[5220:2120:0714/142140:ERROR:get_updates_processor.cc(214)] PostClientToServerMessage() failed during GetUpdates
[5220:3384:0714/142413:ERROR:CONSOLE(122)] "Could not find value for secondaryUser", source: chrome://resources/js/load_time_data.js (122)
[5220:3384:0714/142413:ERROR:CONSOLE(122)] "[undefined] (secondaryUser) is not a boolean", source: chrome://resources/js/load_time_data.js (122)
[5220:3384:0714/142425:ERROR:CONSOLE(122)] "Could not find value for secondaryUser", source: chrome://resources/js/load_time_data.js (122)
[5220:3384:0714/142425:ERROR:CONSOLE(122)] "[undefined] (secondaryUser) is not a boolean", source: chrome://resources/js/load_time_data.js (122)
[5220:3384:0714/142442:ERROR:navigation_entry_screenshot_manager.cc(167)] Invalid entry with unique id: 12

It seems like Chrome is doing different things on different computers and is not actually acting as a standalone browser... but likely interacting with the browser installed on their respective computers via the registry or some other "under the hood, active" communication. Maybe, since I installed the portable executable on my machine, a bunch of my local extensions or preferences were automatically updated to the portable's preferences, etc. and subsequently this is causing a conflict on every other machine??

Can I shutdown Chrome's extensions or extra functions like the calls to the updater? Is there a better standalone portable browser that functions well with Shiny for this type of "deployment" purpose? Can I fix this or is this a lost cause?? This should be obvious but I'll say it anyway: it is definitely not economically efficient to ask the non-technical types to install R, then RStudio, then confirm their working directory structure, then call the runApp() command via the Script window...

like image 374
quickreaction Avatar asked Jul 16 '14 20:07

quickreaction


1 Answers

I started with those same articles, but developed the RInno package to solve this exact problem, i.e. when you want to share your desktop Shiny app with non-technical users who can't be expected to mess around with all those details.

To get started:

install.packages("RInno")
require(RInno)
RInno::install_inno()

Then you just need to call two functions to create an installation framework:

create_app(app_name = "myapp", app_dir = "path/to/myapp")
compile_iss()

This will create an installation wizard that runs like any other program, but installs your shiny app on a Windows desktop computer. If you would like to include R for your co-workers who don't have it installed, add include_R = TRUE to create_app:

create_app(app_name = "myapp", app_dir = "path/to/myapp", include_R = TRUE)

It defaults to include shiny, magrittr and jsonlite, so if you are using other packages like ggplot2 or plotly, just add them to the pkgs argument. You can also include GitHub packages to the remotes argument:

create_app(
    app_name = "myapp", 
    app_dir  = "path/to/myapp"
    pkgs     = c("shiny", "jsonlite", "magrittr", "plotly", "ggplot2"),
    remotes  = c("talgalili/installr", "daattali/shinyjs"))

If you are interested in other features, check out FI Labs - RInno

like image 53
Jonathan Hill Avatar answered Oct 13 '22 07:10

Jonathan Hill