Index: content/renderer/hyphenator/hyphenator.cc |
=================================================================== |
--- content/renderer/hyphenator/hyphenator.cc (revision 152650) |
+++ content/renderer/hyphenator/hyphenator.cc (working copy) |
@@ -4,11 +4,18 @@ |
#include "content/renderer/hyphenator/hyphenator.h" |
+#include "base/bind.h" |
#include "base/file_util.h" |
#include "base/logging.h" |
+#include "base/memory/ref_counted.h" |
#include "base/memory/scoped_ptr.h" |
+#include "base/message_loop_proxy.h" |
#include "base/string_util.h" |
#include "base/utf_string_conversions.h" |
+#include "content/common/hyphenator_messages.h" |
+#include "content/public/renderer/render_thread.h" |
jam
2012/08/23 21:34:29
nit: not needed
Hironori Bono
2012/08/27 06:57:28
Done. I have removed redundant headers. (I do not
|
+#include "content/renderer/render_thread_impl.h" |
+#include "ipc/ipc_channel_proxy.h" |
#include "third_party/hyphen/hyphen.h" |
#include "unicode/uscript.h" |
@@ -176,6 +183,56 @@ |
return !hyphen_offsets->empty(); |
} |
+// A message filter that listens HyphenatorMsg_SetDictionary messages and |
+// initializes the specified Hyphenator object. This class has a weak reference |
+// to the Hyphenator object so a renderer can delete it while a browser opens a |
+// dictionary file. |
+class MessageFilter : public IPC::ChannelProxy::MessageFilter { |
jam
2012/08/23 21:34:29
you don't need a message filter, since you're real
Hironori Bono
2012/08/27 06:57:28
Done. Thanks for your suggestion. The RenderProces
|
+ public: |
+ explicit MessageFilter(base::WeakPtr<content::Hyphenator> hyphenator); |
+ |
+ // IPC::ChannelProxy::MessageFilter implementation. |
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; |
+ |
+ private: |
+ virtual ~MessageFilter(); |
+ |
+ // Called when a browser sends a HyphenatorMsg_SetDictionary message, i.e. |
jam
2012/08/23 21:34:29
nit: by convention we don't comment IPC message ha
Hironori Bono
2012/08/27 06:57:28
Done. Thanks for your comment. (I have removed com
|
+ // when a browser opens the hyphenation dictionary requested by the |
+ // Hyphenator object. |
+ void OnSetDictionary(IPC::PlatformFileForTransit rule_file); |
+ |
+ base::WeakPtr<content::Hyphenator> hyphenator_; |
+ scoped_refptr<base::MessageLoopProxy> message_loop_; |
+}; |
+ |
+MessageFilter::MessageFilter(base::WeakPtr<content::Hyphenator> hyphenator) |
+ : hyphenator_(hyphenator), |
+ message_loop_(base::MessageLoopProxy::current()) { |
+} |
+ |
+MessageFilter::~MessageFilter() { |
+} |
+ |
+bool MessageFilter::OnMessageReceived(const IPC::Message& message) { |
+ bool handled = true; |
+ IPC_BEGIN_MESSAGE_MAP(MessageFilter, message) |
+ IPC_MESSAGE_HANDLER(HyphenatorMsg_SetDictionary, OnSetDictionary) |
+ IPC_MESSAGE_UNHANDLED(handled = false) |
+ IPC_END_MESSAGE_MAP() |
+ return handled; |
+} |
+ |
+void MessageFilter::OnSetDictionary(IPC::PlatformFileForTransit rule_file) { |
+ base::PlatformFile file = |
+ IPC::PlatformFileForTransitToPlatformFile(rule_file); |
+ if (file == base::kInvalidPlatformFileValue) |
+ return; |
+ message_loop_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&content::Hyphenator::SetDictionary, hyphenator_, file)); |
+} |
+ |
} // namespace |
namespace content { |
@@ -183,29 +240,52 @@ |
Hyphenator::Hyphenator(base::PlatformFile file) |
: dictionary_(NULL), |
rule_file_(file), |
- result_(0) { |
+ result_(0), |
+ weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
} |
Hyphenator::~Hyphenator() { |
if (dictionary_) |
hnj_hyphen_free(dictionary_); |
+ if (rule_file_ != base::kInvalidPlatformFileValue) |
+ base::ClosePlatformFile(rule_file_); |
} |
bool Hyphenator::Initialize() { |
if (dictionary_) |
return true; |
+ // Attach the dictionary file to the MemoryMappedFile object. When it |
+ // succeeds, this class does not have to close this file because it is closed |
+ // by the MemoryMappFile class. To prevent this class from closing this file, |
tony
2012/08/22 19:05:50
Nit: typo: MemoryMappFile -> MemoryMappedFile
Hironori Bono
2012/08/27 06:57:28
Done. Thanks for noticing my typo.
|
+ // we reset its handle. |
rule_map_.reset(new file_util::MemoryMappedFile); |
if (!rule_map_->Initialize(rule_file_)) |
return false; |
+ rule_file_ = base::kInvalidPlatformFileValue; |
dictionary_ = hnj_hyphen_load(rule_map_->data(), rule_map_->length()); |
return !!dictionary_; |
} |
+bool Hyphenator::Attach(content::RenderThread* thread, const string16& locale) { |
jam
2012/08/23 21:34:29
ditto
Hironori Bono
2012/08/27 06:57:28
Done. I have removed this redundant comment.
|
+ // Create a new message filter for Hyphenator messages and attach it to the |
+ // given thread with a weak reference to this object so a renderer can delete |
+ // this object while a browser opens a dictionary. |
+ if (!thread) |
+ return false; |
+ locale_.assign(locale); |
+ thread->AddFilter(new MessageFilter(weak_factory_.GetWeakPtr())); |
+ return thread->Send(new HyphenatorHostMsg_OpenDictionary(locale)); |
+} |
+ |
+bool Hyphenator::CanHyphenate(const string16& locale) { |
+ return !locale_.compare(locale); |
+} |
+ |
size_t Hyphenator::ComputeLastHyphenLocation(const string16& word, |
size_t before_index) { |
- if (!dictionary_ || word.empty()) |
+ if (!Initialize() || word.empty()) |
return 0; |
// Call the hyphen library to get all hyphenation points, i.e. positions where |
@@ -228,4 +308,20 @@ |
return 0; |
} |
+void Hyphenator::SetDictionary(base::PlatformFile rule_file) { |
+ // Delete the current dictionary and save the given file to this object. We |
+ // initialize the hyphens library the first time when WebKit actually |
+ // hyphenates a word, i.e. when WebKit calls the ComputeLastHyphenLocation |
+ // function. (WebKit does not always hyphenate words even when it calls the |
+ // CanHyphenate function, e.g. WebKit does not have to hyphenate words when it |
+ // does not have to break text into lines.) |
+ DCHECK(rule_file != base::kInvalidPlatformFileValue); |
+ if (dictionary_) { |
+ hnj_hyphen_free(dictionary_); |
+ dictionary_ = NULL; |
+ } |
+ rule_map_.reset(); |
+ rule_file_ = rule_file; |
+} |
+ |
} // namespace content |