Commit 9213e261 authored by rodmartin's avatar rodmartin Committed by Commit Bot

Added export policy session to Linux

This feature allow users to export the policies in a JSON file.

Bug: 
Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: I708abc3465ecf2a469979fb7d13b22ed947ed392
Reviewed-on: https://chromium-review.googlesource.com/966590
Commit-Queue: Martin Rodriguez <rodmartin@google.com>
Reviewed-by: default avatarJulian Pastarmov <pastarmovj@chromium.org>
Reviewed-by: default avatarDave Schuyler <dschuyler@chromium.org>
Reviewed-by: default avatarOwen Min <zmin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#550246}
parent 1cfcdb1f
...@@ -62,6 +62,7 @@ ...@@ -62,6 +62,7 @@
<div id="session-actions"> <div id="session-actions">
<button id="delete-session-button">$i18n{removeSession}</button> <button id="delete-session-button">$i18n{removeSession}</button>
<button id="rename-session-button">$i18n{renameSession}</button> <button id="rename-session-button">$i18n{renameSession}</button>
<button id="export-policies-linux">$i18n{exportLinux}</button>
</div> </div>
<select size="4" id="session-list"> <select size="4" id="session-list">
</select> </select>
......
...@@ -169,6 +169,10 @@ policy.Page.prototype.initialize = function() { ...@@ -169,6 +169,10 @@ policy.Page.prototype.initialize = function() {
} }
}; };
$('export-policies-linux').onclick = (event) => {
chrome.send('exportLinux', [policy.Page.getInstance().getDictionary()]);
};
// Notify the browser that the page has loaded, causing it to send the // Notify the browser that the page has loaded, causing it to send the
// list of all known policies and the values from the default session. // list of all known policies and the values from the default session.
chrome.send('initialized'); chrome.send('initialized');
......
...@@ -26,6 +26,7 @@ content::WebUIDataSource* CreatePolicyToolUIHtmlSource() { ...@@ -26,6 +26,7 @@ content::WebUIDataSource* CreatePolicyToolUIHtmlSource() {
source->AddLocalizedString("noPoliciesSet", IDS_POLICY_NO_POLICIES_SET); source->AddLocalizedString("noPoliciesSet", IDS_POLICY_NO_POLICIES_SET);
source->AddLocalizedString("showExpandedValue", source->AddLocalizedString("showExpandedValue",
IDS_POLICY_SHOW_EXPANDED_VALUE); IDS_POLICY_SHOW_EXPANDED_VALUE);
source->AddLocalizedString("exportLinux", IDS_EXPORT_POLICIES_LINUX);
source->AddLocalizedString("hideExpandedValue", source->AddLocalizedString("hideExpandedValue",
IDS_POLICY_HIDE_EXPANDED_VALUE); IDS_POLICY_HIDE_EXPANDED_VALUE);
source->AddLocalizedString("loadSession", IDS_POLICY_TOOL_LOAD_SESSION); source->AddLocalizedString("loadSession", IDS_POLICY_TOOL_LOAD_SESSION);
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include "base/path_service.h" #include "base/path_service.h"
#include "base/strings/strcat.h" #include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "base/task_scheduler/task_traits.h"
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "base/values.h" #include "base/values.h"
...@@ -23,6 +25,9 @@ ...@@ -23,6 +25,9 @@
#include "chrome/test/base/ui_test_utils.h" #include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h" #include "content/public/test/browser_test_utils.h"
#include "ui/shell_dialogs/select_file_dialog.h"
#include "ui/shell_dialogs/select_file_dialog_factory.h"
#include "ui/shell_dialogs/select_file_policy.h"
namespace { namespace {
...@@ -43,8 +48,6 @@ class PolicyToolUITest : public InProcessBrowserTest { ...@@ -43,8 +48,6 @@ class PolicyToolUITest : public InProcessBrowserTest {
~PolicyToolUITest() override; ~PolicyToolUITest() override;
protected: protected:
// InProcessBrowserTest implementation.
void SetUpInProcessBrowserTestFixture() override;
void SetUp() override; void SetUp() override;
base::FilePath GetSessionsDir(); base::FilePath GetSessionsDir();
...@@ -105,8 +108,6 @@ PolicyToolUITest::PolicyToolUITest() {} ...@@ -105,8 +108,6 @@ PolicyToolUITest::PolicyToolUITest() {}
PolicyToolUITest::~PolicyToolUITest() {} PolicyToolUITest::~PolicyToolUITest() {}
void PolicyToolUITest::SetUpInProcessBrowserTestFixture() {}
void PolicyToolUITest::SetUp() { void PolicyToolUITest::SetUp() {
scoped_feature_list_.InitAndEnableFeature(features::kPolicyTool); scoped_feature_list_.InitAndEnableFeature(features::kPolicyTool);
InProcessBrowserTest::SetUp(); InProcessBrowserTest::SetUp();
...@@ -261,6 +262,85 @@ std::string PolicyToolUITest::ExtractSinglePolicyValue( ...@@ -261,6 +262,85 @@ std::string PolicyToolUITest::ExtractSinglePolicyValue(
return value->GetString(); return value->GetString();
} }
class PolicyToolUIExportTest : public PolicyToolUITest {
public:
PolicyToolUIExportTest();
~PolicyToolUIExportTest() override;
protected:
// InProcessBrowserTest implementation.
void SetUpInProcessBrowserTestFixture() override;
// The temporary directory and file path for policy saving.
base::ScopedTempDir export_policies_test_dir_;
base::FilePath export_policies_test_file_path_;
};
PolicyToolUIExportTest::PolicyToolUIExportTest() {}
PolicyToolUIExportTest::~PolicyToolUIExportTest() {}
void PolicyToolUIExportTest::SetUpInProcessBrowserTestFixture() {
ASSERT_TRUE(export_policies_test_dir_.CreateUniqueTempDir());
const std::string filename = "policy.json";
export_policies_test_file_path_ =
export_policies_test_dir_.GetPath().AppendASCII(filename);
}
// An artificial SelectFileDialog that immediately returns the location of test
// file instead of showing the UI file picker.
class TestSelectFileDialogPolicyTool : public ui::SelectFileDialog {
public:
TestSelectFileDialogPolicyTool(ui::SelectFileDialog::Listener* listener,
std::unique_ptr<ui::SelectFilePolicy> policy,
const base::FilePath& default_selected_path)
: ui::SelectFileDialog(listener, std::move(policy)) {
default_path_ = default_selected_path;
}
void SelectFileImpl(Type type,
const base::string16& title,
const base::FilePath& default_path,
const FileTypeInfo* file_types,
int file_type_index,
const base::FilePath::StringType& default_extension,
gfx::NativeWindow owning_window,
void* params) override {
listener_->FileSelected(default_path_, /*index=*/0, /*params=*/nullptr);
}
bool IsRunning(gfx::NativeWindow owning_window) const override {
return false;
}
void ListenerDestroyed() override {}
bool HasMultipleFileTypeChoicesImpl() override { return false; }
private:
~TestSelectFileDialogPolicyTool() override {}
base::FilePath default_path_;
};
// A factory associated with the artificial file picker.
class TestSelectFileDialogFactoryPolicyTool
: public ui::SelectFileDialogFactory {
public:
TestSelectFileDialogFactoryPolicyTool(
const base::FilePath& default_selected_path) {
default_path_ = default_selected_path;
}
private:
base::FilePath default_path_;
ui::SelectFileDialog* Create(
ui::SelectFileDialog::Listener* listener,
std::unique_ptr<ui::SelectFilePolicy> policy) override {
return new TestSelectFileDialogPolicyTool(listener, std::move(policy),
default_path_);
}
};
IN_PROC_BROWSER_TEST_F(PolicyToolUITest, CreatingSessionFiles) { IN_PROC_BROWSER_TEST_F(PolicyToolUITest, CreatingSessionFiles) {
base::ScopedAllowBlockingForTesting allow_blocking; base::ScopedAllowBlockingForTesting allow_blocking;
// Check that the directory is not created yet. // Check that the directory is not created yet.
...@@ -526,3 +606,43 @@ IN_PROC_BROWSER_TEST_F(PolicyToolUITest, RenameSessionInvalidName) { ...@@ -526,3 +606,43 @@ IN_PROC_BROWSER_TEST_F(PolicyToolUITest, RenameSessionInvalidName) {
EXPECT_TRUE(IsSessionRenameErrorMessageDisplayed()); EXPECT_TRUE(IsSessionRenameErrorMessageDisplayed());
EXPECT_EQ(expected, *ExtractSessionsList()); EXPECT_EQ(expected, *ExtractSessionsList());
} }
IN_PROC_BROWSER_TEST_F(PolicyToolUIExportTest, ExportSessionPolicyToLinux) {
CreateMultipleSessionFiles(3);
// Set SelectFileDialog to use our factory.
ui::SelectFileDialog::SetFactory(new TestSelectFileDialogFactoryPolicyTool(
export_policies_test_file_path_));
// Test if the current session policy is successfully exported.
ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool"));
std::string javascript =
"$('show-unset').click();"
"var policyEntry = document.querySelectorAll("
" 'section.policy-table-section > * > tbody')[0];"
"policyEntry.getElementsByClassName('edit-button')[0].click();"
"policyEntry.getElementsByClassName('value-edit-field')[0].value ="
" 'test';"
"policyEntry.getElementsByClassName('save-button')[0].click();"
"$('export-policies-linux').click()";
content::WebContents* contents =
browser()->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(content::ExecuteScript(contents, javascript));
// Because we created 3 session policies (with paths {0, 1, 2}), the last one
// is the current active session policy.
EXPECT_TRUE(base::ContentsEqual(export_policies_test_file_path_,
GetSessionPath(FILE_PATH_LITERAL("2"))));
// Test if after an export action, we can continue exporting.
std::string change_session_js =
"$('session-name-field').value = '1';"
"$('load-session-button').click();";
EXPECT_TRUE(content::ExecuteScript(contents, change_session_js + javascript));
base::TaskScheduler::GetInstance()->FlushForTesting();
EXPECT_TRUE(base::ContentsEqual(export_policies_test_file_path_,
GetSessionPath(FILE_PATH_LITERAL("1"))));
TestSelectFileDialogPolicyTool::SetFactory(nullptr);
}
...@@ -11,9 +11,13 @@ ...@@ -11,9 +11,13 @@
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/task_scheduler/post_task.h" #include "base/task_scheduler/post_task.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/chrome_select_file_policy.h"
#include "components/strings/grit/components_strings.h" #include "components/strings/grit/components_strings.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include "ui/shell_dialogs/select_file_policy.h"
namespace { namespace {
...@@ -26,6 +30,9 @@ const base::FilePath::CharType kPolicyToolDefaultSessionName[] = ...@@ -26,6 +30,9 @@ const base::FilePath::CharType kPolicyToolDefaultSessionName[] =
const base::FilePath::CharType kPolicyToolSessionExtension[] = const base::FilePath::CharType kPolicyToolSessionExtension[] =
FILE_PATH_LITERAL("json"); FILE_PATH_LITERAL("json");
const base::FilePath::CharType kPolicyToolLinuxExtension[] =
FILE_PATH_LITERAL("json");
// Returns the current list of all sessions sorted by last access time in // Returns the current list of all sessions sorted by last access time in
// decreasing order. // decreasing order.
base::ListValue GetSessionsList(const base::FilePath& sessions_dir) { base::ListValue GetSessionsList(const base::FilePath& sessions_dir) {
...@@ -90,6 +97,10 @@ void PolicyToolUIHandler::RegisterMessages() { ...@@ -90,6 +97,10 @@ void PolicyToolUIHandler::RegisterMessages() {
"deleteSession", "deleteSession",
base::BindRepeating(&PolicyToolUIHandler::HandleDeleteSession, base::BindRepeating(&PolicyToolUIHandler::HandleDeleteSession,
base::Unretained(this))); base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"exportLinux",
base::BindRepeating(&PolicyToolUIHandler::HandleExportLinux,
base::Unretained(this)));
} }
void PolicyToolUIHandler::OnJavascriptDisallowed() { void PolicyToolUIHandler::OnJavascriptDisallowed() {
...@@ -377,3 +388,72 @@ void PolicyToolUIHandler::HandleDeleteSession(const base::ListValue* args) { ...@@ -377,3 +388,72 @@ void PolicyToolUIHandler::HandleDeleteSession(const base::ListValue* args) {
base::BindOnce(&PolicyToolUIHandler::OnSessionDeleted, base::BindOnce(&PolicyToolUIHandler::OnSessionDeleted,
callback_weak_ptr_factory_.GetWeakPtr())); callback_weak_ptr_factory_.GetWeakPtr()));
} }
void PolicyToolUIHandler::HandleExportLinux(const base::ListValue* args) {
DCHECK_EQ(1U, args->GetSize());
base::JSONWriter::Write(args->GetList()[0], &session_dict_for_exporting_);
ExportSessionToFile(kPolicyToolLinuxExtension);
}
void DoWriteSessionPolicyToFile(const base::FilePath& path,
const std::string& data) {
// TODO(rodmartin): Handle when WriteFile fail.
base::WriteFile(path, data.c_str(), data.size());
}
void PolicyToolUIHandler::WriteSessionPolicyToFile(
const base::FilePath& path) const {
const std::string data = session_dict_for_exporting_;
base::PostTaskWithTraits(
FROM_HERE,
{base::MayBlock(), base::TaskPriority::BACKGROUND,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
base::BindOnce(&DoWriteSessionPolicyToFile, path, data));
}
void PolicyToolUIHandler::FileSelected(const base::FilePath& path,
int index,
void* params) {
DCHECK(export_policies_select_file_dialog_);
WriteSessionPolicyToFile(path);
session_dict_for_exporting_.clear();
export_policies_select_file_dialog_ = nullptr;
}
void PolicyToolUIHandler::FileSelectionCanceled(void* params) {
DCHECK(export_policies_select_file_dialog_);
session_dict_for_exporting_.clear();
export_policies_select_file_dialog_ = nullptr;
}
void PolicyToolUIHandler::ExportSessionToFile(
const base::FilePath::StringType& file_extension) {
// If the "select file" dialog window is already opened, we don't want to open
// it again.
if (export_policies_select_file_dialog_)
return;
content::WebContents* webcontents = web_ui()->GetWebContents();
// Building initial path based on download preferences.
base::FilePath initial_dir =
DownloadPrefs::FromBrowserContext(webcontents->GetBrowserContext())
->DownloadPath();
base::FilePath initial_path =
initial_dir.Append(kPolicyToolDefaultSessionName)
.AddExtension(file_extension);
// TODO(rodmartin): Put an error message when the user is not allowed
// to open select file dialogs.
export_policies_select_file_dialog_ = ui::SelectFileDialog::Create(
this, std::make_unique<ChromeSelectFilePolicy>(webcontents));
ui::SelectFileDialog::FileTypeInfo file_type_info;
file_type_info.extensions = {{file_extension}};
gfx::NativeWindow owning_window = webcontents->GetTopLevelNativeWindow();
export_policies_select_file_dialog_->SelectFile(
ui::SelectFileDialog::SELECT_SAVEAS_FILE, /*title=*/base::string16(),
initial_path, &file_type_info, /*file_type_index=*/0,
/*default_extension=*/base::FilePath::StringType(), owning_window,
/*params=*/nullptr);
}
...@@ -45,6 +45,8 @@ class PolicyToolUIHandler : public PolicyUIHandler { ...@@ -45,6 +45,8 @@ class PolicyToolUIHandler : public PolicyUIHandler {
void HandleDeleteSession(const base::ListValue* args); void HandleDeleteSession(const base::ListValue* args);
void HandleExportLinux(const base::ListValue* args);
void OnSessionDeleted(bool is_successful); void OnSessionDeleted(bool is_successful);
std::string ReadOrCreateFileCallback(); std::string ReadOrCreateFileCallback();
...@@ -67,11 +69,28 @@ class PolicyToolUIHandler : public PolicyUIHandler { ...@@ -67,11 +69,28 @@ class PolicyToolUIHandler : public PolicyUIHandler {
void SetDefaultSessionName(); void SetDefaultSessionName();
// ui::SelectFileDialog::Listener implementation.
void FileSelected(const base::FilePath& path,
int index,
void* params) override;
void FileSelectionCanceled(void* params) override;
void WriteSessionPolicyToFile(const base::FilePath& path) const;
void ExportSessionToFile(const base::FilePath::StringType& file_extension);
bool is_saving_enabled_ = true; bool is_saving_enabled_ = true;
// This string is filled when an export action occurs, it contains the current
// session dictionary in a specific format. This format will be JSON, PLIST,
// or REG; depending on the kind of export.
std::string session_dict_for_exporting_;
base::FilePath sessions_dir_; base::FilePath sessions_dir_;
base::FilePath::StringType session_name_; base::FilePath::StringType session_name_;
scoped_refptr<ui::SelectFileDialog> export_policies_select_file_dialog_;
base::WeakPtrFactory<PolicyToolUIHandler> callback_weak_ptr_factory_; base::WeakPtrFactory<PolicyToolUIHandler> callback_weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(PolicyToolUIHandler); DISALLOW_COPY_AND_ASSIGN(PolicyToolUIHandler);
......
...@@ -237,6 +237,10 @@ ...@@ -237,6 +237,10 @@
<message name="IDS_POLICY_TOOL_TITLE" desc="Admin page title and the title of the section that lists policies."> <message name="IDS_POLICY_TOOL_TITLE" desc="Admin page title and the title of the section that lists policies.">
Policy management Policy management
</message> </message>
<message name="IDS_EXPORT_POLICIES_LINUX" desc="Button that exports the current session policy
in linux format.">
Export Linux
</message>
<message name="IDS_POLICY_TOOL_EDIT" desc="Label for the button to change policy value in current session."> <message name="IDS_POLICY_TOOL_EDIT" desc="Label for the button to change policy value in current session.">
Edit Edit
</message> </message>
......
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