Kiosk mode hosted app must be reconfigured every reboot.

1,766 views
Skip to first unread message

Kris Williams

unread,
Feb 8, 2017, 12:20:58 PM2/8/17
to Chromium-dev
Hey Everyone!  New here, let me know if there is a better place I should be posting this.

There is a nifty digital signage tool called Concerto 2 that I am hosting at my company.  On any normal browser (not in kiosk mode), the behavior is as follows:
  1. Open a client browser and connect to a generic URL  http://concerto.<domain>/frontend
  2. The browser then prompts the user with a unique 6 digit code
  3. On the server/admin side, we input the code to authorize it to connect to our service.
  4. The browser then immediately begins displaying our hosted content.
  5. From that point on, any time the browser visits the URL it automatically displays the content.  This persists past reboots, etc..

I have to deploy about 300 of these, so to make it easier on the stores they will go in I am trying to use enterprise kiosk mode on ASUS chromebits to host this.  I created a quick little hosted app to accomplish this:


{
 
"name": "<myapp>",
 
"description": "My Concerto App",
 
"version":"0.1",
 
"manifest_version":2,
 
"app": {
   
"urls": [
     
"*://<url>/frontend/"
   
],
   
"launch": {
     
"web_url": "<url>/frontend/"
   
}
 
},
 
"icons": {
   
"128": "128.png"
 
},
 
"permissions": [
   
"unlimitedStorage",
   
"notifications"
 
]
}

The behavior is great.  Plugging in the device pulls up the desired URL in full screen with no required input from the user, exactly what I was hoping for.


The problem is that whenever the chromebit loses power, the screen that comes up gives a new unique ID rather than keeping it's previous configuration.


Since this doesn't happen when not in Kiosk mode, I'm assuming that kiosk mode does something on each restart that normal chrome does not, like flush all cookies or generate a new ID for itself.


Power loss is infrequent, but when multiplied by 300 it will generate a fair amount of work to re-associate the new codes each time.


My question is this:

Is there anything I can add to my app code to change this behavior to allow the identity of the kiosk app to be persistent across reboots?  Enterprise management?  Backend chromeOS settings?

And can anyone explain why this is happening only in kiosk mode?


Thanks for your help.

Michael Giuffrida

unread,
Feb 8, 2017, 5:01:45 PM2/8/17
to kr...@bcfranchise.com, Chromium-dev
Can you clarify how the 6-digit code is generated, and if it's persisted to disk on desktop browsers, how that happens?

Is it possible the Chrome OS machines have a device policy configured to "erase all local user data" on sign-out (reboot)?

I believe app settings saved via chrome.storage should persist across reboot. If the problem lies with the app or the policy configuration, you'll need to resolve that externally (this isn't a support channel). If what you're doing "should" work, then please feel free to open a bug at https://crbug.com.

--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev

Drew Wilson

unread,
Feb 9, 2017, 5:09:44 AM2/9/17
to Michael Giuffrida, Raj Duraisamy, kr...@bcfranchise.com, Chromium-dev
Kiosk sessions on Chrome OS *do* preserve state. So this should work if the app is using chrome.storage or cookies to maintain its state.

Also, if you're using an enterprise kiosk session (i.e. you have paid for a Chrome Device Management license) then probably the best way forward is to file a support ticket, since the support folks can help make sure any bugs are routed to the right people internally. But step 1 is probably to understand how the app preserves the 6-digit code.

Kris Williams

unread,
Feb 9, 2017, 12:49:35 PM2/9/17
to Chromium-dev, mich...@chromium.org, sdura...@google.com, kr...@bcfranchise.com
Thank you!  I wish I understood how the 6 digit codes were created, I'm having a hard time figuring it out since I don't have any experience with Ruby.  The code doesn't make sense to me (I'm used to languages like Java and PHP) https://github.com/concerto/concerto

The suggestion of creating a support ticket on this is a good one, I need to reach out to my Rep and find out what my official support channel is.

Toni Barzic

unread,
Feb 9, 2017, 12:54:36 PM2/9/17
to kr...@bcfranchise.com, Chromium-dev, mich...@chromium.org, Raj Duraisamy
It would be useful to know how exactly your kiosk app is set up (afaik, hosted apps cannot run as kiosk).
Is the page hosted by the kiosk app put in a webview? If that is the case, can you make sure that the webview element has partition attribute set to a partition name prefixed with "persist:"? Something like: <webview partition="persist:partition_name_of_your_choice">?
(Otherwise, the webview storage data will be in_memory - i.e. not persisted across reboots).

Toni


On Thu, Feb 9, 2017 at 9:49 AM, Kris Williams <kr...@bcfranchise.com> wrote:
Thank you!  I wish I understood how the 6 digit codes were created, I'm having a hard time figuring it out since I don't have any experience with Ruby.  The code doesn't make sense to me (I'm used to languages like Java and PHP) https://github.com/concerto/concerto

The suggestion of creating a support ticket on this is a good one, I need to reach out to my Rep and find out what my official support channel is.

Kris Williams

unread,
Feb 9, 2017, 1:15:29 PM2/9/17
to Chromium-dev
Sorry guys, I put the wrong code in my first post.  That code was an experiment which I abandoned early on.  Sorry to mislead.  Here is the actual manifest:

{
"name":"BaseCampDSS",
"version":"0.4",
"manifest_version":2,
"minimum_chrome_version":"37.0.0.0",
"permissions":
   
[
   
"webview",
   
"fullscreen",
   
"power",
   
"storage",
   
"<all_urls>",
   
"videoCapture",
   
"geolocation",
   
"pointerLock",
   
"system.display",
   
{"fileSystem":
       
[
       
"write",
       
"retainEntries",
       
"directory"
       
]
   
},
   
"accessibilityFeatures.read",
   
"accessibilityFeatures.modify"
   
],
"app":
{"background":
   
{"scripts":
       
[
       
"js/foam.js",
       
"js/cab.js",
       
"config.js",
       
"background_main.js"
       
]
   
}
},
"kiosk_enabled":true,
"default_locale":"en",
"icons":{"128":"img/128.png"}}

background_main.js
/**
 * Creates the window for the application.
 *
 * @see http://developer.chrome.com/trunk/apps/app.window.html
 */

var runApp = function() {
 
if (chrome.power) {
    chrome
.power.requestKeepAwake('display');
 
}
  console
.log(config);
  chrome
.app.window.create(
      config
?
     
'exported_app_view.html' :
     
'designer_view.html',
     
{
        state
: "fullscreen"
     
},
     
function(win) {
       
if (!this.X) { return; }
       
var window = win.contentWindow;
        window
.onload = function() {
         
this.$addWindow(window);
         
var Y = this.X.subWindow(window, 'Kiosk Designer Window');
         
this.DOM.init(Y);
       
}.bind(this);
        win
.onClosed.addListener(function() {
         
this.$removeWindow(window);
       
}.bind(this));
     
}.bind(this));
}.bind(this);

/**
 * Listens for the app launching then creates the window
 *
 * @see http://developer.chrome.com/trunk/apps/app.runtime.html
 * @see http://developer.chrome.com/trunk/apps/app.window.html
 */

chrome
.app.runtime.onLaunched.addListener(function() {
  runApp
();
});


/**
 * Listens for the app restarting then re-creates the window.
 *
 * @see http://developer.chrome.com/trunk/apps/app.runtime.html
 */

chrome
.app.runtime.onRestarted.addListener(function() {
  runApp
();
});


config.js
window.config = {
   "model_": "AppConfig",
   "id": 1,
   "appName": "BaseCampDSS",
   "homepage": "http://<my domain>/frontend",
   "enableNavBttns": false,
   "enableHomeBttn": false,
   "enableReloadBttn": false,
   "enableLogoutBttn": false,
   "kioskEnabled": true
};

When I run the app locally on my chrome browser in kiosk mode it persists through reboots, just not in as a single app kiosk on my chromebits.  I'm reaching out to support, so at this point unless someone knows what is going on I'll wait to hear back from them.  If I figure it out I'll let everyone know!

Kris Williams

unread,
Feb 9, 2017, 3:51:25 PM2/9/17
to Chromium-dev
Found some code in the third party app that seems related, here is the html template it uses to display the code:
        <p class="center" style="font-size: 4em; font-family: Courier New, monospace; line-height: 1em;">
         
<%# The following span is used to identify this page to the javscript. %>
         
<span id="screen_temp_token"><strong><%= @temp_token %></strong></span>
       
</p>

Here is some code where it seems to be generating the token, seems to be server-side.  It mentions signed cookies, I'm guessing that is how it is storing the code (I'd assumed this before, but this seems to confirm):

Rails.logger.debug "Starting #{File.basename(__FILE__)} at #{Time.now.to_s}"

secret_token
= ENV['SECRET_TOKEN']

if secret_token.blank?
 
if ActiveRecord::Base.connection.table_exists?('concerto_configs')
   
# Try go get secret key from concerto config or auto-generate it
    secret_token
