summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshuchen@chromium.org <shuchen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-09 12:44:13 +0000
committershuchen@chromium.org <shuchen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-09 12:44:13 +0000
commit6040a4668403c6f3ad4959a3fd67dee29ba1f4b7 (patch)
tree68b26e9d838073014d771952fb4bbbc8610c64d5
parent5a263ba64cb1f2270764f02531965ad2ad4146ca (diff)
downloadchromium_src-6040a4668403c6f3ad4959a3fd67dee29ba1f4b7.zip
chromium_src-6040a4668403c6f3ad4959a3fd67dee29ba1f4b7.tar.gz
chromium_src-6040a4668403c6f3ad4959a3fd67dee29ba1f4b7.tar.bz2
[IME] Adds these histograms in IMF. 1) Count of IME is activated/deactivated 2) Count of commits with each IME 3) Count of committed characters with each IME 4) Time duration of using each IME
BUG=367631 TEST=None Review URL: https://codereview.chromium.org/252813004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269250 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chromeos/input_method/input_method_engine.cc41
-rw-r--r--chrome/browser/chromeos/input_method/input_method_engine.h7
-rw-r--r--chrome/browser/chromeos/input_method/input_method_engine_unittest.cc74
3 files changed, 122 insertions, 0 deletions
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.cc b/chrome/browser/chromeos/input_method/input_method_engine.cc
index aaa9539..215e9bd 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine.cc
@@ -19,8 +19,10 @@
#include "ash/shell.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/metrics/histogram.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chromeos/ime/component_extension_ime_manager.h"
#include "chromeos/ime/composition_text.h"
@@ -55,6 +57,19 @@ void UpdateComposition(const CompositionText& composition_text,
composition_text, cursor_pos, is_visible);
}
+// Returns the length of characters of a UTF-8 string with unknown string
+// length. Cannot apply faster algorithm to count characters in an utf-8
+// string without knowing the string length, so just does a full scan.
+size_t GetUtf8StringLength(const char* s) {
+ size_t ret = 0;
+ while (*s) {
+ if ((*s & 0xC0) != 0x80)
+ ret++;
+ ++s;
+ }
+ return ret;
+}
+
} // namespace
InputMethodEngine::InputMethodEngine()
@@ -69,6 +84,8 @@ InputMethodEngine::InputMethodEngine()
sent_key_event_(NULL) {}
InputMethodEngine::~InputMethodEngine() {
+ if (start_time_.ToInternalValue())
+ RecordHistogram("WorkingTime", (end_time_ - start_time_).InSeconds());
input_method::InputMethodManager::Get()->RemoveInputMethodExtension(imm_id_);
}
@@ -122,6 +139,15 @@ const input_method::InputMethodDescriptor& InputMethodEngine::GetDescriptor()
return descriptor_;
}
+void InputMethodEngine::RecordHistogram(const char* name, int count) {
+ std::string histo_name =
+ base::StringPrintf("InputMethod.%s.%s", name, engine_id_.c_str());
+ base::HistogramBase* counter = base::Histogram::FactoryGet(
+ histo_name, 0, 1000000, 50, base::HistogramBase::kNoFlags);
+ if (counter)
+ counter->Add(count);
+}
+
void InputMethodEngine::NotifyImeReady() {
input_method::InputMethodManager* manager =
input_method::InputMethodManager::Get();
@@ -209,6 +235,14 @@ bool InputMethodEngine::CommitText(int context_id, const char* text,
}
IMEBridge::Get()->GetInputContextHandler()->CommitText(text);
+
+ // Records times for using input method.
+ if (!start_time_.ToInternalValue())
+ start_time_ = base::Time::Now();
+ end_time_ = base::Time::Now();
+ // Records histograms for counts of commits and committed characters.
+ RecordHistogram("Commit", 1);
+ RecordHistogram("CommitCharacter", GetUtf8StringLength(text));
return true;
}
@@ -525,11 +559,18 @@ void InputMethodEngine::Enable() {
FocusIn(IMEEngineHandlerInterface::InputContext(
current_input_type_, ui::TEXT_INPUT_MODE_DEFAULT));
EnableInputView(true);
+
+ start_time_ = base::Time();
+ end_time_ = base::Time();
+ RecordHistogram("Enable", 1);
}
void InputMethodEngine::Disable() {
active_ = false;
observer_->OnDeactivated(engine_id_);
+
+ if (start_time_.ToInternalValue())
+ RecordHistogram("WorkingTime", (end_time_ - start_time_).InSeconds());
}
void InputMethodEngine::PropertyActivate(const std::string& property_name) {
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.h b/chrome/browser/chromeos/input_method/input_method_engine.h
index 328653d..716d136 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine.h
+++ b/chrome/browser/chromeos/input_method/input_method_engine.h
@@ -8,6 +8,7 @@
#include <map>
#include <string>
#include <vector>
+#include "base/time/time.h"
#include "chrome/browser/chromeos/input_method/input_method_engine_interface.h"
#include "chromeos/ime/input_method_descriptor.h"
#include "url/gurl.h"
@@ -99,6 +100,8 @@ class InputMethodEngine : public InputMethodEngineInterface {
virtual void HideInputView() OVERRIDE;
private:
+ void RecordHistogram(const char* name, int count);
+
// Converts MenuItem to InputMethodMenuItem.
void MenuItemToProperty(const MenuItem& item,
ash::ime::InputMethodMenuItem* property);
@@ -157,6 +160,10 @@ class InputMethodEngine : public InputMethodEngineInterface {
// Used with SendKeyEvents and ProcessKeyEvent to check if the key event
// sent to ProcessKeyEvent is sent by SendKeyEvents.
const ui::KeyEvent* sent_key_event_;
+
+ // The start & end time of using this input method. This is for UMA.
+ base::Time start_time_;
+ base::Time end_time_;
};
} // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/input_method_engine_unittest.cc b/chrome/browser/chromeos/input_method/input_method_engine_unittest.cc
index 7a8434b..50e3be4 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine_unittest.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine_unittest.cc
@@ -3,6 +3,9 @@
// found in the LICENSE file.
#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/histogram_samples.h"
+#include "base/metrics/statistics_recorder.h"
#include "chrome/browser/chromeos/input_method/input_method_configuration.h"
#include "chrome/browser/chromeos/input_method/input_method_engine.h"
#include "chrome/browser/chromeos/input_method/input_method_engine_interface.h"
@@ -10,6 +13,7 @@
#include "chromeos/ime/extension_ime_util.h"
#include "chromeos/ime/mock_component_extension_ime_manager_delegate.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/ime/chromeos/mock_ime_input_context_handler.h"
namespace chromeos {
@@ -20,6 +24,19 @@ const char kTestExtensionId[] = "mppnpdlheglhdfmldimlhpnegondlapf";
const char kTestExtensionId2[] = "dmpipdbjkoajgdeppkffbjhngfckdloi";
const char kTestImeEngineId[] = "test_engine_id";
+const char* kHistogramNames[] = {
+ "InputMethod.Enable.test_engine_id", "InputMethod.Commit.test_engine_id",
+ "InputMethod.CommitCharacter.test_engine_id",
+};
+
+scoped_ptr<base::HistogramSamples> GetHistogramSamples(
+ const char* histogram_name) {
+ base::HistogramBase* histogram =
+ base::StatisticsRecorder::FindHistogram(histogram_name);
+ EXPECT_NE(static_cast<base::HistogramBase*>(NULL), histogram);
+ return histogram->SnapshotSamples().Pass();
+}
+
enum CallsBitmap {
NONE = 0U,
ACTIVATE = 1U,
@@ -112,13 +129,48 @@ class InputMethodEngineTest : public testing::Test {
layouts_.push_back("us");
InitInputMethod();
IMEBridge::Initialize();
+ mock_ime_input_context_handler_.reset(new MockIMEInputContextHandler());
+ IMEBridge::Get()->SetInputContextHandler(
+ mock_ime_input_context_handler_.get());
+
+ base::StatisticsRecorder::Initialize();
+
+ for (size_t i = 0; i < arraysize(kHistogramNames); i++) {
+ base::Histogram::FactoryGet(
+ kHistogramNames[i], 0, 1000000, 50, base::HistogramBase::kNoFlags)
+ ->Add(0);
+ initial_histogram_samples_[i] =
+ GetHistogramSamples(kHistogramNames[i]).Pass();
+ initial_histogram_samples_map_[kHistogramNames[i]] =
+ initial_histogram_samples_[i].get();
+ }
}
virtual ~InputMethodEngineTest() {
+ IMEBridge::Get()->SetInputContextHandler(NULL);
engine_.reset();
Shutdown();
}
protected:
+ scoped_ptr<base::HistogramSamples> GetHistogramSamplesDelta(
+ const char* histogram_name) {
+ scoped_ptr<base::HistogramSamples> delta_samples(
+ GetHistogramSamples(histogram_name));
+ delta_samples->Subtract(*initial_histogram_samples_map_[histogram_name]);
+
+ return delta_samples.Pass();
+ }
+
+ void ExpectNewSample(const char* histogram_name,
+ base::HistogramBase::Sample sample,
+ int total_count,
+ int sample_count) {
+ scoped_ptr<base::HistogramSamples> delta_samples(
+ GetHistogramSamplesDelta(histogram_name));
+ EXPECT_EQ(total_count, delta_samples->TotalCount());
+ EXPECT_EQ(sample_count, delta_samples->GetCount(sample));
+ }
+
void CreateEngine(bool whitelisted) {
engine_.reset(new InputMethodEngine());
observer_ = new TestObserver();
@@ -141,12 +193,19 @@ class InputMethodEngineTest : public testing::Test {
}
scoped_ptr<InputMethodEngine> engine_;
+
TestObserver* observer_;
std::vector<std::string> languages_;
std::vector<std::string> layouts_;
GURL options_page_;
GURL input_view_;
+ scoped_ptr<base::HistogramSamples>
+ initial_histogram_samples_[arraysize(kHistogramNames)];
+ std::map<std::string, base::HistogramSamples*> initial_histogram_samples_map_;
+
+ scoped_ptr<MockIMEInputContextHandler> mock_ime_input_context_handler_;
+
private:
DISALLOW_COPY_AND_ASSIGN(InputMethodEngineTest);
};
@@ -223,5 +282,20 @@ TEST_F(InputMethodEngineTest, TestSwitching_Password_Whitelisted) {
EXPECT_EQ(DEACTIVATED, observer_->GetCallsBitmapAndReset());
}
+TEST_F(InputMethodEngineTest, TestHistograms) {
+ CreateEngine(true);
+ FocusIn(ui::TEXT_INPUT_TYPE_TEXT);
+ engine_->Enable();
+ std::string error;
+ ExpectNewSample("InputMethod.Enable.test_engine_id", 1, 1, 1);
+ engine_->CommitText(1, "input", &error);
+ engine_->CommitText(1, "入力", &error);
+ engine_->CommitText(1, "input入力", &error);
+ ExpectNewSample("InputMethod.Commit.test_engine_id", 1, 3, 3);
+ ExpectNewSample("InputMethod.CommitCharacter.test_engine_id", 5, 3, 1);
+ ExpectNewSample("InputMethod.CommitCharacter.test_engine_id", 2, 3, 1);
+ ExpectNewSample("InputMethod.CommitCharacter.test_engine_id", 7, 3, 1);
+}
+
} // namespace input_method
} // namespace chromeos