summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chrome_content_browser_client.cc2
-rw-r--r--chrome/browser/spellchecker/spellcheck_message_filter_mac.cc164
-rw-r--r--chrome/browser/spellchecker/spellcheck_message_filter_mac.h11
-rw-r--r--chrome/browser/spellchecker/spellcheck_message_filter_mac_browsertest.cc2
-rw-r--r--chrome/browser/spellchecker/spellcheck_platform_mac.h12
-rw-r--r--chrome/browser/spellchecker/spellcheck_platform_mac.mm16
6 files changed, 186 insertions, 21 deletions
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 9da446b..212950f 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -711,7 +711,7 @@ void ChromeContentBrowserClient::RenderProcessHostCreated(
new SearchProviderInstallStateMessageFilter(id, profile));
host->GetChannel()->AddFilter(new SpellCheckMessageFilter(id));
#if defined(OS_MACOSX)
- host->GetChannel()->AddFilter(new SpellCheckMessageFilterMac());
+ host->GetChannel()->AddFilter(new SpellCheckMessageFilterMac(id));
#endif
host->GetChannel()->AddFilter(new ChromeNetBenchmarkingMessageFilter(
id, profile, context));
diff --git a/chrome/browser/spellchecker/spellcheck_message_filter_mac.cc b/chrome/browser/spellchecker/spellcheck_message_filter_mac.cc
index 88c7cbb..1ff42c2 100644
--- a/chrome/browser/spellchecker/spellcheck_message_filter_mac.cc
+++ b/chrome/browser/spellchecker/spellcheck_message_filter_mac.cc
@@ -4,12 +4,168 @@
#include "chrome/browser/spellchecker/spellcheck_message_filter_mac.h"
+#include "base/bind.h"
+#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/spellchecker/spellcheck_platform_mac.h"
+#include "chrome/browser/spellchecker/spelling_service_client.h"
#include "chrome/common/spellcheck_messages.h"
+#include "chrome/common/spellcheck_result.h"
+#include "content/public/browser/render_process_host.h"
using content::BrowserThread;
-SpellCheckMessageFilterMac::SpellCheckMessageFilterMac() {}
+class SpellingRequest {
+ public:
+ SpellingRequest(SpellingServiceClient* client,
+ content::BrowserMessageFilter* destination,
+ int render_process_id);
+
+ void RequestCheck(const string16& text,
+ int route_id,
+ int identifier,
+ int document_tag);
+ private:
+ // Request server-side checking.
+ void RequestRemoteCheck(const string16& text);
+
+ // Request a check from local spell checker.
+ void RequestLocalCheck(const string16& text, int document_tag);
+
+ // Check if all pending requests are done, send reply to render process if so.
+ void OnCheckCompleted();
+
+ // Called when server-side checking is complete.
+ void OnRemoteCheckCompleted(bool success,
+ const string16& text,
+ const std::vector<SpellCheckResult>& results);
+
+ // Called when local checking is complete.
+ void OnLocalCheckCompleted(const std::vector<SpellCheckResult>& results);
+
+ std::vector<SpellCheckResult> local_results_;
+ std::vector<SpellCheckResult> remote_results_;
+
+ bool local_pending_;
+ bool remote_pending_;
+ bool remote_success_;
+
+ SpellingServiceClient* client_; // Owned by |destination|.
+ content::BrowserMessageFilter* destination_; // ref-counted.
+ int render_process_id_;
+
+ int route_id_;
+ int identifier_;
+ int document_tag_;
+};
+
+SpellingRequest::SpellingRequest(SpellingServiceClient* client,
+ content::BrowserMessageFilter* destination,
+ int render_process_id)
+ : local_pending_(true),
+ remote_pending_(true),
+ client_(client),
+ destination_(destination),
+ render_process_id_(render_process_id),
+ route_id_(-1),
+ identifier_(-1),
+ document_tag_(-1) {
+ destination_->AddRef();
+}
+
+void SpellingRequest::RequestCheck(const string16& text,
+ int route_id,
+ int identifier,
+ int document_tag) {
+ DCHECK(!text.empty());
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ route_id_ = route_id;
+ identifier_ = identifier;
+ document_tag_ = document_tag;
+
+ // Send the remote query out.
+ RequestRemoteCheck(text);
+ RequestLocalCheck(text, document_tag_);
+}
+
+void SpellingRequest::RequestRemoteCheck(const string16& text) {
+ Profile* profile = NULL;
+ content::RenderProcessHost* host =
+ content::RenderProcessHost::FromID(render_process_id_);
+ if (host)
+ profile = Profile::FromBrowserContext(host->GetBrowserContext());
+
+ client_->RequestTextCheck(
+ profile,
+ SpellingServiceClient::SPELLCHECK,
+ text,
+ base::Bind(&SpellingRequest::OnRemoteCheckCompleted,
+ base::Unretained(this)));
+}
+
+void SpellingRequest::RequestLocalCheck(const string16& text,
+ int document_tag) {
+ spellcheck_mac::RequestTextCheck(
+ document_tag,
+ text,
+ base::Bind(&SpellingRequest::OnLocalCheckCompleted,
+ base::Unretained(this)));
+}
+
+void SpellingRequest::OnCheckCompleted() {
+ // Final completion can happen on any thread - don't DCHECK thread.
+
+ if (local_pending_ || remote_pending_)
+ return;
+
+ const std::vector<SpellCheckResult>* check_results = &remote_results_;
+ if (!remote_success_)
+ check_results = &local_results_;
+
+ destination_->Send(
+ new SpellCheckMsg_RespondTextCheck(
+ route_id_,
+ identifier_,
+ *check_results));
+ destination_->Release();
+
+ // Object is self-managed - at this point, its life span is over.
+ delete this;
+}
+
+void SpellingRequest::OnRemoteCheckCompleted(
+ bool success,
+ const string16& text,
+ const std::vector<SpellCheckResult>& results) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ remote_success_ = success;
+ remote_results_ = results;
+ remote_pending_ = false;
+
+ OnCheckCompleted();
+}
+
+void SpellingRequest::OnLocalCheckCompleted(
+ const std::vector<SpellCheckResult>& results) {
+ // Local checking can happen on any thread - don't DCHECK thread.
+
+ local_results_ = results;
+ local_pending_ = false;
+
+ OnCheckCompleted();
+}
+
+
+SpellCheckMessageFilterMac::SpellCheckMessageFilterMac(int render_process_id)
+ : render_process_id_(render_process_id),
+ client_(new SpellingServiceClient) {
+}
+
+void SpellCheckMessageFilterMac::OverrideThreadForMessage(
+ const IPC::Message& message, BrowserThread::ID* thread) {
+ if (message.type() == SpellCheckHostMsg_RequestTextCheck::ID)
+ *thread = BrowserThread::UI;
+}
bool SpellCheckMessageFilterMac::OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) {
@@ -57,8 +213,10 @@ void SpellCheckMessageFilterMac::OnRequestTextCheck(
int route_id,
int identifier,
const string16& text) {
- spellcheck_mac::RequestTextCheck(
- route_id, identifier, ToDocumentTag(route_id), text, this);
+ // SpellingRequest self-destructs.
+ SpellingRequest* request =
+ new SpellingRequest(client_.get(), this, render_process_id_);
+ request->RequestCheck(text, route_id, identifier, ToDocumentTag(route_id));
}
int SpellCheckMessageFilterMac::ToDocumentTag(int route_id) {
diff --git a/chrome/browser/spellchecker/spellcheck_message_filter_mac.h b/chrome/browser/spellchecker/spellcheck_message_filter_mac.h
index d5071db..3a7fa2e 100644
--- a/chrome/browser/spellchecker/spellcheck_message_filter_mac.h
+++ b/chrome/browser/spellchecker/spellcheck_message_filter_mac.h
@@ -7,15 +7,19 @@
#include <map>
+#include "chrome/browser/spellchecker/spelling_service_client.h"
#include "content/public/browser/browser_message_filter.h"
// A message filter implementation that receives
// the Mac-specific spell checker requests from SpellCheckProvider.
class SpellCheckMessageFilterMac : public content::BrowserMessageFilter {
public:
- explicit SpellCheckMessageFilterMac();
+ explicit SpellCheckMessageFilterMac(int render_process_id);
// BrowserMessageFilter implementation.
+ virtual void OverrideThreadForMessage(
+ const IPC::Message& message,
+ content::BrowserThread::ID* thread) OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) OVERRIDE;
@@ -37,6 +41,11 @@ class SpellCheckMessageFilterMac : public content::BrowserMessageFilter {
void RetireDocumentTag(int route_id);
std::map<int,int> tag_map_;
+ int render_process_id_;
+
+ // A JSON-RPC client that calls the Spelling service in the background.
+ scoped_ptr<SpellingServiceClient> client_;
+
DISALLOW_COPY_AND_ASSIGN(SpellCheckMessageFilterMac);
};
diff --git a/chrome/browser/spellchecker/spellcheck_message_filter_mac_browsertest.cc b/chrome/browser/spellchecker/spellcheck_message_filter_mac_browsertest.cc
index 84ddf07..0a25eeb 100644
--- a/chrome/browser/spellchecker/spellcheck_message_filter_mac_browsertest.cc
+++ b/chrome/browser/spellchecker/spellcheck_message_filter_mac_browsertest.cc
@@ -19,7 +19,7 @@
class TestingSpellCheckMessageFilter : public SpellCheckMessageFilterMac {
public:
explicit TestingSpellCheckMessageFilter(MessageLoopForUI* loop)
- : SpellCheckMessageFilterMac(),
+ : SpellCheckMessageFilterMac(0),
loop_(loop) { }
virtual bool Send(IPC::Message* message) OVERRIDE {
diff --git a/chrome/browser/spellchecker/spellcheck_platform_mac.h b/chrome/browser/spellchecker/spellcheck_platform_mac.h
index 5796994..098c2b1 100644
--- a/chrome/browser/spellchecker/spellcheck_platform_mac.h
+++ b/chrome/browser/spellchecker/spellcheck_platform_mac.h
@@ -14,12 +14,18 @@
#include "base/callback_forward.h"
#include "base/string16.h"
+struct SpellCheckResult;
+
namespace content {
class BrowserMessageFilter;
} // namespace content
namespace spellcheck_mac {
+typedef base::Callback<void(
+ const std::vector<SpellCheckResult>& /* results */)>
+ TextCheckCompleteCallback;
+
// Get the languages supported by the platform spellchecker and store them in
// |spellcheck_languages|. Note that they must be converted to
// Chromium style codes (en-US not en_US). See spellchecker.cc for a full list.
@@ -84,11 +90,9 @@ void CloseDocumentWithTag(int tag);
// Requests an asyncronous spell and grammar checking.
// The result is returned to an IPC message to |destination| thus it should
// not be null.
-void RequestTextCheck(int route_id,
- int identifier,
- int document_tag,
+void RequestTextCheck(int document_tag,
const string16& text,
- content::BrowserMessageFilter* destination);
+ TextCheckCompleteCallback callback);
} // namespace spellcheck_mac
diff --git a/chrome/browser/spellchecker/spellcheck_platform_mac.mm b/chrome/browser/spellchecker/spellcheck_platform_mac.mm
index 81fd517..ad1a06d 100644
--- a/chrome/browser/spellchecker/spellcheck_platform_mac.mm
+++ b/chrome/browser/spellchecker/spellcheck_platform_mac.mm
@@ -235,13 +235,11 @@ void CloseDocumentWithTag(int tag) {
[SharedSpellChecker() closeSpellDocumentWithTag:static_cast<NSInteger>(tag)];
}
-void RequestTextCheck(int route_id,
- int identifier,
- int document_tag,
- const string16& text, BrowserMessageFilter* destination) {
+void RequestTextCheck(int document_tag,
+ const string16& text,
+ TextCheckCompleteCallback callback) {
NSString* text_to_check = base::SysUTF16ToNSString(text);
NSRange range_to_check = NSMakeRange(0, [text_to_check length]);
- destination->AddRef();
[SharedSpellChecker()
requestCheckingOfString:text_to_check
@@ -262,12 +260,8 @@ void RequestTextCheck(int route_id,
[result range].location,
[result range].length));
}
- destination->Send(
- new SpellCheckMsg_RespondTextCheck(
- route_id,
- identifier,
- check_results));
- destination->Release();
+ // TODO(groby): Verify we don't need to post from here.
+ callback.Run(check_results);
}];
}