Commit 5f40b788 authored by Yue Cen's avatar Yue Cen Committed by Commit Bot

Pass server response to generate the app list.

Bug: 835029
Cq-Include-Trybots: luci.chromium.try:closure_compilation
Change-Id: Icbe94f99997fe13758400e26ae29eeeb8bb234b6
Reviewed-on: https://chromium-review.googlesource.com/1103778Reviewed-by: default avatarAlexander Alekseev <alemate@chromium.org>
Reviewed-by: default avatarWenzhao (Colin) Zang <wzang@chromium.org>
Commit-Queue: Yue Cen <rsgingerrs@chromium.org>
Cr-Commit-Position: refs/heads/master@{#575814}
parent 3f30b24d
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/chromeos/login/screens/recommend_apps_screen.h" #include "chrome/browser/chromeos/login/screens/recommend_apps_screen.h"
#include "base/json/json_reader.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager.h"
#include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_partition.h"
...@@ -141,8 +143,79 @@ void RecommendAppsScreen::OnDownloaded( ...@@ -141,8 +143,79 @@ void RecommendAppsScreen::OnDownloaded(
} else { } else {
// If the recommended app list were downloaded successfully, show them to // If the recommended app list were downloaded successfully, show them to
// the user. // the user.
view_->OnLoadSuccess(*response_body);
// The response starts with a prefix ")]}'". This needs to be removed before
// further parsing.
const std::string to_escape = ")]}'";
auto pos = response_body->find(to_escape);
if (pos != std::string::npos)
response_body->erase(pos, to_escape.length());
base::Value output(base::Value::Type::LIST);
if (!ParseResponse(*response_body, &output)) {
OnSkip();
return;
}
view_->OnLoadSuccess(output);
}
}
bool RecommendAppsScreen::ParseResponse(const std::string& response,
base::Value* output) {
int error_code;
std::string error_msg;
std::unique_ptr<base::Value> json_value =
base::JSONReader::ReadAndReturnError(response, base::JSON_PARSE_RFC,
&error_code, &error_msg);
if (!json_value || !json_value->is_list()) {
LOG(ERROR) << "Error parsing response JSON: " << error_msg;
return false;
}
base::Value::ListStorage app_list = std::move(json_value->GetList());
if (app_list.size() == 0) {
DVLOG(1) << "No app in the response.";
return false;
}
for (auto& item : app_list) {
base::Value output_map(base::Value::Type::DICTIONARY);
base::DictionaryValue* item_map;
if (!item.GetAsDictionary(&item_map)) {
DVLOG(1) << "Cannot parse item.";
continue;
}
std::string title;
std::string package_name;
std::string icon_url;
if (item_map->GetString("title_", &title) && !title.empty())
output_map.SetKey("name", base::Value(title));
if (item_map->GetString("packageName_", &package_name) &&
!package_name.empty()) {
output_map.SetKey("package_name", base::Value(package_name));
}
base::DictionaryValue* icon_map;
if (item_map->GetDictionary("icon_", &icon_map)) {
base::DictionaryValue* url_map;
if (icon_map->GetDictionary("url_", &url_map)) {
if (url_map->GetString("privateDoNotAccessOrElseSafeUrlWrappedValue_",
&icon_url) &&
!icon_url.empty()) {
output_map.SetKey("icon", base::Value(icon_url));
}
}
}
output->GetList().push_back(std::move(output_map));
} }
return true;
} }
} // namespace chromeos } // namespace chromeos
...@@ -51,6 +51,10 @@ class RecommendAppsScreen : public BaseScreen, ...@@ -51,6 +51,10 @@ class RecommendAppsScreen : public BaseScreen,
// Callback function called when SimpleURLLoader completes. // Callback function called when SimpleURLLoader completes.
void OnDownloaded(std::unique_ptr<std::string> response_body); void OnDownloaded(std::unique_ptr<std::string> response_body);
// If the response is not a valid JSON, return false.
// If the response contains no app, return false;
bool ParseResponse(const std::string& response, base::Value* output);
RecommendAppsScreenView* view_; RecommendAppsScreenView* view_;
std::unique_ptr<network::SimpleURLLoader> app_list_loader_; std::unique_ptr<network::SimpleURLLoader> app_list_loader_;
......
...@@ -39,7 +39,7 @@ class RecommendAppsScreenView { ...@@ -39,7 +39,7 @@ class RecommendAppsScreenView {
// Called when the download of the recommend app list is successful. Shows the // Called when the download of the recommend app list is successful. Shows the
// downloaded |app_list| to the user. // downloaded |app_list| to the user.
virtual void OnLoadSuccess(const std::string& app_list) = 0; virtual void OnLoadSuccess(const base::Value& app_list) = 0;
}; };
} // namespace chromeos } // namespace chromeos
......
...@@ -23,7 +23,7 @@ function generateContents(appIcon, appTitle, appPackageName) { ...@@ -23,7 +23,7 @@ function generateContents(appIcon, appTitle, appPackageName) {
var img = doc.createElement('img'); var img = doc.createElement('img');
img.classList.add('app-icon'); img.classList.add('app-icon');
img.setAttribute('src', appIcon); img.setAttribute('src', decodeURIComponent(appIcon));
var title = doc.createElement('span'); var title = doc.createElement('span');
title.classList.add('app-title'); title.classList.add('app-title');
......
...@@ -13,11 +13,6 @@ Polymer({ ...@@ -13,11 +13,6 @@ Polymer({
behaviors: [I18nBehavior, OobeDialogHostBehavior], behaviors: [I18nBehavior, OobeDialogHostBehavior],
properties: { properties: {
apps: {
type: Array,
value: [] // TODO(rsgingerrs): add the function to fetch the list of apps
},
/** /**
* Reference to OOBE screen object. * Reference to OOBE screen object.
* @type {!OobeTypes.Screen} * @type {!OobeTypes.Screen}
......
...@@ -3,5 +3,12 @@ ...@@ -3,5 +3,12 @@
found in the LICENSE file. --> found in the LICENSE file. -->
<div class="step right hidden" id="recommend-apps" hidden> <div class="step right hidden" id="recommend-apps" hidden>
<recommend-apps id="recommend-apps-screen"></recommend-apps> <recommend-apps id="recommend-apps-screen" hidden></recommend-apps>
<oobe-dialog id="recommend-apps-loading" role="dialog" no-header
no-footer-padding>
<div slot="footer" class="flex layout vertical center center-justified">
<throbber-notice i18n-values="text:recommendAppsLoading">
</throbber-notice>
</div>
</oobe-dialog>
</div> </div>
...@@ -8,7 +8,8 @@ ...@@ -8,7 +8,8 @@
login.createScreen('RecommendAppsScreen', 'recommend-apps', function() { login.createScreen('RecommendAppsScreen', 'recommend-apps', function() {
return { return {
EXTERNAL_API: ['loadAppList', 'setWebview', 'showError'], EXTERNAL_API:
['loadAppList', 'setThrobberVisible', 'setWebview', 'showError'],
/** /**
* Returns the control which should receive initial focus. * Returns the control which should receive initial focus.
...@@ -66,6 +67,8 @@ login.createScreen('RecommendAppsScreen', 'recommend-apps', function() { ...@@ -66,6 +67,8 @@ login.createScreen('RecommendAppsScreen', 'recommend-apps', function() {
showError: function() { showError: function() {
this.ensureInitialized_(); this.ensureInitialized_();
// Hide the loading throbber and show the error message.
this.setThrobberVisible(false);
this.removeClass_('recommend-apps-loading'); this.removeClass_('recommend-apps-loading');
this.removeClass_('recommend-apps-loaded'); this.removeClass_('recommend-apps-loaded');
this.addClass_('error'); this.addClass_('error');
...@@ -81,24 +84,26 @@ login.createScreen('RecommendAppsScreen', 'recommend-apps', function() { ...@@ -81,24 +84,26 @@ login.createScreen('RecommendAppsScreen', 'recommend-apps', function() {
/** /**
* Generate the contents in the webview. * Generate the contents in the webview.
*/ */
loadAppList: function() { loadAppList: function(appList) {
this.ensureInitialized_(); this.ensureInitialized_();
// Hide the loading throbber and show the recommend app list.
this.setThrobberVisible(false);
var appListView = this.getElement_('app-list-view'); var appListView = this.getElement_('app-list-view');
var subtitle = this.getElement_('subtitle'); var subtitle = this.getElement_('subtitle');
subtitle.innerText = loadTimeData.getStringF( subtitle.innerText = loadTimeData.getStringF(
'recommendAppsScreenDescription', 'recommendAppsScreenDescription', appList.length);
$('recommend-apps-screen').apps.length);
appListView.addEventListener('contentload', () => { appListView.addEventListener('contentload', () => {
appListView.executeScript({file: 'recommend_app_list_view.js'}, () => { appListView.executeScript({file: 'recommend_app_list_view.js'}, () => {
$('recommend-apps-screen').apps.forEach(function(app, index) { appList.forEach(function(app, index) {
var generateItemScript = 'generateContents("' + app.icon + '", "' + var generateItemScript = 'generateContents("' + app.icon + '", "' +
app.name + '", "' + app.package_name + '");'; app.name + '", "' + app.package_name + '");';
var generateContents = {code: generateItemScript}; var generateContents = {code: generateItemScript};
appListView.executeScript(generateContents); appListView.executeScript(generateContents);
}); });
this.onGenerateContents.call(this); this.onGenerateContents();
}); });
}); });
}, },
...@@ -135,11 +140,21 @@ login.createScreen('RecommendAppsScreen', 'recommend-apps', function() { ...@@ -135,11 +140,21 @@ login.createScreen('RecommendAppsScreen', 'recommend-apps', function() {
* Handles Retry button click. * Handles Retry button click.
*/ */
onRetry: function() { onRetry: function() {
this.setThrobberVisible(true);
this.removeClass_('recommend-apps-loaded'); this.removeClass_('recommend-apps-loaded');
this.removeClass_('error'); this.removeClass_('error');
this.addClass_('recommend-apps-loading'); this.addClass_('recommend-apps-loading');
chrome.send('recommendAppsRetry'); chrome.send('recommendAppsRetry');
}, },
/**
* This is called to show/hide the loading UI.
* @param {boolean} visible whether to show loading UI.
*/
setThrobberVisible: function(visible) {
$('recommend-apps-loading').hidden = !visible;
$('recommend-apps-screen').hidden = visible;
},
}; };
}); });
\ No newline at end of file
...@@ -84,25 +84,25 @@ void RecommendAppsScreenHandler::Hide() {} ...@@ -84,25 +84,25 @@ void RecommendAppsScreenHandler::Hide() {}
void RecommendAppsScreenHandler::Initialize() {} void RecommendAppsScreenHandler::Initialize() {}
void RecommendAppsScreenHandler::LoadAppListInUI() { void RecommendAppsScreenHandler::LoadAppListInUI(const base::Value& app_list) {
if (!page_is_ready()) if (!page_is_ready()) {
CallJS("showError");
return; return;
}
const ui::ResourceBundle& resource_bundle = const ui::ResourceBundle& resource_bundle =
ui::ResourceBundle::GetSharedInstance(); ui::ResourceBundle::GetSharedInstance();
base::StringPiece app_list_webview = resource_bundle.GetRawDataResource( base::StringPiece app_list_webview = resource_bundle.GetRawDataResource(
IDR_ARC_SUPPORT_RECOMMEND_APP_LIST_VIEW_HTML); IDR_ARC_SUPPORT_RECOMMEND_APP_LIST_VIEW_HTML);
CallJS("setWebview", app_list_webview.as_string()); CallJS("setWebview", app_list_webview.as_string());
CallJS("loadAppList"); CallJS("loadAppList", app_list);
} }
void RecommendAppsScreenHandler::OnLoadError() { void RecommendAppsScreenHandler::OnLoadError() {
CallJS("showError"); CallJS("showError");
} }
void RecommendAppsScreenHandler::OnLoadSuccess(const std::string& app_list) { void RecommendAppsScreenHandler::OnLoadSuccess(const base::Value& app_list) {
// TODO(rsgingerrs): Parse the app_list and pass it to the UI. LoadAppListInUI(app_list);
LoadAppListInUI();
} }
void RecommendAppsScreenHandler::HandleSkip() { void RecommendAppsScreenHandler::HandleSkip() {
......
...@@ -40,10 +40,10 @@ class RecommendAppsScreenHandler : public BaseScreenHandler, ...@@ -40,10 +40,10 @@ class RecommendAppsScreenHandler : public BaseScreenHandler,
// RecommendAppsScreenView: // RecommendAppsScreenView:
void OnLoadError() override; void OnLoadError() override;
void OnLoadSuccess(const std::string& terms_of_service) override; void OnLoadSuccess(const base::Value& app_list) override;
// Call the JS function to load the list of apps in the WebView. // Call the JS function to load the list of apps in the WebView.
void LoadAppListInUI(); void LoadAppListInUI(const base::Value& app_list);
void HandleSkip(); void HandleSkip();
void HandleRetry(); void HandleRetry();
......
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