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 @@
// found in the LICENSE file.
#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_manager.h"
#include "content/public/browser/storage_partition.h"
......@@ -141,8 +143,79 @@ void RecommendAppsScreen::OnDownloaded(
} else {
// If the recommended app list were downloaded successfully, show them to
// 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
......@@ -51,6 +51,10 @@ class RecommendAppsScreen : public BaseScreen,
// Callback function called when SimpleURLLoader completes.
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_;
std::unique_ptr<network::SimpleURLLoader> app_list_loader_;
......
......@@ -39,7 +39,7 @@ class RecommendAppsScreenView {
// Called when the download of the recommend app list is successful. Shows the
// 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
......
......@@ -23,7 +23,7 @@ function generateContents(appIcon, appTitle, appPackageName) {
var img = doc.createElement('img');
img.classList.add('app-icon');
img.setAttribute('src', appIcon);
img.setAttribute('src', decodeURIComponent(appIcon));
var title = doc.createElement('span');
title.classList.add('app-title');
......
......@@ -13,11 +13,6 @@ Polymer({
behaviors: [I18nBehavior, OobeDialogHostBehavior],
properties: {
apps: {
type: Array,
value: [] // TODO(rsgingerrs): add the function to fetch the list of apps
},
/**
* Reference to OOBE screen object.
* @type {!OobeTypes.Screen}
......
......@@ -3,5 +3,12 @@
found in the LICENSE file. -->
<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>
......@@ -8,7 +8,8 @@
login.createScreen('RecommendAppsScreen', 'recommend-apps', function() {
return {
EXTERNAL_API: ['loadAppList', 'setWebview', 'showError'],
EXTERNAL_API:
['loadAppList', 'setThrobberVisible', 'setWebview', 'showError'],
/**
* Returns the control which should receive initial focus.
......@@ -66,6 +67,8 @@ login.createScreen('RecommendAppsScreen', 'recommend-apps', function() {
showError: function() {
this.ensureInitialized_();
// Hide the loading throbber and show the error message.
this.setThrobberVisible(false);
this.removeClass_('recommend-apps-loading');
this.removeClass_('recommend-apps-loaded');
this.addClass_('error');
......@@ -81,24 +84,26 @@ login.createScreen('RecommendAppsScreen', 'recommend-apps', function() {
/**
* Generate the contents in the webview.
*/
loadAppList: function() {
loadAppList: function(appList) {
this.ensureInitialized_();
// Hide the loading throbber and show the recommend app list.
this.setThrobberVisible(false);
var appListView = this.getElement_('app-list-view');
var subtitle = this.getElement_('subtitle');
subtitle.innerText = loadTimeData.getStringF(
'recommendAppsScreenDescription',
$('recommend-apps-screen').apps.length);
'recommendAppsScreenDescription', appList.length);
appListView.addEventListener('contentload', () => {
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 + '", "' +
app.name + '", "' + app.package_name + '");';
var generateContents = {code: generateItemScript};
appListView.executeScript(generateContents);
});
this.onGenerateContents.call(this);
this.onGenerateContents();
});
});
},
......@@ -135,11 +140,21 @@ login.createScreen('RecommendAppsScreen', 'recommend-apps', function() {
* Handles Retry button click.
*/
onRetry: function() {
this.setThrobberVisible(true);
this.removeClass_('recommend-apps-loaded');
this.removeClass_('error');
this.addClass_('recommend-apps-loading');
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() {}
void RecommendAppsScreenHandler::Initialize() {}
void RecommendAppsScreenHandler::LoadAppListInUI() {
if (!page_is_ready())
void RecommendAppsScreenHandler::LoadAppListInUI(const base::Value& app_list) {
if (!page_is_ready()) {
CallJS("showError");
return;
}
const ui::ResourceBundle& resource_bundle =
ui::ResourceBundle::GetSharedInstance();
base::StringPiece app_list_webview = resource_bundle.GetRawDataResource(
IDR_ARC_SUPPORT_RECOMMEND_APP_LIST_VIEW_HTML);
CallJS("setWebview", app_list_webview.as_string());
CallJS("loadAppList");
CallJS("loadAppList", app_list);
}
void RecommendAppsScreenHandler::OnLoadError() {
CallJS("showError");
}
void RecommendAppsScreenHandler::OnLoadSuccess(const std::string& app_list) {
// TODO(rsgingerrs): Parse the app_list and pass it to the UI.
LoadAppListInUI();
void RecommendAppsScreenHandler::OnLoadSuccess(const base::Value& app_list) {
LoadAppListInUI(app_list);
}
void RecommendAppsScreenHandler::HandleSkip() {
......
......@@ -40,10 +40,10 @@ class RecommendAppsScreenHandler : public BaseScreenHandler,
// RecommendAppsScreenView:
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.
void LoadAppListInUI();
void LoadAppListInUI(const base::Value& app_list);
void HandleSkip();
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