Skip to content

Commit

Permalink
Bug 702810 - mozIAsyncHistory should expose an async isURIVisited met…
Browse files Browse the repository at this point in the history
…hod.

r=dietrich sr=gavin
  • Loading branch information
mak77 committed Nov 29, 2011
1 parent 55c3937 commit 329246d
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 10 deletions.
37 changes: 31 additions & 6 deletions toolkit/components/places/History.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,8 @@ GetJSObjectFromArray(JSContext* aCtx,
class VisitedQuery : public AsyncStatementCallback
{
public:
static nsresult Start(nsIURI* aURI)
static nsresult Start(nsIURI* aURI,
mozIVisitedStatusCallback* aCallback=nsnull)
{
NS_PRECONDITION(aURI, "Null URI");

Expand All @@ -346,7 +347,7 @@ class VisitedQuery : public AsyncStatementCallback
nsNavHistory* navHistory = nsNavHistory::GetHistoryService();
NS_ENSURE_STATE(navHistory);
if (navHistory->hasEmbedVisit(aURI)) {
nsRefPtr<VisitedQuery> callback = new VisitedQuery(aURI, true);
nsRefPtr<VisitedQuery> callback = new VisitedQuery(aURI, aCallback, true);
NS_ENSURE_TRUE(callback, NS_ERROR_OUT_OF_MEMORY);
// As per IHistory contract, we must notify asynchronously.
nsCOMPtr<nsIRunnable> event =
Expand All @@ -365,7 +366,7 @@ class VisitedQuery : public AsyncStatementCallback
nsresult rv = URIBinder::Bind(stmt, 0, aURI);
NS_ENSURE_SUCCESS(rv, rv);

nsRefPtr<VisitedQuery> callback = new VisitedQuery(aURI);
nsRefPtr<VisitedQuery> callback = new VisitedQuery(aURI, aCallback);
NS_ENSURE_TRUE(callback, NS_ERROR_OUT_OF_MEMORY);

nsCOMPtr<mozIStoragePendingStatement> handle;
Expand Down Expand Up @@ -400,6 +401,12 @@ class VisitedQuery : public AsyncStatementCallback

nsresult NotifyVisitedStatus()
{
// If an external handling callback is provided, just notify through it.
if (mCallback) {
mCallback->IsVisited(mURI, mIsVisited);
return NS_OK;
}

if (mIsVisited) {
History* history = History::GetService();
NS_ENSURE_STATE(history);
Expand All @@ -425,13 +432,17 @@ class VisitedQuery : public AsyncStatementCallback
}

private:
VisitedQuery(nsIURI* aURI, bool aIsVisited=false)
VisitedQuery(nsIURI* aURI,
mozIVisitedStatusCallback *aCallback=nsnull,
bool aIsVisited=false)
: mURI(aURI)
, mCallback(aCallback)
, mIsVisited(aIsVisited)
{
}

nsCOMPtr<nsIURI> mURI;
nsCOMPtr<mozIVisitedStatusCallback> mCallback;
bool mIsVisited;
};

Expand Down Expand Up @@ -1404,10 +1415,10 @@ History::GetIsVisitedStatement()

// Now we can create our cached statement.
nsresult rv = mReadOnlyDBConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
"SELECT h.id "
"SELECT 1 "
"FROM moz_places h "
"WHERE url = ?1 "
"AND EXISTS(SELECT id FROM moz_historyvisits WHERE place_id = h.id LIMIT 1) "
"AND last_visit_date NOTNULL "
), getter_AddRefs(mIsVisitedStatement));
NS_ENSURE_SUCCESS(rv, nsnull);
return mIsVisitedStatement;
Expand Down Expand Up @@ -2060,6 +2071,20 @@ History::UpdatePlaces(const jsval& aPlaceInfos,
return NS_OK;
}

NS_IMETHODIMP
History::IsURIVisited(nsIURI* aURI,
mozIVisitedStatusCallback* aCallback)
{
NS_ENSURE_STATE(NS_IsMainThread());
NS_ENSURE_ARG(aURI);
NS_ENSURE_ARG(aCallback);

nsresult rv = VisitedQuery::Start(aURI, aCallback);
NS_ENSURE_SUCCESS(rv, rv);

return NS_OK;
}

////////////////////////////////////////////////////////////////////////////////
//// nsIObserver

Expand Down
33 changes: 31 additions & 2 deletions toolkit/components/places/mozIAsyncHistory.idl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Shawn Wilsher <me@shawnwilsher.com>
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
* Marco Bonardo <mak77@bonardo.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
Expand Down Expand Up @@ -158,7 +159,25 @@ interface mozIVisitInfoCallback : nsISupports
/**
* @status EXPERIMENTAL
*/
[scriptable, uuid(f79ca67c-7e57-4511-a400-ea31001c762f)]
[scriptable, function, uuid(994092bf-936f-449b-8dd6-0941e024360d)]
interface mozIVisitedStatusCallback : nsISupports
{
/**
* Notifies whether a certain URI has been visited.
*
* @param aURI
* URI being notified about.
* @param aVisitedStatus
* The visited status of aURI.
*/
void isVisited(in nsIURI aURI,
in boolean aVisitedStatus);
};

/**
* @status EXPERIMENTAL
*/
[scriptable, uuid(b7edc16e-9f3c-4bf5-981b-4e8000b02d89)]
interface mozIAsyncHistory : nsISupports
{
/**
Expand Down Expand Up @@ -186,4 +205,14 @@ interface mozIAsyncHistory : nsISupports
void updatePlaces(in jsval aPlaceInfo,
[optional] in mozIVisitInfoCallback aCallback);

/**
* Checks if a given URI has been visited.
*
* @param aURI
* The URI to check for.
* @param aCallback
* A mozIVisitStatusCallback object which receives the visited status.
*/
void isURIVisited(in nsIURI aURI,
in mozIVisitedStatusCallback aCallback);
};
4 changes: 2 additions & 2 deletions toolkit/components/places/nsNavHistory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -720,10 +720,10 @@ nsNavHistory::FindLastVisit(nsIURI* aURI,
bool nsNavHistory::IsURIStringVisited(const nsACString& aURIString)
{
nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
"SELECT h.id "
"SELECT 1 "
"FROM moz_places h "
"WHERE url = ?1 "
"AND EXISTS(SELECT id FROM moz_historyvisits WHERE place_id = h.id LIMIT 1) "
"AND last_visit_date NOTNULL "
);
NS_ENSURE_TRUE(stmt, false);
mozStorageStatementScoper scoper(stmt);
Expand Down
93 changes: 93 additions & 0 deletions toolkit/components/places/tests/unit/test_isURIVisited.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */

// Tests functionality of the isURIVisited API.

const SCHEMES = {
"http://": true,
"https://": true,
"ftp://": true,
"file:///": true,
"about:": false,
"imap://": false,
"news://": false,
"mailbox:": false,
"moz-anno:favicon:http://": false,
"view-source:http://": false,
"chrome://browser/content/browser.xul?": false,
"resource://": false,
"data:,": false,
"wyciwyg:/0/http://": false,
"javascript:": false,
};

const TRANSITIONS = [
TRANSITION_LINK,
TRANSITION_TYPED,
TRANSITION_BOOKMARK,
TRANSITION_EMBED,
TRANSITION_FRAMED_LINK,
TRANSITION_REDIRECT_PERMANENT,
TRANSITION_REDIRECT_TEMPORARY,
TRANSITION_DOWNLOAD,
];

let gRunner;
function run_test()
{
do_test_pending();
gRunner = step();
gRunner.next();
}

function step()
{
let history = Cc["@mozilla.org/browser/history;1"]
.getService(Ci.mozIAsyncHistory);

for (let scheme in SCHEMES) {
do_log_info("Testing scheme " + scheme);
for (let i = 0; i < TRANSITIONS.length; i++) {
let transition = TRANSITIONS[i];
do_log_info("With transition " + transition);

let uri = NetUtil.newURI(scheme + "mozilla.org/");

history.isURIVisited(uri, function(aURI, aIsVisited) {
do_check_true(uri.equals(aURI));
do_check_false(aIsVisited);

let callback = {
handleError: function () {},
handleResult: function () {},
handleCompletion: function () {
do_log_info("Added visit to " + uri.spec);

history.isURIVisited(uri, function (aURI, aIsVisited) {
do_check_true(uri.equals(aURI));
let checker = SCHEMES[scheme] ? do_check_true : do_check_false;
checker(aIsVisited);

waitForClearHistory(function () {
history.isURIVisited(uri, function(aURI, aIsVisited) {
do_check_true(uri.equals(aURI));
do_check_false(aIsVisited);
gRunner.next();
});
});
});
},
};

history.updatePlaces({ uri: uri
, visits: [ { transitionType: transition
, visitDate: Date.now() * 1000
} ]
}, callback);
});
yield;
}
}

do_test_finished();
}
1 change: 1 addition & 0 deletions toolkit/components/places/tests/unit/xpcshell.ini
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ skip-if = os == "android"
# Bug 676989: test hangs consistently on Android
skip-if = os == "android"
[test_history_sidebar.js]
[test_isURIVisited.js]
[test_isvisited.js]
[test_lastModified.js]
[test_livemarkService_getLivemarkIdForFeedURI.js]
Expand Down

0 comments on commit 329246d

Please sign in to comment.