1 // Copyright 2015 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.
5 #include "chrome/browser/android/offline_pages/offline_page_bridge.h"
7 #include "base/android/jni_array.h"
8 #include "base/android/jni_string.h"
9 #include "base/basictypes.h"
10 #include "base/files/file_path.h"
11 #include "base/strings/string_util.h"
12 #include "chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h"
13 #include "chrome/browser/android/offline_pages/offline_page_model_factory.h"
14 #include "chrome/browser/download/download_prefs.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/profiles/profile_android.h"
17 #include "components/offline_pages/offline_page_feature.h"
18 #include "components/offline_pages/offline_page_item.h"
19 #include "components/offline_pages/offline_page_model.h"
20 #include "content/public/browser/browser_context.h"
21 #include "content/public/browser/download_manager.h"
22 #include "content/public/browser/web_contents.h"
23 #include "jni/OfflinePageBridge_jni.h"
24 #include "net/base/filename_util.h"
26 using base::android::ConvertJavaStringToUTF8
;
27 using base::android::ConvertUTF16ToJavaString
;
28 using base::android::ConvertUTF8ToJavaString
;
29 using base::android::ScopedJavaGlobalRef
;
30 using base::android::ScopedJavaLocalRef
;
32 namespace offline_pages
{
37 void SavePageCallback(const ScopedJavaGlobalRef
<jobject
>& j_callback_obj
,
39 OfflinePageModel::SavePageResult result
) {
40 JNIEnv
* env
= base::android::AttachCurrentThread();
42 Java_SavePageCallback_onSavePageDone(
43 env
, j_callback_obj
.obj(), static_cast<int>(result
),
44 ConvertUTF8ToJavaString(env
, url
.spec()).obj());
47 void DeletePageCallback(const ScopedJavaGlobalRef
<jobject
>& j_callback_obj
,
48 OfflinePageModel::DeletePageResult result
) {
49 JNIEnv
* env
= base::android::AttachCurrentThread();
51 Java_DeletePageCallback_onDeletePageDone(
52 env
, j_callback_obj
.obj(), static_cast<int>(result
));
55 void ToJavaOfflinePageList(JNIEnv
* env
,
57 const std::vector
<OfflinePageItem
>& offline_pages
) {
58 for (const OfflinePageItem
& offline_page
: offline_pages
) {
59 Java_OfflinePageBridge_createOfflinePageAndAddToList(
61 ConvertUTF8ToJavaString(env
, offline_page
.url
.spec()).obj(),
62 offline_page
.bookmark_id
,
63 ConvertUTF8ToJavaString(env
, offline_page
.GetOfflineURL().spec()).obj(),
64 offline_page
.file_size
);
70 static jboolean
IsOfflinePagesEnabled(JNIEnv
* env
,
71 const JavaParamRef
<jclass
>& clazz
) {
72 return offline_pages::IsOfflinePagesEnabled();
75 OfflinePageBridge::OfflinePageBridge(JNIEnv
* env
,
77 content::BrowserContext
* browser_context
)
78 : weak_java_ref_(env
, obj
),
79 offline_page_model_(OfflinePageModelFactory::GetForBrowserContext(
81 browser_context_(browser_context
) {
82 NotifyIfDoneLoading();
83 offline_page_model_
->AddObserver(this);
86 void OfflinePageBridge::Destroy(JNIEnv
*, jobject
) {
87 offline_page_model_
->RemoveObserver(this);
91 void OfflinePageBridge::OfflinePageModelLoaded(OfflinePageModel
* model
) {
92 DCHECK_EQ(offline_page_model_
, model
);
93 NotifyIfDoneLoading();
96 void OfflinePageBridge::GetAllPages(JNIEnv
* env
,
98 jobject j_result_obj
) {
99 DCHECK(offline_page_model_
->is_loaded());
100 DCHECK(j_result_obj
);
101 const std::vector
<OfflinePageItem
>& offline_pages
=
102 offline_page_model_
->GetAllPages();
103 ToJavaOfflinePageList(env
, j_result_obj
, offline_pages
);
106 void OfflinePageBridge::GetPagesToCleanUp(JNIEnv
* env
,
108 jobject j_result_obj
) {
109 DCHECK(offline_page_model_
->is_loaded());
110 DCHECK(j_result_obj
);
111 const std::vector
<OfflinePageItem
>& offline_pages
=
112 offline_page_model_
->GetPagesToCleanUp();
113 ToJavaOfflinePageList(env
, j_result_obj
, offline_pages
);
116 ScopedJavaLocalRef
<jobject
> OfflinePageBridge::GetPageByBookmarkId(
120 OfflinePageItem offline_page
;
121 if (!offline_page_model_
->GetPageByBookmarkId(bookmark_id
, &offline_page
))
122 return ScopedJavaLocalRef
<jobject
>();
124 return Java_OfflinePageBridge_createOfflinePageItem(
125 env
, ConvertUTF8ToJavaString(env
, offline_page
.url
.spec()).obj(),
126 offline_page
.bookmark_id
,
127 ConvertUTF8ToJavaString(env
, offline_page
.GetOfflineURL().spec()).obj(),
128 offline_page
.file_size
);
131 void OfflinePageBridge::SavePage(JNIEnv
* env
,
133 jobject j_callback_obj
,
134 jobject j_web_contents
,
136 DCHECK(j_callback_obj
);
137 DCHECK(j_web_contents
);
139 ScopedJavaGlobalRef
<jobject
> j_callback_ref
;
140 j_callback_ref
.Reset(env
, j_callback_obj
);
142 content::WebContents
* web_contents
=
143 content::WebContents::FromJavaWebContents(j_web_contents
);
144 GURL
url(web_contents
->GetLastCommittedURL());
146 scoped_ptr
<OfflinePageArchiver
> archiver(
147 new OfflinePageMHTMLArchiver(
148 web_contents
, GetDownloadsPath(browser_context_
)));
150 offline_page_model_
->SavePage(
151 url
, bookmark_id
, archiver
.Pass(),
152 base::Bind(&SavePageCallback
, j_callback_ref
, url
));
155 void OfflinePageBridge::DeletePage(JNIEnv
* env
,
157 jobject j_callback_obj
,
159 DCHECK(j_callback_obj
);
161 ScopedJavaGlobalRef
<jobject
> j_callback_ref
;
162 j_callback_ref
.Reset(env
, j_callback_obj
);
164 offline_page_model_
->DeletePageByBookmarkId(bookmark_id
, base::Bind(
165 &DeletePageCallback
, j_callback_ref
));
168 void OfflinePageBridge::DeletePages(JNIEnv
* env
,
170 jobject j_callback_obj
,
171 jlongArray bookmark_ids_array
) {
172 DCHECK(j_callback_obj
);
174 ScopedJavaGlobalRef
<jobject
> j_callback_ref
;
175 j_callback_ref
.Reset(env
, j_callback_obj
);
177 std::vector
<int64
> bookmark_ids
;
178 base::android::JavaLongArrayToInt64Vector(env
, bookmark_ids_array
,
181 offline_page_model_
->DeletePagesByBookmarkId(
183 base::Bind(&DeletePageCallback
, j_callback_ref
));
186 void OfflinePageBridge::NotifyIfDoneLoading() const {
187 if (!offline_page_model_
->is_loaded())
189 JNIEnv
* env
= base::android::AttachCurrentThread();
190 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
193 Java_OfflinePageBridge_offlinePageModelLoaded(env
, obj
.obj());
197 bool OfflinePageBridge::MightBeOfflineURL(const GURL
& url
) {
198 // It has to be a file URL ending with .mhtml extension.
199 return url
.is_valid() &&
200 url
.SchemeIsFile() &&
201 base::EndsWith(url
.spec(),
202 OfflinePageMHTMLArchiver::GetFileNameExtension(),
203 base::CompareCase::INSENSITIVE_ASCII
);
207 base::FilePath
OfflinePageBridge::GetDownloadsPath(
208 content::BrowserContext
* browser_context
) {
209 content::DownloadManager
* manager
=
210 content::BrowserContext::GetDownloadManager(browser_context
);
212 DVLOG(1) << "No download manager available in offline page bridge";
213 return base::FilePath();
216 return DownloadPrefs::FromDownloadManager(manager
)->DownloadPath();
219 static jlong
Init(JNIEnv
* env
,
220 const JavaParamRef
<jobject
>& obj
,
221 const JavaParamRef
<jobject
>& j_profile
) {
222 return reinterpret_cast<jlong
>(new OfflinePageBridge(
223 env
, obj
, ProfileAndroid::FromProfileAndroid(j_profile
)));
226 bool RegisterOfflinePageBridge(JNIEnv
* env
) {
227 return RegisterNativesImpl(env
);
230 } // namespace android
231 } // namespace offline_pages