1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/download/download_dir_policy_handler.h"
6
7#include "base/files/file_path.h"
8#include "base/memory/scoped_ptr.h"
9#include "base/prefs/pref_value_map.h"
10#include "base/values.h"
11#include "chrome/browser/download/download_prefs.h"
12#include "chrome/browser/policy/policy_path_parser.h"
13#include "chrome/common/pref_names.h"
14#include "components/policy/core/browser/configuration_policy_handler_parameters.h"
15#include "components/policy/core/browser/policy_error_map.h"
16#include "components/policy/core/common/policy_map.h"
17#include "components/policy/core/common/policy_types.h"
18#include "grit/components_strings.h"
19#include "policy/policy_constants.h"
20
21#if defined(OS_CHROMEOS)
22#include "chrome/browser/chromeos/drive/file_system_util.h"
23#endif
24
25namespace {
26#if defined(OS_CHROMEOS)
27const char* kDriveNamePolicyVariableName = "${google_drive}";
28
29// Drive root folder relative to its mount point.
30const base::FilePath::CharType* kRootRelativeToDriveMount =
31    FILE_PATH_LITERAL("root");
32#endif
33}  // namespace
34
35DownloadDirPolicyHandler::DownloadDirPolicyHandler()
36    : TypeCheckingPolicyHandler(policy::key::kDownloadDirectory,
37                                base::Value::TYPE_STRING) {}
38
39DownloadDirPolicyHandler::~DownloadDirPolicyHandler() {}
40
41bool DownloadDirPolicyHandler::CheckPolicySettings(
42    const policy::PolicyMap& policies,
43    policy::PolicyErrorMap* errors) {
44  const base::Value* value = NULL;
45  if (!CheckAndGetValue(policies, errors, &value))
46    return false;
47
48#if defined(OS_CHROMEOS)
49  // Download directory can only be set as a user policy. If it is set through
50  // platform policy for a chromeos=1 build, ignore it.
51  if (value &&
52      policies.Get(policy_name())->scope != policy::POLICY_SCOPE_USER) {
53    errors->AddError(policy_name(), IDS_POLICY_SCOPE_ERROR);
54    return false;
55  }
56#endif
57
58  return true;
59}
60
61void DownloadDirPolicyHandler::ApplyPolicySettingsWithParameters(
62    const policy::PolicyMap& policies,
63    const policy::PolicyHandlerParameters& parameters,
64    PrefValueMap* prefs) {
65  const base::Value* value = policies.GetValue(policy_name());
66  base::FilePath::StringType string_value;
67  if (!value || !value->GetAsString(&string_value))
68    return;
69
70  base::FilePath::StringType expanded_value;
71#if defined(OS_CHROMEOS)
72  bool download_to_drive = false;
73  // TODO(kaliamoorthi): Clean up policy::path_parser and fold this code
74  // into it. http://crbug.com/352627
75  size_t position = string_value.find(kDriveNamePolicyVariableName);
76  if (position != base::FilePath::StringType::npos) {
77    base::FilePath::StringType google_drive_root;
78    if (!parameters.user_id_hash.empty()) {
79      google_drive_root = drive::util::GetDriveMountPointPathForUserIdHash(
80                              parameters.user_id_hash)
81                              .Append(kRootRelativeToDriveMount)
82                              .value();
83      download_to_drive = true;
84    }
85    expanded_value = string_value.replace(
86        position,
87        base::FilePath::StringType(kDriveNamePolicyVariableName).length(),
88        google_drive_root);
89  } else {
90    expanded_value = string_value;
91  }
92#else
93  expanded_value = policy::path_parser::ExpandPathVariables(string_value);
94#endif
95  // Make sure the path isn't empty, since that will point to an undefined
96  // location; the default location is used instead in that case.
97  // This is checked after path expansion because a non-empty policy value can
98  // lead to an empty path value after expansion (e.g. "\"\"").
99  if (expanded_value.empty())
100    expanded_value = DownloadPrefs::GetDefaultDownloadDirectory().value();
101  prefs->SetValue(prefs::kDownloadDefaultDirectory,
102                  new base::StringValue(expanded_value));
103
104  // If the policy is mandatory, prompt for download should be disabled.
105  // Otherwise, it would enable a user to bypass the mandatory policy.
106  if (policies.Get(policy_name())->level == policy::POLICY_LEVEL_MANDATORY) {
107    prefs->SetValue(prefs::kPromptForDownload,
108                    new base::FundamentalValue(false));
109#if defined(OS_CHROMEOS)
110    if (download_to_drive) {
111      prefs->SetValue(prefs::kDisableDrive,
112                      new base::FundamentalValue(false));
113    }
114#endif
115  }
116}
117