This source file includes following definitions.
- ConvertBookmarkNode
- ConvertJLongObjectToPrimitive
- ConvertJBooleanObjectToPrimitive
- ConvertJlongToTime
- ConvertJIntegerToJint
- ConvertJStringArrayToString16Array
- ParseAndMaybeAppendScheme
- GetChildFolderByTitle
- Run
- RunOnUIThread
- id_to_delete_
- Run
- RunOnUIThread
- BookmarkNodeRemoved
- Run
- RunOnUIThread
- id_to_update_
- Run
- RunOnUIThread
- BookmarkNodeChanged
- Run
- RunOnUIThread
- Run
- RunOnUIThread
- Run
- RunOnUIThread
- Run
- RunOnUIThread
- ConvertFolderSubtree
- Run
- RunOnUIThread
- Run
- RunOnUIThread
- cancelable_consumer_
- service
- cancelable_consumer
- cancelable_tracker_
- profile
- cancelable_tracker
- Run
- OnFaviconRetrieved
- Run
- OnBookmarkInserted
- result_
- Run
- OnBookmarksQueried
- result_
- Run
- OnBookmarksUpdated
- result_
- Run
- OnBookmarksRemoved
- result_
- Run
- OnHistoryRemoved
- profile_
- BuildSearchRow
- Run
- MakeRequestOnUIThread
- OnSearchTermInserted
- result_
- Run
- OnSearchTermsQueried
- result_
- Run
- MakeRequestOnUIThread
- OnSearchTermsUpdated
- result_
- Run
- OnSearchTermsDeleted
- FillBookmarkRow
- FillSearchRow
- Init
- RegisterChromeBrowserProvider
- handling_extensive_changes_
- Destroy
- AddBookmark
- RemoveBookmark
- UpdateBookmark
- AddBookmarkFromAPI
- QueryBookmarkFromAPI
- UpdateBookmarkFromAPI
- RemoveBookmarkFromAPI
- RemoveHistoryFromAPI
- AddSearchTermFromAPI
- QuerySearchTermFromAPI
- UpdateSearchTermFromAPI
- RemoveSearchTermFromAPI
- BookmarkNodeExists
- CreateBookmarksFolderOnce
- GetAllBookmarkFolders
- RemoveAllBookmarks
- GetBookmarkNode
- GetMobileBookmarksFolder
- IsBookmarkInMobileBookmarksBranch
- GetFaviconOrTouchIcon
- GetThumbnail
- ExtensiveBookmarkChangesBeginning
- ExtensiveBookmarkChangesEnded
- BookmarkModelChanged
- Observe
#include "chrome/browser/android/provider/chrome_browser_provider.h"
#include <list>
#include <utility>
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/logging.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/cancelable_task_tracker.h"
#include "base/time/time.h"
#include "chrome/browser/android/provider/blocking_ui_thread_async_request.h"
#include "chrome/browser/android/provider/bookmark_model_observer_task.h"
#include "chrome/browser/android/provider/run_on_ui_thread_blocking.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/favicon/favicon_service.h"
#include "chrome/browser/favicon/favicon_service_factory.h"
#include "chrome/browser/history/android/android_history_types.h"
#include "chrome/browser/history/android/sqlite_cursor.h"
#include "chrome/browser/history/top_sites.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_service.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "grit/generated_resources.h"
#include "jni/ChromeBrowserProvider_jni.h"
#include "sql/statement.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/layout.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/favicon_size.h"
using base::android::AttachCurrentThread;
using base::android::CheckException;
using base::android::ClearException;
using base::android::ConvertJavaStringToUTF16;
using base::android::ConvertJavaStringToUTF8;
using base::android::ConvertUTF8ToJavaString;
using base::android::ConvertUTF16ToJavaString;
using base::android::GetClass;
using base::android::MethodID;
using base::android::JavaRef;
using base::android::ScopedJavaGlobalRef;
using base::android::ScopedJavaLocalRef;
using content::BrowserThread;
namespace {
const char kDefaultUrlScheme[] = "http://";
const int64 kInvalidContentProviderId = 0;
const int64 kInvalidBookmarkId = -1;
void ConvertBookmarkNode(
const BookmarkNode* node,
const JavaRef<jobject>& parent_node,
ScopedJavaGlobalRef<jobject>* jnode) {
DCHECK(jnode);
if (!node)
return;
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jstring> url;
if (node->is_url())
url.Reset(ConvertUTF8ToJavaString(env, node->url().spec()));
ScopedJavaLocalRef<jstring> title(
ConvertUTF16ToJavaString(env, node->GetTitle()));
jnode->Reset(
Java_BookmarkNode_create(
env, node->id(), (jint) node->type(), title.obj(), url.obj(),
parent_node.obj()));
}
jlong ConvertJLongObjectToPrimitive(JNIEnv* env, jobject long_obj) {
ScopedJavaLocalRef<jclass> jlong_clazz = GetClass(env, "java/lang/Long");
jmethodID long_value = MethodID::Get<MethodID::TYPE_INSTANCE>(
env, jlong_clazz.obj(), "longValue", "()J");
return env->CallLongMethod(long_obj, long_value, NULL);
}
jboolean ConvertJBooleanObjectToPrimitive(JNIEnv* env, jobject boolean_object) {
ScopedJavaLocalRef<jclass> jboolean_clazz =
GetClass(env, "java/lang/Boolean");
jmethodID boolean_value = MethodID::Get<MethodID::TYPE_INSTANCE>(
env, jboolean_clazz.obj(), "booleanValue", "()Z");
return env->CallBooleanMethod(boolean_object, boolean_value, NULL);
}
base::Time ConvertJlongToTime(jlong value) {
return base::Time::UnixEpoch() +
base::TimeDelta::FromMilliseconds((int64)value);
}
jint ConvertJIntegerToJint(JNIEnv* env, jobject integer_obj) {
ScopedJavaLocalRef<jclass> jinteger_clazz =
GetClass(env, "java/lang/Integer");
jmethodID int_value = MethodID::Get<MethodID::TYPE_INSTANCE>(
env, jinteger_clazz.obj(), "intValue", "()I");
return env->CallIntMethod(integer_obj, int_value, NULL);
}
std::vector<base::string16> ConvertJStringArrayToString16Array(
JNIEnv* env,
jobjectArray array) {
std::vector<base::string16> results;
if (array) {
jsize len = env->GetArrayLength(array);
for (int i = 0; i < len; i++) {
results.push_back(ConvertJavaStringToUTF16(env,
static_cast<jstring>(env->GetObjectArrayElement(array, i))));
}
}
return results;
}
GURL ParseAndMaybeAppendScheme(const base::string16& url,
const char* default_scheme) {
GURL gurl(url);
if (!gurl.is_valid() && !gurl.has_scheme()) {
base::string16 refined_url(base::ASCIIToUTF16(default_scheme));
refined_url.append(url);
gurl = GURL(refined_url);
}
return gurl;
}
const BookmarkNode* GetChildFolderByTitle(const BookmarkNode* parent,
const base::string16& title) {
for (int i = 0; i < parent->child_count(); ++i) {
if (parent->GetChild(i)->is_folder() &&
parent->GetChild(i)->GetTitle() == title) {
return parent->GetChild(i);
}
}
return NULL;
}
class AddBookmarkTask : public BookmarkModelTask {
public:
explicit AddBookmarkTask(BookmarkModel* model) : BookmarkModelTask(model) {}
int64 Run(const base::string16& title,
const base::string16& url,
const bool is_folder,
const int64 parent_id) {
int64 result = kInvalidBookmarkId;
RunOnUIThreadBlocking::Run(
base::Bind(&AddBookmarkTask::RunOnUIThread,
model(), title, url, is_folder, parent_id, &result));
return result;
}
static void RunOnUIThread(BookmarkModel* model,
const base::string16& title,
const base::string16& url,
const bool is_folder,
const int64 parent_id,
int64* result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(result);
GURL gurl = ParseAndMaybeAppendScheme(url, kDefaultUrlScheme);
const BookmarkNode* node = model->GetMostRecentlyAddedNodeForURL(gurl);
if (!node) {
const BookmarkNode* parent_node = NULL;
if (parent_id >= 0)
parent_node = model->GetNodeByID(parent_id);
if (!parent_node)
parent_node = model->bookmark_bar_node();
if (is_folder)
node = model->AddFolder(parent_node, parent_node->child_count(), title);
else
node = model->AddURL(parent_node, 0, title, gurl);
}
*result = node ? node ->id() : kInvalidBookmarkId;
}
private:
DISALLOW_COPY_AND_ASSIGN(AddBookmarkTask);
};
class RemoveBookmarkTask : public BookmarkModelObserverTask {
public:
explicit RemoveBookmarkTask(BookmarkModel* model)
: BookmarkModelObserverTask(model),
deleted_(0),
id_to_delete_(kInvalidBookmarkId) {}
virtual ~RemoveBookmarkTask() {}
int Run(const int64 id) {
id_to_delete_ = id;
RunOnUIThreadBlocking::Run(
base::Bind(&RemoveBookmarkTask::RunOnUIThread, model(), id));
return deleted_;
}
static void RunOnUIThread(BookmarkModel* model, const int64 id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
const BookmarkNode* node = model->GetNodeByID(id);
if (node && node->parent()) {
const BookmarkNode* parent_node = node->parent();
model->Remove(parent_node, parent_node->GetIndexOf(node));
}
}
virtual void BookmarkNodeRemoved(BookmarkModel* bookmark_model,
const BookmarkNode* parent,
int old_index,
const BookmarkNode* node) OVERRIDE {
if (bookmark_model == model() && node->id() == id_to_delete_)
++deleted_;
}
private:
int deleted_;
int64 id_to_delete_;
DISALLOW_COPY_AND_ASSIGN(RemoveBookmarkTask);
};
class RemoveAllBookmarksTask : public BookmarkModelObserverTask {
public:
explicit RemoveAllBookmarksTask(BookmarkModel* model)
: BookmarkModelObserverTask(model) {}
virtual ~RemoveAllBookmarksTask() {}
void Run() {
RunOnUIThreadBlocking::Run(
base::Bind(&RemoveAllBookmarksTask::RunOnUIThread, model()));
}
static void RunOnUIThread(BookmarkModel* model) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
model->RemoveAll();
}
private:
DISALLOW_COPY_AND_ASSIGN(RemoveAllBookmarksTask);
};
class UpdateBookmarkTask : public BookmarkModelObserverTask {
public:
explicit UpdateBookmarkTask(BookmarkModel* model)
: BookmarkModelObserverTask(model),
updated_(0),
id_to_update_(kInvalidBookmarkId){}
virtual ~UpdateBookmarkTask() {}
int Run(const int64 id,
const base::string16& title,
const base::string16& url,
const int64 parent_id) {
id_to_update_ = id;
RunOnUIThreadBlocking::Run(
base::Bind(&UpdateBookmarkTask::RunOnUIThread,
model(), id, title, url, parent_id));
return updated_;
}
static void RunOnUIThread(BookmarkModel* model,
const int64 id,
const base::string16& title,
const base::string16& url,
const int64 parent_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
const BookmarkNode* node = model->GetNodeByID(id);
if (node) {
if (node->GetTitle() != title)
model->SetTitle(node, title);
if (node->type() == BookmarkNode::URL) {
GURL bookmark_url = ParseAndMaybeAppendScheme(url, kDefaultUrlScheme);
if (bookmark_url != node->url())
model->SetURL(node, bookmark_url);
}
if (parent_id >= 0 &&
(!node->parent() || parent_id != node->parent()->id())) {
const BookmarkNode* new_parent = model->GetNodeByID(parent_id);
if (new_parent)
model->Move(node, new_parent, 0);
}
}
}
virtual void BookmarkNodeChanged(BookmarkModel* bookmark_model,
const BookmarkNode* node) OVERRIDE {
if (bookmark_model == model() && node->id() == id_to_update_)
++updated_;
}
private:
int updated_;
int64 id_to_update_;
DISALLOW_COPY_AND_ASSIGN(UpdateBookmarkTask);
};
class BookmarkNodeExistsTask : public BookmarkModelTask {
public:
explicit BookmarkNodeExistsTask(BookmarkModel* model)
: BookmarkModelTask(model) {
}
bool Run(const int64 id) {
bool result = false;
RunOnUIThreadBlocking::Run(
base::Bind(&BookmarkNodeExistsTask::RunOnUIThread,
model(), id, &result));
return result;
}
static void RunOnUIThread(BookmarkModel* model,
const int64 id,
bool* result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(result);
*result = model->GetNodeByID(id) != NULL;
}
private:
DISALLOW_COPY_AND_ASSIGN(BookmarkNodeExistsTask);
};
class IsInMobileBookmarksBranchTask : public BookmarkModelTask {
public:
explicit IsInMobileBookmarksBranchTask(BookmarkModel* model)
: BookmarkModelTask(model) {}
bool Run(const int64 id) {
bool result = false;
RunOnUIThreadBlocking::Run(
base::Bind(&IsInMobileBookmarksBranchTask::RunOnUIThread,
model(), id, &result));
return result;
}
static void RunOnUIThread(BookmarkModel* model,
const int64 id,
bool *result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(result);
const BookmarkNode* node = model->GetNodeByID(id);
const BookmarkNode* mobile_node = model->mobile_node();
while (node && node != mobile_node)
node = node->parent();
*result = node == mobile_node;
}
private:
DISALLOW_COPY_AND_ASSIGN(IsInMobileBookmarksBranchTask);
};
class CreateBookmarksFolderOnceTask : public BookmarkModelTask {
public:
explicit CreateBookmarksFolderOnceTask(BookmarkModel* model)
: BookmarkModelTask(model) {}
int64 Run(const base::string16& title, const int64 parent_id) {
int64 result = kInvalidBookmarkId;
RunOnUIThreadBlocking::Run(
base::Bind(&CreateBookmarksFolderOnceTask::RunOnUIThread,
model(), title, parent_id, &result));
return result;
}
static void RunOnUIThread(BookmarkModel* model,
const base::string16& title,
const int64 parent_id,
int64* result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(result);
const BookmarkNode* parent = parent_id >= 0 ?
model->GetNodeByID(parent_id) : model->mobile_node();
DCHECK(parent);
bool in_mobile_bookmarks;
IsInMobileBookmarksBranchTask::RunOnUIThread(model, parent->id(),
&in_mobile_bookmarks);
if (!in_mobile_bookmarks) {
*result = kInvalidBookmarkId;
return;
}
const BookmarkNode* node = GetChildFolderByTitle(parent, title);
if (node) {
*result = node->id();
return;
}
AddBookmarkTask::RunOnUIThread(model, title, base::string16(), true,
parent->id(), result);
}
private:
DISALLOW_COPY_AND_ASSIGN(CreateBookmarksFolderOnceTask);
};
class GetAllBookmarkFoldersTask : public BookmarkModelTask {
public:
explicit GetAllBookmarkFoldersTask(BookmarkModel* model)
: BookmarkModelTask(model) {
}
void Run(ScopedJavaGlobalRef<jobject>* jroot) {
RunOnUIThreadBlocking::Run(
base::Bind(&GetAllBookmarkFoldersTask::RunOnUIThread, model(), jroot));
}
static void RunOnUIThread(BookmarkModel* model,
ScopedJavaGlobalRef<jobject>* jroot) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
const BookmarkNode* root = model->root_node();
if (!root || !root->is_folder())
return;
ConvertFolderSubtree(AttachCurrentThread(), root,
ScopedJavaLocalRef<jobject>(), jroot);
}
private:
static void ConvertFolderSubtree(JNIEnv* env,
const BookmarkNode* node,
const JavaRef<jobject>& parent_folder,
ScopedJavaGlobalRef<jobject>* jfolder) {
DCHECK(node);
DCHECK(node->is_folder());
DCHECK(jfolder);
ConvertBookmarkNode(node, parent_folder, jfolder);
for (int i = 0; i < node->child_count(); ++i) {
const BookmarkNode* child = node->GetChild(i);
if (child->is_folder()) {
ScopedJavaGlobalRef<jobject> jchild;
ConvertFolderSubtree(env, child, *jfolder, &jchild);
Java_BookmarkNode_addChild(env, jfolder->obj(), jchild.obj());
if (ClearException(env)) {
LOG(WARNING) << "Java exception while adding child node.";
return;
}
}
}
}
DISALLOW_COPY_AND_ASSIGN(GetAllBookmarkFoldersTask);
};
class GetBookmarkNodeTask : public BookmarkModelTask {
public:
explicit GetBookmarkNodeTask(BookmarkModel* model)
: BookmarkModelTask(model) {
}
void Run(const int64 id,
bool get_parent,
bool get_children,
ScopedJavaGlobalRef<jobject>* jnode) {
return RunOnUIThreadBlocking::Run(
base::Bind(&GetBookmarkNodeTask::RunOnUIThread,
model(), id, get_parent, get_children, jnode));
}
static void RunOnUIThread(BookmarkModel* model,
const int64 id,
bool get_parent,
bool get_children,
ScopedJavaGlobalRef<jobject>* jnode) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
const BookmarkNode* node = model->GetNodeByID(id);
if (!node || !jnode)
return;
ScopedJavaGlobalRef<jobject> jparent;
if (get_parent) {
ConvertBookmarkNode(node->parent(), ScopedJavaLocalRef<jobject>(),
&jparent);
}
ConvertBookmarkNode(node, jparent, jnode);
JNIEnv* env = AttachCurrentThread();
if (!jparent.is_null()) {
Java_BookmarkNode_addChild(env, jparent.obj(), jnode->obj());
if (ClearException(env)) {
LOG(WARNING) << "Java exception while adding child node.";
return;
}
}
if (get_children) {
for (int i = 0; i < node->child_count(); ++i) {
ScopedJavaGlobalRef<jobject> jchild;
ConvertBookmarkNode(node->GetChild(i), *jnode, &jchild);
Java_BookmarkNode_addChild(env, jnode->obj(), jchild.obj());
if (ClearException(env)) {
LOG(WARNING) << "Java exception while adding child node.";
return;
}
}
}
}
private:
DISALLOW_COPY_AND_ASSIGN(GetBookmarkNodeTask);
};
class GetMobileBookmarksNodeTask : public BookmarkModelTask {
public:
explicit GetMobileBookmarksNodeTask(BookmarkModel* model)
: BookmarkModelTask(model) {}
const BookmarkNode* Run() {
const BookmarkNode* result = NULL;
RunOnUIThreadBlocking::Run(
base::Bind(&GetMobileBookmarksNodeTask::RunOnUIThread,
model(), &result));
return result;
}
static void RunOnUIThread(BookmarkModel* model, const BookmarkNode** result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(result);
*result = model->mobile_node();
}
private:
DISALLOW_COPY_AND_ASSIGN(GetMobileBookmarksNodeTask);
};
template <typename Service>
class AsyncServiceRequest : protected BlockingUIThreadAsyncRequest {
public:
AsyncServiceRequest(Service* service,
CancelableRequestConsumer* cancelable_consumer)
: service_(service), cancelable_consumer_(cancelable_consumer) {}
Service* service() const { return service_; }
CancelableRequestConsumer* cancelable_consumer() const {
return cancelable_consumer_;
}
private:
Service* service_;
CancelableRequestConsumer* cancelable_consumer_;
DISALLOW_COPY_AND_ASSIGN(AsyncServiceRequest);
};
class FaviconServiceTask : public AsyncServiceRequest<FaviconService> {
public:
FaviconServiceTask(FaviconService* service,
Profile* profile,
CancelableRequestConsumer* cancelable_consumer,
base::CancelableTaskTracker* cancelable_tracker)
: AsyncServiceRequest<FaviconService>(service, cancelable_consumer),
profile_(profile),
cancelable_tracker_(cancelable_tracker) {}
Profile* profile() const { return profile_; }
base::CancelableTaskTracker* cancelable_tracker() const {
return cancelable_tracker_;
}
private:
Profile* profile_;
base::CancelableTaskTracker* cancelable_tracker_;
DISALLOW_COPY_AND_ASSIGN(FaviconServiceTask);
};
class BookmarkIconFetchTask : public FaviconServiceTask {
public:
BookmarkIconFetchTask(FaviconService* favicon_service,
Profile* profile,
CancelableRequestConsumer* cancelable_consumer,
base::CancelableTaskTracker* cancelable_tracker)
: FaviconServiceTask(favicon_service,
profile,
cancelable_consumer,
cancelable_tracker) {}
chrome::FaviconBitmapResult Run(const GURL& url) {
RunAsyncRequestOnUIThreadBlocking(
base::Bind(&FaviconService::GetRawFaviconForURL,
base::Unretained(service()),
FaviconService::FaviconForURLParams(
url,
chrome::FAVICON | chrome::TOUCH_ICON,
gfx::kFaviconSize),
ResourceBundle::GetSharedInstance().GetMaxScaleFactor(),
base::Bind(
&BookmarkIconFetchTask::OnFaviconRetrieved,
base::Unretained(this)),
cancelable_tracker()));
return result_;
}
private:
void OnFaviconRetrieved(const chrome::FaviconBitmapResult& bitmap_result) {
result_ = bitmap_result;
RequestCompleted();
}
chrome::FaviconBitmapResult result_;
DISALLOW_COPY_AND_ASSIGN(BookmarkIconFetchTask);
};
class HistoryProviderTask
: public AsyncServiceRequest<AndroidHistoryProviderService> {
public:
HistoryProviderTask(AndroidHistoryProviderService* service,
CancelableRequestConsumer* cancelable_consumer)
: AsyncServiceRequest<AndroidHistoryProviderService>
(service, cancelable_consumer) {}
private:
DISALLOW_COPY_AND_ASSIGN(HistoryProviderTask);
};
class AddBookmarkFromAPITask : public HistoryProviderTask {
public:
AddBookmarkFromAPITask(AndroidHistoryProviderService* service,
CancelableRequestConsumer* cancelable_consumer)
: HistoryProviderTask(service, cancelable_consumer) {}
history::URLID Run(const history::HistoryAndBookmarkRow& row) {
RunAsyncRequestOnUIThreadBlocking(
base::Bind(&AndroidHistoryProviderService::InsertHistoryAndBookmark,
base::Unretained(service()), row, cancelable_consumer(),
base::Bind(&AddBookmarkFromAPITask::OnBookmarkInserted,
base::Unretained(this))));
return result_;
}
private:
void OnBookmarkInserted(AndroidHistoryProviderService::Handle handle,
bool succeeded,
history::URLID id) {
result_ = id;
RequestCompleted();
}
history::URLID result_;
DISALLOW_COPY_AND_ASSIGN(AddBookmarkFromAPITask);
};
class QueryBookmarksFromAPITask : public HistoryProviderTask {
public:
QueryBookmarksFromAPITask(AndroidHistoryProviderService* service,
CancelableRequestConsumer* cancelable_consumer)
: HistoryProviderTask(service, cancelable_consumer),
result_(NULL) {}
history::AndroidStatement* Run(
const std::vector<history::HistoryAndBookmarkRow::ColumnID>& projections,
const std::string& selection,
const std::vector<base::string16>& selection_args,
const std::string& sort_order) {
RunAsyncRequestOnUIThreadBlocking(
base::Bind(&AndroidHistoryProviderService::QueryHistoryAndBookmarks,
base::Unretained(service()), projections, selection,
selection_args, sort_order, cancelable_consumer(),
base::Bind(&QueryBookmarksFromAPITask::OnBookmarksQueried,
base::Unretained(this))));
return result_;
}
private:
void OnBookmarksQueried(AndroidHistoryProviderService::Handle handle,
bool succeeded,
history::AndroidStatement* statement) {
result_ = statement;
RequestCompleted();
}
history::AndroidStatement* result_;
DISALLOW_COPY_AND_ASSIGN(QueryBookmarksFromAPITask);
};
class UpdateBookmarksFromAPITask : public HistoryProviderTask {
public:
UpdateBookmarksFromAPITask(AndroidHistoryProviderService* service,
CancelableRequestConsumer* cancelable_consumer)
: HistoryProviderTask(service, cancelable_consumer),
result_(0) {}
int Run(const history::HistoryAndBookmarkRow& row,
const std::string& selection,
const std::vector<base::string16>& selection_args) {
RunAsyncRequestOnUIThreadBlocking(
base::Bind(&AndroidHistoryProviderService::UpdateHistoryAndBookmarks,
base::Unretained(service()), row, selection,
selection_args, cancelable_consumer(),
base::Bind(&UpdateBookmarksFromAPITask::OnBookmarksUpdated,
base::Unretained(this))));
return result_;
}
private:
void OnBookmarksUpdated(AndroidHistoryProviderService::Handle handle,
bool succeeded,
int updated_row_count) {
result_ = updated_row_count;
RequestCompleted();
}
int result_;
DISALLOW_COPY_AND_ASSIGN(UpdateBookmarksFromAPITask);
};
class RemoveBookmarksFromAPITask : public HistoryProviderTask {
public:
RemoveBookmarksFromAPITask(AndroidHistoryProviderService* service,
CancelableRequestConsumer* cancelable_consumer)
: HistoryProviderTask(service, cancelable_consumer),
result_(0) {}
int Run(const std::string& selection,
const std::vector<base::string16>& selection_args) {
RunAsyncRequestOnUIThreadBlocking(
base::Bind(&AndroidHistoryProviderService::DeleteHistoryAndBookmarks,
base::Unretained(service()), selection, selection_args,
cancelable_consumer(),
base::Bind(&RemoveBookmarksFromAPITask::OnBookmarksRemoved,
base::Unretained(this))));
return result_;
}
private:
void OnBookmarksRemoved(AndroidHistoryProviderService::Handle handle,
bool succeeded,
int removed_row_count) {
result_ = removed_row_count;
RequestCompleted();
}
int result_;
DISALLOW_COPY_AND_ASSIGN(RemoveBookmarksFromAPITask);
};
class RemoveHistoryFromAPITask : public HistoryProviderTask {
public:
RemoveHistoryFromAPITask(AndroidHistoryProviderService* service,
CancelableRequestConsumer* cancelable_consumer)
: HistoryProviderTask(service, cancelable_consumer),
result_(0) {}
int Run(const std::string& selection,
const std::vector<base::string16>& selection_args) {
RunAsyncRequestOnUIThreadBlocking(
base::Bind(&AndroidHistoryProviderService::DeleteHistory,
base::Unretained(service()), selection,
selection_args, cancelable_consumer(),
base::Bind(&RemoveHistoryFromAPITask::OnHistoryRemoved,
base::Unretained(this))));
return result_;
}
private:
void OnHistoryRemoved(AndroidHistoryProviderService::Handle handle,
bool succeeded,
int removed_row_count) {
result_ = removed_row_count;
RequestCompleted();
}
int result_;
DISALLOW_COPY_AND_ASSIGN(RemoveHistoryFromAPITask);
};
class SearchTermTask : public HistoryProviderTask {
protected:
SearchTermTask(AndroidHistoryProviderService* service,
CancelableRequestConsumer* cancelable_consumer,
Profile* profile)
: HistoryProviderTask(service, cancelable_consumer),
profile_(profile) {}
void BuildSearchRow(history::SearchRow* row) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
TemplateURLService* template_service =
TemplateURLServiceFactory::GetForProfile(profile_);
template_service->Load();
const TemplateURL* search_engine =
template_service->GetDefaultSearchProvider();
if (search_engine) {
const TemplateURLRef* search_url = &search_engine->url_ref();
TemplateURLRef::SearchTermsArgs search_terms_args(row->search_term());
search_terms_args.append_extra_query_params = true;
std::string url = search_url->ReplaceSearchTerms(search_terms_args);
if (!url.empty()) {
row->set_url(GURL(url));
row->set_template_url_id(search_engine->id());
}
}
}
private:
Profile* profile_;
DISALLOW_COPY_AND_ASSIGN(SearchTermTask);
};
class AddSearchTermFromAPITask : public SearchTermTask {
public:
AddSearchTermFromAPITask(AndroidHistoryProviderService* service,
CancelableRequestConsumer* cancelable_consumer,
Profile* profile)
: SearchTermTask(service, cancelable_consumer, profile) {}
history::URLID Run(const history::SearchRow& row) {
RunAsyncRequestOnUIThreadBlocking(
base::Bind(&AddSearchTermFromAPITask::MakeRequestOnUIThread,
base::Unretained(this), row));
return result_;
}
private:
void MakeRequestOnUIThread(const history::SearchRow& row) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
history::SearchRow internal_row = row;
BuildSearchRow(&internal_row);
service()->InsertSearchTerm(internal_row, cancelable_consumer(),
base::Bind(&AddSearchTermFromAPITask::OnSearchTermInserted,
base::Unretained(this)));
}
void OnSearchTermInserted(AndroidHistoryProviderService::Handle handle,
bool succeeded,
history::URLID id) {
result_ = id;
RequestCompleted();
}
history::URLID result_;
DISALLOW_COPY_AND_ASSIGN(AddSearchTermFromAPITask);
};
class QuerySearchTermsFromAPITask : public SearchTermTask {
public:
QuerySearchTermsFromAPITask(AndroidHistoryProviderService* service,
CancelableRequestConsumer* cancelable_consumer,
Profile* profile)
: SearchTermTask(service, cancelable_consumer, profile),
result_(NULL) {}
history::AndroidStatement* Run(
const std::vector<history::SearchRow::ColumnID>& projections,
const std::string& selection,
const std::vector<base::string16>& selection_args,
const std::string& sort_order) {
RunAsyncRequestOnUIThreadBlocking(
base::Bind(&AndroidHistoryProviderService::QuerySearchTerms,
base::Unretained(service()), projections, selection,
selection_args, sort_order, cancelable_consumer(),
base::Bind(
&QuerySearchTermsFromAPITask::OnSearchTermsQueried,
base::Unretained(this))));
return result_;
}
private:
void OnSearchTermsQueried(AndroidHistoryProviderService::Handle handle,
bool succeeded,
history::AndroidStatement* statement) {
result_ = statement;
RequestCompleted();
}
history::AndroidStatement* result_;
DISALLOW_COPY_AND_ASSIGN(QuerySearchTermsFromAPITask);
};
class UpdateSearchTermsFromAPITask : public SearchTermTask {
public:
UpdateSearchTermsFromAPITask(AndroidHistoryProviderService* service,
CancelableRequestConsumer* cancelable_consumer,
Profile* profile)
: SearchTermTask(service, cancelable_consumer, profile),
result_(0) {}
int Run(const history::SearchRow& row,
const std::string& selection,
const std::vector<base::string16>& selection_args) {
RunAsyncRequestOnUIThreadBlocking(
base::Bind(&UpdateSearchTermsFromAPITask::MakeRequestOnUIThread,
base::Unretained(this), row, selection, selection_args));
return result_;
}
private:
void MakeRequestOnUIThread(
const history::SearchRow& row,
const std::string& selection,
const std::vector<base::string16>& selection_args) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
history::SearchRow internal_row = row;
BuildSearchRow(&internal_row);
service()->UpdateSearchTerms(
internal_row,
selection,
selection_args,
cancelable_consumer(),
base::Bind(&UpdateSearchTermsFromAPITask::OnSearchTermsUpdated,
base::Unretained(this)));
}
void OnSearchTermsUpdated(AndroidHistoryProviderService::Handle handle,
bool succeeded,
int updated_row_count) {
result_ = updated_row_count;
RequestCompleted();
}
int result_;
DISALLOW_COPY_AND_ASSIGN(UpdateSearchTermsFromAPITask);
};
class RemoveSearchTermsFromAPITask : public SearchTermTask {
public:
RemoveSearchTermsFromAPITask(AndroidHistoryProviderService* service,
CancelableRequestConsumer* cancelable_consumer,
Profile* profile)
: SearchTermTask(service, cancelable_consumer, profile), result_() {}
int Run(const std::string& selection,
const std::vector<base::string16>& selection_args) {
RunAsyncRequestOnUIThreadBlocking(
base::Bind(&AndroidHistoryProviderService::DeleteSearchTerms,
base::Unretained(service()), selection, selection_args,
cancelable_consumer(),
base::Bind(
&RemoveSearchTermsFromAPITask::OnSearchTermsDeleted,
base::Unretained(this))));
return result_;
}
private:
void OnSearchTermsDeleted(AndroidHistoryProviderService::Handle handle,
bool succeeded,
int deleted_row_count) {
result_ = deleted_row_count;
RequestCompleted();
}
int result_;
DISALLOW_COPY_AND_ASSIGN(RemoveSearchTermsFromAPITask);
};
void FillBookmarkRow(JNIEnv* env,
jobject obj,
jstring url,
jobject created,
jobject isBookmark,
jobject date,
jbyteArray favicon,
jstring title,
jobject visits,
jlong parent_id,
history::HistoryAndBookmarkRow* row,
BookmarkModel* model) {
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
if (url) {
base::string16 raw_url = ConvertJavaStringToUTF16(env, url);
GURL gurl = ParseAndMaybeAppendScheme(raw_url, kDefaultUrlScheme);
row->set_url(gurl);
row->set_raw_url(base::UTF16ToUTF8(raw_url));
}
if (created)
row->set_created(ConvertJlongToTime(
ConvertJLongObjectToPrimitive(env, created)));
if (isBookmark)
row->set_is_bookmark(ConvertJBooleanObjectToPrimitive(env, isBookmark));
if (date)
row->set_last_visit_time(ConvertJlongToTime(ConvertJLongObjectToPrimitive(
env, date)));
if (favicon) {
std::vector<uint8> bytes;
base::android::JavaByteArrayToByteVector(env, favicon, &bytes);
row->set_favicon(base::RefCountedBytes::TakeVector(&bytes));
}
if (title)
row->set_title(ConvertJavaStringToUTF16(env, title));
if (visits)
row->set_visit_count(ConvertJIntegerToJint(env, visits));
IsInMobileBookmarksBranchTask task(model);
if (task.Run(parent_id))
row->set_parent_id(parent_id);
}
void FillSearchRow(JNIEnv* env,
jobject obj,
jstring search_term,
jobject date,
history::SearchRow* row) {
if (search_term)
row->set_search_term(ConvertJavaStringToUTF16(env, search_term));
if (date)
row->set_search_time(ConvertJlongToTime(ConvertJLongObjectToPrimitive(
env, date)));
}
}
static jlong Init(JNIEnv* env, jobject obj) {
ChromeBrowserProvider* provider = new ChromeBrowserProvider(env, obj);
return reinterpret_cast<intptr_t>(provider);
}
bool ChromeBrowserProvider::RegisterChromeBrowserProvider(JNIEnv* env) {
return RegisterNativesImpl(env);
}
ChromeBrowserProvider::ChromeBrowserProvider(JNIEnv* env, jobject obj)
: weak_java_provider_(env, obj),
handling_extensive_changes_(false) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
profile_ = g_browser_process->profile_manager()->GetLastUsedProfile();
bookmark_model_ = BookmarkModelFactory::GetForProfile(profile_);
top_sites_ = profile_->GetTopSites();
service_.reset(new AndroidHistoryProviderService(profile_));
favicon_service_.reset(FaviconServiceFactory::GetForProfile(profile_,
Profile::EXPLICIT_ACCESS));
bookmark_model_->AddObserver(this);
notification_registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URL_VISITED,
content::NotificationService::AllSources());
notification_registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED,
content::NotificationService::AllSources());
notification_registrar_.Add(this,
chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED,
content::NotificationService::AllSources());
TemplateURLService* template_service =
TemplateURLServiceFactory::GetForProfile(profile_);
if (!template_service->loaded())
template_service->Load();
}
ChromeBrowserProvider::~ChromeBrowserProvider() {
bookmark_model_->RemoveObserver(this);
}
void ChromeBrowserProvider::Destroy(JNIEnv*, jobject) {
delete this;
}
jlong ChromeBrowserProvider::AddBookmark(JNIEnv* env,
jobject,
jstring jurl,
jstring jtitle,
jboolean is_folder,
jlong parent_id) {
base::string16 url;
if (jurl)
url = ConvertJavaStringToUTF16(env, jurl);
base::string16 title = ConvertJavaStringToUTF16(env, jtitle);
AddBookmarkTask task(bookmark_model_);
return task.Run(title, url, is_folder, parent_id);
}
jint ChromeBrowserProvider::RemoveBookmark(JNIEnv*, jobject, jlong id) {
RemoveBookmarkTask task(bookmark_model_);
return task.Run(id);
}
jint ChromeBrowserProvider::UpdateBookmark(JNIEnv* env,
jobject,
jlong id,
jstring jurl,
jstring jtitle,
jlong parent_id) {
base::string16 url;
if (jurl)
url = ConvertJavaStringToUTF16(env, jurl);
base::string16 title = ConvertJavaStringToUTF16(env, jtitle);
UpdateBookmarkTask task(bookmark_model_);
return task.Run(id, title, url, parent_id);
}
jlong ChromeBrowserProvider::AddBookmarkFromAPI(JNIEnv* env,
jobject obj,
jstring url,
jobject created,
jobject isBookmark,
jobject date,
jbyteArray favicon,
jstring title,
jobject visits,
jlong parent_id) {
DCHECK(url);
history::HistoryAndBookmarkRow row;
FillBookmarkRow(env, obj, url, created, isBookmark, date, favicon, title,
visits, parent_id, &row, bookmark_model_);
if (row.url().is_empty()) {
LOG(ERROR) << "Not a valid URL " << row.raw_url();
return kInvalidContentProviderId;
}
AddBookmarkFromAPITask task(service_.get(), &android_history_consumer_);
return task.Run(row);
}
ScopedJavaLocalRef<jobject> ChromeBrowserProvider::QueryBookmarkFromAPI(
JNIEnv* env,
jobject obj,
jobjectArray projection,
jstring selections,
jobjectArray selection_args,
jstring sort_order) {
std::vector<history::HistoryAndBookmarkRow::ColumnID> query_columns;
std::vector<std::string> columns_name;
if (projection) {
jsize len = env->GetArrayLength(projection);
for (int i = 0; i < len; i++) {
std::string name = ConvertJavaStringToUTF8(env, static_cast<jstring>(
env->GetObjectArrayElement(projection, i)));
history::HistoryAndBookmarkRow::ColumnID id =
history::HistoryAndBookmarkRow::GetColumnID(name);
if (id == history::HistoryAndBookmarkRow::COLUMN_END) {
continue;
}
query_columns.push_back(id);
columns_name.push_back(name);
}
}
std::vector<base::string16> where_args =
ConvertJStringArrayToString16Array(env, selection_args);
std::string where_clause;
if (selections) {
where_clause = ConvertJavaStringToUTF8(env, selections);
}
std::string sort_clause;
if (sort_order) {
sort_clause = ConvertJavaStringToUTF8(env, sort_order);
}
QueryBookmarksFromAPITask task(service_.get(), &android_history_consumer_);
history::AndroidStatement* statement = task.Run(
query_columns, where_clause, where_args, sort_clause);
if (!statement)
return ScopedJavaLocalRef<jobject>();
return SQLiteCursor::NewJavaSqliteCursor(env, columns_name, statement,
service_.get(), favicon_service_.get());
}
jint ChromeBrowserProvider::UpdateBookmarkFromAPI(JNIEnv* env,
jobject obj,
jstring url,
jobject created,
jobject isBookmark,
jobject date,
jbyteArray favicon,
jstring title,
jobject visits,
jlong parent_id,
jstring selections,
jobjectArray selection_args) {
history::HistoryAndBookmarkRow row;
FillBookmarkRow(env, obj, url, created, isBookmark, date, favicon, title,
visits, parent_id, &row, bookmark_model_);
std::vector<base::string16> where_args =
ConvertJStringArrayToString16Array(env, selection_args);
std::string where_clause;
if (selections)
where_clause = ConvertJavaStringToUTF8(env, selections);
UpdateBookmarksFromAPITask task(service_.get(), &android_history_consumer_);
return task.Run(row, where_clause, where_args);
}
jint ChromeBrowserProvider::RemoveBookmarkFromAPI(JNIEnv* env,
jobject obj,
jstring selections,
jobjectArray selection_args) {
std::vector<base::string16> where_args =
ConvertJStringArrayToString16Array(env, selection_args);
std::string where_clause;
if (selections)
where_clause = ConvertJavaStringToUTF8(env, selections);
RemoveBookmarksFromAPITask task(service_.get(), &android_history_consumer_);
return task.Run(where_clause, where_args);
}
jint ChromeBrowserProvider::RemoveHistoryFromAPI(JNIEnv* env,
jobject obj,
jstring selections,
jobjectArray selection_args) {
std::vector<base::string16> where_args =
ConvertJStringArrayToString16Array(env, selection_args);
std::string where_clause;
if (selections)
where_clause = ConvertJavaStringToUTF8(env, selections);
RemoveHistoryFromAPITask task(service_.get(), &android_history_consumer_);
return task.Run(where_clause, where_args);
}
jlong ChromeBrowserProvider::AddSearchTermFromAPI(JNIEnv* env,
jobject obj,
jstring search_term,
jobject date) {
DCHECK(search_term);
history::SearchRow row;
FillSearchRow(env, obj, search_term, date, &row);
if (row.search_term().empty()) {
LOG(ERROR) << "Search term is empty.";
return kInvalidContentProviderId;
}
AddSearchTermFromAPITask task(service_.get(), &android_history_consumer_,
profile_);
return task.Run(row);
}
ScopedJavaLocalRef<jobject> ChromeBrowserProvider::QuerySearchTermFromAPI(
JNIEnv* env,
jobject obj,
jobjectArray projection,
jstring selections,
jobjectArray selection_args,
jstring sort_order) {
std::vector<history::SearchRow::ColumnID> query_columns;
std::vector<std::string> columns_name;
if (projection) {
jsize len = env->GetArrayLength(projection);
for (int i = 0; i < len; i++) {
std::string name = ConvertJavaStringToUTF8(env, static_cast<jstring>(
env->GetObjectArrayElement(projection, i)));
history::SearchRow::ColumnID id =
history::SearchRow::GetColumnID(name);
if (id == history::SearchRow::COLUMN_END) {
LOG(ERROR) << "Can not find " << name;
return ScopedJavaLocalRef<jobject>();
}
query_columns.push_back(id);
columns_name.push_back(name);
}
}
std::vector<base::string16> where_args =
ConvertJStringArrayToString16Array(env, selection_args);
std::string where_clause;
if (selections) {
where_clause = ConvertJavaStringToUTF8(env, selections);
}
std::string sort_clause;
if (sort_order) {
sort_clause = ConvertJavaStringToUTF8(env, sort_order);
}
QuerySearchTermsFromAPITask task(service_.get(), &android_history_consumer_,
profile_);
history::AndroidStatement* statement = task.Run(
query_columns, where_clause, where_args, sort_clause);
if (!statement)
return ScopedJavaLocalRef<jobject>();
return SQLiteCursor::NewJavaSqliteCursor(env, columns_name, statement,
service_.get(), favicon_service_.get());
}
jint ChromeBrowserProvider::UpdateSearchTermFromAPI(
JNIEnv* env, jobject obj, jstring search_term, jobject date,
jstring selections, jobjectArray selection_args) {
history::SearchRow row;
FillSearchRow(env, obj, search_term, date, &row);
std::vector<base::string16> where_args = ConvertJStringArrayToString16Array(
env, selection_args);
std::string where_clause;
if (selections)
where_clause = ConvertJavaStringToUTF8(env, selections);
UpdateSearchTermsFromAPITask task(service_.get(), &android_history_consumer_,
profile_);
return task.Run(row, where_clause, where_args);
}
jint ChromeBrowserProvider::RemoveSearchTermFromAPI(
JNIEnv* env, jobject obj, jstring selections, jobjectArray selection_args) {
std::vector<base::string16> where_args =
ConvertJStringArrayToString16Array(env, selection_args);
std::string where_clause;
if (selections)
where_clause = ConvertJavaStringToUTF8(env, selections);
RemoveSearchTermsFromAPITask task(service_.get(), &android_history_consumer_,
profile_);
return task.Run(where_clause, where_args);
}
jboolean ChromeBrowserProvider::BookmarkNodeExists(
JNIEnv* env,
jobject obj,
jlong id) {
BookmarkNodeExistsTask task(bookmark_model_);
return task.Run(id);
}
jlong ChromeBrowserProvider::CreateBookmarksFolderOnce(
JNIEnv* env,
jobject obj,
jstring jtitle,
jlong parent_id) {
base::string16 title = ConvertJavaStringToUTF16(env, jtitle);
if (title.empty())
return kInvalidBookmarkId;
CreateBookmarksFolderOnceTask task(bookmark_model_);
return task.Run(title, parent_id);
}
ScopedJavaLocalRef<jobject> ChromeBrowserProvider::GetAllBookmarkFolders(
JNIEnv* env,
jobject obj) {
ScopedJavaGlobalRef<jobject> jroot;
GetAllBookmarkFoldersTask task(bookmark_model_);
task.Run(&jroot);
return ScopedJavaLocalRef<jobject>(jroot);
}
void ChromeBrowserProvider::RemoveAllBookmarks(JNIEnv* env, jobject obj) {
RemoveAllBookmarksTask task(bookmark_model_);
task.Run();
}
ScopedJavaLocalRef<jobject> ChromeBrowserProvider::GetBookmarkNode(
JNIEnv* env, jobject obj, jlong id, jboolean get_parent,
jboolean get_children) {
ScopedJavaGlobalRef<jobject> jnode;
GetBookmarkNodeTask task(bookmark_model_);
task.Run(id, get_parent, get_children, &jnode);
return ScopedJavaLocalRef<jobject>(jnode);
}
ScopedJavaLocalRef<jobject> ChromeBrowserProvider::GetMobileBookmarksFolder(
JNIEnv* env,
jobject obj) {
ScopedJavaGlobalRef<jobject> jnode;
GetMobileBookmarksNodeTask task(bookmark_model_);
ConvertBookmarkNode(task.Run(), ScopedJavaLocalRef<jobject>(), &jnode);
return ScopedJavaLocalRef<jobject>(jnode);
}
jboolean ChromeBrowserProvider::IsBookmarkInMobileBookmarksBranch(
JNIEnv* env,
jobject obj,
jlong id) {
IsInMobileBookmarksBranchTask task(bookmark_model_);
return task.Run(id);
}
ScopedJavaLocalRef<jbyteArray> ChromeBrowserProvider::GetFaviconOrTouchIcon(
JNIEnv* env, jobject obj, jstring jurl) {
if (!jurl)
return ScopedJavaLocalRef<jbyteArray>();
GURL url = GURL(ConvertJavaStringToUTF16(env, jurl));
BookmarkIconFetchTask favicon_task(favicon_service_.get(),
profile_,
&favicon_consumer_,
&cancelable_task_tracker_);
chrome::FaviconBitmapResult bitmap_result = favicon_task.Run(url);
if (!bitmap_result.is_valid() || !bitmap_result.bitmap_data.get())
return ScopedJavaLocalRef<jbyteArray>();
return base::android::ToJavaByteArray(env, bitmap_result.bitmap_data->front(),
bitmap_result.bitmap_data->size());
}
ScopedJavaLocalRef<jbyteArray> ChromeBrowserProvider::GetThumbnail(
JNIEnv* env, jobject obj, jstring jurl) {
if (!jurl)
return ScopedJavaLocalRef<jbyteArray>();
GURL url = GURL(ConvertJavaStringToUTF16(env, jurl));
scoped_refptr<base::RefCountedMemory> thumbnail;
if (top_sites_)
top_sites_->GetPageThumbnail(url, false, &thumbnail);
if (!thumbnail.get() || !thumbnail->front()) {
return ScopedJavaLocalRef<jbyteArray>();
}
return base::android::ToJavaByteArray(env, thumbnail->front(),
thumbnail->size());
}
void ChromeBrowserProvider::ExtensiveBookmarkChangesBeginning(
BookmarkModel* model) {
handling_extensive_changes_ = true;
}
void ChromeBrowserProvider::ExtensiveBookmarkChangesEnded(
BookmarkModel* model) {
handling_extensive_changes_ = false;
BookmarkModelChanged();
}
void ChromeBrowserProvider::BookmarkModelChanged() {
if (handling_extensive_changes_)
return;
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = weak_java_provider_.get(env);
if (obj.is_null())
return;
Java_ChromeBrowserProvider_onBookmarkChanged(env, obj.obj());
}
void ChromeBrowserProvider::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
if (type == chrome::NOTIFICATION_HISTORY_URL_VISITED ||
type == chrome::NOTIFICATION_HISTORY_URLS_DELETED) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = weak_java_provider_.get(env);
if (obj.is_null())
return;
Java_ChromeBrowserProvider_onBookmarkChanged(env, obj.obj());
} else if (type ==
chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = weak_java_provider_.get(env);
if (obj.is_null())
return;
Java_ChromeBrowserProvider_onSearchTermChanged(env, obj.obj());
}
}