blob: 716403c09ba54c529e2eb42b0da7a4f9fd50ae0c [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/android/offline_pages/offline_page_bridge.h"
#include <utility>
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h"
#include "chrome/browser/android/offline_pages/offline_page_model_factory.h"
#include "chrome/browser/android/offline_pages/offline_page_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_android.h"
#include "components/offline_pages/offline_page_feature.h"
#include "components/offline_pages/offline_page_item.h"
#include "components/offline_pages/offline_page_model.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/web_contents.h"
#include "jni/OfflinePageBridge_jni.h"
#include "net/base/filename_util.h"
using base::android::ConvertJavaStringToUTF8;
using base::android::ConvertUTF8ToJavaString;
using base::android::ScopedJavaGlobalRef;
using base::android::ScopedJavaLocalRef;
namespace offline_pages {
namespace android {
namespace {
void SavePageCallback(const ScopedJavaGlobalRef<jobject>& j_callback_obj,
const GURL& url,
OfflinePageModel::SavePageResult result) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_SavePageCallback_onSavePageDone(
env, j_callback_obj.obj(), static_cast<int>(result),
ConvertUTF8ToJavaString(env, url.spec()).obj());
}
void DeletePageCallback(const ScopedJavaGlobalRef<jobject>& j_callback_obj,
OfflinePageModel::DeletePageResult result) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_DeletePageCallback_onDeletePageDone(
env, j_callback_obj.obj(), static_cast<int>(result));
}
void ToJavaOfflinePageList(JNIEnv* env,
jobject j_result_obj,
const std::vector<OfflinePageItem>& offline_pages) {
for (const OfflinePageItem& offline_page : offline_pages) {
Java_OfflinePageBridge_createOfflinePageAndAddToList(
env, j_result_obj,
ConvertUTF8ToJavaString(env, offline_page.url.spec()).obj(),
offline_page.bookmark_id,
ConvertUTF8ToJavaString(env, offline_page.GetOfflineURL().spec()).obj(),
offline_page.file_size,
offline_page.creation_time.ToJavaTime(),
offline_page.access_count,
offline_page.last_access_time.ToJavaTime());
}
}
} // namespace
static jint GetFeatureMode(JNIEnv* env, const JavaParamRef<jclass>& clazz) {
return static_cast<jint>(offline_pages::GetOfflinePageFeatureMode());
}
static jboolean CanSavePage(JNIEnv* env,
const JavaParamRef<jclass>& clazz,
const JavaParamRef<jstring>& j_url) {
GURL url(ConvertJavaStringToUTF8(env, j_url));
return url.is_valid() && OfflinePageModel::CanSavePage(url);
}
OfflinePageBridge::OfflinePageBridge(JNIEnv* env,
jobject obj,
content::BrowserContext* browser_context)
: weak_java_ref_(env, obj),
browser_context_(browser_context),
offline_page_model_(
OfflinePageModelFactory::GetForBrowserContext(browser_context)) {
NotifyIfDoneLoading();
offline_page_model_->AddObserver(this);
}
void OfflinePageBridge::Destroy(JNIEnv*, const JavaParamRef<jobject>&) {
offline_page_model_->RemoveObserver(this);
delete this;
}
void OfflinePageBridge::OfflinePageModelLoaded(OfflinePageModel* model) {
DCHECK_EQ(offline_page_model_, model);
NotifyIfDoneLoading();
}
void OfflinePageBridge::OfflinePageModelChanged(OfflinePageModel* model) {
DCHECK_EQ(offline_page_model_, model);
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
if (obj.is_null())
return;
Java_OfflinePageBridge_offlinePageModelChanged(env, obj.obj());
}
void OfflinePageBridge::OfflinePageDeleted(int64_t bookmark_id) {
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
if (obj.is_null())
return;
Java_OfflinePageBridge_offlinePageDeleted(env, obj.obj(), bookmark_id);
}
void OfflinePageBridge::GetAllPages(JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& j_result_obj) {
DCHECK(offline_page_model_->is_loaded());
DCHECK(j_result_obj);
const std::vector<OfflinePageItem> offline_pages =
offline_page_model_->GetAllPages();
ToJavaOfflinePageList(env, j_result_obj, offline_pages);
}
void OfflinePageBridge::GetPagesToCleanUp(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& j_result_obj) {
DCHECK(offline_page_model_->is_loaded());
DCHECK(j_result_obj);
const std::vector<OfflinePageItem> offline_pages =
offline_page_model_->GetPagesToCleanUp();
ToJavaOfflinePageList(env, j_result_obj, offline_pages);
}
ScopedJavaLocalRef<jobject> OfflinePageBridge::GetPageByBookmarkId(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jlong bookmark_id) {
const OfflinePageItem* offline_page =
offline_page_model_->GetPageByBookmarkId(bookmark_id);
if (!offline_page)
return ScopedJavaLocalRef<jobject>();
return CreateOfflinePageItem(env, *offline_page);
}
ScopedJavaLocalRef<jobject> OfflinePageBridge::GetPageByOnlineURL(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jstring>& online_url) {
const OfflinePageItem* offline_page = offline_page_model_->GetPageByOnlineURL(
GURL(ConvertJavaStringToUTF8(env, online_url)));
if (!offline_page)
return ScopedJavaLocalRef<jobject>();
return CreateOfflinePageItem(env, *offline_page);
}
void OfflinePageBridge::SavePage(JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& j_callback_obj,
const JavaParamRef<jobject>& j_web_contents,
jlong bookmark_id) {
DCHECK(j_callback_obj);
DCHECK(j_web_contents);
ScopedJavaGlobalRef<jobject> j_callback_ref;
j_callback_ref.Reset(env, j_callback_obj);
content::WebContents* web_contents =
content::WebContents::FromJavaWebContents(j_web_contents);
GURL url(web_contents->GetLastCommittedURL());
scoped_ptr<OfflinePageArchiver> archiver(
new OfflinePageMHTMLArchiver(web_contents));
offline_page_model_->SavePage(
url, bookmark_id, std::move(archiver),
base::Bind(&SavePageCallback, j_callback_ref, url));
}
void OfflinePageBridge::MarkPageAccessed(JNIEnv* env,
const JavaParamRef<jobject>& obj,
jlong bookmark_id) {
offline_page_model_->MarkPageAccessed(bookmark_id);
}
void OfflinePageBridge::DeletePage(JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& j_callback_obj,
jlong bookmark_id) {
DCHECK(j_callback_obj);
ScopedJavaGlobalRef<jobject> j_callback_ref;
j_callback_ref.Reset(env, j_callback_obj);
offline_page_model_->DeletePageByBookmarkId(bookmark_id, base::Bind(
&DeletePageCallback, j_callback_ref));
}
void OfflinePageBridge::DeletePages(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& j_callback_obj,
const JavaParamRef<jlongArray>& bookmark_ids_array) {
DCHECK(j_callback_obj);
ScopedJavaGlobalRef<jobject> j_callback_ref;
j_callback_ref.Reset(env, j_callback_obj);
std::vector<int64_t> bookmark_ids;
base::android::JavaLongArrayToInt64Vector(env, bookmark_ids_array,
&bookmark_ids);
offline_page_model_->DeletePagesByBookmarkId(
bookmark_ids,
base::Bind(&DeletePageCallback, j_callback_ref));
}
void OfflinePageBridge::CheckMetadataConsistency(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
offline_page_model_->CheckForExternalFileDeletion();
}
ScopedJavaLocalRef<jstring> OfflinePageBridge::GetOfflineUrlForOnlineUrl(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jstring>& j_online_url) {
GURL online_url(ConvertJavaStringToUTF8(env, j_online_url));
GURL offline_url =
OfflinePageUtils::GetOfflineURLForOnlineURL(browser_context_, online_url);
if (!offline_url.is_valid())
return ScopedJavaLocalRef<jstring>();
return ConvertUTF8ToJavaString(env, offline_url.spec());
}
jboolean OfflinePageBridge::IsOfflinePageUrl(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jstring>& j_offline_url) {
GURL offline_url(ConvertJavaStringToUTF8(env, j_offline_url));
return OfflinePageUtils::IsOfflinePage(browser_context_, offline_url);
}
void OfflinePageBridge::NotifyIfDoneLoading() const {
if (!offline_page_model_->is_loaded())
return;
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = weak_java_ref_.get(env);
if (obj.is_null())
return;
Java_OfflinePageBridge_offlinePageModelLoaded(env, obj.obj());
}
ScopedJavaLocalRef<jobject> OfflinePageBridge::CreateOfflinePageItem(
JNIEnv* env,
const OfflinePageItem& offline_page) const {
return Java_OfflinePageBridge_createOfflinePageItem(
env, ConvertUTF8ToJavaString(env, offline_page.url.spec()).obj(),
offline_page.bookmark_id,
ConvertUTF8ToJavaString(env, offline_page.GetOfflineURL().spec()).obj(),
offline_page.file_size,
offline_page.creation_time.ToJavaTime(),
offline_page.access_count,
offline_page.last_access_time.ToJavaTime());
}
static jlong Init(JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& j_profile) {
return reinterpret_cast<jlong>(new OfflinePageBridge(
env, obj, ProfileAndroid::FromProfileAndroid(j_profile)));
}
bool RegisterOfflinePageBridge(JNIEnv* env) {
return RegisterNativesImpl(env);
}
} // namespace android
} // namespace offline_pages