= ConcertoConfig[:secret_token]
 
end
end

if secret_token.blank?
 
require 'securerandom'
  secret_token
= SecureRandom.hex(64)
 
Rails.logger.debug 'Auto-generated secret token'

 
if ActiveRecord::Base.connection.table_exists?('concerto_configs')
   
ConcertoConfig.set('secret_token', secret_token)
 
end
end

# Secret key for verifying the integrity of signed cookies.
Concerto::Application.config.secret_token = secret_token
Concerto::Application.config.secret_key_base = secret_token
ENV
["SECRET_KEY_BASE"] = secret_token

Rails.logger.debug "Completed #{File.basename(__FILE__)} at #{Time.now.to_s}"


Albert Bodenhamer

unread,
Feb 9, 2017, 4:03:26 PM2/9/17
to kr...@bcfranchise.com, Chromium-dev
Hard to say.  Depends on what "Concerto::Application" ultimately ends up doing with that token.  My guess would be they just write it to a cookie, but it's impossible to say from this.

IIRC there's no explicit flush after setting a persistent cookie.  If there's a hard power cut shortly after setting the cookie it can be lost.  On a Chromebit things SHOULD automatically flush after 10 minutes.

One option might be to configure the device and then do a clean shutdown which will force everything to disk.  Once that's done it should be a lot more resilient to power cuts (assuming my guess is correct and it is a persistent cookie)

--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
---
You received this message because you are subscribed to the Google Groups "Chromium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.

Kris Williams

unread,
Feb 9, 2017, 4:25:09 PM2/9/17
to Chromium-dev, kr...@bcfranchise.com
Good suggestion Albert, I did a clean restart but still no joy.

There is a chrome app permission for 'cookies' but when I try to use it the app throws an error and says that permission does not apply to my type of app.

Alon Raskin

unread,
Apr 16, 2018, 10:57:14 AM4/16/18
to Chromium-dev, kr...@bcfranchise.com
Hi,

Did you ever get this working? I too am have the exact same issue with a managed chromeBit running our web app in Kiosk mode. The app works great but looks like localStorage is not persisting through reboots. I even tried implementing a shim which actually uses chrome.storage but have not had any luck so far.

urbanup...@gmail.com

unread,
May 4, 2018, 11:35:02 AM5/4/18
to Chromium-dev, kr...@bcfranchise.com, aras...@gmail.com
Hey Alon, 
we are having the exact same issue and had it running properly for more than half a year. Then, basically out of nowhere, it seems like the cookies/tokens are being deleted after reboot of the chromebit and we have to manually "allow" the devices to access the respective URL. 

We are still digging through the settings in Google Admin Console but no luck so far. Have you had any luck? 

Best from Germany 

Alex

Toni Barzic

unread,
May 4, 2018, 12:38:34 PM5/4/18
to urbanup...@gmail.com, Chromium-dev, Kris Williams, aras...@gmail.com
I assume that you load your web app inside a webview hosted by the kiosk app.
Can you check that the webview uses a persistent storage partition - in other words that the webview element has partition attribute with value that starts with "persist:"?
If this is not the case, the web app will use in-memory storage, and localStorage and cookies would get deleted on reboot (and session restart in general).

Toni

--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
---
You received this message because you are subscribed to the Google Groups "Chromium-dev" group.

Pascal Lindelauf

unread,
Aug 20, 2018, 2:28:38 PM8/20/18
to Chromium-dev, urbanup...@gmail.com, kr...@bcfranchise.com, aras...@gmail.com
We're experiencing the exact same problem: some Chromebits running our webview-based kiosk app. Every now and then these Chromebits simply loose their cookie values. 

We are using the partition="persist:..." option in the webview definition and in almost all cases it works just fine. Only some of our customers are sometimes experiencing these problems and it looks like it's a repeating problem on the same devices. So maybe it has something to do with a specific setting on these "problematic devices"?

Has anyone found a possible cause and/or solution for this?

Pascal.

Op vrijdag 4 mei 2018 18:38:34 UTC+2 schreef Toni Barzic:

Drew Wilson

unread,
Aug 21, 2018, 5:42:06 AM8/21/18
to pas...@lindelauf.com, Chromium-dev, urbanup...@gmail.com, Kris Williams, aras...@gmail.com
Best to log a bug at crbug.com and attach logs from a device where this has happened so we can help diagnose, as it sounds like perhaps the device is losing its local state - please cc me and por...@chromium.org on the bug.

Reply all
Reply to author
Forward
0 new messages