1// Copyright (c) 2012 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 "select_file_dialog_android.h"
6
7#include "base/android/jni_android.h"
8#include "base/android/jni_array.h"
9#include "base/android/jni_string.h"
10#include "base/android/scoped_java_ref.h"
11#include "base/logging.h"
12#include "base/strings/string_split.h"
13#include "base/strings/string_util.h"
14#include "base/strings/utf_string_conversions.h"
15#include "jni/SelectFileDialog_jni.h"
16#include "ui/base/android/window_android.h"
17#include "ui/shell_dialogs/selected_file_info.h"
18
19using base::android::ConvertJavaStringToUTF8;
20
21namespace ui {
22
23// static
24SelectFileDialogImpl* SelectFileDialogImpl::Create(Listener* listener,
25                                                   SelectFilePolicy* policy) {
26  return new SelectFileDialogImpl(listener, policy);
27}
28
29void SelectFileDialogImpl::OnFileSelected(JNIEnv* env,
30                                          jobject java_object,
31                                          jstring filepath,
32                                          jstring display_name) {
33  if (!listener_)
34    return;
35
36  std::string path = ConvertJavaStringToUTF8(env, filepath);
37  std::string file_name = ConvertJavaStringToUTF8(env, display_name);
38  base::FilePath file_path = base::FilePath(path);
39  ui::SelectedFileInfo file_info;
40  file_info.file_path = file_path;
41  file_info.local_path = file_path;
42  if (!file_name.empty())
43    file_info.display_name = file_name;
44
45  listener_->FileSelectedWithExtraInfo(file_info, 0, NULL);
46}
47
48void SelectFileDialogImpl::OnMultipleFilesSelected(JNIEnv* env,
49                                                   jobject java_object,
50                                                   jobjectArray filepaths,
51                                                   jobjectArray display_names) {
52  if (!listener_)
53    return;
54
55  std::vector<ui::SelectedFileInfo> selected_files;
56
57  jsize length = env->GetArrayLength(filepaths);
58  DCHECK(length == env->GetArrayLength(display_names));
59  for (int i = 0; i < length; ++i) {
60    std::string path = ConvertJavaStringToUTF8(
61        env, static_cast<jstring>(env->GetObjectArrayElement(filepaths, i)));
62    std::string display_name = ConvertJavaStringToUTF8(
63        env,
64        static_cast<jstring>(env->GetObjectArrayElement(display_names, i)));
65
66    base::FilePath file_path = base::FilePath(path);
67
68    ui::SelectedFileInfo file_info;
69    file_info.file_path = file_path;
70    file_info.local_path = file_path;
71    file_info.display_name = display_name;
72
73    selected_files.push_back(file_info);
74  }
75
76  listener_->MultiFilesSelectedWithExtraInfo(selected_files, NULL);
77}
78
79void SelectFileDialogImpl::OnFileNotSelected(
80    JNIEnv* env,
81    jobject java_object) {
82  if (listener_)
83    listener_->FileSelectionCanceled(NULL);
84}
85
86bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow) const {
87  return listener_;
88}
89
90void SelectFileDialogImpl::ListenerDestroyed() {
91  listener_ = NULL;
92}
93
94void SelectFileDialogImpl::SelectFileImpl(
95    SelectFileDialog::Type type,
96    const base::string16& title,
97    const base::FilePath& default_path,
98    const SelectFileDialog::FileTypeInfo* file_types,
99    int file_type_index,
100    const std::string& default_extension,
101    gfx::NativeWindow owning_window,
102    void* params) {
103  JNIEnv* env = base::android::AttachCurrentThread();
104
105  // The first element in the pair is a list of accepted types, the second
106  // indicates whether the device's capture capabilities should be used.
107  typedef std::pair<std::vector<base::string16>, bool> AcceptTypes;
108  AcceptTypes accept_types = std::make_pair(std::vector<base::string16>(),
109                                            false);
110
111  if (params)
112    accept_types = *(reinterpret_cast<AcceptTypes*>(params));
113
114  ScopedJavaLocalRef<jobjectArray> accept_types_java =
115      base::android::ToJavaArrayOfStrings(env, accept_types.first);
116
117  bool accept_multiple_files = SelectFileDialog::SELECT_OPEN_MULTI_FILE == type;
118
119  Java_SelectFileDialog_selectFile(env, java_object_.obj(),
120                                   accept_types_java.obj(),
121                                   accept_types.second,
122                                   accept_multiple_files,
123                                   owning_window->GetJavaObject().obj());
124}
125
126bool SelectFileDialogImpl::RegisterSelectFileDialog(JNIEnv* env) {
127  return RegisterNativesImpl(env);
128}
129
130SelectFileDialogImpl::~SelectFileDialogImpl() {
131}
132
133SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener,
134                                           SelectFilePolicy* policy)
135    : SelectFileDialog(listener, policy) {
136  JNIEnv* env = base::android::AttachCurrentThread();
137  java_object_.Reset(
138      Java_SelectFileDialog_create(env, reinterpret_cast<intptr_t>(this)));
139}
140
141bool SelectFileDialogImpl::HasMultipleFileTypeChoicesImpl() {
142  NOTIMPLEMENTED();
143  return false;
144}
145
146SelectFileDialog* CreateAndroidSelectFileDialog(
147    SelectFileDialog::Listener* listener,
148    SelectFilePolicy* policy) {
149  return SelectFileDialogImpl::Create(listener, policy);
150}
151
152}  // namespace ui
153