Commit 7bb2e7bc authored by khmel's avatar khmel Committed by Commit bot

arc: Handle ARC events in MD Settings

This provides handling ARC events.
TURN ON button should be available in case ARC is disabled and unmanaged.
Once ARC is enabled TURN ON button is hidden and APPS section is shown.
APPS section shows link to ARC Settings app once Settings app appears in
the system. While Settings app is not registered tehn link to ARC Settings
is hidden. In case user click on ARC Settings link and Settings app is not
ready yet (ARC is still booting) then Settings app is started in deferred
mode (spinning animation on shelf). Disabling ARC hides APPS section and
TURN ON button is active again.

BUG=720173, b/37523579, b/29244888
TEST=Browser test extended, manually on device for managed/unmanaged
     cases.
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:closure_compilation

Review-Url: https://codereview.chromium.org/2873853002
Cr-Commit-Position: refs/heads/master@{#471206}
parent a3079e2f
......@@ -8,7 +8,13 @@
*/
/**
* @typedef {{appReady: boolean}}
* Type definition of AndroidAppsInfo entry. |playStoreEnabled| indicates that
* Play Store is enabled. |settingsAppAvailable| indicates that Android settings
* app is registered in the system.
* @typedef {{
* playStoreEnabled: boolean,
* settingsAppAvailable: boolean,
* }}
* @see chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc
*/
var AndroidAppsInfo;
......
......@@ -30,13 +30,13 @@
<cr-policy-pref-indicator pref="[[prefs.arc.enabled]]"
icon-aria-label="$i18n{androidAppsPageTitle}">
</cr-policy-pref-indicator>
<template is="dom-if" if="[[androidAppsInfo_.appReady]]">
<template is="dom-if" if="[[androidAppsInfo_.playStoreEnabled]]">
<button class="subpage-arrow" is="paper-icon-button-light"
aria-label="$i18n{androidAppsPageTitle}"
aria-describedby="secondaryText">
</button>
</template>
<template is="dom-if" if="[[!androidAppsInfo_.appReady]]">
<template is="dom-if" if="[[!androidAppsInfo_.playStoreEnabled]]">
<div class="separator"></div>
<paper-button id="enable" class="secondary-button"
on-tap="onEnableTap_"
......
......@@ -38,17 +38,26 @@ Polymer({
/** @private {?settings.AndroidAppsBrowserProxy} */
browserProxy_: null,
/** @private {?WebUIListener} */
listener_: null,
/** @override */
created: function() {
this.browserProxy_ = settings.AndroidAppsBrowserProxyImpl.getInstance();
},
/** @override */
ready: function() {
cr.addWebUIListener(
attached: function() {
this.listener_ = cr.addWebUIListener(
'android-apps-info-update', this.androidAppsInfoUpdate_.bind(this));
this.browserProxy_.requestAndroidAppsInfo();
},
/** @override */
detached: function() {
cr.removeWebUIListener(this.listener_);
},
/**
* @param {AndroidAppsInfo} info
* @private
......@@ -68,7 +77,7 @@ Polymer({
/** @private */
onSubpageTap_: function() {
if (this.androidAppsInfo_.appReady)
if (this.androidAppsInfo_.playStoreEnabled)
settings.navigateTo(settings.Route.ANDROID_APPS_DETAILS);
},
});
......@@ -15,7 +15,7 @@
<div id="manageApps" class="settings-box first"
on-keydown="onManageAndroidAppsKeydown_"
on-tap="onManageAndroidAppsTap_" actionable
hidden="[[!androidAppsInfo_.appReady]]">
hidden="[[!androidAppsInfo.settingsAppAvailable]]">
<div class="start">
<div>$i18n{androidAppsManageApps}</div>
</div>
......
......@@ -17,7 +17,10 @@ Polymer({
prefs: Object,
/** @private {!AndroidAppsInfo|undefined} */
androidAppsInfo: Object,
androidAppsInfo: {
type: Object,
observer: 'onAndroidAppsInfoUpdate_',
},
/** @private */
dialogBody_: {
......@@ -38,6 +41,14 @@ Polymer({
this.browserProxy_ = settings.AndroidAppsBrowserProxyImpl.getInstance();
},
/**
* @private
*/
onAndroidAppsInfoUpdate_: function() {
if (!this.androidAppsInfo.playStoreEnabled)
settings.navigateToPreviousRoute();
},
/**
* @param {Event} event
* @private
......
......@@ -14,7 +14,10 @@ namespace chromeos {
namespace settings {
AndroidAppsHandler::AndroidAppsHandler(Profile* profile)
: arc_prefs_observer_(this), profile_(profile), weak_ptr_factory_(this) {}
: arc_prefs_observer_(this),
arc_session_manager_observer_(this),
profile_(profile),
weak_ptr_factory_(this) {}
AndroidAppsHandler::~AndroidAppsHandler() {}
......@@ -31,12 +34,16 @@ void AndroidAppsHandler::RegisterMessages() {
void AndroidAppsHandler::OnJavascriptAllowed() {
ArcAppListPrefs* arc_prefs = ArcAppListPrefs::Get(profile_);
if (arc_prefs)
if (arc_prefs) {
arc_prefs_observer_.Add(arc_prefs);
// arc::ArcSessionManager is assosiated with primary profile.
arc_session_manager_observer_.Add(arc::ArcSessionManager::Get());
}
}
void AndroidAppsHandler::OnJavascriptDisallowed() {
arc_prefs_observer_.RemoveAll();
arc_session_manager_observer_.RemoveAll();
}
void AndroidAppsHandler::OnAppRegistered(
......@@ -49,27 +56,24 @@ void AndroidAppsHandler::OnAppRemoved(const std::string& app_id) {
OnAppChanged(app_id);
}
void AndroidAppsHandler::OnAppReadyChanged(const std::string& app_id,
bool ready) {
OnAppChanged(app_id);
}
void AndroidAppsHandler::OnAppChanged(const std::string& app_id) {
if (app_id != arc::kSettingsAppId)
return;
SendAndroidAppsInfo();
}
void AndroidAppsHandler::OnArcPlayStoreEnabledChanged(bool enabled) {
SendAndroidAppsInfo();
}
std::unique_ptr<base::DictionaryValue>
AndroidAppsHandler::BuildAndroidAppsInfo() {
std::unique_ptr<base::DictionaryValue> info(new base::DictionaryValue);
bool app_ready = false;
if (arc::IsArcPlayStoreEnabledForProfile(profile_)) {
std::unique_ptr<ArcAppListPrefs::AppInfo> app_info =
ArcAppListPrefs::Get(profile_)->GetApp(arc::kSettingsAppId);
app_ready = app_info && app_info->ready;
}
info->SetBoolean("appReady", app_ready);
info->SetBoolean("playStoreEnabled",
arc::IsArcPlayStoreEnabledForProfile(profile_));
info->SetBoolean(
"settingsAppAvailable",
ArcAppListPrefs::Get(profile_)->IsRegistered(arc::kSettingsAppId));
return info;
}
......
......@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h"
#include "chrome/browser/chromeos/arc/arc_session_manager.h"
#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
......@@ -23,7 +24,8 @@ namespace chromeos {
namespace settings {
class AndroidAppsHandler : public ::settings::SettingsPageUIHandler,
public ArcAppListPrefs::Observer {
public ArcAppListPrefs::Observer,
public arc::ArcSessionManager::Observer {
public:
explicit AndroidAppsHandler(Profile* profile);
~AndroidAppsHandler() override;
......@@ -34,11 +36,13 @@ class AndroidAppsHandler : public ::settings::SettingsPageUIHandler,
void OnJavascriptDisallowed() override;
// ArcAppListPrefs::Observer
void OnAppReadyChanged(const std::string& app_id, bool ready) override;
void OnAppRemoved(const std::string& app_id) override;
void OnAppRegistered(const std::string& app_id,
const ArcAppListPrefs::AppInfo& app_info) override;
// arc::ArcSessionManager::Observer:
void OnArcPlayStoreEnabledChanged(bool enabled) override;
private:
std::unique_ptr<base::DictionaryValue> BuildAndroidAppsInfo();
void OnAppChanged(const std::string& app_id);
......@@ -48,6 +52,8 @@ class AndroidAppsHandler : public ::settings::SettingsPageUIHandler,
ScopedObserver<ArcAppListPrefs, ArcAppListPrefs::Observer>
arc_prefs_observer_;
ScopedObserver<arc::ArcSessionManager, arc::ArcSessionManager::Observer>
arc_session_manager_observer_;
Profile* profile_; // unowned
base::WeakPtrFactory<AndroidAppsHandler> weak_ptr_factory_;
......
......@@ -20,7 +20,7 @@ TestAndroidAppsBrowserProxy.prototype = {
/** @override */
requestAndroidAppsInfo: function() {
this.methodCalled('requestAndroidAppsInfo');
cr.webUIListenerCallback('android-apps-info-update', {appReady: false});
this.setAndroidAppsState(false, false);
},
/** override */
......@@ -28,10 +28,14 @@ TestAndroidAppsBrowserProxy.prototype = {
this.methodCalled('showAndroidAppsSettings');
},
setAppReady: function(ready) {
setAndroidAppsState: function(playStoreEnabled, settingsAppAvailable) {
// We need to make sure to pass a new object here, otherwise the property
// change event may not get fired in the listener.
cr.webUIListenerCallback('android-apps-info-update', {appReady: ready});
var appsInfo = {
playStoreEnabled: playStoreEnabled,
settingsAppAvailable: settingsAppAvailable,
};
cr.webUIListenerCallback('android-apps-info-update', appsInfo);
},
};
......@@ -62,7 +66,7 @@ suite('AndroidAppsPageTests', function() {
return androidAppsBrowserProxy.whenCalled('requestAndroidAppsInfo')
.then(function() {
androidAppsBrowserProxy.setAppReady(false);
androidAppsBrowserProxy.setAndroidAppsState(false, false);
});
});
......@@ -75,7 +79,7 @@ suite('AndroidAppsPageTests', function() {
Polymer.dom.flush();
assertTrue(androidAppsPage.prefs.arc.enabled.value);
androidAppsBrowserProxy.setAppReady(true);
androidAppsBrowserProxy.setAndroidAppsState(true, false);
Polymer.dom.flush();
assertTrue(!!androidAppsPage.$$('.subpage-arrow'));
});
......@@ -84,11 +88,25 @@ suite('AndroidAppsPageTests', function() {
suite('SubPage', function() {
var subpage;
/**
* Returns a new promise that resolves after a window 'popstate' event.
* @return {!Promise}
*/
function whenPopState() {
return new Promise(function(resolve) {
window.addEventListener('popstate', function callback() {
window.removeEventListener('popstate', callback);
resolve();
});
});
}
setup(function() {
androidAppsPage.prefs = {arc: {enabled: {value: true}}};
return androidAppsBrowserProxy.whenCalled('requestAndroidAppsInfo')
.then(function() {
androidAppsBrowserProxy.setAppReady(true);
settings.navigateTo(settings.Route.ANDROID_APPS);
androidAppsBrowserProxy.setAndroidAppsState(true, false);
MockInteractions.tap(androidAppsPage.$$('#android-apps'));
Polymer.dom.flush();
subpage = androidAppsPage.$$('settings-android-apps-subpage');
......@@ -97,8 +115,19 @@ suite('AndroidAppsPageTests', function() {
});
test('Sanity', function() {
assertTrue(!!subpage.$$('#manageApps'));
assertTrue(!!subpage.$$('#remove'));
assertTrue(!!subpage.$$('#manageApps'));
});
test('ManageAppsUpdate', function() {
var manageApps = subpage.$$('#manageApps');
assertTrue(manageApps.hidden);
androidAppsBrowserProxy.setAndroidAppsState(true, true);
Polymer.dom.flush();
assertFalse(manageApps.hidden);
androidAppsBrowserProxy.setAndroidAppsState(true, false);
Polymer.dom.flush();
assertTrue(manageApps.hidden);
});
test('Disable', function() {
......@@ -108,10 +137,22 @@ suite('AndroidAppsPageTests', function() {
var remove = subpage.$$('#remove');
assertTrue(!!remove);
MockInteractions.tap(remove);
subpage.onRemoveTap_();
Polymer.dom.flush();
assertTrue(dialog.open);
dialog.close();
});
test('HideOnDisable', function() {
assertEquals(settings.getCurrentRoute(),
settings.Route.ANDROID_APPS_DETAILS);
androidAppsBrowserProxy.setAndroidAppsState(false, false);
Polymer.dom.flush();
return whenPopState().then(function() {
assertEquals(settings.getCurrentRoute(),
settings.Route.ANDROID_APPS);
});
});
});
......@@ -129,7 +170,7 @@ suite('AndroidAppsPageTests', function() {
};
return androidAppsBrowserProxy.whenCalled('requestAndroidAppsInfo')
.then(function() {
androidAppsBrowserProxy.setAppReady(true);
androidAppsBrowserProxy.setAndroidAppsState(true, true);
MockInteractions.tap(androidAppsPage.$$('#android-apps'));
Polymer.dom.flush();
subpage = androidAppsPage.$$('settings-android-apps-subpage');
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment