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
, jclass clazz
) {
71 return offline_pages::IsOfflinePagesEnabled();
74 OfflinePageBridge::OfflinePageBridge(JNIEnv
* env
,
76 content::BrowserContext
* browser_context
)
77 : weak_java_ref_(env
, obj
),
78 offline_page_model_(OfflinePageModelFactory::GetForBrowserContext(
80 browser_context_(browser_context
) {
81 NotifyIfDoneLoading();
82 offline_page_model_
->AddObserver(this);
85 void OfflinePageBridge::Destroy(JNIEnv
*, jobject
) {
86 offline_page_model_
->RemoveObserver(this);
90 void OfflinePageBridge::OfflinePageModelLoaded(OfflinePageModel
* model
) {
91 DCHECK_EQ(offline_page_model_
, model
);
92 NotifyIfDoneLoading();
95 void OfflinePageBridge::GetAllPages(JNIEnv
* env
,
97 jobject j_result_obj
) {
98 DCHECK(offline_page_model_
->is_loaded());
100 const std::vector
<OfflinePageItem
>& offline_pages
=
101 offline_page_model_
->GetAllPages();
102 ToJavaOfflinePageList(env
, j_result_obj
, offline_pages
);
105 void OfflinePageBridge::GetPagesToCleanUp(JNIEnv
* env
,
107 jobject j_result_obj
) {
108 DCHECK(offline_page_model_
->is_loaded());
109 DCHECK(j_result_obj
);
110 const std::vector
<OfflinePageItem
>& offline_pages
=
111 offline_page_model_
->GetPagesToCleanUp();
112 ToJavaOfflinePageList(env
, j_result_obj
, offline_pages
);
115 ScopedJavaLocalRef
<jobject
> OfflinePageBridge::GetPageByBookmarkId(
119 OfflinePageItem offline_page
;
120 if (!offline_page_model_
->GetPageByBookmarkId(bookmark_id
, &offline_page
))
121 return ScopedJavaLocalRef
<jobject
>();
123 return Java_OfflinePageBridge_createOfflinePageItem(
124 env
, ConvertUTF8ToJavaString(env
, offline_page
.url
.spec()).obj(),
125 offline_page
.bookmark_id
,
126 ConvertUTF8ToJavaString(env
, offline_page
.GetOfflineURL().spec()).obj(),
127 offline_page
.file_size
);
130 void OfflinePageBridge::SavePage(JNIEnv
* env
,
132 jobject j_callback_obj
,
133 jobject j_web_contents
,
135 DCHECK(j_callback_obj
);
136 DCHECK(j_web_contents
);
138 ScopedJavaGlobalRef
<jobject
> j_callback_ref
;
139 j_callback_ref
.Reset(env
, j_callback_obj
);
141 content::WebContents
* web_contents
=
142 content::WebContents::FromJavaWebContents(j_web_contents
);
143 GURL
url(web_contents
->GetLastCommittedURL());
145 scoped_ptr
<OfflinePageArchiver
> archiver(
146 new OfflinePageMHTMLArchiver(
147 web_contents
, GetDownloadsPath(browser_context_
)));
149 offline_page_model_
->SavePage(
150 url
, bookmark_id
, archiver
.Pass(),
151 base::Bind(&SavePageCallback
, j_callback_ref
, url
));
154 void OfflinePageBridge::DeletePage(JNIEnv
* env
,
156 jobject j_callback_obj
,
158 DCHECK(j_callback_obj
);
160 ScopedJavaGlobalRef
<jobject
> j_callback_ref
;
161 j_callback_ref
.Reset(env
, j_callback_obj
);
163 offline_page_model_
->DeletePageByBookmarkId(bookmark_id
, base::Bind(
164 &DeletePageCallback
, j_callback_ref
));
167 void OfflinePageBridge::DeletePages(JNIEnv
* env
,
169 jobject j_callback_obj
,
170 jlongArray bookmark_ids_array
) {
171 DCHECK(j_callback_obj
);
173 ScopedJavaGlobalRef
<jobject
> j_callback_ref
;
174 j_callback_ref
.Reset(env
, j_callback_obj
);
176 std::vector
<int64
> bookmark_ids
;
177 base::android::JavaLongArrayToInt64Vector(env
, bookmark_ids_array
,
180 offline_page_model_
->DeletePagesByBookmarkId(
182 base::Bind(&DeletePageCallback
, j_callback_ref
));
185 void OfflinePageBridge::NotifyIfDoneLoading() const {
186 if (!offline_page_model_
->is_loaded())
188 JNIEnv
* env
= base::android::AttachCurrentThread();
189 ScopedJavaLocalRef
<jobject
> obj
= weak_java_ref_
.get(env
);
192 Java_OfflinePageBridge_offlinePageModelLoaded(env
, obj
.obj());
196 bool OfflinePageBridge::MightBeOfflineURL(const GURL
& url
) {
197 // It has to be a file URL ending with .mhtml extension.
198 return url
.is_valid() &&
199 url
.SchemeIsFile() &&
200 base::EndsWith(url
.spec(),
201 OfflinePageMHTMLArchiver::GetFileNameExtension(),
202 base::CompareCase::INSENSITIVE_ASCII
);
206 base::FilePath
OfflinePageBridge::GetDownloadsPath(
207 content::BrowserContext
* browser_context
) {
208 content::DownloadManager
* manager
=
209 content::BrowserContext::GetDownloadManager(browser_context
);
211 DVLOG(1) << "No download manager available in offline page bridge";
212 return base::FilePath();
215 return DownloadPrefs::FromDownloadManager(manager
)->DownloadPath();
218 static jlong
Init(JNIEnv
* env
, jobject obj
, jobject j_profile
) {
219 return reinterpret_cast<jlong
>(new OfflinePageBridge(
220 env
, obj
, ProfileAndroid::FromProfileAndroid(j_profile
)));
223 bool RegisterOfflinePageBridge(JNIEnv
* env
) {
224 return RegisterNativesImpl(env
);
227 } // namespace android
228 } // namespace offline_pages