diff options
author | Torne (Richard Coles) <torne@google.com> | 2013-12-18 16:25:09 +0000 |
---|---|---|
committer | Torne (Richard Coles) <torne@google.com> | 2013-12-18 16:25:09 +0000 |
commit | a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7 (patch) | |
tree | dafc1c6417406a7fbd422ad0bb890e96909ef564 /content/browser | |
parent | d5f893c0bc79db3066bb5ae5d3d972ba1be7dd5f (diff) | |
download | chromium_org-a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7.tar.gz |
Merge from Chromium at DEPS revision 240154
This commit was generated by merge_to_master.py.
Change-Id: I8f2ba858cf0e7f413dddedc2ae91dc37f7136c2e
Diffstat (limited to 'content/browser')
460 files changed, 12159 insertions, 7277 deletions
diff --git a/content/browser/DEPS b/content/browser/DEPS index f97cc40386..6e6295235a 100644 --- a/content/browser/DEPS +++ b/content/browser/DEPS @@ -60,6 +60,8 @@ include_rules = [ # These should be burned down. http://crbug.com/237267 "!third_party/WebKit/public/web/mac/WebInputEventFactory.h", + "+ui/ozone/ozone_switches.h", + # DO NOT ADD ANY CHROME OR COMPONENTS INCLUDES HERE!!! # See https://sites.google.com/a/chromium.org/dev/developers/content-module # for more information. diff --git a/content/browser/accessibility/accessibility_tree_formatter.cc b/content/browser/accessibility/accessibility_tree_formatter.cc index 3e03b80433..af33a42a7c 100644 --- a/content/browser/accessibility/accessibility_tree_formatter.cc +++ b/content/browser/accessibility/accessibility_tree_formatter.cc @@ -55,7 +55,7 @@ AccessibilityTreeFormatter::BuildAccessibilityTree() { } void AccessibilityTreeFormatter::FormatAccessibilityTree( - string16* contents) { + base::string16* contents) { scoped_ptr<base::DictionaryValue> dict = BuildAccessibilityTree(); RecursiveFormatAccessibilityTree(*(dict.get()), contents); } @@ -76,9 +76,10 @@ void AccessibilityTreeFormatter::RecursiveBuildAccessibilityTree( } void AccessibilityTreeFormatter::RecursiveFormatAccessibilityTree( - const base::DictionaryValue& dict, string16* contents, int depth) { - string16 line = ToString(dict, string16(depth * kIndentSpaces, ' ')); - if (line.find(ASCIIToUTF16(kSkipString)) != string16::npos) + const base::DictionaryValue& dict, base::string16* contents, int depth) { + base::string16 line = + ToString(dict, base::string16(depth * kIndentSpaces, ' ')); + if (line.find(ASCIIToUTF16(kSkipString)) != base::string16::npos) return; *contents += line; @@ -98,8 +99,9 @@ void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node, dict->SetInteger("id", node.renderer_id()); } -string16 AccessibilityTreeFormatter::ToString(const base::DictionaryValue& node, - const string16& indent) { +base::string16 AccessibilityTreeFormatter::ToString( + const base::DictionaryValue& node, + const base::string16& indent) { int id_value; node.GetInteger("id", &id_value); return indent + base::IntToString16(id_value) + @@ -142,7 +144,7 @@ void AccessibilityTreeFormatter::SetFilters( } bool AccessibilityTreeFormatter::MatchesFilters( - const string16& text, bool default_result) const { + const base::string16& text, bool default_result) const { std::vector<Filter>::const_iterator iter = filters_.begin(); bool allow = default_result; for (iter = filters_.begin(); iter != filters_.end(); ++iter) { @@ -158,7 +160,7 @@ bool AccessibilityTreeFormatter::MatchesFilters( return allow; } -string16 AccessibilityTreeFormatter::FormatCoordinates( +base::string16 AccessibilityTreeFormatter::FormatCoordinates( const char* name, const char* x_name, const char* y_name, const base::DictionaryValue& value) { int x, y; @@ -170,12 +172,12 @@ string16 AccessibilityTreeFormatter::FormatCoordinates( } void AccessibilityTreeFormatter::WriteAttribute( - bool include_by_default, const std::string& attr, string16* line) { + bool include_by_default, const std::string& attr, base::string16* line) { WriteAttribute(include_by_default, UTF8ToUTF16(attr), line); } void AccessibilityTreeFormatter::WriteAttribute( - bool include_by_default, const string16& attr, string16* line) { + bool include_by_default, const base::string16& attr, base::string16* line) { if (attr.empty()) return; if (!MatchesFilters(attr, include_by_default)) diff --git a/content/browser/accessibility/accessibility_tree_formatter.h b/content/browser/accessibility/accessibility_tree_formatter.h index 006ee9a2d2..a290886aad 100644 --- a/content/browser/accessibility/accessibility_tree_formatter.h +++ b/content/browser/accessibility/accessibility_tree_formatter.h @@ -52,7 +52,7 @@ class CONTENT_EXPORT AccessibilityTreeFormatter { scoped_ptr<base::DictionaryValue> BuildAccessibilityTree(); // Dumps a BrowserAccessibility tree into a string. - void FormatAccessibilityTree(string16* contents); + void FormatAccessibilityTree(base::string16* contents); // A single filter specification. See GetAllowString() and GetDenyString() // for more information. @@ -62,10 +62,10 @@ class CONTENT_EXPORT AccessibilityTreeFormatter { ALLOW_EMPTY, DENY }; - string16 match_str; + base::string16 match_str; Type type; - Filter(string16 match_str, Type type) + Filter(base::string16 match_str, Type type) : match_str(match_str), type(type) {} }; @@ -100,12 +100,12 @@ class CONTENT_EXPORT AccessibilityTreeFormatter { protected: void RecursiveFormatAccessibilityTree(const BrowserAccessibility& node, - string16* contents, + base::string16* contents, int indent); void RecursiveBuildAccessibilityTree(const BrowserAccessibility& node, base::DictionaryValue* tree_node); void RecursiveFormatAccessibilityTree(const base::DictionaryValue& tree_node, - string16* contents, + base::string16* contents, int depth = 0); // Overridden by each platform to add the required attributes for each node @@ -113,27 +113,28 @@ class CONTENT_EXPORT AccessibilityTreeFormatter { void AddProperties(const BrowserAccessibility& node, base::DictionaryValue* dict); - string16 FormatCoordinates(const char* name, - const char* x_name, - const char* y_name, - const base::DictionaryValue& value); + base::string16 FormatCoordinates(const char* name, + const char* x_name, + const char* y_name, + const base::DictionaryValue& value); // Returns a platform specific representation of a BrowserAccessibility. // Should be zero or more complete lines, each with |prefix| prepended // (to indent each line). - string16 ToString(const base::DictionaryValue& node, const string16& indent); + base::string16 ToString(const base::DictionaryValue& node, + const base::string16& indent); void Initialize(); - bool MatchesFilters(const string16& text, bool default_result) const; + bool MatchesFilters(const base::string16& text, bool default_result) const; // Writes the given attribute string out to |line| if it matches the filters. void WriteAttribute(bool include_by_default, - const string16& attr, - string16* line); + const base::string16& attr, + base::string16* line); void WriteAttribute(bool include_by_default, const std::string& attr, - string16* line); + base::string16* line); BrowserAccessibility* root_; diff --git a/content/browser/accessibility/accessibility_tree_formatter_android.cc b/content/browser/accessibility/accessibility_tree_formatter_android.cc index ae34ef59c0..8c625a3eae 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_android.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_android.cc @@ -25,12 +25,20 @@ const char* BOOL_ATTRIBUTES[] = { "checkable", "checked", "clickable", + "collection", + "collection_item", + "content_invalid", "disabled", + "dismissable", "editable_text", "focusable", "focused", + "heading", + "hierarchical", "invisible", + "multiline", "password", + "range", "scrollable", "selected" }; @@ -41,7 +49,18 @@ const char* STRING_ATTRIBUTES[] = { const char* INT_ATTRIBUTES[] = { "item_index", - "item_count" + "item_count", + "row_count", + "column_count", + "row_index", + "row_span", + "column_index", + "column_span", + "input_type", + "live_region_type", + "range_min", + "range_max", + "range_current_value", }; } @@ -57,17 +76,24 @@ void AccessibilityTreeFormatter::AddProperties( dict->SetString("class", android_node->GetClassName()); // Bool attributes. - dict->SetBoolean("focusable", android_node->IsFocusable()); - dict->SetBoolean("focused", android_node->IsFocused()); - dict->SetBoolean("clickable", android_node->IsClickable()); - dict->SetBoolean("editable_text", android_node->IsEditableText()); dict->SetBoolean("checkable", android_node->IsCheckable()); dict->SetBoolean("checked", android_node->IsChecked()); + dict->SetBoolean("clickable", android_node->IsClickable()); + dict->SetBoolean("collection", android_node->IsCollection()); + dict->SetBoolean("collection_item", android_node->IsCollectionItem()); dict->SetBoolean("disabled", !android_node->IsEnabled()); - dict->SetBoolean("scrollable", android_node->IsScrollable()); + dict->SetBoolean("dismissable", android_node->IsDismissable()); + dict->SetBoolean("editable_text", android_node->IsEditableText()); + dict->SetBoolean("focusable", android_node->IsFocusable()); + dict->SetBoolean("focused", android_node->IsFocused()); + dict->SetBoolean("heading", android_node->IsHeading()); + dict->SetBoolean("hierarchical", android_node->IsHierarchical()); + dict->SetBoolean("invisible", !android_node->IsVisibleToUser()); + dict->SetBoolean("multiline", android_node->IsMultiLine()); + dict->SetBoolean("range", android_node->IsRangeType()); dict->SetBoolean("password", android_node->IsPassword()); + dict->SetBoolean("scrollable", android_node->IsScrollable()); dict->SetBoolean("selected", android_node->IsSelected()); - dict->SetBoolean("invisible", !android_node->IsVisibleToUser()); // String attributes. dict->SetString("name", android_node->GetText()); @@ -75,13 +101,26 @@ void AccessibilityTreeFormatter::AddProperties( // Int attributes. dict->SetInteger("item_index", android_node->GetItemIndex()); dict->SetInteger("item_count", android_node->GetItemCount()); + dict->SetInteger("row_count", android_node->RowCount()); + dict->SetInteger("column_count", android_node->ColumnCount()); + dict->SetInteger("row_index", android_node->RowIndex()); + dict->SetInteger("row_span", android_node->RowSpan()); + dict->SetInteger("column_index", android_node->ColumnIndex()); + dict->SetInteger("column_span", android_node->ColumnSpan()); + dict->SetInteger("input_type", android_node->AndroidInputType()); + dict->SetInteger("live_region_type", android_node->AndroidLiveRegionType()); + dict->SetInteger("range_min", static_cast<int>(android_node->RangeMin())); + dict->SetInteger("range_max", static_cast<int>(android_node->RangeMax())); + dict->SetInteger("range_current_value", + static_cast<int>(android_node->RangeCurrentValue())); } -string16 AccessibilityTreeFormatter::ToString(const DictionaryValue& dict, - const string16& indent) { - string16 line; +base::string16 AccessibilityTreeFormatter::ToString( + const DictionaryValue& dict, + const base::string16& indent) { + base::string16 line; - string16 class_value; + base::string16 class_value; dict.GetString("class", &class_value); WriteAttribute(true, UTF16ToUTF8(class_value), &line); diff --git a/content/browser/accessibility/accessibility_tree_formatter_gtk.cc b/content/browser/accessibility/accessibility_tree_formatter_gtk.cc index 8dd6b9328a..0dc21ce124 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_gtk.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_gtk.cc @@ -37,9 +37,10 @@ void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node, dict->SetInteger("id", node.renderer_id()); } -string16 AccessibilityTreeFormatter::ToString(const base::DictionaryValue& node, - const string16& indent) { - string16 line; +base::string16 AccessibilityTreeFormatter::ToString( + const base::DictionaryValue& node, + const base::string16& indent) { + base::string16 line; std::string role_value; node.GetString("role", &role_value); if (!role_value.empty()) diff --git a/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/content/browser/accessibility/accessibility_tree_formatter_mac.mm index 58881b4af4..021b5fdc41 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_mac.mm +++ b/content/browser/accessibility/accessibility_tree_formatter_mac.mm @@ -161,9 +161,10 @@ void AccessibilityTreeFormatter::AddProperties(const BrowserAccessibility& node, dict->Set(kSizeDictAttr, PopulateSize(cocoa_node).release()); } -string16 AccessibilityTreeFormatter::ToString(const base::DictionaryValue& dict, - const string16& indent) { - string16 line; +base::string16 AccessibilityTreeFormatter::ToString( + const base::DictionaryValue& dict, + const base::string16& indent) { + base::string16 line; NSArray* defaultAttributes = [NSArray arrayWithObjects:NSAccessibilityTitleAttribute, NSAccessibilityValueAttribute, diff --git a/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc b/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc index 053e39b9b0..e2cebc126c 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc @@ -20,10 +20,10 @@ class AccessibilityRoleStateMap { public: static AccessibilityRoleStateMap* GetInstance(); - std::map<int32, string16> ia_role_string_map; - std::map<int32, string16> ia2_role_string_map; - std::map<int32, string16> ia_state_string_map; - std::map<int32, string16> ia2_state_string_map; + std::map<int32, base::string16> ia_role_string_map; + std::map<int32, base::string16> ia2_role_string_map; + std::map<int32, base::string16> ia_state_string_map; + std::map<int32, base::string16> ia2_state_string_map; private: AccessibilityRoleStateMap(); @@ -220,44 +220,44 @@ AccessibilityRoleStateMap::AccessibilityRoleStateMap() { } // namespace. -string16 IAccessibleRoleToString(int32 ia_role) { +base::string16 IAccessibleRoleToString(int32 ia_role) { return AccessibilityRoleStateMap::GetInstance()->ia_role_string_map[ia_role]; } -string16 IAccessible2RoleToString(int32 ia_role) { +base::string16 IAccessible2RoleToString(int32 ia_role) { return AccessibilityRoleStateMap::GetInstance()->ia2_role_string_map[ia_role]; } void IAccessibleStateToStringVector(int32 ia_state, - std::vector<string16>* result) { - const std::map<int32, string16>& state_string_map = + std::vector<base::string16>* result) { + const std::map<int32, base::string16>& state_string_map = AccessibilityRoleStateMap::GetInstance()->ia_state_string_map; - std::map<int32, string16>::const_iterator it; + std::map<int32, base::string16>::const_iterator it; for (it = state_string_map.begin(); it != state_string_map.end(); ++it) { if (it->first & ia_state) result->push_back(it->second); } } -string16 IAccessibleStateToString(int32 ia_state) { - std::vector<string16> strings; +base::string16 IAccessibleStateToString(int32 ia_state) { + std::vector<base::string16> strings; IAccessibleStateToStringVector(ia_state, &strings); return JoinString(strings, ','); } void IAccessible2StateToStringVector(int32 ia2_state, - std::vector<string16>* result) { - const std::map<int32, string16>& state_string_map = + std::vector<base::string16>* result) { + const std::map<int32, base::string16>& state_string_map = AccessibilityRoleStateMap::GetInstance()->ia2_state_string_map; - std::map<int32, string16>::const_iterator it; + std::map<int32, base::string16>::const_iterator it; for (it = state_string_map.begin(); it != state_string_map.end(); ++it) { if (it->first & ia2_state) result->push_back(it->second); } } -string16 IAccessible2StateToString(int32 ia2_state) { - std::vector<string16> strings; +base::string16 IAccessible2StateToString(int32 ia2_state) { + std::vector<base::string16> strings; IAccessible2StateToStringVector(ia2_state, &strings); return JoinString(strings, ','); } diff --git a/content/browser/accessibility/accessibility_tree_formatter_utils_win.h b/content/browser/accessibility/accessibility_tree_formatter_utils_win.h index 1baf20d54a..86b377a64e 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_utils_win.h +++ b/content/browser/accessibility/accessibility_tree_formatter_utils_win.h @@ -13,14 +13,14 @@ namespace content { -CONTENT_EXPORT string16 IAccessibleRoleToString(int32 ia_role); -CONTENT_EXPORT string16 IAccessible2RoleToString(int32 ia_role); -CONTENT_EXPORT string16 IAccessibleStateToString(int32 ia_state); +CONTENT_EXPORT base::string16 IAccessibleRoleToString(int32 ia_role); +CONTENT_EXPORT base::string16 IAccessible2RoleToString(int32 ia_role); +CONTENT_EXPORT base::string16 IAccessibleStateToString(int32 ia_state); CONTENT_EXPORT void IAccessibleStateToStringVector( - int32 ia_state, std::vector<string16>* result); -CONTENT_EXPORT string16 IAccessible2StateToString(int32 ia2_state); + int32 ia_state, std::vector<base::string16>* result); +CONTENT_EXPORT base::string16 IAccessible2StateToString(int32 ia2_state); CONTENT_EXPORT void IAccessible2StateToStringVector( - int32 ia_state, std::vector<string16>* result); + int32 ia_state, std::vector<base::string16>* result); } // namespace content diff --git a/content/browser/accessibility/accessibility_tree_formatter_win.cc b/content/browser/accessibility/accessibility_tree_formatter_win.cc index 679843dc42..c50b52630d 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_win.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_win.cc @@ -76,7 +76,7 @@ void AccessibilityTreeFormatter::AddProperties( if (hresult == S_OK) dict->SetString("value", msaa_variant.m_str); - std::vector<string16> state_strings; + std::vector<base::string16> state_strings; int32 ia_state = acc_obj->ia_state(); // Avoid flakiness: these states depend on whether the window is focused @@ -87,16 +87,16 @@ void AccessibilityTreeFormatter::AddProperties( IAccessibleStateToStringVector(ia_state, &state_strings); IAccessible2StateToStringVector(acc_obj->ia2_state(), &state_strings); base::ListValue* states = new base::ListValue; - for (std::vector<string16>::const_iterator it = state_strings.begin(); + for (std::vector<base::string16>::const_iterator it = state_strings.begin(); it != state_strings.end(); ++it) { states->AppendString(UTF16ToUTF8(*it)); } dict->Set("states", states); - const std::vector<string16>& ia2_attributes = acc_obj->ia2_attributes(); + const std::vector<base::string16>& ia2_attributes = acc_obj->ia2_attributes(); base::ListValue* attributes = new base::ListValue; - for (std::vector<string16>::const_iterator it = ia2_attributes.begin(); + for (std::vector<base::string16>::const_iterator it = ia2_attributes.begin(); it != ia2_attributes.end(); ++it) { attributes->AppendString(UTF16ToUTF8(*it)); @@ -199,15 +199,16 @@ void AccessibilityTreeFormatter::AddProperties( } } -string16 AccessibilityTreeFormatter::ToString(const base::DictionaryValue& dict, - const string16& indent) { - string16 line; +base::string16 AccessibilityTreeFormatter::ToString( + const base::DictionaryValue& dict, + const base::string16& indent) { + base::string16 line; - string16 role_value; + base::string16 role_value; dict.GetString("role", &role_value); WriteAttribute(true, UTF16ToUTF8(role_value), &line); - string16 name_value; + base::string16 name_value; dict.GetString("name", &name_value); WriteAttribute(true, base::StringPrintf(L"name='%ls'", name_value.c_str()), &line); @@ -220,7 +221,7 @@ string16 AccessibilityTreeFormatter::ToString(const base::DictionaryValue& dict, switch (value->GetType()) { case base::Value::TYPE_STRING: { - string16 string_value; + base::string16 string_value; value->GetAsString(&string_value); WriteAttribute(false, StringPrintf(L"%ls='%ls'", @@ -257,7 +258,7 @@ string16 AccessibilityTreeFormatter::ToString(const base::DictionaryValue& dict, for (base::ListValue::const_iterator it = list_value->begin(); it != list_value->end(); ++it) { - string16 string_value; + base::string16 string_value; if ((*it)->GetAsString(&string_value)) WriteAttribute(false, string_value, &line); } diff --git a/content/browser/accessibility/accessibility_ui.cc b/content/browser/accessibility/accessibility_ui.cc index 7808cc1c5f..5203af6ade 100644 --- a/content/browser/accessibility/accessibility_ui.cc +++ b/content/browser/accessibility/accessibility_ui.cc @@ -233,7 +233,7 @@ void AccessibilityUI::RequestAccessibilityTree(const base::ListValue* args) { } scoped_ptr<AccessibilityTreeFormatter> formatter( AccessibilityTreeFormatter::Create(rvh)); - string16 accessibility_contents_utf16; + base::string16 accessibility_contents_utf16; BrowserAccessibilityManager* manager = host_view->GetBrowserAccessibilityManager(); if (!manager) { diff --git a/content/browser/accessibility/accessibility_win_browsertest.cc b/content/browser/accessibility/accessibility_win_browsertest.cc index 8131513c93..bb35348ba7 100644 --- a/content/browser/accessibility/accessibility_win_browsertest.cc +++ b/content/browser/accessibility/accessibility_win_browsertest.cc @@ -226,7 +226,7 @@ class AccessibleChecker { void CheckAccessibleValue(IAccessible* accessible); void CheckAccessibleState(IAccessible* accessible); void CheckAccessibleChildren(IAccessible* accessible); - string16 RoleVariantToString(const base::win::ScopedVariant& role); + base::string16 RoleVariantToString(const base::win::ScopedVariant& role); // Expected accessible name. Checked against IAccessible::get_accName. std::wstring name_; @@ -403,13 +403,13 @@ void AccessibleChecker::CheckAccessibleChildren(IAccessible* parent) { } } -string16 AccessibleChecker::RoleVariantToString( +base::string16 AccessibleChecker::RoleVariantToString( const base::win::ScopedVariant& role) { if (role.type() == VT_I4) return IAccessibleRoleToString(V_I4(&role)); if (role.type() == VT_BSTR) - return string16(V_BSTR(&role), SysStringLen(V_BSTR(&role))); - return string16(); + return base::string16(V_BSTR(&role), SysStringLen(V_BSTR(&role))); + return base::string16(); } } // namespace diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc index 45f2201771..223cd8df55 100644 --- a/content/browser/accessibility/browser_accessibility.cc +++ b/content/browser/accessibility/browser_accessibility.cc @@ -444,17 +444,17 @@ bool BrowserAccessibility::GetStringAttribute( return false; } -string16 BrowserAccessibility::GetString16Attribute( +base::string16 BrowserAccessibility::GetString16Attribute( StringAttribute attribute) const { std::string value_utf8; if (!GetStringAttribute(attribute, &value_utf8)) - return string16(); + return base::string16(); return UTF8ToUTF16(value_utf8); } bool BrowserAccessibility::GetString16Attribute( StringAttribute attribute, - string16* value) const { + base::string16* value) const { std::string value_utf8; if (!GetStringAttribute(attribute, &value_utf8)) return false; @@ -522,7 +522,7 @@ bool BrowserAccessibility::GetHtmlAttribute( } bool BrowserAccessibility::GetHtmlAttribute( - const char* html_attr, string16* value) const { + const char* html_attr, base::string16* value) const { std::string value_utf8; if (!GetHtmlAttribute(html_attr, &value_utf8)) return false; @@ -537,7 +537,7 @@ bool BrowserAccessibility::GetAriaTristate( *is_defined = false; *is_mixed = false; - string16 value; + base::string16 value; if (!GetHtmlAttribute(html_attr, &value) || value.empty() || EqualsASCII(value, "undefined")) { diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h index 1f858f1751..1258803e37 100644 --- a/content/browser/accessibility/browser_accessibility.h +++ b/content/browser/accessibility/browser_accessibility.h @@ -165,12 +165,15 @@ class CONTENT_EXPORT BrowserAccessibility { gfx::Rect location() const { return location_; } BrowserAccessibilityManager* manager() const { return manager_; } const std::string& name() const { return name_; } + const std::string& value() const { return value_; } int32 renderer_id() const { return renderer_id_; } int32 role() const { return role_; } int32 state() const { return state_; } - const std::string& value() const { return value_; } bool instance_active() const { return instance_active_; } + void set_name(const std::string& name) { name_ = name; } + void set_value(const std::string& value) { value_ = value; } + #if defined(OS_MACOSX) && __OBJC__ BrowserAccessibilityCocoa* ToBrowserAccessibilityCocoa(); #elif defined(OS_WIN) @@ -192,7 +195,7 @@ class CONTENT_EXPORT BrowserAccessibility { // need to distinguish between the default value and a missing attribute), // and another that returns the default value for that type if the // attribute is not present. In addition, strings can be returned as - // either std::string or string16, for convenience. + // either std::string or base::string16, for convenience. bool HasBoolAttribute(AccessibilityNodeData::BoolAttribute attr) const; bool GetBoolAttribute(AccessibilityNodeData::BoolAttribute attr) const; @@ -217,8 +220,8 @@ class CONTENT_EXPORT BrowserAccessibility { std::string* value) const; bool GetString16Attribute(AccessibilityNodeData::StringAttribute attribute, - string16* value) const; - string16 GetString16Attribute( + base::string16* value) const; + base::string16 GetString16Attribute( AccessibilityNodeData::StringAttribute attribute) const; bool HasIntListAttribute( @@ -234,7 +237,7 @@ class CONTENT_EXPORT BrowserAccessibility { // Retrieve the value of a html attribute from the attribute map and // returns true if found. - bool GetHtmlAttribute(const char* attr, string16* value) const; + bool GetHtmlAttribute(const char* attr, base::string16* value) const; bool GetHtmlAttribute(const char* attr, std::string* value) const; // Utility method to handle special cases for ARIA booleans, tristates and @@ -278,6 +281,7 @@ class CONTENT_EXPORT BrowserAccessibility { // The parent of this object, may be NULL if we're the root object. BrowserAccessibility* parent_; + private: // The index of this within its parent object. int32 index_in_parent_; diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc index 433c7a1faf..d8a401b6b6 100644 --- a/content/browser/accessibility/browser_accessibility_android.cc +++ b/content/browser/accessibility/browser_accessibility_android.cc @@ -9,6 +9,38 @@ #include "content/common/accessibility_messages.h" #include "content/common/accessibility_node_data.h" +namespace { + +// These are enums from android.text.InputType in Java: +enum { + ANDROID_TEXT_INPUTTYPE_TYPE_NULL = 0, + ANDROID_TEXT_INPUTTYPE_TYPE_DATETIME = 0x4, + ANDROID_TEXT_INPUTTYPE_TYPE_DATETIME_DATE = 0x14, + ANDROID_TEXT_INPUTTYPE_TYPE_DATETIME_TIME = 0x24, + ANDROID_TEXT_INPUTTYPE_TYPE_NUMBER = 0x2, + ANDROID_TEXT_INPUTTYPE_TYPE_PHONE = 0x3, + ANDROID_TEXT_INPUTTYPE_TYPE_TEXT = 0x1, + ANDROID_TEXT_INPUTTYPE_TYPE_TEXT_URI = 0x11, + ANDROID_TEXT_INPUTTYPE_TYPE_TEXT_WEB_EDIT_TEXT = 0xa1, + ANDROID_TEXT_INPUTTYPE_TYPE_TEXT_WEB_EMAIL = 0xd1, + ANDROID_TEXT_INPUTTYPE_TYPE_TEXT_WEB_PASSWORD = 0xe1 +}; + +// These are enums from android.view.View in Java: +enum { + ANDROID_VIEW_VIEW_ACCESSIBILITY_LIVE_REGION_NONE = 0, + ANDROID_VIEW_VIEW_ACCESSIBILITY_LIVE_REGION_POLITE = 1, + ANDROID_VIEW_VIEW_ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 2 +}; + +// These are enums from +// android.view.accessibility.AccessibilityNodeInfo.RangeInfo in Java: +enum { + ANDROID_VIEW_ACCESSIBILITY_RANGE_TYPE_FLOAT = 1 +}; + +} // namespace + namespace content { // static @@ -40,7 +72,7 @@ bool BrowserAccessibilityAndroid::PlatformIsLeaf() const { return false; // Headings with text can drop their children. - string16 name = GetText(); + base::string16 name = GetText(); if (role() == blink::WebAXRoleHeading && !name.empty()) return true; @@ -78,6 +110,33 @@ bool BrowserAccessibilityAndroid::IsClickable() const { return (PlatformIsLeaf() && !GetText().empty()); } +bool BrowserAccessibilityAndroid::IsCollection() const { + return (role() == blink::WebAXRoleGrid || + role() == blink::WebAXRoleList || + role() == blink::WebAXRoleListBox || + role() == blink::WebAXRoleTable || + role() == blink::WebAXRoleTree); +} + +bool BrowserAccessibilityAndroid::IsCollectionItem() const { + return (role() == blink::WebAXRoleCell || + role() == blink::WebAXRoleColumnHeader || + role() == blink::WebAXRoleDescriptionListTerm || + role() == blink::WebAXRoleListBoxOption || + role() == blink::WebAXRoleListItem || + role() == blink::WebAXRoleRowHeader || + role() == blink::WebAXRoleTreeItem); +} + +bool BrowserAccessibilityAndroid::IsContentInvalid() const { + std::string invalid; + return GetHtmlAttribute("aria-invalid", &invalid); +} + +bool BrowserAccessibilityAndroid::IsDismissable() const { + return false; // No concept of "dismissable" on the web currently. +} + bool BrowserAccessibilityAndroid::IsEnabled() const { return HasState(blink::WebAXStateEnabled); } @@ -95,10 +154,31 @@ bool BrowserAccessibilityAndroid::IsFocused() const { return manager()->GetFocus(manager()->GetRoot()) == this; } +bool BrowserAccessibilityAndroid::IsHeading() const { + return (role() == blink::WebAXRoleColumnHeader || + role() == blink::WebAXRoleHeading || + role() == blink::WebAXRoleRowHeader); +} + +bool BrowserAccessibilityAndroid::IsHierarchical() const { + return (role() == blink::WebAXRoleList || + role() == blink::WebAXRoleTree); +} + +bool BrowserAccessibilityAndroid::IsMultiLine() const { + return role() == blink::WebAXRoleTextArea; +} + bool BrowserAccessibilityAndroid::IsPassword() const { return HasState(blink::WebAXStateProtected); } +bool BrowserAccessibilityAndroid::IsRangeType() const { + return (role() == blink::WebAXRoleProgressIndicator || + role() == blink::WebAXRoleScrollBar || + role() == blink::WebAXRoleSlider); +} + bool BrowserAccessibilityAndroid::IsScrollable() const { int dummy; return GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_X_MAX, &dummy); @@ -112,6 +192,10 @@ bool BrowserAccessibilityAndroid::IsVisibleToUser() const { return !HasState(blink::WebAXStateInvisible); } +bool BrowserAccessibilityAndroid::CanOpenPopup() const { + return HasState(blink::WebAXStateHaspopup); +} + const char* BrowserAccessibilityAndroid::GetClassName() const { const char* class_name = NULL; @@ -168,15 +252,15 @@ const char* BrowserAccessibilityAndroid::GetClassName() const { return class_name; } -string16 BrowserAccessibilityAndroid::GetText() const { +base::string16 BrowserAccessibilityAndroid::GetText() const { if (IsIframe() || role() == blink::WebAXRoleWebArea) { - return string16(); + return base::string16(); } - string16 description = GetString16Attribute( + base::string16 description = GetString16Attribute( AccessibilityNodeData::ATTR_DESCRIPTION); - string16 text; + base::string16 text; if (!name().empty()) text = base::UTF8ToUTF16(name()); else if (!description.empty()) @@ -215,6 +299,7 @@ int BrowserAccessibilityAndroid::GetItemIndex() const { switch(role()) { case blink::WebAXRoleListItem: case blink::WebAXRoleListBoxOption: + case blink::WebAXRoleTreeItem: index = index_in_parent(); break; case blink::WebAXRoleSlider: @@ -320,7 +405,7 @@ int BrowserAccessibilityAndroid::GetTextChangeRemovedCount() const { return (old_len - left - right); } -string16 BrowserAccessibilityAndroid::GetTextChangeBeforeText() const { +base::string16 BrowserAccessibilityAndroid::GetTextChangeBeforeText() const { return old_value_; } @@ -340,6 +425,113 @@ int BrowserAccessibilityAndroid::GetEditableTextLength() const { return value().length(); } +int BrowserAccessibilityAndroid::AndroidInputType() const { + std::string html_tag = GetStringAttribute( + AccessibilityNodeData::ATTR_HTML_TAG); + if (html_tag != "input") + return ANDROID_TEXT_INPUTTYPE_TYPE_NULL; + + std::string type; + if (!GetHtmlAttribute("type", &type)) + return ANDROID_TEXT_INPUTTYPE_TYPE_TEXT; + + if (type == "" || type == "text" || type == "search") + return ANDROID_TEXT_INPUTTYPE_TYPE_TEXT; + else if (type == "date") + return ANDROID_TEXT_INPUTTYPE_TYPE_DATETIME_DATE; + else if (type == "datetime" || type == "datetime-local") + return ANDROID_TEXT_INPUTTYPE_TYPE_DATETIME; + else if (type == "email") + return ANDROID_TEXT_INPUTTYPE_TYPE_TEXT_WEB_EMAIL; + else if (type == "month") + return ANDROID_TEXT_INPUTTYPE_TYPE_DATETIME_DATE; + else if (type == "number") + return ANDROID_TEXT_INPUTTYPE_TYPE_NUMBER; + else if (type == "password") + return ANDROID_TEXT_INPUTTYPE_TYPE_TEXT_WEB_PASSWORD; + else if (type == "tel") + return ANDROID_TEXT_INPUTTYPE_TYPE_PHONE; + else if (type == "time") + return ANDROID_TEXT_INPUTTYPE_TYPE_DATETIME_TIME; + else if (type == "url") + return ANDROID_TEXT_INPUTTYPE_TYPE_TEXT_URI; + else if (type == "week") + return ANDROID_TEXT_INPUTTYPE_TYPE_DATETIME; + + return ANDROID_TEXT_INPUTTYPE_TYPE_NULL; +} + +int BrowserAccessibilityAndroid::AndroidLiveRegionType() const { + std::string live = GetStringAttribute( + AccessibilityNodeData::ATTR_LIVE_STATUS); + if (live == "polite") + return ANDROID_VIEW_VIEW_ACCESSIBILITY_LIVE_REGION_POLITE; + else if (live == "assertive") + return ANDROID_VIEW_VIEW_ACCESSIBILITY_LIVE_REGION_ASSERTIVE; + return ANDROID_VIEW_VIEW_ACCESSIBILITY_LIVE_REGION_NONE; +} + +int BrowserAccessibilityAndroid::AndroidRangeType() const { + return ANDROID_VIEW_ACCESSIBILITY_RANGE_TYPE_FLOAT; +} + +int BrowserAccessibilityAndroid::RowCount() const { + if (role() == blink::WebAXRoleGrid || + role() == blink::WebAXRoleTable) { + return CountChildrenWithRole(blink::WebAXRoleRow); + } + + if (role() == blink::WebAXRoleList || + role() == blink::WebAXRoleListBox || + role() == blink::WebAXRoleTree) { + return PlatformChildCount(); + } + + return 0; +} + +int BrowserAccessibilityAndroid::ColumnCount() const { + if (role() == blink::WebAXRoleGrid || + role() == blink::WebAXRoleTable) { + return CountChildrenWithRole(blink::WebAXRoleColumn); + } + return 0; +} + +int BrowserAccessibilityAndroid::RowIndex() const { + if (role() == blink::WebAXRoleListItem || + role() == blink::WebAXRoleListBoxOption || + role() == blink::WebAXRoleTreeItem) { + return index_in_parent(); + } + + return GetIntAttribute(AccessibilityNodeData::ATTR_TABLE_CELL_ROW_INDEX); +} + +int BrowserAccessibilityAndroid::RowSpan() const { + return GetIntAttribute(AccessibilityNodeData::ATTR_TABLE_CELL_ROW_SPAN); +} + +int BrowserAccessibilityAndroid::ColumnIndex() const { + return GetIntAttribute(AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_INDEX); +} + +int BrowserAccessibilityAndroid::ColumnSpan() const { + return GetIntAttribute(AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_SPAN); +} + +float BrowserAccessibilityAndroid::RangeMin() const { + return GetFloatAttribute(AccessibilityNodeData::ATTR_MIN_VALUE_FOR_RANGE); +} + +float BrowserAccessibilityAndroid::RangeMax() const { + return GetFloatAttribute(AccessibilityNodeData::ATTR_MAX_VALUE_FOR_RANGE); +} + +float BrowserAccessibilityAndroid::RangeCurrentValue() const { + return GetFloatAttribute(AccessibilityNodeData::ATTR_VALUE_FOR_RANGE); +} + bool BrowserAccessibilityAndroid::HasFocusableChild() const { // This is called from PlatformIsLeaf, so don't call PlatformChildCount // from within this! @@ -365,7 +557,7 @@ bool BrowserAccessibilityAndroid::HasOnlyStaticTextChildren() const { } bool BrowserAccessibilityAndroid::IsIframe() const { - string16 html_tag = GetString16Attribute( + base::string16 html_tag = GetString16Attribute( AccessibilityNodeData::ATTR_HTML_TAG); return html_tag == ASCIIToUTF16("iframe"); } @@ -374,16 +566,16 @@ void BrowserAccessibilityAndroid::PostInitialize() { BrowserAccessibility::PostInitialize(); if (IsEditableText()) { - if (base::UTF8ToUTF16(value_) != new_value_) { + if (base::UTF8ToUTF16(value()) != new_value_) { old_value_ = new_value_; - new_value_ = base::UTF8ToUTF16(value_); + new_value_ = base::UTF8ToUTF16(value()); } } - if (role_ == blink::WebAXRoleAlert && first_time_) - manager_->NotifyAccessibilityEvent(blink::WebAXEventAlert, this); + if (role() == blink::WebAXRoleAlert && first_time_) + manager()->NotifyAccessibilityEvent(blink::WebAXEventAlert, this); - string16 live; + base::string16 live; if (GetString16Attribute( AccessibilityNodeData::ATTR_CONTAINER_LIVE_STATUS, &live)) { NotifyLiveRegionUpdate(live); @@ -392,19 +584,30 @@ void BrowserAccessibilityAndroid::PostInitialize() { first_time_ = false; } -void BrowserAccessibilityAndroid::NotifyLiveRegionUpdate(string16& aria_live) { +void BrowserAccessibilityAndroid::NotifyLiveRegionUpdate( + base::string16& aria_live) { if (!EqualsASCII(aria_live, aria_strings::kAriaLivePolite) && !EqualsASCII(aria_live, aria_strings::kAriaLiveAssertive)) return; - string16 text = GetText(); + base::string16 text = GetText(); if (cached_text_ != text) { if (!text.empty()) { - manager_->NotifyAccessibilityEvent(blink::WebAXEventShow, + manager()->NotifyAccessibilityEvent(blink::WebAXEventShow, this); } cached_text_ = text; } } +int BrowserAccessibilityAndroid::CountChildrenWithRole( + blink::WebAXRole role) const { + int count = 0; + for (uint32 i = 0; i < PlatformChildCount(); i++) { + if (PlatformGetChild(i)->role() == role) + count++; + } + return count; +} + } // namespace content diff --git a/content/browser/accessibility/browser_accessibility_android.h b/content/browser/accessibility/browser_accessibility_android.h index 7cb979b64b..2968184b53 100644 --- a/content/browser/accessibility/browser_accessibility_android.h +++ b/content/browser/accessibility/browser_accessibility_android.h @@ -21,16 +21,26 @@ class BrowserAccessibilityAndroid : public BrowserAccessibility { bool IsCheckable() const; bool IsChecked() const; bool IsClickable() const; + bool IsCollection() const; + bool IsCollectionItem() const; + bool IsContentInvalid() const; + bool IsDismissable() const; bool IsEnabled() const; bool IsFocusable() const; bool IsFocused() const; + bool IsHeading() const; + bool IsHierarchical() const; + bool IsMultiLine() const; bool IsPassword() const; + bool IsRangeType() const; bool IsScrollable() const; bool IsSelected() const; bool IsVisibleToUser() const; + bool CanOpenPopup() const; + const char* GetClassName() const; - string16 GetText() const; + base::string16 GetText() const; int GetItemIndex() const; int GetItemCount() const; @@ -43,12 +53,28 @@ class BrowserAccessibilityAndroid : public BrowserAccessibility { int GetTextChangeFromIndex() const; int GetTextChangeAddedCount() const; int GetTextChangeRemovedCount() const; - string16 GetTextChangeBeforeText() const; + base::string16 GetTextChangeBeforeText() const; int GetSelectionStart() const; int GetSelectionEnd() const; int GetEditableTextLength() const; + int AndroidInputType() const; + int AndroidLiveRegionType() const; + int AndroidRangeType() const; + + int RowCount() const; + int ColumnCount() const; + + int RowIndex() const; + int RowSpan() const; + int ColumnIndex() const; + int ColumnSpan() const; + + float RangeMin() const; + float RangeMax() const; + float RangeCurrentValue() const; + private: // This gives BrowserAccessibility::Create access to the class constructor. friend class BrowserAccessibility; @@ -59,12 +85,14 @@ class BrowserAccessibilityAndroid : public BrowserAccessibility { bool HasOnlyStaticTextChildren() const; bool IsIframe() const; - void NotifyLiveRegionUpdate(string16& aria_live); + void NotifyLiveRegionUpdate(base::string16& aria_live); + + int CountChildrenWithRole(blink::WebAXRole role) const; - string16 cached_text_; + base::string16 cached_text_; bool first_time_; - string16 old_value_; - string16 new_value_; + base::string16 old_value_; + base::string16 new_value_; DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityAndroid); }; diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm index 15ac608447..9364dbbfc0 100644 --- a/content/browser/accessibility/browser_accessibility_cocoa.mm +++ b/content/browser/accessibility/browser_accessibility_cocoa.mm @@ -569,7 +569,7 @@ NSDictionary* attributeToMethodNameMap = nil; } - (NSString*)invalid { - string16 invalidUTF; + base::string16 invalidUTF; if (!browserAccessibility_->GetHtmlAttribute("aria-invalid", &invalidUTF)) return NULL; NSString* invalid = base::SysUTF16ToNSString(invalidUTF); @@ -1296,10 +1296,10 @@ NSDictionary* attributeToMethodNameMap = nil; nil]]; } else if ([role isEqualToString:NSAccessibilityRowRole]) { if (browserAccessibility_->parent()) { - string16 parentRole; + base::string16 parentRole; browserAccessibility_->parent()->GetHtmlAttribute( "role", &parentRole); - const string16 treegridRole(ASCIIToUTF16("treegrid")); + const base::string16 treegridRole(ASCIIToUTF16("treegrid")); if (parentRole == treegridRole) { [ret addObjectsFromArray:[NSArray arrayWithObjects: NSAccessibilityDisclosingAttribute, diff --git a/content/browser/accessibility/browser_accessibility_gtk.cc b/content/browser/accessibility/browser_accessibility_gtk.cc index c89aa2b63e..06a164cb92 100644 --- a/content/browser/accessibility/browser_accessibility_gtk.cc +++ b/content/browser/accessibility/browser_accessibility_gtk.cc @@ -475,7 +475,7 @@ bool BrowserAccessibilityGtk::IsNative() const { } void BrowserAccessibilityGtk::InitRoleAndState() { - switch(role_) { + switch(role()) { case blink::WebAXRoleDocument: case blink::WebAXRoleRootWebArea: case blink::WebAXRoleWebArea: diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc index 7cd6e85565..63f461c859 100644 --- a/content/browser/accessibility/browser_accessibility_manager_android.cc +++ b/content/browser/accessibility/browser_accessibility_manager_android.cc @@ -229,6 +229,40 @@ jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo( absolute_rect.width(), absolute_rect.height(), is_root); + // New KitKat APIs + Java_BrowserAccessibilityManager_setAccessibilityNodeInfoKitKatAttributes( + env, obj, info, + node->CanOpenPopup(), + node->IsContentInvalid(), + node->IsDismissable(), + node->IsMultiLine(), + node->AndroidInputType(), + node->AndroidLiveRegionType()); + if (node->IsCollection()) { + Java_BrowserAccessibilityManager_setAccessibilityNodeInfoCollectionInfo( + env, obj, info, + node->RowCount(), + node->ColumnCount(), + node->IsHierarchical()); + } + if (node->IsCollectionItem() || node->IsHeading()) { + Java_BrowserAccessibilityManager_setAccessibilityNodeInfoCollectionItemInfo( + env, obj, info, + node->RowIndex(), + node->RowSpan(), + node->ColumnIndex(), + node->ColumnSpan(), + node->IsHeading()); + } + if (node->IsRangeType()) { + Java_BrowserAccessibilityManager_setAccessibilityNodeInfoRangeInfo( + env, obj, info, + node->AndroidRangeType(), + node->RangeMin(), + node->RangeMax(), + node->RangeCurrentValue()); + } + return true; } @@ -282,6 +316,40 @@ jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityEvent( break; } + // Backwards-compatible fallback for new KitKat APIs. + Java_BrowserAccessibilityManager_setAccessibilityEventKitKatAttributes( + env, obj, event, + node->CanOpenPopup(), + node->IsContentInvalid(), + node->IsDismissable(), + node->IsMultiLine(), + node->AndroidInputType(), + node->AndroidLiveRegionType()); + if (node->IsCollection()) { + Java_BrowserAccessibilityManager_setAccessibilityEventCollectionInfo( + env, obj, event, + node->RowCount(), + node->ColumnCount(), + node->IsHierarchical()); + } + if (node->IsCollectionItem() || node->IsHeading()) { + Java_BrowserAccessibilityManager_setAccessibilityEventCollectionItemInfo( + env, obj, event, + node->RowIndex(), + node->RowSpan(), + node->ColumnIndex(), + node->ColumnSpan(), + node->IsHeading()); + } + if (node->IsRangeType()) { + Java_BrowserAccessibilityManager_setAccessibilityEventRangeInfo( + env, obj, event, + node->AndroidRangeType(), + node->RangeMin(), + node->RangeMax(), + node->RangeCurrentValue()); + } + return true; } diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc index 5158935c31..d4dbe6dde2 100644 --- a/content/browser/accessibility/browser_accessibility_manager_win.cc +++ b/content/browser/accessibility/browser_accessibility_manager_win.cc @@ -64,6 +64,12 @@ class AccessibleHWND IAccessible* window_accessible() { return window_accessible_; } + protected: + virtual void OnFinalMessage(HWND hwnd) OVERRIDE { + manager_->OnAccessibleHwndDeleted(); + delete this; + } + private: LRESULT OnGetObject(UINT message, WPARAM w_param, @@ -109,7 +115,8 @@ BrowserAccessibilityManagerWin::BrowserAccessibilityManagerWin( parent_iaccessible_(parent_iaccessible), tracked_scroll_object_(NULL), is_chrome_frame_( - CommandLine::ForCurrentProcess()->HasSwitch("chrome-frame")) { + CommandLine::ForCurrentProcess()->HasSwitch("chrome-frame")), + accessible_hwnd_(NULL) { } BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() { @@ -143,9 +150,8 @@ void BrowserAccessibilityManagerWin::MaybeCallNotifyWinEvent(DWORD event, // accessibility tree. See comments above AccessibleHWND for details. if (BrowserAccessibilityStateImpl::GetInstance()->IsAccessibleBrowser() && !is_chrome_frame_ && - !accessible_hwnd_ && - base::win::GetVersion() < base::win::VERSION_WIN8) { - accessible_hwnd_.reset(new AccessibleHWND(parent_hwnd_, this)); + !accessible_hwnd_) { + accessible_hwnd_ = new AccessibleHWND(parent_hwnd_, this); parent_hwnd_ = accessible_hwnd_->hwnd(); parent_iaccessible_ = accessible_hwnd_->window_accessible(); } @@ -298,4 +304,8 @@ BrowserAccessibilityWin* BrowserAccessibilityManagerWin::GetFromUniqueIdWin( return NULL; } +void BrowserAccessibilityManagerWin::OnAccessibleHwndDeleted() { + accessible_hwnd_ = NULL; +} + } // namespace content diff --git a/content/browser/accessibility/browser_accessibility_manager_win.h b/content/browser/accessibility/browser_accessibility_manager_win.h index c1887c477f..cbfc877909 100644 --- a/content/browser/accessibility/browser_accessibility_manager_win.h +++ b/content/browser/accessibility/browser_accessibility_manager_win.h @@ -58,6 +58,9 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin // unique id, does not make a new reference. BrowserAccessibilityWin* GetFromUniqueIdWin(LONG unique_id_win); + // Called when |accessible_hwnd_| is deleted by its parent. + void OnAccessibleHwndDeleted(); + private: // The closest ancestor HWND. HWND parent_hwnd_; @@ -79,7 +82,8 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin bool is_chrome_frame_; - scoped_ptr<AccessibleHWND> accessible_hwnd_; + // Owned by its parent; OnAccessibleHwndDeleted gets called upon deletion. + AccessibleHWND* accessible_hwnd_; DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManagerWin); }; diff --git a/content/browser/accessibility/browser_accessibility_state_impl_win.cc b/content/browser/accessibility/browser_accessibility_state_impl_win.cc index 824055f6e5..28f05e0e7e 100644 --- a/content/browser/accessibility/browser_accessibility_state_impl_win.cc +++ b/content/browser/accessibility/browser_accessibility_state_impl_win.cc @@ -57,7 +57,7 @@ void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() { for (size_t i = 0; i < module_count; i++) { TCHAR filename[MAX_PATH]; GetModuleFileName(modules[i], filename, sizeof(filename)); - string16 module_name(base::FilePath(filename).BaseName().value()); + base::string16 module_name(base::FilePath(filename).BaseName().value()); if (LowerCaseEqualsASCII(module_name, "fsdomsrv.dll")) jaws = true; if (LowerCaseEqualsASCII(module_name, "vbufbackend_gecko_ia2.dll")) diff --git a/content/browser/accessibility/browser_accessibility_win.cc b/content/browser/accessibility/browser_accessibility_win.cc index fb4c32e700..b43154a06e 100644 --- a/content/browser/accessibility/browser_accessibility_win.cc +++ b/content/browser/accessibility/browser_accessibility_win.cc @@ -58,7 +58,7 @@ class BrowserAccessibilityRelation CONTENT_EXPORT virtual ~BrowserAccessibilityRelation() {} CONTENT_EXPORT void Initialize(BrowserAccessibilityWin* owner, - const string16& type); + const base::string16& type); CONTENT_EXPORT void AddTarget(int target_id); // IAccessibleRelation methods. @@ -75,13 +75,13 @@ class BrowserAccessibilityRelation } private: - string16 type_; + base::string16 type_; base::win::ScopedComPtr<BrowserAccessibilityWin> owner_; std::vector<int> target_ids_; }; void BrowserAccessibilityRelation::Initialize(BrowserAccessibilityWin* owner, - const string16& type) { + const base::string16& type) { owner_ = owner; type_ = type; } @@ -217,27 +217,27 @@ BrowserAccessibilityWin::~BrowserAccessibilityWin() { // IAccessible methods. // // Conventions: -// * Always test for instance_active_ first and return E_FAIL if it's false. +// * Always test for instance_active() first and return E_FAIL if it's false. // * Always check for invalid arguments first, even if they're unused. // * Return S_FALSE if the only output is a string argument and it's empty. // HRESULT BrowserAccessibilityWin::accDoDefaultAction(VARIANT var_id) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; BrowserAccessibilityWin* target = GetTargetFromChildID(var_id); if (!target) return E_INVALIDARG; - manager_->DoDefaultAction(*target); + manager()->DoDefaultAction(*target); return S_OK; } STDMETHODIMP BrowserAccessibilityWin::accHitTest(LONG x_left, LONG y_top, VARIANT* child) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!child) @@ -267,7 +267,7 @@ STDMETHODIMP BrowserAccessibilityWin::accLocation(LONG* x_left, LONG* width, LONG* height, VARIANT var_id) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!x_left || !y_top || !width || !height) @@ -337,7 +337,7 @@ STDMETHODIMP BrowserAccessibilityWin::accNavigate(LONG nav_dir, STDMETHODIMP BrowserAccessibilityWin::get_accChild(VARIANT var_child, IDispatch** disp_child) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!disp_child) @@ -354,7 +354,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accChild(VARIANT var_child, } STDMETHODIMP BrowserAccessibilityWin::get_accChildCount(LONG* child_count) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!child_count) @@ -367,7 +367,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accChildCount(LONG* child_count) { STDMETHODIMP BrowserAccessibilityWin::get_accDefaultAction(VARIANT var_id, BSTR* def_action) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!def_action) @@ -383,7 +383,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accDefaultAction(VARIANT var_id, STDMETHODIMP BrowserAccessibilityWin::get_accDescription(VARIANT var_id, BSTR* desc) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!desc) @@ -398,14 +398,14 @@ STDMETHODIMP BrowserAccessibilityWin::get_accDescription(VARIANT var_id, } STDMETHODIMP BrowserAccessibilityWin::get_accFocus(VARIANT* focus_child) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!focus_child) return E_INVALIDARG; BrowserAccessibilityWin* focus = static_cast<BrowserAccessibilityWin*>( - manager_->GetFocus(this)); + manager()->GetFocus(this)); if (focus == this) { focus_child->vt = VT_I4; focus_child->lVal = CHILDID_SELF; @@ -420,7 +420,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accFocus(VARIANT* focus_child) { } STDMETHODIMP BrowserAccessibilityWin::get_accHelp(VARIANT var_id, BSTR* help) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!help) @@ -436,7 +436,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accHelp(VARIANT var_id, BSTR* help) { STDMETHODIMP BrowserAccessibilityWin::get_accKeyboardShortcut(VARIANT var_id, BSTR* acc_key) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!acc_key) @@ -451,7 +451,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accKeyboardShortcut(VARIANT var_id, } STDMETHODIMP BrowserAccessibilityWin::get_accName(VARIANT var_id, BSTR* name) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!name) @@ -469,7 +469,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accName(VARIANT var_id, BSTR* name) { if (target->GetIntAttribute(AccessibilityNodeData::ATTR_TITLE_UI_ELEMENT, &title_elem_id)) { BrowserAccessibility* title_elem = - manager_->GetFromRendererID(title_elem_id); + manager()->GetFromRendererID(title_elem_id); if (title_elem) name_str = title_elem->GetTextRecursive(); } @@ -485,31 +485,33 @@ STDMETHODIMP BrowserAccessibilityWin::get_accName(VARIANT var_id, BSTR* name) { } STDMETHODIMP BrowserAccessibilityWin::get_accParent(IDispatch** disp_parent) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!disp_parent) return E_INVALIDARG; - IAccessible* parent = parent_->ToBrowserAccessibilityWin(); - if (parent == NULL) { + IAccessible* parent_obj = parent()->ToBrowserAccessibilityWin(); + if (parent_obj == NULL) { // This happens if we're the root of the tree; // return the IAccessible for the window. - parent = manager_->ToBrowserAccessibilityManagerWin()->parent_iaccessible(); + parent_obj = + manager()->ToBrowserAccessibilityManagerWin()->parent_iaccessible(); + // |parent| can only be NULL if the manager was created before the parent // IAccessible was known and it wasn't subsequently set before a client // requested it. Crash hard if this happens so that we get crash reports. - CHECK(parent); + CHECK(parent_obj); } - parent->AddRef(); - *disp_parent = parent; + parent_obj->AddRef(); + *disp_parent = parent_obj; return S_OK; } STDMETHODIMP BrowserAccessibilityWin::get_accRole(VARIANT var_id, VARIANT* role) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!role) @@ -531,7 +533,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accRole(VARIANT var_id, STDMETHODIMP BrowserAccessibilityWin::get_accState(VARIANT var_id, VARIANT* state) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!state) @@ -543,7 +545,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accState(VARIANT var_id, state->vt = VT_I4; state->lVal = target->ia_state_; - if (manager_->GetFocus(NULL) == this) + if (manager()->GetFocus(NULL) == this) state->lVal |= STATE_SYSTEM_FOCUSED; return S_OK; @@ -551,7 +553,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accState(VARIANT var_id, STDMETHODIMP BrowserAccessibilityWin::get_accValue(VARIANT var_id, BSTR* value) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!value) @@ -564,7 +566,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accValue(VARIANT var_id, if (target->ia_role() == ROLE_SYSTEM_PROGRESSBAR || target->ia_role() == ROLE_SYSTEM_SCROLLBAR || target->ia_role() == ROLE_SYSTEM_SLIDER) { - string16 value_text = target->GetValueText(); + base::string16 value_text = target->GetValueText(); *value = SysAllocString(value_text.c_str()); DCHECK(*value); return S_OK; @@ -578,7 +580,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accValue(VARIANT var_id, AccessibilityNodeData::ATTR_COLOR_VALUE_GREEN); int b = target->GetIntAttribute( AccessibilityNodeData::ATTR_COLOR_VALUE_BLUE); - string16 value_text; + base::string16 value_text; value_text = base::IntToString16((r * 100) / 255) + L"% red " + base::IntToString16((g * 100) / 255) + L"% green " + base::IntToString16((b * 100) / 255) + L"% blue"; @@ -599,15 +601,15 @@ STDMETHODIMP BrowserAccessibilityWin::get_accHelpTopic(BSTR* help_file, } STDMETHODIMP BrowserAccessibilityWin::get_accSelection(VARIANT* selected) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; - if (role_ != blink::WebAXRoleListBox) + if (blink_role() != blink::WebAXRoleListBox) return E_NOTIMPL; unsigned long selected_count = 0; - for (size_t i = 0; i < children_.size(); ++i) { - if (children_[i]->HasState(blink::WebAXStateSelected)) + for (size_t i = 0; i < children().size(); ++i) { + if (children()[i]->HasState(blink::WebAXStateSelected)) ++selected_count; } @@ -617,11 +619,11 @@ STDMETHODIMP BrowserAccessibilityWin::get_accSelection(VARIANT* selected) { } if (selected_count == 1) { - for (size_t i = 0; i < children_.size(); ++i) { - if (children_[i]->HasState(blink::WebAXStateSelected)) { + for (size_t i = 0; i < children().size(); ++i) { + if (children()[i]->HasState(blink::WebAXStateSelected)) { selected->vt = VT_DISPATCH; selected->pdispVal = - children_[i]->ToBrowserAccessibilityWin()->NewReference(); + children()[i]->ToBrowserAccessibilityWin()->NewReference(); return S_OK; } } @@ -632,11 +634,11 @@ STDMETHODIMP BrowserAccessibilityWin::get_accSelection(VARIANT* selected) { new base::win::EnumVariant(selected_count); enum_variant->AddRef(); unsigned long index = 0; - for (size_t i = 0; i < children_.size(); ++i) { - if (children_[i]->HasState(blink::WebAXStateSelected)) { + for (size_t i = 0; i < children().size(); ++i) { + if (children()[i]->HasState(blink::WebAXStateSelected)) { enum_variant->ItemAt(index)->vt = VT_DISPATCH; enum_variant->ItemAt(index)->pdispVal = - children_[i]->ToBrowserAccessibilityWin()->NewReference(); + children()[i]->ToBrowserAccessibilityWin()->NewReference(); ++index; } } @@ -648,11 +650,11 @@ STDMETHODIMP BrowserAccessibilityWin::get_accSelection(VARIANT* selected) { STDMETHODIMP BrowserAccessibilityWin::accSelect( LONG flags_sel, VARIANT var_id) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (flags_sel & SELFLAG_TAKEFOCUS) { - manager_->SetFocus(this, true); + manager()->SetFocus(this, true); return S_OK; } @@ -664,7 +666,7 @@ STDMETHODIMP BrowserAccessibilityWin::accSelect( // STDMETHODIMP BrowserAccessibilityWin::role(LONG* role) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!role) @@ -676,7 +678,7 @@ STDMETHODIMP BrowserAccessibilityWin::role(LONG* role) { } STDMETHODIMP BrowserAccessibilityWin::get_attributes(BSTR* attributes) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!attributes) @@ -684,7 +686,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_attributes(BSTR* attributes) { // The iaccessible2 attributes are a set of key-value pairs // separated by semicolons, with a colon between the key and the value. - string16 str; + base::string16 str; for (unsigned int i = 0; i < ia2_attributes_.size(); ++i) { if (i != 0) str += L';'; @@ -700,7 +702,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_attributes(BSTR* attributes) { } STDMETHODIMP BrowserAccessibilityWin::get_states(AccessibleStates* states) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!states) @@ -712,7 +714,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_states(AccessibleStates* states) { } STDMETHODIMP BrowserAccessibilityWin::get_uniqueID(LONG* unique_id) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!unique_id) @@ -723,29 +725,29 @@ STDMETHODIMP BrowserAccessibilityWin::get_uniqueID(LONG* unique_id) { } STDMETHODIMP BrowserAccessibilityWin::get_windowHandle(HWND* window_handle) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!window_handle) return E_INVALIDARG; - *window_handle = manager_->ToBrowserAccessibilityManagerWin()->parent_hwnd(); + *window_handle = manager()->ToBrowserAccessibilityManagerWin()->parent_hwnd(); return S_OK; } STDMETHODIMP BrowserAccessibilityWin::get_indexInParent(LONG* index_in_parent) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!index_in_parent) return E_INVALIDARG; - *index_in_parent = index_in_parent_; + *index_in_parent = this->index_in_parent(); return S_OK; } STDMETHODIMP BrowserAccessibilityWin::get_nRelations(LONG* n_relations) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!n_relations) @@ -758,7 +760,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nRelations(LONG* n_relations) { STDMETHODIMP BrowserAccessibilityWin::get_relation( LONG relation_index, IAccessibleRelation** relation) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (relation_index < 0 || @@ -778,7 +780,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_relations( LONG max_relations, IAccessibleRelation** relations, LONG* n_relations) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!relations || !n_relations) @@ -798,41 +800,41 @@ STDMETHODIMP BrowserAccessibilityWin::get_relations( } STDMETHODIMP BrowserAccessibilityWin::scrollTo(enum IA2ScrollType scroll_type) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; - gfx::Rect r = location_; + gfx::Rect r = location(); switch(scroll_type) { case IA2_SCROLL_TYPE_TOP_LEFT: - manager_->ScrollToMakeVisible(*this, gfx::Rect(r.x(), r.y(), 0, 0)); + manager()->ScrollToMakeVisible(*this, gfx::Rect(r.x(), r.y(), 0, 0)); break; case IA2_SCROLL_TYPE_BOTTOM_RIGHT: - manager_->ScrollToMakeVisible( + manager()->ScrollToMakeVisible( *this, gfx::Rect(r.right(), r.bottom(), 0, 0)); break; case IA2_SCROLL_TYPE_TOP_EDGE: - manager_->ScrollToMakeVisible( + manager()->ScrollToMakeVisible( *this, gfx::Rect(r.x(), r.y(), r.width(), 0)); break; case IA2_SCROLL_TYPE_BOTTOM_EDGE: - manager_->ScrollToMakeVisible( + manager()->ScrollToMakeVisible( *this, gfx::Rect(r.x(), r.bottom(), r.width(), 0)); break; case IA2_SCROLL_TYPE_LEFT_EDGE: - manager_->ScrollToMakeVisible( + manager()->ScrollToMakeVisible( *this, gfx::Rect(r.x(), r.y(), 0, r.height())); break; case IA2_SCROLL_TYPE_RIGHT_EDGE: - manager_->ScrollToMakeVisible( + manager()->ScrollToMakeVisible( *this, gfx::Rect(r.right(), r.y(), 0, r.height())); break; case IA2_SCROLL_TYPE_ANYWHERE: default: - manager_->ScrollToMakeVisible(*this, r); + manager()->ScrollToMakeVisible(*this, r); break; } - manager_->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this); + manager()->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this); return S_OK; } @@ -841,22 +843,22 @@ STDMETHODIMP BrowserAccessibilityWin::scrollToPoint( enum IA2CoordinateType coordinate_type, LONG x, LONG y) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; gfx::Point scroll_to(x, y); if (coordinate_type == IA2_COORDTYPE_SCREEN_RELATIVE) { - scroll_to -= manager_->GetViewBounds().OffsetFromOrigin(); + scroll_to -= manager()->GetViewBounds().OffsetFromOrigin(); } else if (coordinate_type == IA2_COORDTYPE_PARENT_RELATIVE) { - if (parent_) - scroll_to += parent_->location().OffsetFromOrigin(); + if (parent()) + scroll_to += parent()->location().OffsetFromOrigin(); } else { return E_INVALIDARG; } - manager_->ScrollToPoint(*this, scroll_to); - manager_->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this); + manager()->ScrollToPoint(*this, scroll_to); + manager()->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this); return S_OK; } @@ -865,18 +867,18 @@ STDMETHODIMP BrowserAccessibilityWin::get_groupPosition( LONG* group_level, LONG* similar_items_in_group, LONG* position_in_group) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!group_level || !similar_items_in_group || !position_in_group) return E_INVALIDARG; - if (role_ == blink::WebAXRoleListBoxOption && - parent_ && - parent_->role() == blink::WebAXRoleListBox) { + if (blink_role() == blink::WebAXRoleListBoxOption && + parent() && + parent()->role() == blink::WebAXRoleListBox) { *group_level = 0; - *similar_items_in_group = parent_->PlatformChildCount(); - *position_in_group = index_in_parent_ + 1; + *similar_items_in_group = parent()->PlatformChildCount(); + *position_in_group = index_in_parent() + 1; return S_OK; } @@ -888,7 +890,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_groupPosition( // STDMETHODIMP BrowserAccessibilityWin::get_appName(BSTR* app_name) { - // No need to check |instance_active_| because this interface is + // No need to check |instance_active()| because this interface is // global, and doesn't depend on any local state. if (!app_name) @@ -907,7 +909,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_appName(BSTR* app_name) { } STDMETHODIMP BrowserAccessibilityWin::get_appVersion(BSTR* app_version) { - // No need to check |instance_active_| because this interface is + // No need to check |instance_active()| because this interface is // global, and doesn't depend on any local state. if (!app_version) @@ -926,7 +928,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_appVersion(BSTR* app_version) { } STDMETHODIMP BrowserAccessibilityWin::get_toolkitName(BSTR* toolkit_name) { - // No need to check |instance_active_| because this interface is + // No need to check |instance_active()| because this interface is // global, and doesn't depend on any local state. if (!toolkit_name) @@ -942,7 +944,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_toolkitName(BSTR* toolkit_name) { STDMETHODIMP BrowserAccessibilityWin::get_toolkitVersion( BSTR* toolkit_version) { - // No need to check |instance_active_| because this interface is + // No need to check |instance_active()| because this interface is // global, and doesn't depend on any local state. if (!toolkit_version) @@ -959,7 +961,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_toolkitVersion( // STDMETHODIMP BrowserAccessibilityWin::get_description(BSTR* desc) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!desc) @@ -973,7 +975,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_imagePosition( enum IA2CoordinateType coordinate_type, LONG* x, LONG* y) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!x || !y) @@ -981,17 +983,17 @@ STDMETHODIMP BrowserAccessibilityWin::get_imagePosition( if (coordinate_type == IA2_COORDTYPE_SCREEN_RELATIVE) { HWND parent_hwnd = - manager_->ToBrowserAccessibilityManagerWin()->parent_hwnd(); + manager()->ToBrowserAccessibilityManagerWin()->parent_hwnd(); POINT top_left = {0, 0}; ::ClientToScreen(parent_hwnd, &top_left); - *x = location_.x() + top_left.x; - *y = location_.y() + top_left.y; + *x = location().x() + top_left.x; + *y = location().y() + top_left.y; } else if (coordinate_type == IA2_COORDTYPE_PARENT_RELATIVE) { - *x = location_.x(); - *y = location_.y(); - if (parent_) { - *x -= parent_->location().x(); - *y -= parent_->location().y(); + *x = location().x(); + *y = location().y(); + if (parent()) { + *x -= parent()->location().x(); + *y -= parent()->location().y(); } } else { return E_INVALIDARG; @@ -1001,14 +1003,14 @@ STDMETHODIMP BrowserAccessibilityWin::get_imagePosition( } STDMETHODIMP BrowserAccessibilityWin::get_imageSize(LONG* height, LONG* width) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!height || !width) return E_INVALIDARG; - *height = location_.height(); - *width = location_.width(); + *height = location().height(); + *width = location().width(); return S_OK; } @@ -1020,7 +1022,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accessibleAt( long row, long column, IUnknown** accessible) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!accessible) @@ -1056,7 +1058,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accessibleAt( } STDMETHODIMP BrowserAccessibilityWin::get_caption(IUnknown** accessible) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!accessible) @@ -1069,7 +1071,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_caption(IUnknown** accessible) { STDMETHODIMP BrowserAccessibilityWin::get_childIndex(long row, long column, long* cell_index) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!cell_index) @@ -1107,7 +1109,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_childIndex(long row, STDMETHODIMP BrowserAccessibilityWin::get_columnDescription(long column, BSTR* description) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!description) @@ -1131,9 +1133,9 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnDescription(long column, for (int i = 0; i < rows; ++i) { int cell_id = cell_ids[i * columns + column]; BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>( - manager_->GetFromRendererID(cell_id)); - if (cell && cell->role_ == blink::WebAXRoleColumnHeader) { - string16 cell_name = cell->GetString16Attribute( + manager()->GetFromRendererID(cell_id)); + if (cell && cell->blink_role() == blink::WebAXRoleColumnHeader) { + base::string16 cell_name = cell->GetString16Attribute( AccessibilityNodeData::ATTR_NAME); if (cell_name.size() > 0) { *description = SysAllocString(cell_name.c_str()); @@ -1152,7 +1154,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnExtentAt( long row, long column, long* n_columns_spanned) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!n_columns_spanned) @@ -1175,7 +1177,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnExtentAt( AccessibilityNodeData::ATTR_CELL_IDS); int cell_id = cell_ids[row * columns + column]; BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>( - manager_->GetFromRendererID(cell_id)); + manager()->GetFromRendererID(cell_id)); int colspan; if (cell && cell->GetIntAttribute( @@ -1197,7 +1199,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeader( STDMETHODIMP BrowserAccessibilityWin::get_columnIndex(long cell_index, long* column_index) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!column_index) @@ -1213,7 +1215,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnIndex(long cell_index, int cell_id = unique_cell_ids[cell_index]; BrowserAccessibilityWin* cell = - manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); + manager()->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); int col_index; if (cell && cell->GetIntAttribute( @@ -1226,7 +1228,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnIndex(long cell_index, } STDMETHODIMP BrowserAccessibilityWin::get_nColumns(long* column_count) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!column_count) @@ -1243,7 +1245,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nColumns(long* column_count) { } STDMETHODIMP BrowserAccessibilityWin::get_nRows(long* row_count) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!row_count) @@ -1259,7 +1261,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nRows(long* row_count) { } STDMETHODIMP BrowserAccessibilityWin::get_nSelectedChildren(long* cell_count) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!cell_count) @@ -1271,7 +1273,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nSelectedChildren(long* cell_count) { } STDMETHODIMP BrowserAccessibilityWin::get_nSelectedColumns(long* column_count) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!column_count) @@ -1282,7 +1284,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nSelectedColumns(long* column_count) { } STDMETHODIMP BrowserAccessibilityWin::get_nSelectedRows(long* row_count) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!row_count) @@ -1294,7 +1296,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nSelectedRows(long* row_count) { STDMETHODIMP BrowserAccessibilityWin::get_rowDescription(long row, BSTR* description) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!description) @@ -1318,9 +1320,9 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowDescription(long row, for (int i = 0; i < columns; ++i) { int cell_id = cell_ids[row * columns + i]; BrowserAccessibilityWin* cell = - manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); - if (cell && cell->role_ == blink::WebAXRoleRowHeader) { - string16 cell_name = cell->GetString16Attribute( + manager()->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); + if (cell && cell->blink_role() == blink::WebAXRoleRowHeader) { + base::string16 cell_name = cell->GetString16Attribute( AccessibilityNodeData::ATTR_NAME); if (cell_name.size() > 0) { *description = SysAllocString(cell_name.c_str()); @@ -1338,7 +1340,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowDescription(long row, STDMETHODIMP BrowserAccessibilityWin::get_rowExtentAt(long row, long column, long* n_rows_spanned) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!n_rows_spanned) @@ -1361,7 +1363,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowExtentAt(long row, AccessibilityNodeData::ATTR_CELL_IDS); int cell_id = cell_ids[row * columns + column]; BrowserAccessibilityWin* cell = - manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); + manager()->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); int rowspan; if (cell && cell->GetIntAttribute( @@ -1383,7 +1385,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowHeader( STDMETHODIMP BrowserAccessibilityWin::get_rowIndex(long cell_index, long* row_index) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!row_index) @@ -1399,7 +1401,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowIndex(long cell_index, int cell_id = unique_cell_ids[cell_index]; BrowserAccessibilityWin* cell = - manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); + manager()->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); int cell_row_index; if (cell && cell->GetIntAttribute( @@ -1414,7 +1416,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowIndex(long cell_index, STDMETHODIMP BrowserAccessibilityWin::get_selectedChildren(long max_children, long** children, long* n_children) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!children || !n_children) @@ -1428,7 +1430,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_selectedChildren(long max_children, STDMETHODIMP BrowserAccessibilityWin::get_selectedColumns(long max_columns, long** columns, long* n_columns) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!columns || !n_columns) @@ -1442,7 +1444,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_selectedColumns(long max_columns, STDMETHODIMP BrowserAccessibilityWin::get_selectedRows(long max_rows, long** rows, long* n_rows) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!rows || !n_rows) @@ -1454,7 +1456,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_selectedRows(long max_rows, } STDMETHODIMP BrowserAccessibilityWin::get_summary(IUnknown** accessible) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!accessible) @@ -1467,7 +1469,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_summary(IUnknown** accessible) { STDMETHODIMP BrowserAccessibilityWin::get_isColumnSelected( long column, boolean* is_selected) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!is_selected) @@ -1480,7 +1482,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_isColumnSelected( STDMETHODIMP BrowserAccessibilityWin::get_isRowSelected(long row, boolean* is_selected) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!is_selected) @@ -1494,7 +1496,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_isRowSelected(long row, STDMETHODIMP BrowserAccessibilityWin::get_isSelected(long row, long column, boolean* is_selected) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!is_selected) @@ -1512,7 +1514,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowColumnExtentsAtIndex( long* row_extents, long* column_extents, boolean* is_selected) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!row || !column || !row_extents || !column_extents || !is_selected) @@ -1528,7 +1530,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowColumnExtentsAtIndex( int cell_id = unique_cell_ids[index]; BrowserAccessibilityWin* cell = - manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); + manager()->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); int rowspan; int colspan; if (cell && @@ -1563,7 +1565,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nSelectedCells(long* cell_count) { STDMETHODIMP BrowserAccessibilityWin::get_selectedCells( IUnknown*** cells, long* n_selected_cells) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!cells || !n_selected_cells) @@ -1576,7 +1578,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_selectedCells( STDMETHODIMP BrowserAccessibilityWin::get_selectedColumns(long** columns, long* n_columns) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!columns || !n_columns) @@ -1589,7 +1591,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_selectedColumns(long** columns, STDMETHODIMP BrowserAccessibilityWin::get_selectedRows(long** rows, long* n_rows) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!rows || !n_rows) @@ -1607,7 +1609,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_selectedRows(long** rows, STDMETHODIMP BrowserAccessibilityWin::get_columnExtent( long* n_columns_spanned) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!n_columns_spanned) @@ -1627,7 +1629,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnExtent( STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells( IUnknown*** cell_accessibles, long* n_column_header_cells) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!cell_accessibles || !n_column_header_cells) @@ -1666,8 +1668,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells( for (int i = 0; i < rows; ++i) { int cell_id = cell_ids[i * columns + column]; BrowserAccessibilityWin* cell = - manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); - if (cell && cell->role_ == blink::WebAXRoleColumnHeader) + manager()->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); + if (cell && cell->blink_role() == blink::WebAXRoleColumnHeader) (*n_column_header_cells)++; } @@ -1676,11 +1678,10 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells( int index = 0; for (int i = 0; i < rows; ++i) { int cell_id = cell_ids[i * columns + column]; - BrowserAccessibilityWin* cell = - manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); - if (cell && cell->role_ == blink::WebAXRoleColumnHeader) { - (*cell_accessibles)[index] = - static_cast<IAccessible*>(cell->NewReference()); + BrowserAccessibility* cell = manager()->GetFromRendererID(cell_id); + if (cell && cell->role() == blink::WebAXRoleColumnHeader) { + (*cell_accessibles)[index] = static_cast<IAccessible*>( + cell->ToBrowserAccessibilityWin()->NewReference()); ++index; } } @@ -1689,7 +1690,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells( } STDMETHODIMP BrowserAccessibilityWin::get_columnIndex(long* column_index) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!column_index) @@ -1706,7 +1707,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnIndex(long* column_index) { } STDMETHODIMP BrowserAccessibilityWin::get_rowExtent(long* n_rows_spanned) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!n_rows_spanned) @@ -1726,7 +1727,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowExtent(long* n_rows_spanned) { STDMETHODIMP BrowserAccessibilityWin::get_rowHeaderCells( IUnknown*** cell_accessibles, long* n_row_header_cells) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!cell_accessibles || !n_row_header_cells) @@ -1764,9 +1765,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowHeaderCells( for (int i = 0; i < columns; ++i) { int cell_id = cell_ids[row * columns + i]; - BrowserAccessibilityWin* cell = - manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); - if (cell && cell->role_ == blink::WebAXRoleRowHeader) + BrowserAccessibility* cell = manager()->GetFromRendererID(cell_id); + if (cell && cell->role() == blink::WebAXRoleRowHeader) (*n_row_header_cells)++; } @@ -1775,11 +1775,10 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowHeaderCells( int index = 0; for (int i = 0; i < columns; ++i) { int cell_id = cell_ids[row * columns + i]; - BrowserAccessibilityWin* cell = - manager_->GetFromRendererID(cell_id)->ToBrowserAccessibilityWin(); - if (cell && cell->role_ == blink::WebAXRoleRowHeader) { - (*cell_accessibles)[index] = - static_cast<IAccessible*>(cell->NewReference()); + BrowserAccessibility* cell = manager()->GetFromRendererID(cell_id); + if (cell && cell->role() == blink::WebAXRoleRowHeader) { + (*cell_accessibles)[index] = static_cast<IAccessible*>( + cell->ToBrowserAccessibilityWin()->NewReference()); ++index; } } @@ -1788,7 +1787,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowHeaderCells( } STDMETHODIMP BrowserAccessibilityWin::get_rowIndex(long* row_index) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!row_index) @@ -1803,7 +1802,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowIndex(long* row_index) { } STDMETHODIMP BrowserAccessibilityWin::get_isSelected(boolean* is_selected) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!is_selected) @@ -1819,7 +1818,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowColumnExtents( long* row_extents, long* column_extents, boolean* is_selected) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!row_index || @@ -1853,7 +1852,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowColumnExtents( } STDMETHODIMP BrowserAccessibilityWin::get_table(IUnknown** table) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!table) @@ -1884,7 +1883,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_table(IUnknown** table) { // STDMETHODIMP BrowserAccessibilityWin::get_nCharacters(LONG* n_characters) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!n_characters) @@ -1895,15 +1894,15 @@ STDMETHODIMP BrowserAccessibilityWin::get_nCharacters(LONG* n_characters) { } STDMETHODIMP BrowserAccessibilityWin::get_caretOffset(LONG* offset) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!offset) return E_INVALIDARG; *offset = 0; - if (role_ == blink::WebAXRoleTextField || - role_ == blink::WebAXRoleTextArea) { + if (blink_role() == blink::WebAXRoleTextField || + blink_role() == blink::WebAXRoleTextArea) { int sel_start = 0; if (GetIntAttribute(AccessibilityNodeData::ATTR_TEXT_SEL_START, &sel_start)) @@ -1920,18 +1919,21 @@ STDMETHODIMP BrowserAccessibilityWin::get_characterExtents( LONG* out_y, LONG* out_width, LONG* out_height) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!out_x || !out_y || !out_width || !out_height) return E_INVALIDARG; - const string16& text_str = TextForIAccessibleText(); + const base::string16& text_str = TextForIAccessibleText(); HandleSpecialTextOffset(text_str, &offset); if (offset < 0 || offset > static_cast<LONG>(text_str.size())) return E_INVALIDARG; + if (blink_role() != blink::WebAXRoleStaticText) + return E_FAIL; + gfx::Rect character_bounds; if (coordinate_type == IA2_COORDTYPE_SCREEN_RELATIVE) { character_bounds = GetGlobalBoundsForRange(offset, 1); @@ -1951,15 +1953,15 @@ STDMETHODIMP BrowserAccessibilityWin::get_characterExtents( } STDMETHODIMP BrowserAccessibilityWin::get_nSelections(LONG* n_selections) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!n_selections) return E_INVALIDARG; *n_selections = 0; - if (role_ == blink::WebAXRoleTextField || - role_ == blink::WebAXRoleTextArea) { + if (blink_role() == blink::WebAXRoleTextField || + blink_role() == blink::WebAXRoleTextArea) { int sel_start = 0; int sel_end = 0; if (GetIntAttribute(AccessibilityNodeData::ATTR_TEXT_SEL_START, @@ -1975,7 +1977,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nSelections(LONG* n_selections) { STDMETHODIMP BrowserAccessibilityWin::get_selection(LONG selection_index, LONG* start_offset, LONG* end_offset) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!start_offset || !end_offset || selection_index != 0) @@ -1983,8 +1985,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_selection(LONG selection_index, *start_offset = 0; *end_offset = 0; - if (role_ == blink::WebAXRoleTextField || - role_ == blink::WebAXRoleTextArea) { + if (blink_role() == blink::WebAXRoleTextField || + blink_role() == blink::WebAXRoleTextArea) { int sel_start = 0; int sel_end = 0; if (GetIntAttribute( @@ -2001,13 +2003,13 @@ STDMETHODIMP BrowserAccessibilityWin::get_selection(LONG selection_index, STDMETHODIMP BrowserAccessibilityWin::get_text(LONG start_offset, LONG end_offset, BSTR* text) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!text) return E_INVALIDARG; - const string16& text_str = TextForIAccessibleText(); + const base::string16& text_str = TextForIAccessibleText(); // Handle special text offsets. HandleSpecialTextOffset(text_str, &start_offset); @@ -2028,7 +2030,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_text(LONG start_offset, if (end_offset > len) return E_INVALIDARG; - string16 substr = text_str.substr(start_offset, end_offset - start_offset); + base::string16 substr = text_str.substr(start_offset, + end_offset - start_offset); if (substr.empty()) return S_FALSE; @@ -2043,7 +2046,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_textAtOffset( LONG* start_offset, LONG* end_offset, BSTR* text) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!start_offset || !end_offset || !text) @@ -2058,7 +2061,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_textAtOffset( return S_FALSE; } - const string16& text_str = TextForIAccessibleText(); + const base::string16& text_str = TextForIAccessibleText(); *start_offset = FindBoundary( text_str, boundary_type, offset, ui::BACKWARDS_DIRECTION); @@ -2073,7 +2076,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_textBeforeOffset( LONG* start_offset, LONG* end_offset, BSTR* text) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!start_offset || !end_offset || !text) @@ -2088,7 +2091,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_textBeforeOffset( return S_FALSE; } - const string16& text_str = TextForIAccessibleText(); + const base::string16& text_str = TextForIAccessibleText(); *start_offset = FindBoundary( text_str, boundary_type, offset, ui::BACKWARDS_DIRECTION); @@ -2102,7 +2105,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_textAfterOffset( LONG* start_offset, LONG* end_offset, BSTR* text) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!start_offset || !end_offset || !text) @@ -2117,7 +2120,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_textAfterOffset( return S_FALSE; } - const string16& text_str = TextForIAccessibleText(); + const base::string16& text_str = TextForIAccessibleText(); *start_offset = offset; *end_offset = FindBoundary( @@ -2126,13 +2129,13 @@ STDMETHODIMP BrowserAccessibilityWin::get_textAfterOffset( } STDMETHODIMP BrowserAccessibilityWin::get_newText(IA2TextSegment* new_text) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!new_text) return E_INVALIDARG; - string16 text = TextForIAccessibleText(); + base::string16 text = TextForIAccessibleText(); new_text->text = SysAllocString(text.c_str()); new_text->start = 0; @@ -2141,7 +2144,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_newText(IA2TextSegment* new_text) { } STDMETHODIMP BrowserAccessibilityWin::get_oldText(IA2TextSegment* old_text) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!old_text) @@ -2158,7 +2161,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_offsetAtPoint( LONG y, enum IA2CoordinateType coord_type, LONG* offset) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!offset) @@ -2190,52 +2193,52 @@ STDMETHODIMP BrowserAccessibilityWin::scrollSubstringToPoint( STDMETHODIMP BrowserAccessibilityWin::addSelection(LONG start_offset, LONG end_offset) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; - const string16& text_str = TextForIAccessibleText(); + const base::string16& text_str = TextForIAccessibleText(); HandleSpecialTextOffset(text_str, &start_offset); HandleSpecialTextOffset(text_str, &end_offset); - manager_->SetTextSelection(*this, start_offset, end_offset); + manager()->SetTextSelection(*this, start_offset, end_offset); return S_OK; } STDMETHODIMP BrowserAccessibilityWin::removeSelection(LONG selection_index) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (selection_index != 0) return E_INVALIDARG; - manager_->SetTextSelection(*this, 0, 0); + manager()->SetTextSelection(*this, 0, 0); return S_OK; } STDMETHODIMP BrowserAccessibilityWin::setCaretOffset(LONG offset) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; - const string16& text_str = TextForIAccessibleText(); + const base::string16& text_str = TextForIAccessibleText(); HandleSpecialTextOffset(text_str, &offset); - manager_->SetTextSelection(*this, offset, offset); + manager()->SetTextSelection(*this, offset, offset); return S_OK; } STDMETHODIMP BrowserAccessibilityWin::setSelection(LONG selection_index, LONG start_offset, LONG end_offset) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (selection_index != 0) return E_INVALIDARG; - const string16& text_str = TextForIAccessibleText(); + const base::string16& text_str = TextForIAccessibleText(); HandleSpecialTextOffset(text_str, &start_offset); HandleSpecialTextOffset(text_str, &end_offset); - manager_->SetTextSelection(*this, start_offset, end_offset); + manager()->SetTextSelection(*this, start_offset, end_offset); return S_OK; } @@ -2244,7 +2247,7 @@ STDMETHODIMP BrowserAccessibilityWin::setSelection(LONG selection_index, // STDMETHODIMP BrowserAccessibilityWin::get_nHyperlinks(long* hyperlink_count) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!hyperlink_count) @@ -2257,7 +2260,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nHyperlinks(long* hyperlink_count) { STDMETHODIMP BrowserAccessibilityWin::get_hyperlink( long index, IAccessibleHyperlink** hyperlink) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!hyperlink || @@ -2267,7 +2270,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_hyperlink( } BrowserAccessibilityWin* child = - children_[hyperlinks_[index]]->ToBrowserAccessibilityWin(); + children()[hyperlinks_[index]]->ToBrowserAccessibilityWin(); *hyperlink = static_cast<IAccessibleHyperlink*>(child->NewReference()); return S_OK; } @@ -2275,7 +2278,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_hyperlink( STDMETHODIMP BrowserAccessibilityWin::get_hyperlinkIndex( long char_index, long* hyperlink_index) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!hyperlink_index) @@ -2300,7 +2303,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_hyperlinkIndex( // STDMETHODIMP BrowserAccessibilityWin::get_currentValue(VARIANT* value) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!value) @@ -2319,7 +2322,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_currentValue(VARIANT* value) { } STDMETHODIMP BrowserAccessibilityWin::get_minimumValue(VARIANT* value) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!value) @@ -2338,7 +2341,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_minimumValue(VARIANT* value) { } STDMETHODIMP BrowserAccessibilityWin::get_maximumValue(VARIANT* value) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!value) @@ -2366,7 +2369,7 @@ STDMETHODIMP BrowserAccessibilityWin::setCurrentValue(VARIANT new_value) { // STDMETHODIMP BrowserAccessibilityWin::get_URL(BSTR* url) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!url) @@ -2376,7 +2379,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_URL(BSTR* url) { } STDMETHODIMP BrowserAccessibilityWin::get_title(BSTR* title) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!title) @@ -2386,7 +2389,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_title(BSTR* title) { } STDMETHODIMP BrowserAccessibilityWin::get_mimeType(BSTR* mime_type) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!mime_type) @@ -2397,7 +2400,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_mimeType(BSTR* mime_type) { } STDMETHODIMP BrowserAccessibilityWin::get_docType(BSTR* doc_type) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!doc_type) @@ -2418,7 +2421,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nodeInfo( unsigned int* num_children, unsigned int* unique_id, unsigned short* node_type) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!node_name || !name_space_id || !node_value || !num_children || @@ -2426,14 +2429,14 @@ STDMETHODIMP BrowserAccessibilityWin::get_nodeInfo( return E_INVALIDARG; } - string16 tag; + base::string16 tag; if (GetString16Attribute(AccessibilityNodeData::ATTR_HTML_TAG, &tag)) *node_name = SysAllocString(tag.c_str()); else *node_name = NULL; *name_space_id = 0; - *node_value = SysAllocString(UTF8ToUTF16(value_).c_str()); + *node_value = SysAllocString(UTF8ToUTF16(value()).c_str()); *num_children = PlatformChildCount(); *unique_id = unique_id_win_; @@ -2455,22 +2458,22 @@ STDMETHODIMP BrowserAccessibilityWin::get_attributes( short* name_space_id, BSTR* attrib_values, unsigned short* num_attribs) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!attrib_names || !name_space_id || !attrib_values || !num_attribs) return E_INVALIDARG; *num_attribs = max_attribs; - if (*num_attribs > html_attributes_.size()) - *num_attribs = html_attributes_.size(); + if (*num_attribs > html_attributes().size()) + *num_attribs = html_attributes().size(); for (unsigned short i = 0; i < *num_attribs; ++i) { attrib_names[i] = SysAllocString( - UTF8ToUTF16(html_attributes_[i].first).c_str()); + UTF8ToUTF16(html_attributes()[i].first).c_str()); name_space_id[i] = 0; attrib_values[i] = SysAllocString( - UTF8ToUTF16(html_attributes_[i].second).c_str()); + UTF8ToUTF16(html_attributes()[i].second).c_str()); } return S_OK; } @@ -2480,7 +2483,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_attributesForNames( BSTR* attrib_names, short* name_space_id, BSTR* attrib_values) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!attrib_names || !name_space_id || !attrib_values) @@ -2490,10 +2493,10 @@ STDMETHODIMP BrowserAccessibilityWin::get_attributesForNames( name_space_id[i] = 0; bool found = false; std::string name = UTF16ToUTF8((LPCWSTR)attrib_names[i]); - for (unsigned int j = 0; j < html_attributes_.size(); ++j) { - if (html_attributes_[j].first == name) { + for (unsigned int j = 0; j < html_attributes().size(); ++j) { + if (html_attributes()[j].first == name) { attrib_values[i] = SysAllocString( - UTF8ToUTF16(html_attributes_[j].second).c_str()); + UTF8ToUTF16(html_attributes()[j].second).c_str()); found = true; break; } @@ -2511,7 +2514,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_computedStyle( BSTR* style_properties, BSTR* style_values, unsigned short *num_style_properties) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!style_properties || !style_values) @@ -2519,7 +2522,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_computedStyle( // We only cache a single style property for now: DISPLAY - string16 display; + base::string16 display; if (max_style_properties == 0 || !GetString16Attribute(AccessibilityNodeData::ATTR_DISPLAY, &display)) { *num_style_properties = 0; @@ -2538,7 +2541,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_computedStyleForProperties( boolean use_alternate_view, BSTR* style_properties, BSTR* style_values) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!style_properties || !style_values) @@ -2547,10 +2550,10 @@ STDMETHODIMP BrowserAccessibilityWin::get_computedStyleForProperties( // We only cache a single style property for now: DISPLAY for (unsigned short i = 0; i < num_style_properties; ++i) { - string16 name = (LPCWSTR)style_properties[i]; + base::string16 name = (LPCWSTR)style_properties[i]; StringToLowerASCII(&name); if (name == L"display") { - string16 display = GetString16Attribute( + base::string16 display = GetString16Attribute( AccessibilityNodeData::ATTR_DISPLAY); style_values[i] = SysAllocString(display.c_str()); } else { @@ -2567,18 +2570,18 @@ STDMETHODIMP BrowserAccessibilityWin::scrollTo(boolean placeTopLeft) { } STDMETHODIMP BrowserAccessibilityWin::get_parentNode(ISimpleDOMNode** node) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!node) return E_INVALIDARG; - *node = parent_->ToBrowserAccessibilityWin()->NewReference(); + *node = parent()->ToBrowserAccessibilityWin()->NewReference(); return S_OK; } STDMETHODIMP BrowserAccessibilityWin::get_firstChild(ISimpleDOMNode** node) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!node) @@ -2594,7 +2597,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_firstChild(ISimpleDOMNode** node) { } STDMETHODIMP BrowserAccessibilityWin::get_lastChild(ISimpleDOMNode** node) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!node) @@ -2612,37 +2615,37 @@ STDMETHODIMP BrowserAccessibilityWin::get_lastChild(ISimpleDOMNode** node) { STDMETHODIMP BrowserAccessibilityWin::get_previousSibling( ISimpleDOMNode** node) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!node) return E_INVALIDARG; - if (!parent_ || index_in_parent_ <= 0) { + if (!parent() || index_in_parent() <= 0) { *node = NULL; return S_FALSE; } - *node = parent_->children()[index_in_parent_ - 1]-> + *node = parent()->children()[index_in_parent() - 1]-> ToBrowserAccessibilityWin()->NewReference(); return S_OK; } STDMETHODIMP BrowserAccessibilityWin::get_nextSibling(ISimpleDOMNode** node) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!node) return E_INVALIDARG; - if (!parent_ || - index_in_parent_ < 0 || - index_in_parent_ >= static_cast<int>(parent_->children().size()) - 1) { + if (!parent() || + index_in_parent() < 0 || + index_in_parent() >= static_cast<int>(parent()->children().size()) - 1) { *node = NULL; return S_FALSE; } - *node = parent_->children()[index_in_parent_ + 1]-> + *node = parent()->children()[index_in_parent() + 1]-> ToBrowserAccessibilityWin()->NewReference(); return S_OK; } @@ -2650,7 +2653,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nextSibling(ISimpleDOMNode** node) { STDMETHODIMP BrowserAccessibilityWin::get_childAt( unsigned int child_index, ISimpleDOMNode** node) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!node) @@ -2674,7 +2677,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_childAt( // STDMETHODIMP BrowserAccessibilityWin::get_domText(BSTR* dom_text) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!dom_text) @@ -2704,19 +2707,22 @@ STDMETHODIMP BrowserAccessibilityWin::get_unclippedSubstringBounds( int* out_y, int* out_width, int* out_height) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; if (!out_x || !out_y || !out_width || !out_height) return E_INVALIDARG; - const string16& text_str = TextForIAccessibleText(); + const base::string16& text_str = TextForIAccessibleText(); if (start_index > text_str.size() || end_index > text_str.size() || start_index > end_index) { return E_INVALIDARG; } + if (blink_role() != blink::WebAXRoleStaticText) + return E_FAIL; + gfx::Rect bounds = GetGlobalBoundsForRange( start_index, end_index - start_index); *out_x = bounds.x(); @@ -2729,19 +2735,19 @@ STDMETHODIMP BrowserAccessibilityWin::get_unclippedSubstringBounds( STDMETHODIMP BrowserAccessibilityWin::scrollToSubstring( unsigned int start_index, unsigned int end_index) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; - const string16& text_str = TextForIAccessibleText(); + const base::string16& text_str = TextForIAccessibleText(); if (start_index > text_str.size() || end_index > text_str.size() || start_index > end_index) { return E_INVALIDARG; } - manager_->ScrollToMakeVisible(*this, GetLocalBoundsForRange( + manager()->ScrollToMakeVisible(*this, GetLocalBoundsForRange( start_index, end_index - start_index)); - manager_->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this); + manager()->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this); return S_OK; } @@ -2753,7 +2759,7 @@ STDMETHODIMP BrowserAccessibilityWin::scrollToSubstring( STDMETHODIMP BrowserAccessibilityWin::QueryService(REFGUID guidService, REFIID riid, void** object) { - if (!instance_active_) + if (!instance_active()) return E_FAIL; // The system uses IAccessible APIs for many purposes, but only @@ -2766,7 +2772,7 @@ STDMETHODIMP BrowserAccessibilityWin::QueryService(REFGUID guidService, // Special Mozilla extension: return the accessible for the root document. // Screen readers use this to distinguish between a document loaded event // on the root document vs on an iframe. - return manager_->GetRoot()->ToBrowserAccessibilityWin()->QueryInterface( + return manager()->GetRoot()->ToBrowserAccessibilityWin()->QueryInterface( IID_IAccessible2, object); } @@ -2812,7 +2818,7 @@ STDMETHODIMP BrowserAccessibilityWin::GetPatternProvider(PATTERNID id, if (IsEditableText()) { // The BrowserAccessibilityManager keeps track of instances when // we don't want to show the on-screen keyboard. - if (!manager_->IsOSKAllowed(GetGlobalBoundsRect())) + if (!manager()->IsOSKAllowed(GetGlobalBoundsRect())) return E_NOTIMPL; DVLOG(1) << "Returning UIA text provider"; @@ -2903,13 +2909,13 @@ void BrowserAccessibilityWin::PreInitialize() { IntAttributeToIA2(AccessibilityNodeData::ATTR_HIERARCHICAL_LEVEL, "level"); // Expose the set size and position in set for listbox options. - if (role_ == blink::WebAXRoleListBoxOption && - parent_ && - parent_->role() == blink::WebAXRoleListBox) { + if (blink_role() == blink::WebAXRoleListBoxOption && + parent() && + parent()->role() == blink::WebAXRoleListBox) { ia2_attributes_.push_back( - L"setsize:" + base::IntToString16(parent_->PlatformChildCount())); + L"setsize:" + base::IntToString16(parent()->PlatformChildCount())); ia2_attributes_.push_back( - L"setsize:" + base::IntToString16(index_in_parent_ + 1)); + L"setsize:" + base::IntToString16(index_in_parent() + 1)); } if (ia_role_ == ROLE_SYSTEM_CHECKBUTTON || @@ -2950,9 +2956,9 @@ void BrowserAccessibilityWin::PreInitialize() { const std::vector<int32>& unique_cell_ids = table->GetIntListAttribute( AccessibilityNodeData::ATTR_UNIQUE_CELL_IDS); for (size_t i = 0; i < unique_cell_ids.size(); ++i) { - if (unique_cell_ids[i] == renderer_id_) { + if (unique_cell_ids[i] == renderer_id()) { ia2_attributes_.push_back( - string16(L"table-cell-index:") + base::IntToString16(i)); + base::string16(L"table-cell-index:") + base::IntToString16(i)); } } } @@ -3000,25 +3006,25 @@ void BrowserAccessibilityWin::PreInitialize() { // it's nonempty, and the help should become the description if // there's no description - or the name if there's no name or description. if (!description.empty()) { - name_ = description; + set_name(description); description.clear(); } if (!help.empty() && description.empty()) { description = help; help.clear(); } - if (!description.empty() && name_.empty() && !title_elem_id) { - name_ = description; + if (!description.empty() && name().empty() && !title_elem_id) { + set_name(description); description.clear(); } // If it's a text field, also consider the placeholder. std::string placeholder; - if (role_ == blink::WebAXRoleTextField && + if (blink_role() == blink::WebAXRoleTextField && HasState(blink::WebAXStateFocusable) && GetHtmlAttribute("placeholder", &placeholder)) { - if (name_.empty() && !title_elem_id) { - name_ = placeholder; + if (name().empty() && !title_elem_id) { + set_name(placeholder); } else if (description.empty()) { description = placeholder; } @@ -3028,25 +3034,27 @@ void BrowserAccessibilityWin::PreInitialize() { SetStringAttribute(AccessibilityNodeData::ATTR_HELP, help); // On Windows, the value of a document should be its url. - if (role_ == blink::WebAXRoleRootWebArea || - role_ == blink::WebAXRoleWebArea) { - GetStringAttribute(AccessibilityNodeData::ATTR_DOC_URL, &value_); + if (blink_role() == blink::WebAXRoleRootWebArea || + blink_role() == blink::WebAXRoleWebArea) { + set_value(GetStringAttribute(AccessibilityNodeData::ATTR_DOC_URL)); } // For certain roles (listbox option, static text, and list marker) // WebKit stores the main accessible text in the "value" - swap it so // that it's the "name". - if (name_.empty() && - (role_ == blink::WebAXRoleListBoxOption || - role_ == blink::WebAXRoleStaticText || - role_ == blink::WebAXRoleListMarker)) { - name_.swap(value_); + if (name().empty() && + (blink_role() == blink::WebAXRoleListBoxOption || + blink_role() == blink::WebAXRoleStaticText || + blink_role() == blink::WebAXRoleListMarker)) { + std::string tmp = value(); + set_value(name()); + set_name(tmp); } // If this doesn't have a value and is linked then set its value to the url // attribute. This allows screen readers to read an empty link's destination. - if (value_.empty() && (ia_state_ & STATE_SYSTEM_LINKED)) - GetStringAttribute(AccessibilityNodeData::ATTR_URL, &value_); + if (value().empty() && (ia_state_ & STATE_SYSTEM_LINKED)) + set_value(GetStringAttribute(AccessibilityNodeData::ATTR_URL)); // Clear any old relationships between this node and other nodes. for (size_t i = 0; i < relations_.size(); ++i) @@ -3087,14 +3095,14 @@ void BrowserAccessibilityWin::PostInitialize() { DCHECK_EQ(hyperlink_offset_to_index_.size(), hyperlinks_.size()); // Fire an event when an alert first appears. - if (role_ == blink::WebAXRoleAlert && first_time_) - manager_->NotifyAccessibilityEvent(blink::WebAXEventAlert, this); + if (blink_role() == blink::WebAXRoleAlert && first_time_) + manager()->NotifyAccessibilityEvent(blink::WebAXEventAlert, this); // Fire events if text has changed. - string16 text = TextForIAccessibleText(); + base::string16 text = TextForIAccessibleText(); if (previous_text_ != text) { if (!previous_text_.empty() && !text.empty()) { - manager_->NotifyAccessibilityEvent( + manager()->NotifyAccessibilityEvent( blink::WebAXEventShow, this); } @@ -3107,13 +3115,13 @@ void BrowserAccessibilityWin::PostInitialize() { // Fire events if the state has changed. if (!first_time_ && ia_state_ != old_ia_state_) { BrowserAccessibilityManagerWin* manager = - manager_->ToBrowserAccessibilityManagerWin(); + this->manager()->ToBrowserAccessibilityManagerWin(); // Normally focus events are handled elsewhere, however // focus for managed descendants is platform-specific. // Fire a focus event if the focused descendant in a multi-select // list box changes. - if (role_ == blink::WebAXRoleListBoxOption && + if (blink_role() == blink::WebAXRoleListBoxOption && (ia_state_ & STATE_SYSTEM_FOCUSABLE) && (ia_state_ & STATE_SYSTEM_SELECTABLE) && (ia_state_ & STATE_SYSTEM_FOCUSED) && @@ -3151,7 +3159,7 @@ bool BrowserAccessibilityWin::IsNative() const { void BrowserAccessibilityWin::SetLocation(const gfx::Rect& new_location) { BrowserAccessibility::SetLocation(new_location); - manager_->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( + manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( EVENT_OBJECT_LOCATIONCHANGE, unique_id_win()); } @@ -3172,14 +3180,14 @@ BrowserAccessibilityWin* BrowserAccessibilityWin::GetTargetFromChildID( if (child_id >= 1 && child_id <= static_cast<LONG>(PlatformChildCount())) return PlatformGetChild(child_id - 1)->ToBrowserAccessibilityWin(); - return manager_->ToBrowserAccessibilityManagerWin()-> + return manager()->ToBrowserAccessibilityManagerWin()-> GetFromUniqueIdWin(child_id); } HRESULT BrowserAccessibilityWin::GetStringAttributeAsBstr( AccessibilityNodeData::StringAttribute attribute, BSTR* value_bstr) { - string16 str; + base::string16 str; if (!GetString16Attribute(attribute, &str)) return S_FALSE; @@ -3196,7 +3204,7 @@ HRESULT BrowserAccessibilityWin::GetStringAttributeAsBstr( void BrowserAccessibilityWin::StringAttributeToIA2( AccessibilityNodeData::StringAttribute attribute, const char* ia2_attr) { - string16 value; + base::string16 value; if (GetString16Attribute(attribute, &value)) ia2_attributes_.push_back(ASCIIToUTF16(ia2_attr) + L":" + value); } @@ -3221,9 +3229,10 @@ void BrowserAccessibilityWin::IntAttributeToIA2( } } -string16 BrowserAccessibilityWin::GetValueText() { +base::string16 BrowserAccessibilityWin::GetValueText() { float fval; - string16 value = UTF8ToUTF16(value_); + base::string16 value = UTF8ToUTF16(this->value()); + if (value.empty() && GetFloatAttribute(AccessibilityNodeData::ATTR_VALUE_FOR_RANGE, &fval)) { value = UTF8ToUTF16(base::DoubleToString(fval)); @@ -3231,15 +3240,16 @@ string16 BrowserAccessibilityWin::GetValueText() { return value; } -string16 BrowserAccessibilityWin::TextForIAccessibleText() { +base::string16 BrowserAccessibilityWin::TextForIAccessibleText() { if (IsEditableText()) - return UTF8ToUTF16(value_); - return (role_ == blink::WebAXRoleStaticText) ? - UTF8ToUTF16(name_) : hypertext_; + return UTF8ToUTF16(value()); + return (blink_role() == blink::WebAXRoleStaticText) ? + UTF8ToUTF16(name()) : hypertext_; } -void BrowserAccessibilityWin::HandleSpecialTextOffset(const string16& text, - LONG* offset) { +void BrowserAccessibilityWin::HandleSpecialTextOffset( + const base::string16& text, + LONG* offset) { if (*offset == IA2_TEXT_OFFSET_LENGTH) *offset = static_cast<LONG>(text.size()); else if (*offset == IA2_TEXT_OFFSET_CARET) @@ -3262,7 +3272,7 @@ ui::TextBoundaryType BrowserAccessibilityWin::IA2TextBoundaryToTextBoundary( } LONG BrowserAccessibilityWin::FindBoundary( - const string16& text, + const base::string16& text, IA2TextBoundaryType ia2_boundary, LONG start_offset, ui::TextBoundaryDirection direction) { @@ -3276,7 +3286,7 @@ LONG BrowserAccessibilityWin::FindBoundary( BrowserAccessibilityWin* BrowserAccessibilityWin::GetFromRendererID( int32 renderer_id) { - return manager_->GetFromRendererID(renderer_id)->ToBrowserAccessibilityWin(); + return manager()->GetFromRendererID(renderer_id)->ToBrowserAccessibilityWin(); } void BrowserAccessibilityWin::InitRoleAndState() { @@ -3339,7 +3349,7 @@ void BrowserAccessibilityWin::InitRoleAndState() { if (!HasState(blink::WebAXStateReadonly)) ia2_state_ |= IA2_STATE_EDITABLE; - string16 invalid; + base::string16 invalid; if (GetHtmlAttribute("aria-invalid", &invalid)) ia2_state_ |= IA2_STATE_INVALID_ENTRY; @@ -3349,11 +3359,11 @@ void BrowserAccessibilityWin::InitRoleAndState() { if (GetBoolAttribute(AccessibilityNodeData::ATTR_CAN_SET_VALUE)) ia2_state_ |= IA2_STATE_EDITABLE; - string16 html_tag = GetString16Attribute( + base::string16 html_tag = GetString16Attribute( AccessibilityNodeData::ATTR_HTML_TAG); ia_role_ = 0; ia2_role_ = 0; - switch (role_) { + switch (blink_role()) { case blink::WebAXRoleAlert: ia_role_ = ROLE_SYSTEM_ALERT; break; @@ -3463,7 +3473,7 @@ void BrowserAccessibilityWin::InitRoleAndState() { ia_state_ |= STATE_SYSTEM_READONLY; break; case blink::WebAXRoleGroup: { - string16 aria_role = GetString16Attribute( + base::string16 aria_role = GetString16Attribute( AccessibilityNodeData::ATTR_ROLE); if (aria_role == L"group" || html_tag == L"fieldset") { ia_role_ = ROLE_SYSTEM_GROUPING; @@ -3661,7 +3671,7 @@ void BrowserAccessibilityWin::InitRoleAndState() { ia_role_ = ROLE_SYSTEM_PAGETAB; break; case blink::WebAXRoleTable: { - string16 aria_role = GetString16Attribute( + base::string16 aria_role = GetString16Attribute( AccessibilityNodeData::ATTR_ROLE); if (aria_role == L"treegrid") { ia_role_ = ROLE_SYSTEM_OUTLINE; diff --git a/content/browser/accessibility/browser_accessibility_win.h b/content/browser/accessibility/browser_accessibility_win.h index 1bb6ee20d7..a1a3624733 100644 --- a/content/browser/accessibility/browser_accessibility_win.h +++ b/content/browser/accessibility/browser_accessibility_win.h @@ -86,8 +86,8 @@ BrowserAccessibilityWin // Mappings from roles and states to human readable strings. Initialize // with |InitializeStringMaps|. - static std::map<int32, string16> role_string_map; - static std::map<int32, string16> state_string_map; + static std::map<int32, base::string16> role_string_map; + static std::map<int32, base::string16> state_string_map; CONTENT_EXPORT BrowserAccessibilityWin(); @@ -765,13 +765,17 @@ BrowserAccessibilityWin // Accessors. int32 ia_role() const { return ia_role_; } int32 ia_state() const { return ia_state_; } - const string16& role_name() const { return role_name_; } + const base::string16& role_name() const { return role_name_; } int32 ia2_role() const { return ia2_role_; } int32 ia2_state() const { return ia2_state_; } - const std::vector<string16>& ia2_attributes() const { + const std::vector<base::string16>& ia2_attributes() const { return ia2_attributes_; } + // BrowserAccessibility::role is shadowed by IAccessible2::role, so + // we provide an alias for it. + int32 blink_role() const { return BrowserAccessibility::role(); } + private: // Add one to the reference count and return the same object. Always // use this method when returning a BrowserAccessibilityWin object as @@ -813,15 +817,15 @@ BrowserAccessibilityWin // Get the value text, which might come from the floating-point // value for some roles. - string16 GetValueText(); + base::string16 GetValueText(); // Get the text of this node for the purposes of IAccessibleText - it may // be the name, it may be the value, etc. depending on the role. - string16 TextForIAccessibleText(); + base::string16 TextForIAccessibleText(); // If offset is a member of IA2TextSpecialOffsets this function updates the // value of offset and returns, otherwise offset remains unchanged. - void HandleSpecialTextOffset(const string16& text, LONG* offset); + void HandleSpecialTextOffset(const base::string16& text, LONG* offset); // Convert from a IA2TextBoundaryType to a ui::TextBoundaryType. ui::TextBoundaryType IA2TextBoundaryToTextBoundary(IA2TextBoundaryType type); @@ -829,7 +833,7 @@ BrowserAccessibilityWin // Search forwards (direction == 1) or backwards (direction == -1) // from the given offset until the given boundary is found, and // return the offset of that boundary. - LONG FindBoundary(const string16& text, + LONG FindBoundary(const base::string16& text, IA2TextBoundaryType ia2_boundary, LONG start_offset, ui::TextBoundaryDirection direction); @@ -846,26 +850,26 @@ BrowserAccessibilityWin // IAccessible role and state. int32 ia_role_; int32 ia_state_; - string16 role_name_; + base::string16 role_name_; // IAccessible2 role and state. int32 ia2_role_; int32 ia2_state_; // IAccessible2 attributes. - std::vector<string16> ia2_attributes_; + std::vector<base::string16> ia2_attributes_; // True in Initialize when the object is first created, and false // subsequent times. bool first_time_; // The previous text, before the last update to this object. - string16 previous_text_; + base::string16 previous_text_; // The old text to return in IAccessibleText::get_oldText - this is like // previous_text_ except that it's NOT updated when the object // is initialized again but the text doesn't change. - string16 old_text_; + base::string16 old_text_; // The previous state, used to see if there was a state change. int32 old_ia_state_; @@ -874,7 +878,7 @@ BrowserAccessibilityWin std::vector<BrowserAccessibilityRelation*> relations_; // The text of this node including embedded hyperlink characters. - string16 hypertext_; + base::string16 hypertext_; // Maps the |hypertext_| embedded character offset to an index in // |hyperlinks_|. diff --git a/content/browser/accessibility/browser_accessibility_win_unittest.cc b/content/browser/accessibility/browser_accessibility_win_unittest.cc index edb572f014..c1159e6eb6 100644 --- a/content/browser/accessibility/browser_accessibility_win_unittest.cc +++ b/content/browser/accessibility/browser_accessibility_win_unittest.cc @@ -219,7 +219,7 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) { base::win::ScopedBstr name; hr = text_accessible->get_accName(childid_self, name.Receive()); ASSERT_EQ(S_OK, hr); - EXPECT_EQ(L"old text", string16(name)); + EXPECT_EQ(L"old text", base::string16(name)); name.Reset(); text_dispatch.Release(); @@ -250,7 +250,7 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) { hr = text_accessible->get_accName(childid_self, name.Receive()); ASSERT_EQ(S_OK, hr); - EXPECT_EQ(L"new text", string16(name)); + EXPECT_EQ(L"new text", base::string16(name)); text_dispatch.Release(); text_accessible.Release(); @@ -354,7 +354,7 @@ TEST_F(BrowserAccessibilityTest, TestTextBoundaries) { base::win::ScopedBstr text; ASSERT_EQ(S_OK, text1_obj->get_text(0, text1_len, text.Receive())); - ASSERT_EQ(text1_value, base::UTF16ToUTF8(string16(text))); + ASSERT_EQ(text1_value, base::UTF16ToUTF8(base::string16(text))); text.Reset(); ASSERT_EQ(S_OK, text1_obj->get_text(0, 4, text.Receive())); @@ -452,7 +452,7 @@ TEST_F(BrowserAccessibilityTest, TestSimpleHypertext) { base::win::ScopedBstr text; ASSERT_EQ(S_OK, root_obj->get_text(0, text_len, text.Receive())); - EXPECT_EQ(text1_name + text2_name, base::UTF16ToUTF8(string16(text))); + EXPECT_EQ(text1_name + text2_name, base::UTF16ToUTF8(base::string16(text))); long hyperlink_count; ASSERT_EQ(S_OK, root_obj->get_nHyperlinks(&hyperlink_count)); @@ -548,7 +548,7 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) { const std::string embed = base::UTF16ToUTF8( BrowserAccessibilityWin::kEmbeddedCharacter); EXPECT_EQ(text1_name + embed + text2_name + embed, - UTF16ToUTF8(string16(text))); + UTF16ToUTF8(base::string16(text))); text.Reset(); long hyperlink_count; @@ -566,7 +566,7 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) { hyperlink.QueryInterface<IAccessibleText>(hypertext.Receive())); EXPECT_EQ(S_OK, hypertext->get_text(0, 3, text.Receive())); EXPECT_STREQ(button1_text_name.c_str(), - base::UTF16ToUTF8(string16(text)).c_str()); + base::UTF16ToUTF8(base::string16(text)).c_str()); text.Reset(); hyperlink.Release(); hypertext.Release(); @@ -576,7 +576,7 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) { hyperlink.QueryInterface<IAccessibleText>(hypertext.Receive())); EXPECT_EQ(S_OK, hypertext->get_text(0, 4, text.Receive())); EXPECT_STREQ(link1_text_name.c_str(), - base::UTF16ToUTF8(string16(text)).c_str()); + base::UTF16ToUTF8(base::string16(text)).c_str()); text.Reset(); hyperlink.Release(); hypertext.Release(); diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index 45bf951a0a..8cceea7bc5 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc @@ -161,7 +161,7 @@ void DumpAccessibilityTreeTest::RunTest( // Tolerate Windows-style line endings (\r\n) in the expected file: // normalize by deleting all \r from the file (if any) to leave only \n. std::string expected_contents; - RemoveChars(expected_contents_raw, "\r", &expected_contents); + base::RemoveChars(expected_contents_raw, "\r", &expected_contents); if (!expected_contents.compare(0, strlen(kMarkSkipFile), kMarkSkipFile)) { printf("Skipping this test on this platform.\n"); @@ -169,7 +169,7 @@ void DumpAccessibilityTreeTest::RunTest( } // Load the page. - string16 html_contents16; + base::string16 html_contents16; html_contents16 = UTF8ToUTF16(html_contents); GURL url = GetTestUrl("accessibility", html_file.BaseName().MaybeAsASCII().c_str()); @@ -191,7 +191,7 @@ void DumpAccessibilityTreeTest::RunTest( formatter.SetFilters(filters); // Perform a diff (or write the initial baseline). - string16 actual_contents_utf16; + base::string16 actual_contents_utf16; formatter.FormatAccessibilityTree(&actual_contents_utf16); std::string actual_contents = UTF16ToUTF8(actual_contents_utf16); std::vector<std::string> actual_lines, expected_lines; @@ -411,6 +411,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, RunTest(FILE_PATH_LITERAL("input-text-name-calc.html")); } +IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputTypes) { + RunTest(FILE_PATH_LITERAL("input-types.html")); +} + IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityLabel) { RunTest(FILE_PATH_LITERAL("label.html")); } diff --git a/content/browser/android/OWNERS b/content/browser/android/OWNERS index 6a8f307049..4fd5d774a7 100644 --- a/content/browser/android/OWNERS +++ b/content/browser/android/OWNERS @@ -1,5 +1,4 @@ bulach@chromium.org -joth@chromium.org sievers@chromium.org skyostil@chromium.org tedchoc@chromium.org diff --git a/content/browser/android/browser_jni_registrar.cc b/content/browser/android/browser_jni_registrar.cc index 88c88010f3..be30869473 100644 --- a/content/browser/android/browser_jni_registrar.cc +++ b/content/browser/android/browser_jni_registrar.cc @@ -24,6 +24,7 @@ #include "content/browser/android/tracing_controller_android.h" #include "content/browser/android/web_contents_observer_android.h" #include "content/browser/device_orientation/data_fetcher_impl_android.h" +#include "content/browser/frame_host/navigation_controller_android.h" #include "content/browser/geolocation/location_api_adapter_android.h" #include "content/browser/media/android/media_drm_credential_manager.h" #include "content/browser/media/android/media_resource_getter_impl.h" @@ -33,6 +34,7 @@ #include "content/browser/renderer_host/java/java_bound_object.h" #include "content/browser/speech/speech_recognizer_impl_android.h" #include "content/browser/vibration/vibration_provider_android.h" +#include "content/browser/web_contents/web_contents_android.h" using content::SurfaceTexturePeerBrowserImpl; @@ -56,11 +58,13 @@ base::android::RegistrationMethod kContentRegisteredMethods[] = { {"InterstitialPageDelegateAndroid", content::InterstitialPageDelegateAndroid:: RegisterInterstitialPageDelegateAndroid}, + {"LoadUrlParams", content::RegisterLoadUrlParams}, {"MediaDrmCredentialManager", content::MediaDrmCredentialManager::RegisterMediaDrmCredentialManager}, {"MediaResourceGetterImpl", content::MediaResourceGetterImpl::RegisterMediaResourceGetter}, - {"LoadUrlParams", content::RegisterLoadUrlParams}, + {"NavigationControllerAndroid", + content::NavigationControllerAndroid::Register}, {"PowerSaveBlock", content::RegisterPowerSaveBlocker}, {"RegisterImeAdapter", content::RegisterImeAdapter}, {"SpeechRecognizerImplAndroid", @@ -70,6 +74,7 @@ base::android::RegistrationMethod kContentRegisteredMethods[] = { {"TouchPoint", content::RegisterTouchPoint}, {"TracingControllerAndroid", content::RegisterTracingControllerAndroid}, {"VibrationProvider", content::VibrationProviderAndroid::Register}, + {"WebContentsAndroid", content::WebContentsAndroid::Register}, {"WebContentsObserverAndroid", content::RegisterWebContentsObserverAndroid}, {"WebViewStatics", content::RegisterWebViewStatics}, }; diff --git a/content/browser/android/content_startup_flags.cc b/content/browser/android/content_startup_flags.cc index 636a1980c2..7d95034344 100644 --- a/content/browser/android/content_startup_flags.cc +++ b/content/browser/android/content_startup_flags.cc @@ -4,6 +4,7 @@ #include "content/browser/android/content_startup_flags.h" +#include "base/base_switches.h" #include "base/command_line.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" @@ -66,6 +67,8 @@ void SetContentCommandLineFlags(int max_render_process_count, parsed_command_line->AppendSwitch(switches::kEnableOverlayFullscreenVideo); parsed_command_line->AppendSwitch(switches::kEnableOverlayScrollbars); parsed_command_line->AppendSwitch(switches::kEnableOverscrollNotifications); + parsed_command_line->AppendSwitchASCII(switches::kTouchAckTimeoutDelayMs, + "200"); // Run the GPU service as a thread in the browser instead of as a // standalone process. @@ -87,6 +90,12 @@ void SetContentCommandLineFlags(int max_render_process_count, parsed_command_line->AppendSwitchNative( switches::kRegisterPepperPlugins, plugin_descriptor); } + + // Disable profiler timing by default. + if (!parsed_command_line->HasSwitch(switches::kProfilerTiming)) { + parsed_command_line->AppendSwitchASCII( + switches::kProfilerTiming, switches::kProfilerTimingDisabledValue); + } } } // namespace content diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc index 2a53563c4f..7fb557f4df 100644 --- a/content/browser/android/content_view_core_impl.cc +++ b/content/browser/android/content_view_core_impl.cc @@ -68,13 +68,16 @@ using blink::WebGestureEvent; using blink::WebInputEvent; // Describes the type and enabled state of a select popup item. -// Keep in sync with the value defined in SelectPopupDialog.java -enum PopupItemType { - POPUP_ITEM_TYPE_GROUP = 0, - POPUP_ITEM_TYPE_DISABLED, - POPUP_ITEM_TYPE_ENABLED +namespace { + +enum { +#define DEFINE_POPUP_ITEM_TYPE(name, value) POPUP_ITEM_TYPE_##name = value, +#include "content/browser/android/popup_item_type_list.h" +#undef DEFINE_POPUP_ITEM_TYPE }; +} //namespace + namespace content { namespace { @@ -206,6 +209,11 @@ ContentViewCoreImpl::~ContentViewCoreImpl() { notification_registrar_.RemoveAll(); } +base::android::ScopedJavaLocalRef<jobject> +ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env, jobject obj) { + return web_contents_->GetJavaWebContents(); +} + void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv* env, jobject obj) { DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj)); @@ -389,7 +397,7 @@ void ContentViewCoreImpl::UpdateFrameInfo( overdraw_bottom_height); } -void ContentViewCoreImpl::SetTitle(const string16& title) { +void ContentViewCoreImpl::SetTitle(const base::string16& title) { JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); if (obj.is_null()) @@ -438,7 +446,7 @@ void ContentViewCoreImpl::ShowSelectPopupMenu( ScopedJavaLocalRef<jintArray> enabled_array(env, env->NewIntArray(items.size())); - std::vector<string16> labels; + std::vector<base::string16> labels; labels.reserve(items.size()); for (size_t i = 0; i < items.size(); ++i) { labels.push_back(items[i].label); @@ -1121,37 +1129,6 @@ void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj, } } -jboolean ContentViewCoreImpl::CanGoBack(JNIEnv* env, jobject obj) { - return web_contents_->GetController().CanGoBack(); -} - -jboolean ContentViewCoreImpl::CanGoForward(JNIEnv* env, jobject obj) { - return web_contents_->GetController().CanGoForward(); -} - -jboolean ContentViewCoreImpl::CanGoToOffset(JNIEnv* env, jobject obj, - jint offset) { - return web_contents_->GetController().CanGoToOffset(offset); -} - -void ContentViewCoreImpl::GoBack(JNIEnv* env, jobject obj) { - web_contents_->GetController().GoBack(); -} - -void ContentViewCoreImpl::GoForward(JNIEnv* env, jobject obj) { - web_contents_->GetController().GoForward(); -} - -void ContentViewCoreImpl::GoToOffset(JNIEnv* env, jobject obj, jint offset) { - web_contents_->GetController().GoToOffset(offset); -} - -void ContentViewCoreImpl::GoToNavigationIndex(JNIEnv* env, - jobject obj, - jint index) { - web_contents_->GetController().GoToIndex(index); -} - void ContentViewCoreImpl::LoadIfNecessary(JNIEnv* env, jobject obj) { web_contents_->GetController().LoadIfNecessary(); } @@ -1487,7 +1464,7 @@ void ContentViewCoreImpl::EvaluateJavaScript(JNIEnv* env, if (!callback) { // No callback requested. - rvh->ExecuteJavascriptInWebFrame(string16(), // frame_xpath + rvh->ExecuteJavascriptInWebFrame(base::string16(), // frame_xpath ConvertJavaStringToUTF16(env, script)); return; } @@ -1500,7 +1477,7 @@ void ContentViewCoreImpl::EvaluateJavaScript(JNIEnv* env, base::Bind(&JavaScriptResultCallback, j_callback); rvh->ExecuteJavascriptInWebFrameCallbackResult( - string16(), // frame_xpath + base::string16(), // frame_xpath ConvertJavaStringToUTF16(env, script), c_callback); } diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h index 0c3a5ec3ea..040d6e0417 100644 --- a/content/browser/android/content_view_core_impl.h +++ b/content/browser/android/content_view_core_impl.h @@ -68,6 +68,9 @@ class ContentViewCoreImpl : public ContentViewCore, // Methods called from Java via JNI // -------------------------------------------------------------------------- + base::android::ScopedJavaLocalRef<jobject> GetWebContentsAndroid(JNIEnv* env, + jobject obj); + void OnJavaContentViewCoreDestroyed(JNIEnv* env, jobject obj); // Notifies the ContentViewCore that items were selected in the currently @@ -141,13 +144,6 @@ class ContentViewCoreImpl : public ContentViewCore, jfloat x2, jfloat y2); void MoveCaret(JNIEnv* env, jobject obj, jfloat x, jfloat y); - jboolean CanGoBack(JNIEnv* env, jobject obj); - jboolean CanGoForward(JNIEnv* env, jobject obj); - jboolean CanGoToOffset(JNIEnv* env, jobject obj, jint offset); - void GoBack(JNIEnv* env, jobject obj); - void GoForward(JNIEnv* env, jobject obj); - void GoToOffset(JNIEnv* env, jobject obj, jint offset); - void GoToNavigationIndex(JNIEnv* env, jobject obj, jint index); void LoadIfNecessary(JNIEnv* env, jobject obj); void RequestRestoreLoad(JNIEnv* env, jobject obj); void StopLoading(JNIEnv* env, jobject obj); @@ -258,7 +254,7 @@ class ContentViewCoreImpl : public ContentViewCore, int selection_start, int selection_end, int composition_start, int composition_end, bool show_ime_if_needed, bool require_ack); - void SetTitle(const string16& title); + void SetTitle(const base::string16& title); void OnBackgroundColorChanged(SkColor color); bool HasFocus(); diff --git a/content/browser/android/content_view_statics.cc b/content/browser/android/content_view_statics.cc index 917da58280..e176564c4a 100644 --- a/content/browser/android/content_view_statics.cc +++ b/content/browser/android/content_view_statics.cc @@ -62,8 +62,8 @@ void ResumeWebkitSharedTimers(const std::vector<int>& suspended_processes) { // Returns the first substring consisting of the address of a physical location. static jstring FindAddress(JNIEnv* env, jclass clazz, jstring addr) { - string16 content_16 = ConvertJavaStringToUTF16(env, addr); - string16 result_16; + base::string16 content_16 = ConvertJavaStringToUTF16(env, addr); + base::string16 result_16; if (content::address_parser::FindAddress(content_16, &result_16)) return ConvertUTF16ToJavaString(env, result_16).Release(); return NULL; diff --git a/content/browser/android/date_time_chooser_android.cc b/content/browser/android/date_time_chooser_android.cc index be87a932e1..f6b50c9da4 100644 --- a/content/browser/android/date_time_chooser_android.cc +++ b/content/browser/android/date_time_chooser_android.cc @@ -4,17 +4,41 @@ #include "content/browser/android/date_time_chooser_android.h" +#include "base/android/jni_android.h" #include "base/android/jni_string.h" +#include "base/i18n/char_iterator.h" +#include "content/common/date_time_suggestion.h" #include "content/common/view_messages.h" #include "content/public/browser/android/content_view_core.h" #include "content/public/browser/render_view_host.h" #include "jni/DateTimeChooserAndroid_jni.h" +#include "third_party/icu/source/common/unicode/uchar.h" +#include "third_party/icu/source/common/unicode/unistr.h" using base::android::AttachCurrentThread; using base::android::ConvertJavaStringToUTF16; using base::android::ConvertUTF8ToJavaString; +using base::android::ConvertUTF16ToJavaString; +namespace { + +string16 SanitizeSuggestionString(const string16& string) { + string16 trimmed = string.substr(0, 255); + icu::UnicodeString sanitized; + base::i18n::UTF16CharIterator sanitized_iterator(&trimmed); + while (!sanitized_iterator.end()) { + UChar c = sanitized_iterator.get(); + if (u_isprint(c)) + sanitized.append(c); + sanitized_iterator.Advance(); + } + return string16(sanitized.getBuffer(), + static_cast<size_t>(sanitized.length())); +} + +} // namespace + namespace content { // DateTimeChooserAndroid implementation @@ -40,25 +64,7 @@ void DateTimeChooserAndroid::InitializeDateInputTypes( void DateTimeChooserAndroid::ReplaceDateTime(JNIEnv* env, jobject, - int dialog_type, - int year, - int month, - int day, - int hour, - int minute, - int second, - int milli, - int week) { - ViewHostMsg_DateTimeDialogValue_Params value; - value.year = year; - value.month = month; - value.day = day; - value.hour = hour; - value.minute = minute; - value.second = second; - value.milli = milli; - value.week = week; - value.dialog_type = dialog_type; + jdouble value) { host_->Send(new ViewMsg_ReplaceDateTime(host_->GetRoutingID(), value)); } @@ -66,39 +72,46 @@ void DateTimeChooserAndroid::CancelDialog(JNIEnv* env, jobject) { host_->Send(new ViewMsg_CancelDateTimeDialog(host_->GetRoutingID())); } -void DateTimeChooserAndroid::ShowDialog(ContentViewCore* content, - RenderViewHost* host, - int type, - int year, - int month, - int day, - int hour, - int minute, - int second, - int milli, - int week, - double min, - double max, - double step) { +void DateTimeChooserAndroid::ShowDialog( + ContentViewCore* content, + RenderViewHost* host, + ui::TextInputType dialog_type, + double dialog_value, + double min, + double max, + double step, + const std::vector<DateTimeSuggestion>& suggestions) { host_ = host; JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobjectArray> suggestions_array; + + if (suggestions.size() > 0) { + suggestions_array = + Java_DateTimeChooserAndroid_createSuggestionsArray(env, + suggestions.size()); + for (size_t i = 0; i < suggestions.size(); ++i) { + const content::DateTimeSuggestion& suggestion = suggestions[i]; + ScopedJavaLocalRef<jstring> localized_value = ConvertUTF16ToJavaString( + env, SanitizeSuggestionString(suggestion.localized_value)); + ScopedJavaLocalRef<jstring> label = ConvertUTF16ToJavaString( + env, SanitizeSuggestionString(suggestion.label)); + Java_DateTimeChooserAndroid_setDateTimeSuggestionAt(env, + suggestions_array.obj(), i, + suggestion.value, localized_value.obj(), label.obj()); + } + } + j_date_time_chooser_.Reset(Java_DateTimeChooserAndroid_createDateTimeChooser( env, content->GetJavaObject().obj(), reinterpret_cast<intptr_t>(this), - type, - year, - month, - day, - hour, - minute, - second, - milli, - week, + dialog_type, + dialog_value, min, max, - step)); + step, + suggestions_array.obj())); } // ---------------------------------------------------------------------------- diff --git a/content/browser/android/date_time_chooser_android.h b/content/browser/android/date_time_chooser_android.h index a5578e01b8..c02ecf56fe 100644 --- a/content/browser/android/date_time_chooser_android.h +++ b/content/browser/android/date_time_chooser_android.h @@ -6,14 +6,17 @@ #define CONTENT_BROWSER_ANDROID_DATE_TIME_CHOOSER_ANDROID_H_ #include <string> +#include <vector> #include "base/android/jni_helper.h" #include "base/memory/scoped_ptr.h" +#include "ui/base/ime/text_input_type.h" namespace content { class ContentViewCore; class RenderViewHost; +struct DateTimeSuggestion; // Android implementation for DateTimeChooser dialogs. class DateTimeChooserAndroid { @@ -22,33 +25,19 @@ class DateTimeChooserAndroid { ~DateTimeChooserAndroid(); // DateTimeChooser implementation: + // Shows the dialog. |dialog_value| is the date/time value converted to a + // number as defined in HTML. (See blink::InputType::parseToNumber()) void ShowDialog(ContentViewCore* content, RenderViewHost* host, - int type, - int year, - int month, - int day, - int hour, - int minute, - int second, - int milli, - int week, + ui::TextInputType dialog_type, + double dialog_value, double min, double max, - double step); - - // Replaces the current value with the one passed the different fields - void ReplaceDateTime(JNIEnv* env, - jobject, - jint dialog_type, - jint year, - jint month, - jint day, - jint hour, - jint minute, - jint second, - jint milli, - jint week); + double step, + const std::vector<DateTimeSuggestion>& suggestions); + + // Replaces the current value + void ReplaceDateTime(JNIEnv* env, jobject, jdouble value); // Closes the dialog without propagating any changes. void CancelDialog(JNIEnv* env, jobject); diff --git a/content/browser/android/in_process/synchronous_input_event_filter.cc b/content/browser/android/in_process/synchronous_input_event_filter.cc index 5b086fb716..b8ba0ea335 100644 --- a/content/browser/android/in_process/synchronous_input_event_filter.cc +++ b/content/browser/android/in_process/synchronous_input_event_filter.cc @@ -28,8 +28,8 @@ InputEventAckState SynchronousInputEventFilter::HandleInputEvent( // state. While not good, it should also not be fatal. if (handler_.is_null()) return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; - - return handler_.Run(routing_id, &input_event, ui::LatencyInfo()); + ui::LatencyInfo latency; + return handler_.Run(routing_id, &input_event, &latency); } void SynchronousInputEventFilter::SetBoundHandler(const Handler& handler) { diff --git a/content/browser/android/overscroll_glow.cc b/content/browser/android/overscroll_glow.cc index d8e8c77575..8e08de45ec 100644 --- a/content/browser/android/overscroll_glow.cc +++ b/content/browser/android/overscroll_glow.cc @@ -6,6 +6,7 @@ #include "base/debug/trace_event.h" #include "base/lazy_instance.h" +#include "base/threading/worker_pool.h" #include "cc/layers/image_layer.h" #include "content/browser/android/edge_effect.h" #include "ui/gfx/android/java_bitmap.h" @@ -63,54 +64,61 @@ gfx::Vector2dF ZeroSmallComponents(gfx::Vector2dF vector) { return vector; } -} // namespace +// Force loading of any necessary resources. This function is thread-safe. +void EnsureResources() { + g_overscroll_resources.Get(); +} -scoped_ptr<OverscrollGlow> OverscrollGlow::Create(bool enabled, - gfx::SizeF size) { - const SkBitmap& edge = g_overscroll_resources.Get().edge_bitmap(); - const SkBitmap& glow = g_overscroll_resources.Get().glow_bitmap(); - if (edge.isNull() || glow.isNull()) - return scoped_ptr<OverscrollGlow>(); +} // namespace - return make_scoped_ptr(new OverscrollGlow(enabled, size, edge, glow)); -} +scoped_ptr<OverscrollGlow> OverscrollGlow::Create(bool enabled) { + // Don't block the main thread with effect resource loading during creation. + // Effect instantiation is deferred until the effect overscrolls, in which + // case the main thread may block until the resource has loaded. + if (enabled && g_overscroll_resources == NULL) + base::WorkerPool::PostTask(FROM_HERE, base::Bind(EnsureResources), true); -void OverscrollGlow::EnsureResources() { - g_overscroll_resources.Get(); + return make_scoped_ptr(new OverscrollGlow(enabled)); } -OverscrollGlow::OverscrollGlow(bool enabled, - gfx::SizeF size, - const SkBitmap& edge, - const SkBitmap& glow) +OverscrollGlow::OverscrollGlow(bool enabled) : enabled_(enabled), - size_(size), + initialized_(false), horizontal_overscroll_enabled_(true), - vertical_overscroll_enabled_(true), - root_layer_(cc::Layer::Create()) { - for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) { - scoped_refptr<cc::Layer> edge_layer = CreateImageLayer(edge); - scoped_refptr<cc::Layer> glow_layer = CreateImageLayer(glow); - root_layer_->AddChild(edge_layer); - root_layer_->AddChild(glow_layer); - edge_effects_[i] = make_scoped_ptr(new EdgeEffect(edge_layer, glow_layer)); - } -} + vertical_overscroll_enabled_(true) {} OverscrollGlow::~OverscrollGlow() { - root_layer_->RemoveFromParent(); + Detach(); +} + +void OverscrollGlow::Enable() { + enabled_ = true; } -void OverscrollGlow::OnOverscrolled(base::TimeTicks current_time, +void OverscrollGlow::Disable() { + if (!enabled_) + return; + enabled_ = false; + if (!enabled_ && initialized_) { + Detach(); + for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) + edge_effects_[i]->Finish(); + } +} + +bool OverscrollGlow::OnOverscrolled(cc::Layer* overscrolling_layer, + base::TimeTicks current_time, gfx::Vector2dF overscroll, gfx::Vector2dF velocity) { + DCHECK(overscrolling_layer); + if (!enabled_) - return; + return false; // The size of the glow determines the relative effect of the inputs; an // empty-sized effect is effectively disabled. if (size_.IsEmpty()) - return; + return false; if (!horizontal_overscroll_enabled_) { overscroll.set_x(0); @@ -126,10 +134,16 @@ void OverscrollGlow::OnOverscrolled(base::TimeTicks current_time, velocity = ZeroSmallComponents(velocity); if (overscroll.IsZero()) { - Release(current_time); - return; + if (initialized_) { + Release(current_time); + UpdateLayerAttachment(overscrolling_layer); + } + return NeedsAnimate(); } + if (!InitializeIfNecessary()) + return false; + if (!velocity.IsZero()) { // Release effects if scrolling has changed directions. if (velocity.x() * old_velocity_.x() < 0) @@ -152,11 +166,16 @@ void OverscrollGlow::OnOverscrolled(base::TimeTicks current_time, old_velocity_ = velocity; old_overscroll_ = overscroll; + + UpdateLayerAttachment(overscrolling_layer); + return NeedsAnimate(); } bool OverscrollGlow::Animate(base::TimeTicks current_time) { - if (!NeedsAnimate()) + if (!NeedsAnimate()) { + Detach(); return false; + } const gfx::SizeF sizes[EdgeEffect::EDGE_COUNT] = { size_, gfx::SizeF(size_.height(), size_.width()), @@ -170,21 +189,16 @@ bool OverscrollGlow::Animate(base::TimeTicks current_time) { } } - return NeedsAnimate(); -} - -void OverscrollGlow::SetEnabled(bool enabled) { - if (enabled_ == enabled) - return; - enabled_ = enabled; - if (!enabled_) { - for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) - edge_effects_[i]->Finish(); + if (!NeedsAnimate()) { + Detach(); + return false; } + + return true; } bool OverscrollGlow::NeedsAnimate() const { - if (!enabled_) + if (!enabled_ || !initialized_) return false; for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) { if (!edge_effects_[i]->IsFinished()) @@ -193,8 +207,54 @@ bool OverscrollGlow::NeedsAnimate() const { return false; } +void OverscrollGlow::UpdateLayerAttachment(cc::Layer* parent) { + DCHECK(parent); + if (!root_layer_) + return; + + if (!NeedsAnimate()) { + Detach(); + return; + } + + if (root_layer_->parent() != parent) + parent->AddChild(root_layer_); +} + +void OverscrollGlow::Detach() { + if (root_layer_) + root_layer_->RemoveFromParent(); +} + +bool OverscrollGlow::InitializeIfNecessary() { + DCHECK(enabled_); + if (initialized_) + return true; + + const SkBitmap& edge = g_overscroll_resources.Get().edge_bitmap(); + const SkBitmap& glow = g_overscroll_resources.Get().glow_bitmap(); + if (edge.isNull() || glow.isNull()) { + Disable(); + return false; + } + + DCHECK(!root_layer_); + root_layer_ = cc::Layer::Create(); + for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) { + scoped_refptr<cc::Layer> edge_layer = CreateImageLayer(edge); + scoped_refptr<cc::Layer> glow_layer = CreateImageLayer(glow); + root_layer_->AddChild(edge_layer); + root_layer_->AddChild(glow_layer); + edge_effects_[i] = make_scoped_ptr(new EdgeEffect(edge_layer, glow_layer)); + } + + initialized_ = true; + return true; +} + void OverscrollGlow::Pull(base::TimeTicks current_time, gfx::Vector2dF overscroll_delta) { + DCHECK(enabled_ && initialized_); overscroll_delta = ZeroSmallComponents(overscroll_delta); if (overscroll_delta.IsZero()) return; @@ -222,6 +282,7 @@ void OverscrollGlow::Absorb(base::TimeTicks current_time, gfx::Vector2dF velocity, gfx::Vector2dF overscroll, gfx::Vector2dF old_overscroll) { + DCHECK(enabled_ && initialized_); if (overscroll.IsZero() || velocity.IsZero()) return; @@ -243,6 +304,7 @@ void OverscrollGlow::Absorb(base::TimeTicks current_time, } void OverscrollGlow::Release(base::TimeTicks current_time) { + DCHECK(initialized_); for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) { edge_effects_[i]->Release(current_time); } @@ -250,6 +312,7 @@ void OverscrollGlow::Release(base::TimeTicks current_time) { } void OverscrollGlow::ReleaseAxis(Axis axis, base::TimeTicks current_time) { + DCHECK(initialized_); switch (axis) { case AXIS_X: edge_effects_[EdgeEffect::EDGE_LEFT]->Release(current_time); @@ -267,6 +330,7 @@ void OverscrollGlow::ReleaseAxis(Axis axis, base::TimeTicks current_time) { } EdgeEffect* OverscrollGlow::GetOppositeEdge(int edge_index) { + DCHECK(initialized_); return edge_effects_[(edge_index + 2) % EdgeEffect::EDGE_COUNT].get(); } diff --git a/content/browser/android/overscroll_glow.h b/content/browser/android/overscroll_glow.h index ba1d48ff74..3a13fb3c4f 100644 --- a/content/browser/android/overscroll_glow.h +++ b/content/browser/android/overscroll_glow.h @@ -26,38 +26,35 @@ namespace content { */ class OverscrollGlow { public: - // Create and initialize a new effect with the necessary resources. - // If |enabled| is false, the effect will be be deactivated until - // SetEnabled(true) is called. - // The caller should attach |root_layer| to the desired layer tree. - static scoped_ptr<OverscrollGlow> Create(bool enabled, gfx::SizeF size); - - // Force loading of any necessary resources. This function is thread-safe. - static void EnsureResources(); + // Create a new effect. If |enabled| is false, the effect will remain + // deactivated until explicitly enabled. + // Note: No resources will be allocated until the effect is both + // enabled and an overscroll event has occurred. + static scoped_ptr<OverscrollGlow> Create(bool enabled); ~OverscrollGlow(); - // If false, the glow will be deactivated, and subsequent calls to - // OnOverscrolled or Animate will have no effect. - void SetEnabled(bool enabled); + // Enable the effect. If the effect was previously disabled, it will remain + // dormant until subsequent calls to |OnOverscrolled()|. + void Enable(); + + // Deactivate and detach the effect. Subsequent calls to |OnOverscrolled()| or + // |Animate()| will have no effect. + void Disable(); + // Effect layers will be attached to |overscrolling_layer| if necessary. // |overscroll| is the accumulated overscroll for the current gesture. // |velocity| is the instantaneous velocity for the overscroll. - void OnOverscrolled(base::TimeTicks current_time, + // Returns true if the effect still needs animation ticks. + bool OnOverscrolled(cc::Layer* overscrolling_layer, + base::TimeTicks current_time, gfx::Vector2dF overscroll, gfx::Vector2dF velocity); // Returns true if the effect still needs animation ticks. + // Note: The effect will detach itself when no further animation is required. bool Animate(base::TimeTicks current_time); - // Returns true if the effect needs animation ticks. - bool NeedsAnimate() const; - - // The root layer of the effect (not necessarily of the tree). - scoped_refptr<cc::Layer> root_layer() const { - return root_layer_; - } - // Horizontal overscroll will be ignored when false. void set_horizontal_overscroll_enabled(bool enabled) { horizontal_overscroll_enabled_ = enabled; @@ -74,11 +71,13 @@ class OverscrollGlow { private: enum Axis { AXIS_X, AXIS_Y }; - OverscrollGlow(bool enabled, - gfx::SizeF size, - const SkBitmap& edge, - const SkBitmap& glow); + OverscrollGlow(bool enabled); + // Returns whether the effect is initialized. + bool InitializeIfNecessary(); + bool NeedsAnimate() const; + void UpdateLayerAttachment(cc::Layer* parent); + void Detach(); void Pull(base::TimeTicks current_time, gfx::Vector2dF added_overscroll); void Absorb(base::TimeTicks current_time, @@ -93,6 +92,7 @@ class OverscrollGlow { scoped_ptr<EdgeEffect> edge_effects_[EdgeEffect::EDGE_COUNT]; bool enabled_; + bool initialized_; gfx::SizeF size_; gfx::Vector2dF old_overscroll_; gfx::Vector2dF old_velocity_; diff --git a/content/browser/android/popup_item_type_list.h b/content/browser/android/popup_item_type_list.h new file mode 100644 index 0000000000..3f50490f61 --- /dev/null +++ b/content/browser/android/popup_item_type_list.h @@ -0,0 +1,23 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file intentionally does not have header guards because this file +// is meant to be included inside a macro to generate enum values. + +// This file contains a list of sync PopupItemTypes which describe the type +// and enabled state of a select popup item. List is used by Android when +// displaying a new select popup menu. + +#ifndef DEFINE_POPUP_ITEM_TYPE +#error "Please define DEFINE_POPUP_ITEM_TYPE before including this file." +#endif + +// Popup item is of type group +DEFINE_POPUP_ITEM_TYPE(GROUP, 0) + +// Popup item is disabled +DEFINE_POPUP_ITEM_TYPE(DISABLED, 1) + +// Popup item is enabled +DEFINE_POPUP_ITEM_TYPE(ENABLED, 2) diff --git a/content/browser/android/tracing_controller_android.cc b/content/browser/android/tracing_controller_android.cc index 42d147e821..75ac6d7c23 100644 --- a/content/browser/android/tracing_controller_android.cc +++ b/content/browser/android/tracing_controller_android.cc @@ -6,12 +6,9 @@ #include "base/android/jni_android.h" #include "base/android/jni_string.h" -#include "base/command_line.h" #include "base/debug/trace_event.h" -#include "base/files/file_path.h" #include "base/logging.h" -#include "content/browser/tracing/trace_subscriber_stdio.h" -#include "content/public/browser/trace_controller.h" +#include "content/public/browser/tracing_controller.h" #include "jni/TracingControllerAndroid_jni.h" namespace content { @@ -21,29 +18,9 @@ static jlong Init(JNIEnv* env, jobject obj) { return reinterpret_cast<intptr_t>(profiler); } -class TracingControllerAndroid::Subscriber - : public content::TraceSubscriberStdio { - public: - Subscriber(TracingControllerAndroid* profiler, const base::FilePath& path) - : TraceSubscriberStdio(path, FILE_TYPE_ARRAY, false), - profiler_(profiler) {} - - void set_profiler(TracingControllerAndroid* profiler) { - CHECK(!profiler_); - profiler_ = profiler; - } - - virtual void OnEndTracingComplete() OVERRIDE { - TraceSubscriberStdio::OnEndTracingComplete(); - profiler_->OnTracingStopped(); - } - - private: - TracingControllerAndroid* profiler_; -}; - TracingControllerAndroid::TracingControllerAndroid(JNIEnv* env, jobject obj) - : weak_java_object_(env, obj) {} + : weak_java_object_(env, obj), + weak_factory_(this) {} TracingControllerAndroid::~TracingControllerAndroid() {} @@ -56,39 +33,37 @@ bool TracingControllerAndroid::StartTracing(JNIEnv* env, jstring jfilename, jstring jcategories, jboolean record_continuously) { - if (subscriber_.get()) { - return false; - } - std::string filename = base::android::ConvertJavaStringToUTF8(env, jfilename); + file_path_ = base::FilePath( + base::android::ConvertJavaStringToUTF8(env, jfilename)); std::string categories = base::android::ConvertJavaStringToUTF8(env, jcategories); - subscriber_.reset(new Subscriber(this, base::FilePath(filename))); - return TraceController::GetInstance()->BeginTracing( - subscriber_.get(), + + // This log is required by adb_profile_chrome.py. + LOG(WARNING) << "Logging performance trace to file: " << file_path_.value(); + + return TracingController::GetInstance()->EnableRecording( categories, - record_continuously ? base::debug::TraceLog::RECORD_CONTINUOUSLY - : base::debug::TraceLog::RECORD_UNTIL_FULL); + record_continuously ? TracingController::RECORD_CONTINUOUSLY + : TracingController::DEFAULT_OPTIONS, + TracingController::EnableRecordingDoneCallback()); } void TracingControllerAndroid::StopTracing(JNIEnv* env, jobject obj) { - if (!subscriber_.get()) { - return; - } - TraceController* controller = TraceController::GetInstance(); - if (!controller->EndTracingAsync(subscriber_.get())) { + if (!TracingController::GetInstance()->DisableRecording( + file_path_, + base::Bind(&TracingControllerAndroid::OnTracingStopped, + weak_factory_.GetWeakPtr()))) { LOG(ERROR) << "EndTracingAsync failed, forcing an immediate stop"; - controller->CancelSubscriber(subscriber_.get()); - OnTracingStopped(); + OnTracingStopped(file_path_); } } -void TracingControllerAndroid::OnTracingStopped() { +void TracingControllerAndroid::OnTracingStopped( + const base::FilePath& file_path) { JNIEnv* env = base::android::AttachCurrentThread(); base::android::ScopedJavaLocalRef<jobject> obj = weak_java_object_.get(env); - if (obj.obj()) { + if (obj.obj()) Java_TracingControllerAndroid_onTracingStopped(env, obj.obj()); - } - subscriber_.reset(); } static jstring GetDefaultCategories(JNIEnv* env, jobject obj) { diff --git a/content/browser/android/tracing_controller_android.h b/content/browser/android/tracing_controller_android.h index 0cd310ebb6..4d70e7b75e 100644 --- a/content/browser/android/tracing_controller_android.h +++ b/content/browser/android/tracing_controller_android.h @@ -6,7 +6,8 @@ #define CONTENT_BROWSER_ANDROID_TRACING_CONTROLLER_ANDROID_H_ #include "base/android/jni_helper.h" -#include "base/memory/scoped_ptr.h" +#include "base/files/file_path.h" +#include "base/memory/weak_ptr.h" namespace content { @@ -25,12 +26,11 @@ class TracingControllerAndroid { private: ~TracingControllerAndroid(); - void OnTracingStopped(); + void OnTracingStopped(const base::FilePath& file_path); JavaObjectWeakGlobalRef weak_java_object_; - - class Subscriber; - scoped_ptr<Subscriber> subscriber_; + base::FilePath file_path_; + base::WeakPtrFactory<TracingControllerAndroid> weak_factory_; DISALLOW_COPY_AND_ASSIGN(TracingControllerAndroid); }; diff --git a/content/browser/android/web_contents_observer_android.cc b/content/browser/android/web_contents_observer_android.cc index f2494e8f63..235041be67 100644 --- a/content/browser/android/web_contents_observer_android.cc +++ b/content/browser/android/web_contents_observer_android.cc @@ -98,11 +98,11 @@ void WebContentsObserverAndroid::DidStopLoading( void WebContentsObserverAndroid::DidFailProvisionalLoad( int64 frame_id, - const string16& frame_unique_name, + const base::string16& frame_unique_name, bool is_main_frame, const GURL& validated_url, int error_code, - const string16& error_description, + const base::string16& error_description, RenderViewHost* render_view_host) { DidFailLoadInternal( true, is_main_frame, error_code, error_description, validated_url); @@ -113,7 +113,7 @@ void WebContentsObserverAndroid::DidFailLoad( const GURL& validated_url, bool is_main_frame, int error_code, - const string16& error_description, + const base::string16& error_description, RenderViewHost* render_view_host) { DidFailLoadInternal( false, is_main_frame, error_code, error_description, validated_url); @@ -175,7 +175,7 @@ void WebContentsObserverAndroid::DidStartProvisionalLoadForFrame( void WebContentsObserverAndroid::DidCommitProvisionalLoadForFrame( int64 frame_id, - const string16& frame_unique_name, + const base::string16& frame_unique_name, bool is_main_frame, const GURL& url, PageTransition transition_type, @@ -251,7 +251,7 @@ void WebContentsObserverAndroid::DidFailLoadInternal( bool is_provisional_load, bool is_main_frame, int error_code, - const string16& description, + const base::string16& description, const GURL& url) { JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env)); diff --git a/content/browser/android/web_contents_observer_android.h b/content/browser/android/web_contents_observer_android.h index 9742d2827e..15a136390f 100644 --- a/content/browser/android/web_contents_observer_android.h +++ b/content/browser/android/web_contents_observer_android.h @@ -38,17 +38,17 @@ class WebContentsObserverAndroid : public WebContentsObserver { virtual void DidStopLoading(RenderViewHost* render_view_host) OVERRIDE; virtual void DidFailProvisionalLoad( int64 frame_id, - const string16& frame_unique_name, + const base::string16& frame_unique_name, bool is_main_frame, const GURL& validated_url, int error_code, - const string16& error_description, + const base::string16& error_description, RenderViewHost* render_view_host) OVERRIDE; virtual void DidFailLoad(int64 frame_id, const GURL& validated_url, bool is_main_frame, int error_code, - const string16& error_description, + const base::string16& error_description, RenderViewHost* render_view_host) OVERRIDE; virtual void DidNavigateMainFrame(const LoadCommittedDetails& details, const FrameNavigateParams& params) OVERRIDE; @@ -64,7 +64,7 @@ class WebContentsObserverAndroid : public WebContentsObserver { RenderViewHost* render_view_host) OVERRIDE; virtual void DidCommitProvisionalLoadForFrame( int64 frame_id, - const string16& frame_unique_name, + const base::string16& frame_unique_name, bool is_main_frame, const GURL& url, PageTransition transition_type, @@ -83,7 +83,7 @@ class WebContentsObserverAndroid : public WebContentsObserver { void DidFailLoadInternal(bool is_provisional_load, bool is_main_frame, int error_code, - const string16& description, + const base::string16& description, const GURL& url); JavaObjectWeakGlobalRef weak_java_observer_; diff --git a/content/browser/aura/gpu_process_transport_factory.cc b/content/browser/aura/gpu_process_transport_factory.cc index 20b4ea5fa0..21091346e6 100644 --- a/content/browser/aura/gpu_process_transport_factory.cc +++ b/content/browser/aura/gpu_process_transport_factory.cc @@ -179,7 +179,7 @@ scoped_ptr<cc::SoftwareOutputDevice> CreateSoftwareOutputDevice( } scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface( - ui::Compositor* compositor) { + ui::Compositor* compositor, bool software_fallback) { PerCompositorData* data = per_compositor_data_[compositor]; if (!data) data = CreatePerCompositorData(compositor); @@ -187,7 +187,8 @@ scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface( scoped_refptr<ContextProviderCommandBuffer> context_provider; CommandLine* command_line = CommandLine::ForCurrentProcess(); - if (!command_line->HasSwitch(switches::kUIEnableSoftwareCompositing)) { + if (!command_line->HasSwitch(switches::kUIEnableSoftwareCompositing) && + !software_fallback) { context_provider = ContextProviderCommandBuffer::Create( GpuProcessTransportFactory::CreateContextCommon(data->surface_id), "Compositor"); @@ -293,7 +294,8 @@ gfx::GLSurfaceHandle GpuProcessTransportFactory::CreateSharedSurfaceHandle() { gfx::GLSurfaceHandle handle = gfx::GLSurfaceHandle( gfx::kNullPluginWindow, gfx::TEXTURE_TRANSPORT); handle.parent_gpu_process_id = context->GetGPUProcessID(); - handle.parent_client_id = context->GetChannelID(); + handle.parent_client_id = + BrowserGpuChannelHostFactory::instance()->GetGpuChannelId(); return handle; } @@ -451,13 +453,11 @@ GpuProcessTransportFactory::CreateContextCommon(int surface_id) { if (!gpu_channel_host) return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>(); GURL url("chrome://gpu/GpuProcessTransportFactory::CreateContextCommon"); - bool use_echo_for_swap_ack = true; scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context( new WebGraphicsContext3DCommandBufferImpl( surface_id, url, gpu_channel_host.get(), - use_echo_for_swap_ack, attrs, false, WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits())); diff --git a/content/browser/aura/gpu_process_transport_factory.h b/content/browser/aura/gpu_process_transport_factory.h index 36ebb00700..13da92b253 100644 --- a/content/browser/aura/gpu_process_transport_factory.h +++ b/content/browser/aura/gpu_process_transport_factory.h @@ -36,7 +36,7 @@ class GpuProcessTransportFactory // ui::ContextFactory implementation. virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface( - ui::Compositor* compositor) OVERRIDE; + ui::Compositor* compositor, bool software_fallback) OVERRIDE; virtual scoped_refptr<ui::Reflector> CreateReflector( ui::Compositor* source, ui::Layer* target) OVERRIDE; diff --git a/content/browser/aura/owned_mailbox.cc b/content/browser/aura/owned_mailbox.cc new file mode 100644 index 0000000000..1a99d335ac --- /dev/null +++ b/content/browser/aura/owned_mailbox.cc @@ -0,0 +1,42 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/aura/owned_mailbox.h" + +#include "base/logging.h" +#include "content/browser/aura/image_transport_factory.h" +#include "content/common/gpu/client/gl_helper.h" + +namespace content { + +OwnedMailbox::OwnedMailbox(GLHelper* gl_helper) + : texture_id_(0), sync_point_(0), gl_helper_(gl_helper) { + texture_id_ = gl_helper_->CreateTexture(); + mailbox_ = gl_helper_->ProduceMailboxFromTexture(texture_id_, &sync_point_); + ImageTransportFactory::GetInstance()->AddObserver(this); +} + +OwnedMailbox::~OwnedMailbox() { + ImageTransportFactory::GetInstance()->RemoveObserver(this); + if (gl_helper_) { + gl_helper_->WaitSyncPoint(sync_point_); + gl_helper_->DeleteTexture(texture_id_); + } +} + +void OwnedMailbox::UpdateSyncPoint(uint32 sync_point) { + if (sync_point) + sync_point_ = sync_point; +} + +void OwnedMailbox::OnLostResources() { + gl_helper_->WaitSyncPoint(sync_point_); + gl_helper_->DeleteTexture(texture_id_); + texture_id_ = 0; + mailbox_ = gpu::Mailbox(); + sync_point_ = 0; + gl_helper_ = NULL; +} + +} // namespace content diff --git a/content/browser/aura/owned_mailbox.h b/content/browser/aura/owned_mailbox.h new file mode 100644 index 0000000000..ea1c242bf7 --- /dev/null +++ b/content/browser/aura/owned_mailbox.h @@ -0,0 +1,41 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/ref_counted.h" +#include "content/browser/aura/image_transport_factory.h" +#include "gpu/command_buffer/common/mailbox.h" + +namespace content { + +class GLHelper; + +// This class holds a texture id and gpu::Mailbox, and deletes the texture +// id when the object itself is destroyed. Should only be created if a GLHelper +// exists on the ImageTransportFactory. +class OwnedMailbox : public base::RefCounted<OwnedMailbox>, + public ImageTransportFactoryObserver { + public: + explicit OwnedMailbox(GLHelper* gl_helper); + + uint32 texture_id() const { return texture_id_; } + uint32 sync_point() const { return sync_point_; } + const gpu::Mailbox& mailbox() const { return mailbox_; } + + void UpdateSyncPoint(uint32 sync_point); + + protected: + virtual ~OwnedMailbox(); + + virtual void OnLostResources() OVERRIDE; + + private: + friend class base::RefCounted<OwnedMailbox>; + + uint32 texture_id_; + gpu::Mailbox mailbox_; + uint32 sync_point_; + GLHelper* gl_helper_; +}; + +} // namespace content diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc index 8e6bde3b0a..4261572334 100644 --- a/content/browser/browser_child_process_host_impl.cc +++ b/content/browser/browser_child_process_host_impl.cc @@ -192,7 +192,7 @@ base::ProcessHandle BrowserChildProcessHostImpl::GetHandle() const { return child_process_->GetHandle(); } -void BrowserChildProcessHostImpl::SetName(const string16& name) { +void BrowserChildProcessHostImpl::SetName(const base::string16& name) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); data_.name = name; } diff --git a/content/browser/browser_child_process_host_impl.h b/content/browser/browser_child_process_host_impl.h index 6345595a14..428da3ddaf 100644 --- a/content/browser/browser_child_process_host_impl.h +++ b/content/browser/browser_child_process_host_impl.h @@ -54,7 +54,7 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl virtual ChildProcessHost* GetHost() const OVERRIDE; virtual base::TerminationStatus GetTerminationStatus( bool known_dead, int* exit_code) OVERRIDE; - virtual void SetName(const string16& name) OVERRIDE; + virtual void SetName(const base::string16& name) OVERRIDE; virtual void SetHandle(base::ProcessHandle handle) OVERRIDE; // Returns the handle of the child process. This can be called only after diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 093aef3d0f..9b4a1ef6a5 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc @@ -34,6 +34,7 @@ #include "content/browser/gpu/gpu_process_host_ui_shim.h" #include "content/browser/histogram_synchronizer.h" #include "content/browser/loader/resource_dispatcher_host_impl.h" +#include "content/browser/media/media_internals.h" #include "content/browser/net/browser_online_state_observer.h" #include "content/browser/plugin_service_impl.h" #include "content/browser/renderer_host/media/audio_mirroring_manager.h" @@ -462,7 +463,8 @@ void BrowserMainLoop::MainMessageLoopStart() { } { TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:AudioMan") - audio_manager_.reset(media::AudioManager::Create()); + audio_manager_.reset(media::AudioManager::Create( + MediaInternals::GetInstance())); } { TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:MIDIManager") diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc index 7d166a60ae..ef8d7791c5 100644 --- a/content/browser/browser_plugin/browser_plugin_guest.cc +++ b/content/browser/browser_plugin/browser_plugin_guest.cc @@ -351,6 +351,7 @@ BrowserPluginGuest::BrowserPluginGuest( mouse_locked_(false), pending_lock_request_(false), embedder_visible_(true), + copy_request_id_(0), next_permission_request_id_(browser_plugin::kInvalidPermissionRequestID), has_render_view_(has_render_view), last_seen_auto_size_enabled_(false), @@ -365,9 +366,9 @@ BrowserPluginGuest::BrowserPluginGuest( bool BrowserPluginGuest::AddMessageToConsole(WebContents* source, int32 level, - const string16& message, + const base::string16& message, int32 line_no, - const string16& source_id) { + const base::string16& source_id) { if (!delegate_) return false; @@ -507,6 +508,8 @@ bool BrowserPluginGuest::OnMessageReceivedFromEmbedder( OnSwapBuffersACK) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameACK, OnCompositorFrameACK) + IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck, + OnCopyFromCompositingSurfaceAck) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate, OnDragStatusUpdate) IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand, @@ -625,6 +628,9 @@ void BrowserPluginGuest::Initialize( ack_params.name = name_; SendMessageToEmbedder( new BrowserPluginMsg_Attach_ACK(instance_id_, ack_params)); + + if (delegate_) + delegate_->DidAttach(); } BrowserPluginGuest::~BrowserPluginGuest() { @@ -683,6 +689,16 @@ void BrowserPluginGuest::UpdateVisibility() { OnSetVisibility(instance_id_, visible()); } +void BrowserPluginGuest::CopyFromCompositingSurface( + gfx::Rect src_subrect, + gfx::Size dst_size, + const base::Callback<void(bool, const SkBitmap&)>& callback) { + copy_request_callbacks_.insert(std::make_pair(++copy_request_id_, callback)); + SendMessageToEmbedder( + new BrowserPluginMsg_CopyFromCompositingSurface(instance_id(), + copy_request_id_, src_subrect, dst_size)); +} + // screen. gfx::Rect BrowserPluginGuest::ToGuestRect(const gfx::Rect& bounds) { gfx::Rect guest_rect(bounds); @@ -758,6 +774,9 @@ void BrowserPluginGuest::HandleKeyboardEvent( if (delegate_ && delegate_->HandleKeyboardEvent(event)) return; + if (!embedder_web_contents_->GetDelegate()) + return; + // Send the unhandled keyboard events back to the embedder to reprocess them. // TODO(fsamuel): This introduces the possibility of out-of-order keyboard // events because the guest may be arbitrarily delayed when responding to @@ -796,7 +815,7 @@ WebContents* BrowserPluginGuest::OpenURLFromTab(WebContents* source, void BrowserPluginGuest::WebContentsCreated(WebContents* source_contents, int64 source_frame_id, - const string16& frame_name, + const base::string16& frame_name, const GURL& target_url, WebContents* new_contents) { WebContentsImpl* new_contents_impl = @@ -828,6 +847,12 @@ void BrowserPluginGuest::RendererResponsive(WebContents* source) { void BrowserPluginGuest::RunFileChooser(WebContents* web_contents, const FileChooserParams& params) { + if (!attached()) + return; + + if (!embedder_web_contents_->GetDelegate()) + return; + embedder_web_contents_->GetDelegate()->RunFileChooser(web_contents, params); } @@ -1028,7 +1053,7 @@ void BrowserPluginGuest::SendQueuedMessages() { void BrowserPluginGuest::DidCommitProvisionalLoadForFrame( int64 frame_id, - const string16& frame_unique_name, + const base::string16& frame_unique_name, bool is_main_frame, const GURL& url, PageTransition transition_type, @@ -1045,7 +1070,7 @@ void BrowserPluginGuest::DidStopLoading(RenderViewHost* render_view_host) { const char script[] = "window.addEventListener('dragstart', function() { " " window.event.preventDefault(); " "});"; - render_view_host->ExecuteJavascriptInWebFrame(string16(), + render_view_host->ExecuteJavascriptInWebFrame(base::string16(), ASCIIToUTF16(script)); } } @@ -1109,6 +1134,7 @@ bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest( switch (message.type()) { case BrowserPluginHostMsg_BuffersSwappedACK::ID: case BrowserPluginHostMsg_CompositorFrameACK::ID: + case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID: case BrowserPluginHostMsg_DragStatusUpdate::ID: case BrowserPluginHostMsg_ExecuteEditCommand::ID: case BrowserPluginHostMsg_HandleInputEvent::ID: @@ -1377,7 +1403,8 @@ void BrowserPluginGuest::OnNavigateGuest( if (scheme_is_blocked || !url.is_valid()) { if (delegate_) { std::string error_type; - RemoveChars(net::ErrorToString(net::ERR_ABORTED), "net::", &error_type); + base::RemoveChars(net::ErrorToString(net::ERR_ABORTED), "net::", + &error_type); delegate_->LoadAbort(true /* is_top_level */, url, error_type); } return; @@ -1428,15 +1455,10 @@ void BrowserPluginGuest::OnResizeGuest( } // Invalid damage buffer means we are in HW compositing mode, // so just resize the WebContents and repaint if needed. - if (!base::SharedMemory::IsHandleValid(params.damage_buffer_handle)) { - if (!params.view_rect.size().IsEmpty()) - GetWebContents()->GetView()->SizeContents(params.view_rect.size()); - if (params.repaint) - Send(new ViewMsg_Repaint(routing_id(), params.view_rect.size())); - return; - } - SetDamageBuffer(params); - GetWebContents()->GetView()->SizeContents(params.view_rect.size()); + if (base::SharedMemory::IsHandleValid(params.damage_buffer_handle)) + SetDamageBuffer(params); + if (!params.view_rect.size().IsEmpty()) + GetWebContents()->GetView()->SizeContents(params.view_rect.size()); if (params.repaint) Send(new ViewMsg_Repaint(routing_id(), params.view_rect.size())); } @@ -1556,6 +1578,18 @@ void BrowserPluginGuest::OnUpdateRectACK( OnSetSize(instance_id_, auto_size_params, resize_guest_params); } +void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck( + int instance_id, + int request_id, + const SkBitmap& bitmap) { + CHECK(copy_request_callbacks_.count(request_id)); + if (!copy_request_callbacks_.count(request_id)) + return; + const CopyRequestCallback& callback = copy_request_callbacks_[request_id]; + callback.Run(!bitmap.empty() && !bitmap.isNull(), bitmap); + copy_request_callbacks_.erase(request_id); +} + void BrowserPluginGuest::OnUpdateGeometry(int instance_id, const gfx::Rect& view_rect) { // The plugin has moved within the embedder without resizing or the @@ -1633,8 +1667,8 @@ void BrowserPluginGuest::RunJavaScriptDialog( const GURL& origin_url, const std::string& accept_lang, JavaScriptMessageType javascript_message_type, - const string16& message_text, - const string16& default_prompt_text, + const base::string16& message_text, + const base::string16& default_prompt_text, const DialogClosedCallback& callback, bool* did_suppress_message) { base::DictionaryValue request_info; @@ -1659,18 +1693,18 @@ void BrowserPluginGuest::RunJavaScriptDialog( void BrowserPluginGuest::RunBeforeUnloadDialog( WebContents* web_contents, - const string16& message_text, + const base::string16& message_text, bool is_reload, const DialogClosedCallback& callback) { // This is called if the guest has a beforeunload event handler. // This callback allows navigation to proceed. - callback.Run(true, string16()); + callback.Run(true, base::string16()); } bool BrowserPluginGuest::HandleJavaScriptDialog( WebContents* web_contents, bool accept, - const string16* prompt_override) { + const base::string16* prompt_override) { return false; } diff --git a/content/browser/browser_plugin/browser_plugin_guest.h b/content/browser/browser_plugin/browser_plugin_guest.h index 2a9c36cfb4..b3d491801f 100644 --- a/content/browser/browser_plugin/browser_plugin_guest.h +++ b/content/browser/browser_plugin/browser_plugin_guest.h @@ -144,10 +144,15 @@ class CONTENT_EXPORT BrowserPluginGuest void UpdateVisibility(); + void CopyFromCompositingSurface( + gfx::Rect src_subrect, + gfx::Size dst_size, + const base::Callback<void(bool, const SkBitmap&)>& callback); + // WebContentsObserver implementation. virtual void DidCommitProvisionalLoadForFrame( int64 frame_id, - const string16& frame_unique_name, + const base::string16& frame_unique_name, bool is_main_frame, const GURL& url, PageTransition transition_type, @@ -161,9 +166,9 @@ class CONTENT_EXPORT BrowserPluginGuest // WebContentsDelegate implementation. virtual bool AddMessageToConsole(WebContents* source, int32 level, - const string16& message, + const base::string16& message, int32 line_no, - const string16& source_id) OVERRIDE; + const base::string16& source_id) OVERRIDE; // If a new window is created with target="_blank" and rel="noreferrer", then // this method is called, indicating that the new WebContents is ready to be // attached. @@ -189,7 +194,7 @@ class CONTENT_EXPORT BrowserPluginGuest const OpenURLParams& params) OVERRIDE; virtual void WebContentsCreated(WebContents* source_contents, int64 source_frame_id, - const string16& frame_name, + const base::string16& frame_name, const GURL& target_url, WebContents* new_contents) OVERRIDE; virtual void RendererUnresponsive(WebContents* source) OVERRIDE; @@ -208,18 +213,19 @@ class CONTENT_EXPORT BrowserPluginGuest const GURL& origin_url, const std::string& accept_lang, JavaScriptMessageType javascript_message_type, - const string16& message_text, - const string16& default_prompt_text, + const base::string16& message_text, + const base::string16& default_prompt_text, const DialogClosedCallback& callback, bool* did_suppress_message) OVERRIDE; virtual void RunBeforeUnloadDialog( WebContents* web_contents, - const string16& message_text, + const base::string16& message_text, bool is_reload, const DialogClosedCallback& callback) OVERRIDE; - virtual bool HandleJavaScriptDialog(WebContents* web_contents, - bool accept, - const string16* prompt_override) OVERRIDE; + virtual bool HandleJavaScriptDialog( + WebContents* web_contents, + bool accept, + const base::string16* prompt_override) OVERRIDE; virtual void CancelActiveAndPendingDialogs( WebContents* web_contents) OVERRIDE; virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE; @@ -374,7 +380,9 @@ class CONTENT_EXPORT BrowserPluginGuest uint32 output_surface_id, int renderer_host_id, const cc::CompositorFrameAck& ack); - + void OnCopyFromCompositingSurfaceAck(int instance_id, + int request_id, + const SkBitmap& bitmap); // Handles drag events from the embedder. // When dragging, the drag events go to the embedder first, and if the drag // happens on the browser plugin, then the plugin sends a corresponding @@ -527,6 +535,13 @@ class CONTENT_EXPORT BrowserPluginGuest gfx::Size max_auto_size_; gfx::Size min_auto_size_; + // Each copy-request is identified by a unique number. The unique number is + // used to keep track of the right callback. + int copy_request_id_; + typedef base::Callback<void(bool, const SkBitmap&)> CopyRequestCallback; + typedef std::map<int, const CopyRequestCallback> CopyRequestMap; + CopyRequestMap copy_request_callbacks_; + typedef std::map<BrowserPluginGuest*, NewWindowInfo> PendingWindowMap; PendingWindowMap pending_new_windows_; base::WeakPtr<BrowserPluginGuest> opener_; diff --git a/content/browser/browser_plugin/browser_plugin_host_browsertest.cc b/content/browser/browser_plugin/browser_plugin_host_browsertest.cc index 42c748693d..209f43e5e5 100644 --- a/content/browser/browser_plugin/browser_plugin_host_browsertest.cc +++ b/content/browser/browser_plugin/browser_plugin_host_browsertest.cc @@ -453,11 +453,11 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, MAYBE_EmbedderSameAfterNav) { // does not happen and existing embedder doesn't change in web_contents. GURL test_url_new(embedded_test_server()->GetURL( "/browser_plugin_title_change.html")); - const string16 expected_title = ASCIIToUTF16("done"); + const base::string16 expected_title = ASCIIToUTF16("done"); content::TitleWatcher title_watcher(shell()->web_contents(), expected_title); NavigateToURL(shell(), test_url_new); VLOG(0) << "Start waiting for title"; - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); VLOG(0) << "Done navigating to second page"; @@ -536,26 +536,26 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, ReloadEmbedder) { // the page has successfully reloaded when it goes back to 'embedder' // in the next step. { - const string16 expected_title = ASCIIToUTF16("modified"); + const base::string16 expected_title = ASCIIToUTF16("modified"); content::TitleWatcher title_watcher(test_embedder()->web_contents(), expected_title); ExecuteSyncJSFunction(rvh, base::StringPrintf("SetTitle('%s');", "modified")); - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); } // Reload the embedder page, and verify that the reload was successful. // Then navigate the guest to verify that the browser process does not crash. { - const string16 expected_title = ASCIIToUTF16("embedder"); + const base::string16 expected_title = ASCIIToUTF16("embedder"); content::TitleWatcher title_watcher(test_embedder()->web_contents(), expected_title); test_embedder()->web_contents()->GetController().Reload(false); - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); ExecuteSyncJSFunction( @@ -618,7 +618,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, MAYBE_AcceptDragEvents) { // This should trigger appropriate messages from the embedder to the guest, // and end with a drop on the guest. The guest changes title when a drop // happens. - const string16 expected_title = ASCIIToUTF16("DROPPED"); + const base::string16 expected_title = ASCIIToUTF16("DROPPED"); content::TitleWatcher title_watcher(test_guest()->web_contents(), expected_title); @@ -628,7 +628,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, MAYBE_AcceptDragEvents) { blink::WebDragOperationEvery, 0); rvh->DragTargetDrop(gfx::Point(end_x, end_y), gfx::Point(end_x, end_y), 0); - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); } @@ -650,7 +650,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, PostMessage) { RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>( test_embedder()->web_contents()->GetRenderViewHost()); { - const string16 expected_title = ASCIIToUTF16("main guest"); + const base::string16 expected_title = ASCIIToUTF16("main guest"); content::TitleWatcher title_watcher(test_embedder()->web_contents(), expected_title); @@ -661,7 +661,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, PostMessage) { // The title will be updated to "main guest" at the last stage of the // process described above. - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); } } @@ -678,7 +678,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DISABLED_PostMessageToIFrame) { RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>( test_embedder()->web_contents()->GetRenderViewHost()); { - const string16 expected_title = ASCIIToUTF16("main guest"); + const base::string16 expected_title = ASCIIToUTF16("main guest"); content::TitleWatcher title_watcher(test_embedder()->web_contents(), expected_title); @@ -687,7 +687,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DISABLED_PostMessageToIFrame) { // The title will be updated to "main guest" at the last stage of the // process described above. - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); } { @@ -703,7 +703,7 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DISABLED_PostMessageToIFrame) { base::StringPrintf( "CreateChildFrame('%s');", test_url.spec().c_str())); - string16 actual_title = ready_watcher.WaitAndGetTitle(); + base::string16 actual_title = ready_watcher.WaitAndGetTitle(); EXPECT_EQ(ASCIIToUTF16("ready"), actual_title); content::TitleWatcher iframe_watcher(test_embedder()->web_contents(), @@ -810,4 +810,119 @@ IN_PROC_BROWSER_TEST_F(BrowserPluginHostTest, DoNotCrashOnInvalidNavigation) { EXPECT_TRUE(delegate->load_aborted_url().is_valid()); } + +// Tests involving the threaded compositor. +class BrowserPluginThreadedCompositorTest : public BrowserPluginHostTest { + public: + BrowserPluginThreadedCompositorTest() {} + virtual ~BrowserPluginThreadedCompositorTest() {} + + protected: + virtual void SetUpCommandLine(CommandLine* cmd) OVERRIDE { + BrowserPluginHostTest::SetUpCommandLine(cmd); + cmd->AppendSwitch(switches::kEnableThreadedCompositing); + + // http://crbug.com/327035 + cmd->AppendSwitch(switches::kDisableDelegatedRenderer); + } +}; + +static void CompareSkBitmaps(const SkBitmap& expected_bitmap, + const SkBitmap& bitmap) { + EXPECT_EQ(expected_bitmap.width(), bitmap.width()); + if (expected_bitmap.width() != bitmap.width()) + return; + EXPECT_EQ(expected_bitmap.height(), bitmap.height()); + if (expected_bitmap.height() != bitmap.height()) + return; + EXPECT_EQ(expected_bitmap.config(), bitmap.config()); + if (expected_bitmap.config() != bitmap.config()) + return; + + SkAutoLockPixels expected_bitmap_lock(expected_bitmap); + SkAutoLockPixels bitmap_lock(bitmap); + int fails = 0; + const int kAllowableError = 2; + for (int i = 0; i < bitmap.width() && fails < 10; ++i) { + for (int j = 0; j < bitmap.height() && fails < 10; ++j) { + SkColor expected_color = expected_bitmap.getColor(i, j); + SkColor color = bitmap.getColor(i, j); + int expected_alpha = SkColorGetA(expected_color); + int alpha = SkColorGetA(color); + int expected_red = SkColorGetR(expected_color); + int red = SkColorGetR(color); + int expected_green = SkColorGetG(expected_color); + int green = SkColorGetG(color); + int expected_blue = SkColorGetB(expected_color); + int blue = SkColorGetB(color); + EXPECT_NEAR(expected_alpha, alpha, kAllowableError) + << "expected_color: " << std::hex << expected_color + << " color: " << color + << " Failed at " << std::dec << i << ", " << j + << " Failure " << ++fails; + EXPECT_NEAR(expected_red, red, kAllowableError) + << "expected_color: " << std::hex << expected_color + << " color: " << color + << " Failed at " << std::dec << i << ", " << j + << " Failure " << ++fails; + EXPECT_NEAR(expected_green, green, kAllowableError) + << "expected_color: " << std::hex << expected_color + << " color: " << color + << " Failed at " << std::dec << i << ", " << j + << " Failure " << ++fails; + EXPECT_NEAR(expected_blue, blue, kAllowableError) + << "expected_color: " << std::hex << expected_color + << " color: " << color + << " Failed at " << std::dec << i << ", " << j + << " Failure " << ++fails; + } + } + EXPECT_LT(fails, 10); +} + +static void CompareSkBitmapAndRun(const base::Closure& callback, + const SkBitmap& expected_bitmap, + bool *result, + bool succeed, + const SkBitmap& bitmap) { + *result = succeed; + if (succeed) + CompareSkBitmaps(expected_bitmap, bitmap); + callback.Run(); +} + +// http://crbug.com/171744 +#if defined(OS_MACOSX) +#define MAYBE_GetBackingStore DISABLED_GetBackingStore +#else +#define MAYBE_GetBackingStore GetBackingStore +#endif +IN_PROC_BROWSER_TEST_F(BrowserPluginThreadedCompositorTest, + MAYBE_GetBackingStore) { + const char kEmbedderURL[] = "/browser_plugin_embedder.html"; + const char kHTMLForGuest[] = + "data:text/html,<html><style>body { background-color: red; }</style>" + "<body></body></html>"; + StartBrowserPluginTest(kEmbedderURL, kHTMLForGuest, true, + std::string("SetSize(50, 60);")); + + WebContentsImpl* guest_contents = test_guest()->web_contents(); + RenderWidgetHostImpl* guest_widget_host = + RenderWidgetHostImpl::From(guest_contents->GetRenderViewHost()); + + SkBitmap expected_bitmap; + expected_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 50, 60); + expected_bitmap.allocPixels(); + expected_bitmap.eraseARGB(255, 255, 0, 0); // #f00 + bool result = false; + while (!result) { + base::RunLoop loop; + guest_widget_host->CopyFromBackingStore(gfx::Rect(), + guest_widget_host->GetView()->GetViewBounds().size(), + base::Bind(&CompareSkBitmapAndRun, loop.QuitClosure(), expected_bitmap, + &result)); + loop.Run(); + } +} + } // namespace content diff --git a/content/browser/browser_plugin/test_browser_plugin_guest_delegate.cc b/content/browser/browser_plugin/test_browser_plugin_guest_delegate.cc index dc2db35119..59ae63555d 100644 --- a/content/browser/browser_plugin/test_browser_plugin_guest_delegate.cc +++ b/content/browser/browser_plugin/test_browser_plugin_guest_delegate.cc @@ -20,9 +20,9 @@ void TestBrowserPluginGuestDelegate::ResetStates() { void TestBrowserPluginGuestDelegate::AddMessageToConsole( int32 level, - const string16& message, + const base::string16& message, int32 line_no, - const string16& source_id) { + const base::string16& source_id) { } void TestBrowserPluginGuestDelegate::Close() { diff --git a/content/browser/browser_plugin/test_browser_plugin_guest_delegate.h b/content/browser/browser_plugin/test_browser_plugin_guest_delegate.h index 910ff9f324..4bfae4c622 100644 --- a/content/browser/browser_plugin/test_browser_plugin_guest_delegate.h +++ b/content/browser/browser_plugin/test_browser_plugin_guest_delegate.h @@ -22,9 +22,9 @@ class TestBrowserPluginGuestDelegate : public BrowserPluginGuestDelegate { private: // Overridden from BrowserPluginGuestDelegate: virtual void AddMessageToConsole(int32 level, - const string16& message, + const base::string16& message, int32 line_no, - const string16& source_id) OVERRIDE; + const base::string16& source_id) OVERRIDE; virtual void Close() OVERRIDE; virtual void GuestProcessGone(base::TerminationStatus status) OVERRIDE; virtual bool HandleKeyboardEvent( diff --git a/content/browser/browser_shutdown_profile_dumper.cc b/content/browser/browser_shutdown_profile_dumper.cc index ebec936011..3e74e063b0 100644 --- a/content/browser/browser_shutdown_profile_dumper.cc +++ b/content/browser/browser_shutdown_profile_dumper.cc @@ -37,7 +37,7 @@ void BrowserShutdownProfileDumper::WriteTracesToDisc( base::debug::TraceLog::GetInstance()->GetBufferPercentFull() << " full."; DCHECK(!dump_file_); - dump_file_ = file_util::OpenFile(file_name, "w+"); + dump_file_ = base::OpenFile(file_name, "w+"); if (!IsFileValid()) { LOG(ERROR) << "Failed to open performance trace file: " << file_name.value(); @@ -131,7 +131,7 @@ void BrowserShutdownProfileDumper::WriteChars(const char* chars, size_t size) { void BrowserShutdownProfileDumper::CloseFile() { if (!dump_file_) return; - file_util::CloseFile(dump_file_); + base::CloseFile(dump_file_); dump_file_ = NULL; } diff --git a/content/browser/browser_url_handler_impl.cc b/content/browser/browser_url_handler_impl.cc index 9a73afa5eb..05cc72df47 100644 --- a/content/browser/browser_url_handler_impl.cc +++ b/content/browser/browser_url_handler_impl.cc @@ -24,7 +24,7 @@ static bool HandleViewSource(GURL* url, BrowserContext* browser_context) { // Bug 26129: limit view-source to view the content and not any // other kind of 'active' url scheme like 'javascript' or 'data'. static const char* const allowed_sub_schemes[] = { - kHttpScheme, kHttpsScheme, chrome::kFtpScheme, + kHttpScheme, kHttpsScheme, kFtpScheme, chrome::kChromeDevToolsScheme, chrome::kChromeUIScheme, chrome::kFileScheme, chrome::kFileSystemScheme }; diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc index 85ec83a4e3..0667964f3e 100644 --- a/content/browser/child_process_security_policy_impl.cc +++ b/content/browser/child_process_security_policy_impl.cc @@ -310,7 +310,7 @@ ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl() { // We know about these schemes and believe them to be safe. RegisterWebSafeScheme(kHttpScheme); RegisterWebSafeScheme(kHttpsScheme); - RegisterWebSafeScheme(chrome::kFtpScheme); + RegisterWebSafeScheme(kFtpScheme); RegisterWebSafeScheme(chrome::kDataScheme); RegisterWebSafeScheme("feed"); RegisterWebSafeScheme(chrome::kBlobScheme); diff --git a/content/browser/child_process_security_policy_unittest.cc b/content/browser/child_process_security_policy_unittest.cc index 670848fa48..c4d51b3eb3 100644 --- a/content/browser/child_process_security_policy_unittest.cc +++ b/content/browser/child_process_security_policy_unittest.cc @@ -122,7 +122,7 @@ TEST_F(ChildProcessSecurityPolicyTest, IsWebSafeSchemeTest) { EXPECT_TRUE(p->IsWebSafeScheme(kHttpScheme)); EXPECT_TRUE(p->IsWebSafeScheme(kHttpsScheme)); - EXPECT_TRUE(p->IsWebSafeScheme(chrome::kFtpScheme)); + EXPECT_TRUE(p->IsWebSafeScheme(kFtpScheme)); EXPECT_TRUE(p->IsWebSafeScheme(chrome::kDataScheme)); EXPECT_TRUE(p->IsWebSafeScheme("feed")); EXPECT_TRUE(p->IsWebSafeScheme(chrome::kBlobScheme)); diff --git a/content/browser/device_orientation/data_fetcher_impl_android.cc b/content/browser/device_orientation/data_fetcher_impl_android.cc index 230507ee44..c103029f62 100644 --- a/content/browser/device_orientation/data_fetcher_impl_android.cc +++ b/content/browser/device_orientation/data_fetcher_impl_android.cc @@ -8,11 +8,20 @@ #include "base/android/jni_android.h" #include "base/memory/singleton.h" +#include "base/metrics/histogram.h" #include "content/browser/device_orientation/inertial_sensor_consts.h" #include "jni/DeviceMotionAndOrientation_jni.h" using base::android::AttachCurrentThread; +namespace { + +static void updateRotationVectorHistogram(bool value) { + UMA_HISTOGRAM_BOOLEAN("InertialSensor.RotationVectorAndroidAvailable", value); +} + +} + namespace content { DataFetcherImplAndroid::DataFetcherImplAndroid() @@ -54,8 +63,10 @@ void DataFetcherImplAndroid::GotOrientation( device_orientation_buffer_->data.hasGamma = true; device_orientation_buffer_->seqlock.WriteEnd(); - if (!is_orientation_buffer_ready_) + if (!is_orientation_buffer_ready_) { SetOrientationBufferReadyStatus(true); + updateRotationVectorHistogram(true); + } } void DataFetcherImplAndroid::GotAcceleration( @@ -191,6 +202,15 @@ void DataFetcherImplAndroid::CheckMotionBufferReadyToRead() { device_motion_buffer_->data.interval = kInertialSensorIntervalMillis; device_motion_buffer_->seqlock.WriteEnd(); SetMotionBufferReadyStatus(true); + + UMA_HISTOGRAM_BOOLEAN("InertialSensor.AccelerometerAndroidAvailable", + received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION] > 0); + UMA_HISTOGRAM_BOOLEAN( + "InertialSensor.AccelerometerIncGravityAndroidAvailable", + received_motion_data_[RECEIVED_MOTION_DATA_ACCELERATION_INCL_GRAVITY] + > 0); + UMA_HISTOGRAM_BOOLEAN("InertialSensor.GyroscopeAndroidAvailable", + received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] > 0); } } @@ -233,6 +253,10 @@ bool DataFetcherImplAndroid::StartFetchingDeviceOrientationData( // to start firing all-null events. SetOrientationBufferReadyStatus(!success); } + + if (!success) + updateRotationVectorHistogram(false); + return success; } diff --git a/content/browser/devtools/browser_protocol.json b/content/browser/devtools/browser_protocol.json index 029b7a0915..59e73c0c59 100644 --- a/content/browser/devtools/browser_protocol.json +++ b/content/browser/devtools/browser_protocol.json @@ -21,7 +21,7 @@ "type": "object", "properties": [ { "name": "devices", "type": "array", "items": { "$ref": "GPUDevice" }, "description": "The graphics devices on the system. Element 0 is the primary GPU." }, - { "name": "auxAttributes", "type": "object", "optional": "true", "description": "An optional dictionary of additional GPU related attributes." } + { "name": "auxAttributes", "type": "object", "optional": "true", "description": "An optional dictionary of additional GPU related attributes." }, { "name": "featureStatus", "type": "object", "optional": "true", "description": "An optional dictionary of graphics features and their status." } ], "description": "Provides information about the GPU(s) on the system." @@ -42,7 +42,8 @@ "description": "Returns information about the system.", "returns": [ { "name": "info", "$ref": "SystemInfo", "description": "Information about the system." } - ] + ], + "handlers": ["browser"] } ] }] diff --git a/content/browser/devtools/devtools_manager_unittest.cc b/content/browser/devtools/devtools_manager_unittest.cc index f223c6020c..aac9b6cbb9 100644 --- a/content/browser/devtools/devtools_manager_unittest.cc +++ b/content/browser/devtools/devtools_manager_unittest.cc @@ -7,7 +7,6 @@ #include "base/time/time.h" #include "content/browser/devtools/devtools_manager_impl.h" #include "content/browser/devtools/render_view_devtools_agent_host.h" -#include "content/browser/renderer_host/test_render_view_host.h" #include "content/common/view_messages.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/devtools_agent_host.h" @@ -16,6 +15,7 @@ #include "content/public/browser/devtools_external_agent_proxy_delegate.h" #include "content/public/browser/web_contents_delegate.h" #include "content/test/test_content_browser_client.h" +#include "content/test/test_render_view_host.h" #include "content/test/test_web_contents.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/content/browser/devtools/devtools_protocol_constants.cc b/content/browser/devtools/devtools_protocol_constants.cc index ff0357b842..af5ecd1f58 100644 --- a/content/browser/devtools/devtools_protocol_constants.cc +++ b/content/browser/devtools/devtools_protocol_constants.cc @@ -2,206 +2,292 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// THIS FILE IS AUTOGENERATED. +// If you need change something in this file, please see +// protocol.json and browser_protocol.json + #include "content/browser/devtools/devtools_protocol_constants.h" namespace content { namespace devtools { -const char kParamX[] = "x"; -const char kParamY[] = "y"; -const char kParamWidth[] = "width"; -const char kParamHeight[] = "height"; const char kResult[] = "result"; namespace DOM { - -namespace setFileInputFiles { - const char kName[] = "DOM.setFileInputFiles"; - const char kParamFiles[] = "files"; -} // setFileInputFiles - -} // DOM + const char kName[] = "DOM"; + + namespace Rect { + const char kParamHeight[] = "height"; + const char kParamWidth[] = "width"; + const char kParamX[] = "x"; + const char kParamY[] = "y"; + } // Rect + + namespace setFileInputFiles { + const char kName[] = "DOM.setFileInputFiles"; + const char kParamFiles[] = "files"; + const char kParamNodeId[] = "nodeId"; + } // setFileInputFiles +} // DOM namespace Input { - -const char kParamType[] = "type"; -const char kParamModifiers[] = "modifiers"; -const char kParamTimestamp[] = "timestamp"; -const char kParamDeviceSpace[] = "deviceSpace"; - -namespace dispatchMouseEvent { - const char kName[] = "Input.dispatchMouseEvent"; - const char kParamButton[] = "button"; - const char kParamClickCount[] = "clickCount"; -} // dispatchMouseEvent - -namespace dispatchGestureEvent { - const char kName[] = "Input.dispatchGestureEvent"; - const char kParamDeltaX[] = "deltaX"; - const char kParamDeltaY[] = "deltaY"; - const char kParamPinchScale[] = "pinchScale"; -} // dispatchGestureEvent - -} // Input + const char kName[] = "Input"; + + namespace dispatchGestureEvent { + const char kName[] = "Input.dispatchGestureEvent"; + const char kParamDeltaX[] = "deltaX"; + const char kParamDeltaY[] = "deltaY"; + const char kParamPinchScale[] = "pinchScale"; + const char kParamTimestamp[] = "timestamp"; + const char kParamType[] = "type"; + const char kParamX[] = "x"; + const char kParamY[] = "y"; + + namespace Type { + const char kEnumPinchBegin[] = "pinchBegin"; + const char kEnumPinchEnd[] = "pinchEnd"; + const char kEnumPinchUpdate[] = "pinchUpdate"; + const char kEnumScrollBegin[] = "scrollBegin"; + const char kEnumScrollEnd[] = "scrollEnd"; + const char kEnumScrollUpdate[] = "scrollUpdate"; + const char kEnumTap[] = "tap"; + const char kEnumTapDown[] = "tapDown"; + } // Type + } // dispatchGestureEvent + + namespace dispatchMouseEvent { + const char kName[] = "Input.dispatchMouseEvent"; + const char kParamButton[] = "button"; + const char kParamClickCount[] = "clickCount"; + const char kParamDeviceSpace[] = "deviceSpace"; + const char kParamModifiers[] = "modifiers"; + const char kParamTimestamp[] = "timestamp"; + const char kParamType[] = "type"; + const char kParamX[] = "x"; + const char kParamY[] = "y"; + + namespace Button { + const char kEnumLeft[] = "left"; + const char kEnumMiddle[] = "middle"; + const char kEnumNone[] = "none"; + const char kEnumRight[] = "right"; + } // Button + + namespace Type { + const char kEnumMouseMoved[] = "mouseMoved"; + const char kEnumMousePressed[] = "mousePressed"; + const char kEnumMouseReleased[] = "mouseReleased"; + } // Type + } // dispatchMouseEvent +} // Input namespace Inspector { + const char kName[] = "Inspector"; -namespace detached { - const char kName[] = "Inspector.detached"; - const char kParamReason[] = "reason"; -} // detached + namespace detached { + const char kName[] = "Inspector.detached"; + const char kParamReason[] = "reason"; + } // detached -namespace targetCrashed { - const char kName[] = "Inspector.targetCrashed"; -} // targetCrashed - -} // Inspector + namespace targetCrashed { + const char kName[] = "Inspector.targetCrashed"; + } // targetCrashed +} // Inspector namespace Page { + const char kName[] = "Page"; + + namespace NavigationEntry { + const char kParamId[] = "id"; + const char kParamTitle[] = "title"; + const char kParamUrl[] = "url"; + } // NavigationEntry + + namespace Quota { + const char kParamPersistent[] = "persistent"; + const char kParamTemporary[] = "temporary"; + } // Quota + + namespace ScreencastFrameMetadata { + const char kParamDeviceScaleFactor[] = "deviceScaleFactor"; + const char kParamOffsetBottom[] = "offsetBottom"; + const char kParamOffsetTop[] = "offsetTop"; + const char kParamPageScaleFactor[] = "pageScaleFactor"; + const char kParamPageScaleFactorMax[] = "pageScaleFactorMax"; + const char kParamPageScaleFactorMin[] = "pageScaleFactorMin"; + const char kParamViewport[] = "viewport"; + } // ScreencastFrameMetadata + + namespace Usage { + const char kParamPersistent[] = "persistent"; + const char kParamSyncable[] = "syncable"; + const char kParamTemporary[] = "temporary"; + } // Usage + + namespace UsageItem { + const char kParamId[] = "id"; + const char kParamValue[] = "value"; + + namespace Id { + const char kEnumAppcache[] = "appcache"; + const char kEnumDatabase[] = "database"; + const char kEnumFilesystem[] = "filesystem"; + const char kEnumIndexeddatabase[] = "indexeddatabase"; + } // Id + } // UsageItem + + namespace canScreencast { + const char kName[] = "Page.canScreencast"; + const char kResponseResult[] = "result"; + } // canScreencast + + namespace captureScreenshot { + const char kName[] = "Page.captureScreenshot"; + const char kParamFormat[] = "format"; + const char kParamMaxHeight[] = "maxHeight"; + const char kParamMaxWidth[] = "maxWidth"; + const char kParamQuality[] = "quality"; + const char kResponseData[] = "data"; + const char kResponseMetadata[] = "metadata"; + + namespace Format { + const char kEnumJpeg[] = "jpeg"; + const char kEnumPng[] = "png"; + } // Format + } // captureScreenshot + + namespace disable { + const char kName[] = "Page.disable"; + } // disable + + namespace getNavigationHistory { + const char kName[] = "Page.getNavigationHistory"; + const char kResponseCurrentIndex[] = "currentIndex"; + const char kResponseEntries[] = "entries"; + } // getNavigationHistory + + namespace handleJavaScriptDialog { + const char kName[] = "Page.handleJavaScriptDialog"; + const char kParamAccept[] = "accept"; + const char kParamPromptText[] = "promptText"; + } // handleJavaScriptDialog + + namespace navigate { + const char kName[] = "Page.navigate"; + const char kParamUrl[] = "url"; + } // navigate + + namespace navigateToHistoryEntry { + const char kName[] = "Page.navigateToHistoryEntry"; + const char kParamEntryId[] = "entryId"; + } // navigateToHistoryEntry + + namespace queryUsageAndQuota { + const char kName[] = "Page.queryUsageAndQuota"; + const char kParamSecurityOrigin[] = "securityOrigin"; + const char kResponseQuota[] = "quota"; + const char kResponseUsage[] = "usage"; + } // queryUsageAndQuota + + namespace reload { + const char kName[] = "Page.reload"; + const char kParamIgnoreCache[] = "ignoreCache"; + const char kParamScriptPreprocessor[] = "scriptPreprocessor"; + const char kParamScriptToEvaluateOnLoad[] = "scriptToEvaluateOnLoad"; + } // reload + + namespace screencastFrame { + const char kName[] = "Page.screencastFrame"; + const char kParamData[] = "data"; + const char kParamMetadata[] = "metadata"; + } // screencastFrame + + namespace screencastVisibilityChanged { + const char kName[] = "Page.screencastVisibilityChanged"; + const char kParamVisible[] = "visible"; + } // screencastVisibilityChanged + + namespace startScreencast { + const char kName[] = "Page.startScreencast"; + const char kParamFormat[] = "format"; + const char kParamMaxHeight[] = "maxHeight"; + const char kParamMaxWidth[] = "maxWidth"; + const char kParamQuality[] = "quality"; + + namespace Format { + const char kEnumJpeg[] = "jpeg"; + const char kEnumPng[] = "png"; + } // Format + } // startScreencast + + namespace stopScreencast { + const char kName[] = "Page.stopScreencast"; + } // stopScreencast +} // Page -const char kData[] = "data"; -const char kMetadata[] = "metadata"; -const char kParamDeviceScaleFactor[] = "deviceScaleFactor"; -const char kParamPageScaleFactor[] = "pageScaleFactor"; -const char kParamPageScaleFactorMin[] = "pageScaleFactorMin"; -const char kParamPageScaleFactorMax[] = "pageScaleFactorMax"; -const char kParamOffsetBottom[] = "offsetBottom"; -const char kParamOffsetTop[] = "offsetTop"; -const char kParamViewport[] = "viewport"; - -namespace disable { - const char kName[] = "Page.disable"; -} // disable - -namespace handleJavaScriptDialog { - const char kName[] = "Page.handleJavaScriptDialog"; - const char kParamAccept[] = "accept"; - const char kParamPromptText[] = "promptText"; -} // handleJavaScriptDialog - -namespace navigate { - const char kName[] = "Page.navigate"; - const char kParamUrl[] = "url"; -} // navigate - -namespace reload { - const char kName[] = "Page.reload"; -} // reload - -namespace getNavigationHistory { - const char kName[] = "Page.getNavigationHistory"; - const char kResponseCurrentIndex[] = "currentIndex"; - const char kResponseEntries[] = "entries"; - const char kResponseEntryId[] = "id"; - const char kResponseEntryURL[] = "url"; - const char kResponseEntryTitle[] = "title"; -} // getNavigationHistory - -namespace navigateToHistoryEntry { - const char kName[] = "Page.navigateToHistoryEntry"; - const char kParamEntryId[] = "entryId"; -} // navigateToHistoryEntry - -namespace captureScreenshot { - const char kName[] = "Page.captureScreenshot"; - const char kParamFormat[] = "format"; - const char kParamQuality[] = "quality"; - const char kParamMaxWidth[] = "maxWidth"; - const char kParamMaxHeight[] = "maxHeight"; -} // captureScreenshot - -namespace canScreencast { - const char kName[] = "Page.canScreencast"; -} // canScreencast - -namespace startScreencast { - const char kName[] = "Page.startScreencast"; -} // startScreencast - -namespace stopScreencast { - const char kName[] = "Page.stopScreencast"; -} // stopScreencast - -namespace screencastFrame { - const char kName[] = "Page.screencastFrame"; -} // screencastFrame - -namespace queryUsageAndQuota { - const char kName[] = "Page.queryUsageAndQuota"; - const char kParamSecurityOrigin[] = "securityOrigin"; - extern const char kResponseQuota[] = "quota"; - extern const char kResponseUsage[] = "usage"; -} // queryUsageAndQuota - -namespace Quota { - extern const char kItemTemporary[] = "temporary"; - extern const char kItemPersistent[] = "persistent"; -} // Quota - -namespace Usage { - extern const char kItemTemporary[] = "temporary"; - extern const char kItemPersistent[] = "persistent"; - extern const char kItemSyncable[] = "syncable"; -} // Usage - -namespace UsageItem { - namespace ID { - extern const char kFilesystem[] = "filesystem"; - extern const char kDatabase[] = "database"; - extern const char kAppcache[] = "appcache"; - extern const char kIndexedDatabase[] = "indexeddatabase"; - } // ID - extern const char kItemID[] = "id"; - extern const char kItemValue[] = "value"; -} // UsageItem - -namespace screencastVisibilityChanged { - const char kName[] = "Page.screencastVisibilityChanged"; - const char kParamVisible[] = "visible"; -} // screencastVisibilityChanged - -} // Page - -namespace Worker { - -namespace disconnectedFromWorker { - const char kName[] = "Worker.disconnectedFromWorker"; -} // disconnectedFromWorker +namespace SystemInfo { + const char kName[] = "SystemInfo"; -} // Worker + namespace GPUDevice { + const char kParamDeviceId[] = "deviceId"; + const char kParamDeviceString[] = "deviceString"; + const char kParamVendorId[] = "vendorId"; + const char kParamVendorString[] = "vendorString"; + } // GPUDevice + + namespace GPUInfo { + const char kParamAuxAttributes[] = "auxAttributes"; + const char kParamDevices[] = "devices"; + const char kParamFeatureStatus[] = "featureStatus"; + } // GPUInfo + + namespace SystemInfo { + const char kParamGpu[] = "gpu"; + const char kParamModelName[] = "modelName"; + } // SystemInfo + + namespace getInfo { + const char kName[] = "SystemInfo.getInfo"; + const char kResponseInfo[] = "info"; + } // getInfo +} // SystemInfo namespace Tracing { const char kName[] = "Tracing"; -namespace start { - const char kName[] = "Tracing.start"; - const char kCategories[] = "categories"; - const char kTraceOptions[] = "trace-options"; -} // start + namespace dataCollected { + const char kName[] = "Tracing.dataCollected"; + const char kParamValue[] = "value"; + } // dataCollected -namespace end { - const char kName[] = "Tracing.end"; -} + namespace end { + const char kName[] = "Tracing.end"; + } // end -namespace tracingComplete { - const char kName[] = "Tracing.tracingComplete"; -} + namespace start { + const char kName[] = "Tracing.start"; + const char kParamCategories[] = "categories"; + const char kParamOptions[] = "options"; + } // start -namespace dataCollected { - const char kName[] = "Tracing.dataCollected"; - const char kValue[] = "value"; -} + namespace tracingComplete { + const char kName[] = "Tracing.tracingComplete"; + } // tracingComplete +} // Tracing -} // Tracing +namespace Worker { + const char kName[] = "Worker"; -namespace SystemInfo { - const char kName[] = "SystemInfo"; + namespace disconnectFromWorker { + const char kName[] = "Worker.disconnectFromWorker"; + const char kParamWorkerId[] = "workerId"; + } // disconnectFromWorker + + namespace disconnectedFromWorker { + const char kName[] = "Worker.disconnectedFromWorker"; + } // disconnectedFromWorker +} // Worker -namespace getInfo { - const char kName[] = "SystemInfo.getInfo"; -} // getInfo -} // SystemInfo } // devtools } // content - diff --git a/content/browser/devtools/devtools_protocol_constants.h b/content/browser/devtools/devtools_protocol_constants.h index e24304a540..8ed159bc0d 100644 --- a/content/browser/devtools/devtools_protocol_constants.h +++ b/content/browser/devtools/devtools_protocol_constants.h @@ -5,211 +5,290 @@ #ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_CONSTANTSH_ #define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_PROTOCOL_CONSTANTSH_ -// The constants in this file should be used instead manually constructing -// strings passed to and from DevTools protocol. -// -// There is a plan to generate this file from inspector.json automatically. -// Until then please feel free to add the constants here as needed. +// THIS FILE IS AUTOGENERATED. +// If you need change something in this file, please see +// protocol.json and browser_protocol.json namespace content { namespace devtools { -extern const char kParamX[]; -extern const char kParamY[]; -extern const char kParamWidth[]; -extern const char kParamHeight[]; extern const char kResult[]; namespace DOM { + extern const char kName[]; + + namespace Rect { + extern const char kParamHeight[]; + extern const char kParamWidth[]; + extern const char kParamX[]; + extern const char kParamY[]; + } // Rect namespace setFileInputFiles { extern const char kName[]; extern const char kParamFiles[]; - } // setFileInputFiles - -} // DOM + extern const char kParamNodeId[]; + } // setFileInputFiles +} // DOM namespace Input { - - extern const char kParamType[]; - extern const char kParamModifiers[]; - extern const char kParamTimestamp[]; - extern const char kParamDeviceSpace[]; - - namespace dispatchMouseEvent { - extern const char kName[]; - extern const char kParamX[]; - extern const char kParamY[]; - extern const char kParamButton[]; - extern const char kParamClickCount[]; - } // dispatchMouseEvent + extern const char kName[]; namespace dispatchGestureEvent { extern const char kName[]; extern const char kParamDeltaX[]; extern const char kParamDeltaY[]; extern const char kParamPinchScale[]; - } // dispatchGestureEvent + extern const char kParamTimestamp[]; + extern const char kParamType[]; + extern const char kParamX[]; + extern const char kParamY[]; + + namespace Type { + extern const char kEnumPinchBegin[]; + extern const char kEnumPinchEnd[]; + extern const char kEnumPinchUpdate[]; + extern const char kEnumScrollBegin[]; + extern const char kEnumScrollEnd[]; + extern const char kEnumScrollUpdate[]; + extern const char kEnumTap[]; + extern const char kEnumTapDown[]; + } // Type + } // dispatchGestureEvent + + namespace dispatchMouseEvent { + extern const char kName[]; + extern const char kParamButton[]; + extern const char kParamClickCount[]; + extern const char kParamDeviceSpace[]; + extern const char kParamModifiers[]; + extern const char kParamTimestamp[]; + extern const char kParamType[]; + extern const char kParamX[]; + extern const char kParamY[]; -} // Input + namespace Button { + extern const char kEnumLeft[]; + extern const char kEnumMiddle[]; + extern const char kEnumNone[]; + extern const char kEnumRight[]; + } // Button + + namespace Type { + extern const char kEnumMouseMoved[]; + extern const char kEnumMousePressed[]; + extern const char kEnumMouseReleased[]; + } // Type + } // dispatchMouseEvent +} // Input namespace Inspector { + extern const char kName[]; namespace detached { extern const char kName[]; extern const char kParamReason[]; - } // detached + } // detached namespace targetCrashed { extern const char kName[]; - } // targetCrashed - -} // Inspector + } // targetCrashed +} // Inspector namespace Page { + extern const char kName[]; - extern const char kData[]; - extern const char kMetadata[]; - extern const char kParamDeviceScaleFactor[]; - extern const char kParamPageScaleFactor[]; - extern const char kParamPageScaleFactorMin[]; - extern const char kParamPageScaleFactorMax[]; - extern const char kParamOffsetBottom[]; - extern const char kParamOffsetTop[]; - extern const char kParamViewport[]; + namespace NavigationEntry { + extern const char kParamId[]; + extern const char kParamTitle[]; + extern const char kParamUrl[]; + } // NavigationEntry - namespace disable { - extern const char kName[]; - } // disable + namespace Quota { + extern const char kParamPersistent[]; + extern const char kParamTemporary[]; + } // Quota + + namespace ScreencastFrameMetadata { + extern const char kParamDeviceScaleFactor[]; + extern const char kParamOffsetBottom[]; + extern const char kParamOffsetTop[]; + extern const char kParamPageScaleFactor[]; + extern const char kParamPageScaleFactorMax[]; + extern const char kParamPageScaleFactorMin[]; + extern const char kParamViewport[]; + } // ScreencastFrameMetadata - namespace handleJavaScriptDialog { + namespace Usage { + extern const char kParamPersistent[]; + extern const char kParamSyncable[]; + extern const char kParamTemporary[]; + } // Usage + + namespace UsageItem { + extern const char kParamId[]; + extern const char kParamValue[]; + + namespace Id { + extern const char kEnumAppcache[]; + extern const char kEnumDatabase[]; + extern const char kEnumFilesystem[]; + extern const char kEnumIndexeddatabase[]; + } // Id + } // UsageItem + + namespace canScreencast { extern const char kName[]; - extern const char kParamAccept[]; - extern const char kParamPromptText[]; - } // handleJavaScriptDialog + extern const char kResponseResult[]; + } // canScreencast - namespace navigate { + namespace captureScreenshot { extern const char kName[]; - extern const char kParamUrl[]; - } // navigate + extern const char kParamFormat[]; + extern const char kParamMaxHeight[]; + extern const char kParamMaxWidth[]; + extern const char kParamQuality[]; + extern const char kResponseData[]; + extern const char kResponseMetadata[]; - namespace reload { + namespace Format { + extern const char kEnumJpeg[]; + extern const char kEnumPng[]; + } // Format + } // captureScreenshot + + namespace disable { extern const char kName[]; - } // reload + } // disable namespace getNavigationHistory { extern const char kName[]; extern const char kResponseCurrentIndex[]; extern const char kResponseEntries[]; - extern const char kResponseEntryId[]; - extern const char kResponseEntryURL[]; - extern const char kResponseEntryTitle[]; - } // getNavigationHistory + } // getNavigationHistory - namespace navigateToHistoryEntry { + namespace handleJavaScriptDialog { extern const char kName[]; - extern const char kParamEntryId[]; - } // navigateToHistoryEntry + extern const char kParamAccept[]; + extern const char kParamPromptText[]; + } // handleJavaScriptDialog - namespace captureScreenshot { + namespace navigate { extern const char kName[]; - extern const char kParamFormat[]; - extern const char kParamQuality[]; - extern const char kParamMaxWidth[]; - extern const char kParamMaxHeight[]; - } // captureScreenshot + extern const char kParamUrl[]; + } // navigate - namespace canScreencast { + namespace navigateToHistoryEntry { extern const char kName[]; - } // canScreencast + extern const char kParamEntryId[]; + } // navigateToHistoryEntry - namespace startScreencast { + namespace queryUsageAndQuota { extern const char kName[]; - } // startScreencast + extern const char kParamSecurityOrigin[]; + extern const char kResponseQuota[]; + extern const char kResponseUsage[]; + } // queryUsageAndQuota - namespace stopScreencast { + namespace reload { extern const char kName[]; - } // stopScreencast + extern const char kParamIgnoreCache[]; + extern const char kParamScriptPreprocessor[]; + extern const char kParamScriptToEvaluateOnLoad[]; + } // reload namespace screencastFrame { extern const char kName[]; - } // screencastFrame + extern const char kParamData[]; + extern const char kParamMetadata[]; + } // screencastFrame - namespace queryUsageAndQuota { + namespace screencastVisibilityChanged { extern const char kName[]; - extern const char kParamSecurityOrigin[]; - extern const char kResponseQuota[]; - extern const char kResponseUsage[]; - } // queryUsageAndQuota + extern const char kParamVisible[]; + } // screencastVisibilityChanged - namespace Quota { - extern const char kItemTemporary[]; - extern const char kItemPersistent[]; - } // Quota + namespace startScreencast { + extern const char kName[]; + extern const char kParamFormat[]; + extern const char kParamMaxHeight[]; + extern const char kParamMaxWidth[]; + extern const char kParamQuality[]; - namespace Usage { - extern const char kItemTemporary[]; - extern const char kItemPersistent[]; - extern const char kItemSyncable[]; - } // Usage + namespace Format { + extern const char kEnumJpeg[]; + extern const char kEnumPng[]; + } // Format + } // startScreencast - namespace UsageItem { - namespace ID { - extern const char kFilesystem[]; - extern const char kDatabase[]; - extern const char kAppcache[]; - extern const char kIndexedDatabase[]; - } // ID - extern const char kItemID[]; - extern const char kItemValue[]; - } // UsageItem + namespace stopScreencast { + extern const char kName[]; + } // stopScreencast +} // Page - namespace screencastVisibilityChanged { +namespace SystemInfo { + extern const char kName[]; + + namespace GPUDevice { + extern const char kParamDeviceId[]; + extern const char kParamDeviceString[]; + extern const char kParamVendorId[]; + extern const char kParamVendorString[]; + } // GPUDevice + + namespace GPUInfo { + extern const char kParamAuxAttributes[]; + extern const char kParamDevices[]; + extern const char kParamFeatureStatus[]; + } // GPUInfo + + namespace SystemInfo { + extern const char kParamGpu[]; + extern const char kParamModelName[]; + } // SystemInfo + + namespace getInfo { extern const char kName[]; - extern const char kParamVisible[]; - } // screencastVisibilityChanged -} // Page + extern const char kResponseInfo[]; + } // getInfo +} // SystemInfo namespace Tracing { extern const char kName[]; - namespace start { + namespace dataCollected { extern const char kName[]; - extern const char kCategories[]; - extern const char kTraceOptions[]; - } // start + extern const char kParamValue[]; + } // dataCollected namespace end { extern const char kName[]; - } + } // end - namespace tracingComplete { + namespace start { extern const char kName[]; - } + extern const char kParamCategories[]; + extern const char kParamOptions[]; + } // start - namespace dataCollected { + namespace tracingComplete { extern const char kName[]; - extern const char kValue[]; - } - -} // Tracing + } // tracingComplete +} // Tracing namespace Worker { + extern const char kName[]; - namespace disconnectedFromWorker { + namespace disconnectFromWorker { extern const char kName[]; - } // disconnectedFromWorker - -} // Worker + extern const char kParamWorkerId[]; + } // disconnectFromWorker + namespace disconnectedFromWorker { + extern const char kName[]; + } // disconnectedFromWorker +} // Worker -namespace SystemInfo { - extern const char kName[]; - -namespace getInfo { - extern const char kName[]; -} // getInfo -} // SystemInfo } // devtools } // content diff --git a/content/browser/devtools/devtools_resources.gyp b/content/browser/devtools/devtools_resources.gyp index 19b114c9df..30b4220945 100644 --- a/content/browser/devtools/devtools_resources.gyp +++ b/content/browser/devtools/devtools_resources.gyp @@ -8,7 +8,7 @@ 'target_name': 'devtools_resources', 'type': 'none', 'dependencies': [ - '../../../third_party/WebKit/Source/devtools/devtools.gyp:generate_devtools_grd', + '../../../third_party/WebKit/public/blink_devtools.gyp:blink_generate_devtools_grd', ], 'variables': { 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/webkit', diff --git a/content/browser/devtools/devtools_resources.target.darwin-arm.mk b/content/browser/devtools/devtools_resources.target.darwin-arm.mk index a0fc8f39ed..cb142bb384 100644 --- a/content/browser/devtools/devtools_resources.target.darwin-arm.mk +++ b/content/browser/devtools/devtools_resources.target.darwin-arm.mk @@ -12,7 +12,7 @@ gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared) # Make sure our deps are built first. GYP_TARGET_DEPENDENCIES := \ - $(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp + $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_generate_devtools_grd_gyp)/blink_generate_devtools_grd.stamp ### Rules for action "devtools_resources": $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_local_path := $(LOCAL_PATH) @@ -21,7 +21,7 @@ $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_shared_inte $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH)) $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/clique_unittest.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/c_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/gather/txt_unittest.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grd_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/grit_runner_unittest.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/lazy_re_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/base_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/include_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/io_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/message_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/misc_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/structure_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/pseudo_unittest.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/tclib_unittest.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/build_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb_unittest.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/util_unittest.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES) @echo "Gyp action: Generating resources from $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd ($@)" - $(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D use_concatenated_impulse_responses + $(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses $(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ; $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ; diff --git a/content/browser/devtools/devtools_resources.target.darwin-mips.mk b/content/browser/devtools/devtools_resources.target.darwin-mips.mk index a0fc8f39ed..cb142bb384 100644 --- a/content/browser/devtools/devtools_resources.target.darwin-mips.mk +++ b/content/browser/devtools/devtools_resources.target.darwin-mips.mk @@ -12,7 +12,7 @@ gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared) # Make sure our deps are built first. GYP_TARGET_DEPENDENCIES := \ - $(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp + $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_generate_devtools_grd_gyp)/blink_generate_devtools_grd.stamp ### Rules for action "devtools_resources": $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_local_path := $(LOCAL_PATH) @@ -21,7 +21,7 @@ $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_shared_inte $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH)) $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/clique_unittest.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/c_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/gather/txt_unittest.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grd_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/grit_runner_unittest.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/lazy_re_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/base_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/include_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/io_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/message_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/misc_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/structure_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/pseudo_unittest.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/tclib_unittest.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/build_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb_unittest.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/util_unittest.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES) @echo "Gyp action: Generating resources from $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd ($@)" - $(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D use_concatenated_impulse_responses + $(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses $(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ; $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ; diff --git a/content/browser/devtools/devtools_resources.target.darwin-x86.mk b/content/browser/devtools/devtools_resources.target.darwin-x86.mk index a0fc8f39ed..f176b4becf 100644 --- a/content/browser/devtools/devtools_resources.target.darwin-x86.mk +++ b/content/browser/devtools/devtools_resources.target.darwin-x86.mk @@ -12,7 +12,7 @@ gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared) # Make sure our deps are built first. GYP_TARGET_DEPENDENCIES := \ - $(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp + $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_generate_devtools_grd_gyp)/blink_generate_devtools_grd.stamp ### Rules for action "devtools_resources": $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_local_path := $(LOCAL_PATH) @@ -21,7 +21,7 @@ $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_shared_inte $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH)) $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/clique_unittest.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/c_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/gather/txt_unittest.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grd_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/grit_runner_unittest.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/lazy_re_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/base_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/include_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/io_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/message_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/misc_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/structure_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/pseudo_unittest.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/tclib_unittest.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/build_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb_unittest.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/util_unittest.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES) @echo "Gyp action: Generating resources from $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd ($@)" - $(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D use_concatenated_impulse_responses + $(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses $(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ; $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ; diff --git a/content/browser/devtools/devtools_resources.target.linux-arm.mk b/content/browser/devtools/devtools_resources.target.linux-arm.mk index a0fc8f39ed..cb142bb384 100644 --- a/content/browser/devtools/devtools_resources.target.linux-arm.mk +++ b/content/browser/devtools/devtools_resources.target.linux-arm.mk @@ -12,7 +12,7 @@ gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared) # Make sure our deps are built first. GYP_TARGET_DEPENDENCIES := \ - $(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp + $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_generate_devtools_grd_gyp)/blink_generate_devtools_grd.stamp ### Rules for action "devtools_resources": $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_local_path := $(LOCAL_PATH) @@ -21,7 +21,7 @@ $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_shared_inte $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH)) $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/clique_unittest.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/c_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/gather/txt_unittest.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grd_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/grit_runner_unittest.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/lazy_re_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/base_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/include_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/io_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/message_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/misc_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/structure_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/pseudo_unittest.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/tclib_unittest.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/build_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb_unittest.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/util_unittest.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES) @echo "Gyp action: Generating resources from $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd ($@)" - $(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D use_concatenated_impulse_responses + $(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses $(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ; $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ; diff --git a/content/browser/devtools/devtools_resources.target.linux-mips.mk b/content/browser/devtools/devtools_resources.target.linux-mips.mk index a0fc8f39ed..cb142bb384 100644 --- a/content/browser/devtools/devtools_resources.target.linux-mips.mk +++ b/content/browser/devtools/devtools_resources.target.linux-mips.mk @@ -12,7 +12,7 @@ gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared) # Make sure our deps are built first. GYP_TARGET_DEPENDENCIES := \ - $(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp + $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_generate_devtools_grd_gyp)/blink_generate_devtools_grd.stamp ### Rules for action "devtools_resources": $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_local_path := $(LOCAL_PATH) @@ -21,7 +21,7 @@ $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_shared_inte $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH)) $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/clique_unittest.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/c_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/gather/txt_unittest.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grd_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/grit_runner_unittest.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/lazy_re_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/base_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/include_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/io_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/message_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/misc_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/structure_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/pseudo_unittest.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/tclib_unittest.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/build_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb_unittest.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/util_unittest.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES) @echo "Gyp action: Generating resources from $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd ($@)" - $(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D use_concatenated_impulse_responses + $(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses $(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ; $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ; diff --git a/content/browser/devtools/devtools_resources.target.linux-x86.mk b/content/browser/devtools/devtools_resources.target.linux-x86.mk index a0fc8f39ed..f176b4becf 100644 --- a/content/browser/devtools/devtools_resources.target.linux-x86.mk +++ b/content/browser/devtools/devtools_resources.target.linux-x86.mk @@ -12,7 +12,7 @@ gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared) # Make sure our deps are built first. GYP_TARGET_DEPENDENCIES := \ - $(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp + $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_generate_devtools_grd_gyp)/blink_generate_devtools_grd.stamp ### Rules for action "devtools_resources": $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_local_path := $(LOCAL_PATH) @@ -21,7 +21,7 @@ $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_shared_inte $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH)) $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/clique_unittest.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/c_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/rc_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html_unittest.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/gather/txt_unittest.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grd_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/grit_runner_unittest.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/lazy_re_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/base_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/include_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/io_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/message_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/misc_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/structure_unittest.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/pseudo_unittest.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/tclib_unittest.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/build_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc_unittest.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb_unittest.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/util_unittest.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader_unittest.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES) @echo "Gyp action: Generating resources from $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd ($@)" - $(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D use_concatenated_impulse_responses + $(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f GRIT_DIR/../gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses $(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ; $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ; diff --git a/content/browser/devtools/devtools_tracing_handler.cc b/content/browser/devtools/devtools_tracing_handler.cc index 0657b8e48d..e9f6cf10b2 100644 --- a/content/browser/devtools/devtools_tracing_handler.cc +++ b/content/browser/devtools/devtools_tracing_handler.cc @@ -6,14 +6,18 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/file_util.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" #include "base/location.h" +#include "base/memory/ref_counted_memory.h" #include "base/strings/string_split.h" #include "base/strings/stringprintf.h" #include "base/values.h" #include "content/browser/devtools/devtools_http_handler_impl.h" #include "content/browser/devtools/devtools_protocol_constants.h" -#include "content/public/browser/trace_controller.h" -#include "content/public/browser/trace_subscriber.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/tracing_controller.h" namespace content { @@ -23,10 +27,23 @@ const char kRecordUntilFull[] = "record-until-full"; const char kRecordContinuously[] = "record-continuously"; const char kEnableSampling[] = "enable-sampling"; +void ReadFile( + const base::FilePath& path, + const base::Callback<void(const scoped_refptr<base::RefCountedString>&)> + callback) { + std::string trace_data; + if (!base::ReadFileToString(path, &trace_data)) + LOG(ERROR) << "Failed to read file: " << path.value(); + base::DeleteFile(path, false); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(callback, make_scoped_refptr( + base::RefCountedString::TakeString(&trace_data)))); +} + } // namespace DevToolsTracingHandler::DevToolsTracingHandler() - : is_running_(false) { + : weak_factory_(this) { RegisterCommandHandler(devtools::Tracing::start::kName, base::Bind(&DevToolsTracingHandler::OnStart, base::Unretained(this))); @@ -38,28 +55,60 @@ DevToolsTracingHandler::DevToolsTracingHandler() DevToolsTracingHandler::~DevToolsTracingHandler() { } -void DevToolsTracingHandler::OnEndTracingComplete() { - is_running_ = false; +void DevToolsTracingHandler::BeginReadingRecordingResult( + const base::FilePath& path) { + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + base::Bind(&ReadFile, path, + base::Bind(&DevToolsTracingHandler::ReadRecordingResult, + weak_factory_.GetWeakPtr()))); +} + +void DevToolsTracingHandler::ReadRecordingResult( + const scoped_refptr<base::RefCountedString>& trace_data) { + if (trace_data->data().size()) { + scoped_ptr<base::Value> trace_value(base::JSONReader::Read( + trace_data->data())); + DictionaryValue* dictionary = NULL; + bool ok = trace_value->GetAsDictionary(&dictionary); + DCHECK(ok); + ListValue* list = NULL; + ok = dictionary->GetList("traceEvents", &list); + DCHECK(ok); + std::string buffer; + for (size_t i = 0; i < list->GetSize(); ++i) { + std::string item; + base::Value* item_value; + list->Get(i, &item_value); + base::JSONWriter::Write(item_value, &item); + if (buffer.size()) + buffer.append(","); + buffer.append(item); + if (i % 1000 == 0) { + OnTraceDataCollected(buffer); + buffer.clear(); + } + } + if (buffer.size()) + OnTraceDataCollected(buffer); + } + SendNotification(devtools::Tracing::tracingComplete::kName, NULL); } void DevToolsTracingHandler::OnTraceDataCollected( - const scoped_refptr<base::RefCountedString>& trace_fragment) { - if (is_running_) { - // Hand-craft protocol notification message so we can substitute JSON - // that we already got as string as a bare object, not a quoted string. - std::string message = base::StringPrintf( - "{ \"method\": \"%s\", \"params\": { \"%s\": [ %s ] } }", - devtools::Tracing::dataCollected::kName, - devtools::Tracing::dataCollected::kValue, - trace_fragment->data().c_str()); - SendRawMessage(message); - } + const std::string& trace_fragment) { + // Hand-craft protocol notification message so we can substitute JSON + // that we already got as string as a bare object, not a quoted string. + std::string message = base::StringPrintf( + "{ \"method\": \"%s\", \"params\": { \"%s\": [ %s ] } }", + devtools::Tracing::dataCollected::kName, + devtools::Tracing::dataCollected::kParamValue, + trace_fragment.c_str()); + SendRawMessage(message); } -// Note, if you add more options here you also need to update: -// base/debug/trace_event_impl:TraceOptionsFromString -base::debug::TraceLog::Options DevToolsTracingHandler::TraceOptionsFromString( +TracingController::Options DevToolsTracingHandler::TraceOptionsFromString( const std::string& options) { std::vector<std::string> split; std::vector<std::string>::iterator iter; @@ -68,18 +117,14 @@ base::debug::TraceLog::Options DevToolsTracingHandler::TraceOptionsFromString( base::SplitString(options, ',', &split); for (iter = split.begin(); iter != split.end(); ++iter) { if (*iter == kRecordUntilFull) { - ret |= base::debug::TraceLog::RECORD_UNTIL_FULL; + ret &= ~TracingController::RECORD_CONTINUOUSLY; } else if (*iter == kRecordContinuously) { - ret |= base::debug::TraceLog::RECORD_CONTINUOUSLY; + ret |= TracingController::RECORD_CONTINUOUSLY; } else if (*iter == kEnableSampling) { - ret |= base::debug::TraceLog::ENABLE_SAMPLING; + ret |= TracingController::ENABLE_SAMPLING; } } - if (!(ret & base::debug::TraceLog::RECORD_UNTIL_FULL) && - !(ret & base::debug::TraceLog::RECORD_CONTINUOUSLY)) - ret |= base::debug::TraceLog::RECORD_UNTIL_FULL; - - return static_cast<base::debug::TraceLog::Options>(ret); + return static_cast<TracingController::Options>(ret); } scoped_refptr<DevToolsProtocol::Response> @@ -88,25 +133,28 @@ DevToolsTracingHandler::OnStart( std::string categories; base::DictionaryValue* params = command->params(); if (params) - params->GetString(devtools::Tracing::start::kCategories, &categories); + params->GetString(devtools::Tracing::start::kParamCategories, &categories); - base::debug::TraceLog::Options options = - base::debug::TraceLog::RECORD_UNTIL_FULL; - if (params && params->HasKey(devtools::Tracing::start::kTraceOptions)) { + TracingController::Options options = TracingController::DEFAULT_OPTIONS; + if (params && params->HasKey(devtools::Tracing::start::kParamOptions)) { std::string options_param; - params->GetString(devtools::Tracing::start::kTraceOptions, &options_param); + params->GetString(devtools::Tracing::start::kParamOptions, &options_param); options = TraceOptionsFromString(options_param); } - TraceController::GetInstance()->BeginTracing(this, categories, options); - is_running_ = true; + TracingController::GetInstance()->EnableRecording( + categories, options, + TracingController::EnableRecordingDoneCallback()); return command->SuccessResponse(NULL); } scoped_refptr<DevToolsProtocol::Response> DevToolsTracingHandler::OnEnd( scoped_refptr<DevToolsProtocol::Command> command) { - TraceController::GetInstance()->EndTracingAsync(this); + TracingController::GetInstance()->DisableRecording( + base::FilePath(), + base::Bind(&DevToolsTracingHandler::BeginReadingRecordingResult, + weak_factory_.GetWeakPtr())); return command->SuccessResponse(NULL); } diff --git a/content/browser/devtools/devtools_tracing_handler.h b/content/browser/devtools/devtools_tracing_handler.h index 43cd6150ed..b551e7579e 100644 --- a/content/browser/devtools/devtools_tracing_handler.h +++ b/content/browser/devtools/devtools_tracing_handler.h @@ -5,36 +5,36 @@ #ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_TRACING_HANDLER_H_ #define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_TRACING_HANDLER_H_ -#include "base/debug/trace_event.h" +#include "base/memory/weak_ptr.h" #include "content/browser/devtools/devtools_protocol.h" -#include "content/public/browser/trace_subscriber.h" +#include "content/public/browser/tracing_controller.h" + +namespace base { +class RefCountedString; +} namespace content { // This class bridges DevTools remote debugging server with the trace // infrastructure. -class DevToolsTracingHandler - : public TraceSubscriber, - public DevToolsProtocol::Handler { +class DevToolsTracingHandler : public DevToolsProtocol::Handler { public: DevToolsTracingHandler(); virtual ~DevToolsTracingHandler(); - // TraceSubscriber: - virtual void OnEndTracingComplete() OVERRIDE;; - virtual void OnTraceDataCollected( - const scoped_refptr<base::RefCountedString>& trace_fragment) OVERRIDE; - private: + void BeginReadingRecordingResult(const base::FilePath& path); + void ReadRecordingResult(const scoped_refptr<base::RefCountedString>& result); + void OnTraceDataCollected(const std::string& trace_fragment); + scoped_refptr<DevToolsProtocol::Response> OnStart( scoped_refptr<DevToolsProtocol::Command> command); scoped_refptr<DevToolsProtocol::Response> OnEnd( scoped_refptr<DevToolsProtocol::Command> command); - base::debug::TraceLog::Options TraceOptionsFromString( - const std::string& options); + TracingController::Options TraceOptionsFromString(const std::string& options); - bool is_running_; + base::WeakPtrFactory<DevToolsTracingHandler> weak_factory_; DISALLOW_COPY_AND_ASSIGN(DevToolsTracingHandler); }; diff --git a/content/browser/devtools/render_view_devtools_agent_host.cc b/content/browser/devtools/render_view_devtools_agent_host.cc index b2777783ea..8e0348b1c5 100644 --- a/content/browser/devtools/render_view_devtools_agent_host.cc +++ b/content/browser/devtools/render_view_devtools_agent_host.cc @@ -353,7 +353,17 @@ bool RenderViewDevToolsAgentHost::OnMessageReceived( void RenderViewDevToolsAgentHost::OnSwapCompositorFrame( const IPC::Message& message) { - overrides_handler_->OnSwapCompositorFrame(message); + ViewHostMsg_SwapCompositorFrame::Param param; + if (!ViewHostMsg_SwapCompositorFrame::Read(&message, ¶m)) + return; + overrides_handler_->OnSwapCompositorFrame(param.b.metadata); +} + +void RenderViewDevToolsAgentHost::SynchronousSwapCompositorFrame( + const cc::CompositorFrameMetadata& frame_metadata) { + if (!render_view_host_) + return; + overrides_handler_->OnSwapCompositorFrame(frame_metadata); } void RenderViewDevToolsAgentHost::OnSaveAgentRuntimeState( diff --git a/content/browser/devtools/render_view_devtools_agent_host.h b/content/browser/devtools/render_view_devtools_agent_host.h index 4313e2ae2c..e7034008c8 100644 --- a/content/browser/devtools/render_view_devtools_agent_host.h +++ b/content/browser/devtools/render_view_devtools_agent_host.h @@ -16,6 +16,10 @@ #include "content/public/browser/notification_registrar.h" #include "content/public/browser/web_contents_observer.h" +namespace cc { +class CompositorFrameMetadata; +} + namespace content { class DevToolsTracingHandler; @@ -38,6 +42,9 @@ class CONTENT_EXPORT RenderViewDevToolsAgentHost RenderViewHost* render_view_host() { return render_view_host_; } + void SynchronousSwapCompositorFrame( + const cc::CompositorFrameMetadata& frame_metadata); + private: friend class DevToolsAgentHost; diff --git a/content/browser/devtools/renderer_overrides_handler.cc b/content/browser/devtools/renderer_overrides_handler.cc index 2a99b3a3dc..4901f34cc1 100644 --- a/content/browser/devtools/renderer_overrides_handler.cc +++ b/content/browser/devtools/renderer_overrides_handler.cc @@ -63,7 +63,7 @@ static int kCaptureRetryLimit = 2; void ParseGenericInputParams(base::DictionaryValue* params, WebInputEvent* event) { int modifiers = 0; - if (params->GetInteger(devtools::Input::kParamModifiers, + if (params->GetInteger(devtools::Input::dispatchMouseEvent::kParamModifiers, &modifiers)) { if (modifiers & 1) event->modifiers |= WebInputEvent::AltKey; @@ -75,7 +75,7 @@ void ParseGenericInputParams(base::DictionaryValue* params, event->modifiers |= WebInputEvent::ShiftKey; } - params->GetDouble(devtools::Input::kParamTimestamp, + params->GetDouble(devtools::Input::dispatchMouseEvent::kParamTimestamp, &event->timeStampSeconds); } @@ -163,11 +163,8 @@ void RendererOverridesHandler::OnClientDetached() { } void RendererOverridesHandler::OnSwapCompositorFrame( - const IPC::Message& message) { - ViewHostMsg_SwapCompositorFrame::Param param; - if (!ViewHostMsg_SwapCompositorFrame::Read(&message, ¶m)) - return; - last_compositor_frame_metadata_ = param.b.metadata; + const cc::CompositorFrameMetadata& frame_metadata) { + last_compositor_frame_metadata_ = frame_metadata; if (screencast_command_) InnerSwapCompositorFrame(); @@ -293,8 +290,8 @@ RendererOverridesHandler::PageHandleJavaScriptDialog( bool accept; if (!params || !params->GetBoolean(paramAccept, &accept)) return command->InvalidParamResponse(paramAccept); - string16 prompt_override; - string16* prompt_override_ptr = &prompt_override; + base::string16 prompt_override; + base::string16* prompt_override_ptr = &prompt_override; if (!params || !params->GetString( devtools::Page::handleJavaScriptDialog::kParamPromptText, prompt_override_ptr)) { @@ -375,13 +372,13 @@ RendererOverridesHandler::PageGetNavigationHistory( const NavigationEntry* entry = controller.GetEntryAtIndex(i); base::DictionaryValue* entry_value = new base::DictionaryValue(); entry_value->SetInteger( - devtools::Page::getNavigationHistory::kResponseEntryId, + devtools::Page::NavigationEntry::kParamId, entry->GetUniqueID()); entry_value->SetString( - devtools::Page::getNavigationHistory::kResponseEntryURL, + devtools::Page::NavigationEntry::kParamUrl, entry->GetURL().spec()); entry_value->SetString( - devtools::Page::getNavigationHistory::kResponseEntryTitle, + devtools::Page::NavigationEntry::kParamTitle, entry->GetTitle()); entries->Append(entry_value); } @@ -446,16 +443,13 @@ RendererOverridesHandler::PageCaptureScreenshot( &png, gfx::Rect(snapshot_size))) { std::string base64_data; - bool success = base::Base64Encode( + base::Base64Encode( base::StringPiece(reinterpret_cast<char*>(&*png.begin()), png.size()), &base64_data); - if (success) { - base::DictionaryValue* result = new base::DictionaryValue(); - result->SetString( - devtools::Page::kData, base64_data); - return command->SuccessResponse(result); - } - return command->InternalErrorResponse("Unable to base64encode screenshot"); + base::DictionaryValue* result = new base::DictionaryValue(); + result->SetString( + devtools::Page::captureScreenshot::kResponseData, base64_data); + return command->SuccessResponse(result); } // Fallback to copying from compositing surface. @@ -475,10 +469,7 @@ RendererOverridesHandler::PageCanScreencast( scoped_refptr<DevToolsProtocol::Command> command) { base::DictionaryValue* result = new base::DictionaryValue(); #if defined(OS_ANDROID) - // Android WebView does not support Screencast. - std::string product = GetContentClient()->GetProduct(); - bool isChrome = product.find("Chrome/") == 0; - result->SetBoolean(devtools::kResult, isChrome); + result->SetBoolean(devtools::kResult, true); #else result->SetBoolean(devtools::kResult, false); #endif // defined(OS_ANDROID) @@ -559,50 +550,56 @@ void RendererOverridesHandler::ScreenshotCaptured( } std::string base_64_data; - if (!base::Base64Encode(base::StringPiece( - reinterpret_cast<char*>(&data[0]), - data.size()), - &base_64_data)) { - if (command) { - SendAsyncResponse( - command->InternalErrorResponse("Unable to base64 encode")); - } - return; - } + base::Base64Encode( + base::StringPiece(reinterpret_cast<char*>(&data[0]), data.size()), + &base_64_data); base::DictionaryValue* response = new base::DictionaryValue(); - response->SetString(devtools::Page::kData, base_64_data); + response->SetString(devtools::Page::screencastFrame::kParamData, + base_64_data); // Consider metadata empty in case it has no device scale factor. if (metadata.device_scale_factor != 0) { base::DictionaryValue* response_metadata = new base::DictionaryValue(); - response_metadata->SetDouble(devtools::Page::kParamDeviceScaleFactor, - metadata.device_scale_factor); - response_metadata->SetDouble(devtools::Page::kParamPageScaleFactor, - metadata.page_scale_factor); - response_metadata->SetDouble(devtools::Page::kParamPageScaleFactorMin, - metadata.min_page_scale_factor); - response_metadata->SetDouble(devtools::Page::kParamPageScaleFactorMax, - metadata.max_page_scale_factor); - response_metadata->SetDouble(devtools::Page::kParamOffsetTop, - metadata.location_bar_content_translation.y()); - response_metadata->SetDouble(devtools::Page::kParamOffsetBottom, - metadata.overdraw_bottom_height); + response_metadata->SetDouble( + devtools::Page::ScreencastFrameMetadata::kParamDeviceScaleFactor, + metadata.device_scale_factor); + response_metadata->SetDouble( + devtools::Page::ScreencastFrameMetadata::kParamPageScaleFactor, + metadata.page_scale_factor); + response_metadata->SetDouble( + devtools::Page::ScreencastFrameMetadata::kParamPageScaleFactorMin, + metadata.min_page_scale_factor); + response_metadata->SetDouble( + devtools::Page::ScreencastFrameMetadata::kParamPageScaleFactorMax, + metadata.max_page_scale_factor); + response_metadata->SetDouble( + devtools::Page::ScreencastFrameMetadata::kParamOffsetTop, + metadata.location_bar_content_translation.y()); + response_metadata->SetDouble( + devtools::Page::ScreencastFrameMetadata::kParamOffsetBottom, + metadata.overdraw_bottom_height); base::DictionaryValue* viewport = new base::DictionaryValue(); - viewport->SetDouble(devtools::kParamX, metadata.root_scroll_offset.x()); - viewport->SetDouble(devtools::kParamY, metadata.root_scroll_offset.y()); - viewport->SetDouble(devtools::kParamWidth, metadata.viewport_size.width()); - viewport->SetDouble(devtools::kParamHeight, + viewport->SetDouble(devtools::DOM::Rect::kParamX, + metadata.root_scroll_offset.x()); + viewport->SetDouble(devtools::DOM::Rect::kParamY, + metadata.root_scroll_offset.y()); + viewport->SetDouble(devtools::DOM::Rect::kParamWidth, + metadata.viewport_size.width()); + viewport->SetDouble(devtools::DOM::Rect::kParamHeight, metadata.viewport_size.height()); - response_metadata->Set(devtools::Page::kParamViewport, viewport); + response_metadata->Set( + devtools::Page::ScreencastFrameMetadata::kParamViewport, viewport); - // Temporarily duplicate properties to refactor API smoothly. - // TODO(dzvorygin): remove after refactor. - response->MergeDictionary(response_metadata); - - response->Set(devtools::Page::kMetadata, response_metadata); + if (command) { + response->Set(devtools::Page::captureScreenshot::kResponseMetadata, + response_metadata); + } else { + response->Set(devtools::Page::screencastFrame::kParamMetadata, + response_metadata); + } } if (command) { @@ -641,8 +638,8 @@ void DidGetHostUsage( const base::Closure& barrier, int64 value) { base::DictionaryValue* usage_item = new base::DictionaryValue; - usage_item->SetString(devtools::Page::UsageItem::kItemID, client_id); - usage_item->SetDouble(devtools::Page::UsageItem::kItemValue, value); + usage_item->SetString(devtools::Page::UsageItem::kParamId, client_id); + usage_item->SetDouble(devtools::Page::UsageItem::kParamValue, value); list->Append(usage_item); barrier.Run(); } @@ -673,11 +670,11 @@ void DidGetUsageAndQuotaForWebApps( std::string GetStorageTypeName(quota::StorageType type) { switch (type) { case quota::kStorageTypeTemporary: - return devtools::Page::Usage::kItemTemporary; + return devtools::Page::Usage::kParamTemporary; case quota::kStorageTypePersistent: - return devtools::Page::Usage::kItemPersistent; + return devtools::Page::Usage::kParamPersistent; case quota::kStorageTypeSyncable: - return devtools::Page::Usage::kItemSyncable; + return devtools::Page::Usage::kParamSyncable; case quota::kStorageTypeQuotaNotManaged: case quota::kStorageTypeUnknown: NOTREACHED(); @@ -688,13 +685,13 @@ std::string GetStorageTypeName(quota::StorageType type) { std::string GetQuotaClientName(quota::QuotaClient::ID id) { switch (id) { case quota::QuotaClient::kFileSystem: - return devtools::Page::UsageItem::ID::kFilesystem; + return devtools::Page::UsageItem::Id::kEnumFilesystem; case quota::QuotaClient::kDatabase: - return devtools::Page::UsageItem::ID::kDatabase; + return devtools::Page::UsageItem::Id::kEnumDatabase; case quota::QuotaClient::kAppcache: - return devtools::Page::UsageItem::ID::kAppcache; + return devtools::Page::UsageItem::Id::kEnumAppcache; case quota::QuotaClient::kIndexedDatabase: - return devtools::Page::UsageItem::ID::kIndexedDatabase; + return devtools::Page::UsageItem::Id::kEnumIndexeddatabase; default: NOTREACHED(); return ""; @@ -743,12 +740,12 @@ void QueryUsageAndQuotaOnIOThread( security_origin, quota::kStorageTypeTemporary, base::Bind(&DidGetUsageAndQuotaForWebApps, quota_raw_ptr, - std::string(devtools::Page::Quota::kItemTemporary), barrier)); + std::string(devtools::Page::Quota::kParamTemporary), barrier)); quota_manager->GetPersistentHostQuota( host, base::Bind(&DidGetQuotaValue, quota_raw_ptr, - std::string(devtools::Page::Quota::kItemPersistent), + std::string(devtools::Page::Quota::kParamPersistent), barrier)); for (size_t i = 0; i != arraysize(kQuotaClients); i++) { @@ -829,8 +826,9 @@ RendererOverridesHandler::InputDispatchMouseEvent( return NULL; bool device_space = false; - if (!params->GetBoolean(devtools::Input::kParamDeviceSpace, - &device_space) || + if (!params->GetBoolean( + devtools::Input::dispatchMouseEvent::kParamDeviceSpace, + &device_space) || !device_space) { return NULL; } @@ -840,13 +838,16 @@ RendererOverridesHandler::InputDispatchMouseEvent( ParseGenericInputParams(params, &mouse_event); std::string type; - if (params->GetString(devtools::Input::kParamType, + if (params->GetString(devtools::Input::dispatchMouseEvent::kParamType, &type)) { - if (type == "mousePressed") + if (type == + devtools::Input::dispatchMouseEvent::Type::kEnumMousePressed) mouse_event.type = WebInputEvent::MouseDown; - else if (type == "mouseReleased") + else if (type == + devtools::Input::dispatchMouseEvent::Type::kEnumMouseReleased) mouse_event.type = WebInputEvent::MouseUp; - else if (type == "mouseMoved") + else if (type == + devtools::Input::dispatchMouseEvent::Type::kEnumMouseMoved) mouse_event.type = WebInputEvent::MouseMove; else return NULL; @@ -854,8 +855,10 @@ RendererOverridesHandler::InputDispatchMouseEvent( return NULL; } - if (!params->GetInteger(devtools::kParamX, &mouse_event.x) || - !params->GetInteger(devtools::kParamY, &mouse_event.y)) { + if (!params->GetInteger(devtools::Input::dispatchMouseEvent::kParamX, + &mouse_event.x) || + !params->GetInteger(devtools::Input::dispatchMouseEvent::kParamY, + &mouse_event.y)) { return NULL; } @@ -905,23 +908,31 @@ RendererOverridesHandler::InputDispatchGestureEvent( ParseGenericInputParams(params, &event); std::string type; - if (params->GetString(devtools::Input::kParamType, + if (params->GetString(devtools::Input::dispatchGestureEvent::kParamType, &type)) { - if (type == "scrollBegin") + if (type == + devtools::Input::dispatchGestureEvent::Type::kEnumScrollBegin) event.type = WebInputEvent::GestureScrollBegin; - else if (type == "scrollUpdate") + else if (type == + devtools::Input::dispatchGestureEvent::Type::kEnumScrollUpdate) event.type = WebInputEvent::GestureScrollUpdate; - else if (type == "scrollEnd") + else if (type == + devtools::Input::dispatchGestureEvent::Type::kEnumScrollEnd) event.type = WebInputEvent::GestureScrollEnd; - else if (type == "tapDown") + else if (type == + devtools::Input::dispatchGestureEvent::Type::kEnumTapDown) event.type = WebInputEvent::GestureTapDown; - else if (type == "tap") + else if (type == + devtools::Input::dispatchGestureEvent::Type::kEnumTap) event.type = WebInputEvent::GestureTap; - else if (type == "pinchBegin") + else if (type == + devtools::Input::dispatchGestureEvent::Type::kEnumPinchBegin) event.type = WebInputEvent::GesturePinchBegin; - else if (type == "pinchUpdate") + else if (type == + devtools::Input::dispatchGestureEvent::Type::kEnumPinchUpdate) event.type = WebInputEvent::GesturePinchUpdate; - else if (type == "pinchEnd") + else if (type == + devtools::Input::dispatchGestureEvent::Type::kEnumPinchEnd) event.type = WebInputEvent::GesturePinchEnd; else return NULL; @@ -929,8 +940,10 @@ RendererOverridesHandler::InputDispatchGestureEvent( return NULL; } - if (!params->GetInteger(devtools::kParamX, &event.x) || - !params->GetInteger(devtools::kParamY, &event.y)) { + if (!params->GetInteger(devtools::Input::dispatchGestureEvent::kParamX, + &event.x) || + !params->GetInteger(devtools::Input::dispatchGestureEvent::kParamY, + &event.y)) { return NULL; } event.globalX = event.x; diff --git a/content/browser/devtools/renderer_overrides_handler.h b/content/browser/devtools/renderer_overrides_handler.h index 2556c9ae54..cce32767c3 100644 --- a/content/browser/devtools/renderer_overrides_handler.h +++ b/content/browser/devtools/renderer_overrides_handler.h @@ -35,7 +35,7 @@ class CONTENT_EXPORT RendererOverridesHandler virtual ~RendererOverridesHandler(); void OnClientDetached(); - void OnSwapCompositorFrame(const IPC::Message& message); + void OnSwapCompositorFrame(const cc::CompositorFrameMetadata& frame_metadata); void OnVisibilityChanged(bool visible); private: diff --git a/content/browser/devtools/worker_devtools_manager.cc b/content/browser/devtools/worker_devtools_manager.cc index f08523b998..f0608815f3 100644 --- a/content/browser/devtools/worker_devtools_manager.cc +++ b/content/browser/devtools/worker_devtools_manager.cc @@ -52,13 +52,15 @@ base::LazyInstance<AgentHosts>::Leaky g_orphan_map = LAZY_INSTANCE_INITIALIZER; } // namespace struct WorkerDevToolsManager::TerminatedInspectedWorker { - TerminatedInspectedWorker(WorkerId id, const GURL& url, const string16& name) + TerminatedInspectedWorker(WorkerId id, + const GURL& url, + const base::string16& name) : old_worker_id(id), worker_url(url), worker_name(name) {} WorkerId old_worker_id; GURL worker_url; - string16 worker_name; + base::string16 worker_name; }; @@ -202,7 +204,7 @@ class WorkerDevToolsManager::DetachedClientHosts { struct WorkerDevToolsManager::InspectedWorker { InspectedWorker(WorkerProcessHost* host, int route_id, const GURL& url, - const string16& name) + const base::string16& name) : host(host), route_id(route_id), worker_url(url), @@ -210,7 +212,7 @@ struct WorkerDevToolsManager::InspectedWorker { WorkerProcessHost* const host; int const route_id; GURL worker_url; - string16 worker_name; + base::string16 worker_name; }; // static diff --git a/content/browser/dom_storage/dom_storage_context_impl.cc b/content/browser/dom_storage/dom_storage_context_impl.cc index 44c4242c53..2c31bd627b 100644 --- a/content/browser/dom_storage/dom_storage_context_impl.cc +++ b/content/browser/dom_storage/dom_storage_context_impl.cc @@ -68,7 +68,7 @@ DOMStorageNamespace* DOMStorageContextImpl::GetStorageNamespace( if (found == namespaces_.end()) { if (namespace_id == kLocalStorageNamespaceId) { if (!localstorage_directory_.empty()) { - if (!file_util::CreateDirectory(localstorage_directory_)) { + if (!base::CreateDirectory(localstorage_directory_)) { LOG(ERROR) << "Failed to create 'Local Storage' directory," " falling back to in-memory only."; localstorage_directory_ = base::FilePath(); diff --git a/content/browser/dom_storage/dom_storage_message_filter.cc b/content/browser/dom_storage/dom_storage_message_filter.cc index 3ab972cd72..fbc3880abb 100644 --- a/content/browser/dom_storage/dom_storage_message_filter.cc +++ b/content/browser/dom_storage/dom_storage_message_filter.cc @@ -116,8 +116,8 @@ void DOMStorageMessageFilter::OnLoadStorageArea(int connection_id, } void DOMStorageMessageFilter::OnSetItem( - int connection_id, const string16& key, - const string16& value, const GURL& page_url) { + int connection_id, const base::string16& key, + const base::string16& value, const GURL& page_url) { DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); DCHECK_EQ(0, connection_dispatching_message_for_); base::AutoReset<int> auto_reset(&connection_dispatching_message_for_, @@ -129,20 +129,20 @@ void DOMStorageMessageFilter::OnSetItem( } void DOMStorageMessageFilter::OnLogGetItem( - int connection_id, const string16& key, + int connection_id, const base::string16& key, const base::NullableString16& value) { DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); host_->LogGetAreaItem(connection_id, key, value); } void DOMStorageMessageFilter::OnRemoveItem( - int connection_id, const string16& key, + int connection_id, const base::string16& key, const GURL& page_url) { DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO)); DCHECK_EQ(0, connection_dispatching_message_for_); base::AutoReset<int> auto_reset(&connection_dispatching_message_for_, connection_id); - string16 not_used; + base::string16 not_used; host_->RemoveAreaItem(connection_id, key, page_url, ¬_used); Send(new DOMStorageMsg_AsyncOperationComplete(true)); } @@ -163,8 +163,8 @@ void DOMStorageMessageFilter::OnFlushMessages() { void DOMStorageMessageFilter::OnDOMStorageItemSet( const DOMStorageArea* area, - const string16& key, - const string16& new_value, + const base::string16& key, + const base::string16& new_value, const base::NullableString16& old_value, const GURL& page_url) { SendDOMStorageEvent(area, page_url, @@ -175,8 +175,8 @@ void DOMStorageMessageFilter::OnDOMStorageItemSet( void DOMStorageMessageFilter::OnDOMStorageItemRemoved( const DOMStorageArea* area, - const string16& key, - const string16& old_value, + const base::string16& key, + const base::string16& old_value, const GURL& page_url) { SendDOMStorageEvent(area, page_url, base::NullableString16(key, false), diff --git a/content/browser/dom_storage/dom_storage_message_filter.h b/content/browser/dom_storage/dom_storage_message_filter.h index a2670ef37a..3c82418842 100644 --- a/content/browser/dom_storage/dom_storage_message_filter.h +++ b/content/browser/dom_storage/dom_storage_message_filter.h @@ -53,11 +53,11 @@ class DOMStorageMessageFilter void OnCloseStorageArea(int connection_id); void OnLoadStorageArea(int connection_id, DOMStorageValuesMap* map, bool* send_log_get_messages); - void OnSetItem(int connection_id, const string16& key, - const string16& value, const GURL& page_url); - void OnLogGetItem(int connection_id, const string16& key, + void OnSetItem(int connection_id, const base::string16& key, + const base::string16& value, const GURL& page_url); + void OnLogGetItem(int connection_id, const base::string16& key, const base::NullableString16& value); - void OnRemoveItem(int connection_id, const string16& key, + void OnRemoveItem(int connection_id, const base::string16& key, const GURL& page_url); void OnClear(int connection_id, const GURL& page_url); void OnFlushMessages(); @@ -66,14 +66,14 @@ class DOMStorageMessageFilter // sends events back to our renderer process. virtual void OnDOMStorageItemSet( const DOMStorageArea* area, - const string16& key, - const string16& new_value, + const base::string16& key, + const base::string16& new_value, const base::NullableString16& old_value, const GURL& page_url) OVERRIDE; virtual void OnDOMStorageItemRemoved( const DOMStorageArea* area, - const string16& key, - const string16& old_value, + const base::string16& key, + const base::string16& old_value, const GURL& page_url) OVERRIDE; virtual void OnDOMStorageAreaCleared( const DOMStorageArea* area, diff --git a/content/browser/dom_storage/session_storage_database.cc b/content/browser/dom_storage/session_storage_database.cc index bac3df7a67..7b8dcd0bf0 100644 --- a/content/browser/dom_storage/session_storage_database.cc +++ b/content/browser/dom_storage/session_storage_database.cc @@ -280,8 +280,7 @@ bool SessionStorageDatabase::LazyOpen(bool create_if_needed) { return true; if (!create_if_needed && - (!base::PathExists(file_path_) || - file_util::IsDirectoryEmpty(file_path_))) { + (!base::PathExists(file_path_) || base::IsDirectoryEmpty(file_path_))) { // If the directory doesn't exist already and we haven't been asked to // create a file on disk, then we don't bother opening the database. This // means we wait until we absolutely need to put something onto disk before diff --git a/content/browser/download/base_file.cc b/content/browser/download/base_file.cc index 90ab485c36..1de3e842dd 100644 --- a/content/browser/download/base_file.cc +++ b/content/browser/download/base_file.cc @@ -82,8 +82,8 @@ DownloadInterruptReason BaseFile::Initialize( // |initial_directory| can still be empty if ContentBrowserClient returned // an empty path for the downloads directory. if ((initial_directory.empty() || - !file_util::CreateTemporaryFileInDir(initial_directory, &temp_file)) && - !file_util::CreateTemporaryFile(&temp_file)) { + !base::CreateTemporaryFileInDir(initial_directory, &temp_file)) && + !base::CreateTemporaryFile(&temp_file)) { return LogInterruptReason("Unable to create", 0, DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); } @@ -165,7 +165,7 @@ DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) { net::NetLog::TYPE_DOWNLOAD_FILE_RENAMED, base::Bind(&FileRenamedNetLogCallback, &full_path_, &new_path)); Close(); - file_util::CreateDirectory(new_path.DirName()); + base::CreateDirectory(new_path.DirName()); // A simple rename wouldn't work here since we want the file to have // permissions / security descriptors that makes sense in the new directory. diff --git a/content/browser/download/base_file_unittest.cc b/content/browser/download/base_file_unittest.cc index b82b0a8ab7..4ab0c2ae8f 100644 --- a/content/browser/download/base_file_unittest.cc +++ b/content/browser/download/base_file_unittest.cc @@ -464,7 +464,7 @@ TEST_F(BaseFileTest, RenameWithError) { // TestDir is a subdirectory in |temp_dir_| that we will make read-only so // that the rename will fail. base::FilePath test_dir(temp_dir_.path().AppendASCII("TestDir")); - ASSERT_TRUE(file_util::CreateDirectory(test_dir)); + ASSERT_TRUE(base::CreateDirectory(test_dir)); base::FilePath new_path(test_dir.AppendASCII("TestFile")); EXPECT_FALSE(base::PathExists(new_path)); @@ -482,7 +482,7 @@ TEST_F(BaseFileTest, RenameWithError) { // Write data to the file multiple times. TEST_F(BaseFileTest, MultipleWritesWithError) { base::FilePath path; - ASSERT_TRUE(file_util::CreateTemporaryFile(&path)); + ASSERT_TRUE(base::CreateTemporaryFile(&path)); // Create a new file stream. scoped_ptr takes ownership and passes it to // BaseFile; we use the pointer anyway and rely on the BaseFile not // deleting the MockFileStream until the BaseFile is reset. @@ -623,8 +623,7 @@ TEST_F(BaseFileTest, CreatedInDefaultDirectory) { // be a string-wise match to base_file_->full_path().DirName() even though // they are in the same directory. base::FilePath temp_file; - ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(), - &temp_file)); + ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file)); ASSERT_FALSE(temp_file.empty()); EXPECT_STREQ(temp_file.DirName().value().c_str(), base_file_->full_path().DirName().value().c_str()); diff --git a/content/browser/download/download_file_unittest.cc b/content/browser/download/download_file_unittest.cc index dcc0e424bd..141808685f 100644 --- a/content/browser/download/download_file_unittest.cc +++ b/content/browser/download/download_file_unittest.cc @@ -195,7 +195,7 @@ class DownloadFileTest : public testing::Test { void VerifyStreamAndSize() { ::testing::Mock::VerifyAndClearExpectations(input_stream_); int64 size; - EXPECT_TRUE(file_util::GetFileSize(download_file_->FullPath(), &size)); + EXPECT_TRUE(base::GetFileSize(download_file_->FullPath(), &size)); EXPECT_EQ(expected_data_.size(), static_cast<size_t>(size)); } @@ -461,7 +461,7 @@ TEST_F(DownloadFileTest, RenameError) { // Create a subdirectory. base::FilePath tempdir( initial_path.DirName().Append(FILE_PATH_LITERAL("tempdir"))); - ASSERT_TRUE(file_util::CreateDirectory(tempdir)); + ASSERT_TRUE(base::CreateDirectory(tempdir)); base::FilePath target_path(tempdir.Append(initial_path.BaseName())); // Targets diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc index ea0f305a5a..35825d32a9 100644 --- a/content/browser/download/download_manager_impl.cc +++ b/content/browser/download/download_manager_impl.cc @@ -413,7 +413,7 @@ void DownloadManagerImpl::StartDownloadWithId( file_factory_->CreateFile( info->save_info.Pass(), default_download_directory, info->url(), info->referrer_url, - delegate_->GenerateFileHash(), + delegate_ && delegate_->GenerateFileHash(), stream.Pass(), download->GetBoundNetLog(), download->DestinationObserverAsWeakPtr())); diff --git a/content/browser/download/download_manager_impl_unittest.cc b/content/browser/download/download_manager_impl_unittest.cc index aecded1262..3afc41ad5a 100644 --- a/content/browser/download/download_manager_impl_unittest.cc +++ b/content/browser/download/download_manager_impl_unittest.cc @@ -120,7 +120,7 @@ class MockDownloadItemImpl : public DownloadItemImpl { MOCK_CONST_METHOD0(CurrentSpeed, int64()); MOCK_CONST_METHOD0(PercentComplete, int()); MOCK_CONST_METHOD0(AllDataSaved, bool()); - MOCK_CONST_METHOD1(MatchesQuery, bool(const string16& query)); + MOCK_CONST_METHOD1(MatchesQuery, bool(const base::string16& query)); MOCK_CONST_METHOD0(IsDone, bool()); MOCK_CONST_METHOD0(GetFullPath, const base::FilePath&()); MOCK_CONST_METHOD0(GetTargetFilePath, const base::FilePath&()); diff --git a/content/browser/download/drag_download_file.h b/content/browser/download/drag_download_file.h index 41fdf6224e..c281d977d8 100644 --- a/content/browser/download/drag_download_file.h +++ b/content/browser/download/drag_download_file.h @@ -17,7 +17,6 @@ #include "content/public/common/referrer.h" #include "net/base/file_stream.h" #include "ui/base/dragdrop/download_file_interface.h" -#include "ui/base/ui_export.h" #include "url/gurl.h" namespace net { diff --git a/content/browser/download/drag_download_util.cc b/content/browser/download/drag_download_util.cc index 41bff06dd2..0850c3ba08 100644 --- a/content/browser/download/drag_download_util.cc +++ b/content/browser/download/drag_download_util.cc @@ -23,18 +23,18 @@ using net::FileStream; namespace content { -bool ParseDownloadMetadata(const string16& metadata, - string16* mime_type, +bool ParseDownloadMetadata(const base::string16& metadata, + base::string16* mime_type, base::FilePath* file_name, GURL* url) { const char16 separator = L':'; size_t mime_type_end_pos = metadata.find(separator); - if (mime_type_end_pos == string16::npos) + if (mime_type_end_pos == base::string16::npos) return false; size_t file_name_end_pos = metadata.find(separator, mime_type_end_pos + 1); - if (file_name_end_pos == string16::npos) + if (file_name_end_pos == base::string16::npos) return false; GURL parsed_url = GURL(metadata.substr(file_name_end_pos + 1)); @@ -44,7 +44,7 @@ bool ParseDownloadMetadata(const string16& metadata, if (mime_type) *mime_type = metadata.substr(0, mime_type_end_pos); if (file_name) { - string16 file_name_str = metadata.substr( + base::string16 file_name_str = metadata.substr( mime_type_end_pos + 1, file_name_end_pos - mime_type_end_pos - 1); #if defined(OS_WIN) *file_name = base::FilePath(file_name_str); @@ -70,7 +70,7 @@ FileStream* CreateFileStreamForDrop(base::FilePath* file_path, new_file_path = *file_path; } else { #if defined(OS_WIN) - string16 suffix = ASCIIToUTF16("-") + base::IntToString16(seq); + base::string16 suffix = ASCIIToUTF16("-") + base::IntToString16(seq); #else std::string suffix = std::string("-") + base::IntToString(seq); #endif diff --git a/content/browser/download/drag_download_util.h b/content/browser/download/drag_download_util.h index 8b58f4840e..ca266efa62 100644 --- a/content/browser/download/drag_download_util.h +++ b/content/browser/download/drag_download_util.h @@ -32,8 +32,8 @@ namespace content { // appropriately. // For example, we can have // text/plain:example.txt:http://example.com/example.txt -bool ParseDownloadMetadata(const string16& metadata, - string16* mime_type, +bool ParseDownloadMetadata(const base::string16& metadata, + base::string16* mime_type, base::FilePath* file_name, GURL* url); diff --git a/content/browser/download/file_metadata_unittest_linux.cc b/content/browser/download/file_metadata_unittest_linux.cc index 4f223519c4..96db264647 100644 --- a/content/browser/download/file_metadata_unittest_linux.cc +++ b/content/browser/download/file_metadata_unittest_linux.cc @@ -52,8 +52,7 @@ class FileMetadataLinuxTest : public testing::Test { protected: virtual void SetUp() OVERRIDE { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(), - &test_file_)); + ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &test_file_)); int result = setxattr(test_file_.value().c_str(), "user.test", "test", 4, 0); is_xattr_supported_ = (!result) || (errno != ENOTSUP); diff --git a/content/browser/download/mhtml_generation_browsertest.cc b/content/browser/download/mhtml_generation_browsertest.cc index 6e790135bc..11a08519e2 100644 --- a/content/browser/download/mhtml_generation_browsertest.cc +++ b/content/browser/download/mhtml_generation_browsertest.cc @@ -66,7 +66,7 @@ IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTML) { // Make sure the actual generated file has some contents. int64 file_size; - ASSERT_TRUE(file_util::GetFileSize(path, &file_size)); + ASSERT_TRUE(base::GetFileSize(path, &file_size)); EXPECT_GT(file_size, 100); } diff --git a/content/browser/download/save_file_manager.cc b/content/browser/download/save_file_manager.cc index 442c28e102..85651b7709 100644 --- a/content/browser/download/save_file_manager.cc +++ b/content/browser/download/save_file_manager.cc @@ -482,7 +482,7 @@ void SaveFileManager::RenameAllFiles( DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); if (!resource_dir.empty() && !base::PathExists(resource_dir)) - file_util::CreateDirectory(resource_dir); + base::CreateDirectory(resource_dir); for (FinalNameList::const_iterator i = final_names.begin(); i != final_names.end(); ++i) { diff --git a/content/browser/download/save_package.cc b/content/browser/download/save_package.cc index 2fc68dff55..5961e6bf58 100644 --- a/content/browser/download/save_package.cc +++ b/content/browser/download/save_package.cc @@ -519,7 +519,7 @@ bool SavePackage::GenerateFileName(const std::string& disposition, if (ordinal_number > (kMaxFileOrdinalNumber - 1)) { // Use a random file from temporary file. base::FilePath temp_file; - file_util::CreateTemporaryFile(&temp_file); + base::CreateTemporaryFile(&temp_file); file_name = temp_file.RemoveExtension().BaseName().value(); // Get safe pure file name. if (!GetSafePureFileName(saved_main_directory_path_, @@ -1347,7 +1347,7 @@ void SavePackage::CreateDirectoryOnFileThread( if (!skip_dir_check && !base::DirectoryExists(website_save_dir)) { // If the default download dir doesn't exist, create it. if (!base::DirectoryExists(download_save_dir)) { - bool res = file_util::CreateDirectory(download_save_dir); + bool res = base::CreateDirectory(download_save_dir); DCHECK(res); } save_dir = download_save_dir; diff --git a/content/browser/download/save_package.h b/content/browser/download/save_package.h index 939002e1ee..1ab429e16b 100644 --- a/content/browser/download/save_package.h +++ b/content/browser/download/save_package.h @@ -279,7 +279,7 @@ class CONTENT_EXPORT SavePackage base::FilePath saved_main_directory_path_; // The title of the page the user wants to save. - string16 title_; + base::string16 title_; // Used to calculate package download speed (in files per second). base::TimeTicks start_tick_; diff --git a/content/browser/download/save_package_unittest.cc b/content/browser/download/save_package_unittest.cc index c0aa3f8862..47fd1b4668 100644 --- a/content/browser/download/save_package_unittest.cc +++ b/content/browser/download/save_package_unittest.cc @@ -10,8 +10,8 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "content/browser/download/save_package.h" -#include "content/browser/renderer_host/test_render_view_host.h" #include "content/test/net/url_request_mock_http_job.h" +#include "content/test/test_render_view_host.h" #include "content/test/test_web_contents.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -346,7 +346,7 @@ TEST_F(SavePackageTest, MAYBE_TestEnsureMimeExtension) { static const struct SuggestedSaveNameTestCase { const char* page_url; - const string16 page_title; + const base::string16 page_title; const base::FilePath::CharType* expected_name; bool ensure_html_extension; } kSuggestedSaveNames[] = { diff --git a/content/browser/fileapi/blob_url_request_job_unittest.cc b/content/browser/fileapi/blob_url_request_job_unittest.cc index 607bb10566..a09456b607 100644 --- a/content/browser/fileapi/blob_url_request_job_unittest.cc +++ b/content/browser/fileapi/blob_url_request_job_unittest.cc @@ -146,7 +146,7 @@ class BlobURLRequestJobTest : public testing::Test { file_util::WriteFile(temp_file1_, kTestFileData1, arraysize(kTestFileData1) - 1)); base::PlatformFileInfo file_info1; - file_util::GetFileInfo(temp_file1_, &file_info1); + base::GetFileInfo(temp_file1_, &file_info1); temp_file_modification_time1_ = file_info1.last_modified; temp_file2_ = temp_dir_.path().AppendASCII("BlobFile2.dat"); @@ -154,7 +154,7 @@ class BlobURLRequestJobTest : public testing::Test { file_util::WriteFile(temp_file2_, kTestFileData2, arraysize(kTestFileData2) - 1)); base::PlatformFileInfo file_info2; - file_util::GetFileInfo(temp_file2_, &file_info2); + base::GetFileInfo(temp_file2_, &file_info2); temp_file_modification_time2_ = file_info2.last_modified; url_request_job_factory_.SetProtocolHandler("blob", diff --git a/content/browser/fileapi/dragged_file_util_unittest.cc b/content/browser/fileapi/dragged_file_util_unittest.cc index 3c34bec3e9..17b29cc6be 100644 --- a/content/browser/fileapi/dragged_file_util_unittest.cc +++ b/content/browser/fileapi/dragged_file_util_unittest.cc @@ -326,8 +326,7 @@ TEST_F(DraggedFileUtilTest, UnregisteredPathsTest) { // Make sure regular GetFileInfo succeeds. base::PlatformFileInfo info; - ASSERT_TRUE(file_util::GetFileInfo( - root_path().Append(test_case.path), &info)); + ASSERT_TRUE(base::GetFileInfo(root_path().Append(test_case.path), &info)); if (!test_case.is_directory) ASSERT_EQ(test_case.data_file_size, info.size); ASSERT_EQ(test_case.is_directory, info.is_directory); diff --git a/content/browser/fileapi/file_system_context_unittest.cc b/content/browser/fileapi/file_system_context_unittest.cc index 63365dcef7..43003ad0dc 100644 --- a/content/browser/fileapi/file_system_context_unittest.cc +++ b/content/browser/fileapi/file_system_context_unittest.cc @@ -111,6 +111,7 @@ TEST_F(FileSystemContextTest, NullExternalMountPoints) { ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( "system", kFileSystemTypeNativeLocal, + FileSystemMountOption(), base::FilePath(DRIVE FPL("/test/sys/")))); FileSystemURL cracked_isolated = file_system_context->CrackURL( @@ -154,6 +155,7 @@ TEST_F(FileSystemContextTest, FileSystemContextKeepsMountPointsAlive) { ASSERT_TRUE(mount_points->RegisterFileSystem( "system", kFileSystemTypeNativeLocal, + FileSystemMountOption(), base::FilePath(DRIVE FPL("/test/sys/")))); scoped_refptr<FileSystemContext> file_system_context( @@ -198,22 +200,26 @@ TEST_F(FileSystemContextTest, CrackFileSystemURL) { ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( "system", kFileSystemTypeDrive, + FileSystemMountOption(), base::FilePath(DRIVE FPL("/test/sys/")))); ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( "ext", kFileSystemTypeNativeLocal, + FileSystemMountOption(), base::FilePath(DRIVE FPL("/test/ext")))); // Register a system external mount point with the same name/id as the // registered isolated mount point. ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( kIsolatedFileSystemID, kFileSystemTypeRestrictedNativeLocal, + FileSystemMountOption(), base::FilePath(DRIVE FPL("/test/system/isolated")))); // Add a mount points with the same name as a system mount point to // FileSystemContext's external mount points. ASSERT_TRUE(external_mount_points->RegisterFileSystem( "ext", kFileSystemTypeNativeLocal, + FileSystemMountOption(), base::FilePath(DRIVE FPL("/test/local/ext/")))); const GURL kTestOrigin = GURL("http://chromium.org/"); @@ -351,7 +357,8 @@ TEST_F(FileSystemContextTest, CanServeURLRequest) { // A request for an external mount point should be served. const std::string kExternalMountName = "ext_mount"; ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( - kExternalMountName, kFileSystemTypeDrive, base::FilePath())); + kExternalMountName, kFileSystemTypeDrive, FileSystemMountOption(), + base::FilePath())); cracked_url = context->CrackURL( CreateRawFileSystemURL("external", kExternalMountName)); EXPECT_EQ(kFileSystemTypeExternal, cracked_url.mount_type()); diff --git a/content/browser/fileapi/file_system_operation_impl_unittest.cc b/content/browser/fileapi/file_system_operation_impl_unittest.cc index 23dfedeed7..445657d9a0 100644 --- a/content/browser/fileapi/file_system_operation_impl_unittest.cc +++ b/content/browser/fileapi/file_system_operation_impl_unittest.cc @@ -159,7 +159,7 @@ class FileSystemOperationImplTest int64 GetFileSize(const std::string& path) { base::PlatformFileInfo info; - EXPECT_TRUE(file_util::GetFileInfo(PlatformPath(path), &info)); + EXPECT_TRUE(base::GetFileInfo(PlatformPath(path), &info)); return info.size; } @@ -664,7 +664,7 @@ TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirRecursive) { TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileSuccess) { base::FilePath src_local_disk_file_path; - file_util::CreateTemporaryFile(&src_local_disk_file_path); + base::CreateTemporaryFile(&src_local_disk_file_path); const char test_data[] = "foo"; int data_size = ARRAYSIZE_UNSAFE(test_data); file_util::WriteFile(src_local_disk_file_path, test_data, data_size); @@ -689,15 +689,15 @@ TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileSuccess) { // Compare contents of src and copied file. char buffer[100]; - EXPECT_EQ(data_size, file_util::ReadFile(PlatformPath("dest/file"), - buffer, data_size)); + EXPECT_EQ(data_size, base::ReadFile(PlatformPath("dest/file"), + buffer, data_size)); for (int i = 0; i < data_size; ++i) EXPECT_EQ(test_data[i], buffer[i]); } TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileFailureByQuota) { base::FilePath src_local_disk_file_path; - file_util::CreateTemporaryFile(&src_local_disk_file_path); + base::CreateTemporaryFile(&src_local_disk_file_path); const char test_data[] = "foo"; file_util::WriteFile(src_local_disk_file_path, test_data, ARRAYSIZE_UNSAFE(test_data)); @@ -1009,7 +1009,7 @@ TEST_F(FileSystemOperationImplTest, TestTruncate) { // data. EXPECT_EQ(length, GetFileSize("file")); char data[100]; - EXPECT_EQ(length, file_util::ReadFile(platform_path, data, length)); + EXPECT_EQ(length, base::ReadFile(platform_path, data, length)); for (int i = 0; i < length; ++i) { if (i < static_cast<int>(sizeof(test_data))) EXPECT_EQ(test_data[i], data[i]); @@ -1028,7 +1028,7 @@ TEST_F(FileSystemOperationImplTest, TestTruncate) { // Check that its length is now 3 and that it contains only bits of test data. EXPECT_EQ(length, GetFileSize("file")); - EXPECT_EQ(length, file_util::ReadFile(platform_path, data, length)); + EXPECT_EQ(length, base::ReadFile(platform_path, data, length)); for (int i = 0; i < length; ++i) EXPECT_EQ(test_data[i], data[i]); @@ -1065,7 +1065,7 @@ TEST_F(FileSystemOperationImplTest, TestTouchFile) { base::FilePath platform_path = PlatformPath("file"); base::PlatformFileInfo info; - EXPECT_TRUE(file_util::GetFileInfo(platform_path, &info)); + EXPECT_TRUE(base::GetFileInfo(platform_path, &info)); EXPECT_FALSE(info.is_directory); EXPECT_EQ(0, info.size); const base::Time last_modified = info.last_modified; @@ -1083,7 +1083,7 @@ TEST_F(FileSystemOperationImplTest, TestTouchFile) { EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(change_observer()->HasNoChange()); - EXPECT_TRUE(file_util::GetFileInfo(platform_path, &info)); + EXPECT_TRUE(base::GetFileInfo(platform_path, &info)); // We compare as time_t here to lower our resolution, to avoid false // negatives caused by conversion to the local filesystem's native // representation and back. diff --git a/content/browser/fileapi/fileapi_message_filter.cc b/content/browser/fileapi/fileapi_message_filter.cc index 20607d38cd..b6b89fb50a 100644 --- a/content/browser/fileapi/fileapi_message_filter.cc +++ b/content/browser/fileapi/fileapi_message_filter.cc @@ -814,11 +814,22 @@ void FileAPIMessageFilter::DidCreateSnapshot( bool FileAPIMessageFilter::ValidateFileSystemURL( int request_id, const fileapi::FileSystemURL& url) { - if (FileSystemURLIsValid(context_, url)) - return true; - Send(new FileSystemMsg_DidFail(request_id, - base::PLATFORM_FILE_ERROR_INVALID_URL)); - return false; + if (!FileSystemURLIsValid(context_, url)) { + Send(new FileSystemMsg_DidFail(request_id, + base::PLATFORM_FILE_ERROR_INVALID_URL)); + return false; + } + + // Deny access to files in PluginPrivate FileSystem from JavaScript. + // TODO(nhiroki): Move this filter somewhere else since this is not for + // validation. + if (url.type() == fileapi::kFileSystemTypePluginPrivate) { + Send(new FileSystemMsg_DidFail(request_id, + base::PLATFORM_FILE_ERROR_SECURITY)); + return false; + } + + return true; } scoped_refptr<Stream> FileAPIMessageFilter::GetStreamForURL(const GURL& url) { diff --git a/content/browser/fileapi/local_file_util_unittest.cc b/content/browser/fileapi/local_file_util_unittest.cc index fd28035aaf..40995d6931 100644 --- a/content/browser/fileapi/local_file_util_unittest.cc +++ b/content/browser/fileapi/local_file_util_unittest.cc @@ -85,7 +85,7 @@ class LocalFileUtilTest : public testing::Test { int64 GetSize(const char *file_name) { base::PlatformFileInfo info; - file_util::GetFileInfo(LocalPath(file_name), &info); + base::GetFileInfo(LocalPath(file_name), &info); return info.size; } @@ -192,7 +192,7 @@ TEST_F(LocalFileUtilTest, TouchFile) { scoped_ptr<FileSystemOperationContext> context(NewContext()); base::PlatformFileInfo info; - ASSERT_TRUE(file_util::GetFileInfo(LocalPath(file_name), &info)); + ASSERT_TRUE(base::GetFileInfo(LocalPath(file_name), &info)); const base::Time new_accessed = info.last_accessed + base::TimeDelta::FromHours(10); const base::Time new_modified = @@ -202,7 +202,7 @@ TEST_F(LocalFileUtilTest, TouchFile) { file_util()->Touch(context.get(), CreateURL(file_name), new_accessed, new_modified)); - ASSERT_TRUE(file_util::GetFileInfo(LocalPath(file_name), &info)); + ASSERT_TRUE(base::GetFileInfo(LocalPath(file_name), &info)); EXPECT_EQ(new_accessed, info.last_accessed); EXPECT_EQ(new_modified, info.last_modified); @@ -220,7 +220,7 @@ TEST_F(LocalFileUtilTest, TouchDirectory) { false /* recursive */)); base::PlatformFileInfo info; - ASSERT_TRUE(file_util::GetFileInfo(LocalPath(dir_name), &info)); + ASSERT_TRUE(base::GetFileInfo(LocalPath(dir_name), &info)); const base::Time new_accessed = info.last_accessed + base::TimeDelta::FromHours(10); const base::Time new_modified = @@ -230,7 +230,7 @@ TEST_F(LocalFileUtilTest, TouchDirectory) { file_util()->Touch(context.get(), CreateURL(dir_name), new_accessed, new_modified)); - ASSERT_TRUE(file_util::GetFileInfo(LocalPath(dir_name), &info)); + ASSERT_TRUE(base::GetFileInfo(LocalPath(dir_name), &info)); EXPECT_EQ(new_accessed, info.last_accessed); EXPECT_EQ(new_modified, info.last_modified); } diff --git a/content/browser/fileapi/obfuscated_file_util_unittest.cc b/content/browser/fileapi/obfuscated_file_util_unittest.cc index 2a9710e6a6..72dd36008d 100644 --- a/content/browser/fileapi/obfuscated_file_util_unittest.cc +++ b/content/browser/fileapi/obfuscated_file_util_unittest.cc @@ -44,7 +44,7 @@ bool FileExists(const base::FilePath& path) { int64 GetSize(const base::FilePath& path) { int64 size; - EXPECT_TRUE(file_util::GetFileSize(path, &size)); + EXPECT_TRUE(base::GetFileSize(path, &size)); return size; } @@ -2407,7 +2407,7 @@ TEST_F(ObfuscatedFileUtilTest, MigrationBackFromIsolated) { // Populate the origin directory with some fake data. old_directory_db_path = data_dir_path().Append(path); - ASSERT_TRUE(file_util::CreateDirectory(old_directory_db_path)); + ASSERT_TRUE(base::CreateDirectory(old_directory_db_path)); EXPECT_EQ(static_cast<int>(kFakeDirectoryData.size()), file_util::WriteFile(old_directory_db_path.AppendASCII("dummy"), kFakeDirectoryData.data(), diff --git a/content/browser/fileapi/transient_file_util_unittest.cc b/content/browser/fileapi/transient_file_util_unittest.cc index b12a99eecc..2ddb315c55 100644 --- a/content/browser/fileapi/transient_file_util_unittest.cc +++ b/content/browser/fileapi/transient_file_util_unittest.cc @@ -40,8 +40,7 @@ class TransientFileUtilTest : public testing::Test { void CreateAndRegisterTemporaryFile( FileSystemURL* file_url, base::FilePath* file_path) { - EXPECT_TRUE( - file_util::CreateTemporaryFileInDir(data_dir_.path(), file_path)); + EXPECT_TRUE(base::CreateTemporaryFileInDir(data_dir_.path(), file_path)); IsolatedContext* isolated_context = IsolatedContext::GetInstance(); std::string name = "tmp"; std::string fsid = isolated_context->RegisterFileSystemForPath( diff --git a/content/browser/frame_host/OWNERS b/content/browser/frame_host/OWNERS new file mode 100644 index 0000000000..df8aeac954 --- /dev/null +++ b/content/browser/frame_host/OWNERS @@ -0,0 +1 @@ +nasko@chromium.org
diff --git a/content/browser/frame_host/frame_tree.cc b/content/browser/frame_host/frame_tree.cc index 303c496ae4..fef82eebab 100644 --- a/content/browser/frame_host/frame_tree.cc +++ b/content/browser/frame_host/frame_tree.cc @@ -44,19 +44,21 @@ bool FrameTreeNodeForFrameId(int64 frame_id, } // namespace FrameTree::FrameTree(Navigator* navigator, + RenderFrameHostDelegate* render_frame_delegate, RenderViewHostDelegate* render_view_delegate, RenderWidgetHostDelegate* render_widget_delegate, RenderFrameHostManager::Delegate* manager_delegate) - : render_view_delegate_(render_view_delegate), + : render_frame_delegate_(render_frame_delegate), + render_view_delegate_(render_view_delegate), render_widget_delegate_(render_widget_delegate), manager_delegate_(manager_delegate), root_(new FrameTreeNode(navigator, + render_frame_delegate, render_view_delegate, render_widget_delegate, manager_delegate, FrameTreeNode::kInvalidFrameId, - std::string(), - scoped_ptr<RenderFrameHostImpl>())) { + std::string())) { } FrameTree::~FrameTree() { @@ -92,22 +94,26 @@ void FrameTree::OnFirstNavigationAfterSwap(int main_frame_id) { root_->set_frame_id(main_frame_id); } -void FrameTree::AddFrame(int render_frame_host_id, - int64 parent_frame_id, - int64 frame_id, - const std::string& frame_name) { +RenderFrameHostImpl* FrameTree::AddFrame(int render_frame_host_id, + int64 parent_frame_id, + int64 frame_id, + const std::string& frame_name) { FrameTreeNode* parent = FindByFrameID(parent_frame_id); // TODO(ajwong): Should the renderer be killed here? Would there be a race on // shutdown that might make this case possible? if (!parent) - return; + return NULL; - parent->AddChild(CreateNode(frame_id, frame_name, render_frame_host_id, - parent->navigator(), - parent->render_frame_host()->GetProcess())); + scoped_ptr<FrameTreeNode> node(CreateNode( + frame_id, frame_name, render_frame_host_id, parent)); + RenderFrameHostImpl* render_frame = node->render_frame_host(); + parent->AddChild(node.Pass()); + return render_frame; } -void FrameTree::RemoveFrame(int64 parent_frame_id, int64 frame_id) { +void FrameTree::RemoveFrame(RenderFrameHostImpl* render_frame_host, + int64 parent_frame_id, + int64 frame_id) { // If switches::kSitePerProcess is not specified, then the FrameTree only // contains a node for the root element. However, even in this case // frame detachments need to be broadcast outwards. @@ -119,7 +125,7 @@ void FrameTree::RemoveFrame(int64 parent_frame_id, int64 frame_id) { FrameTreeNode* child = FindByFrameID(frame_id); if (!on_frame_removed_.is_null()) { on_frame_removed_.Run( - root_->render_frame_host()->render_view_host(), frame_id); + render_frame_host->render_view_host(), frame_id); } // TODO(ajwong): Should the renderer be killed here? Would there be a race on @@ -164,18 +170,22 @@ scoped_ptr<FrameTreeNode> FrameTree::CreateNode( int64 frame_id, const std::string& frame_name, int render_frame_host_id, - Navigator* navigator, - RenderProcessHost* render_process_host) { + FrameTreeNode* parent_node) { + scoped_ptr<FrameTreeNode> frame_tree_node(new FrameTreeNode( + parent_node->navigator(), render_frame_delegate_, render_view_delegate_, + render_widget_delegate_, manager_delegate_, frame_id, frame_name)); + scoped_ptr<RenderFrameHostImpl> render_frame_host( RenderFrameHostFactory::Create( - root_->render_frame_host()->render_view_host(), + parent_node->render_frame_host()->render_view_host(), + parent_node->render_frame_host()->delegate(), this, + frame_tree_node.get(), render_frame_host_id, false)); - return make_scoped_ptr(new FrameTreeNode(navigator, - render_view_delegate_, render_widget_delegate_, manager_delegate_, - frame_id, frame_name, render_frame_host.Pass())); + frame_tree_node->set_render_frame_host(render_frame_host.release(), true); + return frame_tree_node.Pass(); } } // namespace content diff --git a/content/browser/frame_host/frame_tree.h b/content/browser/frame_host/frame_tree.h index 498dc20ffc..3ef2d4c979 100644 --- a/content/browser/frame_host/frame_tree.h +++ b/content/browser/frame_host/frame_tree.h @@ -16,6 +16,7 @@ namespace content { class FrameTreeNode; class Navigator; +class RenderFrameHostDelegate; class RenderProcessHost; class RenderViewHostDelegate; class RenderViewHostImpl; @@ -46,6 +47,7 @@ class CONTENT_EXPORT FrameTree { // TODO(creis): This set of delegates will change as we move things to // Navigator. FrameTree(Navigator* navigator, + RenderFrameHostDelegate* render_frame_delegate, RenderViewHostDelegate* render_view_delegate, RenderWidgetHostDelegate* render_widget_delegate, RenderFrameHostManager::Delegate* manager_delegate); @@ -72,11 +74,13 @@ class CONTENT_EXPORT FrameTree { // Frame tree manipulation routines. // TODO(creis): These should take in RenderFrameHost routing IDs. - void AddFrame(int render_frame_host_id, - int64 parent_frame_tree_node_id, - int64 frame_id, - const std::string& frame_name); - void RemoveFrame(int64 parent_frame_id, int64 frame_id); + RenderFrameHostImpl* AddFrame(int render_frame_host_id, + int64 parent_frame_tree_node_id, + int64 frame_id, + const std::string& frame_name); + void RemoveFrame(RenderFrameHostImpl* render_frame_host, + int64 parent_frame_id, + int64 frame_id); void SetFrameUrl(int64 frame_id, const GURL& url); // Resets the FrameTree and changes RenderFrameHost for the main frame. @@ -113,11 +117,11 @@ class CONTENT_EXPORT FrameTree { scoped_ptr<FrameTreeNode> CreateNode(int64 frame_id, const std::string& frame_name, int render_frame_host_id, - Navigator* navigator, - RenderProcessHost* render_process_host); + FrameTreeNode* parent_node); // These delegates are installed into all the RenderViewHosts and // RenderFrameHosts that we create. + RenderFrameHostDelegate* render_frame_delegate_; RenderViewHostDelegate* render_view_delegate_; RenderWidgetHostDelegate* render_widget_delegate_; RenderFrameHostManager::Delegate* manager_delegate_; diff --git a/content/browser/frame_host/frame_tree_node.cc b/content/browser/frame_host/frame_tree_node.cc index 65c20ee05b..37b61b4fad 100644 --- a/content/browser/frame_host/frame_tree_node.cc +++ b/content/browser/frame_host/frame_tree_node.cc @@ -16,21 +16,22 @@ const int64 FrameTreeNode::kInvalidFrameId = -1; int64 FrameTreeNode::next_frame_tree_node_id_ = 1; FrameTreeNode::FrameTreeNode(Navigator* navigator, + RenderFrameHostDelegate* render_frame_delegate, RenderViewHostDelegate* render_view_delegate, RenderWidgetHostDelegate* render_widget_delegate, RenderFrameHostManager::Delegate* manager_delegate, int64 frame_id, - const std::string& name, - scoped_ptr<RenderFrameHostImpl> render_frame_host) + const std::string& name) : navigator_(navigator), - render_manager_(render_view_delegate, + render_manager_(render_frame_delegate, + render_view_delegate, render_widget_delegate, manager_delegate), frame_tree_node_id_(next_frame_tree_node_id_++), frame_id_(frame_id), frame_name_(name), owns_render_frame_host_(true), - render_frame_host_(render_frame_host.release()) { + render_frame_host_(NULL) { } FrameTreeNode::~FrameTreeNode() { diff --git a/content/browser/frame_host/frame_tree_node.h b/content/browser/frame_host/frame_tree_node.h index cc8e9fafa6..9c22b125ba 100644 --- a/content/browser/frame_host/frame_tree_node.h +++ b/content/browser/frame_host/frame_tree_node.h @@ -11,6 +11,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" +#include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/frame_host/render_frame_host_manager.h" #include "content/common/content_export.h" #include "url/gurl.h" @@ -29,18 +30,27 @@ class CONTENT_EXPORT FrameTreeNode { static const int64 kInvalidFrameId; FrameTreeNode(Navigator* navigator, + RenderFrameHostDelegate* render_frame_delegate, RenderViewHostDelegate* render_view_delegate, RenderWidgetHostDelegate* render_widget_delegate, RenderFrameHostManager::Delegate* manager_delegate, int64 frame_id, - const std::string& name, - scoped_ptr<RenderFrameHostImpl> render_frame_host); + const std::string& name); ~FrameTreeNode(); void AddChild(scoped_ptr<FrameTreeNode> child); void RemoveChild(FrameTreeNode* child); + // TODO(nasko): This method should be removed once RenderFrameHosts are + // created by RenderFrameHostManager. + void set_render_frame_host( + RenderFrameHostImpl* render_frame_host, + bool owns_render_frame_host) { + render_frame_host_ = render_frame_host; + owns_render_frame_host_ = owns_render_frame_host; + } + // Transitional API allowing the RenderFrameHost of a FrameTreeNode // representing the main frame to be provided by someone else. After // this is called, the FrameTreeNode no longer owns its RenderFrameHost. diff --git a/content/browser/frame_host/frame_tree_unittest.cc b/content/browser/frame_host/frame_tree_unittest.cc index 27b8167814..6f1bb33038 100644 --- a/content/browser/frame_host/frame_tree_unittest.cc +++ b/content/browser/frame_host/frame_tree_unittest.cc @@ -6,7 +6,7 @@ #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" -#include "content/browser/frame_host/navigator.h" +#include "content/browser/frame_host/navigator_impl.h" #include "content/browser/frame_host/render_frame_host_factory.h" #include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_view_host_impl.h" @@ -53,7 +53,7 @@ class FrameTreeTest : public RenderViewHostTestHarness { // - Swapping back to NULL doesn't crash (easier tear-down for interstitials). // - Main frame does not own RenderFrameHost. TEST_F(FrameTreeTest, RootNode) { - FrameTree frame_tree(new Navigator(NULL, NULL), NULL, NULL, NULL); + FrameTree frame_tree(new NavigatorImpl(NULL, NULL), NULL, NULL, NULL, NULL); // Initial state has empty node. FrameTreeNode* root = frame_tree.root(); @@ -80,7 +80,7 @@ TEST_F(FrameTreeTest, RootNode) { // - On creation, frame id is unassigned. // - After a swap, frame id is unassigned. TEST_F(FrameTreeTest, FirstNavigationAfterSwap) { - FrameTree frame_tree(new Navigator(NULL, NULL), NULL, NULL, NULL); + FrameTree frame_tree(new NavigatorImpl(NULL, NULL), NULL, NULL, NULL, NULL); EXPECT_TRUE(frame_tree.IsFirstNavigationAfterSwap()); EXPECT_EQ(FrameTreeNode::kInvalidFrameId, @@ -99,7 +99,7 @@ TEST_F(FrameTreeTest, FirstNavigationAfterSwap) { // - Add a series of nodes and verify tree structure. // - Remove a series of nodes and verify tree structure. TEST_F(FrameTreeTest, Shape) { - FrameTree frame_tree(new Navigator(NULL, NULL), NULL, NULL, NULL); + FrameTree frame_tree(new NavigatorImpl(NULL, NULL), NULL, NULL, NULL, NULL); std::string no_children_node("no children node"); std::string deep_subtree("node with deep subtree"); @@ -108,7 +108,9 @@ TEST_F(FrameTreeTest, Shape) { // main frame swap here. scoped_ptr<RenderFrameHostImpl> render_frame_host = RenderFrameHostFactory::Create(static_cast<RenderViewHostImpl*>(rvh()), + NULL, &frame_tree, + frame_tree.root(), process()->GetNextRoutingID(), false); frame_tree.SwapMainFrame(render_frame_host.get()); @@ -150,7 +152,7 @@ TEST_F(FrameTreeTest, Shape) { GetTreeState(&frame_tree)); // Test removing of nodes. - frame_tree.RemoveFrame(555, 655); + frame_tree.RemoveFrame(NULL, 555, 655); ASSERT_EQ("5: [14: [244: [], 245: []], " "15: [255 'no children node': []], " "16: [264: [], 265: [], 266: [], " @@ -158,7 +160,7 @@ TEST_F(FrameTreeTest, Shape) { "[365: [455: [555: []]]], 268: []]]", GetTreeState(&frame_tree)); - frame_tree.RemoveFrame(16, 265); + frame_tree.RemoveFrame(NULL, 16, 265); ASSERT_EQ("5: [14: [244: [], 245: []], " "15: [255 'no children node': []], " "16: [264: [], 266: [], " @@ -166,7 +168,7 @@ TEST_F(FrameTreeTest, Shape) { "[365: [455: [555: []]]], 268: []]]", GetTreeState(&frame_tree)); - frame_tree.RemoveFrame(5, 15); + frame_tree.RemoveFrame(NULL, 5, 15); ASSERT_EQ("5: [14: [244: [], 245: []], " "16: [264: [], 266: [], " "267 'node with deep subtree': " diff --git a/content/browser/frame_host/interstitial_page_impl.cc b/content/browser/frame_host/interstitial_page_impl.cc index 8b249e924e..7af8d029f7 100644 --- a/content/browser/frame_host/interstitial_page_impl.cc +++ b/content/browser/frame_host/interstitial_page_impl.cc @@ -14,9 +14,9 @@ #include "base/threading/thread.h" #include "content/browser/dom_storage/dom_storage_context_wrapper.h" #include "content/browser/dom_storage/session_storage_namespace_impl.h" +#include "content/browser/frame_host/interstitial_page_navigator_impl.h" #include "content/browser/frame_host/navigation_controller_impl.h" #include "content/browser/frame_host/navigation_entry_impl.h" -#include "content/browser/frame_host/navigator.h" #include "content/browser/loader/resource_dispatcher_host_impl.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_view_host_factory.h" @@ -161,7 +161,8 @@ InterstitialPageImpl::InterstitialPageImpl( // While we get the code to a point to do this, pass NULL for it. // TODO(creis): We will also need to pass delegates for the RVHM as we // start to use it. - frame_tree_(new Navigator(NULL, this), NULL, NULL, NULL), + frame_tree_(new InterstitialPageNavigatorImpl(this, controller_), + NULL, NULL, NULL, NULL), original_child_id_(web_contents->GetRenderProcessHost()->GetID()), original_rvh_id_(web_contents->GetRenderViewHost()->GetRoutingID()), should_revert_web_contents_title_(false), @@ -431,7 +432,7 @@ void InterstitialPageImpl::DidNavigate( void InterstitialPageImpl::UpdateTitle( RenderViewHost* render_view_host, int32 page_id, - const string16& title, + const base::string16& title, base::i18n::TextDirection title_direction) { if (!enabled()) return; @@ -526,6 +527,7 @@ RenderViewHost* InterstitialPageImpl::CreateRenderViewHost() { return RenderViewHostFactory::Create(site_instance.get(), this, this, + this, MSG_ROUTING_NONE, MSG_ROUTING_NONE, false, @@ -545,7 +547,7 @@ WebContentsView* InterstitialPageImpl::CreateWebContentsView() { int32 max_page_id = web_contents()-> GetMaxPageIDForSiteInstance(render_view_host_->GetSiteInstance()); - render_view_host_->CreateRenderView(string16(), + render_view_host_->CreateRenderView(base::string16(), MSG_ROUTING_NONE, max_page_id); controller_->delegate()->RenderViewForInterstitialPageCreated( @@ -697,6 +699,7 @@ gfx::Rect InterstitialPageImpl::GetRootWindowResizerRect() const { } void InterstitialPageImpl::CreateNewWindow( + int render_process_id, int route_id, int main_frame_route_id, const ViewHostMsg_CreateWindow_Params& params, @@ -704,12 +707,14 @@ void InterstitialPageImpl::CreateNewWindow( NOTREACHED() << "InterstitialPage does not support showing popups yet."; } -void InterstitialPageImpl::CreateNewWidget(int route_id, +void InterstitialPageImpl::CreateNewWidget(int render_process_id, + int route_id, blink::WebPopupType popup_type) { NOTREACHED() << "InterstitialPage does not support showing drop-downs yet."; } -void InterstitialPageImpl::CreateNewFullscreenWidget(int route_id) { +void InterstitialPageImpl::CreateNewFullscreenWidget(int render_process_id, + int route_id) { NOTREACHED() << "InterstitialPage does not support showing full screen popups."; } diff --git a/content/browser/frame_host/interstitial_page_impl.h b/content/browser/frame_host/interstitial_page_impl.h index 47a127e823..fddeacd10f 100644 --- a/content/browser/frame_host/interstitial_page_impl.h +++ b/content/browser/frame_host/interstitial_page_impl.h @@ -10,6 +10,7 @@ #include "base/memory/weak_ptr.h" #include "content/browser/frame_host/frame_tree.h" #include "content/browser/frame_host/navigator_delegate.h" +#include "content/browser/frame_host/render_frame_host_delegate.h" #include "content/browser/renderer_host/render_view_host_delegate.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" #include "content/public/browser/interstitial_page.h" @@ -22,7 +23,6 @@ namespace content { class NavigationEntry; class NavigationControllerImpl; -class Navigator; class RenderViewHostImpl; class RenderWidgetHostView; class WebContentsView; @@ -38,6 +38,7 @@ class CONTENT_EXPORT InterstitialPageImpl : public NON_EXPORTED_BASE(InterstitialPage), public NotificationObserver, public WebContentsObserver, + public NON_EXPORTED_BASE(RenderFrameHostDelegate), public RenderViewHostDelegate, public RenderWidgetHostDelegate, public NON_EXPORTED_BASE(NavigatorDelegate) { @@ -101,6 +102,8 @@ class CONTENT_EXPORT InterstitialPageImpl virtual void NavigationEntryCommitted( const LoadCommittedDetails& load_details) OVERRIDE; + // RenderFrameHostDelegate implementation: + // RenderViewHostDelegate implementation: virtual RenderViewHostDelegateView* GetDelegateView() OVERRIDE; virtual const GURL& GetURL() const OVERRIDE; @@ -112,20 +115,23 @@ class CONTENT_EXPORT InterstitialPageImpl const ViewHostMsg_FrameNavigate_Params& params) OVERRIDE; virtual void UpdateTitle(RenderViewHost* render_view_host, int32 page_id, - const string16& title, + const base::string16& title, base::i18n::TextDirection title_direction) OVERRIDE; virtual RendererPreferences GetRendererPrefs( BrowserContext* browser_context) const OVERRIDE; virtual WebPreferences GetWebkitPrefs() OVERRIDE; virtual gfx::Rect GetRootWindowResizerRect() const OVERRIDE; virtual void CreateNewWindow( + int render_process_id, int route_id, int main_frame_route_id, const ViewHostMsg_CreateWindow_Params& params, SessionStorageNamespace* session_storage_namespace) OVERRIDE; - virtual void CreateNewWidget(int route_id, + virtual void CreateNewWidget(int render_process_id, + int route_id, blink::WebPopupType popup_type) OVERRIDE; - virtual void CreateNewFullscreenWidget(int route_id) OVERRIDE; + virtual void CreateNewFullscreenWidget(int render_process_id, + int route_id) OVERRIDE; virtual void ShowCreatedWindow(int route_id, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, @@ -246,7 +252,7 @@ class CONTENT_EXPORT InterstitialPageImpl // The original title of the contents that should be reverted to when the // interstitial is hidden. - string16 original_web_contents_title_; + base::string16 original_web_contents_title_; // Our RenderViewHostViewDelegate, necessary for accelerators to work. scoped_ptr<InterstitialPageRVHDelegateView> rvh_delegate_view_; diff --git a/content/browser/frame_host/interstitial_page_navigator_impl.cc b/content/browser/frame_host/interstitial_page_navigator_impl.cc new file mode 100644 index 0000000000..830e1bfde1 --- /dev/null +++ b/content/browser/frame_host/interstitial_page_navigator_impl.cc @@ -0,0 +1,17 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/frame_host/interstitial_page_navigator_impl.h" + +#include "content/browser/frame_host/interstitial_page_impl.h" +#include "content/browser/frame_host/navigator_delegate.h" + +namespace content { + +InterstitialPageNavigatorImpl::InterstitialPageNavigatorImpl( + InterstitialPageImpl* interstitial, + NavigationControllerImpl* navigation_controller) { +} + +} // namespace content diff --git a/content/browser/frame_host/interstitial_page_navigator_impl.h b/content/browser/frame_host/interstitial_page_navigator_impl.h new file mode 100644 index 0000000000..1b55fd21a3 --- /dev/null +++ b/content/browser/frame_host/interstitial_page_navigator_impl.h @@ -0,0 +1,33 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_FRAME_HOST_INTERSTITIAL_PAGE_NAVIGATOR_IMPL_H_ +#define CONTENT_BROWSER_FRAME_HOST_INTERSTITIAL_PAGE_NAVIGATOR_IMPL_H_ + +#include "base/memory/ref_counted.h" +#include "content/browser/frame_host/navigator.h" +#include "content/common/content_export.h" + +namespace content { + +class NavigationControllerImpl; +class InterstitialPageImpl; + +// Navigator implementation specific to InterstialPageImpl. It allows only one +// navigation to commit, since interstitial pages are not allowed to navigate. +class CONTENT_EXPORT InterstitialPageNavigatorImpl : public Navigator { + public: + InterstitialPageNavigatorImpl( + InterstitialPageImpl* interstitial, + NavigationControllerImpl* navigation_controller); + + private: + virtual ~InterstitialPageNavigatorImpl() {} + + DISALLOW_COPY_AND_ASSIGN(InterstitialPageNavigatorImpl); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_FRAME_HOST_INTERSTITIAL_PAGE_NAVIGATOR_IMPL_H_ diff --git a/content/browser/frame_host/navigation_controller_android.cc b/content/browser/frame_host/navigation_controller_android.cc new file mode 100644 index 0000000000..536e17dd3e --- /dev/null +++ b/content/browser/frame_host/navigation_controller_android.cc @@ -0,0 +1,73 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/frame_host/navigation_controller_android.h" + +#include "base/android/jni_android.h" +#include "content/public/browser/navigation_controller.h" +#include "jni/NavigationControllerImpl_jni.h" + +using base::android::AttachCurrentThread; + +namespace content { + +// static +bool NavigationControllerAndroid::Register(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +NavigationControllerAndroid::NavigationControllerAndroid( + NavigationController* navigation_controller) + : navigation_controller_(navigation_controller) { + JNIEnv* env = AttachCurrentThread(); + obj_.Reset(env, + Java_NavigationControllerImpl_create( + env, reinterpret_cast<intptr_t>(this)).obj()); +} + +NavigationControllerAndroid::~NavigationControllerAndroid() { + Java_NavigationControllerImpl_destroy(AttachCurrentThread(), obj_.obj()); +} + +base::android::ScopedJavaLocalRef<jobject> +NavigationControllerAndroid::GetJavaObject() { + return base::android::ScopedJavaLocalRef<jobject>(obj_); +} + +jboolean NavigationControllerAndroid::CanGoBack(JNIEnv* env, jobject obj) { + return navigation_controller_->CanGoBack(); +} + +jboolean NavigationControllerAndroid::CanGoForward(JNIEnv* env, + jobject obj) { + return navigation_controller_->CanGoForward(); +} + +jboolean NavigationControllerAndroid::CanGoToOffset(JNIEnv* env, + jobject obj, + jint offset) { + return navigation_controller_->CanGoToOffset(offset); +} + +void NavigationControllerAndroid::GoBack(JNIEnv* env, jobject obj) { + navigation_controller_->GoBack(); +} + +void NavigationControllerAndroid::GoForward(JNIEnv* env, jobject obj) { + navigation_controller_->GoForward(); +} + +void NavigationControllerAndroid::GoToOffset(JNIEnv* env, + jobject obj, + jint offset) { + navigation_controller_->GoToOffset(offset); +} + +void NavigationControllerAndroid::GoToNavigationIndex(JNIEnv* env, + jobject obj, + jint index) { + navigation_controller_->GoToIndex(index); +} + +} // namespace content diff --git a/content/browser/frame_host/navigation_controller_android.h b/content/browser/frame_host/navigation_controller_android.h new file mode 100644 index 0000000000..e0c96a63a0 --- /dev/null +++ b/content/browser/frame_host/navigation_controller_android.h @@ -0,0 +1,53 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_FRAME_HOST_NAVIGATION_CONTROLLER_ANDROID_H_ +#define CONTENT_BROWSER_FRAME_HOST_NAVIGATION_CONTROLLER_ANDROID_H_ + +#include <jni.h> + +#include "base/android/scoped_java_ref.h" +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "content/common/content_export.h" + +namespace content { + +class NavigationController; + +// Android wrapper around NavigationController that provides safer passage +// from java and back to native and provides java with a means of communicating +// with its native counterpart. +class CONTENT_EXPORT NavigationControllerAndroid { + public: + static bool Register(JNIEnv* env); + + explicit NavigationControllerAndroid( + NavigationController* navigation_controller); + ~NavigationControllerAndroid(); + + NavigationController* navigation_controller() const { + return navigation_controller_; + } + + base::android::ScopedJavaLocalRef<jobject> GetJavaObject(); + + jboolean CanGoBack(JNIEnv* env, jobject obj); + jboolean CanGoForward(JNIEnv* env, jobject obj); + jboolean CanGoToOffset(JNIEnv* env, jobject obj, jint offset); + void GoBack(JNIEnv* env, jobject obj); + void GoForward(JNIEnv* env, jobject obj); + void GoToOffset(JNIEnv* env, jobject obj, jint offset); + void GoToNavigationIndex(JNIEnv* env, jobject obj, jint index); + + private: + NavigationController* navigation_controller_; + base::android::ScopedJavaGlobalRef<jobject> obj_; + + DISALLOW_COPY_AND_ASSIGN(NavigationControllerAndroid); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_FRAME_HOST_NAVIGATION_CONTROLLER_ANDROID_H_ diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index 0c6f803cb8..a49a9323fa 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc @@ -163,7 +163,7 @@ NavigationEntry* NavigationController::CreateNavigationEntry( -1, loaded_url, referrer, - string16(), + base::string16(), transition, is_renderer_initiated); entry->SetVirtualURL(url); @@ -354,7 +354,7 @@ void NavigationControllerImpl::ReloadInternal(bool check_for_repost, // meanwhile, so we need to revert to the default title upon reload and // invalidate the previously cached title (SetTitle will do both). // See Chromium issue 96041. - pending_entry_->SetTitle(string16()); + pending_entry_->SetTitle(base::string16()); pending_entry_->SetTransitionType(PAGE_TRANSITION_RELOAD); } diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc index 1f31e11b3d..2f0cac26e3 100644 --- a/content/browser/frame_host/navigation_controller_impl_unittest.cc +++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc @@ -14,7 +14,7 @@ #include "content/browser/frame_host/navigation_controller_impl.h" #include "content/browser/frame_host/navigation_entry_impl.h" #include "content/browser/frame_host/navigation_entry_screenshot_manager.h" -#include "content/browser/renderer_host/test_render_view_host.h" +#include "content/browser/frame_host/navigator.h" #include "content/browser/site_instance_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/view_messages.h" @@ -29,6 +29,7 @@ #include "content/public/test/mock_render_process_host.h" #include "content/public/test/test_notification_tracker.h" #include "content/public/test/test_utils.h" +#include "content/test/test_render_view_host.h" #include "content/test/test_web_contents.h" #include "net/base/net_util.h" #include "skia/ext/platform_canvas.h" @@ -921,7 +922,7 @@ TEST_F(NavigationControllerTest, LoadURL_AbortDoesntCancelPending) { params.frame_id = 1; params.is_main_frame = true; params.error_code = net::ERR_ABORTED; - params.error_description = string16(); + params.error_description = base::string16(); params.url = kNewURL; params.showing_repost_interstitial = false; test_rvh()->OnMessageReceived( @@ -999,7 +1000,7 @@ TEST_F(NavigationControllerTest, LoadURL_RedirectAbortDoesntShowPendingURL) { params.frame_id = 1; params.is_main_frame = true; params.error_code = net::ERR_ABORTED; - params.error_description = string16(); + params.error_description = base::string16(); params.url = kRedirectURL; params.showing_repost_interstitial = false; test_rvh()->OnMessageReceived( @@ -2342,7 +2343,7 @@ TEST_F(NavigationControllerTest, RestoreNavigateAfterFailure) { fail_load_params.frame_id = 1; fail_load_params.is_main_frame = true; fail_load_params.error_code = net::ERR_ABORTED; - fail_load_params.error_description = string16(); + fail_load_params.error_description = base::string16(); fail_load_params.url = url; fail_load_params.showing_repost_interstitial = false; rvh->OnMessageReceived( @@ -2648,6 +2649,8 @@ TEST_F(NavigationControllerTest, ReloadTransient) { // See http://crbug.com/266922. TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) { NavigationControllerImpl& controller = controller_impl(); + Navigator* navigator = + contents()->GetFrameTree()->root()->navigator(); const GURL url1("nonexistent:12121"); const GURL url1_fixed("http://nonexistent:12121/"); @@ -2655,8 +2658,7 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) { // We create pending entries for renderer-initiated navigations so that we // can show them in new tabs when it is safe. - contents()->DidStartProvisionalLoadForFrame( - test_rvh(), 1, -1, true, url1); + navigator->DidStartProvisionalLoad(main_test_rfh(), 1, -1, true, url1); // Simulate what happens if a BrowserURLHandler rewrites the URL, causing // the virtual URL to differ from the URL. @@ -2670,8 +2672,7 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) { is_renderer_initiated()); // If the user clicks another link, we should replace the pending entry. - contents()->DidStartProvisionalLoadForFrame( - test_rvh(), 1, -1, true, url2); + navigator->DidStartProvisionalLoad(main_test_rfh(), 1, -1, true, url2); EXPECT_EQ(url2, controller.GetPendingEntry()->GetURL()); EXPECT_EQ(url2, controller.GetPendingEntry()->GetVirtualURL()); @@ -2681,24 +2682,24 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) { EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetVirtualURL()); // We should not replace the pending entry for an error URL. - contents()->DidStartProvisionalLoadForFrame( - test_rvh(), 1, -1, true, url1); + navigator->DidStartProvisionalLoad(main_test_rfh(), 1, -1, true, url1); EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL()); - contents()->DidStartProvisionalLoadForFrame( - test_rvh(), 1, -1, true, GURL(kUnreachableWebDataURL)); + navigator->DidStartProvisionalLoad( + main_test_rfh(), 1, -1, true, GURL(kUnreachableWebDataURL)); EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL()); // We should remember if the pending entry will replace the current one. // http://crbug.com/308444. - contents()->DidStartProvisionalLoadForFrame( - test_rvh(), 1, -1, true, url1); + navigator->DidStartProvisionalLoad(main_test_rfh(), 1, -1, true, url1); NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry())-> set_should_replace_entry(true); - contents()->DidStartProvisionalLoadForFrame( - test_rvh(), 1, -1, true, url2); + navigator->DidStartProvisionalLoad(main_test_rfh(), 1, -1, true, url2); EXPECT_TRUE( NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry())-> should_replace_entry()); + // TODO(nasko): Until OnNavigate is moved to RenderFrameHost, we need + // to go through the RenderViewHost. The TestRenderViewHost routes navigations + // to the main frame. test_rvh()->SendNavigate(0, url2); EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetURL()); } @@ -2897,7 +2898,7 @@ TEST_F(NavigationControllerTest, CloneAndGoBack) { NavigationControllerImpl& controller = controller_impl(); const GURL url1("http://foo1"); const GURL url2("http://foo2"); - const string16 title(ASCIIToUTF16("Title")); + const base::string16 title(ASCIIToUTF16("Title")); NavigateAndCommit(url1); controller.GetVisibleEntry()->SetTitle(title); @@ -2922,7 +2923,7 @@ TEST_F(NavigationControllerTest, CloneAndReload) { NavigationControllerImpl& controller = controller_impl(); const GURL url1("http://foo1"); const GURL url2("http://foo2"); - const string16 title(ASCIIToUTF16("Title")); + const base::string16 title(ASCIIToUTF16("Title")); NavigateAndCommit(url1); controller.GetVisibleEntry()->SetTitle(title); diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc index a9b37cc5db..d5d6fc2c98 100644 --- a/content/browser/frame_host/navigation_entry_impl.cc +++ b/content/browser/frame_host/navigation_entry_impl.cc @@ -60,7 +60,7 @@ NavigationEntryImpl::NavigationEntryImpl(SiteInstanceImpl* instance, int page_id, const GURL& url, const Referrer& referrer, - const string16& title, + const base::string16& title, PageTransition transition_type, bool is_renderer_initiated) : unique_id_(GetUniqueIDInConstructor()), @@ -130,12 +130,12 @@ const GURL& NavigationEntryImpl::GetVirtualURL() const { return virtual_url_.is_empty() ? url_ : virtual_url_; } -void NavigationEntryImpl::SetTitle(const string16& title) { +void NavigationEntryImpl::SetTitle(const base::string16& title) { title_ = title; cached_display_title_.clear(); } -const string16& NavigationEntryImpl::GetTitle() const { +const base::string16& NavigationEntryImpl::GetTitle() const { return title_; } @@ -166,7 +166,7 @@ void NavigationEntryImpl::SetBindings(int bindings) { bindings_ = bindings; } -const string16& NavigationEntryImpl::GetTitleForDisplay( +const base::string16& NavigationEntryImpl::GetTitleForDisplay( const std::string& languages) const { // Most pages have real titles. Don't even bother caching anything if this is // the case. @@ -179,7 +179,7 @@ const string16& NavigationEntryImpl::GetTitleForDisplay( return cached_display_title_; // Use the virtual URL first if any, and fall back on using the real URL. - string16 title; + base::string16 title; if (!virtual_url_.is_empty()) { title = net::FormatUrl(virtual_url_, languages); } else if (!url_.is_empty()) { @@ -188,8 +188,8 @@ const string16& NavigationEntryImpl::GetTitleForDisplay( // For file:// URLs use the filename as the title, not the full path. if (url_.SchemeIsFile()) { - string16::size_type slashpos = title.rfind('/'); - if (slashpos != string16::npos) + base::string16::size_type slashpos = title.rfind('/'); + if (slashpos != base::string16::npos) title = title.substr(slashpos + 1); } @@ -306,13 +306,14 @@ const std::string& NavigationEntryImpl::GetFrameToNavigate() const { } void NavigationEntryImpl::SetExtraData(const std::string& key, - const string16& data) { + const base::string16& data) { extra_data_[key] = data; } bool NavigationEntryImpl::GetExtraData(const std::string& key, - string16* data) const { - std::map<std::string, string16>::const_iterator iter = extra_data_.find(key); + base::string16* data) const { + std::map<std::string, base::string16>::const_iterator iter = + extra_data_.find(key); if (iter == extra_data_.end()) return false; *data = iter->second; diff --git a/content/browser/frame_host/navigation_entry_impl.h b/content/browser/frame_host/navigation_entry_impl.h index c7f4f5fc7c..8a518888ce 100644 --- a/content/browser/frame_host/navigation_entry_impl.h +++ b/content/browser/frame_host/navigation_entry_impl.h @@ -29,7 +29,7 @@ class CONTENT_EXPORT NavigationEntryImpl int page_id, const GURL& url, const Referrer& referrer, - const string16& title, + const base::string16& title, PageTransition transition_type, bool is_renderer_initiated); virtual ~NavigationEntryImpl(); @@ -45,13 +45,13 @@ class CONTENT_EXPORT NavigationEntryImpl virtual const Referrer& GetReferrer() const OVERRIDE; virtual void SetVirtualURL(const GURL& url) OVERRIDE; virtual const GURL& GetVirtualURL() const OVERRIDE; - virtual void SetTitle(const string16& title) OVERRIDE; - virtual const string16& GetTitle() const OVERRIDE; + virtual void SetTitle(const base::string16& title) OVERRIDE; + virtual const base::string16& GetTitle() const OVERRIDE; virtual void SetPageState(const PageState& state) OVERRIDE; virtual const PageState& GetPageState() const OVERRIDE; virtual void SetPageID(int page_id) OVERRIDE; virtual int32 GetPageID() const OVERRIDE; - virtual const string16& GetTitleForDisplay( + virtual const base::string16& GetTitleForDisplay( const std::string& languages) const OVERRIDE; virtual bool IsViewSourceMode() const OVERRIDE; virtual void SetTransitionType(PageTransition transition_type) OVERRIDE; @@ -80,9 +80,9 @@ class CONTENT_EXPORT NavigationEntryImpl virtual void SetFrameToNavigate(const std::string& frame_name) OVERRIDE; virtual const std::string& GetFrameToNavigate() const OVERRIDE; virtual void SetExtraData(const std::string& key, - const string16& data) OVERRIDE; + const base::string16& data) OVERRIDE; virtual bool GetExtraData(const std::string& key, - string16* data) const OVERRIDE; + base::string16* data) const OVERRIDE; virtual void ClearExtraData(const std::string& key) OVERRIDE; virtual void SetHttpStatusCode(int http_status_code) OVERRIDE; virtual int GetHttpStatusCode() const OVERRIDE; @@ -243,7 +243,7 @@ class CONTENT_EXPORT NavigationEntryImpl Referrer referrer_; GURL virtual_url_; bool update_virtual_url_with_url_; - string16 title_; + base::string16 title_; FaviconStatus favicon_; PageState page_state_; int32 page_id_; @@ -290,7 +290,7 @@ class CONTENT_EXPORT NavigationEntryImpl // us from having to do URL formatting on the URL every time the title is // displayed. When the URL, virtual URL, or title is set, this should be // cleared to force a refresh. - mutable string16 cached_display_title_; + mutable base::string16 cached_display_title_; // In case a navigation is transferred to a new RVH but the request has // been generated in the renderer already, this identifies the old request so @@ -342,7 +342,7 @@ class CONTENT_EXPORT NavigationEntryImpl // Used to store extra data to support browser features. This member is not // persisted, unless specific data is taken out/put back in at save/restore // time (see TabNavigation for an example of this). - std::map<std::string, string16> extra_data_; + std::map<std::string, base::string16> extra_data_; // Copy and assignment is explicitly allowed for this class. }; diff --git a/content/browser/frame_host/navigation_entry_impl_unittest.cc b/content/browser/frame_host/navigation_entry_impl_unittest.cc index cb742e497b..488106fefe 100644 --- a/content/browser/frame_host/navigation_entry_impl_unittest.cc +++ b/content/browser/frame_host/navigation_entry_impl_unittest.cc @@ -136,7 +136,7 @@ TEST_F(NavigationEntryTest, NavigationEntryAccessors) { EXPECT_EQ(GURL("from2"), entry2_->GetReferrer().url); // Title - EXPECT_EQ(string16(), entry1_->GetTitle()); + EXPECT_EQ(base::string16(), entry1_->GetTitle()); EXPECT_EQ(ASCIIToUTF16("title"), entry2_->GetTitle()); entry2_->SetTitle(ASCIIToUTF16("title2")); EXPECT_EQ(ASCIIToUTF16("title2"), entry2_->GetTitle()); @@ -219,8 +219,8 @@ TEST_F(NavigationEntryTest, NavigationEntryTimestamps) { // Test extra data stored in the navigation entry. TEST_F(NavigationEntryTest, NavigationEntryExtraData) { - string16 test_data = ASCIIToUTF16("my search terms"); - string16 output; + base::string16 test_data = ASCIIToUTF16("my search terms"); + base::string16 output; entry1_->SetExtraData("search_terms", test_data); EXPECT_FALSE(entry1_->GetExtraData("non_existent_key", &output)); @@ -233,7 +233,7 @@ TEST_F(NavigationEntryTest, NavigationEntryExtraData) { EXPECT_FALSE(entry1_->GetExtraData("search_terms", &output)); EXPECT_EQ(test_data, output); // Using an empty string shows that the data is not present in the map. - string16 output2; + base::string16 output2; EXPECT_FALSE(entry1_->GetExtraData("search_terms", &output2)); EXPECT_EQ(ASCIIToUTF16(""), output2); } diff --git a/content/browser/frame_host/navigator.cc b/content/browser/frame_host/navigator.cc deleted file mode 100644 index 4ca26b68ef..0000000000 --- a/content/browser/frame_host/navigator.cc +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/frame_host/navigator.h" - -#include "content/browser/frame_host/navigator_delegate.h" - -namespace content { - -Navigator::Navigator( - NavigationControllerImpl* nav_controller, - NavigatorDelegate* delegate) - : controller_(nav_controller), - delegate_(delegate) { -} - -} // namespace content diff --git a/content/browser/frame_host/navigator.h b/content/browser/frame_host/navigator.h index c20c9dd9c1..d6658e4cd9 100644 --- a/content/browser/frame_host/navigator.h +++ b/content/browser/frame_host/navigator.h @@ -8,44 +8,33 @@ #include "base/memory/ref_counted.h" #include "content/common/content_export.h" +class GURL; + namespace content { class NavigationControllerImpl; class NavigatorDelegate; +class RenderFrameHostImpl; -// This class is responsible for performing navigations in a node of the -// FrameTree. Its lifetime is bound to all FrameTreeNode objects that are -// using it and will be released once all nodes that use it are freed. -// The Navigator is bound to a single frame tree and cannot be used by multiple -// instances of FrameTree. +// Implementations of this interface are responsible for performing navigations +// in a node of the FrameTree. Its lifetime is bound to all FrameTreeNode +// objects that are using it and will be released once all nodes that use it are +// freed. The Navigator is bound to a single frame tree and cannot be used by +// multiple instances of FrameTree. // TODO(nasko): Move all navigation methods, such as didStartProvisionalLoad -// from WebContentsImpl to this class. +// from WebContentsImpl to this interface. class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> { public: - Navigator(NavigationControllerImpl* nav_controller, - NavigatorDelegate* delegate); - - NavigationControllerImpl* controller() { - return controller_; - } - - NavigatorDelegate* delegate() { - return delegate_; - } - - private: + // The RenderFrameHostImpl started a provisional load. + virtual void DidStartProvisionalLoad(RenderFrameHostImpl* render_frame_host, + int64 frame_id, + int64 parent_frame_id, + bool main_frame, + const GURL& url) {}; + + protected: friend class base::RefCounted<Navigator>; virtual ~Navigator() {} - - // The NavigationController that will keep track of session history for all - // RenderFrameHost objects using this Navigator. - // TODO(nasko): Move ownership of the NavigationController from - // WebContentsImpl to this class. - NavigationControllerImpl* controller_; - - // Used to notify the object embedding this Navigator about navigation - // events. Can be NULL in tests. - NavigatorDelegate* delegate_; }; } // namespace content diff --git a/content/browser/frame_host/navigator_delegate.h b/content/browser/frame_host/navigator_delegate.h index c906b6b111..62b5b48b0b 100644 --- a/content/browser/frame_host/navigator_delegate.h +++ b/content/browser/frame_host/navigator_delegate.h @@ -5,6 +5,8 @@ #ifndef CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_DELEGATE_H_ #define CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_DELEGATE_H_ +#include "content/public/browser/invalidate_type.h" + namespace content { class RenderFrameHost; @@ -12,10 +14,22 @@ class RenderFrameHost; // A delegate API used by Navigator to notify its embedder of navigation // related events. class NavigatorDelegate { - // TODO(nasko): This class will be used to dispatch notifications to - // WebContentsImpl, such as DidStartProvisionalLoad and - // NotifyNavigationStateChanged. Longer term, most of the - // NavigationControllerDelegate methods will likely move here. + public: + // The RenderFrameHost started a provisional load for the frame + // represented by |render_frame_host|. + virtual void DidStartProvisionalLoad( + RenderFrameHostImpl* render_frame_host, + int64 frame_id, + int64 parent_frame_id, + bool is_main_frame, + const GURL& validated_url, + bool is_error_page, + bool is_iframe_srcdoc) {} + + // Notification to the Navigator embedder that navigation state has + // changed. This method corresponds to + // WebContents::NotifyNavigationStateChanged. + virtual void NotifyChangedNavigationState(InvalidateTypes changed_flags) {} }; } // namspace content diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc new file mode 100644 index 0000000000..6cc9dad148 --- /dev/null +++ b/content/browser/frame_host/navigator_impl.cc @@ -0,0 +1,85 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/frame_host/navigator_impl.h" + +#include "content/browser/frame_host/frame_tree_node.h" +#include "content/browser/frame_host/navigation_controller_impl.h" +#include "content/browser/frame_host/navigation_entry_impl.h" +#include "content/browser/frame_host/navigator_delegate.h" +#include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/site_instance_impl.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/invalidate_type.h" +#include "content/public/browser/navigation_controller.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/common/url_constants.h" + +namespace content { + +NavigatorImpl::NavigatorImpl( + NavigationControllerImpl* navigation_controller, + NavigatorDelegate* delegate) + : controller_(navigation_controller), + delegate_(delegate) { +} + +void NavigatorImpl::DidStartProvisionalLoad( + RenderFrameHostImpl* render_frame_host, + int64 frame_id, + int64 parent_frame_id, + bool is_main_frame, + const GURL& url) { + bool is_error_page = (url.spec() == kUnreachableWebDataURL); + bool is_iframe_srcdoc = (url.spec() == kAboutSrcDocURL); + GURL validated_url(url); + RenderProcessHost* render_process_host = render_frame_host->GetProcess(); + RenderViewHost::FilterURL(render_process_host, false, &validated_url); + + if (is_main_frame) { + // If there is no browser-initiated pending entry for this navigation and it + // is not for the error URL, create a pending entry using the current + // SiteInstance, and ensure the address bar updates accordingly. We don't + // know the referrer or extra headers at this point, but the referrer will + // be set properly upon commit. + NavigationEntryImpl* pending_entry = + NavigationEntryImpl::FromNavigationEntry( + controller_->GetPendingEntry()); + bool has_browser_initiated_pending_entry = pending_entry && + !pending_entry->is_renderer_initiated(); + if (!has_browser_initiated_pending_entry && !is_error_page) { + NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( + controller_->CreateNavigationEntry(validated_url, + content::Referrer(), + content::PAGE_TRANSITION_LINK, + true /* is_renderer_initiated */, + std::string(), + controller_->GetBrowserContext())); + entry->set_site_instance( + static_cast<SiteInstanceImpl*>( + render_frame_host->render_view_host()->GetSiteInstance())); + // TODO(creis): If there's a pending entry already, find a safe way to + // update it instead of replacing it and copying over things like this. + if (pending_entry) { + entry->set_transferred_global_request_id( + pending_entry->transferred_global_request_id()); + entry->set_should_replace_entry(pending_entry->should_replace_entry()); + entry->set_redirect_chain(pending_entry->redirect_chain()); + } + controller_->SetPendingEntry(entry); + if (delegate_) + delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL); + } + } + + if (delegate_) { + // Notify the observer about the start of the provisional load. + delegate_->DidStartProvisionalLoad( + render_frame_host, frame_id, parent_frame_id, is_main_frame, + validated_url, is_error_page, is_iframe_srcdoc); + } +} + +} // namespace content diff --git a/content/browser/frame_host/navigator_impl.h b/content/browser/frame_host/navigator_impl.h new file mode 100644 index 0000000000..b66b87de03 --- /dev/null +++ b/content/browser/frame_host/navigator_impl.h @@ -0,0 +1,49 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_IMPL_H_ +#define CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_IMPL_H_ + +#include "base/memory/ref_counted.h" +#include "content/browser/frame_host/navigator.h" +#include "content/common/content_export.h" + +namespace content { + +class NavigationControllerImpl; +class NavigatorDelegate; + +// This class is an implementation of Navigator, responsible for managing +// navigations in regular browser tabs. +class CONTENT_EXPORT NavigatorImpl : public Navigator { + public: + NavigatorImpl(NavigationControllerImpl* navigation_controller, + NavigatorDelegate* delegate); + + // Navigator implementation. + virtual void DidStartProvisionalLoad(RenderFrameHostImpl* render_frame_host, + int64 frame_id, + int64 parent_frame_id, + bool main_frame, + const GURL& url) OVERRIDE; + + private: + virtual ~NavigatorImpl() {} + + // The NavigationController that will keep track of session history for all + // RenderFrameHost objects using this NavigatorImpl. + // TODO(nasko): Move ownership of the NavigationController from + // WebContentsImpl to this class. + NavigationControllerImpl* controller_; + + // Used to notify the object embedding this Navigator about navigation + // events. Can be NULL in tests. + NavigatorDelegate* delegate_; + + DISALLOW_COPY_AND_ASSIGN(NavigatorImpl); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_IMPL_H_ diff --git a/content/browser/frame_host/render_frame_host_delegate.cc b/content/browser/frame_host/render_frame_host_delegate.cc new file mode 100644 index 0000000000..14ed0ad4cb --- /dev/null +++ b/content/browser/frame_host/render_frame_host_delegate.cc @@ -0,0 +1,15 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/frame_host/render_frame_host_delegate.h" + +namespace content { + +bool RenderFrameHostDelegate::OnMessageReceived( + RenderFrameHost* render_view_host, + const IPC::Message& message) { + return false; +} + +} // namespace content diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h new file mode 100644 index 0000000000..1de47dff37 --- /dev/null +++ b/content/browser/frame_host/render_frame_host_delegate.h @@ -0,0 +1,37 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_DELEGATE_H_ +#define CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_DELEGATE_H_ + +#include "content/common/content_export.h" + +namespace IPC { +class Message; +} + +namespace content { +class RenderFrameHost; + +// An interface implemented by an object interested in knowing about the state +// of the RenderFrameHost. +class CONTENT_EXPORT RenderFrameHostDelegate { + public: + // This is used to give the delegate a chance to filter IPC messages. + virtual bool OnMessageReceived(RenderFrameHost* render_frame_host, + const IPC::Message& message); + + // Informs the delegate whenever a RenderFrameHost is created. + virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) {} + + // Informs the delegate whenever a RenderFrameHost is deleted. + virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) {} + + protected: + virtual ~RenderFrameHostDelegate() {} +}; + +} // namespace content + +#endif // CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_DELEGATE_H_ diff --git a/content/browser/frame_host/render_frame_host_factory.cc b/content/browser/frame_host/render_frame_host_factory.cc index 8e9215c33a..4262c1c7eb 100644 --- a/content/browser/frame_host/render_frame_host_factory.cc +++ b/content/browser/frame_host/render_frame_host_factory.cc @@ -5,6 +5,7 @@ #include "content/browser/frame_host/render_frame_host_factory.h" #include "base/logging.h" +#include "content/browser/frame_host/frame_tree_node.h" #include "content/browser/frame_host/render_frame_host_impl.h" namespace content { @@ -15,17 +16,22 @@ RenderFrameHostFactory* RenderFrameHostFactory::factory_ = NULL; // static scoped_ptr<RenderFrameHostImpl> RenderFrameHostFactory::Create( RenderViewHostImpl* render_view_host, + RenderFrameHostDelegate* delegate, FrameTree* frame_tree, + FrameTreeNode* frame_tree_node, int routing_id, bool is_swapped_out) { if (factory_) { return factory_->CreateRenderFrameHost(render_view_host, + delegate, frame_tree, + frame_tree_node, routing_id, is_swapped_out).Pass(); } return make_scoped_ptr(new RenderFrameHostImpl( - render_view_host, frame_tree, routing_id, is_swapped_out)); + render_view_host, delegate, frame_tree, frame_tree_node, routing_id, + is_swapped_out)); } // static diff --git a/content/browser/frame_host/render_frame_host_factory.h b/content/browser/frame_host/render_frame_host_factory.h index 4b6e2b6b54..ce8433d088 100644 --- a/content/browser/frame_host/render_frame_host_factory.h +++ b/content/browser/frame_host/render_frame_host_factory.h @@ -12,6 +12,8 @@ namespace content { class FrameTree; +class FrameTreeNode; +class RenderFrameHostDelegate; class RenderFrameHostImpl; class RenderViewHostImpl; @@ -24,7 +26,9 @@ class CONTENT_EXPORT RenderFrameHostFactory { // or a regular RenderFrameHostImpl if no factory is registered. static scoped_ptr<RenderFrameHostImpl> Create( RenderViewHostImpl* render_view_host, + RenderFrameHostDelegate* delegate, FrameTree* frame_tree, + FrameTreeNode* frame_tree_node, int routing_id, bool is_swapped_out); @@ -39,7 +43,9 @@ class CONTENT_EXPORT RenderFrameHostFactory { // function to create an alternate kind of RenderFrameHostImpl for testing. virtual scoped_ptr<RenderFrameHostImpl> CreateRenderFrameHost( RenderViewHostImpl* render_view_host, + RenderFrameHostDelegate* delegate, FrameTree* frame_tree, + FrameTreeNode* frame_tree_node, int routing_id, bool is_swapped_out) = 0; diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index c1fbc30751..658e834230 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc @@ -7,10 +7,14 @@ #include "base/containers/hash_tables.h" #include "base/lazy_instance.h" #include "content/browser/frame_host/frame_tree.h" +#include "content/browser/frame_host/frame_tree_node.h" +#include "content/browser/frame_host/navigator.h" +#include "content/browser/frame_host/render_frame_host_delegate.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/common/frame_messages.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" +#include "content/public/browser/user_metrics.h" #include "url/gurl.h" namespace content { @@ -33,11 +37,15 @@ RenderFrameHostImpl* RenderFrameHostImpl::FromID( RenderFrameHostImpl::RenderFrameHostImpl( RenderViewHostImpl* render_view_host, + RenderFrameHostDelegate* delegate, FrameTree* frame_tree, + FrameTreeNode* frame_tree_node, int routing_id, bool is_swapped_out) : render_view_host_(render_view_host), + delegate_(delegate), frame_tree_(frame_tree), + frame_tree_node_(frame_tree_node), routing_id_(routing_id), is_swapped_out_(is_swapped_out) { GetProcess()->AddRoute(routing_id_, this); @@ -50,7 +58,12 @@ RenderFrameHostImpl::~RenderFrameHostImpl() { GetProcess()->RemoveRoute(routing_id_); g_routing_id_frame_map.Get().erase( RenderFrameHostID(GetProcess()->GetID(), routing_id_)); + if (delegate_) + delegate_->RenderFrameDeleted(this); +} +int RenderFrameHostImpl::GetRoutingID() { + return routing_id_; } bool RenderFrameHostImpl::Send(IPC::Message* message) { @@ -58,6 +71,9 @@ bool RenderFrameHostImpl::Send(IPC::Message* message) { } bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) { + if (delegate_->OnMessageReceived(this, msg)) + return true; + bool handled = true; bool msg_is_ok = true; IPC_BEGIN_MESSAGE_MAP_EX(RenderFrameHostImpl, msg, msg_is_ok) @@ -66,6 +82,13 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) { OnDidStartProvisionalLoadForFrame) IPC_END_MESSAGE_MAP_EX() + if (!msg_is_ok) { + // The message had a handler, but its de-serialization failed. + // Kill the renderer. + RecordAction(UserMetricsAction("BadMessageTerminate_RFH")); + GetProcess()->ReceivedBadMessage(); + } + return handled; } @@ -83,12 +106,14 @@ void RenderFrameHostImpl::OnCreateChildFrame(int new_frame_routing_id, int64 parent_frame_id, int64 frame_id, const std::string& frame_name) { - frame_tree_->AddFrame(new_frame_routing_id, parent_frame_id, frame_id, - frame_name); + RenderFrameHostImpl* new_frame = frame_tree_->AddFrame( + new_frame_routing_id, parent_frame_id, frame_id, frame_name); + if (delegate_) + delegate_->RenderFrameCreated(new_frame); } void RenderFrameHostImpl::OnDetach(int64 parent_frame_id, int64 frame_id) { - frame_tree_->RemoveFrame(parent_frame_id, frame_id); + frame_tree_->RemoveFrame(this, parent_frame_id, frame_id); } void RenderFrameHostImpl::OnDidStartProvisionalLoadForFrame( @@ -96,8 +121,8 @@ void RenderFrameHostImpl::OnDidStartProvisionalLoadForFrame( int64 parent_frame_id, bool is_main_frame, const GURL& url) { - render_view_host_->OnDidStartProvisionalLoadForFrame( - frame_id, parent_frame_id, is_main_frame, url); + frame_tree_node_->navigator()->DidStartProvisionalLoad( + this, frame_id, parent_frame_id, is_main_frame, url); } } // namespace content diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 3c5e3acef2..2822724adf 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h @@ -13,9 +13,15 @@ class GURL; +namespace base { +class FilePath; +} + namespace content { class FrameTree; +class FrameTreeNode; +class RenderFrameHostDelegate; class RenderProcessHost; class RenderViewHostImpl; @@ -25,6 +31,9 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost { virtual ~RenderFrameHostImpl(); + // RenderFrameHost + virtual int GetRoutingID() OVERRIDE; + // IPC::Sender virtual bool Send(IPC::Message* msg) OVERRIDE; @@ -39,9 +48,8 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost { int64 frame_id, const std::string& frame_name); - RenderViewHostImpl* render_view_host() { - return render_view_host_; - } + RenderViewHostImpl* render_view_host() { return render_view_host_; } + RenderFrameHostDelegate* delegate() { return delegate_; } protected: friend class RenderFrameHostFactory; @@ -50,11 +58,15 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost { // should be the abstraction needed here, but we need RenderViewHost to pass // into WebContentsObserver::FrameDetached for now. RenderFrameHostImpl(RenderViewHostImpl* render_view_host, + RenderFrameHostDelegate* delegate, FrameTree* frame_tree, + FrameTreeNode* frame_tree_node, int routing_id, bool is_swapped_out); private: + friend class TestRenderViewHost; + // IPC Message handlers. void OnDetach(int64 parent_frame_id, int64 frame_id); void OnDidStartProvisionalLoadForFrame(int64 frame_id, @@ -67,10 +79,16 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost { // TODO(nasko): This should be removed and replaced by RenderProcessHost. RenderViewHostImpl* render_view_host_; // Not owned. + RenderFrameHostDelegate* delegate_; + // Reference to the whole frame tree that this RenderFrameHost belongs too. // Allows this RenderFrameHost to add and remove nodes in response to // messages from the renderer requesting DOM manipulation. FrameTree* frame_tree_; + + // The FrameTreeNode which this RenderFrameHostImpl is hosted in. + FrameTreeNode* frame_tree_node_; + int routing_id_; bool is_swapped_out_; diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc index 4e64342eac..8b7448d1a3 100644 --- a/content/browser/frame_host/render_frame_host_manager.cc +++ b/content/browser/frame_host/render_frame_host_manager.cc @@ -57,11 +57,13 @@ RenderFrameHostManager::PendingNavigationParams::PendingNavigationParams( RenderFrameHostManager::PendingNavigationParams::~PendingNavigationParams() {} RenderFrameHostManager::RenderFrameHostManager( + RenderFrameHostDelegate* render_frame_delegate, RenderViewHostDelegate* render_view_delegate, RenderWidgetHostDelegate* render_widget_delegate, Delegate* delegate) : delegate_(delegate), cross_navigation_pending_(false), + render_frame_delegate_(render_frame_delegate), render_view_delegate_(render_view_delegate), render_widget_delegate_(render_widget_delegate), render_view_host_(NULL), @@ -98,8 +100,8 @@ void RenderFrameHostManager::Init(BrowserContext* browser_context, site_instance = SiteInstance::Create(browser_context); render_view_host_ = static_cast<RenderViewHostImpl*>( RenderViewHostFactory::Create( - site_instance, render_view_delegate_, render_widget_delegate_, - routing_id, main_frame_routing_id, false, + site_instance, render_view_delegate_, render_frame_delegate_, + render_widget_delegate_, routing_id, main_frame_routing_id, false, delegate_->IsHidden())); render_view_host_->AttachToFrameTree(); @@ -745,6 +747,7 @@ int RenderFrameHostManager::CreateRenderView( new_render_view_host = static_cast<RenderViewHostImpl*>( RenderViewHostFactory::Create(instance, render_view_delegate_, + render_frame_delegate_, render_widget_delegate_, MSG_ROUTING_NONE, MSG_ROUTING_NONE, @@ -783,9 +786,13 @@ bool RenderFrameHostManager::InitRenderView(RenderViewHost* render_view_host, render_view_host->AllowBindings(pending_web_ui()->GetBindings()); } else { // Ensure that we don't create an unprivileged RenderView in a WebUI-enabled - // process. - CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( - render_view_host->GetProcess()->GetID())); + // process unless it's swapped out. + RenderViewHostImpl* rvh_impl = + static_cast<RenderViewHostImpl*>(render_view_host); + if (!rvh_impl->is_swapped_out()) { + CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( + render_view_host->GetProcess()->GetID())); + } } return delegate_->CreateRenderViewForRenderManager(render_view_host, @@ -799,6 +806,13 @@ void RenderFrameHostManager::CommitPending() { // this triggers won't be able to figure out what's going on. bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); + // We expect SwapOutOldPage to have canceled any modal dialogs and told the + // renderer to suppress any further dialogs until it is swapped out. However, + // crash reports indicate that it's still possible for modal dialogs to exist + // at this point, which poses a risk if we delete their RenderViewHost below. + // Cancel them again to be safe. http://crbug.com/324320. + delegate_->CancelModalDialogsForRenderManager(); + // Next commit the Web UI, if any. Either replace |web_ui_| with // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or // leave |web_ui_| as is if reusing it. diff --git a/content/browser/frame_host/render_frame_host_manager.h b/content/browser/frame_host/render_frame_host_manager.h index 78ca04aefe..94a4998b62 100644 --- a/content/browser/frame_host/render_frame_host_manager.h +++ b/content/browser/frame_host/render_frame_host_manager.h @@ -23,6 +23,7 @@ class InterstitialPageImpl; class NavigationControllerImpl; class NavigationEntry; class NavigationEntryImpl; +class RenderFrameHostDelegate; class RenderFrameHostManagerTest; class RenderViewHost; class RenderViewHostImpl; @@ -113,6 +114,7 @@ class CONTENT_EXPORT RenderFrameHostManager // // You must call Init() before using this class. RenderFrameHostManager( + RenderFrameHostDelegate* render_frame_delegate, RenderViewHostDelegate* render_view_delegate, RenderWidgetHostDelegate* render_widget_delegate, Delegate* delegate); @@ -356,6 +358,7 @@ class CONTENT_EXPORT RenderFrameHostManager // Implemented by the owner of this class, these delegates are installed into // all the RenderViewHosts that we create. + RenderFrameHostDelegate* render_frame_delegate_; RenderViewHostDelegate* render_view_delegate_; RenderWidgetHostDelegate* render_widget_delegate_; diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc index 9a4b004be3..2ba5fb8493 100644 --- a/content/browser/frame_host/render_frame_host_manager_unittest.cc +++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc @@ -6,7 +6,6 @@ #include "content/browser/frame_host/navigation_controller_impl.h" #include "content/browser/frame_host/navigation_entry_impl.h" #include "content/browser/frame_host/render_frame_host_manager.h" -#include "content/browser/renderer_host/test_render_view_host.h" #include "content/browser/site_instance_impl.h" #include "content/browser/webui/web_ui_controller_factory_registry.h" #include "content/common/view_messages.h" @@ -28,6 +27,7 @@ #include "content/public/test/test_notification_tracker.h" #include "content/test/test_content_browser_client.h" #include "content/test/test_content_client.h" +#include "content/test/test_render_view_host.h" #include "content/test/test_web_contents.h" #include "testing/gtest/include/gtest/gtest.h" @@ -260,7 +260,7 @@ TEST_F(RenderFrameHostManagerTest, FilterMessagesWhileSwappedOut) { contents()->GetRenderManagerForTesting()->current_host()); // Send an update title message and make sure it works. - const string16 ntp_title = ASCIIToUTF16("NTP Title"); + const base::string16 ntp_title = ASCIIToUTF16("NTP Title"); blink::WebTextDirection direction = blink::WebTextDirectionLeftToRight; EXPECT_TRUE(ntp_rvh->OnMessageReceived( ViewHostMsg_UpdateTitle(rvh()->GetRoutingID(), 0, ntp_title, direction))); @@ -288,7 +288,7 @@ TEST_F(RenderFrameHostManagerTest, FilterMessagesWhileSwappedOut) { dest_rvh->SendNavigate(101, kDestUrl); // The new RVH should be able to update its title. - const string16 dest_title = ASCIIToUTF16("Google"); + const base::string16 dest_title = ASCIIToUTF16("Google"); EXPECT_TRUE(dest_rvh->OnMessageReceived( ViewHostMsg_UpdateTitle(rvh()->GetRoutingID(), 101, dest_title, direction))); @@ -308,9 +308,9 @@ TEST_F(RenderFrameHostManagerTest, FilterMessagesWhileSwappedOut) { MockRenderProcessHost* ntp_process_host = static_cast<MockRenderProcessHost*>(ntp_rvh->GetProcess()); ntp_process_host->sink().ClearMessages(); - const string16 msg = ASCIIToUTF16("Message"); + const base::string16 msg = ASCIIToUTF16("Message"); bool result = false; - string16 unused; + base::string16 unused; ViewHostMsg_RunBeforeUnloadConfirm before_unload_msg( rvh()->GetRoutingID(), kChromeURL, msg, false, &result, &unused); // Enable pumping for check in BrowserMessageFilter::CheckCanDispatchOnUI. @@ -568,7 +568,7 @@ TEST_F(RenderFrameHostManagerTest, Init) { scoped_ptr<TestWebContents> web_contents( TestWebContents::Create(browser_context(), instance)); RenderFrameHostManager manager(web_contents.get(), web_contents.get(), - web_contents.get()); + web_contents.get(), web_contents.get()); manager.Init(browser_context(), instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE); @@ -594,7 +594,7 @@ TEST_F(RenderFrameHostManagerTest, Navigate) { // Create. RenderFrameHostManager manager(web_contents.get(), web_contents.get(), - web_contents.get()); + web_contents.get(), web_contents.get()); manager.Init(browser_context(), instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE); @@ -604,7 +604,7 @@ TEST_F(RenderFrameHostManagerTest, Navigate) { const GURL kUrl1("http://www.google.com/"); NavigationEntryImpl entry1( NULL /* instance */, -1 /* page_id */, kUrl1, Referrer(), - string16() /* title */, PAGE_TRANSITION_TYPED, + base::string16() /* title */, PAGE_TRANSITION_TYPED, false /* is_renderer_init */); host = manager.Navigate(entry1); @@ -626,7 +626,7 @@ TEST_F(RenderFrameHostManagerTest, Navigate) { NavigationEntryImpl entry2( NULL /* instance */, -1 /* page_id */, kUrl2, Referrer(kUrl1, blink::WebReferrerPolicyDefault), - string16() /* title */, PAGE_TRANSITION_LINK, + base::string16() /* title */, PAGE_TRANSITION_LINK, true /* is_renderer_init */); host = manager.Navigate(entry2); @@ -646,7 +646,7 @@ TEST_F(RenderFrameHostManagerTest, Navigate) { NavigationEntryImpl entry3( NULL /* instance */, -1 /* page_id */, kUrl3, Referrer(kUrl2, blink::WebReferrerPolicyDefault), - string16() /* title */, PAGE_TRANSITION_LINK, + base::string16() /* title */, PAGE_TRANSITION_LINK, false /* is_renderer_init */); host = manager.Navigate(entry3); @@ -686,14 +686,14 @@ TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyReNavigation) { // Create. RenderFrameHostManager manager(web_contents.get(), web_contents.get(), - web_contents.get()); + web_contents.get(), web_contents.get()); manager.Init(browser_context(), instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE); // 1) The first navigation. -------------------------- const GURL kUrl1("http://www.google.com/"); NavigationEntryImpl entry1(NULL /* instance */, -1 /* page_id */, kUrl1, - Referrer(), string16() /* title */, + Referrer(), base::string16() /* title */, PAGE_TRANSITION_TYPED, false /* is_renderer_init */); RenderViewHost* host = manager.Navigate(entry1); @@ -721,7 +721,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyReNavigation) { const GURL kUrl2("http://www.example.com"); NavigationEntryImpl entry2( NULL /* instance */, -1 /* page_id */, kUrl2, Referrer(), - string16() /* title */, PAGE_TRANSITION_TYPED, + base::string16() /* title */, PAGE_TRANSITION_TYPED, false /* is_renderer_init */); RenderViewHostImpl* host2 = static_cast<RenderViewHostImpl*>( manager.Navigate(entry2)); @@ -772,7 +772,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyReNavigation) { // 3) Cross-site navigate to next site before 2) has committed. -------------- const GURL kUrl3("http://webkit.org/"); NavigationEntryImpl entry3(NULL /* instance */, -1 /* page_id */, kUrl3, - Referrer(), string16() /* title */, + Referrer(), base::string16() /* title */, PAGE_TRANSITION_TYPED, false /* is_renderer_init */); test_process_host->sink().ClearMessages(); @@ -829,14 +829,14 @@ TEST_F(RenderFrameHostManagerTest, WebUI) { scoped_ptr<TestWebContents> web_contents( TestWebContents::Create(browser_context(), instance)); RenderFrameHostManager manager(web_contents.get(), web_contents.get(), - web_contents.get()); + web_contents.get(), web_contents.get()); manager.Init(browser_context(), instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE); EXPECT_FALSE(manager.current_host()->IsRenderViewLive()); const GURL kUrl("chrome://foo"); NavigationEntryImpl entry(NULL /* instance */, -1 /* page_id */, kUrl, - Referrer(), string16() /* title */, + Referrer(), base::string16() /* title */, PAGE_TRANSITION_TYPED, false /* is_renderer_init */); RenderViewHost* host = manager.Navigate(entry); @@ -876,16 +876,16 @@ TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) { scoped_ptr<TestWebContents> web_contents1( TestWebContents::Create(browser_context(), blank_instance)); RenderFrameHostManager manager1(web_contents1.get(), web_contents1.get(), - web_contents1.get()); + web_contents1.get(), web_contents1.get()); manager1.Init( browser_context(), blank_instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE); // Test the case that new RVH is considered live. - manager1.current_host()->CreateRenderView(string16(), -1, -1); + manager1.current_host()->CreateRenderView(base::string16(), -1, -1); // Navigate to a WebUI page. const GURL kUrl1("chrome://foo"); NavigationEntryImpl entry1(NULL /* instance */, -1 /* page_id */, kUrl1, - Referrer(), string16() /* title */, + Referrer(), base::string16() /* title */, PAGE_TRANSITION_TYPED, false /* is_renderer_init */); RenderViewHost* host1 = manager1.Navigate(entry1); @@ -906,16 +906,16 @@ TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) { scoped_ptr<TestWebContents> web_contents2( TestWebContents::Create(browser_context(), webui_instance)); RenderFrameHostManager manager2(web_contents2.get(), web_contents2.get(), - web_contents2.get()); + web_contents2.get(), web_contents2.get()); manager2.Init( browser_context(), webui_instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE); // Make sure the new RVH is considered live. This is usually done in // RenderWidgetHost::Init when opening a new tab from a link. - manager2.current_host()->CreateRenderView(string16(), -1, -1); + manager2.current_host()->CreateRenderView(base::string16(), -1, -1); const GURL kUrl2("chrome://foo/bar"); NavigationEntryImpl entry2(NULL /* instance */, -1 /* page_id */, kUrl2, - Referrer(), string16() /* title */, + Referrer(), base::string16() /* title */, PAGE_TRANSITION_LINK, true /* is_renderer_init */); RenderViewHost* host2 = manager2.Navigate(entry2); @@ -1107,7 +1107,7 @@ TEST_F(RenderFrameHostManagerTest, CleanUpSwappedOutRVHOnProcessCrash) { contents()->SetOpener(opener1.get()); // Make sure the new opener RVH is considered live. - opener1_manager->current_host()->CreateRenderView(string16(), -1, -1); + opener1_manager->current_host()->CreateRenderView(base::string16(), -1, -1); // Use a cross-process navigation in the opener to swap out the old RVH. EXPECT_FALSE(opener1_manager->GetSwappedOutRenderViewHost( @@ -1192,7 +1192,7 @@ TEST_F(RenderFrameHostManagerTest, NoSwapOnGuestNavigations) { // Create. RenderFrameHostManager manager(web_contents.get(), web_contents.get(), - web_contents.get()); + web_contents.get(), web_contents.get()); manager.Init(browser_context(), instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE); @@ -1202,7 +1202,7 @@ TEST_F(RenderFrameHostManagerTest, NoSwapOnGuestNavigations) { const GURL kUrl1("http://www.google.com/"); NavigationEntryImpl entry1( NULL /* instance */, -1 /* page_id */, kUrl1, Referrer(), - string16() /* title */, PAGE_TRANSITION_TYPED, + base::string16() /* title */, PAGE_TRANSITION_TYPED, false /* is_renderer_init */); host = manager.Navigate(entry1); @@ -1225,7 +1225,7 @@ TEST_F(RenderFrameHostManagerTest, NoSwapOnGuestNavigations) { NavigationEntryImpl entry2( NULL /* instance */, -1 /* page_id */, kUrl2, Referrer(kUrl1, blink::WebReferrerPolicyDefault), - string16() /* title */, PAGE_TRANSITION_LINK, + base::string16() /* title */, PAGE_TRANSITION_LINK, true /* is_renderer_init */); host = manager.Navigate(entry2); @@ -1257,14 +1257,14 @@ TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyClose) { // Create. RenderFrameHostManager manager(web_contents.get(), web_contents.get(), - web_contents.get()); + web_contents.get(), web_contents.get()); manager.Init(browser_context(), instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE); // 1) The first navigation. -------------------------- const GURL kUrl1("http://www.google.com/"); NavigationEntryImpl entry1(NULL /* instance */, -1 /* page_id */, kUrl1, - Referrer(), string16() /* title */, + Referrer(), base::string16() /* title */, PAGE_TRANSITION_TYPED, false /* is_renderer_init */); RenderViewHost* host = manager.Navigate(entry1); @@ -1291,7 +1291,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyClose) { const GURL kUrl2("http://www.example.com"); NavigationEntryImpl entry2( NULL /* instance */, -1 /* page_id */, kUrl2, Referrer(), - string16() /* title */, PAGE_TRANSITION_TYPED, + base::string16() /* title */, PAGE_TRANSITION_TYPED, false /* is_renderer_init */); RenderViewHostImpl* host2 = static_cast<RenderViewHostImpl*>( manager.Navigate(entry2)); diff --git a/content/browser/frame_host/test_render_frame_host.cc b/content/browser/frame_host/test_render_frame_host.cc deleted file mode 100644 index 040b232c40..0000000000 --- a/content/browser/frame_host/test_render_frame_host.cc +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/frame_host/test_render_frame_host.h" - -namespace content { - -TestRenderFrameHost::TestRenderFrameHost(RenderViewHostImpl* render_view_host, - FrameTree* frame_tree, - int routing_id, - bool is_swapped_out) - : RenderFrameHostImpl(render_view_host, - frame_tree, - routing_id, - is_swapped_out) {} - -TestRenderFrameHost::~TestRenderFrameHost() {} - -} // namespace content diff --git a/content/browser/frame_host/test_render_frame_host.h b/content/browser/frame_host/test_render_frame_host.h deleted file mode 100644 index 18055d67d1..0000000000 --- a/content/browser/frame_host/test_render_frame_host.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_FRAME_HOST_TEST_RENDER_FRAME_HOST_H_ -#define CONTENT_BROWSER_FRAME_HOST_TEST_RENDER_FRAME_HOST_H_ - -#include "base/basictypes.h" -#include "content/browser/frame_host/render_frame_host_impl.h" - -namespace content { - -class TestRenderFrameHost : public RenderFrameHostImpl { - public: - TestRenderFrameHost(RenderViewHostImpl* render_view_host, - FrameTree* frame_tree, - int routing_id, - bool is_swapped_out); - virtual ~TestRenderFrameHost(); - - // TODO(nick): As necessary for testing, override behavior of RenderFrameHost - // here. - - private: - DISALLOW_COPY_AND_ASSIGN(TestRenderFrameHost); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_FRAME_HOST_TEST_RENDER_FRAME_HOST_H_ diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc b/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc index ba048aea88..d466dde4b0 100644 --- a/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc +++ b/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc @@ -186,8 +186,8 @@ void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) { mapper ? "STANDARD GAMEPAD " : "", vendor_id, product_id); - TruncateUTF8ToByteSize(id, WebGamepad::idLengthCap - 1, &id); - string16 tmp16 = UTF8ToUTF16(id); + base::TruncateUTF8ToByteSize(id, WebGamepad::idLengthCap - 1, &id); + base::string16 tmp16 = UTF8ToUTF16(id); memset(pad.id, 0, sizeof(pad.id)); tmp16.copy(pad.id, arraysize(pad.id) - 1); diff --git a/content/browser/geolocation/OWNERS b/content/browser/geolocation/OWNERS index 62bcb071e2..df10cf46d5 100644 --- a/content/browser/geolocation/OWNERS +++ b/content/browser/geolocation/OWNERS @@ -1,7 +1,3 @@ -# Reviewers: bulach@chromium.org mvanouwerkerk@chromium.org timvolodine@chromium.org - -# Just owners: -joth@chromium.org diff --git a/content/browser/geolocation/fake_access_token_store.cc b/content/browser/geolocation/fake_access_token_store.cc index 9f9f61ba7f..0e5fe40128 100644 --- a/content/browser/geolocation/fake_access_token_store.cc +++ b/content/browser/geolocation/fake_access_token_store.cc @@ -45,7 +45,7 @@ void FakeAccessTokenStore::DefaultLoadAccessTokens( } void FakeAccessTokenStore::DefaultSaveAccessToken( - const GURL& server_url, const string16& access_token) { + const GURL& server_url, const base::string16& access_token) { DCHECK(server_url.is_valid()); access_token_set_[server_url] = access_token; } diff --git a/content/browser/geolocation/fake_access_token_store.h b/content/browser/geolocation/fake_access_token_store.h index 4d0867bf0b..30a01859d1 100644 --- a/content/browser/geolocation/fake_access_token_store.h +++ b/content/browser/geolocation/fake_access_token_store.h @@ -23,12 +23,13 @@ class FakeAccessTokenStore : public AccessTokenStore { MOCK_METHOD1(LoadAccessTokens, void(const LoadAccessTokensCallbackType& callback)); MOCK_METHOD2(SaveAccessToken, - void(const GURL& server_url, const string16& access_token)); + void(const GURL& server_url, + const base::string16& access_token)); void DefaultLoadAccessTokens(const LoadAccessTokensCallbackType& callback); void DefaultSaveAccessToken(const GURL& server_url, - const string16& access_token); + const base::string16& access_token); AccessTokenSet access_token_set_; LoadAccessTokensCallbackType callback_; diff --git a/content/browser/geolocation/location_arbitrator_impl.cc b/content/browser/geolocation/location_arbitrator_impl.cc index 37c34ee730..b8ed8c49bf 100644 --- a/content/browser/geolocation/location_arbitrator_impl.cc +++ b/content/browser/geolocation/location_arbitrator_impl.cc @@ -149,7 +149,7 @@ LocationProvider* LocationArbitratorImpl::NewNetworkLocationProvider( AccessTokenStore* access_token_store, net::URLRequestContextGetter* context, const GURL& url, - const string16& access_token) { + const base::string16& access_token) { #if defined(OS_ANDROID) // Android uses its own SystemLocationProvider. return NULL; diff --git a/content/browser/geolocation/location_arbitrator_impl.h b/content/browser/geolocation/location_arbitrator_impl.h index 45910552e4..e756f5e15d 100644 --- a/content/browser/geolocation/location_arbitrator_impl.h +++ b/content/browser/geolocation/location_arbitrator_impl.h @@ -57,7 +57,7 @@ class CONTENT_EXPORT LocationArbitratorImpl : public LocationArbitrator { AccessTokenStore* access_token_store, net::URLRequestContextGetter* context, const GURL& url, - const string16& access_token); + const base::string16& access_token); virtual LocationProvider* NewSystemLocationProvider(); virtual base::Time GetTimeNow() const; diff --git a/content/browser/geolocation/location_arbitrator_impl_unittest.cc b/content/browser/geolocation/location_arbitrator_impl_unittest.cc index 02df43172e..81df7a4326 100644 --- a/content/browser/geolocation/location_arbitrator_impl_unittest.cc +++ b/content/browser/geolocation/location_arbitrator_impl_unittest.cc @@ -85,7 +85,7 @@ class TestingLocationArbitrator : public LocationArbitratorImpl { AccessTokenStore* access_token_store, net::URLRequestContextGetter* context, const GURL& url, - const string16& access_token) OVERRIDE { + const base::string16& access_token) OVERRIDE { return new MockLocationProvider(&cell_); } diff --git a/content/browser/geolocation/network_location_provider.cc b/content/browser/geolocation/network_location_provider.cc index 678edb2409..efc68a7323 100644 --- a/content/browser/geolocation/network_location_provider.cc +++ b/content/browser/geolocation/network_location_provider.cc @@ -27,7 +27,7 @@ bool NetworkLocationProvider::PositionCache::CachePosition( const WifiData& wifi_data, const Geoposition& position) { // Check that we can generate a valid key for the wifi data. - string16 key; + base::string16 key; if (!MakeKey(wifi_data, &key)) { return false; } @@ -57,7 +57,7 @@ bool NetworkLocationProvider::PositionCache::CachePosition( // the cached position if available, NULL otherwise. const Geoposition* NetworkLocationProvider::PositionCache::FindPosition( const WifiData& wifi_data) { - string16 key; + base::string16 key; if (!MakeKey(wifi_data, &key)) { return NULL; } @@ -71,13 +71,13 @@ const Geoposition* NetworkLocationProvider::PositionCache::FindPosition( // static bool NetworkLocationProvider::PositionCache::MakeKey( const WifiData& wifi_data, - string16* key) { + base::string16* key) { // Currently we use only WiFi data and base the key only on the MAC addresses. DCHECK(key); key->clear(); const size_t kCharsPerMacAddress = 6 * 3 + 1; // e.g. "11:22:33:44:55:66|" key->reserve(wifi_data.access_point_data.size() * kCharsPerMacAddress); - const string16 separator(ASCIIToUTF16("|")); + const base::string16 separator(ASCIIToUTF16("|")); for (WifiData::AccessPointDataSet::const_iterator iter = wifi_data.access_point_data.begin(); iter != wifi_data.access_point_data.end(); @@ -96,7 +96,7 @@ LocationProviderBase* NewNetworkLocationProvider( AccessTokenStore* access_token_store, net::URLRequestContextGetter* context, const GURL& url, - const string16& access_token) { + const base::string16& access_token) { return new NetworkLocationProvider( access_token_store, context, url, access_token); } @@ -106,7 +106,7 @@ NetworkLocationProvider::NetworkLocationProvider( AccessTokenStore* access_token_store, net::URLRequestContextGetter* url_context_getter, const GURL& url, - const string16& access_token) + const base::string16& access_token) : access_token_store_(access_token_store), wifi_data_provider_(NULL), wifi_data_update_callback_( @@ -163,7 +163,7 @@ void NetworkLocationProvider::WifiDataUpdateAvailable( void NetworkLocationProvider::LocationResponseAvailable( const Geoposition& position, bool server_error, - const string16& access_token, + const base::string16& access_token, const WifiData& wifi_data) { DCHECK(CalledOnValidThread()); // Record the position and update our cache. diff --git a/content/browser/geolocation/network_location_provider.h b/content/browser/geolocation/network_location_provider.h index d5f3e999d7..710fd3f4fa 100644 --- a/content/browser/geolocation/network_location_provider.h +++ b/content/browser/geolocation/network_location_provider.h @@ -54,12 +54,12 @@ class NetworkLocationProvider // Makes the key for the map of cached positions, using a set of // data. Returns true if a good key was generated, false otherwise. static bool MakeKey(const WifiData& wifi_data, - string16* key); + base::string16* key); // The cache of positions. This is stored as a map keyed on a string that // represents a set of data, and a list to provide // least-recently-added eviction. - typedef std::map<string16, Geoposition> CacheMap; + typedef std::map<base::string16, Geoposition> CacheMap; CacheMap cache_; typedef std::list<CacheMap::iterator> CacheAgeList; CacheAgeList cache_age_list_; // Oldest first. @@ -68,7 +68,7 @@ class NetworkLocationProvider NetworkLocationProvider(AccessTokenStore* access_token_store, net::URLRequestContextGetter* context, const GURL& url, - const string16& access_token); + const base::string16& access_token); virtual ~NetworkLocationProvider(); // LocationProvider implementation @@ -92,7 +92,7 @@ class NetworkLocationProvider void LocationResponseAvailable(const Geoposition& position, bool server_error, - const string16& access_token, + const base::string16& access_token, const WifiData& wifi_data); scoped_refptr<AccessTokenStore> access_token_store_; @@ -111,7 +111,7 @@ class NetworkLocationProvider // Cached value loaded from the token store or set by a previous server // response, and sent in each subsequent network request. - string16 access_token_; + base::string16 access_token_; // The current best position estimate. Geoposition position_; @@ -138,7 +138,7 @@ CONTENT_EXPORT LocationProviderBase* NewNetworkLocationProvider( AccessTokenStore* access_token_store, net::URLRequestContextGetter* context, const GURL& url, - const string16& access_token); + const base::string16& access_token); } // namespace content diff --git a/content/browser/geolocation/network_location_request.cc b/content/browser/geolocation/network_location_request.cc index 2e269b38a6..3ed709218f 100644 --- a/content/browser/geolocation/network_location_request.cc +++ b/content/browser/geolocation/network_location_request.cc @@ -72,7 +72,7 @@ GURL FormRequestURL(const GURL& url); void FormUploadData(const WifiData& wifi_data, const base::Time& timestamp, - const string16& access_token, + const base::string16& access_token, std::string* upload_data); // Attempts to extract a position from the response. Detects and indicates @@ -83,7 +83,7 @@ void GetLocationFromResponse(bool http_post_result, const base::Time& timestamp, const GURL& server_url, Geoposition* position, - string16* access_token); + base::string16* access_token); // Parses the server response body. Returns true if parsing was successful. // Sets |*position| to the parsed location if a valid fix was received, @@ -91,7 +91,7 @@ void GetLocationFromResponse(bool http_post_result, bool ParseServerResponse(const std::string& response_body, const base::Time& timestamp, Geoposition* position, - string16* access_token); + base::string16* access_token); void AddWifiData(const WifiData& wifi_data, int age_milliseconds, base::DictionaryValue* request); @@ -111,7 +111,7 @@ NetworkLocationRequest::NetworkLocationRequest( NetworkLocationRequest::~NetworkLocationRequest() { } -bool NetworkLocationRequest::MakeRequest(const string16& access_token, +bool NetworkLocationRequest::MakeRequest(const base::string16& access_token, const WifiData& wifi_data, const base::Time& timestamp) { RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_REQUEST_START); @@ -150,7 +150,7 @@ void NetworkLocationRequest::OnURLFetchComplete( RecordUmaResponseCode(response_code); Geoposition position; - string16 access_token; + base::string16 access_token; std::string data; source->GetResponseAsString(&data); GetLocationFromResponse(status.is_success(), @@ -207,7 +207,7 @@ GURL FormRequestURL(const GURL& url) { void FormUploadData(const WifiData& wifi_data, const base::Time& timestamp, - const string16& access_token, + const base::string16& access_token, std::string* upload_data) { int age = kint32min; // Invalid so AddInteger() will ignore. if (!timestamp.is_null()) { @@ -291,7 +291,7 @@ void GetLocationFromResponse(bool http_post_result, const base::Time& timestamp, const GURL& server_url, Geoposition* position, - string16* access_token) { + base::string16* access_token) { DCHECK(position); DCHECK(access_token); @@ -351,7 +351,7 @@ bool GetAsDouble(const base::DictionaryValue& object, bool ParseServerResponse(const std::string& response_body, const base::Time& timestamp, Geoposition* position, - string16* access_token) { + base::string16* access_token) { DCHECK(position); DCHECK(!position->Validate()); DCHECK(position->error_code == Geoposition::ERROR_CODE_NONE); diff --git a/content/browser/geolocation/network_location_request.h b/content/browser/geolocation/network_location_request.h index 38aaf3e6ce..6fea08b8bd 100644 --- a/content/browser/geolocation/network_location_request.h +++ b/content/browser/geolocation/network_location_request.h @@ -33,7 +33,7 @@ class NetworkLocationRequest : private net::URLFetcherDelegate { // server or network error - either no response or a 500 error code. typedef base::Callback<void(const Geoposition& /* position */, bool /* server_error */, - const string16& /* access_token */, + const base::string16& /* access_token */, const WifiData& /* wifi_data */)> LocationResponseCallback; @@ -45,7 +45,7 @@ class NetworkLocationRequest : private net::URLFetcherDelegate { // Makes a new request. Returns true if the new request was successfully // started. In all cases, any currently pending request will be canceled. - bool MakeRequest(const string16& access_token, + bool MakeRequest(const base::string16& access_token, const WifiData& wifi_data, const base::Time& timestamp); diff --git a/content/browser/geolocation/wifi_data.h b/content/browser/geolocation/wifi_data.h index a24e42e2ac..72bc3065ab 100644 --- a/content/browser/geolocation/wifi_data.h +++ b/content/browser/geolocation/wifi_data.h @@ -19,11 +19,11 @@ struct CONTENT_EXPORT AccessPointData { ~AccessPointData(); // MAC address, formatted as per MacAddressAsString16. - string16 mac_address; + base::string16 mac_address; int radio_signal_strength; // Measured in dBm int channel; int signal_to_noise; // Ratio in dB - string16 ssid; // Network identifier + base::string16 ssid; // Network identifier }; // This is to allow AccessPointData to be used in std::set. We order diff --git a/content/browser/geolocation/wifi_data_provider_common.cc b/content/browser/geolocation/wifi_data_provider_common.cc index 31f969c3a3..9c2cbae234 100644 --- a/content/browser/geolocation/wifi_data_provider_common.cc +++ b/content/browser/geolocation/wifi_data_provider_common.cc @@ -10,7 +10,7 @@ namespace content { -string16 MacAddressAsString16(const uint8 mac_as_int[6]) { +base::string16 MacAddressAsString16(const uint8 mac_as_int[6]) { // mac_as_int is big-endian. Write in byte chunks. // Format is XX-XX-XX-XX-XX-XX. static const char* const kMacFormatString = diff --git a/content/browser/geolocation/wifi_data_provider_common.h b/content/browser/geolocation/wifi_data_provider_common.h index c42b4c2a85..befdb69211 100644 --- a/content/browser/geolocation/wifi_data_provider_common.h +++ b/content/browser/geolocation/wifi_data_provider_common.h @@ -18,7 +18,7 @@ namespace content { // Converts a MAC address stored as an array of uint8 to a string. -string16 MacAddressAsString16(const uint8 mac_as_int[6]); +base::string16 MacAddressAsString16(const uint8 mac_as_int[6]); // Base class to promote code sharing between platform specific wifi data // providers. It's optional for specific platforms to derive this, but if they diff --git a/content/browser/geolocation/wifi_data_provider_win.cc b/content/browser/geolocation/wifi_data_provider_win.cc index 8efb191845..ed69865fbd 100644 --- a/content/browser/geolocation/wifi_data_provider_win.cc +++ b/content/browser/geolocation/wifi_data_provider_win.cc @@ -127,15 +127,15 @@ class WindowsNdisApi : public WifiDataProviderCommon::WlanApiInterface { private: static bool GetInterfacesNDIS( - std::vector<string16>* interface_service_names_out); + std::vector<base::string16>* interface_service_names_out); // Swaps in content of the vector passed - explicit WindowsNdisApi(std::vector<string16>* interface_service_names); + explicit WindowsNdisApi(std::vector<base::string16>* interface_service_names); bool GetInterfaceDataNDIS(HANDLE adapter_handle, WifiData::AccessPointDataSet* data); // NDIS variables. - std::vector<string16> interface_service_names_; + std::vector<base::string16> interface_service_names_; // Remembers scan result buffer size across calls. int oid_buffer_size_; @@ -144,9 +144,9 @@ class WindowsNdisApi : public WifiDataProviderCommon::WlanApiInterface { // Extracts data for an access point and converts to Gears format. bool GetNetworkData(const WLAN_BSS_ENTRY& bss_entry, AccessPointData* access_point_data); -bool UndefineDosDevice(const string16& device_name); -bool DefineDosDeviceIfNotExists(const string16& device_name); -HANDLE GetFileHandle(const string16& device_name); +bool UndefineDosDevice(const base::string16& device_name); +bool DefineDosDeviceIfNotExists(const base::string16& device_name); +HANDLE GetFileHandle(const base::string16& device_name); // Makes the OID query and returns a Win32 error code. int PerformQuery(HANDLE adapter_handle, BYTE* buffer, @@ -155,7 +155,7 @@ int PerformQuery(HANDLE adapter_handle, bool ResizeBuffer(int requested_size, scoped_ptr_malloc<BYTE>* buffer); // Gets the system directory and appends a trailing slash if not already // present. -bool GetSystemDirectory(string16* path); +bool GetSystemDirectory(base::string16* path); } // namespace WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() { @@ -202,12 +202,12 @@ WindowsWlanApi* WindowsWlanApi::Create() { if (base::win::GetVersion() < base::win::VERSION_VISTA) return NULL; // We use an absolute path to load the DLL to avoid DLL preloading attacks. - string16 system_directory; + base::string16 system_directory; if (!GetSystemDirectory(&system_directory)) { return NULL; } DCHECK(!system_directory.empty()); - string16 dll_path = system_directory + L"wlanapi.dll"; + base::string16 dll_path = system_directory + L"wlanapi.dll"; HINSTANCE library = LoadLibraryEx(dll_path.c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH); @@ -359,7 +359,7 @@ int WindowsWlanApi::GetInterfaceDataWLAN( // WindowsNdisApi WindowsNdisApi::WindowsNdisApi( - std::vector<string16>* interface_service_names) + std::vector<base::string16>* interface_service_names) : oid_buffer_size_(kInitialBufferSize) { DCHECK(!interface_service_names->empty()); interface_service_names_.swap(*interface_service_names); @@ -369,7 +369,7 @@ WindowsNdisApi::~WindowsNdisApi() { } WindowsNdisApi* WindowsNdisApi::Create() { - std::vector<string16> interface_service_names; + std::vector<base::string16> interface_service_names; if (GetInterfacesNDIS(&interface_service_names)) { return new WindowsNdisApi(&interface_service_names); } @@ -412,7 +412,7 @@ bool WindowsNdisApi::GetAccessPointData(WifiData::AccessPointDataSet* data) { } bool WindowsNdisApi::GetInterfacesNDIS( - std::vector<string16>* interface_service_names_out) { + std::vector<base::string16>* interface_service_names_out) { HKEY network_cards_key = NULL; if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, @@ -530,18 +530,18 @@ bool GetNetworkData(const WLAN_BSS_ENTRY& bss_entry, return true; } -bool UndefineDosDevice(const string16& device_name) { +bool UndefineDosDevice(const base::string16& device_name) { // We remove only the mapping we use, that is \Device\<device_name>. - string16 target_path = L"\\Device\\" + device_name; + base::string16 target_path = L"\\Device\\" + device_name; return DefineDosDevice( DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, device_name.c_str(), target_path.c_str()) == TRUE; } -bool DefineDosDeviceIfNotExists(const string16& device_name) { +bool DefineDosDeviceIfNotExists(const base::string16& device_name) { // We create a DOS device name for the device at \Device\<device_name>. - string16 target_path = L"\\Device\\" + device_name; + base::string16 target_path = L"\\Device\\" + device_name; TCHAR target[kStringLength]; if (QueryDosDevice(device_name.c_str(), target, kStringLength) > 0 && @@ -565,10 +565,10 @@ bool DefineDosDeviceIfNotExists(const string16& device_name) { target_path.compare(target) == 0; } -HANDLE GetFileHandle(const string16& device_name) { +HANDLE GetFileHandle(const base::string16& device_name) { // We access a device with DOS path \Device\<device_name> at // \\.\<device_name>. - string16 formatted_device_name = L"\\\\.\\" + device_name; + base::string16 formatted_device_name = L"\\\\.\\" + device_name; return CreateFile(formatted_device_name.c_str(), GENERIC_READ, @@ -610,7 +610,7 @@ bool ResizeBuffer(int requested_size, scoped_ptr_malloc<BYTE>* buffer) { return buffer != NULL; } -bool GetSystemDirectory(string16* path) { +bool GetSystemDirectory(base::string16* path) { DCHECK(path); // Return value includes terminating NULL. int buffer_size = ::GetSystemDirectory(NULL, 0); diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc index 947499967e..d0ce8b4806 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.cc +++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc @@ -11,9 +11,10 @@ #include "content/browser/gpu/gpu_process_host.h" #include "content/browser/gpu/gpu_surface_tracker.h" #include "content/common/child_process_host_impl.h" -#include "content/common/gpu/client/gpu_memory_buffer_impl.h" +#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h" #include "content/common/gpu/gpu_messages.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/gpu_data_manager.h" #include "content/public/common/content_client.h" #include "ipc/ipc_forwarding_message_filter.h" @@ -134,6 +135,10 @@ void BrowserGpuChannelHostFactory::EstablishRequest::Cancel() { finished_ = true; } +bool BrowserGpuChannelHostFactory::CanUseForTesting() { + return GpuDataManager::GetInstance()->GpuAccessAllowed(NULL); +} + void BrowserGpuChannelHostFactory::Initialize(bool establish_gpu_channel) { DCHECK(!instance_); instance_ = new BrowserGpuChannelHostFactory(establish_gpu_channel); @@ -355,7 +360,6 @@ void BrowserGpuChannelHostFactory::GpuChannelEstablished() { GetContentClient()->SetGpuInfo(pending_request_->gpu_info()); gpu_channel_ = GpuChannelHost::Create(this, pending_request_->gpu_host_id(), - gpu_client_id_, pending_request_->gpu_info(), pending_request_->channel_handle()); gpu_host_id_ = pending_request_->gpu_host_id(); @@ -381,11 +385,12 @@ scoped_ptr<gfx::GpuMemoryBuffer> if (!shm->CreateAnonymous(size)) return scoped_ptr<gfx::GpuMemoryBuffer>(); - return make_scoped_ptr<gfx::GpuMemoryBuffer>( - new GpuMemoryBufferImpl(shm.Pass(), - width, - height, - internalformat)); + scoped_ptr<GpuMemoryBufferImplShm> buffer( + new GpuMemoryBufferImplShm(gfx::Size(width, height), internalformat)); + if (!buffer->InitializeFromSharedMemory(shm.Pass())) + return scoped_ptr<gfx::GpuMemoryBuffer>(); + + return buffer.PassAs<gfx::GpuMemoryBuffer>(); } // static diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.h b/content/browser/gpu/browser_gpu_channel_host_factory.h index 6f09e1429b..8b461e4aec 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.h +++ b/content/browser/gpu/browser_gpu_channel_host_factory.h @@ -57,6 +57,10 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory void EstablishGpuChannel(CauseForGpuLaunch cause_for_gpu_launch, const base::Closure& callback); GpuChannelHost* GetGpuChannel(); + int GetGpuChannelId() { return gpu_client_id_; } + + // Used to skip GpuChannelHost tests when there can be no GPU process. + static bool CanUseForTesting(); private: struct CreateRequest { @@ -90,7 +94,7 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory base::WaitableEvent event_; CauseForGpuLaunch cause_for_gpu_launch_; - int gpu_client_id_; + const int gpu_client_id_; int gpu_host_id_; bool reused_gpu_process_; IPC::ChannelHandle channel_handle_; @@ -121,7 +125,7 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory int gpu_host_id, scoped_refptr<IPC::ChannelProxy::MessageFilter> filter); - int gpu_client_id_; + const int gpu_client_id_; scoped_ptr<base::WaitableEvent> shutdown_event_; scoped_refptr<GpuChannelHost> gpu_channel_; int gpu_host_id_; diff --git a/content/browser/gpu/compositor_util.cc b/content/browser/gpu/compositor_util.cc index 916fcdec54..73af1304a4 100644 --- a/content/browser/gpu/compositor_util.cc +++ b/content/browser/gpu/compositor_util.cc @@ -24,14 +24,6 @@ struct GpuFeatureInfo { bool fallback_to_software; }; -// Determine if accelerated-2d-canvas is supported, which depends on whether -// lose_context could happen. -bool SupportsAccelerated2dCanvas() { - if (GpuDataManagerImpl::GetInstance()->GetGPUInfo().can_lose_context) - return false; - return true; -} - #if defined(OS_CHROMEOS) const size_t kNumFeatures = 14; #else @@ -47,7 +39,8 @@ const GpuFeatureInfo GetGpuFeatureInfo(size_t index) { manager->IsFeatureBlacklisted( gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS), command_line.HasSwitch(switches::kDisableAccelerated2dCanvas) || - !SupportsAccelerated2dCanvas(), + !GpuDataManagerImpl::GetInstance()-> + GetGPUInfo().SupportsAccelerated2dCanvas(), "Accelerated 2D canvas is unavailable: either disabled at the command" " line or not supported by the current system.", true @@ -140,6 +133,17 @@ const GpuFeatureInfo GetGpuFeatureInfo(size_t index) { " or command line.", true }, +#if defined(ENABLE_WEBRTC) + { + "video_encode", + manager->IsFeatureBlacklisted( + gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE), + command_line.HasSwitch(switches::kDisableWebRtcHWEncoding), + "Accelerated video encode has been disabled, either via about:flags" + " or command line.", + true + }, +#endif { "video", manager->IsFeatureBlacklisted( diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc index b5b44ffdbb..86b63b4908 100644 --- a/content/browser/gpu/gpu_data_manager_impl_private.cc +++ b/content/browser/gpu/gpu_data_manager_impl_private.cc @@ -198,21 +198,6 @@ void UpdateStats(const gpu::GPUInfo& gpu_info, gpu_info.gl_reset_notification_strategy); } -// Strip out the non-digital info; if after that, we get an empty string, -// return "0". -std::string ProcessVersionString(const std::string& raw_string) { - const std::string valid_set = "0123456789."; - size_t start_pos = raw_string.find_first_of(valid_set); - if (start_pos == std::string::npos) - return "0"; - size_t end_pos = raw_string.find_first_not_of(raw_string, start_pos); - std::string version_string = raw_string.substr( - start_pos, end_pos - start_pos); - if (version_string.empty()) - return "0"; - return version_string; -} - // Combine the integers into a string, seperated by ','. std::string IntSetToString(const std::set<int>& list) { std::string rt; @@ -646,6 +631,11 @@ void GpuDataManagerImplPrivate::AppendRendererCommandLine( if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) && !command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode); +#if defined(ENABLE_WEBRTC) + if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE) && + !command_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) + command_line->AppendSwitch(switches::kDisableWebRtcHWEncoding); +#endif if (use_software_compositor_ && !command_line->HasSwitch(switches::kEnableSoftwareCompositing)) @@ -713,6 +703,12 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine( !command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) { command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode); } +#if defined(ENABLE_WEBRTC) + if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE) && + !command_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) { + command_line->AppendSwitch(switches::kDisableWebRtcHWEncoding); + } +#endif #if defined(OS_WIN) // DisplayLink 7.1 and earlier can cause the GPU process to crash on startup. @@ -999,10 +995,6 @@ void GpuDataManagerImplPrivate::InitializeImpl( const std::string& gpu_blacklist_json, const std::string& gpu_driver_bug_list_json, const gpu::GPUInfo& gpu_info) { - std::string browser_version_string = ProcessVersionString( - GetContentClient()->GetProduct()); - CHECK(!browser_version_string.empty()); - const bool log_gpu_control_list_decisions = CommandLine::ForCurrentProcess()->HasSwitch( switches::kLogGpuControlListDecisions); @@ -1012,8 +1004,7 @@ void GpuDataManagerImplPrivate::InitializeImpl( if (log_gpu_control_list_decisions) gpu_blacklist_->enable_control_list_logging("gpu_blacklist"); bool success = gpu_blacklist_->LoadList( - browser_version_string, gpu_blacklist_json, - gpu::GpuControlList::kCurrentOsOnly); + gpu_blacklist_json, gpu::GpuControlList::kCurrentOsOnly); DCHECK(success); } if (!gpu_driver_bug_list_json.empty()) { @@ -1021,8 +1012,7 @@ void GpuDataManagerImplPrivate::InitializeImpl( if (log_gpu_control_list_decisions) gpu_driver_bug_list_->enable_control_list_logging("gpu_driver_bug_list"); bool success = gpu_driver_bug_list_->LoadList( - browser_version_string, gpu_driver_bug_list_json, - gpu::GpuControlList::kCurrentOsOnly); + gpu_driver_bug_list_json, gpu::GpuControlList::kCurrentOsOnly); DCHECK(success); } diff --git a/content/browser/gpu/gpu_ipc_browsertests.cc b/content/browser/gpu/gpu_ipc_browsertests.cc index f41160d761..ca2ccf9ee0 100644 --- a/content/browser/gpu/gpu_ipc_browsertests.cc +++ b/content/browser/gpu/gpu_ipc_browsertests.cc @@ -10,6 +10,7 @@ #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" #include "content/common/gpu/gpu_process_launch_causes.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/gpu_data_manager.h" #include "content/public/common/content_switches.h" #include "content/test/content_browser_test.h" #include "ui/gl/gl_switches.h" @@ -22,6 +23,9 @@ using content::WebGraphicsContext3DCommandBufferImpl; class ContextTestBase : public content::ContentBrowserTest { public: virtual void SetUpOnMainThread() OVERRIDE { + if (!content::BrowserGpuChannelHostFactory::CanUseForTesting()) + return; + if (!content::BrowserGpuChannelHostFactory::instance()) content::BrowserGpuChannelHostFactory::Initialize(true); @@ -66,6 +70,9 @@ namespace content { class BrowserGpuChannelHostFactoryTest : public ContextTestBase { public: virtual void SetUpOnMainThread() OVERRIDE { + if (!content::BrowserGpuChannelHostFactory::CanUseForTesting()) + return; + // Start all tests without a gpu channel so that the tests exercise a // consistent codepath. if (!content::BrowserGpuChannelHostFactory::instance()) @@ -128,6 +135,9 @@ class BrowserGpuChannelHostFactoryTest : public ContextTestBase { }; IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, Basic) { + if (!context_) + return; + DCHECK(!IsChannelEstablished()); EstablishAndWait(); EXPECT_TRUE(GetGpuChannel() != NULL); @@ -135,6 +145,9 @@ IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, Basic) { IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, EstablishAndTerminate) { + if (!context_) + return; + DCHECK(!IsChannelEstablished()); base::RunLoop run_loop; GetFactory()->EstablishGpuChannel( @@ -147,6 +160,9 @@ IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, } IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, AlreadyEstablished) { + if (!context_) + return; + DCHECK(!IsChannelEstablished()); scoped_refptr<GpuChannelHost> gpu_channel = GetFactory()->EstablishGpuChannelSync( @@ -162,6 +178,9 @@ IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, AlreadyEstablished) { } IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, CrashAndRecover) { + if (!context_) + return; + DCHECK(!IsChannelEstablished()); EstablishAndWait(); scoped_refptr<GpuChannelHost> host = GetGpuChannel(); diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 26b33d45c9..1b7da1c8d7 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc @@ -48,6 +48,10 @@ #include "ui/surface/accelerated_surface_win.h" #endif +#if defined(USE_OZONE) +#include "ui/ozone/ozone_switches.h" +#endif + namespace content { bool GpuProcessHost::gpu_enabled_ = true; @@ -252,7 +256,7 @@ class GpuSandboxedProcessLauncherDelegate #endif if (cmd_line_->HasSwitch(switches::kEnableLogging)) { - string16 log_file_path = logging::GetLogFileFullPath(); + base::string16 log_file_path = logging::GetLogFileFullPath(); if (!log_file_path.empty()) { result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, sandbox::TargetPolicy::FILES_ALLOW_ANY, @@ -1112,6 +1116,9 @@ bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) { switches::kDisableImageTransportSurface, switches::kDisableLogging, switches::kDisableSeccompFilterSandbox, +#if defined(ENABLE_WEBRTC) + switches::kDisableWebRtcHWEncoding, +#endif switches::kEnableLogging, switches::kEnableShareGroupAsyncTextureUpload, switches::kGpuStartupDialog, @@ -1129,6 +1136,9 @@ bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) { #if defined(USE_AURA) switches::kUIPrioritizeInGpuProcess, #endif +#if defined(USE_OZONE) + switches::kOzonePlatform, +#endif }; cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames, arraysize(kSwitchNames)); diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc index ae40d22846..e08a7b3c56 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_backing_store.cc @@ -157,7 +157,7 @@ static void PutVarInt(LevelDBTransaction* transaction, template <typename DBOrTransaction> WARN_UNUSED_RESULT static bool GetString(DBOrTransaction* db, const StringPiece& key, - string16* found_string, + base::string16* found_string, bool* found) { std::string result; *found = false; @@ -172,7 +172,7 @@ WARN_UNUSED_RESULT static bool GetString(DBOrTransaction* db, static void PutString(LevelDBTransaction* transaction, const StringPiece& key, - const string16& value) { + const base::string16& value) { std::string buffer; EncodeString(value, &buffer); transaction->Put(key, &buffer); @@ -513,7 +513,7 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII, origin_url); } - if (!file_util::CreateDirectory(path_base)) { + if (!base::CreateDirectory(path_base)) { LOG(ERROR) << "Unable to create IndexedDB database path " << path_base.AsUTF8Unsafe(); HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY, @@ -653,8 +653,8 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create( return backing_store; } -std::vector<string16> IndexedDBBackingStore::GetDatabaseNames() { - std::vector<string16> found_names; +std::vector<base::string16> IndexedDBBackingStore::GetDatabaseNames() { + std::vector<base::string16> found_names; const std::string start_key = DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_); const std::string stop_key = @@ -678,7 +678,7 @@ std::vector<string16> IndexedDBBackingStore::GetDatabaseNames() { } bool IndexedDBBackingStore::GetIDBDatabaseMetaData( - const string16& name, + const base::string16& name, IndexedDBDatabaseMetadata* metadata, bool* found) { const std::string key = DatabaseNameKey::Encode(origin_identifier_, name); @@ -755,10 +755,11 @@ WARN_UNUSED_RESULT static bool GetNewDatabaseId(LevelDBTransaction* transaction, return true; } -bool IndexedDBBackingStore::CreateIDBDatabaseMetaData(const string16& name, - const string16& version, - int64 int_version, - int64* row_id) { +bool IndexedDBBackingStore::CreateIDBDatabaseMetaData( + const base::string16& name, + const base::string16& version, + int64 int_version, + int64* row_id) { scoped_refptr<LevelDBTransaction> transaction = new LevelDBTransaction(db_.get()); @@ -811,7 +812,7 @@ static void DeleteRange(LevelDBTransaction* transaction, transaction->Remove(it->Key()); } -bool IndexedDBBackingStore::DeleteDatabase(const string16& name) { +bool IndexedDBBackingStore::DeleteDatabase(const base::string16& name) { IDB_TRACE("IndexedDBBackingStore::DeleteDatabase"); scoped_ptr<LevelDBWriteOnlyTransaction> transaction = LevelDBWriteOnlyTransaction::Create(db_.get()); @@ -895,7 +896,7 @@ bool IndexedDBBackingStore::GetObjectStores( // TODO(jsbell): Do this by direct key lookup rather than iteration, to // simplify. - string16 object_store_name; + base::string16 object_store_name; { StringPiece slice(it->Value()); if (!DecodeString(&slice, &object_store_name) || !slice.empty()) @@ -1049,7 +1050,7 @@ bool IndexedDBBackingStore::CreateObjectStore( IndexedDBBackingStore::Transaction* transaction, int64 database_id, int64 object_store_id, - const string16& name, + const base::string16& name, const IndexedDBKeyPath& key_path, bool auto_increment) { IDB_TRACE("IndexedDBBackingStore::CreateObjectStore"); @@ -1103,7 +1104,7 @@ bool IndexedDBBackingStore::DeleteObjectStore( return false; LevelDBTransaction* leveldb_transaction = transaction->transaction(); - string16 object_store_name; + base::string16 object_store_name; bool found = false; bool ok = GetString( leveldb_transaction, @@ -1473,7 +1474,7 @@ bool IndexedDBBackingStore::GetIndexes( // TODO(jsbell): Do this by direct key lookup rather than iteration, to // simplify. int64 index_id = meta_data_key.IndexId(); - string16 index_name; + base::string16 index_name; { StringPiece slice(it->Value()); if (!DecodeString(&slice, &index_name) || !slice.empty()) @@ -1553,7 +1554,7 @@ bool IndexedDBBackingStore::CreateIndex( int64 database_id, int64 object_store_id, int64 index_id, - const string16& name, + const base::string16& name, const IndexedDBKeyPath& key_path, bool is_unique, bool is_multi_entry) { @@ -2022,7 +2023,7 @@ class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor { } // IndexedDBBackingStore::Cursor - virtual std::string* Value() OVERRIDE { + virtual std::string* value() OVERRIDE { NOTREACHED(); return NULL; } @@ -2079,7 +2080,7 @@ class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor { virtual Cursor* Clone() OVERRIDE { return new ObjectStoreCursorImpl(this); } // IndexedDBBackingStore::Cursor - virtual std::string* Value() OVERRIDE { return ¤t_value_; } + virtual std::string* value() OVERRIDE { return ¤t_value_; } virtual bool LoadCurrentRow() OVERRIDE; protected: @@ -2137,15 +2138,15 @@ class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor { virtual Cursor* Clone() OVERRIDE { return new IndexKeyCursorImpl(this); } // IndexedDBBackingStore::Cursor - virtual std::string* Value() OVERRIDE { + virtual std::string* value() OVERRIDE { NOTREACHED(); return NULL; } virtual const IndexedDBKey& primary_key() const OVERRIDE { return *primary_key_; } - virtual const IndexedDBBackingStore::RecordIdentifier& RecordIdentifier() - const { + virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier() + const OVERRIDE { NOTREACHED(); return record_identifier_; } @@ -2244,12 +2245,12 @@ class IndexCursorImpl : public IndexedDBBackingStore::Cursor { virtual Cursor* Clone() OVERRIDE { return new IndexCursorImpl(this); } // IndexedDBBackingStore::Cursor - virtual std::string* Value() OVERRIDE { return ¤t_value_; } + virtual std::string* value() OVERRIDE { return ¤t_value_; } virtual const IndexedDBKey& primary_key() const OVERRIDE { return *primary_key_; } - virtual const IndexedDBBackingStore::RecordIdentifier& RecordIdentifier() - const { + virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier() + const OVERRIDE { NOTREACHED(); return record_identifier_; } diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h index 9ea71f11ac..890f95ebdf 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.h +++ b/content/browser/indexed_db/indexed_db_backing_store.h @@ -69,19 +69,19 @@ class CONTENT_EXPORT IndexedDBBackingStore const GURL& origin_url, LevelDBFactory* factory); - virtual std::vector<string16> GetDatabaseNames(); - virtual bool GetIDBDatabaseMetaData(const string16& name, + virtual std::vector<base::string16> GetDatabaseNames(); + virtual bool GetIDBDatabaseMetaData(const base::string16& name, IndexedDBDatabaseMetadata* metadata, bool* success) WARN_UNUSED_RESULT; - virtual bool CreateIDBDatabaseMetaData(const string16& name, - const string16& version, + virtual bool CreateIDBDatabaseMetaData(const base::string16& name, + const base::string16& version, int64 int_version, int64* row_id); virtual bool UpdateIDBDatabaseIntVersion( IndexedDBBackingStore::Transaction* transaction, int64 row_id, int64 int_version); - virtual bool DeleteDatabase(const string16& name); + virtual bool DeleteDatabase(const base::string16& name); bool GetObjectStores(int64 database_id, IndexedDBDatabaseMetadata::ObjectStoreMap* map) @@ -90,7 +90,7 @@ class CONTENT_EXPORT IndexedDBBackingStore IndexedDBBackingStore::Transaction* transaction, int64 database_id, int64 object_store_id, - const string16& name, + const base::string16& name, const IndexedDBKeyPath& key_path, bool auto_increment); virtual bool DeleteObjectStore( @@ -160,7 +160,7 @@ class CONTENT_EXPORT IndexedDBBackingStore int64 database_id, int64 object_store_id, int64 index_id, - const string16& name, + const base::string16& name, const IndexedDBKeyPath& key_path, bool is_unique, bool is_multi_entry) WARN_UNUSED_RESULT; @@ -226,7 +226,7 @@ class CONTENT_EXPORT IndexedDBBackingStore virtual Cursor* Clone() = 0; virtual const IndexedDBKey& primary_key() const; - virtual std::string* Value() = 0; + virtual std::string* value() = 0; virtual const RecordIdentifier& record_identifier() const; virtual bool LoadCurrentRow() = 0; @@ -279,10 +279,10 @@ class CONTENT_EXPORT IndexedDBBackingStore class Transaction { public: explicit Transaction(IndexedDBBackingStore* backing_store); - ~Transaction(); - void Begin(); - bool Commit(); - void Rollback(); + virtual ~Transaction(); + virtual void Begin(); + virtual bool Commit(); + virtual void Rollback(); void Reset() { backing_store_ = NULL; transaction_ = NULL; diff --git a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc index 396189e519..d3e82964af 100644 --- a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc +++ b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc @@ -236,19 +236,19 @@ TEST_F(IndexedDBBackingStoreTest, InvalidIds) { } TEST_F(IndexedDBBackingStoreTest, CreateDatabase) { - const string16 database_name(ASCIIToUTF16("db1")); + const base::string16 database_name(ASCIIToUTF16("db1")); int64 database_id; - const string16 version(ASCIIToUTF16("old_string_version")); + const base::string16 version(ASCIIToUTF16("old_string_version")); const int64 int_version = 9; const int64 object_store_id = 99; - const string16 object_store_name(ASCIIToUTF16("object_store1")); + const base::string16 object_store_name(ASCIIToUTF16("object_store1")); const bool auto_increment = true; const IndexedDBKeyPath object_store_key_path( ASCIIToUTF16("object_store_key")); const int64 index_id = 999; - const string16 index_name(ASCIIToUTF16("index1")); + const base::string16 index_name(ASCIIToUTF16("index1")); const bool unique = true; const bool multi_entry = true; const IndexedDBKeyPath index_key_path(ASCIIToUTF16("index_key")); diff --git a/content/browser/indexed_db/indexed_db_browsertest.cc b/content/browser/indexed_db/indexed_db_browsertest.cc index 9fca832cc2..e979168e76 100644 --- a/content/browser/indexed_db/indexed_db_browsertest.cc +++ b/content/browser/indexed_db/indexed_db_browsertest.cc @@ -66,7 +66,7 @@ class IndexedDBBrowserTest : public ContentBrowserTest { if (hash) url = GURL(url.spec() + hash); - string16 expected_title16(ASCIIToUTF16(expected_string)); + base::string16 expected_title16(ASCIIToUTF16(expected_string)); TitleWatcher title_watcher(shell->web_contents(), expected_title16); NavigateToURL(shell, url); EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); @@ -234,7 +234,7 @@ static void CopyLevelDBToProfile(Shell* shell, // If we don't create the destination directory first, the contents of the // leveldb directory are copied directly into profile/IndexedDB instead of // profile/IndexedDB/file__0.xxx/ - ASSERT_TRUE(file_util::CreateDirectory(dest)); + ASSERT_TRUE(base::CreateDirectory(dest)); const bool kRecursive = true; ASSERT_TRUE(base::CopyDirectory(test_data_dir, context->data_path(), @@ -342,7 +342,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, LevelDBLogFileTest) { base::FilePath log_file_path = GetContext()->data_path().Append(leveldb_dir).Append(log_file); int64 size; - EXPECT_TRUE(file_util::GetFileSize(log_file_path, &size)); + EXPECT_TRUE(base::GetFileSize(log_file_path, &size)); EXPECT_GT(size, 0); } @@ -399,7 +399,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ConnectionsClosedOnTabClose) { NavigateAndWaitForTitle(new_shell, "version_change_blocked.html", "#tab2", "setVersion(3) blocked"); - string16 expected_title16(ASCIIToUTF16("setVersion(3) complete")); + base::string16 expected_title16(ASCIIToUTF16("setVersion(3) complete")); TitleWatcher title_watcher(new_shell->web_contents(), expected_title16); base::KillProcess( @@ -421,7 +421,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ForceCloseEventTest) { GetContext(), GURL("file:///"))); - string16 expected_title16(ASCIIToUTF16("connection closed")); + base::string16 expected_title16(ASCIIToUTF16("connection closed")); TitleWatcher title_watcher(shell()->web_contents(), expected_title16); EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); } diff --git a/content/browser/indexed_db/indexed_db_callbacks.cc b/content/browser/indexed_db/indexed_db_callbacks.cc index 587b66f066..755551cec8 100644 --- a/content/browser/indexed_db/indexed_db_callbacks.cc +++ b/content/browser/indexed_db/indexed_db_callbacks.cc @@ -71,7 +71,7 @@ void IndexedDBCallbacks::OnError(const IndexedDBDatabaseError& error) { dispatcher_host_ = NULL; } -void IndexedDBCallbacks::OnSuccess(const std::vector<string16>& value) { +void IndexedDBCallbacks::OnSuccess(const std::vector<base::string16>& value) { DCHECK(dispatcher_host_.get()); DCHECK_EQ(kNoCursor, ipc_cursor_id_); @@ -79,7 +79,7 @@ void IndexedDBCallbacks::OnSuccess(const std::vector<string16>& value) { DCHECK_EQ(kNoDatabase, ipc_database_id_); DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); - std::vector<string16> list; + std::vector<base::string16> list; for (unsigned i = 0; i < value.size(); ++i) list.push_back(value[i]); diff --git a/content/browser/indexed_db/indexed_db_callbacks.h b/content/browser/indexed_db/indexed_db_callbacks.h index 1ea0c0b4af..048b563bf2 100644 --- a/content/browser/indexed_db/indexed_db_callbacks.h +++ b/content/browser/indexed_db/indexed_db_callbacks.h @@ -51,7 +51,7 @@ class CONTENT_EXPORT IndexedDBCallbacks virtual void OnError(const IndexedDBDatabaseError& error); // IndexedDBFactory::GetDatabaseNames - virtual void OnSuccess(const std::vector<string16>& string); + virtual void OnSuccess(const std::vector<base::string16>& string); // IndexedDBFactory::Open / DeleteDatabase virtual void OnBlocked(int64 existing_version); diff --git a/content/browser/indexed_db/indexed_db_context_impl.cc b/content/browser/indexed_db/indexed_db_context_impl.cc index 37548c8ff7..e8ab70bbbf 100644 --- a/content/browser/indexed_db/indexed_db_context_impl.cc +++ b/content/browser/indexed_db/indexed_db_context_impl.cc @@ -23,6 +23,7 @@ #include "content/browser/indexed_db/indexed_db_dispatcher_host.h" #include "content/browser/indexed_db/indexed_db_factory.h" #include "content/browser/indexed_db/indexed_db_quota_client.h" +#include "content/browser/indexed_db/indexed_db_tracing.h" #include "content/browser/indexed_db/indexed_db_transaction.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/indexed_db_info.h" @@ -106,6 +107,7 @@ IndexedDBContextImpl::IndexedDBContextImpl( special_storage_policy_(special_storage_policy), quota_manager_proxy_(quota_manager_proxy), task_runner_(task_runner) { + IDB_TRACE("init"); if (!data_path.empty()) data_path_ = data_path.Append(kIndexedDBDirectory); if (quota_manager_proxy) { @@ -295,7 +297,7 @@ base::Time IndexedDBContextImpl::GetOriginLastModified(const GURL& origin_url) { return base::Time(); base::FilePath idb_directory = GetFilePath(origin_url); base::PlatformFileInfo file_info; - if (!file_util::GetFileInfo(idb_directory, &file_info)) + if (!base::GetFileInfo(idb_directory, &file_info)) return base::Time(); return file_info.last_modified; } @@ -346,6 +348,8 @@ void IndexedDBContextImpl::ForceClose(const GURL origin_url) { DCHECK_EQ(connections_[origin_url].size(), 0UL); connections_.erase(origin_url); } + if (factory_) + factory_->ForceClose(origin_url); } size_t IndexedDBContextImpl::GetConnectionCount(const GURL& origin_url) { diff --git a/content/browser/indexed_db/indexed_db_cursor.cc b/content/browser/indexed_db/indexed_db_cursor.cc index 5daf16d39d..6d7bc1c2d5 100644 --- a/content/browser/indexed_db/indexed_db_cursor.cc +++ b/content/browser/indexed_db/indexed_db_cursor.cc @@ -128,7 +128,7 @@ void IndexedDBCursor::CursorPrefetchIterationOperation( break; case indexed_db::CURSOR_KEY_AND_VALUE: { std::string value; - value.swap(*cursor_->Value()); + value.swap(*cursor_->value()); size_estimate += value.size(); found_values.push_back(value); break; diff --git a/content/browser/indexed_db/indexed_db_cursor.h b/content/browser/indexed_db/indexed_db_cursor.h index 5fd86f44b1..f1afc186a7 100644 --- a/content/browser/indexed_db/indexed_db_cursor.h +++ b/content/browser/indexed_db/indexed_db_cursor.h @@ -38,7 +38,7 @@ class CONTENT_EXPORT IndexedDBCursor const IndexedDBKey& primary_key() const { return cursor_->primary_key(); } std::string* Value() const { return (cursor_type_ == indexed_db::CURSOR_KEY_ONLY) ? NULL - : cursor_->Value(); + : cursor_->value(); } void Close(); diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc index 8d63293268..11ef4be8ed 100644 --- a/content/browser/indexed_db/indexed_db_database.cc +++ b/content/browser/indexed_db/indexed_db_database.cc @@ -108,7 +108,7 @@ class IndexedDBDatabase::PendingDeleteCall { }; scoped_refptr<IndexedDBDatabase> IndexedDBDatabase::Create( - const string16& name, + const base::string16& name, IndexedDBBackingStore* backing_store, IndexedDBFactory* factory, const Identifier& unique_identifier) { @@ -128,7 +128,7 @@ bool Contains(const T& container, const U& item) { } } -IndexedDBDatabase::IndexedDBDatabase(const string16& name, +IndexedDBDatabase::IndexedDBDatabase(const base::string16& name, IndexedDBBackingStore* backing_store, IndexedDBFactory* factory, const Identifier& unique_identifier) @@ -273,7 +273,7 @@ bool IndexedDBDatabase::ValidateObjectStoreIdAndNewIndexId( void IndexedDBDatabase::CreateObjectStore(int64 transaction_id, int64 object_store_id, - const string16& name, + const base::string16& name, const IndexedDBKeyPath& key_path, bool auto_increment) { IDB_TRACE("IndexedDBDatabase::CreateObjectStore"); @@ -351,7 +351,7 @@ void IndexedDBDatabase::DeleteObjectStore(int64 transaction_id, void IndexedDBDatabase::CreateIndex(int64 transaction_id, int64 object_store_id, int64 index_id, - const string16& name, + const base::string16& name, const IndexedDBKeyPath& key_path, bool unique, bool multi_entry) { @@ -392,8 +392,9 @@ void IndexedDBDatabase::CreateIndexOperation( index_metadata.key_path, index_metadata.unique, index_metadata.multi_entry)) { - string16 error_string = ASCIIToUTF16("Internal error creating index '") + - index_metadata.name + ASCIIToUTF16("'."); + base::string16 error_string = + ASCIIToUTF16("Internal error creating index '") + + index_metadata.name + ASCIIToUTF16("'."); transaction->Abort(IndexedDBDatabaseError( blink::WebIDBDatabaseExceptionUnknownError, error_string)); return; @@ -446,8 +447,9 @@ void IndexedDBDatabase::DeleteIndexOperation( object_store_id, index_metadata.id); if (!ok) { - string16 error_string = ASCIIToUTF16("Internal error deleting index '") + - index_metadata.name + ASCIIToUTF16("'."); + base::string16 error_string = + ASCIIToUTF16("Internal error deleting index '") + + index_metadata.name + ASCIIToUTF16("'."); transaction->Abort(IndexedDBDatabaseError( blink::WebIDBDatabaseExceptionUnknownError, error_string)); } @@ -791,7 +793,7 @@ void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params, } ScopedVector<IndexWriter> index_writers; - string16 error_message; + base::string16 error_message; bool obeys_constraints = false; bool backing_store_success = MakeIndexWriters(transaction, backing_store_.get(), @@ -897,7 +899,7 @@ void IndexedDBDatabase::SetIndexKeys(int64 transaction_id, } ScopedVector<IndexWriter> index_writers; - string16 error_message; + base::string16 error_message; bool obeys_constraints = false; DCHECK(metadata_.object_stores.find(object_store_id) != metadata_.object_stores.end()); @@ -1219,7 +1221,7 @@ void IndexedDBDatabase::DeleteObjectStoreOperation( transaction->database()->id(), object_store_metadata.id); if (!ok) { - string16 error_string = + base::string16 error_string = ASCIIToUTF16("Internal error deleting object store '") + object_store_metadata.name + ASCIIToUTF16("'."); transaction->Abort(IndexedDBDatabaseError( @@ -1400,8 +1402,14 @@ void IndexedDBDatabase::CreateTransaction( connection->callbacks(), std::set<int64>(object_store_ids.begin(), object_store_ids.end()), static_cast<indexed_db::TransactionMode>(mode), - this); - transactions_[transaction_id] = transaction; + this, + new IndexedDBBackingStore::Transaction(backing_store_)); + TransactionCreated(transaction); +} + +void IndexedDBDatabase::TransactionCreated( + scoped_refptr<IndexedDBTransaction> transaction) { + transactions_[transaction->id()] = transaction; } bool IndexedDBDatabase::IsOpenConnectionBlocked() const { @@ -1449,7 +1457,7 @@ void IndexedDBDatabase::OpenConnection( DCHECK_EQ(IndexedDBDatabaseMetadata::NO_INT_VERSION, metadata_.int_version); } else { - string16 message; + base::string16 message; if (version == IndexedDBDatabaseMetadata::NO_INT_VERSION) message = ASCIIToUTF16( "Internal error opening database with no version specified."); @@ -1714,7 +1722,7 @@ void IndexedDBDatabase::DeleteObjectStoreAbortOperation( } void IndexedDBDatabase::VersionChangeAbortOperation( - const string16& previous_version, + const base::string16& previous_version, int64 previous_int_version, IndexedDBTransaction* transaction) { IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation"); diff --git a/content/browser/indexed_db/indexed_db_database.h b/content/browser/indexed_db/indexed_db_database.h index fa730b0ebf..6297f3dcd6 100644 --- a/content/browser/indexed_db/indexed_db_database.h +++ b/content/browser/indexed_db/indexed_db_database.h @@ -52,7 +52,7 @@ class CONTENT_EXPORT IndexedDBDatabase static const int64 kMinimumIndexId = 30; static scoped_refptr<IndexedDBDatabase> Create( - const string16& name, + const base::string16& name, IndexedDBBackingStore* backing_store, IndexedDBFactory* factory, const Identifier& unique_identifier); @@ -88,7 +88,7 @@ class CONTENT_EXPORT IndexedDBDatabase void CreateObjectStore(int64 transaction_id, int64 object_store_id, - const string16& name, + const base::string16& name, const IndexedDBKeyPath& key_path, bool auto_increment); void DeleteObjectStore(int64 transaction_id, int64 object_store_id); @@ -105,7 +105,7 @@ class CONTENT_EXPORT IndexedDBDatabase void CreateIndex(int64 transaction_id, int64 object_store_id, int64 index_id, - const string16& name, + const base::string16& name, const IndexedDBKeyPath& key_path, bool unique, bool multi_entry); @@ -118,6 +118,7 @@ class CONTENT_EXPORT IndexedDBDatabase return transaction_coordinator_; } + void TransactionCreated(scoped_refptr<IndexedDBTransaction> transaction); void TransactionStarted(IndexedDBTransaction* transaction); void TransactionFinished(IndexedDBTransaction* transaction); void TransactionFinishedAndCompleteFired(IndexedDBTransaction* transaction); @@ -198,7 +199,7 @@ class CONTENT_EXPORT IndexedDBDatabase blink::WebIDBDataLoss data_loss, std::string data_loss_message, IndexedDBTransaction* transaction); - void VersionChangeAbortOperation(const string16& previous_version, + void VersionChangeAbortOperation(const base::string16& previous_version, int64 previous_int_version, IndexedDBTransaction* transaction); void CreateIndexOperation(int64 object_store_id, @@ -243,7 +244,7 @@ class CONTENT_EXPORT IndexedDBDatabase private: friend class base::RefCounted<IndexedDBDatabase>; - IndexedDBDatabase(const string16& name, + IndexedDBDatabase(const base::string16& name, IndexedDBBackingStore* backing_store, IndexedDBFactory* factory, const Identifier& unique_identifier); diff --git a/content/browser/indexed_db/indexed_db_database_error.h b/content/browser/indexed_db/indexed_db_database_error.h index 297bec7be3..1a4f449d81 100644 --- a/content/browser/indexed_db/indexed_db_database_error.h +++ b/content/browser/indexed_db/indexed_db_database_error.h @@ -17,16 +17,16 @@ class IndexedDBDatabaseError { : code_(code) {} IndexedDBDatabaseError(uint16 code, const char* message) : code_(code), message_(ASCIIToUTF16(message)) {} - IndexedDBDatabaseError(uint16 code, const string16& message) + IndexedDBDatabaseError(uint16 code, const base::string16& message) : code_(code), message_(message) {} ~IndexedDBDatabaseError() {} uint16 code() const { return code_; } - const string16& message() const { return message_; } + const base::string16& message() const { return message_; } private: const uint16 code_; - const string16 message_; + const base::string16 message_; }; } // namespace content diff --git a/content/browser/indexed_db/indexed_db_factory.cc b/content/browser/indexed_db/indexed_db_factory.cc index 2cfef62c90..d6883e6188 100644 --- a/content/browser/indexed_db/indexed_db_factory.cc +++ b/content/browser/indexed_db/indexed_db_factory.cc @@ -90,6 +90,11 @@ bool IndexedDBFactory::HasLastBackingStoreReference(const GURL& origin_url) return ptr->HasOneRef(); } +void IndexedDBFactory::ForceClose(const GURL& origin_url) { + if (backing_store_map_.find(origin_url) != backing_store_map_.end()) + ReleaseBackingStore(origin_url, true /* immediate */); +} + void IndexedDBFactory::ContextDestroyed() { // Timers on backing stores hold a reference to this factory. When the // context (which nominally owns this factory) is destroyed during thread @@ -127,10 +132,11 @@ void IndexedDBFactory::GetDatabaseNames( } callbacks->OnSuccess(backing_store->GetDatabaseNames()); + ReleaseBackingStore(origin_url, false /* immediate */); } void IndexedDBFactory::DeleteDatabase( - const string16& name, + const base::string16& name, scoped_refptr<IndexedDBCallbacks> callbacks, const GURL& origin_url, const base::FilePath& data_directory) { @@ -177,6 +183,7 @@ void IndexedDBFactory::DeleteDatabase( database_map_[unique_identifier] = database; database->DeleteDatabase(callbacks); database_map_.erase(unique_identifier); + ReleaseBackingStore(origin_url, false /* immediate */); } void IndexedDBFactory::HandleBackingStoreFailure(const GURL& origin_url) { @@ -191,6 +198,15 @@ bool IndexedDBFactory::IsBackingStoreOpenForTesting(const GURL& origin_url) return backing_store_map_.find(origin_url) != backing_store_map_.end(); } +bool IndexedDBFactory::IsBackingStorePendingCloseForTesting( + const GURL& origin_url) const { + IndexedDBBackingStoreMap::const_iterator it = + backing_store_map_.find(origin_url); + if (it == backing_store_map_.end()) + return false; + return it->second->close_timer()->IsRunning(); +} + scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStore( const GURL& origin_url, const base::FilePath& data_directory, @@ -233,7 +249,7 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStore( } void IndexedDBFactory::Open( - const string16& name, + const base::string16& name, int64 version, int64 transaction_id, scoped_refptr<IndexedDBCallbacks> callbacks, diff --git a/content/browser/indexed_db/indexed_db_factory.h b/content/browser/indexed_db/indexed_db_factory.h index b143853a3a..e27ad69442 100644 --- a/content/browser/indexed_db/indexed_db_factory.h +++ b/content/browser/indexed_db/indexed_db_factory.h @@ -36,7 +36,7 @@ class CONTENT_EXPORT IndexedDBFactory void GetDatabaseNames(scoped_refptr<IndexedDBCallbacks> callbacks, const GURL& origin_url, const base::FilePath& data_directory); - void Open(const string16& name, + void Open(const base::string16& name, int64 version, int64 transaction_id, scoped_refptr<IndexedDBCallbacks> callbacks, @@ -44,7 +44,7 @@ class CONTENT_EXPORT IndexedDBFactory const GURL& origin_url, const base::FilePath& data_directory); - void DeleteDatabase(const string16& name, + void DeleteDatabase(const base::string16& name, scoped_refptr<IndexedDBCallbacks> callbacks, const GURL& origin_url, const base::FilePath& data_directory); @@ -56,6 +56,11 @@ class CONTENT_EXPORT IndexedDBFactory const GURL& origin_url) const; bool IsBackingStoreOpenForTesting(const GURL& origin_url) const; + bool IsBackingStorePendingCloseForTesting(const GURL& origin_url) const; + + // Called by IndexedDBContext after all connections are closed, to + // ensure the backing store closed immediately. + void ForceClose(const GURL& origin_url); // Called by the IndexedDBContext destructor so the factory can do cleanup. void ContextDestroyed(); diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc index 859c2b722d..cb007d521c 100644 --- a/content/browser/indexed_db/indexed_db_factory_unittest.cc +++ b/content/browser/indexed_db/indexed_db_factory_unittest.cc @@ -217,7 +217,7 @@ TEST_F(IndexedDBFactoryTest, QuotaErrorOnDiskFull) { new LookingForQuotaErrorMockCallbacks; scoped_refptr<IndexedDBDatabaseCallbacks> dummy_database_callbacks = new IndexedDBDatabaseCallbacks(NULL, 0, 0); - const string16 name(ASCIIToUTF16("name")); + const base::string16 name(ASCIIToUTF16("name")); factory->Open(name, 1, /* version */ 2, /* transaction_id */ @@ -250,8 +250,12 @@ TEST_F(IndexedDBFactoryTest, BackingStoreReleasedOnForcedClose) { EXPECT_TRUE(callbacks->connection()); EXPECT_TRUE(factory->IsBackingStoreOpenForTesting(origin)); + EXPECT_FALSE(factory->IsBackingStorePendingCloseForTesting(origin)); + callbacks->connection()->ForceClose(); + EXPECT_FALSE(factory->IsBackingStoreOpenForTesting(origin)); + EXPECT_FALSE(factory->IsBackingStorePendingCloseForTesting(origin)); } TEST_F(IndexedDBFactoryTest, BackingStoreReleaseDelayedOnClose) { @@ -283,6 +287,7 @@ TEST_F(IndexedDBFactoryTest, BackingStoreReleaseDelayedOnClose) { callbacks->connection()->Close(); EXPECT_TRUE(store->HasOneRef()); // Factory. EXPECT_TRUE(factory->IsBackingStoreOpenForTesting(origin)); + EXPECT_TRUE(factory->IsBackingStorePendingCloseForTesting(origin)); EXPECT_TRUE(store->close_timer()->IsRunning()); // Take a ref so it won't be destroyed out from under the test. @@ -292,6 +297,98 @@ TEST_F(IndexedDBFactoryTest, BackingStoreReleaseDelayedOnClose) { EXPECT_TRUE(store->HasOneRef()); // Local. EXPECT_FALSE(store->close_timer()->IsRunning()); EXPECT_FALSE(factory->IsBackingStoreOpenForTesting(origin)); + EXPECT_FALSE(factory->IsBackingStorePendingCloseForTesting(origin)); +} + +TEST_F(IndexedDBFactoryTest, DeleteDatabaseClosesBackingStore) { + GURL origin("http://localhost:81"); + + base::ScopedTempDir temp_directory; + ASSERT_TRUE(temp_directory.CreateUniqueTempDir()); + + scoped_refptr<IndexedDBFactory> factory = new IndexedDBFactory(NULL); + EXPECT_FALSE(factory->IsBackingStoreOpenForTesting(origin)); + + const bool expect_connection = false; + scoped_refptr<MockIndexedDBCallbacks> callbacks( + new MockIndexedDBCallbacks(expect_connection)); + factory->DeleteDatabase(ASCIIToUTF16("db"), + callbacks, + origin, + temp_directory.path()); + + EXPECT_TRUE(factory->IsBackingStoreOpenForTesting(origin)); + EXPECT_FALSE(factory->IsBackingStorePendingCloseForTesting(origin)); + + // Now simulate shutdown, which should stop the timer. + factory->ContextDestroyed(); + + EXPECT_FALSE(factory->IsBackingStoreOpenForTesting(origin)); + EXPECT_FALSE(factory->IsBackingStorePendingCloseForTesting(origin)); +} + +TEST_F(IndexedDBFactoryTest, GetDatabaseNamesClosesBackingStore) { + GURL origin("http://localhost:81"); + + base::ScopedTempDir temp_directory; + ASSERT_TRUE(temp_directory.CreateUniqueTempDir()); + + scoped_refptr<IndexedDBFactory> factory = new IndexedDBFactory(NULL); + EXPECT_FALSE(factory->IsBackingStoreOpenForTesting(origin)); + + const bool expect_connection = false; + scoped_refptr<MockIndexedDBCallbacks> callbacks( + new MockIndexedDBCallbacks(expect_connection)); + factory->GetDatabaseNames(callbacks, + origin, + temp_directory.path()); + + EXPECT_TRUE(factory->IsBackingStoreOpenForTesting(origin)); + EXPECT_FALSE(factory->IsBackingStorePendingCloseForTesting(origin)); + + // Now simulate shutdown, which should stop the timer. + factory->ContextDestroyed(); + + EXPECT_FALSE(factory->IsBackingStoreOpenForTesting(origin)); + EXPECT_FALSE(factory->IsBackingStorePendingCloseForTesting(origin)); +} + +TEST_F(IndexedDBFactoryTest, ForceCloseReleasesBackingStore) { + GURL origin("http://localhost:81"); + + base::ScopedTempDir temp_directory; + ASSERT_TRUE(temp_directory.CreateUniqueTempDir()); + + scoped_refptr<IndexedDBFactory> factory = new IndexedDBFactory(NULL); + + scoped_refptr<MockIndexedDBCallbacks> callbacks(new MockIndexedDBCallbacks()); + scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks( + new MockIndexedDBDatabaseCallbacks()); + const int64 transaction_id = 1; + factory->Open(ASCIIToUTF16("db"), + IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION, + transaction_id, + callbacks, + db_callbacks, + origin, + temp_directory.path()); + + EXPECT_TRUE(callbacks->connection()); + EXPECT_TRUE(factory->IsBackingStoreOpenForTesting(origin)); + EXPECT_FALSE(factory->IsBackingStorePendingCloseForTesting(origin)); + + callbacks->connection()->Close(); + + EXPECT_TRUE(factory->IsBackingStoreOpenForTesting(origin)); + EXPECT_TRUE(factory->IsBackingStorePendingCloseForTesting(origin)); + + factory->ForceClose(origin); + + EXPECT_FALSE(factory->IsBackingStoreOpenForTesting(origin)); + EXPECT_FALSE(factory->IsBackingStorePendingCloseForTesting(origin)); + + // Ensure it is safe if the store is not open. + factory->ForceClose(origin); } } // namespace diff --git a/content/browser/indexed_db/indexed_db_fake_backing_store.cc b/content/browser/indexed_db/indexed_db_fake_backing_store.cc index 8766162604..3efd410727 100644 --- a/content/browser/indexed_db/indexed_db_fake_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_fake_backing_store.cc @@ -10,19 +10,19 @@ namespace content { IndexedDBFakeBackingStore::~IndexedDBFakeBackingStore() {} -std::vector<string16> IndexedDBFakeBackingStore::GetDatabaseNames() { - return std::vector<string16>(); +std::vector<base::string16> IndexedDBFakeBackingStore::GetDatabaseNames() { + return std::vector<base::string16>(); } bool IndexedDBFakeBackingStore::GetIDBDatabaseMetaData( - const string16& name, + const base::string16& name, IndexedDBDatabaseMetadata*, bool* found) { return true; } bool IndexedDBFakeBackingStore::CreateIDBDatabaseMetaData( - const string16& name, - const string16& version, + const base::string16& name, + const base::string16& version, int64 int_version, int64* row_id) { return true; @@ -32,14 +32,14 @@ bool IndexedDBFakeBackingStore::UpdateIDBDatabaseIntVersion(Transaction*, int64 version) { return false; } -bool IndexedDBFakeBackingStore::DeleteDatabase(const string16& name) { +bool IndexedDBFakeBackingStore::DeleteDatabase(const base::string16& name) { return true; } bool IndexedDBFakeBackingStore::CreateObjectStore(Transaction*, int64 database_id, int64 object_store_id, - const string16& name, + const base::string16& name, const IndexedDBKeyPath&, bool auto_increment) { return false; @@ -85,7 +85,7 @@ bool IndexedDBFakeBackingStore::CreateIndex(Transaction*, int64 database_id, int64 object_store_id, int64 index_id, - const string16& name, + const base::string16& name, const IndexedDBKeyPath&, bool is_unique, bool is_multi_entry) { @@ -146,4 +146,10 @@ IndexedDBFakeBackingStore::OpenIndexCursor( return scoped_ptr<IndexedDBBackingStore::Cursor>(); } +IndexedDBFakeBackingStore::FakeTransaction::FakeTransaction(bool result) + : IndexedDBBackingStore::Transaction(NULL), result_(result) {} +void IndexedDBFakeBackingStore::FakeTransaction::Begin() {} +bool IndexedDBFakeBackingStore::FakeTransaction::Commit() { return result_; } +void IndexedDBFakeBackingStore::FakeTransaction::Rollback() {} + } // namespace content diff --git a/content/browser/indexed_db/indexed_db_fake_backing_store.h b/content/browser/indexed_db/indexed_db_fake_backing_store.h index 07b63de648..14b956244d 100644 --- a/content/browser/indexed_db/indexed_db_fake_backing_store.h +++ b/content/browser/indexed_db/indexed_db_fake_backing_store.h @@ -17,23 +17,23 @@ class IndexedDBFakeBackingStore : public IndexedDBBackingStore { : IndexedDBBackingStore(GURL("http://localhost:81"), scoped_ptr<LevelDBDatabase>(), scoped_ptr<LevelDBComparator>()) {} - virtual std::vector<string16> GetDatabaseNames() OVERRIDE; - virtual bool GetIDBDatabaseMetaData(const string16& name, + virtual std::vector<base::string16> GetDatabaseNames() OVERRIDE; + virtual bool GetIDBDatabaseMetaData(const base::string16& name, IndexedDBDatabaseMetadata*, bool* found) OVERRIDE; - virtual bool CreateIDBDatabaseMetaData(const string16& name, - const string16& version, + virtual bool CreateIDBDatabaseMetaData(const base::string16& name, + const base::string16& version, int64 int_version, int64* row_id) OVERRIDE; virtual bool UpdateIDBDatabaseIntVersion(Transaction*, int64 row_id, int64 version) OVERRIDE; - virtual bool DeleteDatabase(const string16& name) OVERRIDE; + virtual bool DeleteDatabase(const base::string16& name) OVERRIDE; virtual bool CreateObjectStore(Transaction*, int64 database_id, int64 object_store_id, - const string16& name, + const base::string16& name, const IndexedDBKeyPath&, bool auto_increment) OVERRIDE; @@ -65,7 +65,7 @@ class IndexedDBFakeBackingStore : public IndexedDBBackingStore { int64 database_id, int64 object_store_id, int64 index_id, - const string16& name, + const base::string16& name, const IndexedDBKeyPath&, bool is_unique, bool is_multi_entry) OVERRIDE; @@ -107,6 +107,17 @@ class IndexedDBFakeBackingStore : public IndexedDBBackingStore { indexed_db::CursorDirection) OVERRIDE; + class FakeTransaction : public IndexedDBBackingStore::Transaction { + public: + FakeTransaction(bool result); + virtual void Begin() OVERRIDE; + virtual bool Commit() OVERRIDE; + virtual void Rollback() OVERRIDE; + + private: + bool result_; + }; + protected: friend class base::RefCounted<IndexedDBFakeBackingStore>; virtual ~IndexedDBFakeBackingStore(); diff --git a/content/browser/indexed_db/indexed_db_index_writer.cc b/content/browser/indexed_db/indexed_db_index_writer.cc index 3b36cad0ec..1c2ac0ab5a 100644 --- a/content/browser/indexed_db/indexed_db_index_writer.cc +++ b/content/browser/indexed_db/indexed_db_index_writer.cc @@ -34,7 +34,7 @@ bool IndexWriter::VerifyIndexKeys( int64 index_id, bool* can_add_keys, const IndexedDBKey& primary_key, - string16* error_message) const { + base::string16* error_message) const { *can_add_keys = false; for (size_t i = 0; i < index_keys_.size(); ++i) { bool ok = AddingKeyAllowed(backing_store, @@ -122,7 +122,7 @@ bool MakeIndexWriters( const std::vector<int64>& index_ids, const std::vector<IndexedDBDatabase::IndexKeys>& index_keys, ScopedVector<IndexWriter>* index_writers, - string16* error_message, + base::string16* error_message, bool* completed) { DCHECK_EQ(index_ids.size(), index_keys.size()); *completed = false; diff --git a/content/browser/indexed_db/indexed_db_index_writer.h b/content/browser/indexed_db/indexed_db_index_writer.h index 2ea1c98c8e..8a2cdadee3 100644 --- a/content/browser/indexed_db/indexed_db_index_writer.h +++ b/content/browser/indexed_db/indexed_db_index_writer.h @@ -34,7 +34,7 @@ class IndexWriter { int64 index_id, bool* can_add_keys, const IndexedDBKey& primary_key, - string16* error_message) const WARN_UNUSED_RESULT; + base::string16* error_message) const WARN_UNUSED_RESULT; void WriteIndexKeys(const IndexedDBBackingStore::RecordIdentifier& record, IndexedDBBackingStore* store, @@ -68,7 +68,7 @@ bool MakeIndexWriters( const std::vector<int64>& index_ids, const std::vector<IndexedDBDatabase::IndexKeys>& index_keys, ScopedVector<IndexWriter>* index_writers, - string16* error_message, + base::string16* error_message, bool* completed) WARN_UNUSED_RESULT; } // namespace content diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding.cc b/content/browser/indexed_db/indexed_db_leveldb_coding.cc index dd3964ab44..b6b465f65e 100644 --- a/content/browser/indexed_db/indexed_db_leveldb_coding.cc +++ b/content/browser/indexed_db/indexed_db_leveldb_coding.cc @@ -257,7 +257,7 @@ void EncodeVarInt(int64 value, std::string* into) { } while (n); } -void EncodeString(const string16& value, std::string* into) { +void EncodeString(const base::string16& value, std::string* into) { if (value.empty()) return; // Backing store is UTF-16BE, convert from host endianness. @@ -277,7 +277,7 @@ void EncodeBinary(const std::string& value, std::string* into) { DCHECK(into->size() >= value.size()); } -void EncodeStringWithLength(const string16& value, std::string* into) { +void EncodeStringWithLength(const base::string16& value, std::string* into) { EncodeVarInt(value.length(), into); EncodeString(value, into); } @@ -355,7 +355,7 @@ void EncodeIDBKeyPath(const IndexedDBKeyPath& value, std::string* into) { break; } case WebIDBKeyPathTypeArray: { - const std::vector<string16>& array = value.array(); + const std::vector<base::string16>& array = value.array(); size_t count = array.size(); EncodeVarInt(count, into); for (size_t i = 0; i < count; ++i) { @@ -421,7 +421,7 @@ bool DecodeVarInt(StringPiece* slice, int64* value) { return true; } -bool DecodeString(StringPiece* slice, string16* value) { +bool DecodeString(StringPiece* slice, base::string16* value) { if (slice->empty()) { value->clear(); return true; @@ -430,7 +430,7 @@ bool DecodeString(StringPiece* slice, string16* value) { // Backing store is UTF-16BE, convert to host endianness. DCHECK(!(slice->size() % sizeof(char16))); size_t length = slice->size() / sizeof(char16); - string16 decoded; + base::string16 decoded; decoded.reserve(length); const char16* encoded = reinterpret_cast<const char16*>(slice->begin()); for (unsigned i = 0; i < length; ++i) @@ -441,7 +441,7 @@ bool DecodeString(StringPiece* slice, string16* value) { return true; } -bool DecodeStringWithLength(StringPiece* slice, string16* value) { +bool DecodeStringWithLength(StringPiece* slice, base::string16* value) { if (slice->empty()) return false; @@ -510,7 +510,7 @@ bool DecodeIDBKey(StringPiece* slice, scoped_ptr<IndexedDBKey>* value) { return true; } case kIndexedDBKeyStringTypeByte: { - string16 s; + base::string16 s; if (!DecodeStringWithLength(slice, &s)) return false; *value = make_scoped_ptr(new IndexedDBKey(s)); @@ -551,7 +551,7 @@ bool DecodeIDBKeyPath(StringPiece* slice, IndexedDBKeyPath* value) { // always written as typed. if (slice->size() < 3 || (*slice)[0] != kIndexedDBKeyPathTypeCodedByte1 || (*slice)[1] != kIndexedDBKeyPathTypeCodedByte2) { - string16 s; + base::string16 s; if (!DecodeString(slice, &s)) return false; *value = IndexedDBKeyPath(s); @@ -569,7 +569,7 @@ bool DecodeIDBKeyPath(StringPiece* slice, IndexedDBKeyPath* value) { *value = IndexedDBKeyPath(); return true; case WebIDBKeyPathTypeString: { - string16 string; + base::string16 string; if (!DecodeStringWithLength(slice, &string)) return false; DCHECK(slice->empty()); @@ -577,13 +577,13 @@ bool DecodeIDBKeyPath(StringPiece* slice, IndexedDBKeyPath* value) { return true; } case WebIDBKeyPathTypeArray: { - std::vector<string16> array; + std::vector<base::string16> array; int64 count; if (!DecodeVarInt(slice, &count)) return false; DCHECK_GE(count, 0); while (count--) { - string16 string; + base::string16 string; if (!DecodeStringWithLength(slice, &string)) return false; array.push_back(string); @@ -825,17 +825,6 @@ int CompareEncodedIDBKeys(StringPiece* slice_a, return 0; } -int CompareEncodedIDBKeys(const std::string& key_a, - const std::string& key_b, - bool* ok) { - DCHECK(!key_a.empty()); - DCHECK(!key_b.empty()); - - StringPiece slice_a(key_a); - StringPiece slice_b(key_b); - return CompareEncodedIDBKeys(&slice_a, &slice_b, ok); -} - namespace { template <typename KeyType> @@ -1324,7 +1313,7 @@ bool DatabaseNameKey::Decode(StringPiece* slice, DatabaseNameKey* result) { } std::string DatabaseNameKey::Encode(const std::string& origin_identifier, - const string16& database_name) { + const base::string16& database_name) { std::string ret = KeyPrefix::EncodeEmpty(); ret.push_back(kDatabaseNameTypeByte); EncodeStringWithLength(base::ASCIIToUTF16(origin_identifier), &ret); @@ -1334,7 +1323,7 @@ std::string DatabaseNameKey::Encode(const std::string& origin_identifier, std::string DatabaseNameKey::EncodeMinKeyForOrigin( const std::string& origin_identifier) { - return Encode(origin_identifier, string16()); + return Encode(origin_identifier, base::string16()); } std::string DatabaseNameKey::EncodeStopKeyForOrigin( @@ -1604,8 +1593,9 @@ bool ObjectStoreNamesKey::Decode(StringPiece* slice, return true; } -std::string ObjectStoreNamesKey::Encode(int64 database_id, - const string16& object_store_name) { +std::string ObjectStoreNamesKey::Encode( + int64 database_id, + const base::string16& object_store_name) { KeyPrefix prefix(database_id); std::string ret = prefix.Encode(); ret.push_back(kObjectStoreNamesTypeByte); @@ -1641,7 +1631,7 @@ bool IndexNamesKey::Decode(StringPiece* slice, IndexNamesKey* result) { std::string IndexNamesKey::Encode(int64 database_id, int64 object_store_id, - const string16& index_name) { + const base::string16& index_name) { KeyPrefix prefix(database_id); std::string ret = prefix.Encode(); ret.push_back(kIndexNamesKeyTypeByte); @@ -1692,10 +1682,6 @@ std::string ObjectStoreDataKey::Encode(int64 database_id, return Encode(database_id, object_store_id, encoded_key); } -int ObjectStoreDataKey::Compare(const ObjectStoreDataKey& other, bool* ok) { - return CompareEncodedIDBKeys(encoded_user_key_, other.encoded_user_key_, ok); -} - scoped_ptr<IndexedDBKey> ObjectStoreDataKey::user_key() const { scoped_ptr<IndexedDBKey> key; StringPiece slice(encoded_user_key_); @@ -1740,10 +1726,6 @@ std::string ExistsEntryKey::Encode(int64 database_id, return Encode(database_id, object_store_id, encoded_key); } -int ExistsEntryKey::Compare(const ExistsEntryKey& other, bool* ok) { - return CompareEncodedIDBKeys(encoded_user_key_, other.encoded_user_key_, ok); -} - scoped_ptr<IndexedDBKey> ExistsEntryKey::user_key() const { scoped_ptr<IndexedDBKey> key; StringPiece slice(encoded_user_key_); @@ -1852,25 +1834,6 @@ std::string IndexDataKey::EncodeMaxKey(int64 database_id, std::numeric_limits<int64>::max()); } -int IndexDataKey::Compare(const IndexDataKey& other, - bool only_compare_index_keys, - bool* ok) { - DCHECK_GE(database_id_, 0); - DCHECK_GE(object_store_id_, 0); - DCHECK_GE(index_id_, 0); - int result = - CompareEncodedIDBKeys(encoded_user_key_, other.encoded_user_key_, ok); - if (!*ok || result) - return result; - if (only_compare_index_keys) - return 0; - result = CompareEncodedIDBKeys( - encoded_primary_key_, other.encoded_primary_key_, ok); - if (!*ok || result) - return result; - return CompareInts(sequence_number_, other.sequence_number_); -} - int64 IndexDataKey::DatabaseId() const { DCHECK_GE(database_id_, 0); return database_id_; diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding.h b/content/browser/indexed_db/indexed_db_leveldb_coding.h index 8d0c78047a..556b4605af 100644 --- a/content/browser/indexed_db/indexed_db_leveldb_coding.h +++ b/content/browser/indexed_db/indexed_db_leveldb_coding.h @@ -27,8 +27,9 @@ CONTENT_EXPORT void EncodeByte(unsigned char value, std::string* into); CONTENT_EXPORT void EncodeBool(bool value, std::string* into); CONTENT_EXPORT void EncodeInt(int64 value, std::string* into); CONTENT_EXPORT void EncodeVarInt(int64 value, std::string* into); -CONTENT_EXPORT void EncodeString(const string16& value, std::string* into); -CONTENT_EXPORT void EncodeStringWithLength(const string16& value, +CONTENT_EXPORT void EncodeString(const base::string16& value, + std::string* into); +CONTENT_EXPORT void EncodeStringWithLength(const base::string16& value, std::string* into); CONTENT_EXPORT void EncodeBinary(const std::string& value, std::string* into); CONTENT_EXPORT void EncodeDouble(double value, std::string* into); @@ -45,10 +46,10 @@ CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeInt(base::StringPiece* slice, CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeVarInt(base::StringPiece* slice, int64* value); CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeString(base::StringPiece* slice, - string16* value); + base::string16* value); CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeStringWithLength( base::StringPiece* slice, - string16* value); + base::string16* value); CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeBinary(base::StringPiece* slice, std::string* value); CONTENT_EXPORT WARN_UNUSED_RESULT bool DecodeDouble(base::StringPiece* slice, @@ -68,8 +69,8 @@ CONTENT_EXPORT WARN_UNUSED_RESULT bool ExtractEncodedIDBKey( base::StringPiece* slice, std::string* result); -CONTENT_EXPORT int CompareEncodedIDBKeys(const std::string& a, - const std::string& b, +CONTENT_EXPORT int CompareEncodedIDBKeys(base::StringPiece* slice1, + base::StringPiece* slice2, bool* ok); CONTENT_EXPORT int Compare(const base::StringPiece& a, @@ -188,18 +189,19 @@ class DatabaseNameKey { public: static bool Decode(base::StringPiece* slice, DatabaseNameKey* result); CONTENT_EXPORT static std::string Encode(const std::string& origin_identifier, - const string16& database_name); + const base::string16& database_name); static std::string EncodeMinKeyForOrigin( const std::string& origin_identifier); static std::string EncodeStopKeyForOrigin( const std::string& origin_identifier); - string16 origin() const { return origin_; } - string16 database_name() const { return database_name_; } + base::string16 origin() const { return origin_; } + base::string16 database_name() const { return database_name_; } int Compare(const DatabaseNameKey& other); private: - string16 origin_; // TODO(jsbell): Store encoded strings, or just pointers. - string16 database_name_; + base::string16 origin_; // TODO(jsbell): Store encoded strings, or just + // pointers. + base::string16 database_name_; }; class DatabaseMetaDataKey { @@ -315,14 +317,15 @@ class ObjectStoreNamesKey { // because a mapping is kept in the IndexedDBDatabase. Can the // mapping become unreliable? Can we remove this? static bool Decode(base::StringPiece* slice, ObjectStoreNamesKey* result); - CONTENT_EXPORT static std::string Encode(int64 database_id, - const string16& object_store_name); + CONTENT_EXPORT static std::string Encode( + int64 database_id, + const base::string16& object_store_name); int Compare(const ObjectStoreNamesKey& other); - string16 object_store_name() const { return object_store_name_; } + base::string16 object_store_name() const { return object_store_name_; } private: // TODO(jsbell): Store the encoded string, or just pointers to it. - string16 object_store_name_; + base::string16 object_store_name_; }; class IndexNamesKey { @@ -333,13 +336,13 @@ class IndexNamesKey { static bool Decode(base::StringPiece* slice, IndexNamesKey* result); CONTENT_EXPORT static std::string Encode(int64 database_id, int64 object_store_id, - const string16& index_name); + const base::string16& index_name); int Compare(const IndexNamesKey& other); - string16 index_name() const { return index_name_; } + base::string16 index_name() const { return index_name_; } private: int64 object_store_id_; - string16 index_name_; + base::string16 index_name_; }; class ObjectStoreDataKey { @@ -351,7 +354,6 @@ class ObjectStoreDataKey { static std::string Encode(int64 database_id, int64 object_store_id, const IndexedDBKey& user_key); - int Compare(const ObjectStoreDataKey& other, bool* ok); scoped_ptr<IndexedDBKey> user_key() const; static const int64 kSpecialIndexNumber; ObjectStoreDataKey(); @@ -373,7 +375,6 @@ class ExistsEntryKey { static std::string Encode(int64 database_id, int64 object_store_id, const IndexedDBKey& user_key); - int Compare(const ExistsEntryKey& other, bool* ok); scoped_ptr<IndexedDBKey> user_key() const; static const int64 kSpecialIndexNumber; @@ -410,9 +411,6 @@ class IndexDataKey { CONTENT_EXPORT static std::string EncodeMaxKey(int64 database_id, int64 object_store_id, int64 index_id); - int Compare(const IndexDataKey& other, - bool only_compare_index_keys, - bool* ok); int64 DatabaseId() const; int64 ObjectStoreId() const; int64 IndexId() const; diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc b/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc index 6d6ab0bda5..44c4ab88cd 100644 --- a/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc +++ b/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc @@ -111,8 +111,13 @@ TEST(IndexedDBLevelDBCodingTest, EncodeBool) { } static int CompareKeys(const std::string& a, const std::string& b) { + DCHECK(!a.empty()); + DCHECK(!b.empty()); + + StringPiece slice_a(a); + StringPiece slice_b(b); bool ok; - int result = CompareEncodedIDBKeys(a, b, &ok); + int result = CompareEncodedIDBKeys(&slice_a, &slice_b, &ok); EXPECT_TRUE(ok); return result; } @@ -304,7 +309,7 @@ TEST(IndexedDBLevelDBCodingTest, DecodeVarInt) { } } -static std::string WrappedEncodeString(string16 value) { +static std::string WrappedEncodeString(base::string16 value) { std::string buffer; EncodeString(value, &buffer); return buffer; @@ -321,24 +326,24 @@ TEST(IndexedDBLevelDBCodingTest, EncodeString) { EXPECT_EQ(static_cast<size_t>(6), WrappedEncodeString(ASCIIToUTF16("foo")).size()); EXPECT_EQ(static_cast<size_t>(6), - WrappedEncodeString(string16(test_string_a)).size()); + WrappedEncodeString(base::string16(test_string_a)).size()); EXPECT_EQ(static_cast<size_t>(4), - WrappedEncodeString(string16(test_string_b)).size()); + WrappedEncodeString(base::string16(test_string_b)).size()); } TEST(IndexedDBLevelDBCodingTest, DecodeString) { const char16 test_string_a[] = {'f', 'o', 'o', '\0'}; const char16 test_string_b[] = {0xdead, 0xbeef, '\0'}; - std::vector<string16> test_cases; - test_cases.push_back(string16()); + std::vector<base::string16> test_cases; + test_cases.push_back(base::string16()); test_cases.push_back(ASCIIToUTF16("a")); test_cases.push_back(ASCIIToUTF16("foo")); test_cases.push_back(test_string_a); test_cases.push_back(test_string_b); for (size_t i = 0; i < test_cases.size(); ++i) { - const string16& test_case = test_cases[i]; + const base::string16& test_case = test_cases[i]; std::string v = WrappedEncodeString(test_case); StringPiece slice; @@ -346,7 +351,7 @@ TEST(IndexedDBLevelDBCodingTest, DecodeString) { slice = StringPiece(&*v.begin(), v.size()); } - string16 result; + base::string16 result; EXPECT_TRUE(DecodeString(&slice, &result)); EXPECT_EQ(test_case, result); EXPECT_TRUE(slice.empty()); @@ -360,7 +365,7 @@ TEST(IndexedDBLevelDBCodingTest, DecodeString) { } } -static std::string WrappedEncodeStringWithLength(string16 value) { +static std::string WrappedEncodeStringWithLength(base::string16 value) { std::string buffer; EncodeStringWithLength(value, &buffer); return buffer; @@ -371,13 +376,15 @@ TEST(IndexedDBLevelDBCodingTest, EncodeStringWithLength) { const char16 test_string_b[] = {0xdead, 0xbeef, '\0'}; EXPECT_EQ(static_cast<size_t>(1), - WrappedEncodeStringWithLength(string16()).size()); + WrappedEncodeStringWithLength(base::string16()).size()); EXPECT_EQ(static_cast<size_t>(3), WrappedEncodeStringWithLength(ASCIIToUTF16("a")).size()); EXPECT_EQ(static_cast<size_t>(7), - WrappedEncodeStringWithLength(string16(test_string_a)).size()); + WrappedEncodeStringWithLength( + base::string16(test_string_a)).size()); EXPECT_EQ(static_cast<size_t>(5), - WrappedEncodeStringWithLength(string16(test_string_b)).size()); + WrappedEncodeStringWithLength( + base::string16(test_string_b)).size()); } TEST(IndexedDBLevelDBCodingTest, DecodeStringWithLength) { @@ -390,20 +397,20 @@ TEST(IndexedDBLevelDBCodingTest, DecodeStringWithLength) { long_string[i] = i; long_string[kLongStringLen] = 0; - std::vector<string16> test_cases; + std::vector<base::string16> test_cases; test_cases.push_back(ASCIIToUTF16("")); test_cases.push_back(ASCIIToUTF16("a")); test_cases.push_back(ASCIIToUTF16("foo")); - test_cases.push_back(string16(test_string_a)); - test_cases.push_back(string16(test_string_b)); - test_cases.push_back(string16(long_string)); + test_cases.push_back(base::string16(test_string_a)); + test_cases.push_back(base::string16(test_string_b)); + test_cases.push_back(base::string16(long_string)); for (size_t i = 0; i < test_cases.size(); ++i) { - string16 s = test_cases[i]; + base::string16 s = test_cases[i]; std::string v = WrappedEncodeStringWithLength(s); ASSERT_GT(v.size(), static_cast<size_t>(0)); StringPiece slice(v); - string16 res; + base::string16 res; EXPECT_TRUE(DecodeStringWithLength(&slice, &res)); EXPECT_EQ(s, res); EXPECT_TRUE(slice.empty()); @@ -444,23 +451,23 @@ TEST(IndexedDBLevelDBCodingTest, CompareEncodedStringsWithLength) { const char16 test_string_e[] = {0xd834, 0xdd1e, '\0'}; const char16 test_string_f[] = {0xfffd, '\0'}; - std::vector<string16> test_cases; + std::vector<base::string16> test_cases; test_cases.push_back(ASCIIToUTF16("")); test_cases.push_back(ASCIIToUTF16("a")); test_cases.push_back(ASCIIToUTF16("b")); test_cases.push_back(ASCIIToUTF16("baaa")); test_cases.push_back(ASCIIToUTF16("baab")); test_cases.push_back(ASCIIToUTF16("c")); - test_cases.push_back(string16(test_string_a)); - test_cases.push_back(string16(test_string_b)); - test_cases.push_back(string16(test_string_c)); - test_cases.push_back(string16(test_string_d)); - test_cases.push_back(string16(test_string_e)); - test_cases.push_back(string16(test_string_f)); + test_cases.push_back(base::string16(test_string_a)); + test_cases.push_back(base::string16(test_string_b)); + test_cases.push_back(base::string16(test_string_c)); + test_cases.push_back(base::string16(test_string_d)); + test_cases.push_back(base::string16(test_string_e)); + test_cases.push_back(base::string16(test_string_f)); for (size_t i = 0; i < test_cases.size() - 1; ++i) { - string16 a = test_cases[i]; - string16 b = test_cases[i + 1]; + base::string16 a = test_cases[i]; + base::string16 b = test_cases[i + 1]; EXPECT_LT(a.compare(b), 0); EXPECT_GT(b.compare(a), 0); @@ -630,7 +637,7 @@ TEST(IndexedDBLevelDBCodingTest, EncodeDecodeIDBKeyPath) { } { - key_paths.push_back(IndexedDBKeyPath(string16())); + key_paths.push_back(IndexedDBKeyPath(base::string16())); char expected[] = {0, 0, // Header 1, // Type is string 0 // Length is 0 @@ -661,8 +668,8 @@ TEST(IndexedDBLevelDBCodingTest, EncodeDecodeIDBKeyPath) { } { - std::vector<string16> array; - array.push_back(string16()); + std::vector<base::string16> array; + array.push_back(base::string16()); array.push_back(ASCIIToUTF16("foo")); array.push_back(ASCIIToUTF16("foo.bar")); @@ -700,7 +707,7 @@ TEST(IndexedDBLevelDBCodingTest, DecodeLegacyIDBKeyPath) { std::vector<std::string> encoded_paths; { - key_paths.push_back(IndexedDBKeyPath(string16())); + key_paths.push_back(IndexedDBKeyPath(base::string16())); encoded_paths.push_back(std::string()); } { diff --git a/content/browser/indexed_db/indexed_db_metadata.cc b/content/browser/indexed_db/indexed_db_metadata.cc index 80d31424c5..47b7219f15 100644 --- a/content/browser/indexed_db/indexed_db_metadata.cc +++ b/content/browser/indexed_db/indexed_db_metadata.cc @@ -7,7 +7,7 @@ namespace content { IndexedDBObjectStoreMetadata::IndexedDBObjectStoreMetadata( - const string16& name, + const base::string16& name, int64 id, const IndexedDBKeyPath& key_path, bool auto_increment, @@ -23,11 +23,12 @@ IndexedDBObjectStoreMetadata::~IndexedDBObjectStoreMetadata() {} IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata() : int_version(NO_INT_VERSION) {} -IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata(const string16& name, - int64 id, - const string16& version, - int64 int_version, - int64 max_object_store_id) +IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata( + const base::string16& name, + int64 id, + const base::string16& version, + int64 int_version, + int64 max_object_store_id) : name(name), id(id), version(version), diff --git a/content/browser/indexed_db/indexed_db_metadata.h b/content/browser/indexed_db/indexed_db_metadata.h index 4e8562d1f6..00970a61ee 100644 --- a/content/browser/indexed_db/indexed_db_metadata.h +++ b/content/browser/indexed_db/indexed_db_metadata.h @@ -15,7 +15,7 @@ namespace content { struct IndexedDBIndexMetadata { IndexedDBIndexMetadata() {} - IndexedDBIndexMetadata(const string16& name, + IndexedDBIndexMetadata(const base::string16& name, int64 id, const IndexedDBKeyPath& key_path, bool unique, @@ -25,7 +25,7 @@ struct IndexedDBIndexMetadata { key_path(key_path), unique(unique), multi_entry(multi_entry) {} - string16 name; + base::string16 name; int64 id; IndexedDBKeyPath key_path; bool unique; @@ -36,13 +36,13 @@ struct IndexedDBIndexMetadata { struct CONTENT_EXPORT IndexedDBObjectStoreMetadata { IndexedDBObjectStoreMetadata(); - IndexedDBObjectStoreMetadata(const string16& name, + IndexedDBObjectStoreMetadata(const base::string16& name, int64 id, const IndexedDBKeyPath& key_path, bool auto_increment, int64 max_index_id); ~IndexedDBObjectStoreMetadata(); - string16 name; + base::string16 name; int64 id; IndexedDBKeyPath key_path; bool auto_increment; @@ -64,16 +64,16 @@ struct CONTENT_EXPORT IndexedDBDatabaseMetadata { typedef std::map<int64, IndexedDBObjectStoreMetadata> ObjectStoreMap; IndexedDBDatabaseMetadata(); - IndexedDBDatabaseMetadata(const string16& name, + IndexedDBDatabaseMetadata(const base::string16& name, int64 id, - const string16& version, + const base::string16& version, int64 int_version, int64 max_object_store_id); ~IndexedDBDatabaseMetadata(); - string16 name; + base::string16 name; int64 id; - string16 version; + base::string16 version; int64 int_version; int64 max_object_store_id; diff --git a/content/browser/indexed_db/indexed_db_quota_client_unittest.cc b/content/browser/indexed_db/indexed_db_quota_client_unittest.cc index 25f6620916..cd2f146deb 100644 --- a/content/browser/indexed_db/indexed_db_quota_client_unittest.cc +++ b/content/browser/indexed_db/indexed_db_quota_client_unittest.cc @@ -66,7 +66,7 @@ class IndexedDBQuotaClientTest : public testing::Test { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); base::FilePath indexeddb_dir = temp_dir_.path().Append(IndexedDBContextImpl::kIndexedDBDirectory); - ASSERT_TRUE(file_util::CreateDirectory(indexeddb_dir)); + ASSERT_TRUE(base::CreateDirectory(indexeddb_dir)); idb_context()->set_data_path_for_testing(indexeddb_dir); } @@ -141,8 +141,8 @@ class IndexedDBQuotaClientTest : public testing::Test { void AddFakeIndexedDB(const GURL& origin, int size) { base::FilePath file_path_origin = idb_context()->GetFilePathForTesting( webkit_database::GetIdentifierFromOrigin(origin)); - if (!file_util::CreateDirectory(file_path_origin)) { - LOG(ERROR) << "failed to file_util::CreateDirectory " + if (!base::CreateDirectory(file_path_origin)) { + LOG(ERROR) << "failed to base::CreateDirectory " << file_path_origin.value(); } file_path_origin = file_path_origin.Append(FILE_PATH_LITERAL("fake_file")); diff --git a/content/browser/indexed_db/indexed_db_transaction.cc b/content/browser/indexed_db/indexed_db_transaction.cc index 28f8378f54..b56900b26b 100644 --- a/content/browser/indexed_db/indexed_db_transaction.cc +++ b/content/browser/indexed_db/indexed_db_transaction.cc @@ -18,6 +18,8 @@ namespace content { +const int64 kInactivityTimeoutPeriodSeconds = 60; + IndexedDBTransaction::TaskQueue::TaskQueue() {} IndexedDBTransaction::TaskQueue::~TaskQueue() { clear(); } @@ -53,7 +55,8 @@ IndexedDBTransaction::IndexedDBTransaction( scoped_refptr<IndexedDBDatabaseCallbacks> callbacks, const std::set<int64>& object_store_ids, indexed_db::TransactionMode mode, - IndexedDBDatabase* database) + IndexedDBDatabase* database, + IndexedDBBackingStore::Transaction* backing_store_transaction) : id_(id), object_store_ids_(object_store_ids), mode_(mode), @@ -62,7 +65,7 @@ IndexedDBTransaction::IndexedDBTransaction( commit_pending_(false), callbacks_(callbacks), database_(database), - transaction_(database->backing_store()), + transaction_(backing_store_transaction), backing_store_transaction_begun_(false), should_process_queue_(false), pending_preemptive_events_(0) { @@ -86,6 +89,7 @@ void IndexedDBTransaction::ScheduleTask(Operation task, Operation abort_task) { if (state_ == FINISHED) return; + timeout_timer_.Stop(); used_ = true; task_queue_.push(task); ++diagnostics_.tasks_scheduled; @@ -98,6 +102,7 @@ void IndexedDBTransaction::ScheduleTask(IndexedDBDatabase::TaskType type, if (state_ == FINISHED) return; + timeout_timer_.Stop(); used_ = true; if (type == IndexedDBDatabase::NORMAL_TASK) { task_queue_.push(task); @@ -139,11 +144,13 @@ void IndexedDBTransaction::Abort(const IndexedDBDatabaseError& error) { // alive while executing this method. scoped_refptr<IndexedDBTransaction> protect(this); + timeout_timer_.Stop(); + state_ = FINISHED; should_process_queue_ = false; if (backing_store_transaction_begun_) - transaction_.Rollback(); + transaction_->Rollback(); // Run the abort tasks, if any. while (!abort_task_stack_.empty()) { @@ -158,7 +165,7 @@ void IndexedDBTransaction::Abort(const IndexedDBDatabaseError& error) { // release references and allow the backing store itself to be // released, and order is critical. CloseOpenCursors(); - transaction_.Reset(); + transaction_->Reset(); // Transactions must also be marked as completed before the // front-end is notified, as the transaction completion unblocks @@ -229,19 +236,21 @@ void IndexedDBTransaction::Commit() { // alive while executing this method. scoped_refptr<IndexedDBTransaction> protect(this); + timeout_timer_.Stop(); + // TODO(jsbell): Run abort tasks if commit fails? http://crbug.com/241843 abort_task_stack_.clear(); state_ = FINISHED; - bool committed = !used_ || transaction_.Commit(); + bool committed = !used_ || transaction_->Commit(); // Backing store resources (held via cursors) must be released // before script callbacks are fired, as the script callbacks may // release references and allow the backing store itself to be // released, and order is critical. CloseOpenCursors(); - transaction_.Reset(); + transaction_->Reset(); // Transactions must also be marked as completed before the // front-end is notified, as the transaction completion unblocks @@ -275,7 +284,7 @@ void IndexedDBTransaction::ProcessTaskQueue() { should_process_queue_ = false; if (!backing_store_transaction_begun_) { - transaction_.Begin(); + transaction_->Begin(); backing_store_transaction_begun_ = true; } @@ -302,8 +311,27 @@ void IndexedDBTransaction::ProcessTaskQueue() { // If there are no pending tasks, we haven't already committed/aborted, // and the front-end requested a commit, it is now safe to do so. - if (!HasPendingTasks() && state_ != FINISHED && commit_pending_) + if (!HasPendingTasks() && state_ != FINISHED && commit_pending_) { Commit(); + return; + } + + // The transaction may have been aborted while processing tasks. + if (state_ == FINISHED) + return; + + // Otherwise, start a timer in case the front-end gets wedged and + // never requests further activity. + timeout_timer_.Start( + FROM_HERE, + base::TimeDelta::FromSeconds(kInactivityTimeoutPeriodSeconds), + base::Bind(&IndexedDBTransaction::Timeout, this)); +} + +void IndexedDBTransaction::Timeout() { + Abort(IndexedDBDatabaseError( + blink::WebIDBDatabaseExceptionTimeoutError, + ASCIIToUTF16("Transaction timed out due to inactivity."))); } void IndexedDBTransaction::CloseOpenCursors() { diff --git a/content/browser/indexed_db/indexed_db_transaction.h b/content/browser/indexed_db/indexed_db_transaction.h index 111101fe09..6684856e57 100644 --- a/content/browser/indexed_db/indexed_db_transaction.h +++ b/content/browser/indexed_db/indexed_db_transaction.h @@ -13,6 +13,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/time/time.h" +#include "base/timer/timer.h" #include "content/browser/indexed_db/indexed_db_backing_store.h" #include "content/browser/indexed_db/indexed_db_database.h" #include "content/browser/indexed_db/indexed_db_database_error.h" @@ -22,15 +23,18 @@ namespace content { class IndexedDBCursor; class IndexedDBDatabaseCallbacks; -class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> { +class CONTENT_EXPORT IndexedDBTransaction + : public NON_EXPORTED_BASE(base::RefCounted<IndexedDBTransaction>) { public: typedef base::Callback<void(IndexedDBTransaction*)> Operation; - IndexedDBTransaction(int64 id, - scoped_refptr<IndexedDBDatabaseCallbacks> callbacks, - const std::set<int64>& object_store_ids, - indexed_db::TransactionMode, - IndexedDBDatabase* db); + IndexedDBTransaction( + int64 id, + scoped_refptr<IndexedDBDatabaseCallbacks> callbacks, + const std::set<int64>& object_store_ids, + indexed_db::TransactionMode, + IndexedDBDatabase* db, + IndexedDBBackingStore::Transaction* backing_store_transaction); virtual void Abort(); void Commit(); @@ -55,7 +59,7 @@ class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> { DCHECK_GE(pending_preemptive_events_, 0); } IndexedDBBackingStore::Transaction* BackingStoreTransaction() { - return &transaction_; + return transaction_.get(); } int64 id() const { return id_; } @@ -69,6 +73,7 @@ class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> { }; State state() const { return state_; } + bool IsTimeoutTimerRunning() const { return timeout_timer_.IsRunning(); } struct Diagnostics { base::Time creation_time; @@ -90,6 +95,7 @@ class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> { void ProcessTaskQueue(); void CloseOpenCursors(); + void Timeout(); const int64 id_; const std::set<int64> object_store_ids_; @@ -131,13 +137,19 @@ class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> { TaskQueue preemptive_task_queue_; TaskStack abort_task_stack_; - IndexedDBBackingStore::Transaction transaction_; + scoped_ptr<IndexedDBBackingStore::Transaction> transaction_; bool backing_store_transaction_begun_; bool should_process_queue_; int pending_preemptive_events_; std::set<IndexedDBCursor*> open_cursors_; + + // This timer is started after requests have been processed. If no subsequent + // requests are processed before the timer fires, assume the script is + // unresponsive and abort to unblock the transaction queue. + base::OneShotTimer<IndexedDBTransaction> timeout_timer_; + Diagnostics diagnostics_; }; diff --git a/content/browser/indexed_db/indexed_db_transaction_unittest.cc b/content/browser/indexed_db/indexed_db_transaction_unittest.cc new file mode 100644 index 0000000000..3fc7271b05 --- /dev/null +++ b/content/browser/indexed_db/indexed_db_transaction_unittest.cc @@ -0,0 +1,82 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/indexed_db/indexed_db_transaction.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "content/browser/indexed_db/indexed_db_fake_backing_store.h" +#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { + +namespace { + +class IndexedDBTransactionTest : public testing::Test { + public: + IndexedDBTransactionTest() { + IndexedDBFactory* factory = NULL; + backing_store_ = new IndexedDBFakeBackingStore(); + db_ = IndexedDBDatabase::Create(ASCIIToUTF16("db"), + backing_store_, + factory, + IndexedDBDatabase::Identifier()); + } + + void RunPostedTasks() { message_loop_.RunUntilIdle(); } + void DummyOperation(IndexedDBTransaction* transaction) {} + + protected: + scoped_refptr<IndexedDBFakeBackingStore> backing_store_; + scoped_refptr<IndexedDBDatabase> db_; + + private: + base::MessageLoop message_loop_; + + DISALLOW_COPY_AND_ASSIGN(IndexedDBTransactionTest); +}; + +TEST_F(IndexedDBTransactionTest, Timeout) { + const int64 id = 0; + const std::set<int64> scope; + const bool commit_success = true; + scoped_refptr<IndexedDBTransaction> transaction = new IndexedDBTransaction( + id, + new MockIndexedDBDatabaseCallbacks(), + scope, + indexed_db::TRANSACTION_READ_ONLY, + db_, + new IndexedDBFakeBackingStore::FakeTransaction(commit_success)); + db_->TransactionCreated(transaction); + + // No conflicting transactions, so coordinator will start it immediately: + EXPECT_EQ(IndexedDBTransaction::STARTED, transaction->state()); + EXPECT_FALSE(transaction->IsTimeoutTimerRunning()); + + // Schedule a task - timer won't be started until it's processed. + transaction->ScheduleTask(base::Bind( + &IndexedDBTransactionTest::DummyOperation, base::Unretained(this))); + EXPECT_FALSE(transaction->IsTimeoutTimerRunning()); + + RunPostedTasks(); + EXPECT_TRUE(transaction->IsTimeoutTimerRunning()); + + // Abort should cancel the timer. + transaction->Abort(); + EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state()); + EXPECT_FALSE(transaction->IsTimeoutTimerRunning()); + + // This task will be ignored. + transaction->ScheduleTask(base::Bind( + &IndexedDBTransactionTest::DummyOperation, base::Unretained(this))); + EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state()); + EXPECT_FALSE(transaction->IsTimeoutTimerRunning()); +} + +} // namespace + +} // namespace content diff --git a/content/browser/indexed_db/indexed_db_unittest.cc b/content/browser/indexed_db/indexed_db_unittest.cc index 43613af566..b94b20d431 100644 --- a/content/browser/indexed_db/indexed_db_unittest.cc +++ b/content/browser/indexed_db/indexed_db_unittest.cc @@ -69,8 +69,8 @@ TEST_F(IndexedDBTest, ClearSessionOnlyDatabases) { webkit_database::GetIdentifierFromOrigin(kNormalOrigin)); session_only_path = idb_context->GetFilePathForTesting( webkit_database::GetIdentifierFromOrigin(kSessionOnlyOrigin)); - ASSERT_TRUE(file_util::CreateDirectory(normal_path)); - ASSERT_TRUE(file_util::CreateDirectory(session_only_path)); + ASSERT_TRUE(base::CreateDirectory(normal_path)); + ASSERT_TRUE(base::CreateDirectory(session_only_path)); FlushIndexedDBTaskRunner(); message_loop_.RunUntilIdle(); } @@ -103,8 +103,8 @@ TEST_F(IndexedDBTest, SetForceKeepSessionState) { webkit_database::GetIdentifierFromOrigin(kNormalOrigin)); session_only_path = idb_context->GetFilePathForTesting( webkit_database::GetIdentifierFromOrigin(kSessionOnlyOrigin)); - ASSERT_TRUE(file_util::CreateDirectory(normal_path)); - ASSERT_TRUE(file_util::CreateDirectory(session_only_path)); + ASSERT_TRUE(base::CreateDirectory(normal_path)); + ASSERT_TRUE(base::CreateDirectory(session_only_path)); message_loop_.RunUntilIdle(); } @@ -158,7 +158,7 @@ TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnDelete) { test_path = idb_context->GetFilePathForTesting( webkit_database::GetIdentifierFromOrigin(kTestOrigin)); - ASSERT_TRUE(file_util::CreateDirectory(test_path)); + ASSERT_TRUE(base::CreateDirectory(test_path)); const bool kExpectForceClose = true; @@ -208,7 +208,7 @@ TEST_F(IndexedDBTest, DeleteFailsIfDirectoryLocked) { base::FilePath test_path = idb_context->GetFilePathForTesting( webkit_database::GetIdentifierFromOrigin(kTestOrigin)); - ASSERT_TRUE(file_util::CreateDirectory(test_path)); + ASSERT_TRUE(base::CreateDirectory(test_path)); scoped_ptr<LevelDBLock> lock = LevelDBDatabase::LockForTesting(test_path); diff --git a/content/browser/indexed_db/mock_indexed_db_callbacks.cc b/content/browser/indexed_db/mock_indexed_db_callbacks.cc index c5f93e00ef..a585246ab3 100644 --- a/content/browser/indexed_db/mock_indexed_db_callbacks.cc +++ b/content/browser/indexed_db/mock_indexed_db_callbacks.cc @@ -9,9 +9,17 @@ namespace content { MockIndexedDBCallbacks::MockIndexedDBCallbacks() - : IndexedDBCallbacks(NULL, 0, 0) {} + : IndexedDBCallbacks(NULL, 0, 0), expect_connection_(true) {} +MockIndexedDBCallbacks::MockIndexedDBCallbacks(bool expect_connection) + : IndexedDBCallbacks(NULL, 0, 0), expect_connection_(expect_connection) {} -MockIndexedDBCallbacks::~MockIndexedDBCallbacks() { EXPECT_TRUE(connection_); } +MockIndexedDBCallbacks::~MockIndexedDBCallbacks() { + EXPECT_EQ(expect_connection_, !!connection_); +} + +void MockIndexedDBCallbacks::OnSuccess() {} + +void MockIndexedDBCallbacks::OnSuccess(const std::vector<base::string16>&) {} void MockIndexedDBCallbacks::OnSuccess( scoped_ptr<IndexedDBConnection> connection, diff --git a/content/browser/indexed_db/mock_indexed_db_callbacks.h b/content/browser/indexed_db/mock_indexed_db_callbacks.h index 3d6b949bd2..d4d9217c7d 100644 --- a/content/browser/indexed_db/mock_indexed_db_callbacks.h +++ b/content/browser/indexed_db/mock_indexed_db_callbacks.h @@ -13,7 +13,10 @@ namespace content { class MockIndexedDBCallbacks : public IndexedDBCallbacks { public: MockIndexedDBCallbacks(); + MockIndexedDBCallbacks(bool expect_connection); + virtual void OnSuccess() OVERRIDE; + virtual void OnSuccess(const std::vector<base::string16>&) OVERRIDE; virtual void OnSuccess(scoped_ptr<IndexedDBConnection> connection, const IndexedDBDatabaseMetadata& metadata) OVERRIDE; @@ -22,6 +25,7 @@ class MockIndexedDBCallbacks : public IndexedDBCallbacks { private: virtual ~MockIndexedDBCallbacks(); scoped_ptr<IndexedDBConnection> connection_; + bool expect_connection_; DISALLOW_COPY_AND_ASSIGN(MockIndexedDBCallbacks); }; diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc index 5983052246..93d7e839aa 100644 --- a/content/browser/loader/async_resource_handler.cc +++ b/content/browser/loader/async_resource_handler.cc @@ -151,6 +151,7 @@ bool AsyncResourceHandler::OnRequestRedirected(int request_id, return false; *defer = did_defer_ = true; + OnDefer(); if (rdh_->delegate()) { rdh_->delegate()->OnRequestRedirected( @@ -287,6 +288,7 @@ bool AsyncResourceHandler::OnReadCompleted(int request_id, int bytes_read, "Net.AsyncResourceHandler_PendingDataCount_WhenFull", pending_data_count_, 0, 100, 100); *defer = did_defer_ = true; + OnDefer(); } return true; @@ -377,8 +379,13 @@ bool AsyncResourceHandler::EnsureResourceBufferIsInitialized() { void AsyncResourceHandler::ResumeIfDeferred() { if (did_defer_) { did_defer_ = false; + request()->LogUnblocked(); controller()->Resume(); } } +void AsyncResourceHandler::OnDefer() { + request()->LogBlockedBy("AsyncResourceHandler"); +} + } // namespace content diff --git a/content/browser/loader/async_resource_handler.h b/content/browser/loader/async_resource_handler.h index ac15b5963a..f603f4f858 100644 --- a/content/browser/loader/async_resource_handler.h +++ b/content/browser/loader/async_resource_handler.h @@ -72,6 +72,7 @@ class AsyncResourceHandler : public ResourceHandler, bool EnsureResourceBufferIsInitialized(); void ResumeIfDeferred(); + void OnDefer(); scoped_refptr<ResourceBuffer> buffer_; ResourceDispatcherHostImpl* rdh_; diff --git a/content/browser/loader/buffered_resource_handler.cc b/content/browser/loader/buffered_resource_handler.cc index bc63665140..2a5ef9cd12 100644 --- a/content/browser/loader/buffered_resource_handler.cc +++ b/content/browser/loader/buffered_resource_handler.cc @@ -444,7 +444,7 @@ bool BufferedResourceHandler::HasSupportingPlugin(bool* stale) { bool allow_wildcard = false; WebPluginInfo plugin; return PluginServiceImpl::GetInstance()->GetPluginInfo( - info->GetChildID(), info->GetRouteID(), info->GetContext(), + info->GetChildID(), info->GetRenderFrameID(), info->GetContext(), request()->url(), GURL(), response_->head.mime_type, allow_wildcard, stale, &plugin, NULL); #else diff --git a/content/browser/loader/power_save_block_resource_throttle.cc b/content/browser/loader/power_save_block_resource_throttle.cc index d9b843cba2..7a084b0a71 100644 --- a/content/browser/loader/power_save_block_resource_throttle.cc +++ b/content/browser/loader/power_save_block_resource_throttle.cc @@ -34,6 +34,10 @@ void PowerSaveBlockResourceThrottle::WillProcessResponse(bool* defer) { timer_.Stop(); } +const char* PowerSaveBlockResourceThrottle::GetNameForLogging() const { + return "PowerSaveBlockResourceThrottle"; +} + void PowerSaveBlockResourceThrottle::ActivatePowerSaveBlocker() { power_save_blocker_ = PowerSaveBlocker::Create( PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, diff --git a/content/browser/loader/power_save_block_resource_throttle.h b/content/browser/loader/power_save_block_resource_throttle.h index e94b542615..2a4f9b39c5 100644 --- a/content/browser/loader/power_save_block_resource_throttle.h +++ b/content/browser/loader/power_save_block_resource_throttle.h @@ -24,6 +24,7 @@ class PowerSaveBlockResourceThrottle : public ResourceThrottle { // ResourceThrottle overrides: virtual void WillStartRequest(bool* defer) OVERRIDE; virtual void WillProcessResponse(bool* defer) OVERRIDE; + virtual const char* GetNameForLogging() const OVERRIDE; private: void ActivatePowerSaveBlocker(); diff --git a/content/browser/loader/resource_dispatcher_host_browsertest.cc b/content/browser/loader/resource_dispatcher_host_browsertest.cc index 0a763fede6..011c9758fa 100644 --- a/content/browser/loader/resource_dispatcher_host_browsertest.cc +++ b/content/browser/loader/resource_dispatcher_host_browsertest.cc @@ -59,13 +59,13 @@ class ResourceDispatcherHostBrowserTest : public ContentBrowserTest, void CheckTitleTest(const GURL& url, const std::string& expected_title) { - string16 expected_title16(ASCIIToUTF16(expected_title)); + base::string16 expected_title16(ASCIIToUTF16(expected_title)); TitleWatcher title_watcher(shell()->web_contents(), expected_title16); NavigateToURL(shell(), url); EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); } - bool GetPopupTitle(const GURL& url, string16* title) { + bool GetPopupTitle(const GURL& url, base::string16* title) { NavigateToURL(shell(), url); ShellAddedObserver new_shell_observer; @@ -96,7 +96,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DynamicTitle1) { ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); GURL url(embedded_test_server()->GetURL("/dynamic1.html")); - string16 title; + base::string16 title; ASSERT_TRUE(GetPopupTitle(url, &title)); EXPECT_TRUE(StartsWith(title, ASCIIToUTF16("My Popup Title"), true)) << "Actual title: " << title; @@ -108,7 +108,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, DynamicTitle2) { ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); GURL url(embedded_test_server()->GetURL("/dynamic2.html")); - string16 title; + base::string16 title; ASSERT_TRUE(GetPopupTitle(url, &title)); EXPECT_TRUE(StartsWith(title, ASCIIToUTF16("My Dynamic Title"), true)) << "Actual title: " << title; @@ -364,7 +364,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest, // URLs are prohibited by policy from interacting with sensitive chrome // pages of which the error page is one. Instead, use automation to kick // off the navigation, and wait to see that the tab loads. - string16 expected_title16(ASCIIToUTF16("Title Of Awesomeness")); + base::string16 expected_title16(ASCIIToUTF16("Title Of Awesomeness")); TitleWatcher title_watcher(shell()->web_contents(), expected_title16); bool success; diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index 84cfb57fce..831a368e16 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc @@ -1100,6 +1100,7 @@ void ResourceDispatcherHostImpl::BeginRequest( route_id, request_data.origin_pid, request_id, + request_data.render_frame_id, request_data.is_main_frame, request_data.frame_id, request_data.parent_is_main_frame, @@ -1131,6 +1132,23 @@ void ResourceDispatcherHostImpl::BeginRequest( request, filter_->appcache_service(), child_id, request_data.appcache_host_id, request_data.resource_type); + scoped_ptr<ResourceHandler> handler( + CreateResourceHandler( + request, + request_data, sync_result, route_id, process_type, child_id, + resource_context)); + + BeginRequestInternal(new_request.Pass(), handler.Pass()); +} + +scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::CreateResourceHandler( + net::URLRequest* request, + const ResourceHostMsg_Request& request_data, + IPC::Message* sync_result, + int route_id, + int process_type, + int child_id, + ResourceContext* resource_context) { // Construct the IPC resource handler. scoped_ptr<ResourceHandler> handler; if (sync_result) { @@ -1185,7 +1203,7 @@ void ResourceDispatcherHostImpl::BeginRequest( handler.reset( new ThrottlingResourceHandler(handler.Pass(), request, throttles.Pass())); - BeginRequestInternal(new_request.Pass(), handler.Pass()); + return handler.Pass(); } void ResourceDispatcherHostImpl::OnReleaseDownloadedFile(int request_id) { @@ -1254,6 +1272,7 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo( route_id, 0, request_id_, + MSG_ROUTING_NONE, // render_frame_id false, // is_main_frame -1, // frame_id false, // parent_is_main_frame diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h index ef0e4cfdb7..2e0253ae51 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.h +++ b/content/browser/loader/resource_dispatcher_host_impl.h @@ -372,6 +372,18 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl const ResourceHostMsg_Request& request_data, IPC::Message* sync_result, // only valid for sync int route_id); // only valid for async + + // Creates a ResourceHandler to be used by BeginRequest() for normal resource + // loading. + scoped_ptr<ResourceHandler> CreateResourceHandler( + net::URLRequest* request, + const ResourceHostMsg_Request& request_data, + IPC::Message* sync_result, + int route_id, + int process_type, + int child_id, + ResourceContext* resource_context); + void OnDataDownloadedACK(int request_id); void OnUploadProgressACK(int request_id); void OnCancelRequest(int request_id); diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc index 895951bba1..52d3432884 100644 --- a/content/browser/loader/resource_dispatcher_host_unittest.cc +++ b/content/browser/loader/resource_dispatcher_host_unittest.cc @@ -441,6 +441,10 @@ class GenericResourceThrottle : public ResourceThrottle { } } + virtual const char* GetNameForLogging() const OVERRIDE { + return "GenericResourceThrottle"; + } + void Resume() { ASSERT_TRUE(this == active_throttle_); active_throttle_ = NULL; diff --git a/content/browser/loader/resource_loader.cc b/content/browser/loader/resource_loader.cc index 01f95a1756..bdc9644b1d 100644 --- a/content/browser/loader/resource_loader.cc +++ b/content/browser/loader/resource_loader.cc @@ -19,6 +19,7 @@ #include "content/public/browser/cert_store.h" #include "content/public/browser/resource_context.h" #include "content/public/browser/resource_dispatcher_host_login_delegate.h" +#include "content/public/browser/signed_certificate_timestamp_store.h" #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" #include "content/public/common/process_type.h" @@ -473,6 +474,21 @@ void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) { } } +void ResourceLoader::StoreSignedCertificateTimestamps( + const net::SignedCertificateTimestampAndStatusList& sct_list, + int process_id, + SignedCertificateTimestampIDStatusList* sct_ids) { + SignedCertificateTimestampStore* sct_store( + SignedCertificateTimestampStore::GetInstance()); + + for (net::SignedCertificateTimestampAndStatusList::const_iterator iter = + sct_list.begin(); iter != sct_list.end(); ++iter) { + const int sct_id(sct_store->Store(iter->sct_, process_id)); + sct_ids->push_back( + SignedCertificateTimestampIDAndStatus(sct_id, iter->status_)); + } +} + void ResourceLoader::CompleteResponseStarted() { ResourceRequestInfoImpl* info = GetRequestInfo(); @@ -482,11 +498,19 @@ void ResourceLoader::CompleteResponseStarted() { if (request_->ssl_info().cert.get()) { int cert_id = CertStore::GetInstance()->StoreCert( request_->ssl_info().cert.get(), info->GetChildID()); + + SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids; + StoreSignedCertificateTimestamps( + request_->ssl_info().signed_certificate_timestamps, + info->GetChildID(), + &signed_certificate_timestamp_ids); + response->head.security_info = SerializeSecurityInfo( cert_id, request_->ssl_info().cert_status, request_->ssl_info().security_bits, - request_->ssl_info().connection_status); + request_->ssl_info().connection_status, + signed_certificate_timestamp_ids); } else { // We should not have any SSL state. DCHECK(!request_->ssl_info().cert_status && @@ -590,9 +614,14 @@ void ResourceLoader::ResponseCompleted() { if (ssl_info.cert.get() != NULL) { int cert_id = CertStore::GetInstance()->StoreCert(ssl_info.cert.get(), info->GetChildID()); + SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids; + StoreSignedCertificateTimestamps(ssl_info.signed_certificate_timestamps, + info->GetChildID(), + &signed_certificate_timestamp_ids); + security_info = SerializeSecurityInfo( cert_id, ssl_info.cert_status, ssl_info.security_bits, - ssl_info.connection_status); + ssl_info.connection_status, signed_certificate_timestamp_ids); } bool defer = false; diff --git a/content/browser/loader/resource_loader.h b/content/browser/loader/resource_loader.h index be2c6c5b97..d0b3ae806c 100644 --- a/content/browser/loader/resource_loader.h +++ b/content/browser/loader/resource_loader.h @@ -12,6 +12,7 @@ #include "content/browser/ssl/ssl_error_handler.h" #include "content/common/content_export.h" #include "content/public/browser/resource_controller.h" +#include "content/public/common/signed_certificate_timestamp_id_and_status.h" #include "net/url_request/url_request.h" namespace content { @@ -83,6 +84,14 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate, void StartRequestInternal(); void CancelRequestInternal(int error, bool from_renderer); + // Stores the SignedCertificateTimestamps held in |sct_list| in the + // SignedCertificateTimestampStore singleton, associated with |process_id|. + // On return, |sct_ids| contains the assigned ID and verification status of + // each SignedCertificateTimestamp. + void StoreSignedCertificateTimestamps( + const net::SignedCertificateTimestampAndStatusList& sct_list, + int process_id, + SignedCertificateTimestampIDStatusList* sct_ids); void CompleteResponseStarted(); void StartReading(bool is_continuation); void ResumeReading(); diff --git a/content/browser/loader/resource_request_info_impl.cc b/content/browser/loader/resource_request_info_impl.cc index 3d9ba3536e..32ba7ac6de 100644 --- a/content/browser/loader/resource_request_info_impl.cc +++ b/content/browser/loader/resource_request_info_impl.cc @@ -37,6 +37,7 @@ void ResourceRequestInfo::AllocateForTesting( render_view_id, // route_id 0, // origin_pid 0, // request_id + MSG_ROUTING_NONE, // render_frame_id resource_type == ResourceType::MAIN_FRAME, // is_main_frame 0, // frame_id false, // parent_is_main_frame @@ -90,6 +91,7 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl( int route_id, int origin_pid, int request_id, + int render_frame_id, bool is_main_frame, int64 frame_id, bool parent_is_main_frame, @@ -112,6 +114,7 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl( route_id_(route_id), origin_pid_(origin_pid), request_id_(request_id), + render_frame_id_(render_frame_id), is_main_frame_(is_main_frame), frame_id_(frame_id), parent_is_main_frame_(parent_is_main_frame), @@ -154,6 +157,10 @@ int ResourceRequestInfoImpl::GetRequestID() const { return request_id_; } +int ResourceRequestInfoImpl::GetRenderFrameID() const { + return render_frame_id_; +} + bool ResourceRequestInfoImpl::IsMainFrame() const { return is_main_frame_; } diff --git a/content/browser/loader/resource_request_info_impl.h b/content/browser/loader/resource_request_info_impl.h index 093c22f81c..2635106c5c 100644 --- a/content/browser/loader/resource_request_info_impl.h +++ b/content/browser/loader/resource_request_info_impl.h @@ -45,6 +45,7 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo, int route_id, int origin_pid, int request_id, + int render_frame_id, bool is_main_frame, int64 frame_id, bool parent_is_main_frame, @@ -68,6 +69,7 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo, virtual int GetRouteID() const OVERRIDE; virtual int GetOriginPID() const OVERRIDE; virtual int GetRequestID() const OVERRIDE; + virtual int GetRenderFrameID() const OVERRIDE; virtual bool IsMainFrame() const OVERRIDE; virtual int64 GetFrameID() const OVERRIDE; virtual bool ParentIsMainFrame() const OVERRIDE; @@ -164,6 +166,7 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo, int route_id_; int origin_pid_; int request_id_; + int render_frame_id_; bool is_main_frame_; int64 frame_id_; bool parent_is_main_frame_; diff --git a/content/browser/loader/resource_scheduler.cc b/content/browser/loader/resource_scheduler.cc index 9d05476c3b..4ae240e6fe 100644 --- a/content/browser/loader/resource_scheduler.cc +++ b/content/browser/loader/resource_scheduler.cc @@ -159,6 +159,10 @@ class ResourceScheduler::ScheduledResourceRequest deferred_ = *defer = !ready_; } + virtual const char* GetNameForLogging() const OVERRIDE { + return "ResourceScheduler"; + } + void DidChangePriority(int request_id, net::RequestPriority new_priority) { scheduler_->ReprioritizeRequest(this, new_priority); } @@ -370,7 +374,10 @@ void ResourceScheduler::LoadAnyStartablePendingRequests(Client* client) { StartRequest(request, client); // StartRequest can modify the pending list, so we (re)start evaluation - // from the currently highest priority request. + // from the currently highest priority request. Avoid copying a singular + // iterator, which would trigger undefined behavior. + if (client->pending_requests.GetNextHighestIterator().is_null()) + break; request_iter = client->pending_requests.GetNextHighestIterator(); } else if (query_result == DO_NOT_START_REQUEST_AND_KEEP_SEARCHING) { ++request_iter; diff --git a/content/browser/loader/resource_scheduler_unittest.cc b/content/browser/loader/resource_scheduler_unittest.cc index 60722eea88..07dd333703 100644 --- a/content/browser/loader/resource_scheduler_unittest.cc +++ b/content/browser/loader/resource_scheduler_unittest.cc @@ -92,6 +92,7 @@ class FakeResourceContext : public ResourceContext { virtual net::URLRequestContext* GetRequestContext() OVERRIDE { return NULL; } virtual bool AllowMicAccess(const GURL& origin) OVERRIDE { return false; } virtual bool AllowCameraAccess(const GURL& origin) OVERRIDE { return false; } + virtual std::string GetMediaDeviceIDSalt() OVERRIDE { return std::string(); } }; class FakeResourceMessageFilter : public ResourceMessageFilter { @@ -147,6 +148,7 @@ class ResourceSchedulerTest : public testing::Test { route_id, // route_id 0, // origin_pid ++next_request_id_, // request_id + MSG_ROUTING_NONE, // render_frame_id false, // is_main_frame 0, // frame_id false, // parent_is_main_frame diff --git a/content/browser/loader/throttling_resource_handler.cc b/content/browser/loader/throttling_resource_handler.cc index 23f77da90c..36c595fbf1 100644 --- a/content/browser/loader/throttling_resource_handler.cc +++ b/content/browser/loader/throttling_resource_handler.cc @@ -7,6 +7,7 @@ #include "content/browser/loader/resource_request_info_impl.h" #include "content/public/browser/resource_throttle.h" #include "content/public/common/resource_response.h" +#include "net/url_request/url_request.h" namespace content { @@ -17,10 +18,14 @@ ThrottlingResourceHandler::ThrottlingResourceHandler( : LayeredResourceHandler(request, next_handler.Pass()), deferred_stage_(DEFERRED_NONE), throttles_(throttles.Pass()), - index_(0), + next_index_(0), cancelled_by_resource_throttle_(false) { - for (size_t i = 0; i < throttles_.size(); ++i) + for (size_t i = 0; i < throttles_.size(); ++i) { throttles_[i]->set_controller(this); + // Throttles must have a name, as otherwise, bugs where a throttle fails + // to resume a request can be very difficult to debug. + DCHECK(throttles_[i]->GetNameForLogging()); + } } ThrottlingResourceHandler::~ThrottlingResourceHandler() { @@ -33,12 +38,14 @@ bool ThrottlingResourceHandler::OnRequestRedirected(int request_id, DCHECK(!cancelled_by_resource_throttle_); *defer = false; - while (index_ < throttles_.size()) { - throttles_[index_]->WillRedirectRequest(new_url, defer); - index_++; + while (next_index_ < throttles_.size()) { + int index = next_index_; + throttles_[index]->WillRedirectRequest(new_url, defer); + next_index_++; if (cancelled_by_resource_throttle_) return false; if (*defer) { + OnRequestDefered(index); deferred_stage_ = DEFERRED_REDIRECT; deferred_url_ = new_url; deferred_response_ = response; @@ -46,7 +53,7 @@ bool ThrottlingResourceHandler::OnRequestRedirected(int request_id, } } - index_ = 0; // Reset for next time. + next_index_ = 0; // Reset for next time. return next_handler_->OnRequestRedirected(request_id, new_url, response, defer); @@ -58,19 +65,21 @@ bool ThrottlingResourceHandler::OnWillStart(int request_id, DCHECK(!cancelled_by_resource_throttle_); *defer = false; - while (index_ < throttles_.size()) { - throttles_[index_]->WillStartRequest(defer); - index_++; + while (next_index_ < throttles_.size()) { + int index = next_index_; + throttles_[index]->WillStartRequest(defer); + next_index_++; if (cancelled_by_resource_throttle_) return false; if (*defer) { + OnRequestDefered(index); deferred_stage_ = DEFERRED_START; deferred_url_ = url; return true; // Do not cancel. } } - index_ = 0; // Reset for next time. + next_index_ = 0; // Reset for next time. return next_handler_->OnWillStart(request_id, url, defer); } @@ -80,19 +89,21 @@ bool ThrottlingResourceHandler::OnResponseStarted(int request_id, bool* defer) { DCHECK(!cancelled_by_resource_throttle_); - while (index_ < throttles_.size()) { - throttles_[index_]->WillProcessResponse(defer); - index_++; + while (next_index_ < throttles_.size()) { + int index = next_index_; + throttles_[index]->WillProcessResponse(defer); + next_index_++; if (cancelled_by_resource_throttle_) return false; if (*defer) { + OnRequestDefered(index); deferred_stage_ = DEFERRED_RESPONSE; deferred_response_ = response; return true; // Do not cancel. } } - index_ = 0; // Reset for next time. + next_index_ = 0; // Reset for next time. return next_handler_->OnResponseStarted(request_id, response, defer); } @@ -117,6 +128,8 @@ void ThrottlingResourceHandler::Resume() { DeferredStage last_deferred_stage = deferred_stage_; deferred_stage_ = DEFERRED_NONE; + // Clear information about the throttle that delayed the request. + request()->LogUnblocked(); switch (last_deferred_stage) { case DEFERRED_NONE: NOTREACHED(); @@ -177,4 +190,8 @@ void ThrottlingResourceHandler::ResumeResponse() { } } +void ThrottlingResourceHandler::OnRequestDefered(int throttle_index) { + request()->LogBlockedBy(throttles_[throttle_index]->GetNameForLogging()); +} + } // namespace content diff --git a/content/browser/loader/throttling_resource_handler.h b/content/browser/loader/throttling_resource_handler.h index 65117bc93d..9f98921e26 100644 --- a/content/browser/loader/throttling_resource_handler.h +++ b/content/browser/loader/throttling_resource_handler.h @@ -40,7 +40,7 @@ class ThrottlingResourceHandler : public LayeredResourceHandler, virtual bool OnWillStart(int request_id, const GURL& url, bool* defer) OVERRIDE; - // ResourceThrottleController implementation: + // ResourceController implementation: virtual void Cancel() OVERRIDE; virtual void CancelAndIgnore() OVERRIDE; virtual void CancelWithError(int error_code) OVERRIDE; @@ -51,6 +51,10 @@ class ThrottlingResourceHandler : public LayeredResourceHandler, void ResumeRedirect(); void ResumeResponse(); + // Called when the throttle at |throttle_index| defers a request. Logs the + // name of the throttle that delayed the request. + void OnRequestDefered(int throttle_index); + enum DeferredStage { DEFERRED_NONE, DEFERRED_START, @@ -60,7 +64,7 @@ class ThrottlingResourceHandler : public LayeredResourceHandler, DeferredStage deferred_stage_; ScopedVector<ResourceThrottle> throttles_; - size_t index_; + size_t next_index_; GURL deferred_url_; scoped_refptr<ResourceResponse> deferred_response_; diff --git a/content/browser/media/android/browser_media_player_manager.cc b/content/browser/media/android/browser_media_player_manager.cc index e8d185f579..99b785f235 100644 --- a/content/browser/media/android/browser_media_player_manager.cc +++ b/content/browser/media/android/browser_media_player_manager.cc @@ -34,6 +34,14 @@ using media::MediaSourcePlayer; // attempting to release inactive media players. static const int kMediaPlayerThreshold = 1; +// Maximum sizes for various EME message parameters. These are checks to +// prevent unnecessarily large messages from being passed around, and the sizes +// are somewhat arbitrary as the EME specification doesn't specify any limits. +static const size_t kEmeUuidSize = 16; +static const size_t kEmeTypeMaximum = 50; // Type is a MIME type. +static const size_t kEmeInitDataMaximum = 10240; // 10 KB +static const size_t kEmeResponseMaximum = 10240; // 10 KB + namespace content { static BrowserMediaPlayerManager::Factory g_factory = NULL; @@ -123,11 +131,9 @@ bool BrowserMediaPlayerManager::OnMessageReceived(const IPC::Message& msg) { DestroyAllMediaPlayers) IPC_MESSAGE_HANDLER(MediaKeysHostMsg_InitializeCDM, OnInitializeCDM) - IPC_MESSAGE_HANDLER(MediaKeysHostMsg_GenerateKeyRequest, - OnGenerateKeyRequest) - IPC_MESSAGE_HANDLER(MediaKeysHostMsg_AddKey, OnAddKey) - IPC_MESSAGE_HANDLER(MediaKeysHostMsg_CancelKeyRequest, - OnCancelKeyRequest) + IPC_MESSAGE_HANDLER(MediaKeysHostMsg_CreateSession, OnCreateSession) + IPC_MESSAGE_HANDLER(MediaKeysHostMsg_UpdateSession, OnUpdateSession) + IPC_MESSAGE_HANDLER(MediaKeysHostMsg_ReleaseSession, OnReleaseSession) #if defined(GOOGLE_TV) IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_NotifyExternalSurface, OnNotifyExternalSurface) @@ -193,11 +199,13 @@ void BrowserMediaPlayerManager::OnTimeUpdate(int player_id, void BrowserMediaPlayerManager::SetVideoSurface( gfx::ScopedJavaSurface surface) { MediaPlayerAndroid* player = GetFullscreenPlayer(); - if (player) { - player->SetVideoSurface(surface.Pass()); - Send(new MediaPlayerMsg_DidEnterFullscreen( - routing_id(), player->player_id())); + if (!player) + return; + if (!surface.IsEmpty()) { + Send(new MediaPlayerMsg_DidEnterFullscreen(routing_id(), + player->player_id())); } + player->SetVideoSurface(surface.Pass()); } void BrowserMediaPlayerManager::OnMediaMetadataChanged( @@ -355,7 +363,7 @@ void BrowserMediaPlayerManager::OnProtectedSurfaceRequested(int player_id) { // During the process, DisableFullscreenEncryptedMediaPlayback() may get // called before or after OnEnterFullscreen(). If it is called before // OnEnterFullscreen(), the player will not enter fullscreen. And it will - // retry the process once the GenerateKeyRequest is allowed to proceed + // retry the process once CreateSession() is allowed to proceed. // TODO(qinmin): make this flag default on android. if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableGestureRequirementForMediaFullscreen)) { @@ -363,34 +371,42 @@ void BrowserMediaPlayerManager::OnProtectedSurfaceRequested(int player_id) { } } -void BrowserMediaPlayerManager::OnKeyAdded(int media_keys_id, - uint32 reference_id) { - Send(new MediaKeysMsg_KeyAdded(routing_id(), media_keys_id, reference_id)); -} +// The following 5 functions are EME MediaKeySession events. -void BrowserMediaPlayerManager::OnKeyError( +void BrowserMediaPlayerManager::OnSessionCreated( int media_keys_id, - uint32 reference_id, - media::MediaKeys::KeyError error_code, - int system_code) { - Send(new MediaKeysMsg_KeyError(routing_id(), media_keys_id, - reference_id, error_code, system_code)); + uint32 session_id, + const std::string& web_session_id) { + Send(new MediaKeysMsg_SessionCreated( + routing_id(), media_keys_id, session_id, web_session_id)); } -void BrowserMediaPlayerManager::OnKeyMessage( +void BrowserMediaPlayerManager::OnSessionMessage( int media_keys_id, - uint32 reference_id, + uint32 session_id, const std::vector<uint8>& message, const std::string& destination_url) { - Send(new MediaKeysMsg_KeyMessage(routing_id(), media_keys_id, - reference_id, message, destination_url)); + Send(new MediaKeysMsg_SessionMessage( + routing_id(), media_keys_id, session_id, message, destination_url)); } -void BrowserMediaPlayerManager::OnSetSessionId(int media_keys_id, - uint32 reference_id, - const std::string& session_id) { - Send(new MediaKeysMsg_SetSessionId( - routing_id(), media_keys_id, reference_id, session_id)); +void BrowserMediaPlayerManager::OnSessionReady(int media_keys_id, + uint32 session_id) { + Send(new MediaKeysMsg_SessionReady(routing_id(), media_keys_id, session_id)); +} + +void BrowserMediaPlayerManager::OnSessionClosed(int media_keys_id, + uint32 session_id) { + Send(new MediaKeysMsg_SessionClosed(routing_id(), media_keys_id, session_id)); +} + +void BrowserMediaPlayerManager::OnSessionError( + int media_keys_id, + uint32 session_id, + media::MediaKeys::KeyError error_code, + int system_code) { + Send(new MediaKeysMsg_SessionError( + routing_id(), media_keys_id, session_id, error_code, system_code)); } #if defined(GOOGLE_TV) @@ -538,27 +554,46 @@ void BrowserMediaPlayerManager::OnInitializeCDM( int media_keys_id, const std::vector<uint8>& uuid, const GURL& frame_url) { + if (uuid.size() != kEmeUuidSize) { + // This failure will be discovered and reported by OnCreateSession() + // as GetDrmBridge() will return null. + NOTREACHED() << "Invalid UUID for ID: " << media_keys_id; + return; + } + AddDrmBridge(media_keys_id, uuid, frame_url); // In EME v0.1b MediaKeys lives in the media element. So the |media_keys_id| // is the same as the |player_id|. OnSetMediaKeys(media_keys_id, media_keys_id); } -void BrowserMediaPlayerManager::OnGenerateKeyRequest( +void BrowserMediaPlayerManager::OnCreateSession( int media_keys_id, - uint32 reference_id, + uint32 session_id, const std::string& type, const std::vector<uint8>& init_data) { + if (type.length() > kEmeTypeMaximum) { + OnSessionError( + media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); + return; + } + if (init_data.size() > kEmeInitDataMaximum) { + OnSessionError( + media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); + return; + } + if (CommandLine::ForCurrentProcess() ->HasSwitch(switches::kDisableInfobarForProtectedMediaIdentifier)) { - GenerateKeyIfAllowed(media_keys_id, reference_id, type, init_data, true); + GenerateKeyIfAllowed(media_keys_id, session_id, type, init_data, true); return; } MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id); if (!drm_bridge) { DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found"; - OnKeyError(media_keys_id, reference_id, media::MediaKeys::kUnknownError, 0); + OnSessionError( + media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); return; } @@ -572,25 +607,32 @@ void BrowserMediaPlayerManager::OnGenerateKeyRequest( base::Bind(&BrowserMediaPlayerManager::GenerateKeyIfAllowed, weak_ptr_factory_.GetWeakPtr(), media_keys_id, - reference_id, + session_id, type, init_data)); } -void BrowserMediaPlayerManager::OnAddKey(int media_keys_id, - uint32 reference_id, - const std::vector<uint8>& key, - const std::vector<uint8>& init_data) { +void BrowserMediaPlayerManager::OnUpdateSession( + int media_keys_id, + uint32 session_id, + const std::vector<uint8>& response) { MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id); if (!drm_bridge) { DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found"; - OnKeyError(media_keys_id, reference_id, media::MediaKeys::kUnknownError, 0); + OnSessionError( + media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); return; } - drm_bridge->AddKey(reference_id, - &key[0], key.size(), - &init_data[0], init_data.size()); + if (response.size() > kEmeResponseMaximum) { + DLOG(WARNING) << "Response for ID: " << media_keys_id + << " too long: " << response.size(); + OnSessionError( + media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); + return; + } + + drm_bridge->UpdateSession(session_id, &response[0], response.size()); // In EME v0.1b MediaKeys lives in the media element. So the |media_keys_id| // is the same as the |player_id|. // TODO(xhwang): Separate |media_keys_id| and |player_id|. @@ -599,17 +641,17 @@ void BrowserMediaPlayerManager::OnAddKey(int media_keys_id, player->OnKeyAdded(); } -void BrowserMediaPlayerManager::OnCancelKeyRequest( - int media_keys_id, - uint32 reference_id) { +void BrowserMediaPlayerManager::OnReleaseSession(int media_keys_id, + uint32 session_id) { MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id); if (!drm_bridge) { DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found"; - OnKeyError(media_keys_id, reference_id, media::MediaKeys::kUnknownError, 0); + OnSessionError( + media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); return; } - drm_bridge->CancelKeyRequest(reference_id); + drm_bridge->ReleaseSession(session_id); } void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) { @@ -672,7 +714,7 @@ void BrowserMediaPlayerManager::AddDrmBridge(int media_keys_id, scoped_ptr<MediaDrmBridge> drm_bridge(MediaDrmBridge::Create( media_keys_id, uuid, frame_url, security_level, this)); if (!drm_bridge) { - // This failure will be discovered and reported by OnGenerateKeyRequest() + // This failure will be discovered and reported by OnCreateSession() // as GetDrmBridge() will return null. DVLOG(1) << "failed to create drm bridge."; return; @@ -706,7 +748,7 @@ void BrowserMediaPlayerManager::OnSetMediaKeys(int player_id, void BrowserMediaPlayerManager::GenerateKeyIfAllowed( int media_keys_id, - uint32 reference_id, + uint32 session_id, const std::string& type, const std::vector<uint8>& init_data, bool allowed) { @@ -716,13 +758,13 @@ void BrowserMediaPlayerManager::GenerateKeyIfAllowed( MediaDrmBridge* drm_bridge = GetDrmBridge(media_keys_id); if (!drm_bridge) { DLOG(WARNING) << "No MediaDrmBridge for ID: " << media_keys_id << " found"; - OnKeyError(media_keys_id, reference_id, media::MediaKeys::kUnknownError, 0); + OnSessionError( + media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); return; } media_keys_ids_pending_approval_.erase(media_keys_id); media_keys_ids_approved_.insert(media_keys_id); - drm_bridge->GenerateKeyRequest( - reference_id, type, &init_data[0], init_data.size()); + drm_bridge->CreateSession(session_id, type, &init_data[0], init_data.size()); // TODO(qinmin): currently |media_keys_id| and player ID are identical. // This might not be true in the future. diff --git a/content/browser/media/android/browser_media_player_manager.h b/content/browser/media/android/browser_media_player_manager.h index bd5ad7800d..36ed0618ea 100644 --- a/content/browser/media/android/browser_media_player_manager.h +++ b/content/browser/media/android/browser_media_player_manager.h @@ -90,19 +90,19 @@ class CONTENT_EXPORT BrowserMediaPlayerManager virtual media::MediaDrmBridge* GetDrmBridge(int media_keys_id) OVERRIDE; virtual void DestroyAllMediaPlayers() OVERRIDE; virtual void OnProtectedSurfaceRequested(int player_id) OVERRIDE; - virtual void OnKeyAdded(int media_keys_id, - uint32 reference_id) OVERRIDE; - virtual void OnKeyError(int media_keys_id, - uint32 reference_id, - media::MediaKeys::KeyError error_code, - int system_code) OVERRIDE; - virtual void OnKeyMessage(int media_keys_id, - uint32 reference_id, - const std::vector<uint8>& message, - const std::string& destination_url) OVERRIDE; - virtual void OnSetSessionId(int media_keys_id, - uint32 reference_id, - const std::string& session_id) OVERRIDE; + virtual void OnSessionCreated(int media_keys_id, + uint32 session_id, + const std::string& web_session_id) OVERRIDE; + virtual void OnSessionMessage(int media_keys_id, + uint32 session_id, + const std::vector<uint8>& message, + const std::string& destination_url) OVERRIDE; + virtual void OnSessionReady(int media_keys_id, uint32 session_id) OVERRIDE; + virtual void OnSessionClosed(int media_keys_id, uint32 session_id) OVERRIDE; + virtual void OnSessionError(int media_keys_id, + uint32 session_id, + media::MediaKeys::KeyError error_code, + int system_code) OVERRIDE; #if defined(GOOGLE_TV) void AttachExternalVideoSurface(int player_id, jobject surface); @@ -135,15 +135,14 @@ class CONTENT_EXPORT BrowserMediaPlayerManager void OnInitializeCDM(int media_keys_id, const std::vector<uint8>& uuid, const GURL& frame_url); - void OnGenerateKeyRequest(int media_keys_id, - uint32 reference_id, - const std::string& type, - const std::vector<uint8>& init_data); - void OnAddKey(int media_keys_id, - uint32 reference_id, - const std::vector<uint8>& key, - const std::vector<uint8>& init_data); - void OnCancelKeyRequest(int media_keys_id, uint32 reference_id); + void OnCreateSession(int media_keys_id, + uint32 session_id, + const std::string& type, + const std::vector<uint8>& init_data); + void OnUpdateSession(int media_keys_id, + uint32 session_id, + const std::vector<uint8>& response); + void OnReleaseSession(int media_keys_id, uint32 session_id); void OnSetMediaKeys(int player_id, int media_keys_id); #if defined(GOOGLE_TV) @@ -175,7 +174,7 @@ class CONTENT_EXPORT BrowserMediaPlayerManager private: void GenerateKeyIfAllowed(int media_keys_id, - uint32 reference_id, + uint32 session_id, const std::string& type, const std::vector<uint8>& init_data, bool allowed); diff --git a/content/browser/media/media_browsertest.cc b/content/browser/media/media_browsertest.cc index 215b3e7ff2..0655823363 100644 --- a/content/browser/media/media_browsertest.cc +++ b/content/browser/media/media_browsertest.cc @@ -59,13 +59,13 @@ void MediaBrowserTest::RunMediaTestPage( } void MediaBrowserTest::RunTest(const GURL& gurl, const char* expected) { - const string16 expected_title = ASCIIToUTF16(expected); + const base::string16 expected_title = ASCIIToUTF16(expected); DVLOG(1) << "Running test URL: " << gurl; TitleWatcher title_watcher(shell()->web_contents(), expected_title); AddWaitForTitles(&title_watcher); NavigateToURL(shell(), gurl); - string16 final_title = title_watcher.WaitAndGetTitle(); + base::string16 final_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, final_title); } diff --git a/content/browser/media_devices_monitor.cc b/content/browser/media/media_devices_monitor.cc index 72c3b4b1ce..9f2c18353f 100644 --- a/content/browser/media_devices_monitor.cc +++ b/content/browser/media/media_devices_monitor.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -12,8 +12,7 @@ namespace content { namespace { void EnsureMonitorCaptureDevicesInternal( MediaStreamManager* media_stream_manager) { - media_stream_manager->EnumerateDevices( - NULL, -1, -1, -1, MEDIA_DEVICE_AUDIO_CAPTURE, GURL()); + media_stream_manager->EnsureDeviceMonitorStarted(); } } diff --git a/content/browser/media/media_internals.cc b/content/browser/media/media_internals.cc index 1e0538e49f..1ee42d1757 100644 --- a/content/browser/media/media_internals.cc +++ b/content/browser/media/media_internals.cc @@ -17,8 +17,8 @@ namespace { static base::LazyInstance<content::MediaInternals>::Leaky g_media_internals = LAZY_INSTANCE_INITIALIZER; -string16 SerializeUpdate(const std::string& function, - const base::Value* value) { +base::string16 SerializeUpdate(const std::string& function, + const base::Value* value) { return content::WebUI::GetJavascriptCall( function, std::vector<const base::Value*>(1, value)); } @@ -185,7 +185,7 @@ void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) { } void MediaInternals::SendEverything() { - string16 everything_update; + base::string16 everything_update; { base::AutoLock auto_lock(lock_); everything_update = SerializeUpdate( @@ -194,7 +194,7 @@ void MediaInternals::SendEverything() { SendUpdate(everything_update); } -void MediaInternals::SendUpdate(const string16& update) { +void MediaInternals::SendUpdate(const base::string16& update) { // SendUpdate() may be called from any thread, but must run on the IO thread. // TODO(dalecurtis): This is pretty silly since the update callbacks simply // forward the calls to the UI thread. We should avoid the extra hop. diff --git a/content/browser/media/media_internals.h b/content/browser/media/media_internals.h index 8a179e0197..c0f144a5b8 100644 --- a/content/browser/media/media_internals.h +++ b/content/browser/media/media_internals.h @@ -37,7 +37,7 @@ class CONTENT_EXPORT MediaInternals const std::vector<media::MediaLogEvent>& events); // Called with the update string. - typedef base::Callback<void(const string16&)> UpdateCallback; + typedef base::Callback<void(const base::string16&)> UpdateCallback; // Add/remove update callbacks (see above). Must be called on the IO thread. void AddUpdateCallback(const UpdateCallback& callback); @@ -59,7 +59,7 @@ class CONTENT_EXPORT MediaInternals // Sends |update| to each registered UpdateCallback. Safe to call from any // thread, but will forward to the IO thread. - void SendUpdate(const string16& update); + void SendUpdate(const base::string16& update); // Caches |value| under |cache_key| so that future SendEverything() calls will // include the current data. Calls JavaScript |function|(|value|) for each diff --git a/content/browser/media/media_internals_handler.cc b/content/browser/media/media_internals_handler.cc index a45dd4f51e..9a3e7be214 100644 --- a/content/browser/media/media_internals_handler.cc +++ b/content/browser/media/media_internals_handler.cc @@ -38,12 +38,12 @@ void MediaInternalsMessageHandler::OnGetEverything( proxy_->GetEverything(); } -void MediaInternalsMessageHandler::OnUpdate(const string16& update) { +void MediaInternalsMessageHandler::OnUpdate(const base::string16& update) { // Don't try to execute JavaScript in a RenderView that no longer exists nor // if the chrome://media-internals page hasn't finished loading. RenderViewHost* host = web_ui()->GetWebContents()->GetRenderViewHost(); if (host && page_load_complete_) - host->ExecuteJavascriptInWebFrame(string16(), update); + host->ExecuteJavascriptInWebFrame(base::string16(), update); } } // namespace content diff --git a/content/browser/media/media_internals_handler.h b/content/browser/media/media_internals_handler.h index 8ea6f88a46..265c1224d7 100644 --- a/content/browser/media/media_internals_handler.h +++ b/content/browser/media/media_internals_handler.h @@ -30,7 +30,7 @@ class MediaInternalsMessageHandler : public WebUIMessageHandler { void OnGetEverything(const base::ListValue* list); // MediaInternals message handlers. - void OnUpdate(const string16& update); + void OnUpdate(const base::string16& update); private: scoped_refptr<MediaInternalsProxy> proxy_; diff --git a/content/browser/media/media_internals_proxy.cc b/content/browser/media/media_internals_proxy.cc index d0e0622b41..49456ab498 100644 --- a/content/browser/media/media_internals_proxy.cc +++ b/content/browser/media/media_internals_proxy.cc @@ -69,7 +69,7 @@ void MediaInternalsProxy::GetEverything() { CallJavaScriptFunctionOnUIThread("media.onReceiveConstants", GetConstants()); } -void MediaInternalsProxy::OnUpdate(const string16& update) { +void MediaInternalsProxy::OnUpdate(const base::string16& update) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, @@ -140,7 +140,7 @@ void MediaInternalsProxy::GetEverythingOnIOThread() { MediaInternals::GetInstance()->SendEverything(); } -void MediaInternalsProxy::UpdateUIOnUIThread(const string16& update) { +void MediaInternalsProxy::UpdateUIOnUIThread(const base::string16& update) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); // Don't forward updates to a destructed UI. if (handler_) @@ -175,7 +175,7 @@ void MediaInternalsProxy::CallJavaScriptFunctionOnUIThread( scoped_ptr<base::Value> args_value(args); std::vector<const base::Value*> args_vector; args_vector.push_back(args_value.get()); - string16 update = WebUI::GetJavascriptCall(function, args_vector); + base::string16 update = WebUI::GetJavascriptCall(function, args_vector); UpdateUIOnUIThread(update); } diff --git a/content/browser/media/media_internals_proxy.h b/content/browser/media/media_internals_proxy.h index 5d173b3e73..b737b858a3 100644 --- a/content/browser/media/media_internals_proxy.h +++ b/content/browser/media/media_internals_proxy.h @@ -49,7 +49,7 @@ class MediaInternalsProxy void GetEverything(); // MediaInternals callback. Called on the IO thread. - void OnUpdate(const string16& update); + void OnUpdate(const base::string16& update); // net::NetLog::ThreadSafeObserver implementation. Callable from any thread: virtual void OnAddEntry(const net::NetLog::Entry& entry) OVERRIDE; @@ -65,7 +65,7 @@ class MediaInternalsProxy void ObserveMediaInternalsOnIOThread(); void StopObservingMediaInternalsOnIOThread(); void GetEverythingOnIOThread(); - void UpdateUIOnUIThread(const string16& update); + void UpdateUIOnUIThread(const base::string16& update); // Put |entry| on a list of events to be sent to the page. void AddNetEventOnUIThread(base::Value* entry); diff --git a/content/browser/media/media_internals_unittest.cc b/content/browser/media/media_internals_unittest.cc index e16124bd09..2947104cad 100644 --- a/content/browser/media/media_internals_unittest.cc +++ b/content/browser/media/media_internals_unittest.cc @@ -45,7 +45,7 @@ class MediaInternalsTest protected: // Extracts and deserializes the JSON update data; merges into |update_data_|. - void UpdateCallbackImpl(const string16& update) { + void UpdateCallbackImpl(const base::string16& update) { // Each update string looks like "<JavaScript Function Name>({<JSON>});", to // use the JSON reader we need to strip out the JavaScript code. std::string utf8_update = base::UTF16ToUTF8(update); diff --git a/content/browser/media/webrtc_browsertest.cc b/content/browser/media/webrtc_browsertest.cc index bfb96e1519..47847a7d53 100644 --- a/content/browser/media/webrtc_browsertest.cc +++ b/content/browser/media/webrtc_browsertest.cc @@ -14,6 +14,7 @@ #include "content/shell/browser/shell.h" #include "content/test/content_browser_test.h" #include "content/test/content_browser_test_utils.h" +#include "media/audio/audio_manager.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/perf/perf_test.h" @@ -21,6 +22,14 @@ #include "base/win/windows_version.h" #endif +const char kForceIsac16K[] = +#ifdef OS_ANDROID + // The default audio codec, Opus, doesn't work on Android. + "true"; +#else + "false"; +#endif + namespace { static const char kGetUserMediaAndStop[] = "getUserMediaAndStop"; @@ -130,7 +139,7 @@ class WebrtcBrowserTest: public ContentBrowserTest { } void ExpectTitle(const std::string& expected_title) const { - string16 expected_title16(ASCIIToUTF16(expected_title)); + base::string16 expected_title16(ASCIIToUTF16(expected_title)); TitleWatcher title_watcher(shell()->web_contents(), expected_title16); EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); } @@ -558,4 +567,55 @@ IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, AddTwoMediaStreamsToOnePC) { ExpectTitle("OK"); } +IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, + EstablishAudioVideoCallAndMeasureOutputLevel) { + if (!media::AudioManager::Get()->HasAudioOutputDevices()) { + // Bots with no output devices will force the audio code into a different + // path where it doesn't manage to set either the low or high latency path. + // This test will compute useless values in that case, so skip running on + // such bots (see crbug.com/326338). + LOG(INFO) << "Missing output devices: skipping test..."; + return; + } + + ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch( + switches::kUseFakeDeviceForMediaStream)) + << "Must run with fake devices since the test will explicitly look " + << "for the fake device signal."; + + GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html")); + NavigateToURL(shell(), url); + + EXPECT_TRUE(ExecuteJavascript( + base::StringPrintf("callAndEnsureAudioIsPlaying(%s);", kForceIsac16K))); + ExpectTitle("OK"); +} + +IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, + EstablishAudioVideoCallAndVerifyMutingWorks) { + if (!media::AudioManager::Get()->HasAudioOutputDevices()) { + // Bots with no output devices will force the audio code into a different + // path where it doesn't manage to set either the low or high latency path. + // This test will compute useless values in that case, so skip running on + // such bots (see crbug.com/326338). + LOG(INFO) << "Missing output devices: skipping test..."; + return; + } + + ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch( + switches::kUseFakeDeviceForMediaStream)) + << "Must run with fake devices since the test will explicitly look " + << "for the fake device signal."; + + GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html")); + NavigateToURL(shell(), url); + + EXPECT_TRUE(ExecuteJavascript( + base::StringPrintf("callAndEnsureAudioMutingWorks(%s);", + kForceIsac16K))); + ExpectTitle("OK"); +} + } // namespace content diff --git a/content/browser/media/webrtc_identity_store_backend.cc b/content/browser/media/webrtc_identity_store_backend.cc index 5aed5207a0..d599dcda74 100644 --- a/content/browser/media/webrtc_identity_store_backend.cc +++ b/content/browser/media/webrtc_identity_store_backend.cc @@ -369,7 +369,7 @@ void WebRTCIdentityStoreBackend::SqlLiteStorage::Load(IdentityMap* out_map) { // Ensure the parent directory for storing certs is created before reading // from it. const base::FilePath dir = path_.DirName(); - if (!base::PathExists(dir) && !file_util::CreateDirectory(dir)) { + if (!base::PathExists(dir) && !base::CreateDirectory(dir)) { DLOG(ERROR) << "Unable to open DB file path."; return; } diff --git a/content/browser/media/webrtc_internals_browsertest.cc b/content/browser/media/webrtc_internals_browsertest.cc index b45827623b..0d279b3075 100644 --- a/content/browser/media/webrtc_internals_browsertest.cc +++ b/content/browser/media/webrtc_internals_browsertest.cc @@ -145,7 +145,7 @@ class MAYBE_WebRTCInternalsBrowserTest: public ContentBrowserTest { } void ExpectTitle(const std::string& expected_title) const { - string16 expected_title16(ASCIIToUTF16(expected_title)); + base::string16 expected_title16(ASCIIToUTF16(expected_title)); TitleWatcher title_watcher(shell()->web_contents(), expected_title16); EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); } diff --git a/content/browser/media/webrtc_internals_message_handler.cc b/content/browser/media/webrtc_internals_message_handler.cc index 2ba7522738..8cf8579028 100644 --- a/content/browser/media/webrtc_internals_message_handler.cc +++ b/content/browser/media/webrtc_internals_message_handler.cc @@ -68,11 +68,11 @@ void WebRTCInternalsMessageHandler::OnUpdate(const std::string& command, DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); std::vector<const base::Value*> args_vector; args_vector.push_back(args); - string16 update = WebUI::GetJavascriptCall(command, args_vector); + base::string16 update = WebUI::GetJavascriptCall(command, args_vector); RenderViewHost* host = web_ui()->GetWebContents()->GetRenderViewHost(); if (host) - host->ExecuteJavascriptInWebFrame(string16(), update); + host->ExecuteJavascriptInWebFrame(base::string16(), update); } } // namespace content diff --git a/content/browser/message_port_service.cc b/content/browser/message_port_service.cc index bc2a1ac826..0d9f6084e8 100644 --- a/content/browser/message_port_service.cc +++ b/content/browser/message_port_service.cc @@ -108,7 +108,7 @@ void MessagePortService::Entangle(int local_message_port_id, void MessagePortService::PostMessage( int sender_message_port_id, - const string16& message, + const base::string16& message, const std::vector<int>& sent_message_port_ids) { if (!message_ports_.count(sender_message_port_id)) { NOTREACHED(); @@ -130,7 +130,7 @@ void MessagePortService::PostMessage( void MessagePortService::PostMessageTo( int message_port_id, - const string16& message, + const base::string16& message, const std::vector<int>& sent_message_port_ids) { if (!message_ports_.count(message_port_id)) { NOTREACHED(); diff --git a/content/browser/message_port_service.h b/content/browser/message_port_service.h index 55e536c1dd..668959167f 100644 --- a/content/browser/message_port_service.h +++ b/content/browser/message_port_service.h @@ -19,7 +19,8 @@ class MessagePortMessageFilter; class MessagePortService { public: - typedef std::vector<std::pair<string16, std::vector<int> > > QueuedMessages; + typedef std::vector<std::pair<base::string16, std::vector<int> > > + QueuedMessages; // Returns the MessagePortService singleton. static MessagePortService* GetInstance(); @@ -31,7 +32,7 @@ class MessagePortService { void Destroy(int message_port_id); void Entangle(int local_message_port_id, int remote_message_port_id); void PostMessage(int sender_message_port_id, - const string16& message, + const base::string16& message, const std::vector<int>& sent_message_port_ids); void QueueMessages(int message_port_id); void SendQueuedMessages(int message_port_id, @@ -56,7 +57,7 @@ class MessagePortService { ~MessagePortService(); void PostMessageTo(int message_port_id, - const string16& message, + const base::string16& message, const std::vector<int>& sent_message_port_ids); // Handles the details of removing a message port id. Before calling this, diff --git a/content/browser/net/sqlite_persistent_cookie_store.cc b/content/browser/net/sqlite_persistent_cookie_store.cc index 1c0a8e7a72..a337733922 100644 --- a/content/browser/net/sqlite_persistent_cookie_store.cc +++ b/content/browser/net/sqlite_persistent_cookie_store.cc @@ -544,12 +544,12 @@ bool SQLitePersistentCookieStore::Backend::InitializeDatabase() { base::Time start = base::Time::Now(); const base::FilePath dir = path_.DirName(); - if (!base::PathExists(dir) && !file_util::CreateDirectory(dir)) { + if (!base::PathExists(dir) && !base::CreateDirectory(dir)) { return false; } int64 db_size = 0; - if (file_util::GetFileSize(path_, &db_size)) + if (base::GetFileSize(path_, &db_size)) UMA_HISTOGRAM_COUNTS("Cookie.DBSizeInKB", db_size / 1024 ); db_.reset(new sql::Connection); diff --git a/content/browser/net/sqlite_persistent_cookie_store_unittest.cc b/content/browser/net/sqlite_persistent_cookie_store_unittest.cc index 4adb790668..49ac64be46 100644 --- a/content/browser/net/sqlite_persistent_cookie_store_unittest.cc +++ b/content/browser/net/sqlite_persistent_cookie_store_unittest.cc @@ -289,7 +289,7 @@ TEST_F(SQLitePersistentCookieStoreTest, TestFlush) { // whether the DB file has been modified by checking its size. base::FilePath path = temp_dir_.path().Append(kCookieFilename); base::PlatformFileInfo info; - ASSERT_TRUE(file_util::GetFileInfo(path, &info)); + ASSERT_TRUE(base::GetFileInfo(path, &info)); int64 base_size = info.size; // Write some large cookies, so the DB will have to expand by several KB. @@ -304,7 +304,7 @@ TEST_F(SQLitePersistentCookieStoreTest, TestFlush) { Flush(); // We forced a write, so now the file will be bigger. - ASSERT_TRUE(file_util::GetFileInfo(path, &info)); + ASSERT_TRUE(base::GetFileInfo(path, &info)); ASSERT_GT(info.size, base_size); } diff --git a/content/browser/plugin_browsertest.cc b/content/browser/plugin_browsertest.cc index 2a846f124f..204a143203 100644 --- a/content/browser/plugin_browsertest.cc +++ b/content/browser/plugin_browsertest.cc @@ -83,12 +83,12 @@ class PluginTest : public ContentBrowserTest { } static void LoadAndWaitInWindow(Shell* window, const GURL& url) { - string16 expected_title(ASCIIToUTF16("OK")); + base::string16 expected_title(ASCIIToUTF16("OK")); TitleWatcher title_watcher(window->web_contents(), expected_title); title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL")); title_watcher.AlsoWaitForTitle(ASCIIToUTF16("plugin_not_found")); NavigateToURL(window, url); - string16 title = title_watcher.WaitAndGetTitle(); + base::string16 title = title_watcher.WaitAndGetTitle(); if (title == ASCIIToUTF16("plugin_not_found")) { const testing::TestInfo* const test_info = testing::UnitTest::GetInstance()->current_test_info(); @@ -170,7 +170,7 @@ IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInvokeInSynchronousMouseUp)) { NavigateToURL(shell(), GetURL("execute_script_delete_in_mouse_up.html")); - string16 expected_title(ASCIIToUTF16("OK")); + base::string16 expected_title(ASCIIToUTF16("OK")); TitleWatcher title_watcher(shell()->web_contents(), expected_title); title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL")); SimulateMouseClick(shell()->web_contents(), 0, @@ -201,7 +201,7 @@ IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInvokeAlert)) { // race condition where the alert can come up before we start watching for it. shell()->LoadURL(GetURL("self_delete_plugin_invoke_alert.html")); - string16 expected_title(ASCIIToUTF16("OK")); + base::string16 expected_title(ASCIIToUTF16("OK")); TitleWatcher title_watcher(shell()->web_contents(), expected_title); title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL")); @@ -408,7 +408,7 @@ IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_PluginConvertPointTest) { NavigateToURL(shell(), GetURL("convert_point.html")); - string16 expected_title(ASCIIToUTF16("OK")); + base::string16 expected_title(ASCIIToUTF16("OK")); TitleWatcher title_watcher(shell()->web_contents(), expected_title); title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL")); // TODO(stuartmorgan): When the automation system supports sending clicks, diff --git a/content/browser/plugin_loader_posix_unittest.cc b/content/browser/plugin_loader_posix_unittest.cc index 8f90723212..13620f74dd 100644 --- a/content/browser/plugin_loader_posix_unittest.cc +++ b/content/browser/plugin_loader_posix_unittest.cc @@ -64,11 +64,11 @@ class PluginLoaderPosixTest : public testing::Test { public: PluginLoaderPosixTest() : plugin1_(ASCIIToUTF16("plugin1"), base::FilePath("/tmp/one.plugin"), - ASCIIToUTF16("1.0"), string16()), + ASCIIToUTF16("1.0"), base::string16()), plugin2_(ASCIIToUTF16("plugin2"), base::FilePath("/tmp/two.plugin"), - ASCIIToUTF16("2.0"), string16()), + ASCIIToUTF16("2.0"), base::string16()), plugin3_(ASCIIToUTF16("plugin3"), base::FilePath("/tmp/three.plugin"), - ASCIIToUTF16("3.0"), string16()), + ASCIIToUTF16("3.0"), base::string16()), file_thread_(BrowserThread::FILE, &message_loop_), io_thread_(BrowserThread::IO, &message_loop_), plugin_loader_(new MockPluginLoaderPosix) { diff --git a/content/browser/plugin_service_impl.cc b/content/browser/plugin_service_impl.cc index 1ddcf4012a..74feedeec3 100644 --- a/content/browser/plugin_service_impl.cc +++ b/content/browser/plugin_service_impl.cc @@ -298,7 +298,12 @@ PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess( START_NPAPI_FLASH_AT_LEAST_ONCE, FLASH_USAGE_ENUM_COUNT); } - +#if defined(OS_CHROMEOS) + // TODO(ihf): Move to an earlier place once crbug.com/314301 is fixed. For now + // we still want Plugin.FlashUsage recorded if we end up here. + LOG(WARNING) << "Refusing to start npapi plugin on ChromeOS."; + return NULL; +#endif // This plugin isn't loaded by any plugin process, so create a new process. scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost()); if (!new_host->Init(info)) { @@ -314,8 +319,10 @@ PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess( const base::FilePath& profile_data_directory) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path)) + if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path)) { + VLOG(1) << "Unable to load ppapi plugin: " << plugin_path.MaybeAsASCII(); return NULL; + } PpapiPluginProcessHost* plugin_host = FindPpapiPluginProcess(plugin_path, profile_data_directory); @@ -324,8 +331,11 @@ PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess( // Validate that the plugin is actually registered. PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path); - if (!info) + if (!info) { + VLOG(1) << "Unable to find ppapi plugin registration for: " + << plugin_path.MaybeAsASCII(); return NULL; + } // Record when PPAPI Flash process is started for the first time. static bool counted = false; @@ -337,8 +347,14 @@ PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess( } // This plugin isn't loaded by any plugin process, so create a new process. - return PpapiPluginProcessHost::CreatePluginHost( + plugin_host = PpapiPluginProcessHost::CreatePluginHost( *info, profile_data_directory); + if (!plugin_host) { + VLOG(1) << "Unable to create ppapi plugin process for: " + << plugin_path.MaybeAsASCII(); + } + + return plugin_host; } PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess( @@ -367,7 +383,7 @@ PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess( void PluginServiceImpl::OpenChannelToNpapiPlugin( int render_process_id, - int render_view_id, + int render_frame_id, const GURL& url, const GURL& page_url, const std::string& mime_type, @@ -379,7 +395,7 @@ void PluginServiceImpl::OpenChannelToNpapiPlugin( // Make sure plugins are loaded if necessary. PluginServiceFilterParams params = { render_process_id, - render_view_id, + render_frame_id, page_url, client->GetResourceContext() }; @@ -430,14 +446,14 @@ void PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin( const std::string& mime_type, PluginProcessHost::Client* client, const std::vector<WebPluginInfo>&) { - GetAllowedPluginForOpenChannelToPlugin(params.render_process_id, - params.render_view_id, url, params.page_url, mime_type, client, - params.resource_context); + GetAllowedPluginForOpenChannelToPlugin( + params.render_process_id, params.render_frame_id, url, params.page_url, + mime_type, client, params.resource_context); } void PluginServiceImpl::GetAllowedPluginForOpenChannelToPlugin( int render_process_id, - int render_view_id, + int render_frame_id, const GURL& url, const GURL& page_url, const std::string& mime_type, @@ -446,7 +462,7 @@ void PluginServiceImpl::GetAllowedPluginForOpenChannelToPlugin( WebPluginInfo info; bool allow_wildcard = true; bool found = GetPluginInfo( - render_process_id, render_view_id, resource_context, + render_process_id, render_frame_id, resource_context, url, page_url, mime_type, allow_wildcard, NULL, &info, NULL); base::FilePath plugin_path; @@ -498,7 +514,7 @@ bool PluginServiceImpl::GetPluginInfoArray( } bool PluginServiceImpl::GetPluginInfo(int render_process_id, - int render_view_id, + int render_frame_id, ResourceContext* context, const GURL& url, const GURL& page_url, @@ -516,7 +532,7 @@ bool PluginServiceImpl::GetPluginInfo(int render_process_id, for (size_t i = 0; i < plugins.size(); ++i) { if (!filter_ || filter_->IsPluginAvailable(render_process_id, - render_view_id, + render_frame_id, context, url, page_url, @@ -547,9 +563,9 @@ bool PluginServiceImpl::GetPluginInfoByPath(const base::FilePath& plugin_path, return false; } -string16 PluginServiceImpl::GetPluginDisplayNameByPath( +base::string16 PluginServiceImpl::GetPluginDisplayNameByPath( const base::FilePath& path) { - string16 plugin_name = path.LossyDisplayName(); + base::string16 plugin_name = path.LossyDisplayName(); WebPluginInfo info; if (PluginService::GetInstance()->GetPluginInfoByPath(path, &info) && !info.name.empty()) { diff --git a/content/browser/plugin_service_impl.h b/content/browser/plugin_service_impl.h index 11fb257e99..d8e3de62ae 100644 --- a/content/browser/plugin_service_impl.h +++ b/content/browser/plugin_service_impl.h @@ -59,7 +59,7 @@ struct PepperPluginInfo; // surpass that limit. struct PluginServiceFilterParams { int render_process_id; - int render_view_id; + int render_frame_id; GURL page_url; ResourceContext* resource_context; }; @@ -80,7 +80,7 @@ class CONTENT_EXPORT PluginServiceImpl std::vector<WebPluginInfo>* info, std::vector<std::string>* actual_mime_types) OVERRIDE; virtual bool GetPluginInfo(int render_process_id, - int render_view_id, + int render_frame_id, ResourceContext* context, const GURL& url, const GURL& page_url, @@ -91,7 +91,7 @@ class CONTENT_EXPORT PluginServiceImpl std::string* actual_mime_type) OVERRIDE; virtual bool GetPluginInfoByPath(const base::FilePath& plugin_path, WebPluginInfo* info) OVERRIDE; - virtual string16 GetPluginDisplayNameByPath( + virtual base::string16 GetPluginDisplayNameByPath( const base::FilePath& path) OVERRIDE; virtual void GetPlugins(const GetPluginsCallback& callback) OVERRIDE; virtual PepperPluginInfo* GetRegisteredPpapiPluginInfo( @@ -139,7 +139,7 @@ class CONTENT_EXPORT PluginServiceImpl // a new plugin process if necessary. This must be called on the IO thread // or else a deadlock can occur. void OpenChannelToNpapiPlugin(int render_process_id, - int render_view_id, + int render_frame_id, const GURL& url, const GURL& page_url, const std::string& mime_type, @@ -195,7 +195,7 @@ class CONTENT_EXPORT PluginServiceImpl // Helper so we can do the plugin lookup on the FILE thread. void GetAllowedPluginForOpenChannelToPlugin( int render_process_id, - int render_view_id, + int render_frame_id, const GURL& url, const GURL& page_url, const std::string& mime_type, diff --git a/content/browser/power_save_blocker_win.cc b/content/browser/power_save_blocker_win.cc index fce72c65b6..cf9bb02301 100644 --- a/content/browser/power_save_blocker_win.cc +++ b/content/browser/power_save_blocker_win.cc @@ -39,7 +39,7 @@ HANDLE CreatePowerRequest(POWER_REQUEST_TYPE type, const std::string& reason) { if (!PowerCreateRequestFn || !PowerSetRequestFn) return INVALID_HANDLE_VALUE; } - string16 wide_reason = ASCIIToUTF16(reason); + base::string16 wide_reason = ASCIIToUTF16(reason); REASON_CONTEXT context = {0}; context.Version = POWER_REQUEST_CONTEXT_VERSION; context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING; diff --git a/content/browser/ppapi_plugin_process_host.cc b/content/browser/ppapi_plugin_process_host.cc index fbf512a741..cb408af5b8 100644 --- a/content/browser/ppapi_plugin_process_host.cc +++ b/content/browser/ppapi_plugin_process_host.cc @@ -117,6 +117,7 @@ PpapiPluginProcessHost* PpapiPluginProcessHost::CreatePluginHost( const base::FilePath& profile_data_directory) { PpapiPluginProcessHost* plugin_host = new PpapiPluginProcessHost( info, profile_data_directory); + DCHECK(plugin_host); if (plugin_host->Init(info)) return plugin_host; @@ -178,7 +179,7 @@ void PpapiPluginProcessHost::DidDeleteOutOfProcessInstance( // static void PpapiPluginProcessHost::FindByName( - const string16& name, + const base::string16& name, std::vector<PpapiPluginProcessHost*>* hosts) { for (PpapiPluginProcessHostIterator iter; !iter.Done(); ++iter) { if (iter->process_.get() && iter->process_->GetData().name == name) @@ -253,8 +254,10 @@ bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) { } std::string channel_id = process_->GetHost()->CreateChannel(); - if (channel_id.empty()) + if (channel_id.empty()) { + VLOG(1) << "Could not create pepper host channel."; return false; + } const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); CommandLine::StringType plugin_launcher = @@ -267,8 +270,10 @@ bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) { int flags = ChildProcessHost::CHILD_NORMAL; #endif base::FilePath exe_path = ChildProcessHost::GetChildPath(flags); - if (exe_path.empty()) + if (exe_path.empty()) { + VLOG(1) << "Pepper plugin exe path is empty."; return false; + } CommandLine* cmd_line = new CommandLine(exe_path); cmd_line->AppendSwitchASCII(switches::kProcessType, @@ -357,10 +362,12 @@ void PpapiPluginProcessHost::RequestPluginChannel(Client* client) { } void PpapiPluginProcessHost::OnProcessLaunched() { + VLOG(2) << "ppapi plugin process launched."; host_impl_->set_plugin_process_handle(process_->GetHandle()); } void PpapiPluginProcessHost::OnProcessCrashed(int exit_code) { + VLOG(1) << "ppapi plugin process crashed."; PluginServiceImpl::GetInstance()->RegisterPluginCrash(plugin_path_); } @@ -391,8 +398,8 @@ void PpapiPluginProcessHost::OnChannelConnected(int32 peer_pid) { // Called when the browser <--> plugin channel has an error. This normally // means the plugin has crashed. void PpapiPluginProcessHost::OnChannelError() { - DVLOG(1) << "PpapiPluginProcessHost" << (is_broker_ ? "[broker]" : "") - << "::OnChannelError()"; + VLOG(1) << "PpapiPluginProcessHost" << (is_broker_ ? "[broker]" : "") + << "::OnChannelError()"; // We don't need to notify the renderers that were communicating with the // plugin since they have their own channels which will go into the error // state at the same time. Instead, we just need to notify any renderers diff --git a/content/browser/ppapi_plugin_process_host.h b/content/browser/ppapi_plugin_process_host.h index 87c79c31d2..594c12f615 100644 --- a/content/browser/ppapi_plugin_process_host.h +++ b/content/browser/ppapi_plugin_process_host.h @@ -92,7 +92,7 @@ class PpapiPluginProcessHost : public BrowserChildProcessHostDelegate, // Returns the instances that match the specified process name. // It can only be called on the IO thread. - static void FindByName(const string16& name, + static void FindByName(const base::string16& name, std::vector<PpapiPluginProcessHost*>* hosts); // IPC::Sender implementation: diff --git a/content/browser/renderer_host/clipboard_message_filter.cc b/content/browser/renderer_host/clipboard_message_filter.cc index ae365d5cfd..6ba95f8f12 100644 --- a/content/browser/renderer_host/clipboard_message_filter.cc +++ b/content/browser/renderer_host/clipboard_message_filter.cc @@ -145,9 +145,10 @@ void ClipboardMessageFilter::OnGetSequenceNumber(ui::ClipboardType type, *sequence_number = GetClipboard()->GetSequenceNumber(type); } -void ClipboardMessageFilter::OnReadAvailableTypes(ui::ClipboardType type, - std::vector<string16>* types, - bool* contains_filenames) { +void ClipboardMessageFilter::OnReadAvailableTypes( + ui::ClipboardType type, + std::vector<base::string16>* types, + bool* contains_filenames) { GetClipboard()->ReadAvailableTypes(type, types, contains_filenames); } @@ -163,7 +164,7 @@ void ClipboardMessageFilter::OnClear(ui::ClipboardType type) { } void ClipboardMessageFilter::OnReadText(ui::ClipboardType type, - string16* result) { + base::string16* result) { GetClipboard()->ReadText(type, result); } @@ -173,7 +174,7 @@ void ClipboardMessageFilter::OnReadAsciiText(ui::ClipboardType type, } void ClipboardMessageFilter::OnReadHTML(ui::ClipboardType type, - string16* markup, + base::string16* markup, GURL* url, uint32* fragment_start, uint32* fragment_end) { @@ -224,8 +225,8 @@ void ClipboardMessageFilter::OnReadImageReply( } void ClipboardMessageFilter::OnReadCustomData(ui::ClipboardType clipboard_type, - const string16& type, - string16* result) { + const base::string16& type, + base::string16* result) { GetClipboard()->ReadCustomData(clipboard_type, type, result); } diff --git a/content/browser/renderer_host/clipboard_message_filter.h b/content/browser/renderer_host/clipboard_message_filter.h index 3ae7d1b5c1..dd2784be53 100644 --- a/content/browser/renderer_host/clipboard_message_filter.h +++ b/content/browser/renderer_host/clipboard_message_filter.h @@ -39,12 +39,12 @@ class ClipboardMessageFilter : public BrowserMessageFilter { bool* result); void OnClear(ui::ClipboardType type); void OnReadAvailableTypes(ui::ClipboardType type, - std::vector<string16>* types, + std::vector<base::string16>* types, bool* contains_filenames); - void OnReadText(ui::ClipboardType type, string16* result); + void OnReadText(ui::ClipboardType type, base::string16* result); void OnReadAsciiText(ui::ClipboardType type, std::string* result); void OnReadHTML(ui::ClipboardType type, - string16* markup, + base::string16* markup, GURL* url, uint32* fragment_start, uint32* fragment_end); @@ -52,13 +52,13 @@ class ClipboardMessageFilter : public BrowserMessageFilter { void OnReadImage(ui::ClipboardType type, IPC::Message* reply_msg); void OnReadImageReply(const SkBitmap& bitmap, IPC::Message* reply_msg); void OnReadCustomData(ui::ClipboardType clipboard_type, - const string16& type, - string16* result); + const base::string16& type, + base::string16* result); void OnReadData(const ui::Clipboard::FormatType& format, std::string* data); #if defined(OS_MACOSX) - void OnFindPboardWriteString(const string16& text); + void OnFindPboardWriteString(const base::string16& text); #endif // We have our own clipboard because we want to access the clipboard on the diff --git a/content/browser/renderer_host/clipboard_message_filter_mac.mm b/content/browser/renderer_host/clipboard_message_filter_mac.mm index ee8f5a3e42..3c59d31f40 100644 --- a/content/browser/renderer_host/clipboard_message_filter_mac.mm +++ b/content/browser/renderer_host/clipboard_message_filter_mac.mm @@ -40,7 +40,8 @@ class WriteFindPboardWrapper { } // namespace // Called on the IO thread. -void ClipboardMessageFilter::OnFindPboardWriteString(const string16& text) { +void ClipboardMessageFilter::OnFindPboardWriteString( + const base::string16& text) { if (text.length() <= kMaxFindPboardStringLength) { NSString* nsText = base::SysUTF16ToNSString(text); if (nsText) { diff --git a/content/browser/renderer_host/compositing_iosurface_mac.h b/content/browser/renderer_host/compositing_iosurface_mac.h index d15f2b8885..06493511b9 100644 --- a/content/browser/renderer_host/compositing_iosurface_mac.h +++ b/content/browser/renderer_host/compositing_iosurface_mac.h @@ -69,7 +69,7 @@ class CompositingIOSurfaceMac { const gfx::Rect& window_rect, float window_scale_factor, RenderWidgetHostViewFrameSubscriber* frame_subscriber, - bool using_core_animation); + bool flush_drawable); // Copy the data of the "live" OpenGL texture referring to this IOSurfaceRef // into |out|. The copied region is specified with |src_pixel_subrect| and diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index b2e33c8fba..78b23989bd 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc @@ -377,12 +377,10 @@ CreateGpuProcessViewContext( limits.max_transfer_buffer_size = std::min( 3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize); limits.mapped_memory_reclaim_limit = 2 * 1024 * 1024; - bool use_echo_for_swap_ack = true; return make_scoped_ptr( new WebGraphicsContext3DCommandBufferImpl(surface_id, url, gpu_channel_host.get(), - use_echo_for_swap_ack, attributes, false, limits)); diff --git a/content/browser/renderer_host/database_message_filter.cc b/content/browser/renderer_host/database_message_filter.cc index d41be65f50..55ea305d6e 100644 --- a/content/browser/renderer_host/database_message_filter.cc +++ b/content/browser/renderer_host/database_message_filter.cc @@ -113,13 +113,14 @@ bool DatabaseMessageFilter::OnMessageReceived( DatabaseMessageFilter::~DatabaseMessageFilter() { } -void DatabaseMessageFilter::OnDatabaseOpenFile(const string16& vfs_file_name, - int desired_flags, - IPC::Message* reply_msg) { +void DatabaseMessageFilter::OnDatabaseOpenFile( + const base::string16& vfs_file_name, + int desired_flags, + IPC::Message* reply_msg) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); base::PlatformFile file_handle = base::kInvalidPlatformFileValue; std::string origin_identifier; - string16 database_name; + base::string16 database_name; // When in incognito mode, we want to make sure that all DB files are // removed when the incognito browser context goes away, so we add the @@ -162,16 +163,18 @@ void DatabaseMessageFilter::OnDatabaseOpenFile(const string16& vfs_file_name, Send(reply_msg); } -void DatabaseMessageFilter::OnDatabaseDeleteFile(const string16& vfs_file_name, - const bool& sync_dir, - IPC::Message* reply_msg) { +void DatabaseMessageFilter::OnDatabaseDeleteFile( + const base::string16& vfs_file_name, + const bool& sync_dir, + IPC::Message* reply_msg) { DatabaseDeleteFile(vfs_file_name, sync_dir, reply_msg, kNumDeleteRetries); } -void DatabaseMessageFilter::DatabaseDeleteFile(const string16& vfs_file_name, - bool sync_dir, - IPC::Message* reply_msg, - int reschedule_count) { +void DatabaseMessageFilter::DatabaseDeleteFile( + const base::string16& vfs_file_name, + bool sync_dir, + IPC::Message* reply_msg, + int reschedule_count) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); // Return an error if the file name is invalid or if the file could not @@ -183,8 +186,8 @@ void DatabaseMessageFilter::DatabaseDeleteFile(const string16& vfs_file_name, // In order to delete a journal file in incognito mode, we only need to // close the open handle to it that's stored in the database tracker. if (db_tracker_->IsIncognitoProfile()) { - const string16 wal_suffix(ASCIIToUTF16("-wal")); - string16 sqlite_suffix; + const base::string16 wal_suffix(ASCIIToUTF16("-wal")); + base::string16 sqlite_suffix; // WAL files can be deleted without having previously been opened. if (!db_tracker_->HasSavedIncognitoFileHandle(vfs_file_name) && @@ -215,7 +218,7 @@ void DatabaseMessageFilter::DatabaseDeleteFile(const string16& vfs_file_name, } void DatabaseMessageFilter::OnDatabaseGetFileAttributes( - const string16& vfs_file_name, + const base::string16& vfs_file_name, IPC::Message* reply_msg) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); int32 attributes = -1; @@ -230,7 +233,7 @@ void DatabaseMessageFilter::OnDatabaseGetFileAttributes( } void DatabaseMessageFilter::OnDatabaseGetFileSize( - const string16& vfs_file_name, IPC::Message* reply_msg) { + const base::string16& vfs_file_name, IPC::Message* reply_msg) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); int64 size = 0; base::FilePath db_file = @@ -278,8 +281,8 @@ void DatabaseMessageFilter::OnDatabaseGetUsageAndQuota( void DatabaseMessageFilter::OnDatabaseOpened( const std::string& origin_identifier, - const string16& database_name, - const string16& description, + const base::string16& database_name, + const base::string16& description, int64 estimated_size) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); @@ -299,7 +302,7 @@ void DatabaseMessageFilter::OnDatabaseOpened( void DatabaseMessageFilter::OnDatabaseModified( const std::string& origin_identifier, - const string16& database_name) { + const base::string16& database_name) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); if (!database_connections_.IsDatabaseOpened( origin_identifier, database_name)) { @@ -313,7 +316,7 @@ void DatabaseMessageFilter::OnDatabaseModified( void DatabaseMessageFilter::OnDatabaseClosed( const std::string& origin_identifier, - const string16& database_name) { + const base::string16& database_name) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); if (!database_connections_.IsDatabaseOpened( origin_identifier, database_name)) { @@ -328,7 +331,7 @@ void DatabaseMessageFilter::OnDatabaseClosed( void DatabaseMessageFilter::OnHandleSqliteError( const std::string& origin_identifier, - const string16& database_name, + const base::string16& database_name, int error) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); if (!DatabaseUtil::IsValidOriginIdentifier(origin_identifier)) { @@ -342,7 +345,7 @@ void DatabaseMessageFilter::OnHandleSqliteError( void DatabaseMessageFilter::OnDatabaseSizeChanged( const std::string& origin_identifier, - const string16& database_name, + const base::string16& database_name, int64 database_size) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); if (database_connections_.IsOriginUsed(origin_identifier)) { @@ -353,7 +356,7 @@ void DatabaseMessageFilter::OnDatabaseSizeChanged( void DatabaseMessageFilter::OnDatabaseScheduledForDeletion( const std::string& origin_identifier, - const string16& database_name) { + const base::string16& database_name) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); Send(new DatabaseMsg_CloseImmediately(origin_identifier, database_name)); } diff --git a/content/browser/renderer_host/database_message_filter.h b/content/browser/renderer_host/database_message_filter.h index 9e168c5404..5024335633 100644 --- a/content/browser/renderer_host/database_message_filter.h +++ b/content/browser/renderer_host/database_message_filter.h @@ -41,15 +41,15 @@ class DatabaseMessageFilter void RemoveObserver(); // VFS message handlers (file thread) - void OnDatabaseOpenFile(const string16& vfs_file_name, + void OnDatabaseOpenFile(const base::string16& vfs_file_name, int desired_flags, IPC::Message* reply_msg); - void OnDatabaseDeleteFile(const string16& vfs_file_name, + void OnDatabaseDeleteFile(const base::string16& vfs_file_name, const bool& sync_dir, IPC::Message* reply_msg); - void OnDatabaseGetFileAttributes(const string16& vfs_file_name, + void OnDatabaseGetFileAttributes(const base::string16& vfs_file_name, IPC::Message* reply_msg); - void OnDatabaseGetFileSize(const string16& vfs_file_name, + void OnDatabaseGetFileSize(const base::string16& vfs_file_name, IPC::Message* reply_msg); // Quota message handler (io thread) @@ -62,26 +62,26 @@ class DatabaseMessageFilter // Database tracker message handlers (file thread) void OnDatabaseOpened(const std::string& origin_identifier, - const string16& database_name, - const string16& description, + const base::string16& database_name, + const base::string16& description, int64 estimated_size); void OnDatabaseModified(const std::string& origin_identifier, - const string16& database_name); + const base::string16& database_name); void OnDatabaseClosed(const std::string& origin_identifier, - const string16& database_name); + const base::string16& database_name); void OnHandleSqliteError(const std::string& origin_identifier, - const string16& database_name, + const base::string16& database_name, int error); // DatabaseTracker::Observer callbacks (file thread) virtual void OnDatabaseSizeChanged(const std::string& origin_identifier, - const string16& database_name, + const base::string16& database_name, int64 database_size) OVERRIDE; virtual void OnDatabaseScheduledForDeletion( const std::string& origin_identifier, - const string16& database_name) OVERRIDE; + const base::string16& database_name) OVERRIDE; - void DatabaseDeleteFile(const string16& vfs_file_name, + void DatabaseDeleteFile(const base::string16& vfs_file_name, bool sync_dir, IPC::Message* reply_msg, int reschedule_count); diff --git a/content/browser/renderer_host/file_utilities_message_filter.cc b/content/browser/renderer_host/file_utilities_message_filter.cc index 65645e014e..5daa6ff221 100644 --- a/content/browser/renderer_host/file_utilities_message_filter.cc +++ b/content/browser/renderer_host/file_utilities_message_filter.cc @@ -48,7 +48,7 @@ void FileUtilitiesMessageFilter::OnGetFileInfo( return; } - if (!file_util::GetFileInfo(path, result)) + if (!base::GetFileInfo(path, result)) *status = base::PLATFORM_FILE_ERROR_FAILED; } diff --git a/content/browser/renderer_host/gtk_im_context_wrapper.cc b/content/browser/renderer_host/gtk_im_context_wrapper.cc index 7ce65585d7..d4b77894f5 100644 --- a/content/browser/renderer_host/gtk_im_context_wrapper.cc +++ b/content/browser/renderer_host/gtk_im_context_wrapper.cc @@ -477,7 +477,7 @@ void GtkIMContextWrapper::ConfirmComposition() { if (host_view_->GetRenderWidgetHost()) { RenderWidgetHostImpl::From( host_view_->GetRenderWidgetHost())->ImeConfirmComposition( - string16(), gfx::Range::InvalidRange(), false); + base::string16(), gfx::Range::InvalidRange(), false); } // Reset the input method. @@ -485,7 +485,7 @@ void GtkIMContextWrapper::ConfirmComposition() { } } -void GtkIMContextWrapper::HandleCommit(const string16& text) { +void GtkIMContextWrapper::HandleCommit(const base::string16& text) { if (suppress_next_commit_) return; diff --git a/content/browser/renderer_host/gtk_im_context_wrapper.h b/content/browser/renderer_host/gtk_im_context_wrapper.h index 1647df1330..8bd027f0e8 100644 --- a/content/browser/renderer_host/gtk_im_context_wrapper.h +++ b/content/browser/renderer_host/gtk_im_context_wrapper.h @@ -75,7 +75,7 @@ class GtkIMContextWrapper { void ProcessInputMethodResult(const GdkEventKey* event, bool filtered); // Real code of "commit" signal handler. - void HandleCommit(const string16& text); + void HandleCommit(const base::string16& text); // Real code of "preedit-start" signal handler. void HandlePreeditStart(); @@ -180,7 +180,7 @@ class GtkIMContextWrapper { // Stores a copy of the most recent commit text received by commit signal // handler. - string16 commit_text_; + base::string16 commit_text_; // If it's true then the next "commit" signal will be suppressed. // It's only used to workaround http://crbug.com/50485. diff --git a/content/browser/renderer_host/image_transport_factory_android.cc b/content/browser/renderer_host/image_transport_factory_android.cc index a55b823914..5fa9a7e134 100644 --- a/content/browser/renderer_host/image_transport_factory_android.cc +++ b/content/browser/renderer_host/image_transport_factory_android.cc @@ -48,7 +48,7 @@ class CmdBufferImageTransportFactory : public ImageTransportFactoryAndroid { } virtual GLHelper* GetGLHelper() OVERRIDE; virtual uint32 GetChannelID() OVERRIDE { - return context_->GetChannelID(); + return BrowserGpuChannelHostFactory::instance()->GetGpuChannelId(); } private: @@ -81,12 +81,10 @@ CmdBufferImageTransportFactory::CmdBufferImageTransportFactory() { 3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize); limits.mapped_memory_reclaim_limit = WebGraphicsContext3DCommandBufferImpl::kNoLimit; - bool use_echo_for_swap_ack = true; context_.reset( new WebGraphicsContext3DCommandBufferImpl(0, // offscreen url, gpu_channel_host.get(), - use_echo_for_swap_ack, attrs, false, limits)); diff --git a/content/browser/renderer_host/ime_adapter_android.cc b/content/browser/renderer_host/ime_adapter_android.cc index 9e7fe47c27..92d972f22c 100644 --- a/content/browser/renderer_host/ime_adapter_android.cc +++ b/content/browser/renderer_host/ime_adapter_android.cc @@ -136,7 +136,7 @@ void ImeAdapterAndroid::SetComposingText(JNIEnv* env, jobject, jstring text, if (!rwhi) return; - string16 text16 = ConvertJavaStringToUTF16(env, text); + base::string16 text16 = ConvertJavaStringToUTF16(env, text); std::vector<blink::WebCompositionUnderline> underlines; underlines.push_back( blink::WebCompositionUnderline(0, text16.length(), SK_ColorBLACK, @@ -155,7 +155,7 @@ void ImeAdapterAndroid::CommitText(JNIEnv* env, jobject, jstring text) { if (!rwhi) return; - string16 text16 = ConvertJavaStringToUTF16(env, text); + base::string16 text16 = ConvertJavaStringToUTF16(env, text); rwhi->ImeConfirmComposition(text16, gfx::Range::InvalidRange(), false); } @@ -164,7 +164,8 @@ void ImeAdapterAndroid::FinishComposingText(JNIEnv* env, jobject) { if (!rwhi) return; - rwhi->ImeConfirmComposition(string16(), gfx::Range::InvalidRange(), true); + rwhi->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(), + true); } void ImeAdapterAndroid::AttachImeAdapter(JNIEnv* env, jobject java_object) { diff --git a/content/browser/renderer_host/input/gesture_event_filter.h b/content/browser/renderer_host/input/gesture_event_filter.h index d8ccdf3742..d0517008bf 100644 --- a/content/browser/renderer_host/input/gesture_event_filter.h +++ b/content/browser/renderer_host/input/gesture_event_filter.h @@ -93,9 +93,13 @@ class CONTENT_EXPORT GestureEventFilter { debounce_enabled_ = enabled; } + void set_debounce_interval_time_ms_for_testing(int interval_time_ms) { + debounce_interval_time_ms_ = interval_time_ms; + } + private: - friend class MockRenderWidgetHost; friend class GestureEventFilterTest; + friend class MockRenderWidgetHost; // TODO(mohsen): There are a bunch of ShouldForward.../ShouldDiscard... // methods that are getting confusing. This should be somehow fixed. Maybe diff --git a/content/browser/renderer_host/input/gesture_event_filter_unittest.cc b/content/browser/renderer_host/input/gesture_event_filter_unittest.cc index 1ed8d93106..421fd70131 100644 --- a/content/browser/renderer_host/input/gesture_event_filter_unittest.cc +++ b/content/browser/renderer_host/input/gesture_event_filter_unittest.cc @@ -10,8 +10,8 @@ #include "base/message_loop/message_loop.h" #include "base/time/time.h" #include "content/browser/renderer_host/input/gesture_event_filter.h" -#include "content/browser/renderer_host/input/synthetic_web_input_event_builders.h" #include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h" +#include "content/common/input/synthetic_web_input_event_builders.h" #include "content/port/common/input_event_ack_state.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/web/WebInputEvent.h" @@ -142,7 +142,7 @@ class GestureEventFilterTest : public testing::Test, } void set_debounce_interval_time_ms(int ms) { - filter()->debounce_interval_time_ms_ = ms; + filter()->set_debounce_interval_time_ms_for_testing(ms); } void set_synchronous_ack(InputEventAckState ack_result) { diff --git a/content/browser/renderer_host/input/input_router.h b/content/browser/renderer_host/input/input_router.h index a346a00f88..2dbb4ed00a 100644 --- a/content/browser/renderer_host/input/input_router.h +++ b/content/browser/renderer_host/input/input_router.h @@ -54,6 +54,15 @@ class InputRouter : public IPC::Listener { // router. When |false|, the caller can forego sending touch events, and // instead consume them directly. virtual bool ShouldForwardTouchEvent() const = 0; + + // Allow the router to make more informed input handling decisions based on + // the current view. + enum ViewFlags { + VIEW_FLAGS_NONE = 0, + FIXED_PAGE_SCALE = 1 << 0, + MOBILE_VIEWPORT = 1 << 1 + }; + virtual void OnViewUpdated(int view_flags) = 0; }; } // namespace content diff --git a/content/browser/renderer_host/input/immediate_input_router.cc b/content/browser/renderer_host/input/input_router_impl.cc index 4fa30aae23..59efb11a12 100644 --- a/content/browser/renderer_host/input/immediate_input_router.cc +++ b/content/browser/renderer_host/input/input_router_impl.cc @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/input/immediate_input_router.h" +#include "content/browser/renderer_host/input/input_router_impl.h" #include "base/auto_reset.h" #include "base/command_line.h" #include "base/metrics/histogram.h" +#include "base/strings/string_number_conversions.h" #include "content/browser/renderer_host/input/gesture_event_filter.h" #include "content/browser/renderer_host/input/input_ack_handler.h" #include "content/browser/renderer_host/input/input_router_client.h" @@ -15,6 +16,7 @@ #include "content/browser/renderer_host/overscroll_controller.h" #include "content/common/content_constants_internal.h" #include "content/common/edit_command.h" +#include "content/common/input/touch_action.h" #include "content/common/input/web_input_event_traits.h" #include "content/common/input_messages.h" #include "content/common/view_messages.h" @@ -39,6 +41,21 @@ using blink::WebMouseWheelEvent; namespace content { namespace { +bool GetTouchAckTimeoutDelayMs(size_t* touch_ack_timeout_delay_ms) { + CommandLine* parsed_command_line = CommandLine::ForCurrentProcess(); + if (!parsed_command_line->HasSwitch(switches::kTouchAckTimeoutDelayMs)) + return false; + + std::string timeout_string = parsed_command_line->GetSwitchValueASCII( + switches::kTouchAckTimeoutDelayMs); + size_t timeout_value; + if (!base::StringToSizeT(timeout_string, &timeout_value)) + return false; + + *touch_ack_timeout_delay_ms = timeout_value; + return true; +} + GestureEventWithLatencyInfo MakeGestureEvent(WebInputEvent::Type type, double timestamp_seconds, int x, @@ -63,19 +80,18 @@ const char* GetEventAckName(InputEventAckState ack_result) { case INPUT_EVENT_ACK_STATE_CONSUMED: return "CONSUMED"; case INPUT_EVENT_ACK_STATE_NOT_CONSUMED: return "NOT_CONSUMED"; case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: return "NO_CONSUMER_EXISTS"; - default: - DLOG(WARNING) << "Unhandled InputEventAckState in GetEventAckName.\n"; - break; + case INPUT_EVENT_ACK_STATE_IGNORED: return "IGNORED"; } + DLOG(WARNING) << "Unhandled InputEventAckState in GetEventAckName."; return ""; } } // namespace -ImmediateInputRouter::ImmediateInputRouter(IPC::Sender* sender, - InputRouterClient* client, - InputAckHandler* ack_handler, - int routing_id) +InputRouterImpl::InputRouterImpl(IPC::Sender* sender, + InputRouterClient* client, + InputAckHandler* ack_handler, + int routing_id) : sender_(sender), client_(client), ack_handler_(ack_handler), @@ -85,20 +101,25 @@ ImmediateInputRouter::ImmediateInputRouter(IPC::Sender* sender, mouse_move_pending_(false), mouse_wheel_pending_(false), has_touch_handler_(false), + touch_ack_timeout_enabled_(false), + touch_ack_timeout_delay_ms_(std::numeric_limits<size_t>::max()), current_ack_source_(ACK_SOURCE_NONE), - touch_event_queue_(new TouchEventQueue(this)), gesture_event_filter_(new GestureEventFilter(this, this)) { DCHECK(sender); DCHECK(client); DCHECK(ack_handler); + touch_event_queue_.reset(new TouchEventQueue(this)); + touch_ack_timeout_enabled_ = + GetTouchAckTimeoutDelayMs(&touch_ack_timeout_delay_ms_); + touch_event_queue_->SetAckTimeoutEnabled(touch_ack_timeout_enabled_, + touch_ack_timeout_delay_ms_); } -ImmediateInputRouter::~ImmediateInputRouter() { -} +InputRouterImpl::~InputRouterImpl() {} -void ImmediateInputRouter::Flush() {} +void InputRouterImpl::Flush() {} -bool ImmediateInputRouter::SendInput(scoped_ptr<IPC::Message> message) { +bool InputRouterImpl::SendInput(scoped_ptr<IPC::Message> message) { DCHECK(IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart); switch (message->type()) { // Check for types that require an ACK. @@ -114,7 +135,7 @@ bool ImmediateInputRouter::SendInput(scoped_ptr<IPC::Message> message) { } } -void ImmediateInputRouter::SendMouseEvent( +void InputRouterImpl::SendMouseEvent( const MouseEventWithLatencyInfo& mouse_event) { // Order is important here; we need to convert all MouseEvents before they // propagate further, e.g., to the tap suppression controller. @@ -136,7 +157,7 @@ void ImmediateInputRouter::SendMouseEvent( SendMouseEventImmediately(mouse_event); } -void ImmediateInputRouter::SendWheelEvent( +void InputRouterImpl::SendWheelEvent( const MouseWheelEventWithLatencyInfo& wheel_event) { // If there's already a mouse wheel event waiting to be sent to the renderer, // add the new deltas to that event. Not doing so (e.g., by dropping the old @@ -160,10 +181,9 @@ void ImmediateInputRouter::SendWheelEvent( FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency, false); } -void ImmediateInputRouter::SendKeyboardEvent( - const NativeWebKeyboardEvent& key_event, - const ui::LatencyInfo& latency_info, - bool is_keyboard_shortcut) { +void InputRouterImpl::SendKeyboardEvent(const NativeWebKeyboardEvent& key_event, + const ui::LatencyInfo& latency_info, + bool is_keyboard_shortcut) { // Put all WebKeyboardEvent objects in a queue since we can't trust the // renderer and we need to give something to the HandleKeyboardEvent // handler. @@ -176,9 +196,12 @@ void ImmediateInputRouter::SendKeyboardEvent( FilterAndSendWebInputEvent(key_event, latency_info, is_keyboard_shortcut); } -void ImmediateInputRouter::SendGestureEvent( +void InputRouterImpl::SendGestureEvent( const GestureEventWithLatencyInfo& gesture_event) { - HandleGestureScroll(gesture_event); + if (touch_action_filter_.FilterGestureEvent(gesture_event.event)) + return; + + touch_event_queue_->OnGestureScrollEvent(gesture_event); if (!IsInOverscrollGesture() && !gesture_event_filter_->ShouldForward(gesture_event)) { @@ -191,14 +214,14 @@ void ImmediateInputRouter::SendGestureEvent( FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false); } -void ImmediateInputRouter::SendTouchEvent( +void InputRouterImpl::SendTouchEvent( const TouchEventWithLatencyInfo& touch_event) { touch_event_queue_->QueueEvent(touch_event); } // Forwards MouseEvent without passing it through // TouchpadTapSuppressionController. -void ImmediateInputRouter::SendMouseEventImmediately( +void InputRouterImpl::SendMouseEventImmediately( const MouseEventWithLatencyInfo& mouse_event) { // Avoid spamming the renderer with mouse move events. It is important // to note that WM_MOUSEMOVE events are anyways synthetic, but since our @@ -218,25 +241,23 @@ void ImmediateInputRouter::SendMouseEventImmediately( FilterAndSendWebInputEvent(mouse_event.event, mouse_event.latency, false); } -void ImmediateInputRouter::SendTouchEventImmediately( +void InputRouterImpl::SendTouchEventImmediately( const TouchEventWithLatencyInfo& touch_event) { FilterAndSendWebInputEvent(touch_event.event, touch_event.latency, false); } -void ImmediateInputRouter::SendGestureEventImmediately( +void InputRouterImpl::SendGestureEventImmediately( const GestureEventWithLatencyInfo& gesture_event) { - HandleGestureScroll(gesture_event); FilterAndSendWebInputEvent(gesture_event.event, gesture_event.latency, false); } -const NativeWebKeyboardEvent* - ImmediateInputRouter::GetLastKeyboardEvent() const { +const NativeWebKeyboardEvent* InputRouterImpl::GetLastKeyboardEvent() const { if (key_queue_.empty()) return NULL; return &key_queue_.front(); } -bool ImmediateInputRouter::ShouldForwardTouchEvent() const { +bool InputRouterImpl::ShouldForwardTouchEvent() const { // Always send a touch event if the renderer has a touch-event handler. It is // possible that a renderer stops listening to touch-events while there are // still events in the touch-queue. In such cases, the new events should still @@ -244,15 +265,25 @@ bool ImmediateInputRouter::ShouldForwardTouchEvent() const { return has_touch_handler_ || !touch_event_queue_->empty(); } -bool ImmediateInputRouter::OnMessageReceived(const IPC::Message& message) { +void InputRouterImpl::OnViewUpdated(int view_flags) { + bool fixed_page_scale = (view_flags & FIXED_PAGE_SCALE) != 0; + bool mobile_viewport = (view_flags & MOBILE_VIEWPORT) != 0; + touch_event_queue_->SetAckTimeoutEnabled( + touch_ack_timeout_enabled_ && !(fixed_page_scale || mobile_viewport), + touch_ack_timeout_delay_ms_); +} + +bool InputRouterImpl::OnMessageReceived(const IPC::Message& message) { bool handled = true; bool message_is_ok = true; - IPC_BEGIN_MESSAGE_MAP_EX(ImmediateInputRouter, message, message_is_ok) + IPC_BEGIN_MESSAGE_MAP_EX(InputRouterImpl, message, message_is_ok) IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck) IPC_MESSAGE_HANDLER(ViewHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck) IPC_MESSAGE_HANDLER(ViewHostMsg_SelectRange_ACK, OnSelectRangeAck) IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers, OnHasTouchEventHandlers) + IPC_MESSAGE_HANDLER(InputHostMsg_SetTouchAction, + OnSetTouchAction) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -262,20 +293,19 @@ bool ImmediateInputRouter::OnMessageReceived(const IPC::Message& message) { return handled; } -void ImmediateInputRouter::OnTouchEventAck( - const TouchEventWithLatencyInfo& event, - InputEventAckState ack_result) { +void InputRouterImpl::OnTouchEventAck(const TouchEventWithLatencyInfo& event, + InputEventAckState ack_result) { ack_handler_->OnTouchEventAck(event, ack_result); } -void ImmediateInputRouter::OnGestureEventAck( +void InputRouterImpl::OnGestureEventAck( const GestureEventWithLatencyInfo& event, InputEventAckState ack_result) { ProcessAckForOverscroll(event.event, ack_result); ack_handler_->OnGestureEventAck(event, ack_result); } -bool ImmediateInputRouter::SendSelectRange(scoped_ptr<IPC::Message> message) { +bool InputRouterImpl::SendSelectRange(scoped_ptr<IPC::Message> message) { DCHECK(message->type() == InputMsg_SelectRange::ID); if (select_range_pending_) { next_selection_range_ = message.Pass(); @@ -286,7 +316,7 @@ bool ImmediateInputRouter::SendSelectRange(scoped_ptr<IPC::Message> message) { return Send(message.release()); } -bool ImmediateInputRouter::SendMoveCaret(scoped_ptr<IPC::Message> message) { +bool InputRouterImpl::SendMoveCaret(scoped_ptr<IPC::Message> message) { DCHECK(message->type() == InputMsg_MoveCaret::ID); if (move_caret_pending_) { next_move_caret_ = message.Pass(); @@ -297,16 +327,18 @@ bool ImmediateInputRouter::SendMoveCaret(scoped_ptr<IPC::Message> message) { return Send(message.release()); } -bool ImmediateInputRouter::Send(IPC::Message* message) { +bool InputRouterImpl::Send(IPC::Message* message) { return sender_->Send(message); } -void ImmediateInputRouter::FilterAndSendWebInputEvent( +void InputRouterImpl::FilterAndSendWebInputEvent( const WebInputEvent& input_event, const ui::LatencyInfo& latency_info, bool is_keyboard_shortcut) { - TRACE_EVENT1("input", "ImmediateInputRouter::FilterAndSendWebInputEvent", - "type", WebInputEventTraits::GetName(input_event.type)); + TRACE_EVENT1("input", + "InputRouterImpl::FilterAndSendWebInputEvent", + "type", + WebInputEventTraits::GetName(input_event.type)); // Transmit any pending wheel events on a non-wheel event. This ensures that // final PhaseEnded wheel event is received, which is necessary to terminate @@ -327,9 +359,9 @@ void ImmediateInputRouter::FilterAndSendWebInputEvent( OfferToHandlers(input_event, latency_info, is_keyboard_shortcut); } -void ImmediateInputRouter::OfferToHandlers(const WebInputEvent& input_event, - const ui::LatencyInfo& latency_info, - bool is_keyboard_shortcut) { +void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event, + const ui::LatencyInfo& latency_info, + bool is_keyboard_shortcut) { if (OfferToOverscrollController(input_event, latency_info)) return; @@ -347,7 +379,7 @@ void ImmediateInputRouter::OfferToHandlers(const WebInputEvent& input_event, } } -bool ImmediateInputRouter::OfferToOverscrollController( +bool InputRouterImpl::OfferToOverscrollController( const WebInputEvent& input_event, const ui::LatencyInfo& latency_info) { OverscrollController* controller = client_->GetOverscrollController(); @@ -382,8 +414,8 @@ bool ImmediateInputRouter::OfferToOverscrollController( return consumed; } -bool ImmediateInputRouter::OfferToClient(const WebInputEvent& input_event, - const ui::LatencyInfo& latency_info) { +bool InputRouterImpl::OfferToClient(const WebInputEvent& input_event, + const ui::LatencyInfo& latency_info) { bool consumed = false; InputEventAckState filter_ack = @@ -408,7 +440,7 @@ bool ImmediateInputRouter::OfferToClient(const WebInputEvent& input_event, return consumed; } -bool ImmediateInputRouter::OfferToRenderer(const WebInputEvent& input_event, +bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event, const ui::LatencyInfo& latency_info, bool is_keyboard_shortcut) { input_event_start_time_ = TimeTicks::Now(); @@ -420,10 +452,9 @@ bool ImmediateInputRouter::OfferToRenderer(const WebInputEvent& input_event, return false; } -void ImmediateInputRouter::OnInputEventAck( - WebInputEvent::Type event_type, - InputEventAckState ack_result, - const ui::LatencyInfo& latency_info) { +void InputRouterImpl::OnInputEventAck(WebInputEvent::Type event_type, + InputEventAckState ack_result, + const ui::LatencyInfo& latency_info) { // Log the time delta for processing an input event. TimeDelta delta = TimeTicks::Now() - input_event_start_time_; UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta); @@ -451,19 +482,19 @@ void ImmediateInputRouter::OnInputEventAck( Details<int>(&type)); } -void ImmediateInputRouter::OnMsgMoveCaretAck() { +void InputRouterImpl::OnMsgMoveCaretAck() { move_caret_pending_ = false; if (next_move_caret_) SendMoveCaret(next_move_caret_.Pass()); } -void ImmediateInputRouter::OnSelectRangeAck() { +void InputRouterImpl::OnSelectRangeAck() { select_range_pending_ = false; if (next_selection_range_) SendSelectRange(next_selection_range_.Pass()); } -void ImmediateInputRouter::OnHasTouchEventHandlers(bool has_handlers) { +void InputRouterImpl::OnHasTouchEventHandlers(bool has_handlers) { if (has_touch_handler_ == has_handlers) return; has_touch_handler_ = has_handlers; @@ -472,12 +503,20 @@ void ImmediateInputRouter::OnHasTouchEventHandlers(bool has_handlers) { client_->OnHasTouchEventHandlers(has_handlers); } -void ImmediateInputRouter::ProcessInputEventAck( +void InputRouterImpl::OnSetTouchAction( + content::TouchAction touch_action) { + // Synthetic touchstart events should get filtered out in RenderWidget. + DCHECK(touch_event_queue_->IsPendingAckTouchStart()); + + touch_action_filter_.OnSetTouchAction(touch_action); +} + +void InputRouterImpl::ProcessInputEventAck( WebInputEvent::Type event_type, InputEventAckState ack_result, const ui::LatencyInfo& latency_info, AckSource ack_source) { - TRACE_EVENT2("input", "ImmediateInputRouter::ProcessInputEventAck", + TRACE_EVENT2("input", "InputRouterImpl::ProcessInputEventAck", "type", WebInputEventTraits::GetName(event_type), "ack", GetEventAckName(ack_result)); @@ -506,9 +545,8 @@ void ImmediateInputRouter::ProcessInputEventAck( } } -void ImmediateInputRouter::ProcessKeyboardAck( - blink::WebInputEvent::Type type, - InputEventAckState ack_result) { +void InputRouterImpl::ProcessKeyboardAck(blink::WebInputEvent::Type type, + InputEventAckState ack_result) { if (key_queue_.empty()) { ack_handler_->OnUnexpectedEventAck(InputAckHandler::UNEXPECTED_ACK); } else if (key_queue_.front().type != type) { @@ -521,15 +559,15 @@ void ImmediateInputRouter::ProcessKeyboardAck( key_queue_.pop_front(); ack_handler_->OnKeyboardEventAck(front_item, ack_result); - // WARNING: This ImmediateInputRouter can be deallocated at this point + // WARNING: This InputRouterImpl can be deallocated at this point // (i.e. in the case of Ctrl+W, where the call to - // HandleKeyboardEvent destroys this ImmediateInputRouter). + // HandleKeyboardEvent destroys this InputRouterImpl). // TODO(jdduke): crbug.com/274029 - Make ack-triggered shutdown async. } } -void ImmediateInputRouter::ProcessMouseAck(blink::WebInputEvent::Type type, - InputEventAckState ack_result) { +void InputRouterImpl::ProcessMouseAck(blink::WebInputEvent::Type type, + InputEventAckState ack_result) { if (type != WebInputEvent::MouseMove) return; @@ -543,8 +581,8 @@ void ImmediateInputRouter::ProcessMouseAck(blink::WebInputEvent::Type type, } } -void ImmediateInputRouter::ProcessWheelAck(InputEventAckState ack_result, - const ui::LatencyInfo& latency) { +void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result, + const ui::LatencyInfo& latency) { ProcessAckForOverscroll(current_wheel_event_.event, ack_result); // TODO(miletus): Add renderer side latency to each uncoalesced mouse @@ -564,9 +602,9 @@ void ImmediateInputRouter::ProcessWheelAck(InputEventAckState ack_result, } } -void ImmediateInputRouter::ProcessGestureAck(WebInputEvent::Type type, - InputEventAckState ack_result, - const ui::LatencyInfo& latency) { +void InputRouterImpl::ProcessGestureAck(WebInputEvent::Type type, + InputEventAckState ack_result, + const ui::LatencyInfo& latency) { // If |ack_result| originated from the overscroll controller, only // feed |gesture_event_filter_| the ack if it was expecting one. if (current_ack_source_ == OVERSCROLL_CONTROLLER && @@ -578,16 +616,15 @@ void ImmediateInputRouter::ProcessGestureAck(WebInputEvent::Type type, gesture_event_filter_->ProcessGestureAck(ack_result, type, latency); } -void ImmediateInputRouter::ProcessTouchAck( +void InputRouterImpl::ProcessTouchAck( InputEventAckState ack_result, const ui::LatencyInfo& latency) { // |touch_event_queue_| will forward to OnTouchEventAck when appropriate. touch_event_queue_->ProcessTouchAck(ack_result, latency); } -void ImmediateInputRouter::ProcessAckForOverscroll( - const WebInputEvent& event, - InputEventAckState ack_result) { +void InputRouterImpl::ProcessAckForOverscroll(const WebInputEvent& event, + InputEventAckState ack_result) { // Acks sent from the overscroll controller need not be fed back into the // overscroll controller. if (current_ack_source_ == OVERSCROLL_CONTROLLER) @@ -601,12 +638,7 @@ void ImmediateInputRouter::ProcessAckForOverscroll( event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result)); } -void ImmediateInputRouter::HandleGestureScroll( - const GestureEventWithLatencyInfo& gesture_event) { - touch_event_queue_->OnGestureScrollEvent(gesture_event); -} - -void ImmediateInputRouter::SimulateTouchGestureWithMouse( +void InputRouterImpl::SimulateTouchGestureWithMouse( const MouseEventWithLatencyInfo& event) { const WebMouseEvent& mouse_event = event.event; int x = mouse_event.x, y = mouse_event.y; @@ -686,7 +718,7 @@ void ImmediateInputRouter::SimulateTouchGestureWithMouse( } } -bool ImmediateInputRouter::IsInOverscrollGesture() const { +bool InputRouterImpl::IsInOverscrollGesture() const { OverscrollController* controller = client_->GetOverscrollController(); return controller && controller->overscroll_mode() != OVERSCROLL_NONE; } diff --git a/content/browser/renderer_host/input/immediate_input_router.h b/content/browser/renderer_host/input/input_router_impl.h index 56e4987c5f..e12b7510cc 100644 --- a/content/browser/renderer_host/input/immediate_input_router.h +++ b/content/browser/renderer_host/input/input_router_impl.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_IMMEDIATE_INPUT_ROUTER_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_IMMEDIATE_INPUT_ROUTER_H_ +#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_IMPL_H_ +#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_IMPL_H_ #include <queue> @@ -12,6 +12,7 @@ #include "base/time/time.h" #include "content/browser/renderer_host/input/gesture_event_filter.h" #include "content/browser/renderer_host/input/input_router.h" +#include "content/browser/renderer_host/input/touch_action_filter.h" #include "content/browser/renderer_host/input/touch_event_queue.h" #include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h" #include "content/public/browser/native_web_keyboard_event.h" @@ -31,19 +32,18 @@ class InputRouterClient; class OverscrollController; class RenderWidgetHostImpl; -// A default implementation for browser input event routing. Input commands are -// forwarded to the renderer immediately upon receipt. -class CONTENT_EXPORT ImmediateInputRouter +// A default implementation for browser input event routing. +class CONTENT_EXPORT InputRouterImpl : public NON_EXPORTED_BASE(InputRouter), public NON_EXPORTED_BASE(GestureEventFilterClient), public NON_EXPORTED_BASE(TouchEventQueueClient), public NON_EXPORTED_BASE(TouchpadTapSuppressionControllerClient) { public: - ImmediateInputRouter(IPC::Sender* sender, - InputRouterClient* client, - InputAckHandler* ack_handler, - int routing_id); - virtual ~ImmediateInputRouter(); + InputRouterImpl(IPC::Sender* sender, + InputRouterClient* client, + InputAckHandler* ack_handler, + int routing_id); + virtual ~InputRouterImpl(); // InputRouter virtual void Flush() OVERRIDE; @@ -62,12 +62,13 @@ class CONTENT_EXPORT ImmediateInputRouter const TouchEventWithLatencyInfo& touch_event) OVERRIDE; virtual const NativeWebKeyboardEvent* GetLastKeyboardEvent() const OVERRIDE; virtual bool ShouldForwardTouchEvent() const OVERRIDE; + virtual void OnViewUpdated(int view_flags) OVERRIDE; // IPC::Listener virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; private: - friend class ImmediateInputRouterTest; + friend class InputRouterImplTest; friend class MockRenderWidgetHost; // TouchpadTapSuppressionControllerClient @@ -123,6 +124,7 @@ private: void OnMsgMoveCaretAck(); void OnSelectRangeAck(); void OnHasTouchEventHandlers(bool has_handlers); + void OnSetTouchAction(content::TouchAction touch_action); // Indicates the source of an ack provided to |ProcessInputEventAck()|. // The source is tracked by |current_ack_source_|, which aids in ack routing. @@ -168,8 +170,6 @@ private: void ProcessAckForOverscroll(const blink::WebInputEvent& event, InputEventAckState ack_result); - void HandleGestureScroll(const GestureEventWithLatencyInfo& gesture_event); - void SimulateTouchGestureWithMouse( const MouseEventWithLatencyInfo& mouse_event); @@ -235,16 +235,21 @@ private: // not sent to the renderer. bool has_touch_handler_; + // Whether touch ack timeout handling has been enabled via the command line. + bool touch_ack_timeout_enabled_; + size_t touch_ack_timeout_delay_ms_; + // The source of the ack within the scope of |ProcessInputEventAck()|. // Defaults to ACK_SOURCE_NONE. AckSource current_ack_source_; scoped_ptr<TouchEventQueue> touch_event_queue_; scoped_ptr<GestureEventFilter> gesture_event_filter_; + TouchActionFilter touch_action_filter_; - DISALLOW_COPY_AND_ASSIGN(ImmediateInputRouter); + DISALLOW_COPY_AND_ASSIGN(InputRouterImpl); }; } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_IMMEDIATE_INPUT_ROUTER_H_ +#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_IMPL_H_ diff --git a/content/browser/renderer_host/input/immediate_input_router_unittest.cc b/content/browser/renderer_host/input/input_router_impl_unittest.cc index dfd1ee026b..ba94e8057b 100644 --- a/content/browser/renderer_host/input/immediate_input_router_unittest.cc +++ b/content/browser/renderer_host/input/input_router_impl_unittest.cc @@ -3,18 +3,21 @@ // found in the LICENSE file. #include "base/basictypes.h" +#include "base/command_line.h" #include "base/memory/scoped_ptr.h" #include "base/strings/utf_string_conversions.h" #include "content/browser/renderer_host/input/gesture_event_filter.h" -#include "content/browser/renderer_host/input/immediate_input_router.h" #include "content/browser/renderer_host/input/input_router_client.h" -#include "content/browser/renderer_host/input/input_router_unittest.h" +#include "content/browser/renderer_host/input/input_router_impl.h" +#include "content/browser/renderer_host/input/mock_input_ack_handler.h" #include "content/browser/renderer_host/input/mock_input_router_client.h" #include "content/common/content_constants_internal.h" #include "content/common/edit_command.h" +#include "content/common/input/synthetic_web_input_event_builders.h" #include "content/common/input/web_input_event_traits.h" #include "content/common/input_messages.h" #include "content/common/view_messages.h" +#include "content/public/common/content_switches.h" #include "content/public/test/mock_render_process_host.h" #include "content/public/test/test_browser_context.h" #include "testing/gtest/include/gtest/gtest.h" @@ -27,6 +30,7 @@ using base::TimeDelta; using blink::WebGestureEvent; +using blink::WebKeyboardEvent; using blink::WebInputEvent; using blink::WebMouseEvent; using blink::WebMouseWheelEvent; @@ -103,23 +107,149 @@ bool EventListIsSubset(const ScopedVector<ui::TouchEvent>& subset, } // namespace -class ImmediateInputRouterTest : public InputRouterTest { +class InputRouterImplTest : public testing::Test { public: - ImmediateInputRouterTest() {} - virtual ~ImmediateInputRouterTest() {} + InputRouterImplTest() {} + virtual ~InputRouterImplTest() {} protected: - // InputRouterTest - virtual scoped_ptr<InputRouter> CreateInputRouter(RenderProcessHost* process, - InputRouterClient* client, - InputAckHandler* handler, - int routing_id) OVERRIDE { - ImmediateInputRouter* ir = - new ImmediateInputRouter(process, client, handler, routing_id); - ir->gesture_event_filter_->set_debounce_enabled_for_testing(false); - return scoped_ptr<InputRouter>(ir); + // testing::Test + virtual void SetUp() OVERRIDE { + browser_context_.reset(new TestBrowserContext()); + process_.reset(new MockRenderProcessHost(browser_context_.get())); + client_.reset(new MockInputRouterClient()); + ack_handler_.reset(new MockInputAckHandler()); + input_router_.reset(new InputRouterImpl( + process_.get(), client_.get(), ack_handler_.get(), MSG_ROUTING_NONE)); + input_router_->gesture_event_filter_->set_debounce_enabled_for_testing( + false); + client_->set_input_router(input_router()); + ack_handler_->set_input_router(input_router()); } + virtual void TearDown() OVERRIDE { + // Process all pending tasks to avoid leaks. + base::MessageLoop::current()->RunUntilIdle(); + + input_router_.reset(); + client_.reset(); + process_.reset(); + browser_context_.reset(); + } + + void SimulateKeyboardEvent(WebInputEvent::Type type, bool is_shortcut) { + WebKeyboardEvent event = SyntheticWebKeyboardEventBuilder::Build(type); + NativeWebKeyboardEvent native_event; + memcpy(&native_event, &event, sizeof(event)); + input_router_->SendKeyboardEvent( + native_event, + ui::LatencyInfo(), + is_shortcut); + } + + void SimulateWheelEvent(float dX, float dY, int modifiers, bool precise) { + input_router_->SendWheelEvent(MouseWheelEventWithLatencyInfo( + SyntheticWebMouseWheelEventBuilder::Build(dX, dY, modifiers, precise), + ui::LatencyInfo())); + } + + void SimulateMouseMove(int x, int y, int modifiers) { + input_router_->SendMouseEvent(MouseEventWithLatencyInfo( + SyntheticWebMouseEventBuilder::Build( + WebInputEvent::MouseMove, x, y, modifiers), + ui::LatencyInfo())); + } + + void SimulateWheelEventWithPhase(WebMouseWheelEvent::Phase phase) { + input_router_->SendWheelEvent(MouseWheelEventWithLatencyInfo( + SyntheticWebMouseWheelEventBuilder::Build(phase), ui::LatencyInfo())); + } + + void SimulateGestureEvent(const WebGestureEvent& gesture) { + input_router_->SendGestureEvent( + GestureEventWithLatencyInfo(gesture, ui::LatencyInfo())); + } + + void SimulateGestureEvent(WebInputEvent::Type type, + WebGestureEvent::SourceDevice sourceDevice) { + SimulateGestureEvent( + SyntheticWebGestureEventBuilder::Build(type, sourceDevice)); + } + + void SimulateGestureScrollUpdateEvent(float dX, float dY, int modifiers) { + SimulateGestureEvent( + SyntheticWebGestureEventBuilder::BuildScrollUpdate(dX, dY, modifiers)); + } + + void SimulateGesturePinchUpdateEvent(float scale, + float anchorX, + float anchorY, + int modifiers) { + SimulateGestureEvent( + SyntheticWebGestureEventBuilder::BuildPinchUpdate(scale, + anchorX, + anchorY, + modifiers)); + } + + void SimulateGestureFlingStartEvent( + float velocityX, + float velocityY, + WebGestureEvent::SourceDevice sourceDevice) { + SimulateGestureEvent( + SyntheticWebGestureEventBuilder::BuildFling(velocityX, + velocityY, + sourceDevice)); + } + + void SimulateTouchEvent(WebInputEvent::Type type) { + touch_event_.ResetPoints(); + int index = PressTouchPoint(0, 0); + switch (type) { + case WebInputEvent::TouchStart: + // Already handled by |PressTouchPoint()|. + break; + case WebInputEvent::TouchMove: + MoveTouchPoint(index, 5, 5); + break; + case WebInputEvent::TouchEnd: + ReleaseTouchPoint(index); + break; + case WebInputEvent::TouchCancel: + CancelTouchPoint(index); + break; + default: + FAIL() << "Invalid touch event type."; + break; + } + SendTouchEvent(); + } + + void SetTouchTimestamp(base::TimeDelta timestamp) { + touch_event_.SetTimestamp(timestamp); + } + + void SendTouchEvent() { + input_router_->SendTouchEvent( + TouchEventWithLatencyInfo(touch_event_, ui::LatencyInfo())); + touch_event_.ResetPoints(); + } + + int PressTouchPoint(int x, int y) { + return touch_event_.PressPoint(x, y); + } + + void MoveTouchPoint(int index, int x, int y) { + touch_event_.MovePoint(index, x, y); + } + + void ReleaseTouchPoint(int index) { + touch_event_.ReleasePoint(index); + } + + void CancelTouchPoint(int index) { + touch_event_.CancelPoint(index); + } void SendInputEventACK(blink::WebInputEvent::Type type, InputEventAckState ack_result) { scoped_ptr<IPC::Message> response( @@ -128,26 +258,37 @@ class ImmediateInputRouterTest : public InputRouterTest { input_router_->OnMessageReceived(*response); } - ImmediateInputRouter* input_router() const { - return static_cast<ImmediateInputRouter*>(input_router_.get()); - } - - bool no_touch_to_renderer() { - return input_router()->touch_event_queue_->no_touch_to_renderer(); + InputRouterImpl* input_router() const { + return input_router_.get(); } bool TouchEventQueueEmpty() const { return input_router()->touch_event_queue_->empty(); } + bool TouchEventTimeoutEnabled() const { + return input_router()->touch_event_queue_->ack_timeout_enabled(); + } + size_t GetSentMessageCountAndResetSink() { size_t count = process_->sink().message_count(); process_->sink().ClearMessages(); return count; } + + scoped_ptr<MockRenderProcessHost> process_; + scoped_ptr<MockInputRouterClient> client_; + scoped_ptr<MockInputAckHandler> ack_handler_; + scoped_ptr<InputRouterImpl> input_router_; + + private: + base::MessageLoopForUI message_loop_; + SyntheticWebTouchEvent touch_event_; + + scoped_ptr<TestBrowserContext> browser_context_; }; -TEST_F(ImmediateInputRouterTest, CoalescesRangeSelection) { +TEST_F(InputRouterImplTest, CoalescesRangeSelection) { input_router_->SendInput(scoped_ptr<IPC::Message>( new InputMsg_SelectRange(0, gfx::Point(1, 2), gfx::Point(3, 4)))); ExpectIPCMessageWithArg2<InputMsg_SelectRange>( @@ -186,7 +327,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesRangeSelection) { EXPECT_EQ(0u, GetSentMessageCountAndResetSink()); } -TEST_F(ImmediateInputRouterTest, CoalescesCaretMove) { +TEST_F(InputRouterImplTest, CoalescesCaretMove) { input_router_->SendInput( scoped_ptr<IPC::Message>(new InputMsg_MoveCaret(0, gfx::Point(1, 2)))); ExpectIPCMessageWithArg1<InputMsg_MoveCaret>( @@ -221,7 +362,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesCaretMove) { EXPECT_EQ(0u, GetSentMessageCountAndResetSink()); } -TEST_F(ImmediateInputRouterTest, HandledInputEvent) { +TEST_F(InputRouterImplTest, HandledInputEvent) { client_->set_filter_state(INPUT_EVENT_ACK_STATE_CONSUMED); // Simulate a keyboard event. @@ -238,7 +379,7 @@ TEST_F(ImmediateInputRouterTest, HandledInputEvent) { ASSERT_EQ(NULL, input_router_->GetLastKeyboardEvent()); } -TEST_F(ImmediateInputRouterTest, ClientCanceledKeyboardEvent) { +TEST_F(InputRouterImplTest, ClientCanceledKeyboardEvent) { client_->set_filter_state(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); // Simulate a keyboard event that has no consumer. @@ -258,7 +399,7 @@ TEST_F(ImmediateInputRouterTest, ClientCanceledKeyboardEvent) { EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount()); } -TEST_F(ImmediateInputRouterTest, ShortcutKeyboardEvent) { +TEST_F(InputRouterImplTest, ShortcutKeyboardEvent) { SimulateKeyboardEvent(WebInputEvent::RawKeyDown, true); EXPECT_TRUE(GetIsShortcutFromHandleInputEventMessage( process_->sink().GetMessageAt(0))); @@ -270,7 +411,7 @@ TEST_F(ImmediateInputRouterTest, ShortcutKeyboardEvent) { process_->sink().GetMessageAt(0))); } -TEST_F(ImmediateInputRouterTest, NoncorrespondingKeyEvents) { +TEST_F(InputRouterImplTest, NoncorrespondingKeyEvents) { SimulateKeyboardEvent(WebInputEvent::RawKeyDown, false); SendInputEventACK(WebInputEvent::KeyUp, @@ -280,7 +421,7 @@ TEST_F(ImmediateInputRouterTest, NoncorrespondingKeyEvents) { // Tests ported from RenderWidgetHostTest -------------------------------------- -TEST_F(ImmediateInputRouterTest, HandleKeyEventsWeSent) { +TEST_F(InputRouterImplTest, HandleKeyEventsWeSent) { // Simulate a keyboard event. SimulateKeyboardEvent(WebInputEvent::RawKeyDown, false); ASSERT_TRUE(input_router_->GetLastKeyboardEvent()); @@ -300,7 +441,7 @@ TEST_F(ImmediateInputRouterTest, HandleKeyEventsWeSent) { ack_handler_->acked_keyboard_event().type); } -TEST_F(ImmediateInputRouterTest, IgnoreKeyEventsWeDidntSend) { +TEST_F(InputRouterImplTest, IgnoreKeyEventsWeDidntSend) { // Send a simulated, unrequested key response. We should ignore this. SendInputEventACK(WebInputEvent::RawKeyDown, INPUT_EVENT_ACK_STATE_NOT_CONSUMED); @@ -308,7 +449,7 @@ TEST_F(ImmediateInputRouterTest, IgnoreKeyEventsWeDidntSend) { EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount()); } -TEST_F(ImmediateInputRouterTest, CoalescesWheelEvents) { +TEST_F(InputRouterImplTest, CoalescesWheelEvents) { // Simulate wheel events. SimulateWheelEvent(0, -5, 0, false); // sent directly SimulateWheelEvent(0, -10, 0, false); // enqueued @@ -320,7 +461,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesWheelEvents) { InputMsg_HandleInputEvent::ID)); EXPECT_EQ(1U, GetSentMessageCountAndResetSink()); - // Check that the ACK sends the second message via ImmediateInputForwarder + // Check that the ACK sends the second message immediately. SendInputEventACK(WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED); // The coalesced events can queue up a delayed ack @@ -349,7 +490,7 @@ TEST_F(ImmediateInputRouterTest, CoalescesWheelEvents) { EXPECT_EQ(0U, GetSentMessageCountAndResetSink()); } -TEST_F(ImmediateInputRouterTest, +TEST_F(InputRouterImplTest, CoalescesWheelEventsQueuedPhaseEndIsNotDropped) { // Send an initial gesture begin and ACK it. SimulateGestureEvent(WebInputEvent::GestureScrollBegin, @@ -388,7 +529,7 @@ TEST_F(ImmediateInputRouterTest, } // Tests that touch-events are queued properly. -TEST_F(ImmediateInputRouterTest, TouchEventQueue) { +TEST_F(InputRouterImplTest, TouchEventQueue) { PressTouchPoint(1, 1); SendTouchEvent(); EXPECT_TRUE(client_->GetAndResetFilterEventCalled()); @@ -422,7 +563,7 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueue) { // Tests that the touch-queue is emptied if a page stops listening for touch // events. -TEST_F(ImmediateInputRouterTest, TouchEventQueueFlush) { +TEST_F(InputRouterImplTest, TouchEventQueueFlush) { input_router_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true)); EXPECT_TRUE(client_->has_touch_handler()); EXPECT_EQ(0U, GetSentMessageCountAndResetSink()); @@ -449,7 +590,7 @@ TEST_F(ImmediateInputRouterTest, TouchEventQueueFlush) { #if defined(OS_WIN) || defined(USE_AURA) // Tests that the acked events have correct state. (ui::Events are used only on // windows and aura) -TEST_F(ImmediateInputRouterTest, AckedTouchEventState) { +TEST_F(InputRouterImplTest, AckedTouchEventState) { input_router_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true)); EXPECT_EQ(0U, GetSentMessageCountAndResetSink()); EXPECT_TRUE(TouchEventQueueEmpty()); @@ -533,7 +674,7 @@ TEST_F(ImmediateInputRouterTest, AckedTouchEventState) { } #endif // defined(OS_WIN) || defined(USE_AURA) -TEST_F(ImmediateInputRouterTest, UnhandledWheelEvent) { +TEST_F(InputRouterImplTest, UnhandledWheelEvent) { // Simulate wheel events. SimulateWheelEvent(0, -5, 0, false); // sent directly SimulateWheelEvent(0, -10, 0, false); // enqueued @@ -561,7 +702,7 @@ TEST_F(ImmediateInputRouterTest, UnhandledWheelEvent) { EXPECT_EQ(ack_handler_->acked_wheel_event().deltaY, -5); } -TEST_F(ImmediateInputRouterTest, TouchTypesIgnoringAck) { +TEST_F(InputRouterImplTest, TouchTypesIgnoringAck) { int start_type = static_cast<int>(WebInputEvent::TouchStart); int end_type = static_cast<int>(WebInputEvent::TouchCancel); for (int i = start_type; i <= end_type; ++i) { @@ -588,7 +729,7 @@ TEST_F(ImmediateInputRouterTest, TouchTypesIgnoringAck) { } } -TEST_F(ImmediateInputRouterTest, GestureTypesIgnoringAck) { +TEST_F(InputRouterImplTest, GestureTypesIgnoringAck) { int start_type = static_cast<int>(WebInputEvent::GestureScrollBegin); int end_type = static_cast<int>(WebInputEvent::GesturePinchUpdate); for (int i = start_type; i <= end_type; ++i) { @@ -607,7 +748,7 @@ TEST_F(ImmediateInputRouterTest, GestureTypesIgnoringAck) { // Test that GestureShowPress, GestureTapDown and GestureTapCancel events don't // wait for ACKs. -TEST_F(ImmediateInputRouterTest, GestureTypesIgnoringAckInterleaved) { +TEST_F(InputRouterImplTest, GestureTypesIgnoringAckInterleaved) { // Interleave a few events that do and do not ignore acks, ensuring that // ack-ignoring events aren't dispatched until all prior events which observe // their ack disposition have been dispatched. @@ -680,7 +821,7 @@ TEST_F(ImmediateInputRouterTest, GestureTypesIgnoringAckInterleaved) { // Test that GestureShowPress events don't get out of order due to // ignoring their acks. -TEST_F(ImmediateInputRouterTest, GestureShowPressIsInOrder) { +TEST_F(InputRouterImplTest, GestureShowPressIsInOrder) { SimulateGestureEvent(WebInputEvent::GestureTap, WebGestureEvent::Touchscreen); @@ -711,4 +852,31 @@ TEST_F(ImmediateInputRouterTest, GestureShowPressIsInOrder) { EXPECT_EQ(3U, ack_handler_->GetAndResetAckCount()); } +// Test that touch ack timeout behavior is properly configured via the command +// line, and toggled by the view update flags. +TEST_F(InputRouterImplTest, TouchAckTimeoutConfigured) { + CommandLine::ForCurrentProcess()->AppendSwitchASCII( + switches::kTouchAckTimeoutDelayMs, "5"); + TearDown(); + SetUp(); + ASSERT_TRUE(TouchEventTimeoutEnabled()); + + // A fixed page scale or mobile viewport should disable the touch timeout. + input_router()->OnViewUpdated(InputRouter::FIXED_PAGE_SCALE); + EXPECT_FALSE(TouchEventTimeoutEnabled()); + + input_router()->OnViewUpdated(InputRouter::VIEW_FLAGS_NONE); + EXPECT_TRUE(TouchEventTimeoutEnabled()); + + input_router()->OnViewUpdated(InputRouter::MOBILE_VIEWPORT); + EXPECT_FALSE(TouchEventTimeoutEnabled()); + + input_router()->OnViewUpdated(InputRouter::MOBILE_VIEWPORT | + InputRouter::FIXED_PAGE_SCALE); + EXPECT_FALSE(TouchEventTimeoutEnabled()); + + input_router()->OnViewUpdated(InputRouter::VIEW_FLAGS_NONE); + EXPECT_TRUE(TouchEventTimeoutEnabled()); +} + } // namespace content diff --git a/content/browser/renderer_host/input/input_router_unittest.cc b/content/browser/renderer_host/input/input_router_unittest.cc deleted file mode 100644 index b1181eed9b..0000000000 --- a/content/browser/renderer_host/input/input_router_unittest.cc +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/renderer_host/input/input_router_unittest.h" - -#include "content/browser/renderer_host/input/input_router.h" -#include "content/common/input_messages.h" - -using blink::WebGestureEvent; -using blink::WebInputEvent; -using blink::WebMouseEvent; -using blink::WebMouseWheelEvent; -using blink::WebTouchEvent; -using blink::WebTouchPoint; - -namespace content { - -InputRouterTest::InputRouterTest() {} -InputRouterTest::~InputRouterTest() {} - -void InputRouterTest::SetUp() { - browser_context_.reset(new TestBrowserContext()); - process_.reset(new MockRenderProcessHost(browser_context_.get())); - client_.reset(new MockInputRouterClient()); - ack_handler_.reset(new MockInputAckHandler()); - input_router_ = CreateInputRouter(process_.get(), - client_.get(), - ack_handler_.get(), - MSG_ROUTING_NONE); - client_->set_input_router(input_router_.get()); - ack_handler_->set_input_router(input_router_.get()); -} - -void InputRouterTest::TearDown() { - // Process all pending tasks to avoid InputRouterTest::leaks. - base::MessageLoop::current()->RunUntilIdle(); - - input_router_.reset(); - client_.reset(); - process_.reset(); - browser_context_.reset(); -} - -void InputRouterTest::SimulateKeyboardEvent(WebInputEvent::Type type, - bool is_shortcut) { - input_router_->SendKeyboardEvent( - SyntheticWebKeyboardEventBuilder::Build(type), - ui::LatencyInfo(), - is_shortcut); -} - -void InputRouterTest::SimulateWheelEvent(float dX, - float dY, - int modifiers, - bool precise) { - input_router_->SendWheelEvent( - MouseWheelEventWithLatencyInfo( - SyntheticWebMouseWheelEventBuilder::Build(dX, dY, modifiers, precise), - ui::LatencyInfo())); -} - -void InputRouterTest::SimulateMouseMove(int x, int y, int modifiers) { - input_router_->SendMouseEvent( - MouseEventWithLatencyInfo(SyntheticWebMouseEventBuilder::Build( - WebInputEvent::MouseMove, x, y, modifiers), - ui::LatencyInfo())); -} - -void InputRouterTest::SimulateWheelEventWithPhase( - WebMouseWheelEvent::Phase phase) { - input_router_->SendWheelEvent( - MouseWheelEventWithLatencyInfo( - SyntheticWebMouseWheelEventBuilder::Build(phase), ui::LatencyInfo())); -} - -void InputRouterTest::SimulateGestureEvent( - const WebGestureEvent& gesture) { - GestureEventWithLatencyInfo gesture_with_latency(gesture, ui::LatencyInfo()); - input_router_->SendGestureEvent(gesture_with_latency); -} - -void InputRouterTest::SimulateGestureEvent( - WebInputEvent::Type type, - WebGestureEvent::SourceDevice sourceDevice) { - SimulateGestureEvent( - SyntheticWebGestureEventBuilder::Build(type, sourceDevice)); -} - -void InputRouterTest::SimulateGestureScrollUpdateEvent(float dX, - float dY, - int modifiers) { - SimulateGestureEvent( - SyntheticWebGestureEventBuilder::BuildScrollUpdate(dX, dY, modifiers)); -} - -void InputRouterTest::SimulateGesturePinchUpdateEvent(float scale, - float anchorX, - float anchorY, - int modifiers) { - SimulateGestureEvent( - SyntheticWebGestureEventBuilder::BuildPinchUpdate(scale, - anchorX, - anchorY, - modifiers)); -} - -void InputRouterTest::SimulateGestureFlingStartEvent( - float velocityX, - float velocityY, - WebGestureEvent::SourceDevice sourceDevice) { - SimulateGestureEvent( - SyntheticWebGestureEventBuilder::BuildFling(velocityX, - velocityY, - sourceDevice)); -} - -void InputRouterTest::SimulateTouchEvent(WebInputEvent::Type type) { - touch_event_.ResetPoints(); - int index = PressTouchPoint(0, 0); - switch (type) { - case WebInputEvent::TouchStart: - // Already handled by |PressTouchPoint()|. - break; - case WebInputEvent::TouchMove: - MoveTouchPoint(index, 5, 5); - break; - case WebInputEvent::TouchEnd: - ReleaseTouchPoint(index); - break; - case WebInputEvent::TouchCancel: - CancelTouchPoint(index); - break; - default: - FAIL() << "Invalid touch event type."; - break; - } - SendTouchEvent(); -} - -void InputRouterTest::SetTouchTimestamp(base::TimeDelta timestamp) { - touch_event_.SetTimestamp(timestamp); -} - -void InputRouterTest::SendTouchEvent() { - input_router_->SendTouchEvent( - TouchEventWithLatencyInfo(touch_event_, ui::LatencyInfo())); - touch_event_.ResetPoints(); -} - -int InputRouterTest::PressTouchPoint(int x, int y) { - return touch_event_.PressPoint(x, y); -} - -void InputRouterTest::MoveTouchPoint(int index, int x, int y) { - touch_event_.MovePoint(index, x, y); -} - -void InputRouterTest::ReleaseTouchPoint(int index) { - touch_event_.ReleasePoint(index); -} - -void InputRouterTest::CancelTouchPoint(int index) { - touch_event_.CancelPoint(index); -} - -} // namespace content diff --git a/content/browser/renderer_host/input/input_router_unittest.h b/content/browser/renderer_host/input/input_router_unittest.h deleted file mode 100644 index d9a6775456..0000000000 --- a/content/browser/renderer_host/input/input_router_unittest.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_UNITTEST_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_UNITTEST_H_ - -#include "base/memory/scoped_ptr.h" -#include "content/browser/renderer_host/input/input_router_client.h" -#include "content/browser/renderer_host/input/mock_input_ack_handler.h" -#include "content/browser/renderer_host/input/mock_input_router_client.h" -#include "content/browser/renderer_host/input/synthetic_web_input_event_builders.h" -#include "content/public/test/mock_render_process_host.h" -#include "content/public/test/test_browser_context.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/WebKit/public/web/WebInputEvent.h" - -namespace content { - -class InputRouter; -class MockInputRouterClient; - -class InputRouterTest : public testing::Test { - public: - InputRouterTest(); - virtual ~InputRouterTest(); - - protected: - // Called on SetUp. - virtual scoped_ptr<InputRouter> CreateInputRouter(RenderProcessHost* process, - InputRouterClient* client, - InputAckHandler* handler, - int routing_id) = 0; - - // testing::Test - virtual void SetUp() OVERRIDE; - virtual void TearDown() OVERRIDE; - - void SendInputEventACK(blink::WebInputEvent::Type type, - InputEventAckState ack_result); - void SimulateKeyboardEvent(blink::WebInputEvent::Type type, - bool is_shortcut); - void SimulateWheelEvent(float dX, float dY, int modifiers, bool precise); - void SimulateMouseMove(int x, int y, int modifiers); - void SimulateWheelEventWithPhase(blink::WebMouseWheelEvent::Phase phase); - void SimulateGestureEvent(const blink::WebGestureEvent& event); - void SimulateGestureEvent(blink::WebInputEvent::Type type, - blink::WebGestureEvent::SourceDevice sourceDevice); - void SimulateGestureScrollUpdateEvent(float dX, float dY, int modifiers); - void SimulateGesturePinchUpdateEvent(float scale, - float anchorX, - float anchorY, - int modifiers); - void SimulateGestureFlingStartEvent( - float velocityX, - float velocityY, - blink::WebGestureEvent::SourceDevice sourceDevice); - void SimulateTouchEvent(blink::WebInputEvent::Type type); - void SetTouchTimestamp(base::TimeDelta timestamp); - - // Sends a touch event (irrespective of whether the page has a touch-event - // handler or not). - void SendTouchEvent(); - - int PressTouchPoint(int x, int y); - void MoveTouchPoint(int index, int x, int y); - void ReleaseTouchPoint(int index); - void CancelTouchPoint(int index); - - scoped_ptr<MockRenderProcessHost> process_; - scoped_ptr<MockInputRouterClient> client_; - scoped_ptr<MockInputAckHandler> ack_handler_; - scoped_ptr<InputRouter> input_router_; - - private: - base::MessageLoopForUI message_loop_; - SyntheticWebTouchEvent touch_event_; - - scoped_ptr<TestBrowserContext> browser_context_; -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_MOCK_INPUT_ROUTER_UNITTEST_H_ diff --git a/content/browser/renderer_host/input/synthetic_gesture.cc b/content/browser/renderer_host/input/synthetic_gesture.cc index 9b57168dcd..8b2b3bedbe 100644 --- a/content/browser/renderer_host/input/synthetic_gesture.cc +++ b/content/browser/renderer_host/input/synthetic_gesture.cc @@ -4,9 +4,11 @@ #include "content/browser/renderer_host/input/synthetic_gesture.h" +#include "base/logging.h" #include "content/browser/renderer_host/input/synthetic_gesture_target.h" #include "content/browser/renderer_host/input/synthetic_pinch_gesture.h" #include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" +#include "content/browser/renderer_host/input/synthetic_tap_gesture.h" namespace content { namespace { @@ -33,6 +35,9 @@ scoped_ptr<SyntheticGesture> SyntheticGesture::Create( case SyntheticGestureParams::PINCH_GESTURE: return CreateGesture<SyntheticPinchGesture, SyntheticPinchGestureParams>(gesture_params); + case SyntheticGestureParams::TAP_GESTURE: + return CreateGesture<SyntheticTapGesture, + SyntheticTapGestureParams>(gesture_params); } NOTREACHED() << "Invalid synthetic gesture type"; return scoped_ptr<SyntheticGesture>(); diff --git a/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc b/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc index baefa695d1..f449e5774c 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc +++ b/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc @@ -9,15 +9,21 @@ #include "content/browser/renderer_host/input/synthetic_gesture_target.h" #include "content/browser/renderer_host/input/synthetic_pinch_gesture.h" #include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" +#include "content/browser/renderer_host/input/synthetic_tap_gesture.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" -#include "content/browser/renderer_host/test_render_view_host.h" #include "content/common/input/input_event.h" +#include "content/common/input/synthetic_pinch_gesture_params.h" #include "content/common/input/synthetic_smooth_scroll_gesture_params.h" +#include "content/common/input/synthetic_tap_gesture_params.h" #include "content/public/test/mock_render_process_host.h" #include "content/public/test/test_browser_context.h" +#include "content/test/test_render_view_host.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/gfx/point.h" #include "ui/gfx/point_f.h" +#include "ui/gfx/vector2d.h" +#include "ui/gfx/vector2d_f.h" namespace content { @@ -25,6 +31,7 @@ namespace { const int kFlushInputRateInMs = 16; const int kPointerAssumedStoppedTimeMs = 43; +const int kTouchSlopInDips = 7; class MockSyntheticGesture : public SyntheticGesture { public: @@ -100,6 +107,10 @@ class MockSyntheticGestureTarget : public SyntheticGestureTarget { pointer_assumed_stopped_time_ms_ = time_ms; } + virtual int GetTouchSlopInDips() const OVERRIDE { + return kTouchSlopInDips; + } + int num_success() const { return num_success_; } int num_failure() const { return num_failure_; } @@ -115,9 +126,22 @@ class MockSyntheticGestureTarget : public SyntheticGestureTarget { int pointer_assumed_stopped_time_ms_; }; -class MockSyntheticSmoothScrollMouseTarget : public MockSyntheticGestureTarget { +class MockSyntheticSmoothScrollGestureTarget + : public MockSyntheticGestureTarget { public: - MockSyntheticSmoothScrollMouseTarget() : scroll_distance_(0) {} + MockSyntheticSmoothScrollGestureTarget() {} + virtual ~MockSyntheticSmoothScrollGestureTarget() {} + + gfx::Vector2dF scroll_distance() const { return scroll_distance_; } + + protected: + gfx::Vector2dF scroll_distance_; +}; + +class MockSyntheticSmoothScrollMouseTarget + : public MockSyntheticSmoothScrollGestureTarget { + public: + MockSyntheticSmoothScrollMouseTarget() {} virtual ~MockSyntheticSmoothScrollMouseTarget() {} virtual void DispatchInputEventToPlatform(const InputEvent& event) OVERRIDE { @@ -125,20 +149,16 @@ class MockSyntheticSmoothScrollMouseTarget : public MockSyntheticGestureTarget { ASSERT_EQ(web_event->type, blink::WebInputEvent::MouseWheel); const blink::WebMouseWheelEvent* mouse_wheel_event = static_cast<const blink::WebMouseWheelEvent*>(web_event); - ASSERT_EQ(mouse_wheel_event->deltaX, 0); - scroll_distance_ -= mouse_wheel_event->deltaY; + scroll_distance_ -= gfx::Vector2dF(mouse_wheel_event->deltaX, + mouse_wheel_event->deltaY); } - - float scroll_distance() const { return scroll_distance_; } - - private: - float scroll_distance_; }; -class MockSyntheticSmoothScrollTouchTarget : public MockSyntheticGestureTarget { +class MockSyntheticSmoothScrollTouchTarget + : public MockSyntheticSmoothScrollGestureTarget { public: MockSyntheticSmoothScrollTouchTarget() - : scroll_distance_(0), anchor_y_(0), started_(false) {} + : started_(false) {} virtual ~MockSyntheticSmoothScrollTouchTarget() {} virtual void DispatchInputEventToPlatform(const InputEvent& event) OVERRIDE { @@ -150,7 +170,8 @@ class MockSyntheticSmoothScrollTouchTarget : public MockSyntheticGestureTarget { if (!started_) { ASSERT_EQ(touch_event->type, blink::WebInputEvent::TouchStart); - anchor_y_ = touch_event->touches[0].position.y; + anchor_.SetPoint(touch_event->touches[0].position.x, + touch_event->touches[0].position.y); started_ = true; } else { ASSERT_NE(touch_event->type, blink::WebInputEvent::TouchStart); @@ -158,15 +179,14 @@ class MockSyntheticSmoothScrollTouchTarget : public MockSyntheticGestureTarget { // Ignore move events. if (touch_event->type == blink::WebInputEvent::TouchEnd) - scroll_distance_ = anchor_y_ - touch_event->touches[0].position.y; + scroll_distance_ = + anchor_ - gfx::PointF(touch_event->touches[0].position.x, + touch_event->touches[0].position.y); } } - float scroll_distance() const { return scroll_distance_; } - - private: - float scroll_distance_; - float anchor_y_; + protected: + gfx::Point anchor_; bool started_; }; @@ -244,6 +264,88 @@ class MockSyntheticPinchTouchTarget : public MockSyntheticGestureTarget { bool started_; }; +class MockSyntheticTapGestureTarget : public MockSyntheticGestureTarget { + public: + MockSyntheticTapGestureTarget() : state_(NOT_STARTED) {} + virtual ~MockSyntheticTapGestureTarget() {} + + bool GestureFinished() const { return state_ == FINISHED; } + gfx::Point position() const { return position_; } + + protected: + enum GestureState { + NOT_STARTED, + STARTED, + FINISHED + }; + + gfx::Point position_; + GestureState state_; +}; + +class MockSyntheticTapTouchTarget : public MockSyntheticTapGestureTarget { + public: + MockSyntheticTapTouchTarget() {} + virtual ~MockSyntheticTapTouchTarget() {} + + virtual void DispatchInputEventToPlatform(const InputEvent& event) OVERRIDE { + const blink::WebInputEvent* web_event = event.web_event.get(); + ASSERT_TRUE(blink::WebInputEvent::isTouchEventType(web_event->type)); + const blink::WebTouchEvent* touch_event = + static_cast<const blink::WebTouchEvent*>(web_event); + ASSERT_EQ(touch_event->touchesLength, (unsigned int)1); + + switch (state_) { + case NOT_STARTED: + EXPECT_EQ(touch_event->type, blink::WebInputEvent::TouchStart); + position_ = gfx::Point(touch_event->touches[0].position); + state_ = STARTED; + break; + case STARTED: + EXPECT_EQ(touch_event->type, blink::WebInputEvent::TouchEnd); + EXPECT_EQ(position_, gfx::Point(touch_event->touches[0].position)); + state_ = FINISHED; + break; + case FINISHED: + EXPECT_FALSE(true); + break; + } + } +}; + +class MockSyntheticTapMouseTarget : public MockSyntheticTapGestureTarget { + public: + MockSyntheticTapMouseTarget() {} + virtual ~MockSyntheticTapMouseTarget() {} + + virtual void DispatchInputEventToPlatform(const InputEvent& event) OVERRIDE { + const blink::WebInputEvent* web_event = event.web_event.get(); + ASSERT_TRUE(blink::WebInputEvent::isMouseEventType(web_event->type)); + const blink::WebMouseEvent* mouse_event = + static_cast<const blink::WebMouseEvent*>(web_event); + + switch (state_) { + case NOT_STARTED: + EXPECT_EQ(mouse_event->type, blink::WebInputEvent::MouseDown); + EXPECT_EQ(mouse_event->button, blink::WebMouseEvent::ButtonLeft); + EXPECT_EQ(mouse_event->clickCount, 1); + position_ = gfx::Point(mouse_event->x, mouse_event->y); + state_ = STARTED; + break; + case STARTED: + EXPECT_EQ(mouse_event->type, blink::WebInputEvent::MouseUp); + EXPECT_EQ(mouse_event->button, blink::WebMouseEvent::ButtonLeft); + EXPECT_EQ(mouse_event->clickCount, 1); + EXPECT_EQ(position_, gfx::Point(mouse_event->x, mouse_event->y)); + state_ = FINISHED; + break; + case FINISHED: + EXPECT_FALSE(true); + break; + } + } +}; + class SyntheticGestureControllerTest : public testing::Test { public: SyntheticGestureControllerTest() {} @@ -359,23 +461,105 @@ TEST_F(SyntheticGestureControllerTest, TwoGesturesInFlight) { EXPECT_EQ(0, target_->num_failure()); } -TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureTouch) { +gfx::Vector2d AddTouchSlopToVector(const gfx::Vector2d& vector, + SyntheticGestureTarget* target) { + const int kTouchSlop = target->GetTouchSlopInDips(); + + int x = vector.x(); + if (x > 0) + x += kTouchSlop; + else if (x < 0) + x -= kTouchSlop; + + int y = vector.y(); + if (y > 0) + y += kTouchSlop; + else if (y < 0) + y -= kTouchSlop; + + return gfx::Vector2d(x, y); +} + +TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureTouchVertical) { + CreateControllerAndTarget<MockSyntheticSmoothScrollTouchTarget>(); + + SyntheticSmoothScrollGestureParams params; + params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; + params.distance = gfx::Vector2d(0, 123); + params.anchor.SetPoint(89, 32); + + scoped_ptr<SyntheticSmoothScrollGesture> gesture( + new SyntheticSmoothScrollGesture(params)); + controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); + FlushInputUntilComplete(); + + MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target = + static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_); + EXPECT_EQ(1, target_->num_success()); + EXPECT_EQ(0, target_->num_failure()); + EXPECT_EQ(AddTouchSlopToVector(params.distance, target_), + smooth_scroll_target->scroll_distance()); +} + +TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureTouchHorizontal) { CreateControllerAndTarget<MockSyntheticSmoothScrollTouchTarget>(); SyntheticSmoothScrollGestureParams params; params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; - params.distance = 123; + params.distance = gfx::Vector2d(-234, 0); + params.anchor.SetPoint(12, -23); scoped_ptr<SyntheticSmoothScrollGesture> gesture( new SyntheticSmoothScrollGesture(params)); controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); FlushInputUntilComplete(); + MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target = + static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_); EXPECT_EQ(1, target_->num_success()); EXPECT_EQ(0, target_->num_failure()); - EXPECT_FLOAT_EQ(params.distance, - static_cast<MockSyntheticSmoothScrollTouchTarget*>(target_) - ->scroll_distance()); + EXPECT_EQ(AddTouchSlopToVector(params.distance, target_), + smooth_scroll_target->scroll_distance()); +} + +void CheckIsWithinRange(float scroll_distance, + int target_distance, + SyntheticGestureTarget* target) { + if (target_distance > 0) { + EXPECT_LE(target_distance, scroll_distance); + EXPECT_LE(scroll_distance, target_distance + target->GetTouchSlopInDips()); + } else { + EXPECT_GE(target_distance, scroll_distance); + EXPECT_GE(scroll_distance, target_distance - target->GetTouchSlopInDips()); + } +} + +void CheckScrollDistanceIsWithinRange(const gfx::Vector2dF& scroll_distance, + const gfx::Vector2d& target_distance, + SyntheticGestureTarget* target) { + CheckIsWithinRange(scroll_distance.x(), target_distance.x(), target); + CheckIsWithinRange(scroll_distance.y(), target_distance.y(), target); +} + +TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureTouchDiagonal) { + CreateControllerAndTarget<MockSyntheticSmoothScrollTouchTarget>(); + + SyntheticSmoothScrollGestureParams params; + params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; + params.distance = gfx::Vector2d(413, -83); + params.anchor.SetPoint(0, 7); + + scoped_ptr<SyntheticSmoothScrollGesture> gesture( + new SyntheticSmoothScrollGesture(params)); + controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); + FlushInputUntilComplete(); + + MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target = + static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_); + EXPECT_EQ(1, target_->num_success()); + EXPECT_EQ(0, target_->num_failure()); + CheckScrollDistanceIsWithinRange( + smooth_scroll_target->scroll_distance(), params.distance, target_); } TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureTouchLongStop) { @@ -386,7 +570,9 @@ TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureTouchLongStop) { // gesture is active. SyntheticSmoothScrollGestureParams params; params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; - params.distance = 21; + params.distance = gfx::Vector2d(21, -12); + params.prevent_fling = true; + params.anchor.SetPoint(-98, -23); target_->set_pointer_assumed_stopped_time_ms(543); @@ -395,31 +581,121 @@ TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureTouchLongStop) { controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); FlushInputUntilComplete(); + MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target = + static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_); EXPECT_EQ(1, target_->num_success()); EXPECT_EQ(0, target_->num_failure()); - EXPECT_FLOAT_EQ(params.distance, - static_cast<MockSyntheticSmoothScrollTouchTarget*>(target_) - ->scroll_distance()); + CheckScrollDistanceIsWithinRange( + smooth_scroll_target->scroll_distance(), params.distance, target_); EXPECT_GE(GetTotalTime(), target_->PointerAssumedStoppedTime()); } -TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureMouse) { +TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureTouchFling) { + CreateControllerAndTarget<MockSyntheticSmoothScrollTouchTarget>(); + + // Create a smooth scroll with a short distance and set the pointer assumed + // stopped time high. Disable 'prevent_fling' and check that the gesture + // finishes without waiting before it stops. + SyntheticSmoothScrollGestureParams params; + params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; + params.distance = gfx::Vector2d(-43, 19); + params.prevent_fling = false; + params.anchor.SetPoint(-89, 78); + + target_->set_pointer_assumed_stopped_time_ms(543); + + scoped_ptr<SyntheticSmoothScrollGesture> gesture( + new SyntheticSmoothScrollGesture(params)); + controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); + FlushInputUntilComplete(); + + MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target = + static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_); + EXPECT_EQ(1, target_->num_success()); + EXPECT_EQ(0, target_->num_failure()); + CheckScrollDistanceIsWithinRange( + smooth_scroll_target->scroll_distance(), params.distance, target_); + EXPECT_LE(GetTotalTime(), target_->PointerAssumedStoppedTime()); +} + +TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureTouchZeroDistance) { + CreateControllerAndTarget<MockSyntheticSmoothScrollTouchTarget>(); + + SyntheticSmoothScrollGestureParams params; + params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; + params.distance = gfx::Vector2d(0, 0); + params.anchor.SetPoint(-32, 43); + + scoped_ptr<SyntheticSmoothScrollGesture> gesture( + new SyntheticSmoothScrollGesture(params)); + controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); + FlushInputUntilComplete(); + + MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target = + static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_); + EXPECT_EQ(1, target_->num_success()); + EXPECT_EQ(0, target_->num_failure()); + EXPECT_EQ(gfx::Vector2dF(0, 0), smooth_scroll_target->scroll_distance()); +} + +TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureMouseVertical) { + CreateControllerAndTarget<MockSyntheticSmoothScrollMouseTarget>(); + + SyntheticSmoothScrollGestureParams params; + params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT; + params.distance = gfx::Vector2d(0, -234); + params.anchor.SetPoint(432, 89); + + scoped_ptr<SyntheticSmoothScrollGesture> gesture( + new SyntheticSmoothScrollGesture(params)); + controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); + FlushInputUntilComplete(); + + MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target = + static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_); + EXPECT_EQ(1, target_->num_success()); + EXPECT_EQ(0, target_->num_failure()); + EXPECT_EQ(params.distance, smooth_scroll_target->scroll_distance()); +} + +TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureMouseHorizontal) { CreateControllerAndTarget<MockSyntheticSmoothScrollMouseTarget>(); SyntheticSmoothScrollGestureParams params; params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT; - params.distance = -234; + params.distance = gfx::Vector2d(345, 0); + params.anchor.SetPoint(90, 12); scoped_ptr<SyntheticSmoothScrollGesture> gesture( new SyntheticSmoothScrollGesture(params)); controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); FlushInputUntilComplete(); + MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target = + static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_); EXPECT_EQ(1, target_->num_success()); EXPECT_EQ(0, target_->num_failure()); - EXPECT_FLOAT_EQ(params.distance, - static_cast<MockSyntheticSmoothScrollTouchTarget*>(target_) - ->scroll_distance()); + EXPECT_EQ(params.distance, smooth_scroll_target->scroll_distance()); +} + +TEST_F(SyntheticGestureControllerTest, SmoothScrollGestureMouseDiagonal) { + CreateControllerAndTarget<MockSyntheticSmoothScrollMouseTarget>(); + + SyntheticSmoothScrollGestureParams params; + params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT; + params.distance = gfx::Vector2d(-194, 303); + params.anchor.SetPoint(90, 12); + + scoped_ptr<SyntheticSmoothScrollGesture> gesture( + new SyntheticSmoothScrollGesture(params)); + controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); + FlushInputUntilComplete(); + + MockSyntheticSmoothScrollGestureTarget* smooth_scroll_target = + static_cast<MockSyntheticSmoothScrollGestureTarget*>(target_); + EXPECT_EQ(1, target_->num_success()); + EXPECT_EQ(0, target_->num_failure()); + EXPECT_EQ(params.distance, smooth_scroll_target->scroll_distance()); } TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZoomIn) { @@ -429,19 +705,20 @@ TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZoomIn) { params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; params.zoom_in = true; params.total_num_pixels_covered = 345; + params.anchor.SetPoint(54, 89); scoped_ptr<SyntheticPinchGesture> gesture(new SyntheticPinchGesture(params)); controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); FlushInputUntilComplete(); + MockSyntheticPinchTouchTarget* pinch_target = + static_cast<MockSyntheticPinchTouchTarget*>(target_); EXPECT_EQ(1, target_->num_success()); EXPECT_EQ(0, target_->num_failure()); - EXPECT_EQ( - static_cast<MockSyntheticPinchTouchTarget*>(target_)->zoom_direction(), - MockSyntheticPinchTouchTarget::ZOOM_IN); - EXPECT_FLOAT_EQ(params.total_num_pixels_covered, - static_cast<MockSyntheticPinchTouchTarget*>(target_) - ->total_num_pixels_covered()); + EXPECT_EQ(pinch_target->zoom_direction(), + MockSyntheticPinchTouchTarget::ZOOM_IN); + EXPECT_EQ(params.total_num_pixels_covered + 2 * target_->GetTouchSlopInDips(), + pinch_target->total_num_pixels_covered()); } TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZoomOut) { @@ -451,19 +728,85 @@ TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZoomOut) { params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; params.zoom_in = false; params.total_num_pixels_covered = 456; + params.anchor.SetPoint(-12, 93); scoped_ptr<SyntheticPinchGesture> gesture(new SyntheticPinchGesture(params)); controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); FlushInputUntilComplete(); + MockSyntheticPinchTouchTarget* pinch_target = + static_cast<MockSyntheticPinchTouchTarget*>(target_); + EXPECT_EQ(1, target_->num_success()); + EXPECT_EQ(0, target_->num_failure()); + EXPECT_EQ(pinch_target->zoom_direction(), + MockSyntheticPinchTouchTarget::ZOOM_OUT); + EXPECT_EQ(params.total_num_pixels_covered + 2 * target_->GetTouchSlopInDips(), + pinch_target->total_num_pixels_covered()); +} + +TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZeroPixelsCovered) { + CreateControllerAndTarget<MockSyntheticPinchTouchTarget>(); + + SyntheticPinchGestureParams params; + params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; + params.zoom_in = true; + params.total_num_pixels_covered = 0; + + scoped_ptr<SyntheticPinchGesture> gesture(new SyntheticPinchGesture(params)); + controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); + FlushInputUntilComplete(); + + MockSyntheticPinchTouchTarget* pinch_target = + static_cast<MockSyntheticPinchTouchTarget*>(target_); + EXPECT_EQ(1, target_->num_success()); + EXPECT_EQ(0, target_->num_failure()); + EXPECT_EQ(pinch_target->zoom_direction(), + MockSyntheticPinchTouchTarget::ZOOM_DIRECTION_UNKNOWN); + EXPECT_EQ(0, pinch_target->total_num_pixels_covered()); +} + +TEST_F(SyntheticGestureControllerTest, TapGestureTouch) { + CreateControllerAndTarget<MockSyntheticTapTouchTarget>(); + + SyntheticTapGestureParams params; + params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; + params.duration_ms = 123; + params.position.SetPoint(87, -124); + + scoped_ptr<SyntheticTapGesture> gesture(new SyntheticTapGesture(params)); + controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); + FlushInputUntilComplete(); + + MockSyntheticTapTouchTarget* tap_target = + static_cast<MockSyntheticTapTouchTarget*>(target_); + EXPECT_EQ(1, target_->num_success()); + EXPECT_EQ(0, target_->num_failure()); + EXPECT_TRUE(tap_target->GestureFinished()); + EXPECT_EQ(tap_target->position(), params.position); + EXPECT_GE(GetTotalTime(), + base::TimeDelta::FromMilliseconds(params.duration_ms)); +} + +TEST_F(SyntheticGestureControllerTest, TapGestureMouse) { + CreateControllerAndTarget<MockSyntheticTapMouseTarget>(); + + SyntheticTapGestureParams params; + params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT; + params.duration_ms = 79; + params.position.SetPoint(98, 123); + + scoped_ptr<SyntheticTapGesture> gesture(new SyntheticTapGesture(params)); + controller_->QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>()); + FlushInputUntilComplete(); + + MockSyntheticTapMouseTarget* tap_target = + static_cast<MockSyntheticTapMouseTarget*>(target_); EXPECT_EQ(1, target_->num_success()); EXPECT_EQ(0, target_->num_failure()); - EXPECT_EQ( - static_cast<MockSyntheticPinchTouchTarget*>(target_)->zoom_direction(), - MockSyntheticPinchTouchTarget::ZOOM_OUT); - EXPECT_FLOAT_EQ(params.total_num_pixels_covered, - static_cast<MockSyntheticPinchTouchTarget*>(target_) - ->total_num_pixels_covered()); + EXPECT_TRUE(tap_target->GestureFinished()); + EXPECT_EQ(tap_target->position(), params.position); + EXPECT_GE(GetTotalTime(), + base::TimeDelta::FromMilliseconds(params.duration_ms)); } } // namespace diff --git a/content/browser/renderer_host/input/synthetic_gesture_target.h b/content/browser/renderer_host/input/synthetic_gesture_target.h index 5b31b0294f..01487fc277 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_target.h +++ b/content/browser/renderer_host/input/synthetic_gesture_target.h @@ -44,6 +44,10 @@ class CONTENT_EXPORT SyntheticGestureTarget { // After how much time of inaction does the target assume that a pointer has // stopped moving. virtual base::TimeDelta PointerAssumedStoppedTime() const = 0; + + // Returns the maximum number of DIPs a touch pointer can move without being + // considered moving by the platform. + virtual int GetTouchSlopInDips() const = 0; }; } // namespace content diff --git a/content/browser/renderer_host/input/synthetic_gesture_target_android.cc b/content/browser/renderer_host/input/synthetic_gesture_target_android.cc index acaee85dd9..cf5181ab93 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_target_android.cc +++ b/content/browser/renderer_host/input/synthetic_gesture_target_android.cc @@ -5,8 +5,11 @@ #include "content/browser/renderer_host/input/synthetic_gesture_target_android.h" #include "content/browser/android/content_view_core_impl.h" +#include "content/browser/renderer_host/render_widget_host_impl.h" #include "jni/TouchEventSynthesizer_jni.h" #include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/gfx/android/view_configuration.h" +#include "ui/gfx/screen.h" using blink::WebTouchEvent; @@ -80,4 +83,10 @@ bool SyntheticGestureTargetAndroid::SupportsSyntheticGestureSourceType( return gesture_source_type == SyntheticGestureParams::TOUCH_INPUT; } +int SyntheticGestureTargetAndroid::GetTouchSlopInDips() const { + float device_scale_factor = + gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().device_scale_factor(); + return gfx::ViewConfiguration::GetTouchSlopInPixels() / device_scale_factor; +} + } // namespace content diff --git a/content/browser/renderer_host/input/synthetic_gesture_target_android.h b/content/browser/renderer_host/input/synthetic_gesture_target_android.h index d31516e98b..b8c5a5d814 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_target_android.h +++ b/content/browser/renderer_host/input/synthetic_gesture_target_android.h @@ -33,6 +33,8 @@ class SyntheticGestureTargetAndroid : public SyntheticGestureTargetBase { SyntheticGestureParams::GestureSourceType gesture_source_type) const OVERRIDE; + virtual int GetTouchSlopInDips() const OVERRIDE; + private: // Enum values below need to be kept in sync with TouchEventSynthesizer.java enum Action { diff --git a/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc b/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc index 1d5c6a8d29..9e103137ad 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc +++ b/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc @@ -11,6 +11,7 @@ #include "ui/aura/client/screen_position_client.h" #include "ui/aura/root_window.h" #include "ui/aura/window.h" +#include "ui/events/gestures/gesture_configuration.h" using blink::WebTouchEvent; using blink::WebMouseWheelEvent; @@ -70,4 +71,10 @@ bool SyntheticGestureTargetAura::SupportsSyntheticGestureSourceType( gesture_source_type == SyntheticGestureParams::MOUSE_INPUT; } +int SyntheticGestureTargetAura::GetTouchSlopInDips() const { + // - 1 because Aura considers a pointer to be moving if it has moved at least + // 'max_touch_move_in_pixels_for_click' pixels. + return ui::GestureConfiguration::max_touch_move_in_pixels_for_click() - 1; +} + } // namespace content diff --git a/content/browser/renderer_host/input/synthetic_gesture_target_aura.h b/content/browser/renderer_host/input/synthetic_gesture_target_aura.h index 69837de83a..5a4ab9cbfe 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_target_aura.h +++ b/content/browser/renderer_host/input/synthetic_gesture_target_aura.h @@ -30,6 +30,8 @@ class SyntheticGestureTargetAura : public SyntheticGestureTargetBase { SyntheticGestureParams::GestureSourceType gesture_source_type) const OVERRIDE; + virtual int GetTouchSlopInDips() const OVERRIDE; + private: DISALLOW_COPY_AND_ASSIGN(SyntheticGestureTargetAura); }; diff --git a/content/browser/renderer_host/input/synthetic_gesture_target_base.cc b/content/browser/renderer_host/input/synthetic_gesture_target_base.cc index bc6dc8f2f4..0938eebb64 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_target_base.cc +++ b/content/browser/renderer_host/input/synthetic_gesture_target_base.cc @@ -25,6 +25,11 @@ namespace { // fling on Android. const int kPointerAssumedStoppedTimeMs = 50; +// SyntheticGestureTargetBase passes input events straight on to the renderer +// without going through a gesture recognition framework. There is thus no touch +// slop. +const int kTouchSlopInDips = 0; + } // namespace SyntheticGestureTargetBase::SyntheticGestureTargetBase( @@ -110,4 +115,8 @@ base::TimeDelta SyntheticGestureTargetBase::PointerAssumedStoppedTime() return base::TimeDelta::FromMilliseconds(kPointerAssumedStoppedTimeMs); } +int SyntheticGestureTargetBase::GetTouchSlopInDips() const { + return kTouchSlopInDips; +} + } // namespace content diff --git a/content/browser/renderer_host/input/synthetic_gesture_target_base.h b/content/browser/renderer_host/input/synthetic_gesture_target_base.h index 711c0c3a55..efb8d76b57 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_target_base.h +++ b/content/browser/renderer_host/input/synthetic_gesture_target_base.h @@ -55,8 +55,10 @@ class SyntheticGestureTargetBase : public SyntheticGestureTarget { virtual base::TimeDelta PointerAssumedStoppedTime() const OVERRIDE; + virtual int GetTouchSlopInDips() const OVERRIDE; + protected: - RenderWidgetHostImpl* render_widget_host() { return host_; } + RenderWidgetHostImpl* render_widget_host() const { return host_; } private: RenderWidgetHostImpl* host_; diff --git a/content/browser/renderer_host/input/synthetic_pinch_gesture.cc b/content/browser/renderer_host/input/synthetic_pinch_gesture.cc index 7700b6d59a..dfe5cf474e 100644 --- a/content/browser/renderer_host/input/synthetic_pinch_gesture.cc +++ b/content/browser/renderer_host/input/synthetic_pinch_gesture.cc @@ -6,77 +6,92 @@ #include <cmath> +#include "base/logging.h" #include "content/common/input/input_event.h" #include "ui/events/latency_info.h" namespace content { -namespace { - -// TODO(dominikg): Use touch slop to compute this value. -const float kMinPointerDistance = 40.0f; - -} SyntheticPinchGesture::SyntheticPinchGesture( const SyntheticPinchGestureParams& params) - : params_(params), started_(false) { + : params_(params), + current_y_0_(0.0f), + current_y_1_(0.0f), + target_y_0_(0.0f), + target_y_1_(0.0f), + gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT), + state_(SETUP) { DCHECK_GE(params_.total_num_pixels_covered, 0); - - float inner_distance_to_anchor = kMinPointerDistance / 2.0f; - float outer_distance_to_anchor = - inner_distance_to_anchor + params_.total_num_pixels_covered / 2.0f; - - // Move pointers away from each other to zoom in - // or towards each other to zoom out. - if (params_.zoom_in) { - current_y_0_ = params_.anchor.y() - inner_distance_to_anchor; - current_y_1_ = params_.anchor.y() + inner_distance_to_anchor; - target_y_0_ = params_.anchor.y() - outer_distance_to_anchor; - target_y_1_ = params_.anchor.y() + outer_distance_to_anchor; - } else { - current_y_0_ = params_.anchor.y() - outer_distance_to_anchor; - current_y_1_ = params_.anchor.y() + outer_distance_to_anchor; - target_y_0_ = params_.anchor.y() - inner_distance_to_anchor; - target_y_1_ = params_.anchor.y() + inner_distance_to_anchor; - } } SyntheticPinchGesture::~SyntheticPinchGesture() {} SyntheticGesture::Result SyntheticPinchGesture::ForwardInputEvents( const base::TimeDelta& interval, SyntheticGestureTarget* target) { + if (state_ == SETUP) { + gesture_source_type_ = params_.gesture_source_type; + if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT) + gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType(); - SyntheticGestureParams::GestureSourceType source = - params_.gesture_source_type; - if (source == SyntheticGestureParams::DEFAULT_INPUT) - source = target->GetDefaultSyntheticGestureSourceType(); + if (!target->SupportsSyntheticGestureSourceType(gesture_source_type_)) + return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_SUPPORTED_BY_PLATFORM; - if (!target->SupportsSyntheticGestureSourceType(source)) - return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_SUPPORTED_BY_PLATFORM; + state_ = STARTED; + } - if (source == SyntheticGestureParams::TOUCH_INPUT) - return ForwardTouchInputEvents(interval, target); + DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT); + if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT) + ForwardTouchInputEvents(interval, target); else return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED; + + return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED + : SyntheticGesture::GESTURE_RUNNING; } -SyntheticGesture::Result SyntheticPinchGesture::ForwardTouchInputEvents( +void SyntheticPinchGesture::ForwardTouchInputEvents( const base::TimeDelta& interval, SyntheticGestureTarget* target) { - if (HasFinished()) - return SyntheticGesture::GESTURE_FINISHED; - - if (!started_) { - touch_event_.PressPoint(params_.anchor.x(), current_y_0_); - touch_event_.PressPoint(params_.anchor.x(), current_y_1_); - ForwardTouchEvent(target); - started_ = true; + switch (state_) { + case STARTED: + // Check for an early finish. + if (params_.total_num_pixels_covered == 0) { + state_ = DONE; + break; + } + SetupCoordinates(target); + PressTouchPoints(target); + state_ = MOVING; + break; + case MOVING: + UpdateTouchPoints(interval); + MoveTouchPoints(target); + if (HasReachedTarget()) { + ReleaseTouchPoints(target); + state_ = DONE; + } + break; + case SETUP: + NOTREACHED() << "State SETUP invalid for synthetic pinch."; + case DONE: + NOTREACHED() << "State DONE invalid for synthetic pinch."; } +} +void SyntheticPinchGesture::UpdateTouchPoints(base::TimeDelta interval) { // Compute the delta for the first pointer. The other one moves exactly // the same but in the opposite direction. float delta = GetDeltaForPointer0(interval); current_y_0_ += delta; current_y_1_ -= delta; +} + +void SyntheticPinchGesture::PressTouchPoints(SyntheticGestureTarget* target) { + touch_event_.PressPoint(params_.anchor.x(), current_y_0_); + touch_event_.PressPoint(params_.anchor.x(), current_y_1_); + ForwardTouchEvent(target); +} + +void SyntheticPinchGesture::MoveTouchPoints(SyntheticGestureTarget* target) { // The current pointer positions are stored as float but the pointer // coordinates of the input event are integers. Floor both positions so that // in case of an odd distance one of the pointers (the one whose position goes @@ -85,22 +100,43 @@ SyntheticGesture::Result SyntheticPinchGesture::ForwardTouchInputEvents( touch_event_.MovePoint(0, params_.anchor.x(), floor(current_y_0_)); touch_event_.MovePoint(1, params_.anchor.x(), floor(current_y_1_)); ForwardTouchEvent(target); +} - if (HasFinished()) { - touch_event_.ReleasePoint(0); - touch_event_.ReleasePoint(1); - ForwardTouchEvent(target); - return SyntheticGesture::GESTURE_FINISHED; - } - - return SyntheticGesture::GESTURE_RUNNING; +void SyntheticPinchGesture::ReleaseTouchPoints(SyntheticGestureTarget* target) { + touch_event_.ReleasePoint(0); + touch_event_.ReleasePoint(1); + ForwardTouchEvent(target); } -void SyntheticPinchGesture::ForwardTouchEvent(SyntheticGestureTarget* target) { + +void SyntheticPinchGesture::ForwardTouchEvent(SyntheticGestureTarget* target) + const { target->DispatchInputEventToPlatform( InputEvent(touch_event_, ui::LatencyInfo(), false)); } +void SyntheticPinchGesture::SetupCoordinates(SyntheticGestureTarget* target) { + const float kTouchSlopInDips = target->GetTouchSlopInDips(); + float inner_distance_to_anchor = 2 * kTouchSlopInDips; + float outer_distance_to_anchor = inner_distance_to_anchor + + params_.total_num_pixels_covered / 2.0f + + kTouchSlopInDips; + + // Move pointers away from each other to zoom in + // or towards each other to zoom out. + if (params_.zoom_in) { + current_y_0_ = params_.anchor.y() - inner_distance_to_anchor; + current_y_1_ = params_.anchor.y() + inner_distance_to_anchor; + target_y_0_ = params_.anchor.y() - outer_distance_to_anchor; + target_y_1_ = params_.anchor.y() + outer_distance_to_anchor; + } else { + current_y_0_ = params_.anchor.y() - outer_distance_to_anchor; + current_y_1_ = params_.anchor.y() + outer_distance_to_anchor; + target_y_0_ = params_.anchor.y() - inner_distance_to_anchor; + target_y_1_ = params_.anchor.y() + inner_distance_to_anchor; + } +} + float SyntheticPinchGesture::GetDeltaForPointer0( const base::TimeDelta& interval) const { float total_abs_delta = @@ -123,7 +159,7 @@ float SyntheticPinchGesture::ComputeAbsoluteRemainingDistance() const { return 2 * distance_0; } -bool SyntheticPinchGesture::HasFinished() const { +bool SyntheticPinchGesture::HasReachedTarget() const { return ComputeAbsoluteRemainingDistance() == 0; } diff --git a/content/browser/renderer_host/input/synthetic_pinch_gesture.h b/content/browser/renderer_host/input/synthetic_pinch_gesture.h index e8cdebfc6e..97405ce126 100644 --- a/content/browser/renderer_host/input/synthetic_pinch_gesture.h +++ b/content/browser/renderer_host/input/synthetic_pinch_gesture.h @@ -7,9 +7,9 @@ #include "content/browser/renderer_host/input/synthetic_gesture.h" #include "content/browser/renderer_host/input/synthetic_gesture_target.h" -#include "content/browser/renderer_host/input/synthetic_web_input_event_builders.h" #include "content/common/content_export.h" #include "content/common/input/synthetic_pinch_gesture_params.h" +#include "content/common/input/synthetic_web_input_event_builders.h" #include "third_party/WebKit/public/web/WebInputEvent.h" namespace content { @@ -23,23 +23,36 @@ class CONTENT_EXPORT SyntheticPinchGesture : public SyntheticGesture { const base::TimeDelta& interval, SyntheticGestureTarget* target) OVERRIDE; private: + enum GestureState { + SETUP, + STARTED, + MOVING, + DONE + }; + + void ForwardTouchInputEvents( + const base::TimeDelta& interval, SyntheticGestureTarget* target); + + void UpdateTouchPoints(base::TimeDelta interval); + void PressTouchPoints(SyntheticGestureTarget* target); + void MoveTouchPoints(SyntheticGestureTarget* target); + void ReleaseTouchPoints(SyntheticGestureTarget* target); + void ForwardTouchEvent(SyntheticGestureTarget* target) const; + + void SetupCoordinates(SyntheticGestureTarget* target); + float GetDeltaForPointer0(const base::TimeDelta& interval) const; + float ComputeAbsoluteRemainingDistance() const; + bool HasReachedTarget() const; + SyntheticPinchGestureParams params_; float current_y_0_; float current_y_1_; float target_y_0_; float target_y_1_; - bool started_; + SyntheticGestureParams::GestureSourceType gesture_source_type_; + GestureState state_; SyntheticWebTouchEvent touch_event_; - SyntheticGesture::Result ForwardTouchInputEvents( - const base::TimeDelta& interval, SyntheticGestureTarget* target); - - void ForwardTouchEvent(SyntheticGestureTarget* target); - - float GetDeltaForPointer0(const base::TimeDelta& interval) const; - float ComputeAbsoluteRemainingDistance() const; - bool HasFinished() const; - DISALLOW_COPY_AND_ASSIGN(SyntheticPinchGesture); }; diff --git a/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc b/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc index 84d4a1812a..b2fb4bb7eb 100644 --- a/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc +++ b/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc @@ -4,17 +4,31 @@ #include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" -#include <cmath> - +#include "base/logging.h" #include "content/common/input/input_event.h" #include "ui/events/latency_info.h" +#include "ui/gfx/point_f.h" namespace content { +namespace { + +gfx::Vector2d FloorTowardZero(const gfx::Vector2dF& vector) { + int x = vector.x() > 0 ? floor(vector.x()) : ceil(vector.x()); + int y = vector.y() > 0 ? floor(vector.y()) : ceil(vector.y()); + return gfx::Vector2d(x, y); +} + +gfx::Vector2d CeilFromZero(const gfx::Vector2dF& vector) { + int x = vector.x() > 0 ? ceil(vector.x()) : floor(vector.x()); + int y = vector.y() > 0 ? ceil(vector.y()) : floor(vector.y()); + return gfx::Vector2d(x, y); +} + +} // namespace SyntheticSmoothScrollGesture::SyntheticSmoothScrollGesture( const SyntheticSmoothScrollGestureParams& params) : params_(params), - current_y_(params_.anchor.y()), gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT), state_(SETUP) {} @@ -50,30 +64,34 @@ void SyntheticSmoothScrollGesture::ForwardTouchInputEvents( switch (state_) { case STARTED: // Check for an early finish. - if (HasScrolledEntireDistance()) { + if (params_.distance.IsZero()) { state_ = DONE; break; } - touch_event_.PressPoint(params_.anchor.x(), current_y_); - ForwardTouchEvent(target); + AddTouchSlopToDistance(target); + PressTouchPoint(target); state_ = MOVING; break; case MOVING: - current_y_ += GetPositionDelta(interval); - touch_event_.MovePoint(0, params_.anchor.x(), current_y_); - ForwardTouchEvent(target); + total_delta_ += GetPositionDelta(interval); + MoveTouchPoint(target); - if (HasScrolledEntireDistance()) - state_ = STOPPING; + if (HasScrolledEntireDistance()) { + if (params_.prevent_fling) { + state_ = STOPPING; + } else { + ReleaseTouchPoint(target); + state_ = DONE; + } + } break; case STOPPING: total_stopping_wait_time_ += interval; if (total_stopping_wait_time_ >= target->PointerAssumedStoppedTime()) { // Send one last move event, but don't change the location. Without this // we'd still sometimes cause a fling on Android. - ForwardTouchEvent(target); - touch_event_.ReleasePoint(0); - ForwardTouchEvent(target); + MoveTouchPoint(target); + ReleaseTouchPoint(target); state_ = DONE; } break; @@ -91,7 +109,7 @@ void SyntheticSmoothScrollGesture::ForwardMouseInputEvents( switch (state_) { case STARTED: // Check for an early finish. - if (HasScrolledEntireDistance()) { + if (params_.distance.IsZero()) { state_ = DONE; break; } @@ -99,9 +117,16 @@ void SyntheticSmoothScrollGesture::ForwardMouseInputEvents( // Fall through to forward the first event. case MOVING: { - const float delta = floor(GetPositionDelta(interval)); - current_y_ += delta; - ForwardMouseWheelEvent(target, delta); + // Even though WebMouseWheelEvents take floating point deltas, + // internally the scroll position is stored as an integer. We therefore + // keep track of the discrete delta which is consistent with the + // internal scrolling state. This ensures that when the gesture has + // finished we've scrolled exactly the specified distance. + total_delta_ += GetPositionDelta(interval); + gfx::Vector2d delta_discrete = + FloorTowardZero(total_delta_ - total_delta_discrete_); + ForwardMouseWheelEvent(target, delta_discrete); + total_delta_discrete_ += delta_discrete; } if (HasScrolledEntireDistance()) state_ = DONE; @@ -125,9 +150,9 @@ void SyntheticSmoothScrollGesture::ForwardTouchEvent( } void SyntheticSmoothScrollGesture::ForwardMouseWheelEvent( - SyntheticGestureTarget* target, float delta) const { + SyntheticGestureTarget* target, const gfx::Vector2dF& delta) const { blink::WebMouseWheelEvent mouse_wheel_event = - SyntheticWebMouseWheelEventBuilder::Build(0, delta, 0, false); + SyntheticWebMouseWheelEventBuilder::Build(delta.x(), delta.y(), 0, false); mouse_wheel_event.x = params_.anchor.x(); mouse_wheel_event.y = params_.anchor.y(); @@ -136,30 +161,63 @@ void SyntheticSmoothScrollGesture::ForwardMouseWheelEvent( InputEvent(mouse_wheel_event, ui::LatencyInfo(), false)); } -float SyntheticSmoothScrollGesture::GetPositionDelta( +void SyntheticSmoothScrollGesture::PressTouchPoint( + SyntheticGestureTarget* target) { + touch_event_.PressPoint(params_.anchor.x(), params_.anchor.y()); + ForwardTouchEvent(target); +} + +void SyntheticSmoothScrollGesture::MoveTouchPoint( + SyntheticGestureTarget* target) { + gfx::PointF touch_position = params_.anchor + total_delta_; + touch_event_.MovePoint(0, touch_position.x(), touch_position.y()); + ForwardTouchEvent(target); +} + +void SyntheticSmoothScrollGesture::ReleaseTouchPoint( + SyntheticGestureTarget* target) { + touch_event_.ReleasePoint(0); + ForwardTouchEvent(target); +} + +void SyntheticSmoothScrollGesture::AddTouchSlopToDistance( + SyntheticGestureTarget* target) { + // Android uses euclidean distance to compute if a touch pointer has moved + // beyond the slop, while Aura uses Manhattan distance. We're using Euclidean + // distance and round up to the nearest integer. + // For vertical and horizontal scrolls (the common case), both methods produce + // the same result. + gfx::Vector2dF touch_slop_delta = ProjectLengthOntoScrollDirection( + target->GetTouchSlopInDips()); + params_.distance += CeilFromZero(touch_slop_delta); +} + +gfx::Vector2dF SyntheticSmoothScrollGesture::GetPositionDelta( const base::TimeDelta& interval) const { - float abs_delta = params_.speed_in_pixels_s * interval.InSecondsF(); + float delta_length = params_.speed_in_pixels_s * interval.InSecondsF(); // Make sure we're not scrolling too far. - abs_delta = std::min(abs_delta, ComputeAbsoluteRemainingDistance()); + gfx::Vector2dF remaining_delta = ComputeRemainingDelta(); + if (delta_length > remaining_delta.Length()) + // In order to scroll in a certain direction we need to move the + // touch pointer/mouse wheel in the opposite direction. + return -remaining_delta; + else + return -ProjectLengthOntoScrollDirection(delta_length); +} - // A positive distance indicates scrolling down, which means the touch pointer - // moves up or the scroll wheel moves down. In either case, the delta is - // negative when scrolling down and positive when scrolling up. - return params_.distance > 0 ? -abs_delta : abs_delta; +gfx::Vector2dF SyntheticSmoothScrollGesture::ProjectLengthOntoScrollDirection( + float delta_length) const { + const float kTotalLength = params_.distance.Length(); + return ScaleVector2d(params_.distance, delta_length / kTotalLength); } -float SyntheticSmoothScrollGesture::ComputeAbsoluteRemainingDistance() const { - float remaining_distance = - params_.distance - (params_.anchor.y() - current_y_); - float abs_remaining_distance = - params_.distance > 0 ? remaining_distance : -remaining_distance; - DCHECK_GE(abs_remaining_distance, 0); - return abs_remaining_distance; +gfx::Vector2dF SyntheticSmoothScrollGesture::ComputeRemainingDelta() const { + return params_.distance + total_delta_; } bool SyntheticSmoothScrollGesture::HasScrolledEntireDistance() const { - return ComputeAbsoluteRemainingDistance() == 0; + return ComputeRemainingDelta().IsZero(); } } // namespace content diff --git a/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h b/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h index 10428b16e1..53b4da5468 100644 --- a/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h +++ b/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h @@ -8,10 +8,12 @@ #include "base/time/time.h" #include "content/browser/renderer_host/input/synthetic_gesture.h" #include "content/browser/renderer_host/input/synthetic_gesture_target.h" -#include "content/browser/renderer_host/input/synthetic_web_input_event_builders.h" #include "content/common/content_export.h" #include "content/common/input/synthetic_smooth_scroll_gesture_params.h" +#include "content/common/input/synthetic_web_input_event_builders.h" #include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/gfx/vector2d.h" +#include "ui/gfx/vector2d_f.h" namespace content { @@ -32,12 +34,6 @@ class CONTENT_EXPORT SyntheticSmoothScrollGesture : public SyntheticGesture { STOPPING, DONE }; - SyntheticSmoothScrollGestureParams params_; - float current_y_; - SyntheticWebTouchEvent touch_event_; - SyntheticGestureParams::GestureSourceType gesture_source_type_; - GestureState state_; - base::TimeDelta total_stopping_wait_time_; void ForwardTouchInputEvents( const base::TimeDelta& interval, SyntheticGestureTarget* target); @@ -46,12 +42,26 @@ class CONTENT_EXPORT SyntheticSmoothScrollGesture : public SyntheticGesture { void ForwardTouchEvent(SyntheticGestureTarget* target) const; void ForwardMouseWheelEvent(SyntheticGestureTarget* target, - float delta) const; + const gfx::Vector2dF& delta) const; + + void PressTouchPoint(SyntheticGestureTarget* target); + void MoveTouchPoint(SyntheticGestureTarget* target); + void ReleaseTouchPoint(SyntheticGestureTarget* target); - float GetPositionDelta(const base::TimeDelta& interval) const; - float ComputeAbsoluteRemainingDistance() const; + void AddTouchSlopToDistance(SyntheticGestureTarget* target); + gfx::Vector2dF GetPositionDelta(const base::TimeDelta& interval) const; + gfx::Vector2dF ProjectLengthOntoScrollDirection(float delta_length) const; + gfx::Vector2dF ComputeRemainingDelta() const; bool HasScrolledEntireDistance() const; + SyntheticSmoothScrollGestureParams params_; + gfx::Vector2dF total_delta_; + gfx::Vector2d total_delta_discrete_; + SyntheticWebTouchEvent touch_event_; + SyntheticGestureParams::GestureSourceType gesture_source_type_; + GestureState state_; + base::TimeDelta total_stopping_wait_time_; + DISALLOW_COPY_AND_ASSIGN(SyntheticSmoothScrollGesture); }; diff --git a/content/browser/renderer_host/input/synthetic_tap_gesture.cc b/content/browser/renderer_host/input/synthetic_tap_gesture.cc new file mode 100644 index 0000000000..1f15d82f01 --- /dev/null +++ b/content/browser/renderer_host/input/synthetic_tap_gesture.cc @@ -0,0 +1,119 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/input/synthetic_tap_gesture.h" + +#include "base/logging.h" +#include "content/common/input/input_event.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/events/latency_info.h" + +namespace content { +namespace { + +void DispatchEventToPlatform(SyntheticGestureTarget* target, + const blink::WebInputEvent& event) { + target->DispatchInputEventToPlatform( + InputEvent(event, ui::LatencyInfo(), false)); +} + +} // namespace + +SyntheticTapGesture::SyntheticTapGesture( + const SyntheticTapGestureParams& params) + : params_(params), + gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT), + state_(SETUP) { + DCHECK_GE(params_.duration_ms, 0); +} + +SyntheticTapGesture::~SyntheticTapGesture() {} + +SyntheticGesture::Result SyntheticTapGesture::ForwardInputEvents( + const base::TimeDelta& interval, SyntheticGestureTarget* target) { + if (state_ == SETUP) { + gesture_source_type_ = params_.gesture_source_type; + if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT) + gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType(); + + if (!target->SupportsSyntheticGestureSourceType(gesture_source_type_)) + return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_SUPPORTED_BY_PLATFORM; + + state_ = PRESS; + } + + DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT); + if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT || + gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT) + ForwardTouchOrMouseInputEvents(interval, target); + else + return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED; + + return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED + : SyntheticGesture::GESTURE_RUNNING; +} + +void SyntheticTapGesture::ForwardTouchOrMouseInputEvents( + const base::TimeDelta& interval, SyntheticGestureTarget* target) { + switch (state_) { + case PRESS: + Press(target); + // Release immediately if duration is 0. + if (params_.duration_ms == 0) { + Release(target); + state_ = DONE; + } else { + state_ = WAITING_TO_RELEASE; + } + break; + case WAITING_TO_RELEASE: + total_waiting_time_ += interval; + if (total_waiting_time_ >= + base::TimeDelta::FromMilliseconds(params_.duration_ms)) { + Release(target); + state_ = DONE; + } + break; + case SETUP: + NOTREACHED() << "State SETUP invalid for synthetic tap gesture."; + case DONE: + NOTREACHED() << "State DONE invalid for synthetic tap gesture."; + } +} + +void SyntheticTapGesture::Press(SyntheticGestureTarget* target) { + if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT) { + touch_event_.PressPoint(params_.position.x(), params_.position.y()); + DispatchEventToPlatform(target, touch_event_); + } else if (gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT) { + blink::WebMouseEvent mouse_event = + SyntheticWebMouseEventBuilder::Build(blink::WebInputEvent::MouseDown, + params_.position.x(), + params_.position.y(), + 0); + mouse_event.clickCount = 1; + DispatchEventToPlatform(target, mouse_event); + } else { + NOTREACHED() << "Invalid gesture source type for synthetic tap gesture."; + } +} + +void SyntheticTapGesture::Release(SyntheticGestureTarget* target) { + if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT) { + touch_event_.ReleasePoint(0); + DispatchEventToPlatform(target, touch_event_); + } else if (gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT) { + blink::WebMouseEvent mouse_event = + SyntheticWebMouseEventBuilder::Build(blink::WebInputEvent::MouseUp, + params_.position.x(), + params_.position.y(), + 0); + mouse_event.clickCount = 1; + DispatchEventToPlatform(target, mouse_event); + } else { + NOTREACHED() << "Invalid gesture source type for synthetic tap gesture."; + } +} + +} // namespace content diff --git a/content/browser/renderer_host/input/synthetic_tap_gesture.h b/content/browser/renderer_host/input/synthetic_tap_gesture.h new file mode 100644 index 0000000000..22217f9909 --- /dev/null +++ b/content/browser/renderer_host/input/synthetic_tap_gesture.h @@ -0,0 +1,49 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TAP_GESTURE_H_ +#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TAP_GESTURE_H_ + +#include "content/browser/renderer_host/input/synthetic_gesture.h" +#include "content/browser/renderer_host/input/synthetic_gesture_target.h" +#include "content/common/content_export.h" +#include "content/common/input/synthetic_tap_gesture_params.h" +#include "content/common/input/synthetic_web_input_event_builders.h" + +namespace content { + +class CONTENT_EXPORT SyntheticTapGesture : public SyntheticGesture { + public: + explicit SyntheticTapGesture(const SyntheticTapGestureParams& params); + virtual ~SyntheticTapGesture(); + + virtual SyntheticGesture::Result ForwardInputEvents( + const base::TimeDelta& interval, SyntheticGestureTarget* target) OVERRIDE; + + private: + enum GestureState { + SETUP, + PRESS, + WAITING_TO_RELEASE, + DONE + }; + + void ForwardTouchOrMouseInputEvents(const base::TimeDelta& interval, + SyntheticGestureTarget* target); + + void Press(SyntheticGestureTarget* target); + void Release(SyntheticGestureTarget* target); + + SyntheticTapGestureParams params_; + base::TimeDelta total_waiting_time_; + SyntheticWebTouchEvent touch_event_; + SyntheticGestureParams::GestureSourceType gesture_source_type_; + GestureState state_; + + DISALLOW_COPY_AND_ASSIGN(SyntheticTapGesture); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_TAP_GESTURE_H_ diff --git a/content/browser/renderer_host/input/synthetic_web_input_event_builders.cc b/content/browser/renderer_host/input/synthetic_web_input_event_builders.cc deleted file mode 100644 index 09f38dc569..0000000000 --- a/content/browser/renderer_host/input/synthetic_web_input_event_builders.cc +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/renderer_host/input/synthetic_web_input_event_builders.h" - -#include "base/logging.h" -#include "content/browser/renderer_host/input/web_input_event_util.h" -#include "ui/events/keycodes/keyboard_codes.h" - -namespace content { - -using blink::WebInputEvent; -using blink::WebKeyboardEvent; -using blink::WebGestureEvent; -using blink::WebMouseEvent; -using blink::WebMouseWheelEvent; -using blink::WebTouchEvent; -using blink::WebTouchPoint; - -WebMouseEvent SyntheticWebMouseEventBuilder::Build( - blink::WebInputEvent::Type type) { - WebMouseEvent result; - result.type = type; - return result; -} - -WebMouseEvent SyntheticWebMouseEventBuilder::Build( - blink::WebInputEvent::Type type, - int window_x, - int window_y, - int modifiers) { - DCHECK(WebInputEvent::isMouseEventType(type)); - WebMouseEvent result = Build(type); - result.x = window_x; - result.y = window_y; - result.windowX = window_x; - result.windowY = window_y; - result.modifiers = modifiers; - - if (type == WebInputEvent::MouseDown || type == WebInputEvent::MouseUp) - result.button = WebMouseEvent::ButtonLeft; - else - result.button = WebMouseEvent::ButtonNone; - - return result; -} - -WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build( - WebMouseWheelEvent::Phase phase) { - WebMouseWheelEvent result; - result.type = WebInputEvent::MouseWheel; - result.phase = phase; - return result; -} - -WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build(float dx, - float dy, - int modifiers, - bool precise) { - WebMouseWheelEvent result; - result.type = WebInputEvent::MouseWheel; - result.deltaX = dx; - result.deltaY = dy; - result.modifiers = modifiers; - result.hasPreciseScrollingDeltas = precise; - return result; -} - -NativeWebKeyboardEvent SyntheticWebKeyboardEventBuilder::Build( - WebInputEvent::Type type) { - DCHECK(WebInputEvent::isKeyboardEventType(type)); - NativeWebKeyboardEvent result; - result.type = type; - result.windowsKeyCode = ui::VKEY_L; // non-null made up value. - return result; -} - -WebGestureEvent SyntheticWebGestureEventBuilder::Build( - WebInputEvent::Type type, - WebGestureEvent::SourceDevice source_device) { - DCHECK(WebInputEvent::isGestureEventType(type)); - WebGestureEvent result; - result.type = type; - result.sourceDevice = source_device; - return result; -} - -WebGestureEvent SyntheticWebGestureEventBuilder::BuildScrollUpdate( - float dx, - float dy, - int modifiers) { - WebGestureEvent result = Build(WebInputEvent::GestureScrollUpdate, - WebGestureEvent::Touchscreen); - result.data.scrollUpdate.deltaX = dx; - result.data.scrollUpdate.deltaY = dy; - result.modifiers = modifiers; - return result; -} - -WebGestureEvent SyntheticWebGestureEventBuilder::BuildPinchUpdate( - float scale, - float anchor_x, - float anchor_y, - int modifiers) { - WebGestureEvent result = Build(WebInputEvent::GesturePinchUpdate, - WebGestureEvent::Touchscreen); - result.data.pinchUpdate.scale = scale; - result.x = anchor_x; - result.y = anchor_y; - result.modifiers = modifiers; - return result; -} - -WebGestureEvent SyntheticWebGestureEventBuilder::BuildFling( - float velocity_x, - float velocity_y, - WebGestureEvent::SourceDevice source_device) { - WebGestureEvent result = Build(WebInputEvent::GestureFlingStart, - source_device); - result.data.flingStart.velocityX = velocity_x; - result.data.flingStart.velocityY = velocity_y; - return result; -} - -SyntheticWebTouchEvent::SyntheticWebTouchEvent() : WebTouchEvent() {} - -void SyntheticWebTouchEvent::ResetPoints() { - int point = 0; - for (unsigned int i = 0; i < touchesLength; ++i) { - if (touches[i].state == WebTouchPoint::StateReleased) - continue; - - touches[point] = touches[i]; - touches[point].state = WebTouchPoint::StateStationary; - ++point; - } - touchesLength = point; - type = WebInputEvent::Undefined; -} - -int SyntheticWebTouchEvent::PressPoint(int x, int y) { - if (touchesLength == touchesLengthCap) - return -1; - WebTouchPoint& point = touches[touchesLength]; - point.id = touchesLength; - point.position.x = point.screenPosition.x = x; - point.position.y = point.screenPosition.y = y; - point.state = WebTouchPoint::StatePressed; - point.radiusX = point.radiusY = 1.f; - ++touchesLength; - type = WebInputEvent::TouchStart; - return point.id; -} - -void SyntheticWebTouchEvent::MovePoint(int index, int x, int y) { - CHECK(index >= 0 && index < touchesLengthCap); - WebTouchPoint& point = touches[index]; - point.position.x = point.screenPosition.x = x; - point.position.y = point.screenPosition.y = y; - touches[index].state = WebTouchPoint::StateMoved; - type = WebInputEvent::TouchMove; -} - -void SyntheticWebTouchEvent::ReleasePoint(int index) { - CHECK(index >= 0 && index < touchesLengthCap); - touches[index].state = WebTouchPoint::StateReleased; - type = WebInputEvent::TouchEnd; -} - -void SyntheticWebTouchEvent::CancelPoint(int index) { - CHECK(index >= 0 && index < touchesLengthCap); - touches[index].state = WebTouchPoint::StateCancelled; - type = WebInputEvent::TouchCancel; -} - -void SyntheticWebTouchEvent::SetTimestamp(base::TimeDelta timestamp) { - timeStampSeconds = timestamp.InSecondsF(); -} - -SyntheticWebTouchEvent SyntheticWebTouchEventBuilder::Build( - WebInputEvent::Type type) { - DCHECK(WebInputEvent::isTouchEventType(type)); - SyntheticWebTouchEvent result; - result.type = type; - return result; -}; - -} // namespace content diff --git a/content/browser/renderer_host/input/synthetic_web_input_event_builders.h b/content/browser/renderer_host/input/synthetic_web_input_event_builders.h deleted file mode 100644 index 754f42df5f..0000000000 --- a/content/browser/renderer_host/input/synthetic_web_input_event_builders.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_WEB_INPUT_EVENT_BUILDERS_H_ -#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_WEB_INPUT_EVENT_BUILDERS_H_ - -#include "base/time/time.h" -#include "content/common/content_export.h" -#include "content/public/browser/native_web_keyboard_event.h" -#include "third_party/WebKit/public/web/WebInputEvent.h" - -// Provides sensible creation of default WebInputEvents for testing purposes. - -namespace content { - -class CONTENT_EXPORT SyntheticWebMouseEventBuilder { - public: - static blink::WebMouseEvent Build(blink::WebInputEvent::Type type); - static blink::WebMouseEvent Build(blink::WebInputEvent::Type type, - int window_x, - int window_y, - int modifiers); -}; - -class CONTENT_EXPORT SyntheticWebMouseWheelEventBuilder { - public: - static blink::WebMouseWheelEvent Build( - blink::WebMouseWheelEvent::Phase phase); - static blink::WebMouseWheelEvent Build(float dx, - float dy, - int modifiers, - bool precise); -}; - -class CONTENT_EXPORT SyntheticWebKeyboardEventBuilder { - public: - static NativeWebKeyboardEvent Build(blink::WebInputEvent::Type type); -}; - -class CONTENT_EXPORT SyntheticWebGestureEventBuilder { - public: - static blink::WebGestureEvent Build( - blink::WebInputEvent::Type type, - blink::WebGestureEvent::SourceDevice sourceDevice); - static blink::WebGestureEvent BuildScrollUpdate(float dx, - float dY, - int modifiers); - static blink::WebGestureEvent BuildPinchUpdate(float scale, - float anchor_x, - float anchor_y, - int modifiers); - static blink::WebGestureEvent BuildFling( - float velocity_x, - float velocity_y, - blink::WebGestureEvent::SourceDevice source_device); -}; - -class CONTENT_EXPORT SyntheticWebTouchEvent - : public NON_EXPORTED_BASE(blink::WebTouchEvent) { - public: - SyntheticWebTouchEvent(); - - // Mark all the points as stationary, and remove any released points. - void ResetPoints(); - - // Adds an additional point to the touch list, returning the point's index. - int PressPoint(int x, int y); - void MovePoint(int index, int x, int y); - void ReleasePoint(int index); - void CancelPoint(int index); - - void SetTimestamp(base::TimeDelta timestamp); -}; - -class CONTENT_EXPORT SyntheticWebTouchEventBuilder { - public: - static SyntheticWebTouchEvent Build(blink::WebInputEvent::Type type); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_WEB_INPUT_EVENT_BUILDERS_H_ diff --git a/content/browser/renderer_host/input/timeout_monitor.cc b/content/browser/renderer_host/input/timeout_monitor.cc new file mode 100644 index 0000000000..93b310286b --- /dev/null +++ b/content/browser/renderer_host/input/timeout_monitor.cc @@ -0,0 +1,78 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/input/timeout_monitor.h" + +using base::Time; +using base::TimeDelta; + +namespace content { + +TimeoutMonitor::TimeoutMonitor(const TimeoutHandler& timeout_handler) + : timeout_handler_(timeout_handler) { + DCHECK(!timeout_handler_.is_null()); +} + +TimeoutMonitor::~TimeoutMonitor() {} + +void TimeoutMonitor::Start(TimeDelta delay) { + // Set time_when_considered_timed_out_ if it's null. Also, update + // time_when_considered_timed_out_ if the caller's request is sooner than the + // existing one. This will have the side effect that the existing timeout will + // be forgotten. + Time requested_end_time = Time::Now() + delay; + if (time_when_considered_timed_out_.is_null() || + time_when_considered_timed_out_ > requested_end_time) + time_when_considered_timed_out_ = requested_end_time; + + // If we already have a timer with the same or shorter duration, then we can + // wait for it to finish. + if (timeout_timer_.IsRunning() && timeout_timer_.GetCurrentDelay() <= delay) { + // If time_when_considered_timed_out_ was null, this timer may fire early. + // CheckTimedOut handles that that by calling Start with the remaining time. + // If time_when_considered_timed_out_ was non-null, it means we still + // haven't been stopped, so we leave time_when_considered_timed_out_ as is. + return; + } + + // Either the timer is not yet running, or we need to adjust the timer to + // fire sooner. + time_when_considered_timed_out_ = requested_end_time; + timeout_timer_.Stop(); + timeout_timer_.Start(FROM_HERE, delay, this, &TimeoutMonitor::CheckTimedOut); +} + +void TimeoutMonitor::Restart(TimeDelta delay) { + // Setting to null will cause StartTimeoutMonitor to restart the timer. + time_when_considered_timed_out_ = Time(); + Start(delay); +} + +void TimeoutMonitor::Stop() { + // We do not bother to stop the timeout_timer_ here in case it will be + // started again shortly, which happens to be the common use case. + time_when_considered_timed_out_ = Time(); +} + +void TimeoutMonitor::CheckTimedOut() { + // If we received a call to |Stop()|. + if (time_when_considered_timed_out_.is_null()) + return; + + // If we have not waited long enough, then wait some more. + Time now = Time::Now(); + if (now < time_when_considered_timed_out_) { + Start(time_when_considered_timed_out_ - now); + return; + } + + timeout_handler_.Run(); +} + +bool TimeoutMonitor::IsRunning() const { + return timeout_timer_.IsRunning() && + !time_when_considered_timed_out_.is_null(); +} + +} // namespace content diff --git a/content/browser/renderer_host/input/timeout_monitor.h b/content/browser/renderer_host/input/timeout_monitor.h new file mode 100644 index 0000000000..88154e86e7 --- /dev/null +++ b/content/browser/renderer_host/input/timeout_monitor.h @@ -0,0 +1,50 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_TIMEOUT_MONITOR_H_ +#define CONTENT_BROWSER_RENDERER_HOST_INPUT_TIMEOUT_MONITOR_H_ + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/time/time.h" +#include "base/timer/timer.h" +#include "content/common/content_export.h" + +namespace content { + +// Utility class for handling a timeout callback with periodic starts and stops. +class CONTENT_EXPORT TimeoutMonitor { + public: + typedef base::Closure TimeoutHandler; + + explicit TimeoutMonitor(const TimeoutHandler& timeout_handler); + ~TimeoutMonitor(); + + // Schedule the timeout timer to fire at |delay| into the future. If a timeout + // has already been scheduled, reschedule only if |delay| is sooner than the + // currently scheduled timeout time. + void Start(base::TimeDelta delay); + + void Restart(base::TimeDelta delay); + void Stop(); + bool IsRunning() const; + + private: + void CheckTimedOut(); + + TimeoutHandler timeout_handler_; + + // Indicates a time in the future when we would consider the input as + // having timed out, if it does not receive an appropriate stop request. + base::Time time_when_considered_timed_out_; + + // This timer runs to check if |time_when_considered_timed_out_| has past. + base::OneShotTimer<TimeoutMonitor> timeout_timer_; + + DISALLOW_COPY_AND_ASSIGN(TimeoutMonitor); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_TIMEOUT_MONITOR_H_ diff --git a/content/browser/renderer_host/input/touch_action_filter.cc b/content/browser/renderer_host/input/touch_action_filter.cc new file mode 100644 index 0000000000..665ff15bd3 --- /dev/null +++ b/content/browser/renderer_host/input/touch_action_filter.cc @@ -0,0 +1,63 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/input/touch_action_filter.h" + +#include "third_party/WebKit/public/web/WebInputEvent.h" + +using blink::WebInputEvent; +using blink::WebGestureEvent; + +namespace content { + +TouchActionFilter::TouchActionFilter() : + drop_scroll_gesture_events_(false), + allowed_touch_action_(TOUCH_ACTION_AUTO) { +} + +bool TouchActionFilter::FilterGestureEvent( + const WebGestureEvent& gesture_event) { + // Filter for allowable touch actions first (eg. before the TouchEventQueue + // can decide to send a touch cancel event). + // TODO(rbyers): Add touch-action control over for pinch. crbug.com/247566. + switch(gesture_event.type) { + case WebInputEvent::GestureScrollBegin: + if (allowed_touch_action_ == TOUCH_ACTION_NONE) + drop_scroll_gesture_events_ = true; + // FALL THROUGH + case WebInputEvent::GestureScrollUpdate: + if (drop_scroll_gesture_events_) + return true; + break; + + case WebInputEvent::GestureScrollEnd: + case WebInputEvent::GestureFlingStart: + allowed_touch_action_ = content::TOUCH_ACTION_AUTO; + if (drop_scroll_gesture_events_) { + drop_scroll_gesture_events_ = false; + return true; + } + break; + + default: + // Gesture events unrelated to touch actions (panning/zooming) are left + // alone. + break; + } + + return false; +} + +void TouchActionFilter::OnSetTouchAction( + content::TouchAction touch_action) { + // For multiple fingers, we take the intersection of the touch actions for + // all fingers that have gone down during this action. + // TODO(rbyers): What exact multi-finger semantic do we want? This is left + // as implementation-defined in the pointer events specification. + // crbug.com/247566. + if (touch_action == content::TOUCH_ACTION_NONE) + allowed_touch_action_ = content::TOUCH_ACTION_NONE; +} + +} diff --git a/content/browser/renderer_host/input/touch_action_filter.h b/content/browser/renderer_host/input/touch_action_filter.h new file mode 100644 index 0000000000..6485c45a93 --- /dev/null +++ b/content/browser/renderer_host/input/touch_action_filter.h @@ -0,0 +1,45 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_ACTION_FILTER_H_ +#define CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_ACTION_FILTER_H_ + +#include "base/basictypes.h" +#include "content/common/content_export.h" +#include "content/common/input/touch_action.h" + +namespace blink { +class WebGestureEvent; +} + +namespace content { + +// The TouchActionFilter is responsible for filtering scroll and pinch gesture +// events according to the CSS touch-action values the renderer has sent for +// each touch point. +// For details see the touch-action design doc at http://goo.gl/KcKbxQ. +class CONTENT_EXPORT TouchActionFilter { +public: + TouchActionFilter(); + + // Returns true if the supplied gesture event should be dropped based on + // the current touch-action state. + bool FilterGestureEvent(const blink::WebGestureEvent& gesture_event); + + // Called when a set-touch-action message is received from the renderer + // for a touch start event that is currently in flight. + void OnSetTouchAction(content::TouchAction touch_action); + +private: + // Whether GestureScroll events should be discarded due to touch-action. + bool drop_scroll_gesture_events_; + + // What touch actions are currently permitted. + content::TouchAction allowed_touch_action_; + + DISALLOW_COPY_AND_ASSIGN(TouchActionFilter); +}; + +} +#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_ACTION_FILTER_H_ diff --git a/content/browser/renderer_host/input/touch_action_filter_unittest.cc b/content/browser/renderer_host/input/touch_action_filter_unittest.cc new file mode 100644 index 0000000000..a07ef09dfb --- /dev/null +++ b/content/browser/renderer_host/input/touch_action_filter_unittest.cc @@ -0,0 +1,100 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/input/touch_action_filter.h" +#include "content/common/input/synthetic_web_input_event_builders.h" +#include "content/port/browser/event_with_latency_info.h" +#include "content/port/common/input_event_ack_state.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" + +using blink::WebGestureEvent; +using blink::WebInputEvent; + +namespace content { + +TEST(TouchActionFilterTest, SimpleFilter) { + TouchActionFilter filter; + + const WebGestureEvent scroll_begin = SyntheticWebGestureEventBuilder::Build( + WebInputEvent::GestureScrollBegin, WebGestureEvent::Touchscreen); + const WebGestureEvent scroll_update = + SyntheticWebGestureEventBuilder::BuildScrollUpdate(0, 10, 0); + const WebGestureEvent scroll_end = SyntheticWebGestureEventBuilder::Build( + WebInputEvent::GestureScrollEnd, WebGestureEvent::Touchscreen); + const WebGestureEvent tap = SyntheticWebGestureEventBuilder::Build( + WebInputEvent::GestureTap, WebGestureEvent::Touchscreen); + + // No events filtered by default. + EXPECT_FALSE(filter.FilterGestureEvent(scroll_begin)); + EXPECT_FALSE(filter.FilterGestureEvent(scroll_update)); + EXPECT_FALSE(filter.FilterGestureEvent(scroll_end)); + EXPECT_FALSE(filter.FilterGestureEvent(tap)); + + // TOUCH_ACTION_AUTO doesn't cause any filtering. + filter.OnSetTouchAction(TOUCH_ACTION_AUTO); + EXPECT_FALSE(filter.FilterGestureEvent(scroll_begin)); + EXPECT_FALSE(filter.FilterGestureEvent(scroll_update)); + EXPECT_FALSE(filter.FilterGestureEvent(scroll_end)); + + // TOUCH_ACTION_NONE filters out all scroll events, but no other events. + filter.OnSetTouchAction(TOUCH_ACTION_NONE); + EXPECT_FALSE(filter.FilterGestureEvent(tap)); + EXPECT_TRUE(filter.FilterGestureEvent(scroll_begin)); + EXPECT_TRUE(filter.FilterGestureEvent(scroll_update)); + EXPECT_TRUE(filter.FilterGestureEvent(scroll_update)); + EXPECT_TRUE(filter.FilterGestureEvent(scroll_end)); + + // After the end of a gesture the state is reset. + EXPECT_FALSE(filter.FilterGestureEvent(scroll_begin)); + EXPECT_FALSE(filter.FilterGestureEvent(scroll_update)); + EXPECT_FALSE(filter.FilterGestureEvent(scroll_end)); + + // Setting touch action doesn't impact any in-progress gestures. + EXPECT_FALSE(filter.FilterGestureEvent(scroll_begin)); + filter.OnSetTouchAction(TOUCH_ACTION_NONE); + EXPECT_FALSE(filter.FilterGestureEvent(scroll_update)); + EXPECT_FALSE(filter.FilterGestureEvent(scroll_end)); + + // And the state is still cleared for the next gesture. + EXPECT_FALSE(filter.FilterGestureEvent(scroll_begin)); + EXPECT_FALSE(filter.FilterGestureEvent(scroll_end)); + + // Changing the touch action during a gesture has no effect. + filter.OnSetTouchAction(TOUCH_ACTION_NONE); + EXPECT_TRUE(filter.FilterGestureEvent(scroll_begin)); + filter.OnSetTouchAction(TOUCH_ACTION_AUTO); + EXPECT_TRUE(filter.FilterGestureEvent(scroll_update)); + EXPECT_TRUE(filter.FilterGestureEvent(scroll_update)); + EXPECT_TRUE(filter.FilterGestureEvent(scroll_end)); +} + +TEST(TouchActionFilterTest, MultiTouch) { + TouchActionFilter filter; + + const WebGestureEvent scroll_begin = SyntheticWebGestureEventBuilder::Build( + WebInputEvent::GestureScrollBegin, WebGestureEvent::Touchscreen); + const WebGestureEvent scroll_update = + SyntheticWebGestureEventBuilder::BuildScrollUpdate(0, 10, 0); + const WebGestureEvent scrollEnd = SyntheticWebGestureEventBuilder::Build( + WebInputEvent::GestureScrollEnd, WebGestureEvent::Touchscreen); + + // For multiple points, the intersection is what matters. + filter.OnSetTouchAction(TOUCH_ACTION_NONE); + filter.OnSetTouchAction(TOUCH_ACTION_AUTO); + EXPECT_TRUE(filter.FilterGestureEvent(scroll_begin)); + EXPECT_TRUE(filter.FilterGestureEvent(scroll_update)); + EXPECT_TRUE(filter.FilterGestureEvent(scroll_update)); + EXPECT_TRUE(filter.FilterGestureEvent(scrollEnd)); + + filter.OnSetTouchAction(TOUCH_ACTION_AUTO); + filter.OnSetTouchAction(TOUCH_ACTION_NONE); + filter.OnSetTouchAction(TOUCH_ACTION_AUTO); + EXPECT_TRUE(filter.FilterGestureEvent(scroll_begin)); + EXPECT_TRUE(filter.FilterGestureEvent(scroll_update)); + EXPECT_TRUE(filter.FilterGestureEvent(scroll_update)); + EXPECT_TRUE(filter.FilterGestureEvent(scrollEnd)); +} + +} // namespace content diff --git a/content/browser/renderer_host/input/touch_event_queue.cc b/content/browser/renderer_host/input/touch_event_queue.cc index ecc1205672..3524b18250 100644 --- a/content/browser/renderer_host/input/touch_event_queue.cc +++ b/content/browser/renderer_host/input/touch_event_queue.cc @@ -5,13 +5,165 @@ #include "content/browser/renderer_host/input/touch_event_queue.h" #include "base/auto_reset.h" +#include "base/command_line.h" #include "base/debug/trace_event.h" #include "base/stl_util.h" +#include "content/browser/renderer_host/input/timeout_monitor.h" +#include "content/common/input/web_input_event_traits.h" +#include "content/public/common/content_switches.h" + +using blink::WebInputEvent; +using blink::WebTouchEvent; +using blink::WebTouchPoint; namespace content { +namespace { + +const InputEventAckState kDefaultNotForwardedAck = + INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; +TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent( + const TouchEventWithLatencyInfo& event_to_cancel) { + TouchEventWithLatencyInfo event = event_to_cancel; + event.event.type = WebInputEvent::TouchCancel; + for (size_t i = 0; i < event.event.touchesLength; i++) + event.event.touches[i].state = WebTouchPoint::StateCancelled; + return event; +} + +bool IsNewTouchGesture(const WebTouchEvent& event) { + if (event.type != WebInputEvent::TouchStart) + return false; + if (!event.touchesLength) + return false; + for (size_t i = 0; i < event.touchesLength; i++) { + if (event.touches[i].state != WebTouchPoint::StatePressed) + return false; + } + return true; +} + +bool ShouldTouchTypeTriggerTimeout(WebInputEvent::Type type) { + return type == WebInputEvent::TouchStart || + type == WebInputEvent::TouchMove; +} + +} // namespace + +class TouchEventQueue::TouchTimeoutHandler { + public: + TouchTimeoutHandler(TouchEventQueue* touch_queue, size_t timeout_delay_ms) + : touch_queue_(touch_queue), + timeout_delay_(base::TimeDelta::FromMilliseconds(timeout_delay_ms)), + pending_ack_state_(PENDING_ACK_NONE), + timeout_monitor_(base::Bind(&TouchTimeoutHandler::OnTimeOut, + base::Unretained(this))) {} + + ~TouchTimeoutHandler() {} + + void Start(const TouchEventWithLatencyInfo& event) { + DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE); + DCHECK(ShouldTouchTypeTriggerTimeout(event.event.type)); + timeout_event_ = event; + timeout_monitor_.Restart(timeout_delay_); + } + + bool ConfirmTouchEvent(InputEventAckState ack_result) { + switch (pending_ack_state_) { + case PENDING_ACK_NONE: + timeout_monitor_.Stop(); + return false; + case PENDING_ACK_ORIGINAL_EVENT: + if (AckedTimeoutEventRequiresCancel(ack_result)) { + SetPendingAckState(PENDING_ACK_CANCEL_EVENT); + TouchEventWithLatencyInfo cancel_event = + ObtainCancelEventForTouchEvent(timeout_event_); + touch_queue_->UpdateTouchAckStates( + cancel_event.event, kDefaultNotForwardedAck); + touch_queue_->client_->SendTouchEventImmediately(cancel_event); + } else { + SetPendingAckState(PENDING_ACK_NONE); + touch_queue_->UpdateTouchAckStates(timeout_event_.event, ack_result); + } + return true; + case PENDING_ACK_CANCEL_EVENT: + SetPendingAckState(PENDING_ACK_NONE); + return true; + } + return false; + } + + bool HasTimeoutEvent() const { + return pending_ack_state_ != PENDING_ACK_NONE; + } + + bool IsTimeoutTimerRunning() const { + return timeout_monitor_.IsRunning(); + } + + private: + enum PendingAckState { + PENDING_ACK_NONE, + PENDING_ACK_ORIGINAL_EVENT, + PENDING_ACK_CANCEL_EVENT, + }; + + void OnTimeOut() { + SetPendingAckState(PENDING_ACK_ORIGINAL_EVENT); + touch_queue_->FlushQueue(); + } + + // Skip a cancel event if the timed-out event had no consumer and was the + // initial event in the gesture. + bool AckedTimeoutEventRequiresCancel(InputEventAckState ack_result) const { + DCHECK(HasTimeoutEvent()); + if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) + return true; + return !IsNewTouchGesture(timeout_event_.event); + } + + void SetPendingAckState(PendingAckState new_pending_ack_state) { + DCHECK_NE(pending_ack_state_, new_pending_ack_state); + switch (new_pending_ack_state) { + case PENDING_ACK_ORIGINAL_EVENT: + DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE); + TRACE_EVENT_ASYNC_BEGIN0("input", "TouchEventTimeout", this); + break; + case PENDING_ACK_CANCEL_EVENT: + DCHECK_EQ(pending_ack_state_, PENDING_ACK_ORIGINAL_EVENT); + DCHECK(!timeout_monitor_.IsRunning()); + DCHECK(touch_queue_->empty()); + TRACE_EVENT_ASYNC_STEP_INTO0( + "input", "TouchEventTimeout", this, "CancelEvent"); + break; + case PENDING_ACK_NONE: + DCHECK(!timeout_monitor_.IsRunning()); + DCHECK(touch_queue_->empty()); + TRACE_EVENT_ASYNC_END0("input", "TouchEventTimeout", this); + break; + } + pending_ack_state_ = new_pending_ack_state; + } + + + TouchEventQueue* touch_queue_; + + // How long to wait on a touch ack before cancelling the touch sequence. + base::TimeDelta timeout_delay_; + + // The touch event source for which we expect the next ack. + PendingAckState pending_ack_state_; + + // The event for which the ack timeout is triggered. + TouchEventWithLatencyInfo timeout_event_; + + // Provides timeout-based callback behavior. + TimeoutMonitor timeout_monitor_; +}; + + // This class represents a single coalesced touch event. However, it also keeps // track of all the original touch-events that were coalesced into a single // event. The coalesced event is forwarded to the renderer, while the original @@ -19,9 +171,10 @@ typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; // the Client receives the event with their original timestamp. class CoalescedWebTouchEvent { public: - explicit CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event) + CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event, + bool ignore_ack) : coalesced_event_(event), - ignore_ack_(false) { + ignore_ack_(ignore_ack) { events_.push_back(event); TRACE_EVENT_ASYNC_BEGIN0( "input", "TouchEventQueue::QueueEvent", this); @@ -64,7 +217,6 @@ class CoalescedWebTouchEvent { size_t size() const { return events_.size(); } bool ignore_ack() const { return ignore_ack_; } - void set_ignore_ack(bool value) { ignore_ack_ = value; } private: // This is the event that is forwarded to the renderer. @@ -83,7 +235,10 @@ class CoalescedWebTouchEvent { TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client) : client_(client), dispatching_touch_ack_(NULL), - no_touch_to_renderer_(false) { + dispatching_touch_(false), + no_touch_to_renderer_(false), + renderer_is_consuming_touch_gesture_(false), + ack_timeout_enabled_(false) { DCHECK(client); } @@ -98,7 +253,7 @@ void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) { if (touch_queue_.empty() && !dispatching_touch_ack_) { // There is no touch event in the queue. Forward it to the renderer // immediately. - touch_queue_.push_back(new CoalescedWebTouchEvent(event)); + touch_queue_.push_back(new CoalescedWebTouchEvent(event, false)); TryForwardNextEventToRenderer(); return; } @@ -110,35 +265,26 @@ void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) { if (last_event->CoalesceEventIfPossible(event)) return; } - touch_queue_.push_back(new CoalescedWebTouchEvent(event)); + touch_queue_.push_back(new CoalescedWebTouchEvent(event, false)); } void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result, const ui::LatencyInfo& latency_info) { DCHECK(!dispatching_touch_ack_); + dispatching_touch_ = false; + + if (timeout_handler_ && timeout_handler_->ConfirmTouchEvent(ack_result)) + return; + if (touch_queue_.empty()) return; - // Update the ACK status for each touch point in the ACKed event. - const blink::WebTouchEvent& event = - touch_queue_.front()->coalesced_event().event; - if (event.type == blink::WebInputEvent::TouchEnd || - event.type == blink::WebInputEvent::TouchCancel) { - // The points have been released. Erase the ACK states. - for (unsigned i = 0; i < event.touchesLength; ++i) { - const blink::WebTouchPoint& point = event.touches[i]; - if (point.state == blink::WebTouchPoint::StateReleased || - point.state == blink::WebTouchPoint::StateCancelled) - touch_ack_states_.erase(point.id); - } - } else if (event.type == blink::WebInputEvent::TouchStart) { - for (unsigned i = 0; i < event.touchesLength; ++i) { - const blink::WebTouchPoint& point = event.touches[i]; - if (point.state == blink::WebTouchPoint::StatePressed) - touch_ack_states_[point.id] = ack_result; - } - } + if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) + renderer_is_consuming_touch_gesture_ = true; + const WebTouchEvent& acked_event = + touch_queue_.front()->coalesced_event().event; + UpdateTouchAckStates(acked_event, ack_result); PopTouchEventToClient(ack_result, latency_info); TryForwardNextEventToRenderer(); } @@ -150,12 +296,29 @@ void TouchEventQueue::TryForwardNextEventToRenderer() { while (!touch_queue_.empty()) { const TouchEventWithLatencyInfo& touch = touch_queue_.front()->coalesced_event(); + if (IsNewTouchGesture(touch.event)) + renderer_is_consuming_touch_gesture_ = false; if (ShouldForwardToRenderer(touch.event)) { - client_->SendTouchEventImmediately(touch); + ForwardToRenderer(touch); break; } - PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, - ui::LatencyInfo()); + PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo()); + } +} + +void TouchEventQueue::ForwardToRenderer( + const TouchEventWithLatencyInfo& touch) { + DCHECK(!dispatching_touch_); + // A synchronous ack will reset |dispatching_touch_|, in which case + // the touch timeout should not be started. + base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); + client_->SendTouchEventImmediately(touch); + if (ack_timeout_enabled_ && + dispatching_touch_ && + !renderer_is_consuming_touch_gesture_ && + ShouldTouchTypeTriggerTimeout(touch.event.type)) { + DCHECK(timeout_handler_); + timeout_handler_->Start(touch); } } @@ -170,24 +333,21 @@ void TouchEventQueue::OnGestureScrollEvent( if (no_touch_to_renderer_ || !dispatching_touch_ack_) return; no_touch_to_renderer_ = true; + + // If we have a timeout event, a cancel has already been dispatched + // for the current touch stream. + if (HasTimeoutEvent()) + return; + // Fake a TouchCancel to cancel the touch points of the touch event // that is currently being acked. - TouchEventWithLatencyInfo cancel_event = - dispatching_touch_ack_->coalesced_event(); - cancel_event.event.type = blink::WebInputEvent::TouchCancel; - for (size_t i = 0; i < cancel_event.event.touchesLength; i++) - cancel_event.event.touches[i].state = - blink::WebTouchPoint::StateCancelled; - CoalescedWebTouchEvent* coalesced_cancel_event = - new CoalescedWebTouchEvent(cancel_event); - // Ignore the ack of the touch cancel so when it is acked, it won't get - // sent to gesture recognizer. - coalesced_cancel_event->set_ignore_ack(true); - // |dispatching_touch_ack_| is non-null when we reach here, meaning we + // Note: |dispatching_touch_ack_| is non-null when we reach here, meaning we // are in the scope of PopTouchEventToClient() and that no touch event // in the queue is waiting for ack from renderer. So we can just insert // the touch cancel at the beginning of the queue. - touch_queue_.push_front(coalesced_cancel_event); + touch_queue_.push_front(new CoalescedWebTouchEvent( + ObtainCancelEventForTouchEvent( + dispatching_touch_ack_->coalesced_event()), true)); } else if (type == blink::WebInputEvent::GestureScrollEnd || type == blink::WebInputEvent::GestureFlingStart) { no_touch_to_renderer_ = false; @@ -196,22 +356,52 @@ void TouchEventQueue::OnGestureScrollEvent( void TouchEventQueue::FlushQueue() { DCHECK(!dispatching_touch_ack_); + DCHECK(!dispatching_touch_); while (!touch_queue_.empty()) - PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, - ui::LatencyInfo()); + PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo()); +} + +bool TouchEventQueue::IsPendingAckTouchStart() const { + DCHECK(!dispatching_touch_ack_); + if (touch_queue_.empty()) + return false; + + const blink::WebTouchEvent& event = + touch_queue_.front()->coalesced_event().event; + return (event.type == WebInputEvent::TouchStart); +} + +void TouchEventQueue::SetAckTimeoutEnabled(bool enabled, + size_t ack_timeout_delay_ms) { + if (!enabled) { + // Avoid resetting |timeout_handler_|, as an outstanding timeout may + // be active and must be completed for ack handling consistency. + ack_timeout_enabled_ = false; + return; + } + + ack_timeout_enabled_ = true; + if (!timeout_handler_) + timeout_handler_.reset(new TouchTimeoutHandler(this, ack_timeout_delay_ms)); +} + +bool TouchEventQueue::HasTimeoutEvent() const { + return timeout_handler_ && timeout_handler_->HasTimeoutEvent(); } -size_t TouchEventQueue::GetQueueSize() const { - return touch_queue_.size(); +bool TouchEventQueue::IsTimeoutRunningForTesting() const { + return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning(); } -const TouchEventWithLatencyInfo& TouchEventQueue::GetLatestEvent() const { +const TouchEventWithLatencyInfo& +TouchEventQueue::GetLatestEventForTesting() const { return touch_queue_.back()->coalesced_event(); } void TouchEventQueue::PopTouchEventToClient( InputEventAckState ack_result, const ui::LatencyInfo& renderer_latency_info) { + DCHECK(!dispatching_touch_ack_); if (touch_queue_.empty()) return; scoped_ptr<CoalescedWebTouchEvent> acked_event(touch_queue_.front()); @@ -234,19 +424,22 @@ void TouchEventQueue::PopTouchEventToClient( } bool TouchEventQueue::ShouldForwardToRenderer( - const blink::WebTouchEvent& event) const { + const WebTouchEvent& event) const { + if (HasTimeoutEvent()) + return false; + if (no_touch_to_renderer_ && event.type != blink::WebInputEvent::TouchCancel) return false; // Touch press events should always be forwarded to the renderer. - if (event.type == blink::WebInputEvent::TouchStart) + if (event.type == WebInputEvent::TouchStart) return true; for (unsigned int i = 0; i < event.touchesLength; ++i) { - const blink::WebTouchPoint& point = event.touches[i]; + const WebTouchPoint& point = event.touches[i]; // If a point has been stationary, then don't take it into account. - if (point.state == blink::WebTouchPoint::StateStationary) + if (point.state == WebTouchPoint::StateStationary) continue; if (touch_ack_states_.count(point.id) > 0) { @@ -263,4 +456,25 @@ bool TouchEventQueue::ShouldForwardToRenderer( return false; } +void TouchEventQueue::UpdateTouchAckStates(const WebTouchEvent& event, + InputEventAckState ack_result) { + // Update the ACK status for each touch point in the ACKed event. + if (event.type == WebInputEvent::TouchEnd || + event.type == WebInputEvent::TouchCancel) { + // The points have been released. Erase the ACK states. + for (unsigned i = 0; i < event.touchesLength; ++i) { + const WebTouchPoint& point = event.touches[i]; + if (point.state == WebTouchPoint::StateReleased || + point.state == WebTouchPoint::StateCancelled) + touch_ack_states_.erase(point.id); + } + } else if (event.type == WebInputEvent::TouchStart) { + for (unsigned i = 0; i < event.touchesLength; ++i) { + const WebTouchPoint& point = event.touches[i]; + if (point.state == WebTouchPoint::StatePressed) + touch_ack_states_[point.id] = ack_result; + } + } +} + } // namespace content diff --git a/content/browser/renderer_host/input/touch_event_queue.h b/content/browser/renderer_host/input/touch_event_queue.h index a3053c4e9b..ea7eb71fe5 100644 --- a/content/browser/renderer_host/input/touch_event_queue.h +++ b/content/browser/renderer_host/input/touch_event_queue.h @@ -38,7 +38,7 @@ class CONTENT_EXPORT TouchEventQueue { // The |client| must outlive the TouchEventQueue. explicit TouchEventQueue(TouchEventQueueClient* client); - virtual ~TouchEventQueue(); + ~TouchEventQueue(); // Adds an event to the queue. The event may be coalesced with previously // queued events (e.g. consecutive touch-move events can be coalesced into a @@ -54,28 +54,42 @@ class CONTENT_EXPORT TouchEventQueue { // When GestureScrollBegin is received, we send a touch cancel to renderer, // route all the following touch events directly to client, and ignore the - // ack for the touch cancel. When GestureScrollEnd/GestureFlingStart is - // received, we resume the normal flow of sending touch events to renderer. + // ack for the touch cancel. When Gesture{ScrollEnd,FlingStart} is received, + // resume the normal flow of sending touch events to the renderer. void OnGestureScrollEvent(const GestureEventWithLatencyInfo& gesture_event); // Empties the queue of touch events. This may result in any number of gesture // events being sent to the renderer. void FlushQueue(); - // Returns whether the event-queue is empty. + // Returns whether the currently pending touch event (waiting ACK) is for + // a touch start event. + bool IsPendingAckTouchStart() const; + + // Sets whether a delayed touch ack will cancel and flush the current + // touch sequence. + void SetAckTimeoutEnabled(bool enabled, size_t ack_timeout_delay_ms); + bool empty() const WARN_UNUSED_RESULT { return touch_queue_.empty(); } - bool no_touch_to_renderer() const { - return no_touch_to_renderer_; + size_t size() const { + return touch_queue_.size(); + } + + bool ack_timeout_enabled() const { + return ack_timeout_enabled_; } private: + class TouchTimeoutHandler; + friend class TouchTimeoutHandler; friend class TouchEventQueueTest; - size_t GetQueueSize() const; - const TouchEventWithLatencyInfo& GetLatestEvent() const; + bool HasTimeoutEvent() const; + bool IsTimeoutRunningForTesting() const; + const TouchEventWithLatencyInfo& GetLatestEventForTesting() const; // Walks the queue, checking each event for |ShouldForwardToRenderer()|. // If true, forwards the touch event and stops processing further events. @@ -88,6 +102,10 @@ class CONTENT_EXPORT TouchEventQueue { const ui::LatencyInfo& renderer_latency_info); bool ShouldForwardToRenderer(const blink::WebTouchEvent& event) const; + void ForwardToRenderer(const TouchEventWithLatencyInfo& event); + void UpdateTouchAckStates(const blink::WebTouchEvent& event, + InputEventAckState ack_result); + // Handles touch event forwarding and ack'ed event dispatch. TouchEventQueueClient* client_; @@ -104,11 +122,21 @@ class CONTENT_EXPORT TouchEventQueue { // is being dispatched. CoalescedWebTouchEvent* dispatching_touch_ack_; - // Don't send touch events to renderer. This is enabled when the page - // is scrolling. This behaviour is currently enabled only on aura behind - // a flag. + // Used to prevent touch timeout scheduling if we receive a synchronous + // ack after forwarding a touch event to the client. + bool dispatching_touch_; + + // Don't send touch events to the renderer while scrolling. bool no_touch_to_renderer_; + // Whether an event in the current (multi)touch sequence was consumed by the + // renderer. The touch timeout will never be activated when this is true. + bool renderer_is_consuming_touch_gesture_; + + // Optional handler for timed-out touch event acks, disabled by default. + bool ack_timeout_enabled_; + scoped_ptr<TouchTimeoutHandler> timeout_handler_; + DISALLOW_COPY_AND_ASSIGN(TouchEventQueue); }; diff --git a/content/browser/renderer_host/input/touch_event_queue_unittest.cc b/content/browser/renderer_host/input/touch_event_queue_unittest.cc index b4631b9858..875b798546 100644 --- a/content/browser/renderer_host/input/touch_event_queue_unittest.cc +++ b/content/browser/renderer_host/input/touch_event_queue_unittest.cc @@ -5,8 +5,10 @@ #include "base/basictypes.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" -#include "content/browser/renderer_host/input/synthetic_web_input_event_builders.h" +#include "base/message_loop/message_loop.h" +#include "content/browser/renderer_host/input/timeout_monitor.h" #include "content/browser/renderer_host/input/touch_event_queue.h" +#include "content/common/input/synthetic_web_input_event_builders.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/web/WebInputEvent.h" @@ -16,6 +18,9 @@ using blink::WebTouchEvent; using blink::WebTouchPoint; namespace content { +namespace { +const size_t kDefaultTouchTimeoutDelayMs = 10; +} class TouchEventQueueTest : public testing::Test, public TouchEventQueueClient { @@ -67,13 +72,12 @@ class TouchEventQueueTest : public testing::Test, protected: - void SendTouchEvent(const WebTouchEvent& event) { - queue_->QueueEvent(TouchEventWithLatencyInfo(event, ui::LatencyInfo())); + void SetUpForTimeoutTesting(size_t timeout_delay_ms) { + queue_->SetAckTimeoutEnabled(true, timeout_delay_ms); } - void SendTouchEvent() { - SendTouchEvent(touch_event_); - touch_event_.ResetPoints(); + void SendTouchEvent(const WebTouchEvent& event) { + queue_->QueueEvent(TouchEventWithLatencyInfo(event, ui::LatencyInfo())); } void SendGestureEvent(WebInputEvent::Type type) { @@ -99,20 +103,30 @@ class TouchEventQueueTest : public testing::Test, sync_ack_result_.reset(new InputEventAckState(sync_ack_result)); } - int PressTouchPoint(int x, int y) { - return touch_event_.PressPoint(x, y); + void PressTouchPoint(int x, int y) { + touch_event_.PressPoint(x, y); + SendTouchEvent(); } void MoveTouchPoint(int index, int x, int y) { touch_event_.MovePoint(index, x, y); + SendTouchEvent(); + } + + void MoveTouchPoints(int index0, int x0, int y0, int index1, int x1, int y1) { + touch_event_.MovePoint(index0, x0, y0); + touch_event_.MovePoint(index1, x1, y1); + SendTouchEvent(); } void ReleaseTouchPoint(int index) { touch_event_.ReleasePoint(index); + SendTouchEvent(); } void CancelTouchPoint(int index) { touch_event_.CancelPoint(index); + SendTouchEvent(); } size_t GetAndResetAckedEventCount() { @@ -127,16 +141,32 @@ class TouchEventQueueTest : public testing::Test, return count; } + bool IsPendingAckTouchStart() const { + return queue_->IsPendingAckTouchStart(); + } + void Flush() { queue_->FlushQueue(); } + void SetEnableTouchForwarding(bool enabled) { + queue_->no_touch_to_renderer_ = !enabled; + } + + bool WillForwardTouchEvents() { + return !queue_->no_touch_to_renderer_ && !queue_->HasTimeoutEvent(); + } + + bool IsTimeoutRunning() { + return queue_->IsTimeoutRunningForTesting(); + } + size_t queued_event_count() const { - return queue_->GetQueueSize(); + return queue_->size(); } const WebTouchEvent& latest_event() const { - return queue_->GetLatestEvent().event; + return queue_->GetLatestEventForTesting().event; } const WebTouchEvent& acked_event() const { @@ -160,6 +190,11 @@ class TouchEventQueueTest : public testing::Test, } private: + void SendTouchEvent() { + SendTouchEvent(touch_event_); + touch_event_.ResetPoints(); + } + scoped_ptr<TouchEventQueue> queue_; size_t sent_event_count_; size_t acked_event_count_; @@ -170,19 +205,18 @@ class TouchEventQueueTest : public testing::Test, scoped_ptr<WebTouchEvent> followup_touch_event_; scoped_ptr<WebGestureEvent> followup_gesture_event_; scoped_ptr<InputEventAckState> sync_ack_result_; + base::MessageLoopForUI message_loop_; }; // Tests that touch-events are queued properly. TEST_F(TouchEventQueueTest, Basic) { PressTouchPoint(1, 1); - SendTouchEvent(); EXPECT_EQ(1U, queued_event_count()); EXPECT_EQ(1U, GetAndResetSentEventCount()); // The second touch should not be sent since one is already in queue. MoveTouchPoint(0, 5, 5); - SendTouchEvent(); EXPECT_EQ(2U, queued_event_count()); EXPECT_EQ(0U, GetAndResetSentEventCount()); @@ -210,20 +244,15 @@ TEST_F(TouchEventQueueTest, Flush) { // Send a touch-press event. PressTouchPoint(1, 1); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); ReleaseTouchPoint(0); - SendTouchEvent(); // Events will be queued until the first sent event is ack'ed. for (int i = 5; i < 15; ++i) { PressTouchPoint(1, 1); - SendTouchEvent(); MoveTouchPoint(0, i, i); - SendTouchEvent(); ReleaseTouchPoint(0); - SendTouchEvent(); } EXPECT_EQ(32U, queued_event_count()); EXPECT_EQ(0U, GetAndResetSentEventCount()); @@ -248,18 +277,15 @@ TEST_F(TouchEventQueueTest, Flush) { TEST_F(TouchEventQueueTest, Coalesce) { // Send a touch-press event. PressTouchPoint(1, 1); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); // Send a few touch-move events, followed by a touch-release event. All the // touch-move events should be coalesced into a single event. - for (int i = 5; i < 15; ++i) { + for (int i = 5; i < 15; ++i) MoveTouchPoint(0, i, i); - SendTouchEvent(); - } + EXPECT_EQ(0U, GetAndResetSentEventCount()); ReleaseTouchPoint(0); - SendTouchEvent(); EXPECT_EQ(0U, GetAndResetSentEventCount()); EXPECT_EQ(3U, queued_event_count()); @@ -291,15 +317,13 @@ TEST_F(TouchEventQueueTest, Coalesce) { TEST_F(TouchEventQueueTest, SentTouchEventDoesNotCoalesce) { // Send a touch-press event. PressTouchPoint(1, 1); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); // Send a few touch-move events, followed by a touch-release event. All the // touch-move events should be coalesced into a single event. - for (int i = 5; i < 15; ++i) { + for (int i = 5; i < 15; ++i) MoveTouchPoint(0, i, i); - SendTouchEvent(); - } + EXPECT_EQ(0U, GetAndResetSentEventCount()); EXPECT_EQ(2U, queued_event_count()); @@ -310,11 +334,9 @@ TEST_F(TouchEventQueueTest, SentTouchEventDoesNotCoalesce) { // The coalesced touch-move event has been sent to the renderer. Any new // touch-move event should not be coalesced with the sent event. MoveTouchPoint(0, 5, 5); - SendTouchEvent(); EXPECT_EQ(2U, queued_event_count()); MoveTouchPoint(0, 7, 7); - SendTouchEvent(); EXPECT_EQ(2U, queued_event_count()); } @@ -322,33 +344,27 @@ TEST_F(TouchEventQueueTest, SentTouchEventDoesNotCoalesce) { TEST_F(TouchEventQueueTest, MultiTouch) { // Press the first finger. PressTouchPoint(1, 1); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); // Move the finger. MoveTouchPoint(0, 5, 5); - SendTouchEvent(); EXPECT_EQ(2U, queued_event_count()); // Now press a second finger. PressTouchPoint(2, 2); - SendTouchEvent(); EXPECT_EQ(3U, queued_event_count()); // Move both fingers. - MoveTouchPoint(0, 10, 10); + MoveTouchPoints(0, 10, 10, 1, 20, 20); MoveTouchPoint(1, 20, 20); - SendTouchEvent(); EXPECT_EQ(4U, queued_event_count()); // Move only one finger now. MoveTouchPoint(0, 15, 15); - SendTouchEvent(); EXPECT_EQ(4U, queued_event_count()); // Move the other finger. MoveTouchPoint(1, 25, 25); - SendTouchEvent(); EXPECT_EQ(4U, queued_event_count()); // Make sure both fingers are marked as having been moved in the coalesced @@ -364,12 +380,10 @@ TEST_F(TouchEventQueueTest, MultiTouch) { TEST_F(TouchEventQueueTest, AckAfterQueueFlushed) { // Send some touch-events to the renderer. PressTouchPoint(1, 1); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); EXPECT_EQ(1U, queued_event_count()); MoveTouchPoint(0, 10, 10); - SendTouchEvent(); EXPECT_EQ(0U, GetAndResetSentEventCount()); EXPECT_EQ(2U, queued_event_count()); @@ -397,12 +411,10 @@ TEST_F(TouchEventQueueTest, AckAfterQueueFlushed) { TEST_F(TouchEventQueueTest, NoConsumer) { // The first touch-press should reach the renderer. PressTouchPoint(1, 1); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); // The second touch should not be sent since one is already in queue. MoveTouchPoint(0, 5, 5); - SendTouchEvent(); EXPECT_EQ(0U, GetAndResetSentEventCount()); EXPECT_EQ(2U, queued_event_count()); @@ -416,7 +428,6 @@ TEST_F(TouchEventQueueTest, NoConsumer) { // Send a release event. This should not reach the renderer. ReleaseTouchPoint(0); - SendTouchEvent(); EXPECT_EQ(0U, GetAndResetSentEventCount()); EXPECT_EQ(WebInputEvent::TouchEnd, acked_event().type); EXPECT_EQ(1U, GetAndResetAckedEventCount()); @@ -426,18 +437,13 @@ TEST_F(TouchEventQueueTest, NoConsumer) { // events should be queued first. After the NO_CONSUMER ack for the first // touch-press, all events upto the second touch-press should be flushed. PressTouchPoint(10, 10); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); MoveTouchPoint(0, 5, 5); - SendTouchEvent(); MoveTouchPoint(0, 6, 5); - SendTouchEvent(); ReleaseTouchPoint(0); - SendTouchEvent(); PressTouchPoint(6, 5); - SendTouchEvent(); EXPECT_EQ(0U, GetAndResetSentEventCount()); // The queue should hold the first sent touch-press event, the coalesced // touch-move event, the touch-end event and the second touch-press event. @@ -459,7 +465,6 @@ TEST_F(TouchEventQueueTest, NoConsumer) { // Send a second press event. Even though the first touch had NO_CONSUMER, // this press event should reach the renderer. PressTouchPoint(1, 1); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); EXPECT_EQ(1U, queued_event_count()); } @@ -470,24 +475,17 @@ TEST_F(TouchEventQueueTest, ConsumerIgnoreMultiFinger) { // the second touch point. PressTouchPoint(1, 1); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); MoveTouchPoint(0, 5, 5); - SendTouchEvent(); PressTouchPoint(10, 10); - SendTouchEvent(); MoveTouchPoint(0, 2, 2); - SendTouchEvent(); MoveTouchPoint(1, 4, 10); - SendTouchEvent(); - MoveTouchPoint(0, 10, 10); - MoveTouchPoint(1, 20, 20); - SendTouchEvent(); + MoveTouchPoints(0, 10, 10, 1, 20, 20); // Since the first touch-press is still pending ACK, no other event should // have been sent to the renderer. @@ -523,22 +521,18 @@ TEST_F(TouchEventQueueTest, ConsumerIgnoreMultiFinger) { // Move just the second touch point. Because the first touch point did not // move, this event should not reach the renderer. MoveTouchPoint(1, 30, 30); - SendTouchEvent(); EXPECT_EQ(0U, GetAndResetSentEventCount()); EXPECT_EQ(0U, queued_event_count()); // Move just the first touch point. This should reach the renderer. MoveTouchPoint(0, 10, 10); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); EXPECT_EQ(1U, queued_event_count()); // Move both fingers. This event should reach the renderer (after the ACK of // the previous move event is received), because the first touch point did // move. - MoveTouchPoint(0, 15, 15); - MoveTouchPoint(1, 25, 25); - SendTouchEvent(); + MoveTouchPoints(0, 15, 15, 1, 25, 25); EXPECT_EQ(0U, GetAndResetSentEventCount()); SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED); @@ -554,21 +548,16 @@ TEST_F(TouchEventQueueTest, ConsumerIgnoreMultiFinger) { // the second finger should be immediately released to the view, and the // touch-press event should be dispatched to the renderer. ReleaseTouchPoint(0); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); EXPECT_EQ(1U, queued_event_count()); MoveTouchPoint(1, 40, 40); - SendTouchEvent(); MoveTouchPoint(1, 50, 50); - SendTouchEvent(); PressTouchPoint(1, 1); - SendTouchEvent(); MoveTouchPoint(1, 30, 30); - SendTouchEvent(); EXPECT_EQ(0U, GetAndResetSentEventCount()); EXPECT_EQ(4U, queued_event_count()); @@ -594,7 +583,6 @@ TEST_F(TouchEventQueueTest, ConsumerIgnoreMultiFinger) { TEST_F(TouchEventQueueTest, AckWithFollowupEvents) { // Queue a touch down. PressTouchPoint(1, 1); - SendTouchEvent(); EXPECT_EQ(1U, queued_event_count()); EXPECT_EQ(1U, GetAndResetSentEventCount()); EXPECT_EQ(0U, GetAndResetAckedEventCount()); @@ -618,9 +606,7 @@ TEST_F(TouchEventQueueTest, AckWithFollowupEvents) { EXPECT_EQ(WebInputEvent::TouchStart, acked_event().type); // Queue another event. - PressTouchPoint(1, 1); MoveTouchPoint(0, 2, 2); - SendTouchEvent(); EXPECT_EQ(2U, queued_event_count()); // Receive an ACK for the touch-move followup event. This should cause the @@ -636,41 +622,33 @@ TEST_F(TouchEventQueueTest, SynchronousAcks) { // TouchStart SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED); PressTouchPoint(1, 1); - SendTouchEvent(); EXPECT_EQ(0U, queued_event_count()); EXPECT_EQ(1U, GetAndResetSentEventCount()); EXPECT_EQ(1U, GetAndResetAckedEventCount()); // TouchMove SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED); - PressTouchPoint(1, 1); MoveTouchPoint(0, 2, 2); - SendTouchEvent(); EXPECT_EQ(0U, queued_event_count()); EXPECT_EQ(1U, GetAndResetSentEventCount()); EXPECT_EQ(1U, GetAndResetAckedEventCount()); // TouchEnd SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED); - PressTouchPoint(1, 1); ReleaseTouchPoint(0); - SendTouchEvent(); EXPECT_EQ(0U, queued_event_count()); EXPECT_EQ(1U, GetAndResetSentEventCount()); EXPECT_EQ(1U, GetAndResetAckedEventCount()); // TouchCancel (first inserting a TouchStart so the TouchCancel will be sent) PressTouchPoint(1, 1); - SendTouchEvent(); SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED); EXPECT_EQ(0U, queued_event_count()); EXPECT_EQ(1U, GetAndResetSentEventCount()); EXPECT_EQ(1U, GetAndResetAckedEventCount()); SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED); - PressTouchPoint(1, 1); CancelTouchPoint(0); - SendTouchEvent(); EXPECT_EQ(0U, queued_event_count()); EXPECT_EQ(1U, GetAndResetSentEventCount()); EXPECT_EQ(1U, GetAndResetAckedEventCount()); @@ -707,47 +685,40 @@ TEST_F(TouchEventQueueTest, ImmediateAckWithFollowupEvents) { // Tests basic TouchEvent forwarding suppression. TEST_F(TouchEventQueueTest, NoTouchBasic) { // Disable TouchEvent forwarding. - set_no_touch_to_renderer(true); + SetEnableTouchForwarding(false); MoveTouchPoint(0, 30, 5); - SendTouchEvent(); EXPECT_EQ(0U, GetAndResetSentEventCount()); EXPECT_EQ(1U, GetAndResetAckedEventCount()); // TouchMove should not be sent to renderer. MoveTouchPoint(0, 65, 10); - SendTouchEvent(); EXPECT_EQ(0U, GetAndResetSentEventCount()); EXPECT_EQ(1U, GetAndResetAckedEventCount()); // TouchEnd should not be sent to renderer. ReleaseTouchPoint(0); - SendTouchEvent(); EXPECT_EQ(0U, GetAndResetSentEventCount()); EXPECT_EQ(1U, GetAndResetAckedEventCount()); // TouchStart should not be sent to renderer. PressTouchPoint(5, 5); - SendTouchEvent(); EXPECT_EQ(0U, GetAndResetSentEventCount()); EXPECT_EQ(1U, GetAndResetAckedEventCount()); // Enable TouchEvent forwarding. - set_no_touch_to_renderer(false); + SetEnableTouchForwarding(true); PressTouchPoint(80, 10); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); EXPECT_EQ(1U, GetAndResetAckedEventCount()); MoveTouchPoint(0, 80, 20); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); EXPECT_EQ(1U, GetAndResetAckedEventCount()); ReleaseTouchPoint(0); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); EXPECT_EQ(1U, GetAndResetAckedEventCount()); @@ -757,19 +728,16 @@ TEST_F(TouchEventQueueTest, NoTouchBasic) { TEST_F(TouchEventQueueTest, NoTouchOnScroll) { // Queue a TouchStart. PressTouchPoint(0, 1); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); EXPECT_EQ(1U, GetAndResetAckedEventCount()); MoveTouchPoint(0, 20, 5); - SendTouchEvent(); EXPECT_EQ(1U, queued_event_count()); EXPECT_EQ(1U, GetAndResetSentEventCount()); // Queue another TouchStart. PressTouchPoint(20, 20); - SendTouchEvent(); EXPECT_EQ(2U, queued_event_count()); EXPECT_EQ(0U, GetAndResetSentEventCount()); EXPECT_EQ(WebInputEvent::TouchStart, latest_event().type); @@ -778,9 +746,9 @@ TEST_F(TouchEventQueueTest, NoTouchOnScroll) { WebGestureEvent followup_scroll; followup_scroll.type = WebInputEvent::GestureScrollBegin; SetFollowupEvent(followup_scroll); - ASSERT_FALSE(no_touch_to_renderer()); + ASSERT_TRUE(WillForwardTouchEvents()); SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); - EXPECT_TRUE(no_touch_to_renderer()); + EXPECT_FALSE(WillForwardTouchEvents()); EXPECT_EQ(1U, GetAndResetSentEventCount()); EXPECT_EQ(1U, GetAndResetAckedEventCount()); EXPECT_EQ(2U, queued_event_count()); @@ -794,46 +762,387 @@ TEST_F(TouchEventQueueTest, NoTouchOnScroll) { EXPECT_EQ(0U, GetAndResetSentEventCount()); EXPECT_EQ(WebInputEvent::TouchStart, acked_event().type); - // TouchMove should not be sent to renderer. + // TouchMove should not be sent to the renderer. MoveTouchPoint(0, 30, 5); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetAckedEventCount()); EXPECT_EQ(0U, GetAndResetSentEventCount()); EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, acked_event_state()); // GestureScrollUpdates should not change affect touch forwarding. SendGestureEvent(WebInputEvent::GestureScrollUpdate); - EXPECT_TRUE(no_touch_to_renderer()); + EXPECT_FALSE(WillForwardTouchEvents()); - // TouchEnd should not be sent to renderer. + // TouchEnd should not be sent to the renderer. ReleaseTouchPoint(0); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetAckedEventCount()); EXPECT_EQ(0U, GetAndResetSentEventCount()); EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, acked_event_state()); // GestureScrollEnd will resume the sending of TouchEvents to renderer. SendGestureEvent(blink::WebInputEvent::GestureScrollEnd); - EXPECT_FALSE(no_touch_to_renderer()); + EXPECT_TRUE(WillForwardTouchEvents()); // Now TouchEvents should be forwarded normally. PressTouchPoint(80, 10); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); EXPECT_EQ(1U, GetAndResetAckedEventCount()); MoveTouchPoint(0, 80, 20); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); EXPECT_EQ(1U, GetAndResetAckedEventCount()); ReleaseTouchPoint(0); - SendTouchEvent(); EXPECT_EQ(1U, GetAndResetSentEventCount()); SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); EXPECT_EQ(1U, GetAndResetAckedEventCount()); } +// Tests that IsTouchStartPendingAck works correctly. +TEST_F(TouchEventQueueTest, PendingStart) { + + EXPECT_FALSE(IsPendingAckTouchStart()); + + // Send the touchstart for one point (#1). + PressTouchPoint(1, 1); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_TRUE(IsPendingAckTouchStart()); + + // Send a touchmove for that point (#2). + MoveTouchPoint(0, 5, 5); + EXPECT_EQ(2U, queued_event_count()); + EXPECT_TRUE(IsPendingAckTouchStart()); + + // Ack the touchstart (#1). + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_FALSE(IsPendingAckTouchStart()); + + // Send a touchstart for another point (#3). + PressTouchPoint(10, 10); + EXPECT_EQ(2U, queued_event_count()); + EXPECT_FALSE(IsPendingAckTouchStart()); + + // Ack the touchmove (#2). + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_TRUE(IsPendingAckTouchStart()); + + // Send a touchstart for a third point (#4). + PressTouchPoint(15, 15); + EXPECT_EQ(2U, queued_event_count()); + EXPECT_TRUE(IsPendingAckTouchStart()); + + // Ack the touchstart for the second point (#3). + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(1U, queued_event_count()); + EXPECT_TRUE(IsPendingAckTouchStart()); + + // Ack the touchstart for the third point (#4). + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(0U, queued_event_count()); + EXPECT_FALSE(IsPendingAckTouchStart()); +} + +// Tests that the touch timeout is started when sending certain touch types. +TEST_F(TouchEventQueueTest, TouchTimeoutTypes) { + SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs); + + // Sending a TouchStart will start the timeout. + PressTouchPoint(0, 1); + EXPECT_TRUE(IsTimeoutRunning()); + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); + + // A TouchMove should start the timeout. + MoveTouchPoint(0, 5, 5); + EXPECT_TRUE(IsTimeoutRunning()); + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); + + // A TouchEnd should not start the timeout. + ReleaseTouchPoint(0); + EXPECT_FALSE(IsTimeoutRunning()); + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); + + // A TouchCancel should not start the timeout. + PressTouchPoint(0, 1); + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + ASSERT_FALSE(IsTimeoutRunning()); + CancelTouchPoint(0); + EXPECT_FALSE(IsTimeoutRunning()); + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); +} + +// Tests that a delayed TouchEvent ack will trigger a TouchCancel timeout, +// disabling touch forwarding until the next TouchStart is received after +// the timeout events are ack'ed. +TEST_F(TouchEventQueueTest, TouchTimeoutBasic) { + SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs); + + // Queue a TouchStart. + GetAndResetSentEventCount(); + GetAndResetAckedEventCount(); + PressTouchPoint(0, 1); + ASSERT_EQ(1U, GetAndResetSentEventCount()); + ASSERT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_TRUE(IsTimeoutRunning()); + EXPECT_TRUE(WillForwardTouchEvents()); + + // Delay the ack. + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::MessageLoop::QuitClosure(), + base::TimeDelta::FromMilliseconds(kDefaultTouchTimeoutDelayMs * 2)); + base::MessageLoop::current()->Run(); + + // The timeout should have fired, synthetically ack'ing the timed-out event. + // TouchEvent forwarding is disabled until the ack is received for the + // timed-out event and the future cancel event. + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_FALSE(WillForwardTouchEvents()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Ack'ing the original event should trigger a cancel event. + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_FALSE(WillForwardTouchEvents()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + + // Touch events should not be forwarded until we receive the cancel acks. + PressTouchPoint(0, 1); + ASSERT_EQ(0U, GetAndResetSentEventCount()); + ASSERT_EQ(1U, GetAndResetAckedEventCount()); + + // The synthetic TouchCancel ack should not reach the client, but should + // resume touch forwarding. + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_TRUE(WillForwardTouchEvents()); + + // Subsequent events should be handled normally. + PressTouchPoint(0, 1); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); +} + +// Tests that the timeout is never started if the renderer consumes +// a TouchEvent from the current touch sequence. +TEST_F(TouchEventQueueTest, NoTouchTimeoutIfRendererIsConsumingGesture) { + SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs); + + // Queue a TouchStart. + PressTouchPoint(0, 1); + ASSERT_TRUE(IsTimeoutRunning()); + + // Mark the event as consumed. This should prevent the timeout from + // being activated on subsequent TouchEvents in this gesture. + SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); + + // A TouchMove should not start the timeout. + MoveTouchPoint(0, 5, 5); + EXPECT_FALSE(IsTimeoutRunning()); + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + + // A secondary TouchStart should not start the timeout. + PressTouchPoint(1, 0); + EXPECT_FALSE(IsTimeoutRunning()); + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + + // A TouchEnd should not start the timeout. + ReleaseTouchPoint(1); + EXPECT_FALSE(IsTimeoutRunning()); + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + + // A TouchCancel should not start the timeout. + CancelTouchPoint(0); + EXPECT_FALSE(IsTimeoutRunning()); +} + +// Tests that the timeout is never started if the ack is synchronous. +TEST_F(TouchEventQueueTest, NoTouchTimeoutIfAckIsSynchronous) { + SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs); + + // Queue a TouchStart. + SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED); + ASSERT_FALSE(IsTimeoutRunning()); + PressTouchPoint(0, 1); + EXPECT_FALSE(IsTimeoutRunning()); +} + +// Tests that a TouchCancel timeout plays nice when the timed out touch stream +// turns into a scroll gesture sequence. +TEST_F(TouchEventQueueTest, TouchTimeoutWithFollowupGesture) { + SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs); + + // Queue a TouchStart. + PressTouchPoint(0, 1); + EXPECT_TRUE(IsTimeoutRunning()); + EXPECT_TRUE(WillForwardTouchEvents()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + + // The cancelled sequence may turn into a scroll gesture. + WebGestureEvent followup_scroll; + followup_scroll.type = WebInputEvent::GestureScrollBegin; + SetFollowupEvent(followup_scroll); + + // Delay the ack. + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::MessageLoop::QuitClosure(), + base::TimeDelta::FromMilliseconds(kDefaultTouchTimeoutDelayMs * 2)); + base::MessageLoop::current()->Run(); + + // The timeout should have fired, disabling touch forwarding until both acks + // are received, acking the timed out event. + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_FALSE(WillForwardTouchEvents()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Ack the original event, triggering a TouchCancel. + SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_FALSE(WillForwardTouchEvents()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + + // Ack the cancel event. Normally, this would resume touch forwarding, + // but we're still within a scroll gesture so it remains disabled. + SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_FALSE(WillForwardTouchEvents()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + + // Try to forward a touch event. + GetAndResetSentEventCount(); + GetAndResetAckedEventCount(); + PressTouchPoint(0, 1); + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Now end the scroll sequence, resuming touch handling. + SendGestureEvent(blink::WebInputEvent::GestureScrollEnd); + EXPECT_TRUE(WillForwardTouchEvents()); + PressTouchPoint(0, 1); + EXPECT_TRUE(IsTimeoutRunning()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); +} + +// Tests that a TouchCancel timeout plays nice when the timed out touch stream +// turns into a scroll gesture sequence, but the original event acks are +// significantly delayed. +TEST_F(TouchEventQueueTest, TouchTimeoutWithFollowupGestureAndDelayedAck) { + SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs); + + // Queue a TouchStart. + PressTouchPoint(0, 1); + EXPECT_TRUE(IsTimeoutRunning()); + EXPECT_TRUE(WillForwardTouchEvents()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + + // The cancelled sequence may turn into a scroll gesture. + WebGestureEvent followup_scroll; + followup_scroll.type = WebInputEvent::GestureScrollBegin; + SetFollowupEvent(followup_scroll); + + // Delay the ack. + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::MessageLoop::QuitClosure(), + base::TimeDelta::FromMilliseconds(kDefaultTouchTimeoutDelayMs * 2)); + base::MessageLoop::current()->Run(); + + // The timeout should have fired, disabling touch forwarding until both acks + // are received and acking the timed out event. + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_FALSE(WillForwardTouchEvents()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Try to forward a touch event. + GetAndResetSentEventCount(); + GetAndResetAckedEventCount(); + PressTouchPoint(0, 1); + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Now end the scroll sequence. Events will not be forwarded until the two + // outstanding touch acks are received. + SendGestureEvent(blink::WebInputEvent::GestureScrollEnd); + PressTouchPoint(0, 1); + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Ack the original event, triggering a cancel. + SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + + // Ack the cancel event, resuming touch forwarding. + SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + + PressTouchPoint(0, 1); + EXPECT_TRUE(IsTimeoutRunning()); + EXPECT_EQ(1U, GetAndResetSentEventCount()); +} + +// Tests that a delayed TouchEvent ack will not trigger a TouchCancel timeout if +// the timed-out event had no consumer. +TEST_F(TouchEventQueueTest, NoCancelOnTouchTimeoutWithoutConsumer) { + SetUpForTimeoutTesting(kDefaultTouchTimeoutDelayMs); + + // Queue a TouchStart. + PressTouchPoint(0, 1); + ASSERT_EQ(1U, GetAndResetSentEventCount()); + ASSERT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_TRUE(IsTimeoutRunning()); + EXPECT_TRUE(WillForwardTouchEvents()); + + // Delay the ack. + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::MessageLoop::QuitClosure(), + base::TimeDelta::FromMilliseconds(kDefaultTouchTimeoutDelayMs * 2)); + base::MessageLoop::current()->Run(); + + // The timeout should have fired, synthetically ack'ing the timed out event. + // TouchEvent forwarding is disabled until the original ack is received. + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_FALSE(WillForwardTouchEvents()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + EXPECT_EQ(1U, GetAndResetAckedEventCount()); + + // Touch events should not be forwarded until we receive the original ack. + PressTouchPoint(0, 1); + ASSERT_EQ(0U, GetAndResetSentEventCount()); + ASSERT_EQ(1U, GetAndResetAckedEventCount()); + + // Ack'ing the original event should not trigger a cancel event, as the + // TouchStart had no consumer. However, it should re-enable touch forwarding. + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); + EXPECT_FALSE(IsTimeoutRunning()); + EXPECT_TRUE(WillForwardTouchEvents()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); + EXPECT_EQ(0U, GetAndResetSentEventCount()); + + // Subsequent events should be handled normally. + PressTouchPoint(0, 1); + EXPECT_EQ(1U, GetAndResetSentEventCount()); + EXPECT_EQ(0U, GetAndResetAckedEventCount()); +} } // namespace content diff --git a/content/browser/renderer_host/input/touch_input_browsertest.cc b/content/browser/renderer_host/input/touch_input_browsertest.cc new file mode 100644 index 0000000000..859e1a4af4 --- /dev/null +++ b/content/browser/renderer_host/input/touch_input_browsertest.cc @@ -0,0 +1,307 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/auto_reset.h" +#include "base/command_line.h" +#include "base/run_loop.h" +#include "content/browser/renderer_host/render_widget_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/input/synthetic_web_input_event_builders.h" +#include "content/common/input_messages.h" +#include "content/public/browser/browser_message_filter.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_widget_host_view.h" +#include "content/public/common/content_switches.h" +#include "content/shell/browser/shell.h" +#include "content/test/content_browser_test.h" +#include "content/test/content_browser_test_utils.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/events/event_switches.h" +#include "ui/events/latency_info.h" + +using blink::WebInputEvent; + +namespace { + +void GiveItSomeTime() { + base::RunLoop run_loop; + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + run_loop.QuitClosure(), + base::TimeDelta::FromMilliseconds(10)); + run_loop.Run(); +} + +const char kTouchEventDataURL[] = + "data:text/html;charset=utf-8," + "<body onload='setup();'>" + "<div id='first'></div><div id='second'></div><div id='third'></div>" + "<style>" + " #first {" + " position: absolute;" + " width: 100px;" + " height: 100px;" + " top: 0px;" + " left: 0px;" + " background-color: green;" + " -webkit-transform: translate3d(0, 0, 0);" + " }" + " #second {" + " position: absolute;" + " width: 100px;" + " height: 100px;" + " top: 0px;" + " left: 110px;" + " background-color: blue;" + " -webkit-transform: translate3d(0, 0, 0);" + " }" + " #third {" + " position: absolute;" + " width: 100px;" + " height: 100px;" + " top: 110px;" + " left: 0px;" + " background-color: yellow;" + " -webkit-transform: translate3d(0, 0, 0);" + " }" + "</style>" + "<script>" + " function setup() {" + " second.ontouchstart = function() {};" + " third.ontouchstart = function(e) {" + " e.preventDefault();" + " };" + " }" + "</script>"; + +} // namespace + +namespace content { + +class InputEventMessageFilter : public BrowserMessageFilter { + public: + InputEventMessageFilter() + : type_(WebInputEvent::Undefined), + state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {} + + void WaitForAck(WebInputEvent::Type type) { + base::RunLoop run_loop; + base::AutoReset<base::Closure> reset_quit(&quit_, run_loop.QuitClosure()); + base::AutoReset<WebInputEvent::Type> reset_type(&type_, type); + run_loop.Run(); + } + + InputEventAckState last_ack_state() const { return state_; } + + protected: + virtual ~InputEventMessageFilter() {} + + private: + void ReceivedEventAck(WebInputEvent::Type type, InputEventAckState state) { + if (type_ == type) { + state_ = state; + quit_.Run(); + } + } + + // BrowserMessageFilter: + virtual bool OnMessageReceived(const IPC::Message& message, + bool* message_was_ok) OVERRIDE { + if (message.type() == InputHostMsg_HandleInputEvent_ACK::ID) { + ui::LatencyInfo latency; + WebInputEvent::Type type = WebInputEvent::Undefined; + InputEventAckState ack = INPUT_EVENT_ACK_STATE_UNKNOWN; + InputHostMsg_HandleInputEvent_ACK::Read(&message, &type, &ack, &latency); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&InputEventMessageFilter::ReceivedEventAck, + this, type, ack)); + } + return false; + } + + base::Closure quit_; + WebInputEvent::Type type_; + InputEventAckState state_; + + DISALLOW_COPY_AND_ASSIGN(InputEventMessageFilter); +}; + +class TouchInputBrowserTest : public ContentBrowserTest, + public testing::WithParamInterface<std::string> { + public: + TouchInputBrowserTest() {} + virtual ~TouchInputBrowserTest() {} + + RenderWidgetHostImpl* GetWidgetHost() { + return RenderWidgetHostImpl::From(shell()->web_contents()-> + GetRenderViewHost()); + } + + InputEventMessageFilter* filter() { return filter_.get(); } + + protected: + void LoadURLAndAddFilter() { + const GURL data_url(kTouchEventDataURL); + NavigateToURL(shell(), data_url); + + WebContentsImpl* web_contents = + static_cast<WebContentsImpl*>(shell()->web_contents()); + RenderWidgetHostImpl* host = + RenderWidgetHostImpl::From(web_contents->GetRenderViewHost()); + host->GetView()->SetSize(gfx::Size(400, 400)); + + // The page is loaded in the renderer, wait for a new frame to arrive. + while (!host->ScheduleComposite()) + GiveItSomeTime(); + + filter_ = new InputEventMessageFilter(); + host->GetProcess()->AddFilter(filter_); + } + + // ContentBrowserTest: + virtual void SetUp() OVERRIDE { + // We expect real pixel output for these tests. + UseRealGLContexts(); + + // On legacy windows, these tests need real GL bindings to pass. +#if defined(OS_WIN) && !defined(USE_AURA) + UseRealGLBindings(); +#endif + + ContentBrowserTest::SetUp(); + } + + virtual void SetUpCommandLine(CommandLine* cmd) OVERRIDE { + cmd->AppendSwitchASCII(switches::kTouchEvents, + switches::kTouchEventsEnabled); + cmd->AppendSwitch(GetParam()); + } + + scoped_refptr<InputEventMessageFilter> filter_; +}; + +// Touch input event tests don't work on Mac with the legacy software renderer. +// These can be enabled when software compositing is enabled. +// http://crbug.com/268038 +#if defined(OS_MACOSX) +#define MAYBE_TouchNoHandler DISABLED_TouchNoHandler +#else +#define MAYBE_TouchNoHandler TouchNoHandler +#endif +IN_PROC_BROWSER_TEST_P(TouchInputBrowserTest, MAYBE_TouchNoHandler) { + LoadURLAndAddFilter(); + SyntheticWebTouchEvent touch; + + // A press on |first| should be acked with NO_CONSUMER_EXISTS since there is + // no touch-handler on it. + touch.PressPoint(25, 25); + GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); + filter()->WaitForAck(WebInputEvent::TouchStart); + + if (GetParam() == std::string(switches::kEnableThreadedCompositing)) { + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, + filter()->last_ack_state()); + } else { + // http://crbug.com/326232: This should be NO_CONSUMER_EXISTS once + // WebViewImpl::hasTouchEventHandlersAt() is implemented. + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state()); + } + + // If a touch-press is acked with NO_CONSUMER_EXISTS, then subsequent + // touch-points don't need to be dispatched until the touch point is released. + touch.ReleasePoint(0); + GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); + touch.ResetPoints(); +} + +// Touch input event tests don't work on Mac with the legacy software renderer. +// These can be enabled when software compositing is enabled. +// http://crbug.com/268038 +#if defined(OS_MACOSX) +#define MAYBE_TouchHandlerNoConsume DISABLED_TouchHandlerNoConsume +#else +#define MAYBE_TouchHandlerNoConsume TouchHandlerNoConsume +#endif +IN_PROC_BROWSER_TEST_P(TouchInputBrowserTest, MAYBE_TouchHandlerNoConsume) { + LoadURLAndAddFilter(); + SyntheticWebTouchEvent touch; + + // Press on |second| should be acked with NOT_CONSUMED since there is a + // touch-handler on |second|, but it doesn't consume the event. + touch.PressPoint(125, 25); + GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); + filter()->WaitForAck(WebInputEvent::TouchStart); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state()); + + touch.ReleasePoint(0); + GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); + filter()->WaitForAck(WebInputEvent::TouchEnd); + touch.ResetPoints(); +} + +// Touch input event tests don't work on Mac with the legacy software renderer. +// These can be enabled when software compositing is enabled. +// http://crbug.com/268038 +#if defined(OS_MACOSX) +#define MAYBE_TouchHandlerConsume DISABLED_TouchHandlerConsume +#else +#define MAYBE_TouchHandlerConsume TouchHandlerConsume +#endif +IN_PROC_BROWSER_TEST_P(TouchInputBrowserTest, MAYBE_TouchHandlerConsume) { + LoadURLAndAddFilter(); + SyntheticWebTouchEvent touch; + + // Press on |third| should be acked with CONSUMED since the touch-handler on + // |third| consimes the event. + touch.PressPoint(25, 125); + GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); + filter()->WaitForAck(WebInputEvent::TouchStart); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, filter()->last_ack_state()); + + touch.ReleasePoint(0); + GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); + filter()->WaitForAck(WebInputEvent::TouchEnd); +} + +// Touch input event tests don't work on Mac with the legacy software renderer. +// These can be enabled when software compositing is enabled. +// http://crbug.com/268038 +#if defined(OS_MACOSX) +#define MAYBE_MultiPointTouchPress DISABLED_MultiPointTouchPress +#else +#define MAYBE_MultiPointTouchPress MultiPointTouchPress +#endif +IN_PROC_BROWSER_TEST_P(TouchInputBrowserTest, MAYBE_MultiPointTouchPress) { + LoadURLAndAddFilter(); + SyntheticWebTouchEvent touch; + + // Press on |first|, which sould be acked with NO_CONSUMER_EXISTS. Then press + // on |third|. That point should be acked with CONSUMED. + touch.PressPoint(25, 25); + GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); + filter()->WaitForAck(WebInputEvent::TouchStart); + if (GetParam() == std::string(switches::kEnableThreadedCompositing)) { + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, + filter()->last_ack_state()); + } else { + // http://crbug.com/326232: This should be NO_CONSUMER_EXISTS once + // WebViewImpl::hasTouchEventHandlersAt() is implemented. + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state()); + } + + touch.PressPoint(25, 125); + GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); + filter()->WaitForAck(WebInputEvent::TouchStart); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, filter()->last_ack_state()); +} + +INSTANTIATE_TEST_CASE_P(WithoutInputHandlerProxy, TouchInputBrowserTest, + ::testing::Values(std::string(switches::kDisableThreadedCompositing))); + +#if !defined(OS_MACOSX) +INSTANTIATE_TEST_CASE_P(WithInputHandlerProxy, TouchInputBrowserTest, + ::testing::Values(std::string(switches::kEnableThreadedCompositing))); +#endif + +} // namespace content diff --git a/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc b/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc index bbb6a08c2f..39fca2f854 100644 --- a/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc +++ b/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc @@ -9,7 +9,7 @@ #include "ui/events/gestures/gesture_configuration.h" #if defined(OS_ANDROID) -#include "content/common/android/view_configuration.h" +#include "ui/gfx/android/view_configuration.h" #endif namespace content { @@ -56,11 +56,11 @@ bool TouchscreenTapSuppressionController::ShouldSuppressGestureTapEnd() { // TODO(jdduke): Enable ui::GestureConfiguration on Android and initialize // with parameters from ViewConfiguration. int TouchscreenTapSuppressionController::MaxCancelToDownTimeInMs() { - return ViewConfiguration::GetTapTimeoutInMs(); + return gfx::ViewConfiguration::GetTapTimeoutInMs(); } int TouchscreenTapSuppressionController::MaxTapGapTimeInMs() { - return ViewConfiguration::GetLongPressTimeoutInMs(); + return gfx::ViewConfiguration::GetLongPressTimeoutInMs(); } #else int TouchscreenTapSuppressionController::MaxCancelToDownTimeInMs() { diff --git a/content/browser/renderer_host/java/OWNERS b/content/browser/renderer_host/java/OWNERS index 4b297c43ee..d378671071 100644 --- a/content/browser/renderer_host/java/OWNERS +++ b/content/browser/renderer_host/java/OWNERS @@ -1,2 +1,2 @@ -joth@chromium.org steveblock@chromium.org +torne@chromium.org diff --git a/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc b/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc index 6d792e7dac..562517a114 100644 --- a/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc +++ b/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc @@ -59,7 +59,7 @@ JavaBridgeDispatcherHost::~JavaBridgeDispatcherHost() { base::Bind(&CleanUpStubs, stubs_)); } -void JavaBridgeDispatcherHost::AddNamedObject(const string16& name, +void JavaBridgeDispatcherHost::AddNamedObject(const base::string16& name, NPObject* object) { NPVariant_Param variant_param; CreateNPVariantParam(object, &variant_param); @@ -68,7 +68,7 @@ void JavaBridgeDispatcherHost::AddNamedObject(const string16& name, render_view_host_->GetRoutingID(), name, variant_param)); } -void JavaBridgeDispatcherHost::RemoveNamedObject(const string16& name) { +void JavaBridgeDispatcherHost::RemoveNamedObject(const base::string16& name) { // On receipt of this message, the JavaBridgeDispatcher will drop its // reference to the corresponding proxy object. When the last reference is // removed, the proxy object will delete its NPObjectProxy, which will cause diff --git a/content/browser/renderer_host/java/java_bridge_dispatcher_host.h b/content/browser/renderer_host/java/java_bridge_dispatcher_host.h index 94ee632131..21e47c0d3b 100644 --- a/content/browser/renderer_host/java/java_bridge_dispatcher_host.h +++ b/content/browser/renderer_host/java/java_bridge_dispatcher_host.h @@ -42,8 +42,8 @@ class JavaBridgeDispatcherHost // to |object|, which is manipulated on the background thread. This class // holds a reference to |object| for the time that the proxy object is bound // to the window object. - void AddNamedObject(const string16& name, NPObject* object); - void RemoveNamedObject(const string16& name); + void AddNamedObject(const base::string16& name, NPObject* object); + void RemoveNamedObject(const base::string16& name); // Since this object is ref-counted, it might outlive render_view_host_. void RenderViewDeleted(); diff --git a/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc b/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc index f06d9fe4aa..02cf4dcc06 100644 --- a/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc +++ b/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc @@ -31,7 +31,7 @@ JavaBridgeDispatcherHostManager::~JavaBridgeDispatcherHostManager() { DCHECK_EQ(0U, instances_.size()); } -void JavaBridgeDispatcherHostManager::AddNamedObject(const string16& name, +void JavaBridgeDispatcherHostManager::AddNamedObject(const base::string16& name, NPObject* object) { // Record this object in a map so that we can add it into RenderViewHosts // created later. The JavaBridgeDispatcherHost instances will take a @@ -67,7 +67,8 @@ void JavaBridgeDispatcherHostManager::SetRetainedObjectSet( } } -void JavaBridgeDispatcherHostManager::RemoveNamedObject(const string16& name) { +void JavaBridgeDispatcherHostManager::RemoveNamedObject( + const base::string16& name) { ObjectMap::iterator iter = objects_.find(name); if (iter == objects_.end()) { return; diff --git a/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h b/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h index e3d629af37..29523b5739 100644 --- a/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h +++ b/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h @@ -34,8 +34,8 @@ class JavaBridgeDispatcherHostManager // These methods add or remove the object to each JavaBridgeDispatcherHost. // Each one holds a reference to the NPObject while the object is bound to // the corresponding RenderView. See JavaBridgeDispatcherHost for details. - void AddNamedObject(const string16& name, NPObject* object); - void RemoveNamedObject(const string16& name); + void AddNamedObject(const base::string16& name, NPObject* object); + void RemoveNamedObject(const base::string16& name); void OnGetChannelHandle(RenderViewHost* render_view_host, IPC::Message* reply_msg); @@ -60,7 +60,7 @@ class JavaBridgeDispatcherHostManager typedef std::map<RenderViewHost*, scoped_refptr<JavaBridgeDispatcherHost> > InstanceMap; InstanceMap instances_; - typedef std::map<string16, NPObject*> ObjectMap; + typedef std::map<base::string16, NPObject*> ObjectMap; ObjectMap objects_; JavaObjectWeakGlobalRef retained_object_set_; diff --git a/content/browser/renderer_host/java/java_method.cc b/content/browser/renderer_host/java/java_method.cc index ef2d097dd3..5a654fe130 100644 --- a/content/browser/renderer_host/java/java_method.cc +++ b/content/browser/renderer_host/java/java_method.cc @@ -86,7 +86,7 @@ std::string BinaryNameToJNIName(const std::string& binary_name, return jni_name; } NOTREACHED(); - return EmptyString(); + return std::string(); } } // namespace diff --git a/content/browser/renderer_host/media/OWNERS b/content/browser/renderer_host/media/OWNERS index 45ac661112..bc20fb9af2 100644 --- a/content/browser/renderer_host/media/OWNERS +++ b/content/browser/renderer_host/media/OWNERS @@ -16,6 +16,9 @@ per-file web_contents*=hclam@chromium.org per-file web_contents*=justinlin@chromium.org per-file web_contents*=miu@chromium.org per-file web_contents*=nick@chromium.org +per-file video_capture_device_impl*=hclam@chromium.org +per-file video_capture_device_impl*=miu@chromium.org +per-file video_capture_device_impl*=nick@chromium.org per-file video_capture_oracle*=hclam@chromium.org per-file video_capture_oracle*=justinlin@chromium.org per-file video_capture_oracle*=miu@chromium.org diff --git a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc index a94d7f1c36..76cb1794a9 100644 --- a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc +++ b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc @@ -55,7 +55,7 @@ class AudioInputDeviceManagerTest : public testing::Test { message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO)); io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO, message_loop_.get())); - audio_manager_.reset(media::AudioManager::Create()); + audio_manager_.reset(media::AudioManager::CreateForTesting()); manager_ = new AudioInputDeviceManager(audio_manager_.get()); audio_input_listener_.reset(new MockAudioInputDeviceManagerListener()); manager_->Register(audio_input_listener_.get(), diff --git a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc index 0f8a5e99e4..87f38a714b 100644 --- a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc +++ b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc @@ -154,7 +154,7 @@ class MockAudioRendererHost : public AudioRendererHost { class AudioRendererHostTest : public testing::Test { public: AudioRendererHostTest() { - audio_manager_.reset(media::AudioManager::Create()); + audio_manager_.reset(media::AudioManager::CreateForTesting()); media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); media_stream_manager_->UseFakeDevice(); host_ = new MockAudioRendererHost(audio_manager_.get(), diff --git a/content/browser/renderer_host/media/desktop_capture_device_ash.cc b/content/browser/renderer_host/media/desktop_capture_device_aura.cc index 08a74826b4..5419488c88 100644 --- a/content/browser/renderer_host/media/desktop_capture_device_ash.cc +++ b/content/browser/renderer_host/media/desktop_capture_device_aura.cc @@ -1,8 +1,8 @@ // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// -#include "content/browser/renderer_host/media/desktop_capture_device_ash.h" + +#include "content/browser/renderer_host/media/desktop_capture_device_aura.h" #include "base/logging.h" #include "base/timer/timer.h" @@ -41,6 +41,9 @@ class DesktopVideoCaptureMachine virtual void Stop() OVERRIDE; // Implements aura::WindowObserver. + virtual void OnWindowBoundsChanged(aura::Window* window, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) OVERRIDE; virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; // Implements ui::CompositorObserver. @@ -60,6 +63,9 @@ class DesktopVideoCaptureMachine // |dirty| is false for timer polls and true for compositor updates. void Capture(bool dirty); + // Update capture size. Must be called on the UI thread. + void UpdateCaptureSize(); + // Response callback for cc::Layer::RequestCopyOfOutput(). void DidCopyOutput( scoped_refptr<media::VideoFrame> video_frame, @@ -117,6 +123,9 @@ bool DesktopVideoCaptureMachine::Start( DCHECK(oracle_proxy.get()); oracle_proxy_ = oracle_proxy; + // Update capture size. + UpdateCaptureSize(); + // Start observing window events. desktop_window_->AddObserver(this); @@ -156,6 +165,14 @@ void DesktopVideoCaptureMachine::Stop() { started_ = false; } +void DesktopVideoCaptureMachine::UpdateCaptureSize() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (oracle_proxy_ && desktop_layer_) { + oracle_proxy_->UpdateCaptureSize(ui::ConvertSizeToPixel( + desktop_layer_, desktop_layer_->bounds().size())); + } +} + void DesktopVideoCaptureMachine::Capture(bool dirty) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -248,6 +265,17 @@ void DesktopVideoCaptureMachine::DidCopyOutput( base::Passed(&release_callback))); } +void DesktopVideoCaptureMachine::OnWindowBoundsChanged( + aura::Window* window, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) { + DCHECK(desktop_window_ && window == desktop_window_); + + // Post task to update capture size on UI thread. + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( + &DesktopVideoCaptureMachine::UpdateCaptureSize, AsWeakPtr())); +} + void DesktopVideoCaptureMachine::OnWindowDestroyed(aura::Window* window) { DCHECK(desktop_window_ && window == desktop_window_); desktop_window_ = NULL; @@ -266,33 +294,33 @@ void DesktopVideoCaptureMachine::OnCompositingEnded( } // namespace -DesktopCaptureDeviceAsh::DesktopCaptureDeviceAsh( +DesktopCaptureDeviceAura::DesktopCaptureDeviceAura( const DesktopMediaID& source) : impl_(new VideoCaptureDeviceImpl(scoped_ptr<VideoCaptureMachine>( new DesktopVideoCaptureMachine(source)))) {} -DesktopCaptureDeviceAsh::~DesktopCaptureDeviceAsh() { - DVLOG(2) << "DesktopCaptureDeviceAsh@" << this << " destroying."; +DesktopCaptureDeviceAura::~DesktopCaptureDeviceAura() { + DVLOG(2) << "DesktopCaptureDeviceAura@" << this << " destroying."; } // static -media::VideoCaptureDevice* DesktopCaptureDeviceAsh::Create( +media::VideoCaptureDevice* DesktopCaptureDeviceAura::Create( const DesktopMediaID& source) { // This implementation only supports screen capture. if (source.type != DesktopMediaID::TYPE_SCREEN) return NULL; - return new DesktopCaptureDeviceAsh(source); + return new DesktopCaptureDeviceAura(source); } -void DesktopCaptureDeviceAsh::AllocateAndStart( +void DesktopCaptureDeviceAura::AllocateAndStart( const media::VideoCaptureParams& params, scoped_ptr<Client> client) { DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString(); impl_->AllocateAndStart(params, client.Pass()); } -void DesktopCaptureDeviceAsh::StopAndDeAllocate() { +void DesktopCaptureDeviceAura::StopAndDeAllocate() { impl_->StopAndDeAllocate(); } diff --git a/content/browser/renderer_host/media/desktop_capture_device_ash.h b/content/browser/renderer_host/media/desktop_capture_device_aura.h index 95969a8e6b..bd0d7180b9 100644 --- a/content/browser/renderer_host/media/desktop_capture_device_ash.h +++ b/content/browser/renderer_host/media/desktop_capture_device_aura.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_DESKTOP_CAPTURE_DEVICE_ASH_H_ -#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_DESKTOP_CAPTURE_DEVICE_ASH_H_ +#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_DESKTOP_CAPTURE_DEVICE_AURA_H_ +#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_DESKTOP_CAPTURE_DEVICE_AURA_H_ #include <string> @@ -20,14 +20,14 @@ namespace content { class VideoCaptureDeviceImpl; -// An implementation of VideoCaptureDevice that mirrors the desktop on Ash. -class CONTENT_EXPORT DesktopCaptureDeviceAsh +// An implementation of VideoCaptureDevice that mirrors an Aura window. +class CONTENT_EXPORT DesktopCaptureDeviceAura : public media::VideoCaptureDevice { public: - // Creates a VideoCaptureDevice for the Ash desktop. + // Creates a VideoCaptureDevice for the Aura desktop. static media::VideoCaptureDevice* Create(const DesktopMediaID& source); - virtual ~DesktopCaptureDeviceAsh(); + virtual ~DesktopCaptureDeviceAura(); // VideoCaptureDevice implementation. virtual void AllocateAndStart(const media::VideoCaptureParams& params, @@ -35,14 +35,14 @@ class CONTENT_EXPORT DesktopCaptureDeviceAsh virtual void StopAndDeAllocate() OVERRIDE; private: - DesktopCaptureDeviceAsh(const DesktopMediaID& source); + DesktopCaptureDeviceAura(const DesktopMediaID& source); const scoped_ptr<class VideoCaptureDeviceImpl> impl_; - DISALLOW_COPY_AND_ASSIGN(DesktopCaptureDeviceAsh); + DISALLOW_COPY_AND_ASSIGN(DesktopCaptureDeviceAura); }; } // namespace content -#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_DESKTOP_CAPTURE_DEVICE_ASH_H_ +#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_DESKTOP_CAPTURE_DEVICE_AURA_H_ diff --git a/content/browser/renderer_host/media/desktop_capture_device_ash_unittest.cc b/content/browser/renderer_host/media/desktop_capture_device_aura_unittest.cc index 2e82475219..1e87c69300 100644 --- a/content/browser/renderer_host/media/desktop_capture_device_ash_unittest.cc +++ b/content/browser/renderer_host/media/desktop_capture_device_aura_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/renderer_host/media/desktop_capture_device_ash.h" +#include "content/browser/renderer_host/media/desktop_capture_device_aura.h" #include "base/synchronization/waitable_event.h" #include "content/browser/browser_thread_impl.h" @@ -49,18 +49,18 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client { }; // Test harness that sets up a minimal environment with necessary stubs. -class DesktopCaptureDeviceAshTest : public testing::Test { +class DesktopCaptureDeviceAuraTest : public testing::Test { public: - DesktopCaptureDeviceAshTest() + DesktopCaptureDeviceAuraTest() : browser_thread_for_ui_(BrowserThread::UI, &message_loop_) {} - virtual ~DesktopCaptureDeviceAshTest() {} + virtual ~DesktopCaptureDeviceAuraTest() {} protected: virtual void SetUp() OVERRIDE { helper_.reset(new aura::test::AuraTestHelper(&message_loop_)); helper_->SetUp(); - // We need a window to cover desktop area so that DesktopCaptureDeviceAsh + // We need a window to cover desktop area so that DesktopCaptureDeviceAura // can use gfx::NativeWindow::GetWindowAtScreenPoint() to locate the // root window associated with the primary display. gfx::Rect desktop_bounds = root_window()->bounds(); @@ -90,13 +90,13 @@ class DesktopCaptureDeviceAshTest : public testing::Test { scoped_ptr<aura::Window> desktop_window_; scoped_ptr<aura::test::TestWindowDelegate> window_delegate_; - DISALLOW_COPY_AND_ASSIGN(DesktopCaptureDeviceAshTest); + DISALLOW_COPY_AND_ASSIGN(DesktopCaptureDeviceAuraTest); }; -TEST_F(DesktopCaptureDeviceAshTest, StartAndStop) { +TEST_F(DesktopCaptureDeviceAuraTest, StartAndStop) { DesktopMediaID source(DesktopMediaID::TYPE_SCREEN, 0); scoped_ptr<media::VideoCaptureDevice> capture_device( - DesktopCaptureDeviceAsh::Create(source)); + DesktopCaptureDeviceAura::Create(source)); scoped_ptr<MockDeviceClient> client(new MockDeviceClient()); EXPECT_CALL(*client, OnError()).Times(0); diff --git a/content/browser/renderer_host/media/device_request_message_filter.cc b/content/browser/renderer_host/media/device_request_message_filter.cc index 5eaf7c6bb3..a1801e7cc0 100644 --- a/content/browser/renderer_host/media/device_request_message_filter.cc +++ b/content/browser/renderer_host/media/device_request_message_filter.cc @@ -7,7 +7,6 @@ #include "content/browser/browser_main_loop.h" #include "content/browser/renderer_host/media/media_stream_manager.h" #include "content/common/media/media_stream_messages.h" -#include "content/public/browser/media_device_id.h" #include "content/public/browser/resource_context.h" // Clears the MediaStreamDevice.name from all devices in |device_list|. @@ -97,12 +96,12 @@ void DeviceRequestMessageFilter::DevicesEnumerated( if (label == request_it->audio_devices_label) { request_it->has_audio_returned = true; DCHECK(audio_devices->empty()); - HmacDeviceIds(request_it->origin, new_devices, audio_devices); + *audio_devices = new_devices; } else { DCHECK(label == request_it->video_devices_label); request_it->has_video_returned = true; DCHECK(video_devices->empty()); - HmacDeviceIds(request_it->origin, new_devices, video_devices); + *video_devices = new_devices; } if (!request_it->has_audio_returned || !request_it->has_video_returned) { @@ -151,33 +150,18 @@ void DeviceRequestMessageFilter::OnChannelClosing() { requests_.clear(); } -void DeviceRequestMessageFilter::HmacDeviceIds( - const GURL& origin, - const StreamDeviceInfoArray& raw_devices, - StreamDeviceInfoArray* devices_with_guids) { - DCHECK(devices_with_guids); - - // Replace raw ids with hmac'd ids before returning to renderer process. - for (StreamDeviceInfoArray::const_iterator device_itr = raw_devices.begin(); - device_itr != raw_devices.end(); - ++device_itr) { - StreamDeviceInfo current_device_info = *device_itr; - current_device_info.device.id = - content::GetHMACForMediaDeviceID(origin, device_itr->device.id); - devices_with_guids->push_back(current_device_info); - } -} - void DeviceRequestMessageFilter::OnGetSources(int request_id, const GURL& security_origin) { // Make request to get audio devices. const std::string& audio_label = media_stream_manager_->EnumerateDevices( - this, -1, -1, -1, MEDIA_DEVICE_AUDIO_CAPTURE, security_origin); + this, -1, -1, resource_context_, -1, MEDIA_DEVICE_AUDIO_CAPTURE, + security_origin); DCHECK(!audio_label.empty()); // Make request for video devices. const std::string& video_label = media_stream_manager_->EnumerateDevices( - this, -1, -1, -1, MEDIA_DEVICE_VIDEO_CAPTURE, security_origin); + this, -1, -1, resource_context_, -1, MEDIA_DEVICE_VIDEO_CAPTURE, + security_origin); DCHECK(!video_label.empty()); requests_.push_back(DeviceRequest( diff --git a/content/browser/renderer_host/media/device_request_message_filter.h b/content/browser/renderer_host/media/device_request_message_filter.h index edae564d10..4ea2c67a88 100644 --- a/content/browser/renderer_host/media/device_request_message_filter.h +++ b/content/browser/renderer_host/media/device_request_message_filter.h @@ -53,9 +53,6 @@ class CONTENT_EXPORT DeviceRequestMessageFilter : public BrowserMessageFilter, private: void OnGetSources(int request_id, const GURL& security_origin); - void HmacDeviceIds(const GURL& origin, - const StreamDeviceInfoArray& raw_devices, - StreamDeviceInfoArray* devices_with_guids); // Owned by ProfileIOData which is guaranteed to outlive DRMF. ResourceContext* resource_context_; diff --git a/content/browser/renderer_host/media/device_request_message_filter_unittest.cc b/content/browser/renderer_host/media/device_request_message_filter_unittest.cc index c3ffe9576f..16435dcf2a 100644 --- a/content/browser/renderer_host/media/device_request_message_filter_unittest.cc +++ b/content/browser/renderer_host/media/device_request_message_filter_unittest.cc @@ -6,7 +6,6 @@ #include "content/browser/renderer_host/media/device_request_message_filter.h" #include "content/browser/renderer_host/media/media_stream_manager.h" #include "content/common/media/media_stream_messages.h" -#include "content/public/browser/media_device_id.h" #include "content/public/test/mock_resource_context.h" #include "content/public/test/test_browser_thread.h" #include "testing/gmock/include/gmock/gmock.h" @@ -26,10 +25,11 @@ class MockMediaStreamManager : public MediaStreamManager { virtual ~MockMediaStreamManager() {} - MOCK_METHOD6(EnumerateDevices, + MOCK_METHOD7(EnumerateDevices, std::string(MediaStreamRequester* requester, int render_process_id, int render_view_id, + ResourceContext* rc, int page_request_id, MediaStreamType type, const GURL& security_origin)); @@ -38,6 +38,7 @@ class MockMediaStreamManager : public MediaStreamManager { std::string DoEnumerateDevices(MediaStreamRequester* requester, int render_process_id, int render_view_id, + ResourceContext* rc, int page_request_id, MediaStreamType type, const GURL& security_origin) { @@ -94,10 +95,10 @@ class DeviceRequestMessageFilterTest : public testing::Test { AddVideoDevices(number_video_devices); GURL origin("https://test.com"); EXPECT_CALL(*media_stream_manager_, - EnumerateDevices(_, _, _, _, MEDIA_DEVICE_AUDIO_CAPTURE, _)) + EnumerateDevices(_, _, _, _, _, MEDIA_DEVICE_AUDIO_CAPTURE, _)) .Times(1); EXPECT_CALL(*media_stream_manager_, - EnumerateDevices(_, _, _, _, MEDIA_DEVICE_VIDEO_CAPTURE, _)) + EnumerateDevices(_, _, _, _, _, MEDIA_DEVICE_VIDEO_CAPTURE, _)) .Times(1); // Send message to get devices. Should trigger 2 EnumerateDevice() requests. const int kRequestId = 123; @@ -118,11 +119,6 @@ class DeviceRequestMessageFilterTest : public testing::Test { host_->requested_devices().size()); EXPECT_EQ(kRequestId, host_->received_id()); - // Check to make sure no devices have raw ids. - EXPECT_FALSE(DoesContainRawIds(host_->requested_devices())); - - // Check to make sure every GUID produced matches a raw device id. - EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->requested_devices(), origin)); } bool AreLabelsPresent(MediaStreamType type) { @@ -143,7 +139,7 @@ class DeviceRequestMessageFilterTest : public testing::Test { new TestBrowserThread(BrowserThread::IO, message_loop_.get())); media_stream_manager_.reset(new MockMediaStreamManager()); - ON_CALL(*media_stream_manager_, EnumerateDevices(_, _, _, _, _, _)) + ON_CALL(*media_stream_manager_, EnumerateDevices(_, _, _, _, _, _, _)) .WillByDefault(Invoke(media_stream_manager_.get(), &MockMediaStreamManager::DoEnumerateDevices)); @@ -199,48 +195,6 @@ class DeviceRequestMessageFilterTest : public testing::Test { host_->DevicesEnumerated(kVideoLabel, physical_video_devices_); } - bool DoesContainRawIds(const StreamDeviceInfoArray& devices) { - for (size_t i = 0; i < devices.size(); i++) { - for (size_t j = 0; j < physical_audio_devices_.size(); ++j) { - if (physical_audio_devices_[j].device.id == devices[i].device.id) - return true; - } - for (size_t j = 0; j < physical_video_devices_.size(); ++j) { - if (physical_video_devices_[j].device.id == devices[i].device.id) - return true; - } - } - return false; - } - - bool DoesEveryDeviceMapToRawId(const StreamDeviceInfoArray& devices, - const GURL& origin) { - for (size_t i = 0; i < devices.size(); i++) { - bool found_match = false; - for (size_t j = 0; j < physical_audio_devices_.size(); ++j) { - if (content::DoesMediaDeviceIDMatchHMAC( - origin, - devices[i].device.id, - physical_audio_devices_[j].device.id)) { - EXPECT_FALSE(found_match); - found_match = true; - } - } - for (size_t j = 0; j < physical_video_devices_.size(); ++j) { - if (content::DoesMediaDeviceIDMatchHMAC( - origin, - devices[i].device.id, - physical_video_devices_[j].device.id)) { - EXPECT_FALSE(found_match); - found_match = true; - } - } - if (!found_match) - return false; - } - return true; - } - int next_device_id_; }; diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc index ef91e0f36f..5ce805e643 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc @@ -14,8 +14,10 @@ namespace content { MediaStreamDispatcherHost::MediaStreamDispatcherHost( int render_process_id, + ResourceContext* resource_context, MediaStreamManager* media_stream_manager) : render_process_id_(render_process_id), + resource_context_(resource_context), media_stream_manager_(media_stream_manager) { } @@ -70,7 +72,7 @@ void MediaStreamDispatcherHost::DevicesEnumerated( StreamRequest request = it->second; Send(new MediaStreamMsg_DevicesEnumerated( - request.render_view_id, request.page_request_id, label, devices)); + request.render_view_id, request.page_request_id, devices)); } void MediaStreamDispatcherHost::DeviceOpened( @@ -80,16 +82,6 @@ void MediaStreamDispatcherHost::DeviceOpened( DVLOG(1) << "MediaStreamDispatcherHost::DeviceOpened(" << ", {label = " << label << "})"; - // TODO(perkj): Checking for StreamRequest here is a temporary fix to avoid - // an Assert in PopRequest. Remove this once the real problem is solved. - // crbug/316396. - StreamMap::iterator it = streams_.find(label); - DCHECK(it != streams_.end()); - if (it == streams_.end()) { - LOG(ERROR) << "DeviceOpened but there is no request for the device."; - return; - } - StreamRequest request = PopRequest(label); Send(new MediaStreamMsg_DeviceOpened( @@ -145,14 +137,11 @@ void MediaStreamDispatcherHost::OnGenerateStream( << security_origin.spec() << ")"; const std::string& label = media_stream_manager_->GenerateStream( - this, render_process_id_, render_view_id, page_request_id, + this, render_process_id_, render_view_id, resource_context_, + page_request_id, components, security_origin); - if (label.empty()) { - Send(new MediaStreamMsg_StreamGenerationFailed(render_view_id, - page_request_id)); - } else { - StoreRequest(render_view_id, page_request_id, label); - } + CHECK(!label.empty()); + StoreRequest(render_view_id, page_request_id, label); } void MediaStreamDispatcherHost::OnCancelGenerateStream(int render_view_id, @@ -194,25 +183,20 @@ void MediaStreamDispatcherHost::OnEnumerateDevices( << security_origin.spec() << ")"; const std::string& label = media_stream_manager_->EnumerateDevices( - this, render_process_id_, render_view_id, page_request_id, - type, security_origin); + this, render_process_id_, render_view_id, resource_context_, + page_request_id, type, security_origin); StoreRequest(render_view_id, page_request_id, label); } void MediaStreamDispatcherHost::OnCancelEnumerateDevices( int render_view_id, - const std::string& label) { + int page_request_id) { DVLOG(1) << "MediaStreamDispatcherHost::OnCancelEnumerateDevices(" << render_view_id << ", " - << label << ")"; + << page_request_id << ")"; - if (streams_.find(label) == streams_.end()) { - // According to the comments in MediaStreamDispatcher::OnDevicesEnumerated, - // OnCancelEnumerateDevices can be called several times with the same label. - DVLOG(1) << "Enumeration request with label " << label - << "does not exist."; - return; - } + std::string label; + GetRequestLabel(render_view_id, page_request_id, &label); media_stream_manager_->CancelRequest(label); PopRequest(label); } @@ -231,8 +215,8 @@ void MediaStreamDispatcherHost::OnOpenDevice( << security_origin.spec() << ")"; const std::string& label = media_stream_manager_->OpenDevice( - this, render_process_id_, render_view_id, page_request_id, - device_id, type, security_origin); + this, render_process_id_, render_view_id, resource_context_, + page_request_id, device_id, type, security_origin); StoreRequest(render_view_id, page_request_id, label); } @@ -264,4 +248,17 @@ MediaStreamDispatcherHost::PopRequest(const std::string& label) { return request; } +void MediaStreamDispatcherHost::GetRequestLabel( + int render_view_id, int page_request_id, std::string* label) { + for (StreamMap::const_iterator it = streams_.begin(); it != streams_.end(); + ++it) { + if (it->second.render_view_id == render_view_id && + it->second.page_request_id == page_request_id) { + *label = it->first; + return; + } + } + NOTREACHED(); +} + } // namespace content diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.h b/content/browser/renderer_host/media/media_stream_dispatcher_host.h index 7649bb61b8..1dd72dc577 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host.h +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.h @@ -14,8 +14,10 @@ #include "content/common/content_export.h" #include "content/common/media/media_stream_options.h" #include "content/public/browser/browser_message_filter.h" +#include "content/public/browser/resource_context.h" namespace content { + class MediaStreamManager; // MediaStreamDispatcherHost is a delegate for Media Stream API messages used by @@ -25,6 +27,7 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter, public MediaStreamRequester { public: MediaStreamDispatcherHost(int render_process_id, + ResourceContext* resource_context, MediaStreamManager* media_stream_manager); // MediaStreamRequester implementation. @@ -79,7 +82,7 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter, const GURL& security_origin); void OnCancelEnumerateDevices(int render_view_id, - const std::string& label); + int page_request_id); void OnOpenDevice(int render_view_id, int page_request_id, @@ -94,8 +97,12 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter, int page_request_id, const std::string& label); StreamRequest PopRequest(const std::string& label); + void GetRequestLabel(int render_view_id, + int page_request_id, + std::string* label); int render_process_id_; + ResourceContext* resource_context_; MediaStreamManager* media_stream_manager_; // Active requests. When the MediaStreamManager responds to a a request the diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc index e17302ff04..0b0ef5c907 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc @@ -15,12 +15,14 @@ #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" #include "content/common/media/media_stream_messages.h" #include "content/common/media/media_stream_options.h" +#include "content/public/browser/media_device_id.h" #include "content/public/test/mock_resource_context.h" +#include "content/public/test/test_browser_context.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/test/test_content_browser_client.h" #include "content/test/test_content_client.h" #include "ipc/ipc_message_macros.h" -#include "media/audio/audio_manager.h" +#include "media/audio/mock_audio_manager.h" #include "media/video/capture/fake_video_capture_device.h" #include "net/url_request/url_request_context.h" #include "testing/gmock/include/gmock/gmock.h" @@ -42,9 +44,10 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, public TestContentBrowserClient { public: MockMediaStreamDispatcherHost( + ResourceContext* resource_context, const scoped_refptr<base::MessageLoopProxy>& message_loop, MediaStreamManager* manager) - : MediaStreamDispatcherHost(kProcessId, manager), + : MediaStreamDispatcherHost(kProcessId, resource_context, manager), message_loop_(message_loop) {} // A list of mock methods. @@ -59,10 +62,11 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, void OnGenerateStream(int render_view_id, int page_request_id, const StreamOptions& components, + const GURL& security_origin, const base::Closure& quit_closure) { quit_closures_.push(quit_closure); MediaStreamDispatcherHost::OnGenerateStream( - render_view_id, page_request_id, components, GURL()); + render_view_id, page_request_id, components, security_origin); } void OnStopStreamDevice(int render_view_id, @@ -74,25 +78,28 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, int page_request_id, const std::string& device_id, MediaStreamType type, + const GURL& security_origin, const base::Closure& quit_closure) { quit_closures_.push(quit_closure); MediaStreamDispatcherHost::OnOpenDevice( - render_view_id, page_request_id, device_id, type, GURL()); + render_view_id, page_request_id, device_id, type, security_origin); } - bool FindExistingRequestedDeviceInfo(const std::string& device_id, - MediaStreamRequestType request_type, - StreamDeviceInfo* device_info) { - MediaRequestState request_state; - return media_stream_manager_->FindExistingRequestedDeviceInfo( - kProcessId, kRenderId, request_type, device_id, device_info, - &request_state); + void OnEnumerateDevices(int render_view_id, + int page_request_id, + MediaStreamType type, + const GURL& security_origin, + const base::Closure& quit_closure) { + quit_closures_.push(quit_closure); + MediaStreamDispatcherHost::OnEnumerateDevices( + render_view_id, page_request_id, type, security_origin); } std::string label_; StreamDeviceInfoArray audio_devices_; StreamDeviceInfoArray video_devices_; StreamDeviceInfo opened_device_; + StreamDeviceInfoArray enumerated_devices_; private: virtual ~MockMediaStreamDispatcherHost() {} @@ -112,6 +119,8 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, OnStreamGenerationFailed) IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceStopped, OnDeviceStopped) IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened, OnDeviceOpened) + IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerated, + OnDevicesEnumerated) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() EXPECT_TRUE(handled); @@ -153,14 +162,12 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, void OnDeviceStopped(const IPC::Message& msg, const std::string& label, const content::StreamDeviceInfo& device) { + if (IsVideoMediaType(device.device.type)) + EXPECT_TRUE(StreamDeviceInfo::IsEqual(device, video_devices_[0])); + if (IsAudioMediaType(device.device.type)) + EXPECT_TRUE(StreamDeviceInfo::IsEqual(device, audio_devices_[0])); + OnDeviceStopped(msg.routing_id()); - // Notify that the event have occurred. - if (!quit_closures_.empty()) { - base::Closure quit_closure = quit_closures_.front(); - quit_closures_.pop(); - message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure)); - } - label_ = ""; } void OnDeviceOpened(const IPC::Message& msg, @@ -174,6 +181,15 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, opened_device_ = device; } + void OnDevicesEnumerated(const IPC::Message& msg, + int request_id, + const StreamDeviceInfoArray& devices) { + base::Closure quit_closure = quit_closures_.front(); + quit_closures_.pop(); + message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure)); + enumerated_devices_ = devices; + } + scoped_refptr<base::MessageLoopProxy> message_loop_; std::queue<base::Closure> quit_closures_; @@ -188,15 +204,19 @@ class MediaStreamDispatcherHostTest : public testing::Test { public: MediaStreamDispatcherHostTest() : old_browser_client_(NULL), - thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) { + thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), + origin_("https://test.com") { + audio_manager_.reset( + new media::MockAudioManager(base::MessageLoopProxy::current())); // Create our own MediaStreamManager. - audio_manager_.reset(media::AudioManager::Create()); media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); // Make sure we use fake devices to avoid long delays. media_stream_manager_->UseFakeDevice(); - host_ = new MockMediaStreamDispatcherHost(base::MessageLoopProxy::current(), - media_stream_manager_.get()); + host_ = new MockMediaStreamDispatcherHost( + browser_context_.GetResourceContext(), + base::MessageLoopProxy::current(), + media_stream_manager_.get()); // Use the fake content client and browser. content_client_.reset(new TestContentClient()); @@ -205,10 +225,14 @@ class MediaStreamDispatcherHostTest : public testing::Test { } virtual ~MediaStreamDispatcherHostTest() { - // Recover the old browser client and content client. - SetBrowserClientForTesting(old_browser_client_); - content_client_.reset(); - media_stream_manager_->WillDestroyCurrentMessageLoop(); + } + + virtual void SetUp() OVERRIDE { + media::FakeVideoCaptureDevice::GetDeviceNames(&physical_video_devices_); + ASSERT_GT(physical_video_devices_.size(), 0u); + + audio_manager_->GetAudioInputDeviceNames(&physical_audio_devices_); + ASSERT_GT(physical_audio_devices_.size(), 0u); } virtual void TearDown() OVERRIDE { @@ -229,9 +253,33 @@ class MediaStreamDispatcherHostTest : public testing::Test { int page_request_id, const StreamOptions& options) { base::RunLoop run_loop; - host_->OnGenerateStream(render_view_id, page_request_id, options, + int expected_audio_array_size = + (options.audio_type != MEDIA_NO_SERVICE && + physical_audio_devices_.size() > 0) ? 1 : 0; + int expected_video_array_size = + (options.video_type != MEDIA_NO_SERVICE && + physical_video_devices_.size() > 0) ? 1 : 0; + EXPECT_CALL(*host_.get(), OnStreamGenerated(render_view_id, page_request_id, + expected_audio_array_size, + expected_video_array_size)); + host_->OnGenerateStream(render_view_id, page_request_id, options, origin_, run_loop.QuitClosure()); run_loop.Run(); + EXPECT_FALSE(DoesContainRawIds(host_->audio_devices_)); + EXPECT_FALSE(DoesContainRawIds(host_->video_devices_)); + EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->audio_devices_, origin_)); + EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->video_devices_, origin_)); + } + + void GenerateStreamAndWaitForFailure(int render_view_id, + int page_request_id, + const StreamOptions& options) { + base::RunLoop run_loop; + EXPECT_CALL(*host_.get(), + OnStreamGenerationFailed(render_view_id, page_request_id)); + host_->OnGenerateStream(render_view_id, page_request_id, options, origin_, + run_loop.QuitClosure()); + run_loop.Run(); } void OpenVideoDeviceAndWaitForResult(int render_view_id, @@ -239,9 +287,75 @@ class MediaStreamDispatcherHostTest : public testing::Test { const std::string& device_id) { base::RunLoop run_loop; host_->OnOpenDevice(render_view_id, page_request_id, device_id, - MEDIA_DEVICE_VIDEO_CAPTURE, + MEDIA_DEVICE_VIDEO_CAPTURE, origin_, run_loop.QuitClosure()); run_loop.Run(); + EXPECT_FALSE(DoesContainRawIds(host_->video_devices_)); + EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->video_devices_, origin_)); + } + + void EnumerateDevicesAndWaitForResult(int render_view_id, + int page_request_id, + MediaStreamType type) { + base::RunLoop run_loop; + host_->OnEnumerateDevices(render_view_id, page_request_id, type, origin_, + run_loop.QuitClosure()); + run_loop.Run(); + ASSERT_FALSE(host_->enumerated_devices_.empty()); + EXPECT_FALSE(DoesContainRawIds(host_->enumerated_devices_)); + EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->enumerated_devices_, origin_)); + } + + bool DoesContainRawIds(const StreamDeviceInfoArray& devices) { + for (size_t i = 0; i < devices.size(); ++i) { + media::AudioDeviceNames::const_iterator audio_it = + physical_audio_devices_.begin(); + for (; audio_it != physical_audio_devices_.end(); ++audio_it) { + if (audio_it->unique_id == devices[i].device.id) + return true; + } + media::VideoCaptureDevice::Names::const_iterator video_it = + physical_video_devices_.begin(); + for (; video_it != physical_video_devices_.end(); ++video_it) { + if (video_it->id() == devices[i].device.id) + return true; + } + } + return false; + } + + bool DoesEveryDeviceMapToRawId(const StreamDeviceInfoArray& devices, + const GURL& origin) { + for (size_t i = 0; i < devices.size(); ++i) { + bool found_match = false; + media::AudioDeviceNames::const_iterator audio_it = + physical_audio_devices_.begin(); + for (; audio_it != physical_audio_devices_.end(); ++audio_it) { + if (content::DoesMediaDeviceIDMatchHMAC( + browser_context_.GetResourceContext(), + origin, + devices[i].device.id, + audio_it->unique_id)) { + EXPECT_FALSE(found_match); + found_match = true; + } + } + media::VideoCaptureDevice::Names::const_iterator video_it = + physical_video_devices_.begin(); + for (; video_it != physical_video_devices_.end(); ++video_it) { + if (content::DoesMediaDeviceIDMatchHMAC( + browser_context_.GetResourceContext(), + origin, + devices[i].device.id, + video_it->id())) { + EXPECT_FALSE(found_match); + found_match = true; + } + } + if (!found_match) + return false; + } + return true; } scoped_refptr<MockMediaStreamDispatcherHost> host_; @@ -250,19 +364,32 @@ class MediaStreamDispatcherHostTest : public testing::Test { ContentBrowserClient* old_browser_client_; scoped_ptr<ContentClient> content_client_; content::TestBrowserThreadBundle thread_bundle_; + content::TestBrowserContext browser_context_; + media::AudioDeviceNames physical_audio_devices_; + media::VideoCaptureDevice::Names physical_video_devices_; + GURL origin_; }; TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithVideoOnly) { StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE); SetupFakeUI(true); - EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1)); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); EXPECT_EQ(host_->audio_devices_.size(), 0u); EXPECT_EQ(host_->video_devices_.size(), 1u); } +TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioOnly) { + StreamOptions options(MEDIA_DEVICE_AUDIO_CAPTURE, MEDIA_NO_SERVICE); + + SetupFakeUI(true); + GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); + + EXPECT_EQ(host_->audio_devices_.size(), 1u); + EXPECT_EQ(host_->video_devices_.size(), 0u); +} + // This test generates two streams with video only using the same render view // id. The same capture device with the same device and session id is expected // to be used. @@ -271,7 +398,6 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsFromSameRenderId) { // Generate first stream. SetupFakeUI(true); - EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1)); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); // Check the latest generated stream. @@ -283,8 +409,6 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsFromSameRenderId) { // Generate second stream. SetupFakeUI(true); - EXPECT_CALL(*host_.get(), - OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1)); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId + 1, options); // Check the latest generated stream. @@ -304,7 +428,6 @@ TEST_F(MediaStreamDispatcherHostTest, // Generate first stream. SetupFakeUI(true); - EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1)); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); EXPECT_EQ(host_->audio_devices_.size(), 0u); @@ -333,7 +456,6 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) { // Generate first stream. SetupFakeUI(true); - EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1)); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); // Check the latest generated stream. @@ -345,8 +467,6 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) { // Generate second stream from another render view. SetupFakeUI(true); - EXPECT_CALL(*host_.get(), - OnStreamGenerated(kRenderId+1, kPageRequestId + 1, 0, 1)); GenerateStreamAndWaitForResult(kRenderId+1, kPageRequestId + 1, options); // Check the latest generated stream. @@ -376,41 +496,153 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithoutWaiting) { base::RunLoop run_loop1; base::RunLoop run_loop2; - host_->OnGenerateStream(kRenderId, kPageRequestId, options, + host_->OnGenerateStream(kRenderId, kPageRequestId, options, origin_, run_loop1.QuitClosure()); - host_->OnGenerateStream(kRenderId, kPageRequestId + 1, options, + host_->OnGenerateStream(kRenderId, kPageRequestId + 1, options, origin_, run_loop2.QuitClosure()); run_loop1.Run(); run_loop2.Run(); } +// Test that we can generate streams where a sourceId is specified in the +// request. +TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithSourceId) { + ASSERT_GE(physical_audio_devices_.size(), 1u); + ASSERT_GE(physical_video_devices_.size(), 1u); + + media::AudioDeviceNames::const_iterator audio_it = + physical_audio_devices_.begin(); + for (; audio_it != physical_audio_devices_.end(); ++audio_it) { + StreamOptions options(MEDIA_DEVICE_AUDIO_CAPTURE, + MEDIA_DEVICE_VIDEO_CAPTURE); + options.audio_device_id = content::GetHMACForMediaDeviceID( + browser_context_.GetResourceContext(), + origin_, + audio_it->unique_id); + ASSERT_FALSE(options.audio_device_id.empty()); + + // Generate first stream. + SetupFakeUI(true); + GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); + EXPECT_EQ(host_->audio_devices_[0].device.id, options.audio_device_id); + } + + media::VideoCaptureDevice::Names::const_iterator video_it = + physical_video_devices_.begin(); + for (; video_it != physical_video_devices_.end(); ++video_it) { + StreamOptions options(MEDIA_DEVICE_AUDIO_CAPTURE, + MEDIA_DEVICE_VIDEO_CAPTURE); + options.video_device_id = content::GetHMACForMediaDeviceID( + browser_context_.GetResourceContext(), + origin_, + video_it->id()); + ASSERT_FALSE(options.video_device_id.empty()); + + // Generate first stream. + SetupFakeUI(true); + GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); + EXPECT_EQ(host_->video_devices_[0].device.id, options.video_device_id); + } +} + +// Test that generating a stream with an invalid video source id fail. +TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithInvalidVideoSourceId) { + StreamOptions options(MEDIA_DEVICE_AUDIO_CAPTURE, + MEDIA_DEVICE_VIDEO_CAPTURE); + options.video_device_id = "invalid source id"; + + SetupFakeUI(true); + GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); + EXPECT_NE(host_->video_devices_[0].device.id, options.video_device_id); +} + +// Test that generating a stream with an invalid audio source id fail. +TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithInvalidAudioSourceId) { + StreamOptions options(MEDIA_DEVICE_AUDIO_CAPTURE, + MEDIA_DEVICE_VIDEO_CAPTURE); + options.audio_device_id = "invalid source id"; + + SetupFakeUI(true); + GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); + EXPECT_NE(host_->audio_devices_[0].device.id, options.audio_device_id); +} + +TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsNoAvailableVideoDevice) { + size_t number_of_fake_devices = physical_video_devices_.size(); + media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(0); + media::FakeVideoCaptureDevice::GetDeviceNames(&physical_video_devices_); + StreamOptions options(MEDIA_DEVICE_AUDIO_CAPTURE, MEDIA_DEVICE_VIDEO_CAPTURE); + + SetupFakeUI(true); + GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); + EXPECT_TRUE(host_->video_devices_.empty()); + + // Reset the number of fake devices for next test. + media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(number_of_fake_devices); +} + +// Test that if a OnStopStreamDevice message is received for a device that has +// been opened in a MediaStream and by pepper, the device is only stopped for +// the MediaStream. TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStream) { StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE); SetupFakeUI(true); - EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1)); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); - const std::string device_id = host_->video_devices_.front().device.id; - const int session_id = host_->video_devices_.front().session_id; - StreamDeviceInfo video_device_info; - EXPECT_TRUE(host_->FindExistingRequestedDeviceInfo(device_id, - MEDIA_GENERATE_STREAM, - &video_device_info)); - EXPECT_EQ(video_device_info.device.id, device_id); - EXPECT_EQ(video_device_info.session_id, session_id); - - OpenVideoDeviceAndWaitForResult(kRenderId, kPageRequestId, device_id); - - host_->OnStopStreamDevice(kRenderId, device_id); - - EXPECT_FALSE(host_->FindExistingRequestedDeviceInfo(device_id, - MEDIA_GENERATE_STREAM, - &video_device_info)); - EXPECT_TRUE(host_->FindExistingRequestedDeviceInfo(device_id, - MEDIA_OPEN_DEVICE, - &video_device_info)); + std::string stream_request_label = host_->label_; + StreamDeviceInfo video_device_info = host_->video_devices_.front(); + ASSERT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest( + stream_request_label).size()); + + // Open the same device by Pepper. + OpenVideoDeviceAndWaitForResult(kRenderId, kPageRequestId, + video_device_info.device.id); + std::string open_device_request_label = host_->label_; + + // Stop the device in the MediaStream. + host_->OnStopStreamDevice(kRenderId, video_device_info.device.id); + + EXPECT_EQ(0u, media_stream_manager_->GetDevicesOpenedByRequest( + stream_request_label).size()); + EXPECT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest( + open_device_request_label).size()); +} + +TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStreamAndRestart) { + StreamOptions options(MEDIA_DEVICE_AUDIO_CAPTURE, + MEDIA_DEVICE_VIDEO_CAPTURE); + + SetupFakeUI(true); + GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); + + std::string request_label1 = host_->label_; + StreamDeviceInfo video_device_info = host_->video_devices_.front(); + // Expect that 1 audio and 1 video device has been opened. + EXPECT_EQ(2u, media_stream_manager_->GetDevicesOpenedByRequest( + request_label1).size()); + + host_->OnStopStreamDevice(kRenderId, video_device_info.device.id); + EXPECT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest( + request_label1).size()); + + GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); + std::string request_label2 = host_->label_; + + StreamDeviceInfoArray request1_devices = + media_stream_manager_->GetDevicesOpenedByRequest(request_label1); + StreamDeviceInfoArray request2_devices = + media_stream_manager_->GetDevicesOpenedByRequest(request_label2); + + ASSERT_EQ(1u, request1_devices.size()); + ASSERT_EQ(2u, request2_devices.size()); + + // Test that the same audio device has been opened in both streams. + EXPECT_TRUE(StreamDeviceInfo::IsEqual(request1_devices[0], + request2_devices[0]) || + StreamDeviceInfo::IsEqual(request1_devices[0], + request2_devices[1])); } TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreamsOnChannelClosing) { @@ -421,7 +653,7 @@ TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreamsOnChannelClosing) { // Create multiple GenerateStream requests. size_t streams = 5; for (size_t i = 1; i <= streams; ++i) { - host_->OnGenerateStream(kRenderId, kPageRequestId + i, options, + host_->OnGenerateStream(kRenderId, kPageRequestId + i, options, origin_, run_loop.QuitClosure()); } @@ -437,8 +669,6 @@ TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreamsOnChannelClosing) { size_t generated_streams = 3; for (size_t i = 0; i < generated_streams; ++i) { SetupFakeUI(true); - EXPECT_CALL(*host_.get(), - OnStreamGenerated(kRenderId, kPageRequestId + i, 0, 1)); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId + i, options); } @@ -456,16 +686,48 @@ TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) { .WillOnce(SaveArg<0>(&close_callback)); media_stream_manager_->UseFakeUI(stream_ui.PassAs<FakeMediaStreamUIProxy>()); - EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1)); - EXPECT_CALL(*host_.get(), OnDeviceStopped(kRenderId)); GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); EXPECT_EQ(host_->audio_devices_.size(), 0u); EXPECT_EQ(host_->video_devices_.size(), 1u); ASSERT_FALSE(close_callback.is_null()); + EXPECT_CALL(*host_.get(), OnDeviceStopped(kRenderId)); close_callback.Run(); base::RunLoop().RunUntilIdle(); } +// Test that the dispatcher is notified if a video device that is in use is +// being unplugged. +TEST_F(MediaStreamDispatcherHostTest, VideoDeviceUnplugged) { + size_t number_of_fake_devices = physical_video_devices_.size(); + StreamOptions options(MEDIA_DEVICE_AUDIO_CAPTURE, MEDIA_DEVICE_VIDEO_CAPTURE); + SetupFakeUI(true); + GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); + EXPECT_EQ(host_->audio_devices_.size(), 1u); + EXPECT_EQ(host_->video_devices_.size(), 1u); + + media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(0); + + base::RunLoop run_loop; + EXPECT_CALL(*host_.get(), OnDeviceStopped(kRenderId)) + .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); + media_stream_manager_->OnDevicesChanged( + base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE); + + run_loop.Run(); + + media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(number_of_fake_devices); +} + +TEST_F(MediaStreamDispatcherHostTest, EnumerateAudioDevices) { + EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId, + MEDIA_DEVICE_AUDIO_CAPTURE); +} + +TEST_F(MediaStreamDispatcherHostTest, EnumerateVideoDevices) { + EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId, + MEDIA_DEVICE_VIDEO_CAPTURE); +} + }; // namespace content diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index ab09254b31..2c36f314c7 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc @@ -12,6 +12,7 @@ #include "base/compiler_specific.h" #include "base/logging.h" #include "base/rand_util.h" +#include "base/run_loop.h" #include "base/threading/thread.h" #include "content/browser/renderer_host/media/audio_input_device_manager.h" #include "content/browser/renderer_host/media/device_request_message_filter.h" @@ -63,17 +64,18 @@ static bool Requested(const MediaStreamRequest& request, request.video_type == stream_type); } -// TODO(xians): Merge DeviceRequest with MediaStreamRequest. class MediaStreamManager::DeviceRequest { public: DeviceRequest(MediaStreamRequester* requester, const MediaStreamRequest& request, int requesting_process_id, - int requesting_view_id) + int requesting_view_id, + ResourceContext* resource_context) : requester(requester), request(request), requesting_process_id(requesting_process_id), requesting_view_id(requesting_view_id), + resource_context(resource_context), state_(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_NOT_REQUESTED) { } @@ -90,15 +92,9 @@ class MediaStreamManager::DeviceRequest { state_[stream_type] = new_state; } - if (request.video_type != MEDIA_TAB_VIDEO_CAPTURE && - request.audio_type != MEDIA_TAB_AUDIO_CAPTURE && - new_state != MEDIA_REQUEST_STATE_CLOSING) { - return; - } - MediaObserver* media_observer = GetContentClient()->browser()->GetMediaObserver(); - if (media_observer == NULL) + if (!media_observer) return; // If we appended a device_id scheme, we want to remove it when notifying @@ -133,6 +129,8 @@ class MediaStreamManager::DeviceRequest { // specifies the target renderer from which audio and video is captured. const int requesting_view_id; + ResourceContext* resource_context; + StreamDeviceInfoArray devices; // Callback to the requester which audio/video devices have been selected. @@ -181,6 +179,7 @@ MediaStreamManager::MediaStreamManager(media::AudioManager* audio_manager) } MediaStreamManager::~MediaStreamManager() { + DVLOG(1) << "~MediaStreamManager"; DCHECK(requests_.empty()); DCHECK(!device_thread_.get()); } @@ -207,28 +206,38 @@ std::string MediaStreamManager::MakeMediaAccessRequest( DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); // Create a new request based on options. MediaStreamRequest stream_request( - render_process_id, render_view_id, page_request_id, std::string(), + render_process_id, render_view_id, page_request_id, security_origin, MEDIA_DEVICE_ACCESS, std::string(), std::string(), options.audio_type, options.video_type); + // TODO(perkj): The argument list with NULL parameters to DeviceRequest + // suggests that this is the wrong design. Can this be refactored? DeviceRequest* request = new DeviceRequest(NULL, stream_request, - render_process_id, render_view_id); + render_process_id, render_view_id, + NULL); const std::string& label = AddRequest(request); request->callback = callback; - - HandleRequest(label); - + // Post a task and handle the request asynchronously. The reason is that the + // requester won't have a label for the request until this function returns + // and thus can not handle a response. Using base::Unretained is safe since + // MediaStreamManager is deleted on the UI thread, after the IO thread has + // been stopped. + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&MediaStreamManager::SetupRequest, + base::Unretained(this), label)); return label; } -std::string MediaStreamManager::GenerateStream( - MediaStreamRequester* requester, - int render_process_id, - int render_view_id, - int page_request_id, - const StreamOptions& options, - const GURL& security_origin) { +std::string MediaStreamManager::GenerateStream(MediaStreamRequester* requester, + int render_process_id, + int render_view_id, + ResourceContext* rc, + int page_request_id, + const StreamOptions& options, + const GURL& security_origin) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DVLOG(1) << "GenerateStream()"; if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kUseFakeDeviceForMediaStream)) { UseFakeDevice(); @@ -238,101 +247,51 @@ std::string MediaStreamManager::GenerateStream( UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy>()); } - int target_render_process_id = render_process_id; - int target_render_view_id = render_view_id; - std::string tab_capture_device_id; - - // Customize options for a WebContents based capture. - if (options.audio_type == MEDIA_TAB_AUDIO_CAPTURE || - options.video_type == MEDIA_TAB_VIDEO_CAPTURE) { - // TODO(justinlin): Can't plumb audio mirroring using stream type right - // now, so plumbing by device_id. Will revisit once it's refactored. - // http://crbug.com/163100 - tab_capture_device_id = - WebContentsCaptureUtil::AppendWebContentsDeviceScheme( - !options.video_device_id.empty() ? - options.video_device_id : options.audio_device_id); - - bool has_valid_device_id = WebContentsCaptureUtil::ExtractTabCaptureTarget( - tab_capture_device_id, &target_render_process_id, - &target_render_view_id); - if (!has_valid_device_id || - (options.audio_type != MEDIA_TAB_AUDIO_CAPTURE && - options.audio_type != MEDIA_NO_SERVICE) || - (options.video_type != MEDIA_TAB_VIDEO_CAPTURE && - options.video_type != MEDIA_NO_SERVICE)) { - LOG(ERROR) << "Invalid request."; - return std::string(); - } - } - - std::string translated_audio_device_id; - std::string translated_video_device_id; - if (options.audio_type == MEDIA_DEVICE_AUDIO_CAPTURE) { - bool found_match = TranslateGUIDToRawId( - MEDIA_DEVICE_AUDIO_CAPTURE, security_origin, options.audio_device_id, - &translated_audio_device_id); - DCHECK(found_match || translated_audio_device_id.empty()); - } - - if (options.video_type == MEDIA_DEVICE_VIDEO_CAPTURE) { - bool found_match = TranslateGUIDToRawId( - MEDIA_DEVICE_VIDEO_CAPTURE, security_origin, options.video_device_id, - &translated_video_device_id); - DCHECK(found_match || translated_video_device_id.empty()); - } - - if (options.video_type == MEDIA_DESKTOP_VIDEO_CAPTURE || - options.audio_type == MEDIA_LOOPBACK_AUDIO_CAPTURE) { - // For screen capture we only support two valid combinations: - // (1) screen video capture only, or - // (2) screen video capture with loopback audio capture. - if (options.video_type != MEDIA_DESKTOP_VIDEO_CAPTURE || - (options.audio_type != MEDIA_NO_SERVICE && - options.audio_type != MEDIA_LOOPBACK_AUDIO_CAPTURE)) { - // TODO(sergeyu): Surface error message to the calling JS code. - LOG(ERROR) << "Invalid screen capture request."; - return std::string(); - } - translated_video_device_id = options.video_device_id; - } - // Create a new request based on options. MediaStreamRequest stream_request( - target_render_process_id, target_render_view_id, page_request_id, - tab_capture_device_id, security_origin, MEDIA_GENERATE_STREAM, - translated_audio_device_id, translated_video_device_id, + render_process_id, render_view_id, page_request_id, + security_origin, MEDIA_GENERATE_STREAM, + options.audio_device_id, options.video_device_id, options.audio_type, options.video_type); DeviceRequest* request = new DeviceRequest(requester, stream_request, render_process_id, - render_view_id); + render_view_id, + rc); const std::string& label = AddRequest(request); - HandleRequest(label); + + // Post a task and handle the request asynchronously. The reason is that the + // requester won't have a label for the request until this function returns + // and thus can not handle a response. Using base::Unretained is safe since + // MediaStreamManager is deleted on the UI thread, after the IO thread has + // been stopped. + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&MediaStreamManager::SetupRequest, + base::Unretained(this), label)); return label; } void MediaStreamManager::CancelRequest(const std::string& label) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); DVLOG(1) << "CancelRequest({label = " << label << "})"; - DeviceRequests::iterator request_it = requests_.find(label); - if (request_it == requests_.end()) { - NOTREACHED(); + DeviceRequest* request = FindRequest(label); + if (!request) { + // The request does not exist. + LOG(ERROR) << "The request with label = " << label << " does not exist."; return; } - scoped_ptr<DeviceRequest> request(request_it->second); - RemoveRequest(request_it); - if (request->request.request_type == MEDIA_ENUMERATE_DEVICES) { + DeleteRequest(label); return; } // This is a request for opening one or more devices. for (StreamDeviceInfoArray::iterator device_it = request->devices.begin(); - device_it != request->devices.end(); ++device_it) { + device_it != request->devices.end(); ++device_it) { + MediaRequestState state = request->state(device_it->device.type); // If we have not yet requested the device to be opened - just ignore it. - if (request->state(device_it->device.type) != MEDIA_REQUEST_STATE_OPENING - && - request->state(device_it->device.type) != MEDIA_REQUEST_STATE_DONE) { + if (state != MEDIA_REQUEST_STATE_OPENING && + state != MEDIA_REQUEST_STATE_DONE) { continue; } // Stop the opening/opened devices of the requests. @@ -341,6 +300,7 @@ void MediaStreamManager::CancelRequest(const std::string& label) { // Cancel the request if still pending at UI side. request->SetState(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_CLOSING); + DeleteRequest(label); } void MediaStreamManager::CancelAllRequests(int render_process_id) { @@ -363,7 +323,6 @@ void MediaStreamManager::StopStreamDevice(int render_process_id, DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); DVLOG(1) << "StopStreamDevice({render_view_id = " << render_view_id << "} " << ", {device_id = " << device_id << "})"; - // Find the first request for this |render_process_id| and |render_view_id| // of type MEDIA_GENERATE_STREAM that has requested to use |device_id| and // stop it. @@ -409,10 +368,9 @@ void MediaStreamManager::StopDevice(MediaStreamType type, int session_id) { } // If this request doesn't have any active devices, remove the request. if (devices->empty()) { - DeviceRequests::iterator del_itor(request_it); + std::string label = request_it->first; ++request_it; - scoped_ptr<DeviceRequest> request(del_itor->second); - RemoveRequest(del_itor); + DeleteRequest(label); } else { ++request_it; } @@ -444,67 +402,81 @@ std::string MediaStreamManager::EnumerateDevices( MediaStreamRequester* requester, int render_process_id, int render_view_id, + ResourceContext* rc, int page_request_id, MediaStreamType type, const GURL& security_origin) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK(requester); DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE || type == MEDIA_DEVICE_VIDEO_CAPTURE); - // When the requester is NULL, the request is made by the UI to ensure MSM - // starts monitoring devices. - if (!requester) { - if (!monitoring_started_) - StartMonitoring(); - - return std::string(); - } - // Create a new request. StreamOptions options; - EnumerationCache* cache = NULL; if (type == MEDIA_DEVICE_AUDIO_CAPTURE) { options.audio_type = type; - cache = &audio_enumeration_cache_; } else if (type == MEDIA_DEVICE_VIDEO_CAPTURE) { options.video_type = type; - cache = &video_enumeration_cache_; } else { NOTREACHED(); return std::string(); } MediaStreamRequest stream_request( - render_process_id, render_view_id, page_request_id, std::string(), + render_process_id, render_view_id, page_request_id, security_origin, MEDIA_ENUMERATE_DEVICES, std::string(), std::string(), options.audio_type, options.video_type); DeviceRequest* request = new DeviceRequest(requester, stream_request, - render_process_id, - render_view_id); + render_process_id, render_view_id, + rc); const std::string& label = AddRequest(request); + // Post a task and handle the request asynchronously. The reason is that the + // requester won't have a label for the request until this function returns + // and thus can not handle a response. Using base::Unretained is safe since + // MediaStreamManager is deleted on the UI thread, after the IO thread has + // been stopped. + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&MediaStreamManager::DoEnumerateDevices, + base::Unretained(this), label)); + + return label; +} + +void MediaStreamManager::DoEnumerateDevices(const std::string& label) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DeviceRequest* request = FindRequest(label); + if (!request) + return; // This can happen if the request has been canceled. + + MediaStreamType type; + EnumerationCache* cache; + if (request->request.audio_type == MEDIA_DEVICE_AUDIO_CAPTURE) { + DCHECK_EQ(MEDIA_NO_SERVICE, request->request.video_type); + type = MEDIA_DEVICE_AUDIO_CAPTURE; + cache = &audio_enumeration_cache_; + } else { + DCHECK_EQ(MEDIA_DEVICE_VIDEO_CAPTURE, request->request.video_type); + type = MEDIA_DEVICE_VIDEO_CAPTURE; + cache = &video_enumeration_cache_; + } if (cache->valid) { // Cached device list of this type exists. Just send it out. request->SetState(type, MEDIA_REQUEST_STATE_REQUESTED); - - // Need to post a task since the requester won't have label till - // this function returns. - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&MediaStreamManager::SendCachedDeviceList, - base::Unretained(this), cache, label)); + request->devices = cache->devices; + FinalizeEnumerateDevices(label, request); } else { StartEnumeration(request); } - DVLOG(1) << "Enumerate Devices ({label = " << label << "})"; - return label; } std::string MediaStreamManager::OpenDevice( MediaStreamRequester* requester, int render_process_id, int render_view_id, + ResourceContext* rc, int page_request_id, const std::string& device_id, MediaStreamType type, @@ -527,29 +499,31 @@ std::string MediaStreamManager::OpenDevice( } MediaStreamRequest stream_request( - render_process_id, render_view_id, page_request_id, std::string(), + render_process_id, render_view_id, page_request_id, security_origin, MEDIA_OPEN_DEVICE, options.audio_device_id, options.video_device_id, options.audio_type, options.video_type); DeviceRequest* request = new DeviceRequest(requester, stream_request, - render_process_id, - render_view_id); + render_process_id, render_view_id, + rc); const std::string& label = AddRequest(request); - StartEnumeration(request); + // Post a task and handle the request asynchronously. The reason is that the + // requester won't have a label for the request until this function returns + // and thus can not handle a response. Using base::Unretained is safe since + // MediaStreamManager is deleted on the UI thread, after the IO thread has + // been stopped. + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&MediaStreamManager::SetupRequest, + base::Unretained(this), label)); DVLOG(1) << "OpenDevice ({label = " << label << "})"; return label; } -void MediaStreamManager::SendCachedDeviceList( - EnumerationCache* cache, - const std::string& label) { +void MediaStreamManager::EnsureDeviceMonitorStarted() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - if (cache->valid) { - DeviceRequests::iterator it = requests_.find(label); - if (it != requests_.end()) { - it->second->requester->DevicesEnumerated(label, cache->devices); - } - } + if (!monitoring_started_) + StartMonitoring(); } void MediaStreamManager::StopRemovedDevices( @@ -585,7 +559,12 @@ void MediaStreamManager::StopRemovedDevice(const MediaStreamDevice& device) { for (StreamDeviceInfoArray::const_iterator device_it = request->devices.begin(); device_it != request->devices.end(); ++device_it) { - if (device_it->device.IsEqual(device)) { + std::string source_id = content::GetHMACForMediaDeviceID( + request->resource_context, + request->request.security_origin, + device.id); + if (device_it->device.id == source_id && + device_it->device.type == device.type) { session_ids.push_back(device_it->session_id); if (it->second->requester) { it->second->requester->DeviceStopped( @@ -630,14 +609,69 @@ void MediaStreamManager::StopMonitoring() { } } -bool MediaStreamManager::TranslateGUIDToRawId(MediaStreamType stream_type, - const GURL& security_origin, - const std::string& device_guid, - std::string* raw_device_id) { +bool MediaStreamManager::TranslateRequestedSourceIdToDeviceId( + DeviceRequest* request) { + MediaStreamRequest* ms_request = &request->request; + // If a specific device has been requested we need to find the real device id. + if (ms_request->audio_type == MEDIA_DEVICE_AUDIO_CAPTURE && + !ms_request->requested_audio_device_id.empty()) { + if (!TranslateSourceIdToDeviceId(MEDIA_DEVICE_AUDIO_CAPTURE, + request->resource_context, + ms_request->security_origin, + ms_request->requested_audio_device_id, + &ms_request->requested_audio_device_id)) { + // TODO(perkj): gUM should support mandatory and optional constraints. + // Ie - if the sourceId is mandatory but it does not match - gUM should + // fail. For now we treat sourceId as an optional constraint. + LOG(WARNING) << "Requested device does not exist."; + ms_request->requested_audio_device_id = ""; + return true;; + } + } + + if (ms_request->video_type == MEDIA_DEVICE_VIDEO_CAPTURE && + !ms_request->requested_video_device_id.empty()) { + if (!TranslateSourceIdToDeviceId(MEDIA_DEVICE_VIDEO_CAPTURE, + request->resource_context, + ms_request->security_origin, + ms_request->requested_video_device_id, + &ms_request->requested_video_device_id)) { + // TODO(perkj): gUM should support mandatory and optional constraints. + // Ie - if the sourceId is mandatory but it does not match - gUM should + // fail. For now we treat sourceId as an optional constraint. + LOG(WARNING) << "Requested device does not exist."; + ms_request->requested_video_device_id = ""; + return true; + } + } + DVLOG(3) << "Requested audio device " + << ms_request->requested_audio_device_id + << "Requested video device " + << ms_request->requested_video_device_id; + return true; +} + +void MediaStreamManager::TranslateDeviceIdToSourceId( + DeviceRequest* request, + MediaStreamDevice* device) { + if (request->request.audio_type == MEDIA_DEVICE_AUDIO_CAPTURE || + request->request.video_type == MEDIA_DEVICE_VIDEO_CAPTURE) { + device->id = content::GetHMACForMediaDeviceID( + request->resource_context, + request->request.security_origin, + device->id); + } +} + +bool MediaStreamManager::TranslateSourceIdToDeviceId( + MediaStreamType stream_type, + ResourceContext* rc, + const GURL& security_origin, + const std::string& source_id, + std::string* device_id) { DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE || stream_type == MEDIA_DEVICE_VIDEO_CAPTURE); - if (device_guid.empty()) - return false; + DCHECK(!source_id.empty()); EnumerationCache* cache = stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ? @@ -650,9 +684,9 @@ bool MediaStreamManager::TranslateGUIDToRawId(MediaStreamType stream_type, for (StreamDeviceInfoArray::const_iterator it = cache->devices.begin(); it != cache->devices.end(); ++it) { - if (content::DoesMediaDeviceIDMatchHMAC( - security_origin, device_guid, it->device.id)) { - *raw_device_id = it->device.id; + if (content::DoesMediaDeviceIDMatchHMAC(rc, security_origin, source_id, + it->device.id)) { + *device_id = it->device.id; return true; } } @@ -700,13 +734,36 @@ std::string MediaStreamManager::AddRequest(DeviceRequest* request) { return unique_label; } -void MediaStreamManager::RemoveRequest(DeviceRequests::iterator it) { +MediaStreamManager::DeviceRequest* +MediaStreamManager::FindRequest(const std::string& label) const { + DeviceRequests::const_iterator request_it = requests_.find(label); + return request_it == requests_.end() ? NULL : request_it->second; +} + +void MediaStreamManager::DeleteRequest(const std::string& label) { + DeviceRequests::iterator it = requests_.find(label); + scoped_ptr<DeviceRequest> request(it->second); requests_.erase(it); } -void MediaStreamManager::PostRequestToUI(const std::string& label) { +void MediaStreamManager::PostRequestToUI(const std::string& label, + DeviceRequest* request) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - DeviceRequest* request = requests_[label]; + DVLOG(1) << "PostRequestToUI({label= " << label << "})"; + // If a specific device has been requested we need to find the real device id. + if (!TranslateRequestedSourceIdToDeviceId(request)) { + FinalizeRequestFailed(label, request); + return; + } + + const MediaStreamType audio_type = request->request.audio_type; + const MediaStreamType video_type = request->request.video_type; + + // Post the request to UI and set the state. + if (IsAudioMediaType(audio_type)) + request->SetState(audio_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL); + if (IsVideoMediaType(video_type)) + request->SetState(video_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL); if (use_fake_ui_) { if (!fake_ui_) @@ -741,9 +798,20 @@ void MediaStreamManager::PostRequestToUI(const std::string& label) { base::Unretained(this), label)); } -void MediaStreamManager::HandleRequest(const std::string& label) { +void MediaStreamManager::SetupRequest(const std::string& label) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - DeviceRequest* request = requests_[label]; + DeviceRequest* request = FindRequest(label); + if (!request) { + DVLOG(1) << "SetupRequest label " << label << " doesn't exist!!"; + return; // This can happen if the request has been canceled. + } + + if (!request->request.security_origin.is_valid()) { + LOG(ERROR) << "Invalid security origin. " + << request->request.security_origin; + FinalizeRequestFailed(label, request); + return; + } const MediaStreamType audio_type = request->request.audio_type; const MediaStreamType video_type = request->request.video_type; @@ -751,9 +819,17 @@ void MediaStreamManager::HandleRequest(const std::string& label) { bool is_web_contents_capture = audio_type == MEDIA_TAB_AUDIO_CAPTURE || video_type == MEDIA_TAB_VIDEO_CAPTURE; + if (is_web_contents_capture && !SetupTabCaptureRequest(request)) { + FinalizeRequestFailed(label, request); + return; + } bool is_screen_capture = video_type == MEDIA_DESKTOP_VIDEO_CAPTURE; + if (is_screen_capture && !SetupScreenCaptureRequest(request)) { + FinalizeRequestFailed(label, request); + return; + } if (!is_web_contents_capture && !is_screen_capture && @@ -763,38 +839,102 @@ void MediaStreamManager::HandleRequest(const std::string& label) { StartEnumeration(request); return; } + PostRequestToUI(label, request); +} - // No need to do new device enumerations, post the request to UI - // immediately. - if (IsAudioMediaType(audio_type)) - request->SetState(audio_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL); - if (IsVideoMediaType(video_type)) - request->SetState(video_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL); +bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) { + DCHECK(request->request.audio_type == MEDIA_TAB_AUDIO_CAPTURE || + request->request.video_type == MEDIA_TAB_VIDEO_CAPTURE); - PostRequestToUI(label); + MediaStreamRequest* ms_request = &request->request; + // Customize options for a WebContents based capture. + int target_render_process_id = 0; + int target_render_view_id = 0; + + // TODO(justinlin): Can't plumb audio mirroring using stream type right + // now, so plumbing by device_id. Will revisit once it's refactored. + // http://crbug.com/163100 + std::string tab_capture_device_id = + WebContentsCaptureUtil::AppendWebContentsDeviceScheme( + !ms_request->requested_video_device_id.empty() ? + ms_request->requested_video_device_id : + ms_request->requested_audio_device_id); + + bool has_valid_device_id = WebContentsCaptureUtil::ExtractTabCaptureTarget( + tab_capture_device_id, &target_render_process_id, + &target_render_view_id); + if (!has_valid_device_id || + (ms_request->audio_type != MEDIA_TAB_AUDIO_CAPTURE && + ms_request->audio_type != MEDIA_NO_SERVICE) || + (ms_request->video_type != MEDIA_TAB_VIDEO_CAPTURE && + ms_request->video_type != MEDIA_NO_SERVICE)) { + return false; + } + ms_request->tab_capture_device_id = tab_capture_device_id; + ms_request->render_process_id = target_render_process_id; + ms_request->render_view_id = target_render_view_id; + DVLOG(3) << "SetupTabCaptureRequest " + << ", {tab_capture_device_id = " << tab_capture_device_id << "}" + << ", {target_render_process_id = " << target_render_process_id + << "}" + << ", {target_render_view_id = " << target_render_view_id << "}"; + return true; +} + +bool MediaStreamManager::SetupScreenCaptureRequest(DeviceRequest* request) { + DCHECK(request->request.audio_type == MEDIA_LOOPBACK_AUDIO_CAPTURE || + request->request.video_type == MEDIA_DESKTOP_VIDEO_CAPTURE); + const MediaStreamRequest& ms_request = request->request; + + // For screen capture we only support two valid combinations: + // (1) screen video capture only, or + // (2) screen video capture with loopback audio capture. + if (ms_request.video_type != MEDIA_DESKTOP_VIDEO_CAPTURE || + (ms_request.audio_type != MEDIA_NO_SERVICE && + ms_request.audio_type != MEDIA_LOOPBACK_AUDIO_CAPTURE)) { + // TODO(sergeyu): Surface error message to the calling JS code. + LOG(ERROR) << "Invalid screen capture request."; + return false; + } + return true; +} + +StreamDeviceInfoArray MediaStreamManager::GetDevicesOpenedByRequest( + const std::string& label) const { + DeviceRequest* request = FindRequest(label); + if (!request) + return StreamDeviceInfoArray(); + return request->devices; } bool MediaStreamManager::FindExistingRequestedDeviceInfo( - int render_process_id, - int render_view_id, - MediaStreamRequestType type, - const std::string& device_id, - StreamDeviceInfo* device_info, - MediaRequestState* request_state) const { - DCHECK(device_info); - DCHECK(request_state); + const DeviceRequest& new_request, + const MediaStreamDevice& new_device_info, + StreamDeviceInfo* existing_device_info, + MediaRequestState* existing_request_state) const { + DCHECK(existing_device_info); + DCHECK(existing_request_state); + + const MediaStreamRequest& new_ms_request = new_request.request; + + std::string source_id = content::GetHMACForMediaDeviceID( + new_request.resource_context, + new_ms_request.security_origin, + new_device_info.id); + for (DeviceRequests::const_iterator it = requests_.begin(); it != requests_.end() ; ++it) { const DeviceRequest* request = it->second; - if (request->requesting_process_id ==render_process_id && - request->requesting_view_id == render_view_id && - request->request.request_type == type) { + if (request->requesting_process_id == new_request.requesting_process_id && + request->requesting_view_id == new_request.requesting_view_id && + request->request.request_type == new_ms_request.request_type) { for (StreamDeviceInfoArray::const_iterator device_it = request->devices.begin(); device_it != request->devices.end(); ++device_it) { - if (device_it->device.id == device_id) { - *device_info = *device_it; - *request_state = request->state(device_it->device.type); + if (device_it->device.id == source_id && + device_it->device.type == new_device_info.type) { + *existing_device_info = *device_it; + *existing_request_state = request->state(device_it->device.type); return true; } } @@ -803,6 +943,72 @@ bool MediaStreamManager::FindExistingRequestedDeviceInfo( return false; } +void MediaStreamManager::FinalizeGenerateStream(const std::string& label, + DeviceRequest* request) { + DVLOG(1) << "FinalizeGenerateStream label " << label; + const StreamDeviceInfoArray& requested_devices = request->devices; + + // Partition the array of devices into audio vs video. + StreamDeviceInfoArray audio_devices, video_devices; + for (StreamDeviceInfoArray::const_iterator device_it = + requested_devices.begin(); + device_it != requested_devices.end(); ++device_it) { + if (IsAudioMediaType(device_it->device.type)) { + audio_devices.push_back(*device_it); + } else if (IsVideoMediaType(device_it->device.type)) { + video_devices.push_back(*device_it); + } else { + NOTREACHED(); + } + } + + request->requester->StreamGenerated(label, audio_devices, video_devices); +} + +void MediaStreamManager::FinalizeRequestFailed( + const std::string& label, + DeviceRequest* request) { + if (request->requester) + request->requester->StreamGenerationFailed(label); + + if (request->request.request_type == MEDIA_DEVICE_ACCESS && + !request->callback.is_null()) { + request->callback.Run(MediaStreamDevices(), request->ui_proxy.Pass()); + } + + DeleteRequest(label); +} + +void MediaStreamManager::FinalizeOpenDevice(const std::string& label, + DeviceRequest* request) { + const StreamDeviceInfoArray& requested_devices = request->devices; + request->requester->DeviceOpened(label, requested_devices.front()); +} + +void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label, + DeviceRequest* request) { + if (!request->request.security_origin.is_valid()) { + request->requester->DevicesEnumerated(label, StreamDeviceInfoArray()); + return; + } + for (StreamDeviceInfoArray::iterator it = request->devices.begin(); + it != request->devices.end(); ++it) { + TranslateDeviceIdToSourceId(request, &it->device); + } + request->requester->DevicesEnumerated(label, request->devices); +} + +void MediaStreamManager::FinalizeMediaAccessRequest( + const std::string& label, + DeviceRequest* request, + const MediaStreamDevices& devices) { + if (!request->callback.is_null()) + request->callback.Run(devices, request->ui_proxy.Pass()); + + // Delete the request since it is done. + DeleteRequest(label); +} + void MediaStreamManager::InitializeDeviceManagersOnIOThread() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); if (device_thread_) @@ -858,7 +1064,6 @@ void MediaStreamManager::Opened(MediaStreamType stream_type, const StreamDeviceInfo* info = audio_input_device_manager_->GetOpenedDeviceInfoById( device_it->session_id); - DCHECK_EQ(info->device.id, device_it->device.id); device_it->device.input = info->device.input; device_it->device.matched_output = info->device.matched_output; } @@ -877,27 +1082,12 @@ void MediaStreamManager::HandleRequestDone(const std::string& label, DVLOG(1) << "HandleRequestDone(" << ", {label = " << label << "})"; - const StreamDeviceInfoArray& requested_devices = request->devices; switch (request->request.request_type) { case MEDIA_OPEN_DEVICE: - request->requester->DeviceOpened(label, requested_devices.front()); + FinalizeOpenDevice(label, request); break; case MEDIA_GENERATE_STREAM: { - // Partition the array of devices into audio vs video. - StreamDeviceInfoArray audio_devices, video_devices; - for (StreamDeviceInfoArray::const_iterator device_it = - requested_devices.begin(); - device_it != requested_devices.end(); ++device_it) { - if (IsAudioMediaType(device_it->device.type)) { - audio_devices.push_back(*device_it); - } else if (IsVideoMediaType(device_it->device.type)) { - video_devices.push_back(*device_it); - } else { - NOTREACHED(); - } - } - - request->requester->StreamGenerated(label, audio_devices, video_devices); + FinalizeGenerateStream(label, request); break; } default: @@ -940,10 +1130,7 @@ void MediaStreamManager::DevicesEnumerated( // for example, when the machine just wakes up from sleep. We set the cache // to be invalid so that the next media request will trigger the // enumeration again. See issue/317673. - if (devices.size()) - cache->valid = true; - else - cache->valid = false; + cache->valid = !devices.empty(); } if (need_update_clients && monitoring_started_) @@ -965,11 +1152,13 @@ void MediaStreamManager::DevicesEnumerated( } for (std::list<std::string>::iterator it = label_list.begin(); it != label_list.end(); ++it) { - DeviceRequest* request = requests_[*it]; + DeviceRequest* request = FindRequest(*it); switch (request->request.request_type) { case MEDIA_ENUMERATE_DEVICES: - if (need_update_clients && request->requester) - request->requester->DevicesEnumerated(*it, devices); + if (need_update_clients && request->requester) { + request->devices = devices; + FinalizeEnumerateDevices(*it, request); + } break; default: if (request->state(request->request.audio_type) == @@ -982,8 +1171,7 @@ void MediaStreamManager::DevicesEnumerated( break; } - // Post the request to UI for permission approval. - PostRequestToUI(*it); + PostRequestToUI(*it, request); break; } } @@ -999,39 +1187,24 @@ void MediaStreamManager::HandleAccessRequestResponse( DVLOG(1) << "HandleAccessRequestResponse(" << ", {label = " << label << "})"; - DeviceRequests::iterator request_it = requests_.find(label); - if (request_it == requests_.end()) { + DeviceRequest* request = FindRequest(label); + if (!request) { + // The request has been canceled before the UI returned. return; } - // Handle the case when the request was denied. - if (devices.empty()) { - // Notify the users about the request result. - scoped_ptr<DeviceRequest> request(request_it->second); - if (request->requester) - request->requester->StreamGenerationFailed(label); - - if (request->request.request_type == MEDIA_DEVICE_ACCESS && - !request->callback.is_null()) { - request->callback.Run(MediaStreamDevices(), request->ui_proxy.Pass()); - } - - RemoveRequest(request_it); + if (request->request.request_type == MEDIA_DEVICE_ACCESS) { + FinalizeMediaAccessRequest(label, request, devices); return; } - if (request_it->second->request.request_type == MEDIA_DEVICE_ACCESS) { - scoped_ptr<DeviceRequest> request(request_it->second); - if (!request->callback.is_null()) - request->callback.Run(devices, request->ui_proxy.Pass()); - - // Delete the request since it is done. - RemoveRequest(request_it); + // Handle the case when the request was denied. + if (devices.empty()) { + FinalizeRequestFailed(label, request); return; } // Process all newly-accepted devices for this request. - DeviceRequest* request = request_it->second; bool found_audio = false; bool found_video = false; for (MediaStreamDevices::const_iterator device_it = devices.begin(); @@ -1072,30 +1245,29 @@ void MediaStreamManager::HandleAccessRequestResponse( // per render view. This is so that the permission to use a device can be // revoked by a single call to StopStreamDevice regardless of how many // MediaStreams it is being used in. - if (request->request.request_type == MEDIA_GENERATE_STREAM) { MediaRequestState state; - if (FindExistingRequestedDeviceInfo(request->requesting_process_id, - request->requesting_view_id, - request->request.request_type, - device_it->id, + if (FindExistingRequestedDeviceInfo(*request, + device_info.device, &device_info, &state)) { request->devices.push_back(device_info); request->SetState(device_info.device.type, state); DVLOG(1) << "HandleAccessRequestResponse - device already opened " - << ", {label = " << label << "}" - << ", device_id = " << device_it->id << "}"; + << ", {label = " << label << "}" + << ", device_id = " << device_it->id << "}"; continue; } } device_info.session_id = GetDeviceManager(device_info.device.type)->Open(device_info); + TranslateDeviceIdToSourceId(request, &device_info.device); request->devices.push_back(device_info); + request->SetState(device_info.device.type, MEDIA_REQUEST_STATE_OPENING); DVLOG(1) << "HandleAccessRequestResponse - opening device " << ", {label = " << label << "}" - << ", {device_id = " << device_it->id << "}" + << ", {device_id = " << device_info.device.id << "}" << ", {session_id = " << device_info.session_id << "}"; } @@ -1115,11 +1287,10 @@ void MediaStreamManager::HandleAccessRequestResponse( void MediaStreamManager::StopMediaStreamFromBrowser(const std::string& label) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - DeviceRequests::iterator it = requests_.find(label); - if (it == requests_.end()) + DeviceRequest* request = FindRequest(label); + if (!request) return; - DeviceRequest* request = it->second; // Notify renderers that the devices in the stream will be stopped. if (request->requester) { for (StreamDeviceInfoArray::iterator device_it = request->devices.begin(); @@ -1146,6 +1317,7 @@ void MediaStreamManager::UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy> fake_ui) { } void MediaStreamManager::WillDestroyCurrentMessageLoop() { + DVLOG(3) << "MediaStreamManager::WillDestroyCurrentMessageLoop()"; DCHECK_EQ(base::MessageLoop::current(), io_loop_); DCHECK(requests_.empty()); if (device_thread_) { diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h index d1b6ec245d..db99cd5371 100644 --- a/content/browser/renderer_host/media/media_stream_manager.h +++ b/content/browser/renderer_host/media/media_stream_manager.h @@ -51,6 +51,7 @@ class FakeMediaStreamUIProxy; class MediaStreamDeviceSettings; class MediaStreamRequester; class MediaStreamUIProxy; +class ResourceContext; class VideoCaptureManager; // MediaStreamManager is used to generate and close new media devices, not to @@ -96,6 +97,7 @@ class CONTENT_EXPORT MediaStreamManager std::string GenerateStream(MediaStreamRequester* requester, int render_process_id, int render_view_id, + ResourceContext* rc, int page_request_id, const StreamOptions& components, const GURL& security_origin); @@ -119,6 +121,7 @@ class CONTENT_EXPORT MediaStreamManager virtual std::string EnumerateDevices(MediaStreamRequester* requester, int render_process_id, int render_view_id, + ResourceContext* rc, int page_request_id, MediaStreamType type, const GURL& security_origin); @@ -129,11 +132,16 @@ class CONTENT_EXPORT MediaStreamManager std::string OpenDevice(MediaStreamRequester* requester, int render_process_id, int render_view_id, + ResourceContext* rc, int page_request_id, const std::string& device_id, MediaStreamType type, const GURL& security_origin); + // Called by UI to make sure the device monitor is started so that UI receive + // notifications about device changes. + void EnsureDeviceMonitorStarted(); + // Implements MediaStreamProviderListener. virtual void Opened(MediaStreamType stream_type, int capture_session_id) OVERRIDE; @@ -155,12 +163,19 @@ class CONTENT_EXPORT MediaStreamManager // generated stream (or when using --use-fake-ui-for-media-stream). void UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy> fake_ui); + // Returns all devices currently opened by a request with label |label|. + // If no request with |label| exist, an empty array is returned. + StreamDeviceInfoArray GetDevicesOpenedByRequest( + const std::string& label) const; + // This object gets deleted on the UI thread after the IO thread has been // destroyed. So we need to know when IO thread is being destroyed so that - // we can delete VideoCaptureManager and AudioInputDeviceManager. - // We also must call this function explicitly in tests which use - // TestBrowserThreadBundle, because the notification happens too late in that - // case (see http://crbug.com/247525#c14). + // we can delete VideoCaptureManager and AudioInputDeviceManager. Normally + // this is handled by + // base::MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop. + // But for some tests which use TestBrowserThreadBundle, we need to call + // WillDestroyCurrentMessageLoop explicitly because the notification happens + // too late. (see http://crbug.com/247525#c14). virtual void WillDestroyCurrentMessageLoop() OVERRIDE; protected: @@ -168,8 +183,6 @@ class CONTENT_EXPORT MediaStreamManager MediaStreamManager(); private: - friend class MockMediaStreamDispatcherHost; - // Contains all data needed to keep track of requests. class DeviceRequest; @@ -193,11 +206,12 @@ class CONTENT_EXPORT MediaStreamManager void NotifyDevicesChanged(MediaStreamType stream_type, const StreamDeviceInfoArray& devices); - void HandleAccessRequestResponse(const std::string& label, const MediaStreamDevices& devices); void StopMediaStreamFromBrowser(const std::string& label); + void DoEnumerateDevices(const std::string& label); + // Helpers. // Checks if all devices that was requested in the request identififed by // |label| has been opened and set the request state accordingly. @@ -216,23 +230,39 @@ class CONTENT_EXPORT MediaStreamManager MediaStreamProvider* GetDeviceManager(MediaStreamType stream_type); void StartEnumeration(DeviceRequest* request); std::string AddRequest(DeviceRequest* request); - void RemoveRequest(DeviceRequests::iterator it); + DeviceRequest* FindRequest(const std::string& label) const; + void DeleteRequest(const std::string& label); void ClearEnumerationCache(EnumerationCache* cache); - void PostRequestToUI(const std::string& label); - void HandleRequest(const std::string& label); - // Returns true if a device with |device_id| has already been requested by - // |render_process_id| and |render_view_id| of type |type|. If it has been - // requested, |device_info| contain information about the the device. - bool FindExistingRequestedDeviceInfo(int render_process_id, - int render_view_id, - MediaStreamRequestType type, - const std::string& device_id, - StreamDeviceInfo* device_info, - MediaRequestState* request_state) const; - - // Sends cached device list to a client corresponding to the request - // identified by |label|. - void SendCachedDeviceList(EnumerationCache* cache, const std::string& label); + // Prepare the request with label |label| by starting device enumeration if + // needed. + void SetupRequest(const std::string& label); + bool SetupTabCaptureRequest(DeviceRequest* request); + bool SetupScreenCaptureRequest(DeviceRequest* request); + // Called when a request has been setup and devices have been enumerated if + // needed. If a certain source id has been requested, the source id is + // translated to a real device id before the request is posted to UI. + void PostRequestToUI(const std::string& label, DeviceRequest* request); + // Returns true if a device with |device_id| has already been requested with + // a render procecss_id and render_view_id and type equal to the the values + // in |request|. If it has been requested, |device_info| contain information + // about the device. + bool FindExistingRequestedDeviceInfo( + const DeviceRequest& new_request, + const MediaStreamDevice& new_device_info, + StreamDeviceInfo* existing_device_info, + MediaRequestState* existing_request_state) const; + + void FinalizeGenerateStream(const std::string& label, + DeviceRequest* request); + void FinalizeRequestFailed(const std::string& label, + DeviceRequest* request); + void FinalizeOpenDevice(const std::string& label, + DeviceRequest* request); + void FinalizeMediaAccessRequest(const std::string& label, + DeviceRequest* request, + const MediaStreamDevices& devices); + void FinalizeEnumerateDevices(const std::string& label, + DeviceRequest* request); // This method is called when an audio or video device is plugged in or // removed. It make sure all MediaStreams that use a removed device is @@ -249,14 +279,19 @@ class CONTENT_EXPORT MediaStreamManager void StartMonitoring(); void StopMonitoring(); - // Finds and returns the raw device id corresponding to the given - // |device_guid|. Returns true if there was a raw device id that matched the - // given |device_guid|, false if nothing matched it. - bool TranslateGUIDToRawId( + bool TranslateRequestedSourceIdToDeviceId(DeviceRequest* request); + void TranslateDeviceIdToSourceId(DeviceRequest* request, + MediaStreamDevice* device); + + // Finds and returns the device id corresponding to the given + // |source_id|. Returns true if there was a raw device id that matched the + // given |source_id|, false if nothing matched it. + bool TranslateSourceIdToDeviceId( MediaStreamType stream_type, + ResourceContext* rc, const GURL& security_origin, - const std::string& device_guid, - std::string* raw_device_id); + const std::string& source_id, + std::string* device_id); // Device thread shared by VideoCaptureManager and AudioInputDeviceManager. scoped_ptr<base::Thread> device_thread_; @@ -280,15 +315,10 @@ class CONTENT_EXPORT MediaStreamManager // All non-closed request. DeviceRequests requests_; - std::vector<int> opened_audio_session_ids_; - std::vector<int> opened_video_session_ids_; - // Hold a pointer to the IO loop to check we delete the device thread and // managers on the right thread. base::MessageLoop* io_loop_; - bool screen_capture_active_; - bool use_fake_ui_; scoped_ptr<FakeMediaStreamUIProxy> fake_ui_; diff --git a/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/content/browser/renderer_host/media/media_stream_manager_unittest.cc index 03e95e0b66..f4f0b2090e 100644 --- a/content/browser/renderer_host/media/media_stream_manager_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_manager_unittest.cc @@ -13,6 +13,10 @@ #include "content/common/media/media_stream_options.h" #include "content/public/test/test_browser_thread_bundle.h" #include "media/audio/audio_manager_base.h" +#include "media/audio/fake_audio_log_factory.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + #if defined(USE_ALSA) #include "media/audio/alsa/audio_manager_alsa.h" #elif defined(OS_ANDROID) @@ -24,8 +28,6 @@ #else #include "media/audio/fake_audio_manager.h" #endif -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" using testing::_; @@ -49,7 +51,7 @@ typedef media::FakeAudioManager AudioManagerPlatform; // the buildbots. media::AudioManagerBase class MockAudioManager : public AudioManagerPlatform { public: - MockAudioManager() {} + MockAudioManager() : AudioManagerPlatform(&fake_audio_log_factory_) {} virtual ~MockAudioManager() {} virtual void GetAudioInputDeviceNames( @@ -64,6 +66,7 @@ class MockAudioManager : public AudioManagerPlatform { } private: + media::FakeAudioLogFactory fake_audio_log_factory_; DISALLOW_COPY_AND_ASSIGN(MockAudioManager); }; @@ -81,7 +84,6 @@ class MediaStreamManagerTest : public ::testing::Test { } virtual ~MediaStreamManagerTest() { - media_stream_manager_->WillDestroyCurrentMessageLoop(); } MOCK_METHOD1(Response, void(int index)); @@ -133,6 +135,8 @@ TEST_F(MediaStreamManagerTest, MakeAndCancelMediaAccessRequest) { std::string label = MakeMediaAccessRequest(0); // No callback is expected. media_stream_manager_->CancelRequest(label); + run_loop_.RunUntilIdle(); + media_stream_manager_->WillDestroyCurrentMessageLoop(); } TEST_F(MediaStreamManagerTest, MakeMultipleRequests) { diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy.cc b/content/browser/renderer_host/media/media_stream_ui_proxy.cc index 3e4edbc0ac..b91ccb1209 100644 --- a/content/browser/renderer_host/media/media_stream_ui_proxy.cc +++ b/content/browser/renderer_host/media/media_stream_ui_proxy.cc @@ -193,12 +193,16 @@ void FakeMediaStreamUIProxy::RequestAccess( it != devices_.end(); ++it) { if (!accepted_audio && IsAudioMediaType(request.audio_type) && - IsAudioMediaType(it->type)) { + IsAudioMediaType(it->type) && + (request.requested_audio_device_id.empty() || + request.requested_audio_device_id == it->id)) { devices_to_use.push_back(*it); accepted_audio = true; } else if (!accepted_video && IsVideoMediaType(request.video_type) && - IsVideoMediaType(it->type)) { + IsVideoMediaType(it->type) && + (request.requested_video_device_id.empty() || + request.requested_video_device_id == it->id)) { devices_to_use.push_back(*it); accepted_video = true; } diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc b/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc index 82219a6e87..bff55c618c 100644 --- a/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc @@ -92,7 +92,7 @@ MATCHER_P(SameRequest, expected, "") { } TEST_F(MediaStreamUIProxyTest, Deny) { - MediaStreamRequest request(0, 0, 0, std::string(), GURL("http://origin/"), + MediaStreamRequest request(0, 0, 0, GURL("http://origin/"), MEDIA_GENERATE_STREAM, std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE, @@ -118,7 +118,7 @@ TEST_F(MediaStreamUIProxyTest, Deny) { } TEST_F(MediaStreamUIProxyTest, AcceptAndStart) { - MediaStreamRequest request(0, 0, 0, std::string(), GURL("http://origin/"), + MediaStreamRequest request(0, 0, 0, GURL("http://origin/"), MEDIA_GENERATE_STREAM, std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE, @@ -152,7 +152,7 @@ TEST_F(MediaStreamUIProxyTest, AcceptAndStart) { // Verify that the proxy can be deleted before the request is processed. TEST_F(MediaStreamUIProxyTest, DeleteBeforeAccepted) { - MediaStreamRequest request(0, 0, 0, std::string(), GURL("http://origin/"), + MediaStreamRequest request(0, 0, 0, GURL("http://origin/"), MEDIA_GENERATE_STREAM, std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE, @@ -174,7 +174,7 @@ TEST_F(MediaStreamUIProxyTest, DeleteBeforeAccepted) { } TEST_F(MediaStreamUIProxyTest, StopFromUI) { - MediaStreamRequest request(0, 0, 0, std::string(), GURL("http://origin/"), + MediaStreamRequest request(0, 0, 0, GURL("http://origin/"), MEDIA_GENERATE_STREAM, std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE, diff --git a/content/browser/renderer_host/media/midi_host.cc b/content/browser/renderer_host/media/midi_host.cc index 934d5a21f1..d6781f61df 100644 --- a/content/browser/renderer_host/media/midi_host.cc +++ b/content/browser/renderer_host/media/midi_host.cc @@ -16,26 +16,41 @@ #include "content/public/browser/media_observer.h" #include "content/public/browser/user_metrics.h" #include "media/midi/midi_manager.h" +#include "media/midi/midi_message_queue.h" +#include "media/midi/midi_message_util.h" using media::MIDIManager; using media::MIDIPortInfoList; +namespace content { +namespace { + // The total number of bytes which we're allowed to send to the OS // before knowing that they have been successfully sent. -static const size_t kMaxInFlightBytes = 10 * 1024 * 1024; // 10 MB. +const size_t kMaxInFlightBytes = 10 * 1024 * 1024; // 10 MB. // We keep track of the number of bytes successfully sent to // the hardware. Every once in a while we report back to the renderer // the number of bytes sent since the last report. This threshold determines // how many bytes will be sent before reporting back to the renderer. -static const size_t kAcknowledgementThresholdBytes = 1024 * 1024; // 1 MB. +const size_t kAcknowledgementThresholdBytes = 1024 * 1024; // 1 MB. -static const uint8 kSysExMessage = 0xf0; +const uint8 kSysExMessage = 0xf0; +const uint8 kEndOfSysExMessage = 0xf7; -namespace content { +bool IsDataByte(uint8 data) { + return (data & 0x80) == 0; +} + +bool IsSystemRealTimeMessage(uint8 data) { + return 0xf8 <= data && data <= 0xff; +} + +} // namespace MIDIHost::MIDIHost(int renderer_process_id, media::MIDIManager* midi_manager) : renderer_process_id_(renderer_process_id), + has_sys_ex_permission_(false), midi_manager_(midi_manager), sent_bytes_in_flight_(0), bytes_sent_since_last_acknowledgement_(0) { @@ -75,6 +90,12 @@ void MIDIHost::OnStartSession(int client_id) { if (success) { input_ports = midi_manager_->input_ports(); output_ports = midi_manager_->output_ports(); + received_messages_queues_.clear(); + received_messages_queues_.resize(input_ports.size()); + // ChildSecurityPolicy is set just before OnStartSession by + // MIDIDispatcherHost. So we can safely cache the policy. + has_sys_ex_permission_ = ChildProcessSecurityPolicyImpl::GetInstance()-> + CanSendMIDISysExMessage(renderer_process_id_); } } @@ -94,32 +115,26 @@ void MIDIHost::OnSendData(uint32 port, if (data.empty()) return; - base::AutoLock auto_lock(in_flight_lock_); - - // Sanity check that we won't send too much. - if (sent_bytes_in_flight_ > kMaxInFlightBytes || - data.size() > kMaxInFlightBytes || - data.size() + sent_bytes_in_flight_ > kMaxInFlightBytes) + // Blink running in a renderer checks permission to raise a SecurityError + // in JavaScript. The actual permission check for security purposes + // happens here in the browser process. + if (!has_sys_ex_permission_ && + (std::find(data.begin(), data.end(), kSysExMessage) != data.end())) { + RecordAction(UserMetricsAction("BadMessageTerminate_MIDI")); + BadMessageReceived(); return; - - if (data[0] >= kSysExMessage) { - // Blink running in a renderer checks permission to raise a SecurityError in - // JavaScript. The actual permission check for security perposes happens - // here in the browser process. - if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanSendMIDISysExMessage( - renderer_process_id_)) { - RecordAction(UserMetricsAction("BadMessageTerminate_MIDI")); - BadMessageReceived(); - return; - } } - midi_manager_->DispatchSendMIDIData( - this, - port, - data, - timestamp); + if (!IsValidWebMIDIData(data)) + return; + base::AutoLock auto_lock(in_flight_lock_); + // Sanity check that we won't send too much data. + // TODO(yukawa): Consider to send an error event back to the renderer + // after some future discussion in W3C. + if (data.size() + sent_bytes_in_flight_ > kMaxInFlightBytes) + return; + midi_manager_->DispatchSendMIDIData(this, port, data, timestamp); sent_bytes_in_flight_ += data.size(); } @@ -130,20 +145,29 @@ void MIDIHost::ReceiveMIDIData( double timestamp) { TRACE_EVENT0("midi", "MIDIHost::ReceiveMIDIData"); - // Check a process security policy to receive a system exclusive message. - if (length > 0 && data[0] >= kSysExMessage) { - if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanSendMIDISysExMessage( - renderer_process_id_)) { - // MIDI devices may send a system exclusive messages even if the renderer - // doesn't have a permission to receive it. Don't kill the renderer as - // OnSendData() does. - return; - } - } + if (received_messages_queues_.size() <= port) + return; - // Send to the renderer. - std::vector<uint8> v(data, data + length); - Send(new MIDIMsg_DataReceived(port, v, timestamp)); + // Lazy initialization + if (received_messages_queues_[port] == NULL) + received_messages_queues_[port] = new media::MIDIMessageQueue(true); + + received_messages_queues_[port]->Add(data, length); + std::vector<uint8> message; + while (true) { + received_messages_queues_[port]->Get(&message); + if (message.empty()) + break; + + // MIDI devices may send a system exclusive messages even if the renderer + // doesn't have a permission to receive it. Don't kill the renderer as + // OnSendData() does. + if (message[0] == kSysExMessage && !has_sys_ex_permission_) + continue; + + // Send to the renderer. + Send(new MIDIMsg_DataReceived(port, message, timestamp)); + } } void MIDIHost::AccumulateMIDIBytesSent(size_t n) { @@ -165,4 +189,37 @@ void MIDIHost::AccumulateMIDIBytesSent(size_t n) { } } +// static +bool MIDIHost::IsValidWebMIDIData(const std::vector<uint8>& data) { + bool in_sysex = false; + size_t waiting_data_length = 0; + for (size_t i = 0; i < data.size(); ++i) { + const uint8 current = data[i]; + if (IsSystemRealTimeMessage(current)) + continue; // Real time message can be placed at any point. + if (waiting_data_length > 0) { + if (!IsDataByte(current)) + return false; // Error: |current| should have been data byte. + --waiting_data_length; + continue; // Found data byte as expected. + } + if (in_sysex) { + if (data[i] == kEndOfSysExMessage) + in_sysex = false; + else if (!IsDataByte(current)) + return false; // Error: |current| should have been data byte. + continue; // Found data byte as expected. + } + if (current == kSysExMessage) { + in_sysex = true; + continue; // Found SysEX + } + waiting_data_length = media::GetMIDIMessageLength(current); + if (waiting_data_length == 0) + return false; // Error: |current| should have been a valid status byte. + --waiting_data_length; // Found status byte + } + return waiting_data_length == 0 && !in_sysex; +} + } // namespace content diff --git a/content/browser/renderer_host/media/midi_host.h b/content/browser/renderer_host/media/midi_host.h index e3b9df1b6b..153863fe60 100644 --- a/content/browser/renderer_host/media/midi_host.h +++ b/content/browser/renderer_host/media/midi_host.h @@ -7,8 +7,10 @@ #include <vector> +#include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" #include "content/common/content_export.h" #include "content/public/browser/browser_message_filter.h" #include "content/public/browser/browser_thread.h" @@ -16,6 +18,7 @@ namespace media { class MIDIManager; +class MIDIMessageQueue; } namespace content { @@ -33,11 +36,10 @@ class CONTENT_EXPORT MIDIHost bool* message_was_ok) OVERRIDE; // MIDIManagerClient implementation. - virtual void ReceiveMIDIData( - uint32 port, - const uint8* data, - size_t length, - double timestamp) OVERRIDE; + virtual void ReceiveMIDIData(uint32 port, + const uint8* data, + size_t length, + double timestamp) OVERRIDE; virtual void AccumulateMIDIBytesSent(size_t n) OVERRIDE; // Start session to access MIDI hardware. @@ -49,13 +51,25 @@ class CONTENT_EXPORT MIDIHost double timestamp); private: + FRIEND_TEST_ALL_PREFIXES(MIDIHostTest, IsValidWebMIDIData); friend class base::DeleteHelper<MIDIHost>; friend class BrowserThread; virtual ~MIDIHost(); + // Returns true if |data| fulfills the requirements of MIDIOutput.send API + // defined in the WebMIDI spec. + // - |data| must be any number of complete MIDI messages (data abbreviation + // called "running status" is disallowed). + // - 1-byte MIDI realtime messages can be placed at any position of |data|. + static bool IsValidWebMIDIData(const std::vector<uint8>& data); + int renderer_process_id_; + // Represents if the renderer has a permission to send/receive MIDI SysEX + // messages. + bool has_sys_ex_permission_; + // |midi_manager_| talks to the platform-specific MIDI APIs. // It can be NULL if the platform (or our current implementation) // does not support MIDI. If not supported then a call to @@ -63,6 +77,9 @@ class CONTENT_EXPORT MIDIHost // OnSendData() will do nothing. media::MIDIManager* const midi_manager_; + // Buffers where data sent from each MIDI input port is stored. + ScopedVector<media::MIDIMessageQueue> received_messages_queues_; + // The number of bytes sent to the platform-specific MIDI sending // system, but not yet completed. size_t sent_bytes_in_flight_; diff --git a/content/browser/renderer_host/media/midi_host_unittest.cc b/content/browser/renderer_host/media/midi_host_unittest.cc new file mode 100644 index 0000000000..fedb4265b9 --- /dev/null +++ b/content/browser/renderer_host/media/midi_host_unittest.cc @@ -0,0 +1,90 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/media/midi_host.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { +namespace { + +const uint8 kGMOn[] = { 0xf0, 0x7e, 0x7f, 0x09, 0x01, 0xf7 }; +const uint8 kGSOn[] = { + 0xf0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7f, 0x00, 0x41, 0xf7, +}; +const uint8 kNoteOn[] = { 0x90, 0x3c, 0x7f }; +const uint8 kNoteOnWithRunningStatus[] = { + 0x90, 0x3c, 0x7f, 0x3c, 0x7f, 0x3c, 0x7f, +}; +const uint8 kChannelPressure[] = { 0xd0, 0x01 }; +const uint8 kChannelPressureWithRunningStatus[] = { + 0xd0, 0x01, 0x01, 0x01, +}; +const uint8 kTimingClock[] = { 0xf8 }; +const uint8 kBrokenData1[] = { 0x90 }; +const uint8 kBrokenData2[] = { 0xf7 }; +const uint8 kBrokenData3[] = { 0xf2, 0x00 }; +const uint8 kDataByte0[] = { 0x00 }; + +template <typename T, size_t N> +const std::vector<T> AsVector(const T(&data)[N]) { + std::vector<T> buffer; + buffer.insert(buffer.end(), data, data + N); + return buffer; +} + +template <typename T, size_t N> +void PushToVector(const T(&data)[N], std::vector<T>* buffer) { + buffer->insert(buffer->end(), data, data + N); +} + +} // namespace + +TEST(MIDIHostTest, IsValidWebMIDIData) { + // Test single event scenario + EXPECT_TRUE(MIDIHost::IsValidWebMIDIData(AsVector(kGMOn))); + EXPECT_TRUE(MIDIHost::IsValidWebMIDIData(AsVector(kGSOn))); + EXPECT_TRUE(MIDIHost::IsValidWebMIDIData(AsVector(kNoteOn))); + EXPECT_TRUE(MIDIHost::IsValidWebMIDIData(AsVector(kChannelPressure))); + EXPECT_TRUE(MIDIHost::IsValidWebMIDIData(AsVector(kTimingClock))); + EXPECT_FALSE(MIDIHost::IsValidWebMIDIData(AsVector(kBrokenData1))); + EXPECT_FALSE(MIDIHost::IsValidWebMIDIData(AsVector(kBrokenData2))); + EXPECT_FALSE(MIDIHost::IsValidWebMIDIData(AsVector(kBrokenData3))); + EXPECT_FALSE(MIDIHost::IsValidWebMIDIData(AsVector(kDataByte0))); + + // MIDI running status should be disallowed + EXPECT_FALSE(MIDIHost::IsValidWebMIDIData( + AsVector(kNoteOnWithRunningStatus))); + EXPECT_FALSE(MIDIHost::IsValidWebMIDIData( + AsVector(kChannelPressureWithRunningStatus))); + + // Multiple messages are allowed as long as each of them is complete. + { + std::vector<uint8> buffer; + PushToVector(kGMOn, &buffer); + PushToVector(kNoteOn, &buffer); + PushToVector(kGSOn, &buffer); + PushToVector(kTimingClock, &buffer); + PushToVector(kNoteOn, &buffer); + EXPECT_TRUE(MIDIHost::IsValidWebMIDIData(buffer)); + PushToVector(kBrokenData1, &buffer); + EXPECT_FALSE(MIDIHost::IsValidWebMIDIData(buffer)); + } + + // MIDI realtime message can be placed at any position. + { + const uint8 kNoteOnWithRealTimeClock[] = { + 0x90, 0xf8, 0x3c, 0x7f, 0x90, 0xf8, 0x3c, 0xf8, 0x7f, 0xf8, + }; + EXPECT_TRUE(MIDIHost::IsValidWebMIDIData( + AsVector(kNoteOnWithRealTimeClock))); + + const uint8 kGMOnWithRealTimeClock[] = { + 0xf0, 0xf8, 0x7e, 0x7f, 0x09, 0x01, 0xf8, 0xf7, + }; + EXPECT_TRUE(MIDIHost::IsValidWebMIDIData(AsVector(kGMOnWithRealTimeClock))); + } +} + +} // namespace conent diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc index 6f1cbc0fb0..7581df39d5 100644 --- a/content/browser/renderer_host/media/video_capture_controller.cc +++ b/content/browser/renderer_host/media/video_capture_controller.cc @@ -346,7 +346,7 @@ void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame( break; case media::PIXEL_FORMAT_NV21: DCHECK(!chopped_width && !chopped_height); - origin_colorspace = libyuv::FOURCC_NV12; + origin_colorspace = libyuv::FOURCC_NV21; break; case media::PIXEL_FORMAT_YUY2: DCHECK(!chopped_width && !chopped_height); @@ -513,8 +513,20 @@ VideoCaptureController::VideoCaptureDeviceClient::DoReserveOutputBuffer( if ((rotation % 180) == 0) { rotated_buffers_.erase(buffer_id); } else { - if (rotated_buffers_.insert(buffer_id).second) - memset(output_buffer->data(), 0, output_buffer->size()); + if (rotated_buffers_.insert(buffer_id).second) { + scoped_refptr<media::VideoFrame> frame = + media::VideoFrame::WrapExternalPackedMemory( + media::VideoFrame::I420, + dimensions, + gfx::Rect(dimensions), + dimensions, + static_cast<uint8*>(output_buffer->data()), + output_buffer->size(), + base::SharedMemory::NULLHandle(), + base::TimeDelta(), + base::Closure()); + media::FillYUV(frame, 0, 128, 128); + } } return output_buffer; diff --git a/content/browser/renderer_host/media/video_capture_device_impl.cc b/content/browser/renderer_host/media/video_capture_device_impl.cc index 54af30f71b..9b37b296c4 100644 --- a/content/browser/renderer_host/media/video_capture_device_impl.cc +++ b/content/browser/renderer_host/media/video_capture_device_impl.cc @@ -23,6 +23,7 @@ #include "content/public/browser/browser_thread.h" #include "media/base/bind_to_loop.h" #include "media/base/video_frame.h" +#include "media/base/video_util.h" #include "media/video/capture/video_capture_types.h" #include "ui/gfx/rect.h" @@ -44,12 +45,18 @@ void DeleteCaptureMachineOnUIThread( ThreadSafeCaptureOracle::ThreadSafeCaptureOracle( scoped_ptr<media::VideoCaptureDevice::Client> client, scoped_ptr<VideoCaptureOracle> oracle, - const gfx::Size& capture_size, - int frame_rate) + const media::VideoCaptureParams& params) : client_(client.Pass()), oracle_(oracle.Pass()), - capture_size_(capture_size), - frame_rate_(frame_rate) {} + params_(params), + capture_size_updated_(false) { + // Frame dimensions must each be an even integer since the client wants (or + // will convert to) YUV420. + capture_size_ = gfx::Size( + MakeEven(params.requested_format.frame_size.width()), + MakeEven(params.requested_format.frame_size.height())); + frame_rate_ = params.requested_format.frame_rate; +} ThreadSafeCaptureOracle::~ThreadSafeCaptureOracle() {} @@ -122,6 +129,29 @@ bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture( return true; } +void ThreadSafeCaptureOracle::UpdateCaptureSize(const gfx::Size& source_size) { + base::AutoLock guard(lock_); + + // If this is the first call to UpdateCaptureSize(), or the receiver supports + // variable resolution, then determine the capture size by treating the + // requested width and height as maxima. + if (!capture_size_updated_ || params_.allow_resolution_change) { + // The capture resolution should not exceed the source frame size. + // In other words it should downscale the image but not upscale it. + if (source_size.width() > params_.requested_format.frame_size.width() || + source_size.height() > params_.requested_format.frame_size.height()) { + gfx::Rect capture_rect = media::ComputeLetterboxRegion( + gfx::Rect(params_.requested_format.frame_size), source_size); + capture_size_ = gfx::Size(MakeEven(capture_rect.width()), + MakeEven(capture_rect.height())); + } else { + capture_size_ = gfx::Size(MakeEven(source_size.width()), + MakeEven(source_size.height())); + } + capture_size_updated_ = true; + } +} + void ThreadSafeCaptureOracle::Stop() { base::AutoLock guard(lock_); client_.reset(); @@ -173,13 +203,10 @@ void VideoCaptureDeviceImpl::AllocateAndStart( return; } - // Frame dimensions must each be a positive, even integer, since the client - // wants (or will convert to) YUV420. - gfx::Size frame_size(MakeEven(params.requested_format.frame_size.width()), - MakeEven(params.requested_format.frame_size.height())); - if (frame_size.width() < kMinFrameWidth || - frame_size.height() < kMinFrameHeight) { - DVLOG(1) << "invalid frame size: " << frame_size.ToString(); + if (params.requested_format.frame_size.width() < kMinFrameWidth || + params.requested_format.frame_size.height() < kMinFrameHeight) { + DVLOG(1) << "invalid frame size: " + << params.requested_format.frame_size.ToString(); client->OnError(); return; } @@ -191,10 +218,7 @@ void VideoCaptureDeviceImpl::AllocateAndStart( new VideoCaptureOracle(capture_period, kAcceleratedSubscriberIsSupported)); oracle_proxy_ = - new ThreadSafeCaptureOracle(client.Pass(), - oracle.Pass(), - frame_size, - params.requested_format.frame_rate); + new ThreadSafeCaptureOracle(client.Pass(), oracle.Pass(), params); // Starts the capture machine asynchronously. BrowserThread::PostTaskAndReplyWithResult( diff --git a/content/browser/renderer_host/media/video_capture_device_impl.h b/content/browser/renderer_host/media/video_capture_device_impl.h index ec771e8485..d9329b6aa4 100644 --- a/content/browser/renderer_host/media/video_capture_device_impl.h +++ b/content/browser/renderer_host/media/video_capture_device_impl.h @@ -45,8 +45,7 @@ class ThreadSafeCaptureOracle public: ThreadSafeCaptureOracle(scoped_ptr<media::VideoCaptureDevice::Client> client, scoped_ptr<VideoCaptureOracle> oracle, - const gfx::Size& capture_size, - int frame_rate); + const media::VideoCaptureParams& params); // Called when a captured frame is available or an error has occurred. // If |success| is true then the frame provided is valid and |timestamp| @@ -64,6 +63,10 @@ class ThreadSafeCaptureOracle return oracle_->capture_period(); } + // Updates capture resolution based on the supplied source size and the + // maximum frame size. + void UpdateCaptureSize(const gfx::Size& source_size); + // Stop new captures from happening (but doesn't forget the client). void Stop(); @@ -89,9 +92,15 @@ class ThreadSafeCaptureOracle // Makes the decision to capture a frame. const scoped_ptr<VideoCaptureOracle> oracle_; + // The video capture parameters used to construct the oracle proxy. + const media::VideoCaptureParams params_; + + // Indicates if capture size has been updated after construction. + bool capture_size_updated_; + // The current capturing resolution and frame rate. - const gfx::Size capture_size_; - const int frame_rate_; + gfx::Size capture_size_; + int frame_rate_; }; // Keeps track of the video capture source frames and executes copying on the diff --git a/content/browser/renderer_host/media/video_capture_host_unittest.cc b/content/browser/renderer_host/media/video_capture_host_unittest.cc index d56e005e10..1c169a4cd5 100644 --- a/content/browser/renderer_host/media/video_capture_host_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_host_unittest.cc @@ -20,7 +20,9 @@ #include "content/browser/renderer_host/media/video_capture_manager.h" #include "content/common/media/video_capture_messages.h" #include "content/public/test/mock_resource_context.h" +#include "content/public/test/test_browser_context.h" #include "content/public/test/test_browser_thread_bundle.h" +#include "content/test/test_content_browser_client.h" #include "media/audio/audio_manager.h" #include "media/base/video_frame.h" #include "media/video/capture/video_capture_types.h" @@ -58,7 +60,7 @@ class DumpVideo { void StartDump(int width, int height) { base::FilePath file_name = base::FilePath(base::StringPrintf( FILE_PATH_LITERAL("dump_w%d_h%d.yuv"), width, height)); - file_.reset(file_util::OpenFile(file_name, "wb")); + file_.reset(base::OpenFile(file_name, "wb")); expected_size_ = media::VideoFrame::AllocationSize( media::VideoFrame::I420, gfx::Size(width, height)); } @@ -243,8 +245,9 @@ class VideoCaptureHostTest : public testing::Test { opened_session_id_(kInvalidMediaCaptureSessionId) {} virtual void SetUp() OVERRIDE { + SetBrowserClientForTesting(&browser_client_); // Create our own MediaStreamManager. - audio_manager_.reset(media::AudioManager::Create()); + audio_manager_.reset(media::AudioManager::CreateForTesting()); media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); #ifndef TEST_REAL_CAPTURE_DEVICE media_stream_manager_->UseFakeDevice(); @@ -272,15 +275,13 @@ class VideoCaptureHostTest : public testing::Test { // Release the reference to the mock object. The object will be destructed // on the current message loop. host_ = NULL; - - media_stream_manager_->WillDestroyCurrentMessageLoop(); } void OpenSession() { const int render_process_id = 1; const int render_view_id = 1; const int page_request_id = 1; - const GURL security_origin; + const GURL security_origin("http://test.com"); ASSERT_TRUE(opened_device_label_.empty()); @@ -292,6 +293,7 @@ class VideoCaptureHostTest : public testing::Test { &stream_requester_, render_process_id, render_view_id, + browser_context_.GetResourceContext(), page_request_id, MEDIA_DEVICE_VIDEO_CAPTURE, security_origin); @@ -314,6 +316,7 @@ class VideoCaptureHostTest : public testing::Test { &stream_requester_, render_process_id, render_view_id, + browser_context_.GetResourceContext(), page_request_id, devices[0].device.id, MEDIA_DEVICE_VIDEO_CAPTURE, @@ -434,6 +437,8 @@ class VideoCaptureHostTest : public testing::Test { scoped_ptr<media::AudioManager> audio_manager_; scoped_ptr<MediaStreamManager> media_stream_manager_; content::TestBrowserThreadBundle thread_bundle_; + content::TestBrowserContext browser_context_; + content::TestContentBrowserClient browser_client_; scoped_refptr<base::MessageLoopProxy> message_loop_; int opened_session_id_; std::string opened_device_label_; diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc index 00fa52e43e..ff71016dc1 100644 --- a/content/browser/renderer_host/media/video_capture_manager.cc +++ b/content/browser/renderer_host/media/video_capture_manager.cc @@ -19,14 +19,16 @@ #include "content/public/common/content_switches.h" #include "content/public/common/desktop_media_id.h" #include "content/public/common/media_stream_request.h" +#include "media/base/media_switches.h" #include "media/base/scoped_histogram_timer.h" #include "media/video/capture/fake_video_capture_device.h" +#include "media/video/capture/file_video_capture_device.h" #include "media/video/capture/video_capture_device.h" #if defined(ENABLE_SCREEN_CAPTURE) #include "content/browser/renderer_host/media/desktop_capture_device.h" #if defined(OS_CHROMEOS) -#include "content/browser/renderer_host/media/desktop_capture_device_ash.h" +#include "content/browser/renderer_host/media/desktop_capture_device_aura.h" #endif #endif @@ -45,7 +47,7 @@ VideoCaptureManager::DeviceEntry::~DeviceEntry() {} VideoCaptureManager::VideoCaptureManager() : listener_(NULL), new_capture_session_id_(1), - use_fake_device_(false) { + artificial_device_source_for_testing_ (DISABLED) { } VideoCaptureManager::~VideoCaptureManager() { @@ -131,7 +133,12 @@ void VideoCaptureManager::Close(int capture_session_id) { } void VideoCaptureManager::UseFakeDevice() { - use_fake_device_ = true; + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kUseFileForFakeVideoCapture)) { + artificial_device_source_for_testing_ = Y4M_FILE; + } else { + artificial_device_source_for_testing_ = TEST_PATTERN; + } } void VideoCaptureManager::DoStartDeviceOnDeviceThread( @@ -150,9 +157,20 @@ void VideoCaptureManager::DoStartDeviceOnDeviceThread( media::VideoCaptureDevice::Name* found = video_capture_devices_.FindById(entry->id); if (found) { - video_capture_device.reset(use_fake_device_ ? - media::FakeVideoCaptureDevice::Create(*found) : - media::VideoCaptureDevice::Create(*found)); + switch (artificial_device_source_for_testing_) { + case DISABLED: + video_capture_device.reset( + media::VideoCaptureDevice::Create(*found)); + break; + case TEST_PATTERN: + video_capture_device.reset( + media::FakeVideoCaptureDevice::Create(*found)); + break; + case Y4M_FILE: + video_capture_device.reset( + media::FileVideoCaptureDevice::Create(*found)); + break; + } } break; } @@ -167,7 +185,7 @@ void VideoCaptureManager::DoStartDeviceOnDeviceThread( if (id.type != DesktopMediaID::TYPE_NONE) { #if defined(OS_CHROMEOS) // TODO(hshi): enable this path for Ash windows in metro mode. - video_capture_device.reset(DesktopCaptureDeviceAsh::Create(id)); + video_capture_device.reset(DesktopCaptureDeviceAura::Create(id)); #else video_capture_device = DesktopCaptureDevice::Create(id); #endif @@ -320,10 +338,16 @@ VideoCaptureManager::GetAvailableDevicesOnDeviceThread( // Cache the latest enumeration of video capture devices. // We'll refer to this list again in OnOpen to avoid having to // enumerate the devices again. - if (!use_fake_device_) { - media::VideoCaptureDevice::GetDeviceNames(&result); - } else { - media::FakeVideoCaptureDevice::GetDeviceNames(&result); + switch (artificial_device_source_for_testing_) { + case DISABLED: + media::VideoCaptureDevice::GetDeviceNames(&result); + break; + case TEST_PATTERN: + media::FakeVideoCaptureDevice::GetDeviceNames(&result); + break; + case Y4M_FILE: + media::FileVideoCaptureDevice::GetDeviceNames(&result); + break; } // TODO(nick): The correctness of device start depends on this cache being diff --git a/content/browser/renderer_host/media/video_capture_manager.h b/content/browser/renderer_host/media/video_capture_manager.h index 67dbb75373..82c61537dd 100644 --- a/content/browser/renderer_host/media/video_capture_manager.h +++ b/content/browser/renderer_host/media/video_capture_manager.h @@ -168,9 +168,15 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider { typedef std::set<DeviceEntry*> DeviceEntries; DeviceEntries devices_; - // Set to true if using fake video capture devices for testing, false by - // default. This is only used for the MEDIA_DEVICE_VIDEO_CAPTURE device type. - bool use_fake_device_; + // For unit testing and for performance/quality tests, a test device can be + // used instead of a real one. The device can be a simple fake device (a + // rolling pacman), or a file that is played in a loop continuously. This only + // applies to the MEDIA_DEVICE_VIDEO_CAPTURE device type. + enum { + DISABLED, + TEST_PATTERN, + Y4M_FILE + } artificial_device_source_for_testing_; // We cache the enumerated video capture devices in // GetAvailableDevicesOnDeviceThread() and then later look up the requested ID diff --git a/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc b/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc index 5ef2ef9d87..34bb8334ae 100644 --- a/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc +++ b/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc @@ -16,7 +16,6 @@ #include "content/browser/renderer_host/media/web_contents_capture_util.h" #include "content/browser/renderer_host/render_view_host_factory.h" #include "content/browser/renderer_host/render_widget_host_impl.h" -#include "content/browser/renderer_host/test_render_view_host.h" #include "content/port/browser/render_widget_host_view_frame_subscriber.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" @@ -24,6 +23,7 @@ #include "content/public/test/test_browser_context.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_utils.h" +#include "content/test/test_render_view_host.h" #include "content/test/test_web_contents.h" #include "media/base/video_util.h" #include "media/base/yuv_convert.h" @@ -228,13 +228,14 @@ class CaptureTestRenderViewHost : public TestRenderViewHost { public: CaptureTestRenderViewHost(SiteInstance* instance, RenderViewHostDelegate* delegate, + RenderFrameHostDelegate* frame_delegate, RenderWidgetHostDelegate* widget_delegate, int routing_id, int main_frame_routing_id, bool swapped_out, CaptureTestSourceController* controller) - : TestRenderViewHost(instance, delegate, widget_delegate, routing_id, - main_frame_routing_id, swapped_out), + : TestRenderViewHost(instance, delegate, frame_delegate, widget_delegate, + routing_id, main_frame_routing_id, swapped_out), controller_(controller) { // Override the default view installed by TestRenderViewHost; we need // our special subclass which has mocked-out tab capture support. @@ -289,13 +290,15 @@ class CaptureTestRenderViewHostFactory : public RenderViewHostFactory { virtual RenderViewHost* CreateRenderViewHost( SiteInstance* instance, RenderViewHostDelegate* delegate, + RenderFrameHostDelegate* frame_delegate, RenderWidgetHostDelegate* widget_delegate, int routing_id, int main_frame_routing_id, bool swapped_out) OVERRIDE { - return new CaptureTestRenderViewHost(instance, delegate, widget_delegate, - routing_id, main_frame_routing_id, - swapped_out, controller_); + return new CaptureTestRenderViewHost(instance, delegate, frame_delegate, + widget_delegate, routing_id, + main_frame_routing_id, swapped_out, + controller_); } private: CaptureTestSourceController* controller_; diff --git a/content/browser/renderer_host/native_web_keyboard_event_aura.cc b/content/browser/renderer_host/native_web_keyboard_event_aura.cc index 1587bba1a8..c33f12ffc7 100644 --- a/content/browser/renderer_host/native_web_keyboard_event_aura.cc +++ b/content/browser/renderer_host/native_web_keyboard_event_aura.cc @@ -15,7 +15,7 @@ namespace { // RenderViewHostDelegate::HandledKeybardEvent after the original aura // event is destroyed. ui::Event* CopyEvent(ui::Event* event) { - return event ? static_cast<ui::KeyEvent*>(event)->Copy() : NULL; + return event ? new ui::KeyEvent(*static_cast<ui::KeyEvent*>(event)) : NULL; } int EventFlagsToWebInputEventModifiers(int flags) { diff --git a/content/browser/renderer_host/p2p/socket_dispatcher_host.h b/content/browser/renderer_host/p2p/socket_dispatcher_host.h index b2d76f468b..813da993b9 100644 --- a/content/browser/renderer_host/p2p/socket_dispatcher_host.h +++ b/content/browser/renderer_host/p2p/socket_dispatcher_host.h @@ -11,9 +11,9 @@ #include <vector> #include "content/browser/renderer_host/p2p/socket_host_throttler.h" -#include "content/common/p2p_sockets.h" #include "content/public/browser/browser_message_filter.h" #include "content/public/browser/browser_thread.h" +#include "content/public/common/p2p_socket_type.h" #include "net/base/ip_endpoint.h" #include "net/base/network_change_notifier.h" diff --git a/content/browser/renderer_host/p2p/socket_host.h b/content/browser/renderer_host/p2p/socket_host.h index 0ca8e0e36b..a11488451a 100644 --- a/content/browser/renderer_host/p2p/socket_host.h +++ b/content/browser/renderer_host/p2p/socket_host.h @@ -6,7 +6,7 @@ #define CONTENT_BROWSER_RENDERER_HOST_P2P_SOCKET_HOST_H_ #include "content/common/content_export.h" -#include "content/common/p2p_sockets.h" +#include "content/public/common/p2p_socket_type.h" #include "net/base/ip_endpoint.h" #include "net/udp/datagram_socket.h" diff --git a/content/browser/renderer_host/p2p/socket_host_tcp.cc b/content/browser/renderer_host/p2p/socket_host_tcp.cc index 3c890bba9f..2900541dcb 100644 --- a/content/browser/renderer_host/p2p/socket_host_tcp.cc +++ b/content/browser/renderer_host/p2p/socket_host_tcp.cc @@ -26,6 +26,8 @@ const int kPacketHeaderSize = sizeof(PacketLength); const int kReadBufferSize = 4096; const int kPacketLengthOffset = 2; const int kTurnChannelDataHeaderSize = 4; +const int kRecvSocketBufferSize = 128 * 1024; +const int kSendSocketBufferSize = 128 * 1024; bool IsTlsClientSocket(content::P2PSocketType type) { return (type == content::P2P_SOCKET_STUN_TLS_CLIENT || @@ -198,6 +200,17 @@ void P2PSocketHostTcpBase::ProcessTlsSslConnectDone(int status) { void P2PSocketHostTcpBase::OnOpen() { state_ = STATE_OPEN; + // Setting socket send and receive buffer size. + if (!socket_->SetReceiveBufferSize(kRecvSocketBufferSize)) { + LOG(WARNING) << "Failed to set socket receive buffer size to " + << kRecvSocketBufferSize; + } + + if (!socket_->SetSendBufferSize(kSendSocketBufferSize)) { + LOG(WARNING) << "Failed to set socket send buffer size to " + << kSendSocketBufferSize; + } + DoSendSocketCreateMsg(); DoRead(); } diff --git a/content/browser/renderer_host/p2p/socket_host_tcp.h b/content/browser/renderer_host/p2p/socket_host_tcp.h index 20de668dc1..b84efc7c28 100644 --- a/content/browser/renderer_host/p2p/socket_host_tcp.h +++ b/content/browser/renderer_host/p2p/socket_host_tcp.h @@ -13,7 +13,7 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "content/browser/renderer_host/p2p/socket_host.h" -#include "content/common/p2p_sockets.h" +#include "content/public/common/p2p_socket_type.h" #include "net/base/completion_callback.h" #include "net/base/ip_endpoint.h" diff --git a/content/browser/renderer_host/p2p/socket_host_tcp_server.h b/content/browser/renderer_host/p2p/socket_host_tcp_server.h index 924e2d30e7..2581e83ee7 100644 --- a/content/browser/renderer_host/p2p/socket_host_tcp_server.h +++ b/content/browser/renderer_host/p2p/socket_host_tcp_server.h @@ -13,7 +13,7 @@ #include "base/message_loop/message_loop.h" #include "content/browser/renderer_host/p2p/socket_host.h" #include "content/common/content_export.h" -#include "content/common/p2p_sockets.h" +#include "content/public/common/p2p_socket_type.h" #include "ipc/ipc_sender.h" #include "net/base/completion_callback.h" #include "net/socket/tcp_server_socket.h" diff --git a/content/browser/renderer_host/p2p/socket_host_udp.cc b/content/browser/renderer_host/p2p/socket_host_udp.cc index 6b433f46ff..8201ccb552 100644 --- a/content/browser/renderer_host/p2p/socket_host_udp.cc +++ b/content/browser/renderer_host/p2p/socket_host_udp.cc @@ -5,10 +5,12 @@ #include "content/browser/renderer_host/p2p/socket_host_udp.h" #include "base/bind.h" +#include "base/command_line.h" #include "base/debug/trace_event.h" #include "base/stl_util.h" #include "content/browser/renderer_host/p2p/socket_host_throttler.h" #include "content/common/p2p_messages.h" +#include "content/public/common/content_switches.h" #include "ipc/ipc_sender.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" @@ -18,6 +20,8 @@ namespace { // UDP packets cannot be bigger than 64k. const int kReadBufferSize = 65536; +// Socket receive buffer size. +const int kRecvSocketBufferSize = 65536; // 64K // Defines set of transient errors. These errors are ignored when we get them // from sendto() or recvfrom() calls. @@ -39,6 +43,11 @@ bool IsTransientError(int error) { error == net::ERR_OUT_OF_MEMORY; } +bool AllowUDPWithoutSTUN() { + return CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableP2PSocketSTUNFilter); +} + } // namespace namespace content { @@ -87,6 +96,12 @@ bool P2PSocketHostUdp::Init(const net::IPEndPoint& local_address, return false; } + // Setting recv socket buffer size. + if (!socket_->SetReceiveBufferSize(kRecvSocketBufferSize)) { + LOG(WARNING) << "Failed to set socket receive buffer size to " + << kRecvSocketBufferSize; + } + net::IPEndPoint address; result = socket_->GetLocalAddress(&address); if (result < 0) { @@ -147,7 +162,7 @@ void P2PSocketHostUdp::HandleReadResult(int result) { if (!ContainsKey(connected_peers_, recv_address_)) { P2PSocketHost::StunMessageType type; bool stun = GetStunPacketType(&*data.begin(), data.size(), &type); - if (stun && IsRequestOrResponse(type)) { + if ((stun && IsRequestOrResponse(type)) || AllowUDPWithoutSTUN()) { connected_peers_.insert(recv_address_); } else if (!stun || type == STUN_DATA_INDICATION) { LOG(ERROR) << "Received unexpected data packet from " @@ -174,7 +189,7 @@ void P2PSocketHostUdp::Send(const net::IPEndPoint& to, return; } - if (!ContainsKey(connected_peers_, to)) { + if (!ContainsKey(connected_peers_, to) && !AllowUDPWithoutSTUN()) { P2PSocketHost::StunMessageType type = P2PSocketHost::StunMessageType(); bool stun = GetStunPacketType(&*data.begin(), data.size(), &type); if (!stun || type == STUN_DATA_INDICATION) { diff --git a/content/browser/renderer_host/p2p/socket_host_udp.h b/content/browser/renderer_host/p2p/socket_host_udp.h index ad0e354936..96b2244482 100644 --- a/content/browser/renderer_host/p2p/socket_host_udp.h +++ b/content/browser/renderer_host/p2p/socket_host_udp.h @@ -15,7 +15,7 @@ #include "base/message_loop/message_loop.h" #include "content/browser/renderer_host/p2p/socket_host.h" #include "content/common/content_export.h" -#include "content/common/p2p_sockets.h" +#include "content/public/common/p2p_socket_type.h" #include "net/base/ip_endpoint.h" #include "net/udp/udp_server_socket.h" diff --git a/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc b/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc index 5657f47ac9..3ccacfc288 100644 --- a/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc +++ b/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc @@ -140,6 +140,11 @@ class FakeDatagramServerSocket : public net::DatagramServerSocket { return net::ERR_NOT_IMPLEMENTED; } + virtual int SetMulticastInterface(uint32 interface_index) OVERRIDE { + NOTIMPLEMENTED(); + return net::ERR_NOT_IMPLEMENTED; + } + virtual int SetMulticastTimeToLive(int time_to_live) OVERRIDE { NOTIMPLEMENTED(); return net::ERR_NOT_IMPLEMENTED; diff --git a/content/browser/renderer_host/pepper/pepper_file_io_host.cc b/content/browser/renderer_host/pepper/pepper_file_io_host.cc index a0f2f68cca..ec8b6edc46 100644 --- a/content/browser/renderer_host/pepper/pepper_file_io_host.cc +++ b/content/browser/renderer_host/pepper/pepper_file_io_host.cc @@ -12,7 +12,6 @@ #include "content/browser/renderer_host/pepper/pepper_file_ref_host.h" #include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h" #include "content/browser/renderer_host/pepper/pepper_security_helper.h" -#include "content/browser/renderer_host/pepper/quota_file_io.h" #include "content/common/fileapi/file_system_messages.h" #include "content/common/sandbox_util.h" #include "content/common/view_messages.h" @@ -50,84 +49,6 @@ int32_t ErrorOrByteNumber(int32_t pp_error, int32_t byte_number) { return pp_error == PP_OK ? byte_number : pp_error; } -class QuotaFileIODelegate : public QuotaFileIO::Delegate { - public: - QuotaFileIODelegate(scoped_refptr<fileapi::FileSystemContext> context, - int render_process_id) - : context_(context), - weak_factory_(this) { } - virtual ~QuotaFileIODelegate() {} - - virtual void QueryAvailableSpace( - const GURL& origin, - quota::StorageType type, - const AvailableSpaceCallback& callback) OVERRIDE { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - quota::QuotaManagerProxy* quota_manager_proxy = - context_->quota_manager_proxy(); - DCHECK(quota_manager_proxy); - if (!quota_manager_proxy) { - callback.Run(0); - return; - } - quota::QuotaManager* qm = quota_manager_proxy->quota_manager(); - DCHECK(qm); - if (!qm) { - callback.Run(0); - return; - } - qm->GetUsageAndQuotaForWebApps( - origin, - type, - base::Bind(&QuotaFileIODelegate::GotUsageAndQuotaForWebApps, - weak_factory_.GetWeakPtr(), callback)); - } - - void GotUsageAndQuotaForWebApps(const AvailableSpaceCallback& callback, - quota::QuotaStatusCode code, - int64 usage, - int64 quota) { - if (code == quota::kQuotaStatusOk) - callback.Run(std::max(static_cast<int64>(0), quota - usage)); - else - callback.Run(0); - } - - virtual void WillUpdateFile(const GURL& file_path) OVERRIDE { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - fileapi::FileSystemURL url(context_->CrackURL(file_path)); - if (!url.is_valid()) - return; - const fileapi::UpdateObserverList* observers = - context_->GetUpdateObservers(url.type()); - if (!observers) - return; - observers->Notify(&fileapi::FileUpdateObserver::OnStartUpdate, - MakeTuple(url)); - } - virtual void DidUpdateFile(const GURL& file_path, int64_t delta) OVERRIDE { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - fileapi::FileSystemURL url(context_->CrackURL(file_path)); - if (!url.is_valid()) - return; - const fileapi::UpdateObserverList* observers = - context_->GetUpdateObservers(url.type()); - if (!observers) - return; - observers->Notify(&fileapi::FileUpdateObserver::OnUpdate, - MakeTuple(url, delta)); - observers->Notify(&fileapi::FileUpdateObserver::OnEndUpdate, - MakeTuple(url)); - } - virtual scoped_refptr<base::MessageLoopProxy> - GetFileThreadMessageLoopProxy() OVERRIDE { - return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE); - } - private: - scoped_refptr<fileapi::FileSystemContext> context_; - base::WeakPtrFactory<QuotaFileIODelegate> weak_factory_; -}; - PepperFileIOHost::UIThreadStuff GetUIThreadStuffForInternalFileSystems(int render_process_id) { PepperFileIOHost::UIThreadStuff stuff; @@ -168,9 +89,11 @@ PepperFileIOHost::PepperFileIOHost(BrowserPpapiHostImpl* host, browser_ppapi_host_(host), render_process_host_(NULL), file_(base::kInvalidPlatformFileValue), + open_flags_(0), file_system_type_(PP_FILESYSTEMTYPE_INVALID), quota_policy_(quota::kQuotaLimitTypeUnknown), - open_flags_(0), + max_written_offset_(0), + check_quota_(false), weak_factory_(this) { int unused; if (!host->GetRenderViewIDsForInstance(instance, @@ -251,7 +174,6 @@ int32_t PepperFileIOHost::OnHostMsgOpen( render_process_id_, file_system_url_)) return PP_ERROR_NOACCESS; - BrowserThread::PostTaskAndReplyWithResult( BrowserThread::UI, FROM_HERE, @@ -298,6 +220,7 @@ void PepperFileIOHost::GotUIThreadStuffForInternalFileSystems( host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenReply()); return; } + quota_policy_ = quota::kQuotaLimitTypeUnknown; quota::QuotaManagerProxy* quota_manager_proxy = file_system_context_->quota_manager_proxy(); @@ -325,8 +248,22 @@ void PepperFileIOHost::DidOpenInternalFile( base::PlatformFileError result, base::PlatformFile file, const base::Closure& on_close_callback) { - if (result == base::PLATFORM_FILE_OK) + if (result == base::PLATFORM_FILE_OK) { on_close_callback_ = on_close_callback; + + check_quota_ = file_system_host_ && file_system_host_->ChecksQuota(); + if (check_quota_) { + file_system_host_->OpenQuotaFile( + this, + file_system_url_.path(), + base::Bind(&PepperFileIOHost::DidOpenQuotaFile, + weak_factory_.GetWeakPtr(), + reply_context, + file)); + return; + } + } + ExecutePlatformOpenFileCallback( reply_context, result, base::PassPlatformFile(&file), true); } @@ -378,26 +315,43 @@ int32_t PepperFileIOHost::OnHostMsgWrite( FileIOStateManager::OPERATION_WRITE, true); if (rv != PP_OK) return rv; + if (offset < 0) + return PP_ERROR_BADARGUMENT; - QuotaFileIO::WriteCallback cb = - base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback, - weak_factory_.GetWeakPtr(), - context->MakeReplyMessageContext()); + if (check_quota_) { + int64_t actual_offset = + (open_flags_ & PP_FILEOPENFLAG_APPEND) ? max_written_offset_ : offset; - if (quota_file_io_) { - if (!quota_file_io_->Write(offset, buffer.c_str(), buffer.size(), cb)) - return PP_ERROR_FAILED; - } else { - if (!base::FileUtilProxy::Write( - file_message_loop_, - file_, - offset, - buffer.c_str(), - buffer.size(), - cb)) - return PP_ERROR_FAILED; + uint64_t max_offset = actual_offset + buffer.size(); + if (max_offset > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) + return PP_ERROR_FAILED; // max_offset overflows. + int64_t amount = static_cast<int64_t>(max_offset) - max_written_offset_; + + // Quota request amounts are restricted to 32 bits so we can use atomics + // when we move this code to the plugin side of the proxy. + if (amount > std::numeric_limits<int32_t>::max()) + return PP_ERROR_NOQUOTA; + + if (amount > 0) { + int32_t result = file_system_host_->RequestQuota( + static_cast<int32_t>(amount), + base::Bind(&PepperFileIOHost::GotWriteQuota, + weak_factory_.GetWeakPtr(), + context->MakeReplyMessageContext(), + offset, buffer)); + if (result == PP_OK_COMPLETIONPENDING) { + state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE); + return result; + } + // RequestQuota returns either PP_OK_COMPLETIONPENDING or the requested + // quota amount. + DCHECK(result > 0); + } } + if (!CallWrite(context->MakeReplyMessageContext(), offset, buffer)) + return PP_ERROR_FAILED; + state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE); return PP_OK_COMPLETIONPENDING; } @@ -409,20 +363,37 @@ int32_t PepperFileIOHost::OnHostMsgSetLength( FileIOStateManager::OPERATION_EXCLUSIVE, true); if (rv != PP_OK) return rv; + if (length < 0) + return PP_ERROR_BADARGUMENT; - base::FileUtilProxy::StatusCallback cb = - base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback, - weak_factory_.GetWeakPtr(), - context->MakeReplyMessageContext()); - - if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) { - if (!quota_file_io_->SetLength(length, cb)) - return PP_ERROR_FAILED; - } else { - if (!base::FileUtilProxy::Truncate(file_message_loop_, file_, length, cb)) - return PP_ERROR_FAILED; + if (check_quota_) { + int64_t amount = length - max_written_offset_; + // Quota request amounts are restricted to 32 bits so we can use atomics + // when we move this code to the plugin side of the proxy. + if (amount > std::numeric_limits<int32_t>::max()) + return PP_ERROR_NOQUOTA; + + if (amount > 0) { + int32_t result = file_system_host_->RequestQuota( + static_cast<int32_t>(amount), + base::Bind(&PepperFileIOHost::GotSetLengthQuota, + weak_factory_.GetWeakPtr(), + context->MakeReplyMessageContext(), + length)); + if (result == PP_OK_COMPLETIONPENDING) { + state_manager_.SetPendingOperation( + FileIOStateManager::OPERATION_EXCLUSIVE); + return result; + } + // RequestQuota returns either PP_OK_COMPLETIONPENDING or the requested + // quota amount. + DCHECK(result > 0); + } } + if (!CallSetLength(context->MakeReplyMessageContext(), length)) + return PP_ERROR_FAILED; + state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); return PP_OK_COMPLETIONPENDING; } @@ -448,6 +419,9 @@ int32_t PepperFileIOHost::OnHostMsgFlush( int32_t PepperFileIOHost::OnHostMsgClose( ppapi::host::HostMessageContext* context) { + if (check_quota_) + file_system_host_->CloseQuotaFile(this); + if (file_ != base::kInvalidPlatformFileValue) { base::FileUtilProxy::Close( file_message_loop_, @@ -455,11 +429,84 @@ int32_t PepperFileIOHost::OnHostMsgClose( base::Bind(&PepperFileIOHost::DidCloseFile, weak_factory_.GetWeakPtr())); file_ = base::kInvalidPlatformFileValue; - quota_file_io_.reset(); } return PP_OK; } +void PepperFileIOHost::DidOpenQuotaFile( + ppapi::host::ReplyMessageContext reply_context, + base::PlatformFile file, + int64_t max_written_offset) { + max_written_offset_ = max_written_offset; + DCHECK_LE(0, max_written_offset_); + + ExecutePlatformOpenFileCallback( + reply_context, base::PLATFORM_FILE_OK, base::PassPlatformFile(&file), + true); +} + +void PepperFileIOHost::GotWriteQuota( + ppapi::host::ReplyMessageContext reply_context, + int64_t offset, + const std::string& buffer, + int32_t granted) { + if (granted == 0) { + reply_context.params.set_result(PP_ERROR_NOQUOTA); + } else if (!CallWrite(reply_context, offset, buffer)) { + reply_context.params.set_result(PP_ERROR_FAILED); + } else { + max_written_offset_ += granted; + return; + } + // Return the error result set above. + host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply()); + state_manager_.SetOperationFinished(); +} + +void PepperFileIOHost::GotSetLengthQuota( + ppapi::host::ReplyMessageContext reply_context, + int64_t length, + int32_t granted) { + if (granted == 0) { + reply_context.params.set_result(PP_ERROR_NOQUOTA); + } else if (!CallSetLength(reply_context, length)) { + reply_context.params.set_result(PP_ERROR_FAILED); + } else { + max_written_offset_ += granted; + return; + } + // Return the error result set above. + host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply()); + state_manager_.SetOperationFinished(); +} + +bool PepperFileIOHost::CallWrite( + ppapi::host::ReplyMessageContext reply_context, + int64_t offset, + const std::string& buffer) { + return base::FileUtilProxy::Write( + file_message_loop_, + file_, + offset, + buffer.c_str(), + buffer.size(), + base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback, + weak_factory_.GetWeakPtr(), + reply_context)); +} + +bool PepperFileIOHost::CallSetLength( + ppapi::host::ReplyMessageContext reply_context, + int64_t length) { + return base::FileUtilProxy::Truncate( + file_message_loop_, + file_, + length, + base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback, + weak_factory_.GetWeakPtr(), + reply_context)); +} + void PepperFileIOHost::DidCloseFile(base::PlatformFileError error) { // Silently ignore if we fail to close the file. if (!on_close_callback_.is_null()) { @@ -525,13 +572,7 @@ void PepperFileIOHost::ExecutePlatformOpenFileCallback( DCHECK(file_ == base::kInvalidPlatformFileValue); file_ = file.ReleaseValue(); - DCHECK(!quota_file_io_.get()); if (file_ != base::kInvalidPlatformFileValue) { - if (ppapi::FileSystemTypeHasQuota(file_system_type_)) { - quota_file_io_.reset(new QuotaFileIO( - new QuotaFileIODelegate(file_system_context_, render_process_id_), - file_, file_system_url_.ToGURL(), file_system_type_)); - } int32_t flags_to_send = open_flags_; if (!host()->permissions().HasPermission(ppapi::PERMISSION_DEV)) { // IMPORTANT: Clear PP_FILEOPENFLAG_WRITE and PP_FILEOPENFLAG_APPEND so diff --git a/content/browser/renderer_host/pepper/pepper_file_io_host.h b/content/browser/renderer_host/pepper/pepper_file_io_host.h index dd5d8dd527..1c5cfcda8e 100644 --- a/content/browser/renderer_host/pepper/pepper_file_io_host.h +++ b/content/browser/renderer_host/pepper/pepper_file_io_host.h @@ -23,11 +23,8 @@ #include "webkit/browser/fileapi/file_system_context.h" #include "webkit/common/quota/quota_types.h" -using ppapi::host::ReplyMessageContext; - namespace content { class PepperFileSystemBrowserHost; -class QuotaFileIO; class PepperFileIOHost : public ppapi::host::ResourceHost, public base::SupportsWeakPtr<PepperFileIOHost> { @@ -45,6 +42,12 @@ class PepperFileIOHost : public ppapi::host::ResourceHost, const IPC::Message& msg, ppapi::host::HostMessageContext* context) OVERRIDE; + // Direct access for PepperFileSystemBrowserHost. + int64_t max_written_offset() const { return max_written_offset_; } + void set_max_written_offset(int64_t max_written_offset) { + max_written_offset_ = max_written_offset; + } + struct UIThreadStuff { UIThreadStuff(); ~UIThreadStuff(); @@ -76,31 +79,50 @@ class PepperFileIOHost : public ppapi::host::ResourceHost, // PP_Error code and send back the reply. Note that the argument // ReplyMessageContext is copied so that we have a closure containing all // necessary information to reply. - void ExecutePlatformGeneralCallback(ReplyMessageContext reply_context, - base::PlatformFileError error_code); - void ExecutePlatformOpenFileCallback(ReplyMessageContext reply_context, - base::PlatformFileError error_code, - base::PassPlatformFile file, - bool unused_created); - void ExecutePlatformWriteCallback(ReplyMessageContext reply_context, - base::PlatformFileError error_code, - int bytes_written); + void ExecutePlatformGeneralCallback( + ppapi::host::ReplyMessageContext reply_context, + base::PlatformFileError error_code); + void ExecutePlatformOpenFileCallback( + ppapi::host::ReplyMessageContext reply_context, + base::PlatformFileError error_code, + base::PassPlatformFile file, + bool unused_created); + void ExecutePlatformWriteCallback( + ppapi::host::ReplyMessageContext reply_context, + base::PlatformFileError error_code, + int bytes_written); void GotUIThreadStuffForInternalFileSystems( - ReplyMessageContext reply_context, + ppapi::host::ReplyMessageContext reply_context, int platform_file_flags, UIThreadStuff ui_thread_stuff); void DidOpenInternalFile( - ReplyMessageContext reply_context, + ppapi::host::ReplyMessageContext reply_context, base::PlatformFileError result, base::PlatformFile file, const base::Closure& on_close_callback); void GotResolvedRenderProcessId( - ReplyMessageContext reply_context, + ppapi::host::ReplyMessageContext reply_context, base::FilePath path, int platform_file_flags, base::ProcessId resolved_render_process_id); + void DidOpenQuotaFile(ppapi::host::ReplyMessageContext reply_context, + base::PlatformFile file, + int64_t max_written_offset); + void GotWriteQuota(ppapi::host::ReplyMessageContext reply_context, + int64_t offset, + const std::string& buffer, + int32_t granted); + void GotSetLengthQuota(ppapi::host::ReplyMessageContext reply_context, + int64_t length, + int32_t granted); + bool CallWrite(ppapi::host::ReplyMessageContext reply_context, + int64_t offset, + const std::string& buffer); + bool CallSetLength(ppapi::host::ReplyMessageContext reply_context, + int64_t length); + void DidCloseFile(base::PlatformFileError error); // Adds file_ to |reply_context| with the specified |open_flags|. @@ -115,6 +137,7 @@ class PepperFileIOHost : public ppapi::host::ResourceHost, base::ProcessId resolved_render_process_id_; base::PlatformFile file_; + int32_t open_flags_; // The file system type specified in the Open() call. This will be // PP_FILESYSTEMTYPE_INVALID before open was called. This value does not @@ -122,19 +145,15 @@ class PepperFileIOHost : public ppapi::host::ResourceHost, PP_FileSystemType file_system_type_; base::WeakPtr<PepperFileSystemBrowserHost> file_system_host_; + // Used to check if we can pass file handle to plugins. + quota::QuotaLimitType quota_policy_; + // Valid only for PP_FILESYSTEMTYPE_LOCAL{PERSISTENT,TEMPORARY}. scoped_refptr<fileapi::FileSystemContext> file_system_context_; fileapi::FileSystemURL file_system_url_; base::Closure on_close_callback_; - - // Used to check if we can pass file handle to plugins. - quota::QuotaLimitType quota_policy_; - - // Pointer to a QuotaFileIO instance, which is valid only while a file - // of type PP_FILESYSTEMTYPE_LOCAL{PERSISTENT,TEMPORARY} is opened. - scoped_ptr<QuotaFileIO> quota_file_io_; - - int32_t open_flags_; + int64_t max_written_offset_; + bool check_quota_; ppapi::FileIOStateManager state_manager_; diff --git a/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc b/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc index a5064a69e4..94b3263a62 100644 --- a/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc +++ b/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc @@ -6,6 +6,8 @@ #include "base/bind.h" #include "base/callback.h" +#include "content/browser/renderer_host/pepper/pepper_file_io_host.h" +#include "content/browser/renderer_host/pepper/quota_reservation.h" #include "content/public/browser/browser_ppapi_host.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/plugin_service.h" @@ -19,7 +21,6 @@ #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/shared_impl/file_system_util.h" #include "ppapi/shared_impl/file_type_conversion.h" -#include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_operation_runner.h" #include "webkit/browser/fileapi/isolated_context.h" #include "webkit/common/fileapi/file_system_util.h" @@ -28,6 +29,9 @@ namespace content { namespace { +// This is the minimum amount of quota we reserve per file system. +const int64_t kMinimumQuotaReservationSize = 1024 * 1024; // 1 MB + scoped_refptr<fileapi::FileSystemContext> GetFileSystemContextFromRenderId(int render_process_id) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -42,6 +46,16 @@ GetFileSystemContextFromRenderId(int render_process_id) { } // namespace +PepperFileSystemBrowserHost::QuotaRequest::QuotaRequest( + int32_t amount_arg, + const RequestQuotaCallback& callback_arg) + : amount(amount_arg), + callback(callback_arg) { +} + +PepperFileSystemBrowserHost::QuotaRequest::~QuotaRequest() { +} + PepperFileSystemBrowserHost::PepperFileSystemBrowserHost(BrowserPpapiHost* host, PP_Instance instance, PP_Resource resource, @@ -52,6 +66,8 @@ PepperFileSystemBrowserHost::PepperFileSystemBrowserHost(BrowserPpapiHost* host, called_open_(false), opened_(false), file_system_context_(NULL), + reserved_quota_(0), + reserving_quota_(false), weak_factory_(this) { } @@ -78,7 +94,7 @@ void PepperFileSystemBrowserHost::OpenExisting(const GURL& root_url, BrowserThread::UI, FROM_HERE, base::Bind(&GetFileSystemContextFromRenderId, render_process_id), - base::Bind(&PepperFileSystemBrowserHost::OpenExistingWithContext, + base::Bind(&PepperFileSystemBrowserHost::OpenExistingFileSystem, weak_factory_.GetWeakPtr(), callback)); } @@ -100,6 +116,67 @@ bool PepperFileSystemBrowserHost::IsFileSystemHost() { return true; } +void PepperFileSystemBrowserHost::OpenQuotaFile( + PepperFileIOHost* file_io_host, + const base::FilePath& file_path, + const OpenQuotaFileCallback& callback) { + int32_t id = file_io_host->pp_resource(); + std::pair<FileMap::iterator, bool> insert_result = + files_.insert(std::make_pair(id, file_io_host)); + if (insert_result.second) { + base::PostTaskAndReplyWithResult( + file_system_context_->default_file_task_runner(), + FROM_HERE, + base::Bind(&QuotaReservation::OpenFile, + quota_reservation_, + id, + file_path), + callback); + } else { + NOTREACHED(); + } +} + +void PepperFileSystemBrowserHost::CloseQuotaFile( + PepperFileIOHost* file_io_host) { + int32_t id = file_io_host->pp_resource(); + int64_t max_written_offset = 0; + FileMap::iterator it = files_.find(id); + if (it != files_.end()) { + max_written_offset = file_io_host->max_written_offset(); + files_.erase(it); + } else { + NOTREACHED(); + return; + } + + file_system_context_->default_file_task_runner()->PostTask( + FROM_HERE, + base::Bind(&QuotaReservation::CloseFile, + quota_reservation_, + id, + max_written_offset)); +} + +int32_t PepperFileSystemBrowserHost::RequestQuota( + int32_t amount, + const RequestQuotaCallback& callback) { + DCHECK(amount >= 0); + if (!reserving_quota_ && reserved_quota_ >= amount) { + reserved_quota_ -= amount; + return amount; + } + + // Queue up a pending quota request. + pending_quota_requests_.push(QuotaRequest(amount, callback)); + + // Reserve more quota if we haven't already. + if (!reserving_quota_) + ReserveQuota(amount); + + return PP_OK_COMPLETIONPENDING; +} + int32_t PepperFileSystemBrowserHost::OnHostMsgOpen( ppapi::host::HostMessageContext* context, int64_t /* unused */) { @@ -128,14 +205,14 @@ int32_t PepperFileSystemBrowserHost::OnHostMsgOpen( BrowserThread::UI, FROM_HERE, base::Bind(&GetFileSystemContextFromRenderId, render_process_id), - base::Bind(&PepperFileSystemBrowserHost::GotFileSystemContext, + base::Bind(&PepperFileSystemBrowserHost::OpenFileSystem, weak_factory_.GetWeakPtr(), context->MakeReplyMessageContext(), file_system_type)); return PP_OK_COMPLETIONPENDING; } -void PepperFileSystemBrowserHost::OpenExistingWithContext( +void PepperFileSystemBrowserHost::OpenExistingFileSystem( const base::Closure& callback, scoped_refptr<fileapi::FileSystemContext> file_system_context) { if (file_system_context.get()) { @@ -147,10 +224,15 @@ void PepperFileSystemBrowserHost::OpenExistingWithContext( LOG(WARNING) << "Could not retrieve file system context."; } SetFileSystemContext(file_system_context); + + int32_t pp_error = CreateQuotaReservation(callback); + if (pp_error == PP_OK_COMPLETIONPENDING) + return; + callback.Run(); } -void PepperFileSystemBrowserHost::GotFileSystemContext( +void PepperFileSystemBrowserHost::OpenFileSystem( ppapi::host::ReplyMessageContext reply_context, fileapi::FileSystemType file_system_type, scoped_refptr<fileapi::FileSystemContext> file_system_context) { @@ -159,13 +241,16 @@ void PepperFileSystemBrowserHost::GotFileSystemContext( reply_context, GURL(), std::string(), base::PLATFORM_FILE_ERROR_FAILED); return; } + + SetFileSystemContext(file_system_context); + GURL origin = browser_ppapi_host_->GetDocumentURLForInstance( pp_instance()).GetOrigin(); - file_system_context->OpenFileSystem(origin, file_system_type, + file_system_context_->OpenFileSystem(origin, file_system_type, fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, base::Bind(&PepperFileSystemBrowserHost::OpenFileSystemComplete, - weak_factory_.GetWeakPtr(), reply_context)); - SetFileSystemContext(file_system_context); + weak_factory_.GetWeakPtr(), + reply_context)); } void PepperFileSystemBrowserHost::OpenFileSystemComplete( @@ -177,12 +262,20 @@ void PepperFileSystemBrowserHost::OpenFileSystemComplete( if (pp_error == PP_OK) { opened_ = true; root_url_ = root; + + pp_error = CreateQuotaReservation( + base::Bind(&PepperFileSystemBrowserHost::SendReplyForFileSystem, + weak_factory_.GetWeakPtr(), + reply_context, + static_cast<int32_t>(PP_OK))); + if (pp_error == PP_OK_COMPLETIONPENDING) + return; + // For PP_OK and all other error codes, we can send the reply now. } - reply_context.params.set_result(pp_error); - host()->SendReply(reply_context, PpapiPluginMsg_FileSystem_OpenReply()); + SendReplyForFileSystem(reply_context, pp_error); } -void PepperFileSystemBrowserHost::GotIsolatedFileSystemContext( +void PepperFileSystemBrowserHost::OpenIsolatedFileSystem( ppapi::host::ReplyMessageContext reply_context, const std::string& fsid, PP_IsolatedFileSystemType_Private type, @@ -273,16 +366,27 @@ int32_t PepperFileSystemBrowserHost::OnHostMsgInitIsolatedFileSystem( return PP_ERROR_FAILED; } + root_url_ = GURL(fileapi::GetIsolatedFileSystemRootURIString( + browser_ppapi_host_->GetDocumentURLForInstance(pp_instance()).GetOrigin(), + fsid, ppapi::IsolatedFileSystemTypeToRootName(type))); + BrowserThread::PostTaskAndReplyWithResult( BrowserThread::UI, FROM_HERE, base::Bind(&GetFileSystemContextFromRenderId, render_process_id), - base::Bind(&PepperFileSystemBrowserHost::GotIsolatedFileSystemContext, + base::Bind(&PepperFileSystemBrowserHost::OpenIsolatedFileSystem, weak_factory_.GetWeakPtr(), context->MakeReplyMessageContext(), fsid, type)); return PP_OK_COMPLETIONPENDING; } +void PepperFileSystemBrowserHost::SendReplyForFileSystem( + ppapi::host::ReplyMessageContext reply_context, + int32_t pp_error) { + reply_context.params.set_result(pp_error); + host()->SendReply(reply_context, PpapiPluginMsg_FileSystem_OpenReply()); +} + void PepperFileSystemBrowserHost::SendReplyForIsolatedFileSystem( ppapi::host::ReplyMessageContext reply_context, const std::string& fsid, @@ -303,6 +407,95 @@ void PepperFileSystemBrowserHost::SetFileSystemContext( } } +int32_t PepperFileSystemBrowserHost::CreateQuotaReservation( + const base::Closure& callback) { + if (!ppapi::FileSystemTypeHasQuota(type_)) + return PP_OK; + + DCHECK(root_url_.is_valid()); + base::PostTaskAndReplyWithResult( + file_system_context_->default_file_task_runner(), + FROM_HERE, + base::Bind(&QuotaReservation::Create, + file_system_context_, + root_url_.GetOrigin(), + ppapi::PepperFileSystemTypeToFileSystemType(type_)), + base::Bind(&PepperFileSystemBrowserHost::GotQuotaReservation, + weak_factory_.GetWeakPtr(), + callback)); + return PP_OK_COMPLETIONPENDING; +} + +void PepperFileSystemBrowserHost::GotQuotaReservation( + const base::Closure& callback, + scoped_refptr<QuotaReservation> quota_reservation) { + quota_reservation_ = quota_reservation; + callback.Run(); +} + +void PepperFileSystemBrowserHost::ReserveQuota(int32_t amount) { + DCHECK(!reserving_quota_); + reserving_quota_ = true; + + // Get the max_written_offset for each open file. + QuotaReservation::OffsetMap max_written_offsets; + for (FileMap::iterator it = files_.begin(); it != files_.end(); ++ it) { + max_written_offsets.insert( + std::make_pair(it->first, it->second->max_written_offset())); + } + + int64_t reservation_amount = std::max<int64_t>(kMinimumQuotaReservationSize, + amount); + file_system_context_->default_file_task_runner()->PostTask( + FROM_HERE, + base::Bind(&QuotaReservation::ReserveQuota, + quota_reservation_, + reservation_amount, + max_written_offsets, + base::Bind(&PepperFileSystemBrowserHost::GotReservedQuota, + weak_factory_.GetWeakPtr()))); +} + +void PepperFileSystemBrowserHost::GotReservedQuota( + int64_t amount, + const QuotaReservation::OffsetMap& max_written_offsets) { + DCHECK(reserving_quota_); + reserving_quota_ = false; + reserved_quota_ = amount; + + // Update open files with their new base sizes. This won't write over any + // updates since the files are waiting for quota and can't write. + for (FileMap::iterator it = files_.begin(); it != files_.end(); ++ it) { + QuotaReservation::OffsetMap::const_iterator offset_it = + max_written_offsets.find(it->first); + if (offset_it != max_written_offsets.end()) + it->second->set_max_written_offset(offset_it->second); + else + NOTREACHED(); + } + + DCHECK(!pending_quota_requests_.empty()); + // If we can't grant the first request after refreshing reserved_quota_, then + // fail all pending quota requests to avoid an infinite refresh/fail loop. + bool fail_all = reserved_quota_ < pending_quota_requests_.front().amount; + while (!pending_quota_requests_.empty()) { + QuotaRequest& request = pending_quota_requests_.front(); + if (fail_all) { + request.callback.Run(0); + pending_quota_requests_.pop(); + } else if (reserved_quota_ >= request.amount) { + reserved_quota_ -= request.amount; + request.callback.Run(request.amount); + pending_quota_requests_.pop(); + } else { + // Refresh the quota reservation for the first pending request that we + // can't satisfy. + ReserveQuota(request.amount); + break; + } + } +} + std::string PepperFileSystemBrowserHost::GetPluginMimeType() const { base::FilePath plugin_path = browser_ppapi_host_->GetPluginPath(); PepperPluginInfo* info = diff --git a/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h b/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h index e872bc5b49..5dcf333eb5 100644 --- a/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h +++ b/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h @@ -5,11 +5,14 @@ #ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_FILE_SYSTEM_BROWSER_HOST_H_ #define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_FILE_SYSTEM_BROWSER_HOST_H_ +#include <queue> #include <string> +#include <vector> #include "base/basictypes.h" #include "base/callback.h" #include "base/memory/weak_ptr.h" +#include "content/browser/renderer_host/pepper/quota_reservation.h" #include "content/common/content_export.h" #include "ppapi/c/pp_file_info.h" #include "ppapi/c/private/ppb_isolated_file_system_private.h" @@ -17,11 +20,11 @@ #include "ppapi/host/resource_host.h" #include "url/gurl.h" #include "webkit/browser/fileapi/file_system_context.h" -#include "webkit/common/fileapi/file_system_types.h" namespace content { class BrowserPpapiHost; +class PepperFileIOHost; class CONTENT_EXPORT PepperFileSystemBrowserHost : public ppapi::host::ResourceHost, @@ -41,7 +44,7 @@ class CONTENT_EXPORT PepperFileSystemBrowserHost // Calls |callback| when complete. void OpenExisting(const GURL& root_url, const base::Closure& callback); - // ppapi::host::ResourceHost override. + // ppapi::host::ResourceHost overrides. virtual int32_t OnResourceMessageReceived( const IPC::Message& msg, ppapi::host::HostMessageContext* context) OVERRIDE; @@ -60,14 +63,39 @@ class CONTENT_EXPORT PepperFileSystemBrowserHost fileapi::FileSystemOperationRunner* GetFileSystemOperationRunner() const { return file_system_operation_runner_.get(); } - + bool ChecksQuota() const { return quota_reservation_ != NULL; } + // Opens a file for writing with quota checks. Returns the file size in the + // callback. + typedef base::Callback<void(int64_t)> OpenQuotaFileCallback; + void OpenQuotaFile(PepperFileIOHost* file_io_host, + const base::FilePath& file_path, + const OpenQuotaFileCallback& callback); + // Closes the file. This must be called after OpenQuotaFile and before the + // PepperFileIOHost is destroyed. + void CloseQuotaFile(PepperFileIOHost* file_io_host); + // Requests the given amount of quota. Returns the amount requested or + // PP_OK_COMPLETIONPENDING, in which case the amount granted is returned in + // the callback. Requests can't partially succeed so the amount granted is + // either 0 or the amount of the request. Requesting an amount of 0 will + // return immediately with a 0 result. + typedef base::Callback<void(int32_t)> RequestQuotaCallback; + int32_t RequestQuota(int32_t amount, + const RequestQuotaCallback& callback); private: friend class PepperFileSystemBrowserHostTest; - void OpenExistingWithContext( + struct QuotaRequest { + QuotaRequest(int32_t amount, const RequestQuotaCallback& callback); + ~QuotaRequest(); + + int32_t amount; + RequestQuotaCallback callback; + }; + + void OpenExistingFileSystem( const base::Closure& callback, scoped_refptr<fileapi::FileSystemContext> file_system_context); - void GotFileSystemContext( + void OpenFileSystem( ppapi::host::ReplyMessageContext reply_context, fileapi::FileSystemType file_system_type, scoped_refptr<fileapi::FileSystemContext> file_system_context); @@ -76,7 +104,7 @@ class CONTENT_EXPORT PepperFileSystemBrowserHost const GURL& root, const std::string& name, base::PlatformFileError error); - void GotIsolatedFileSystemContext( + void OpenIsolatedFileSystem( ppapi::host::ReplyMessageContext reply_context, const std::string& fsid, PP_IsolatedFileSystemType_Private type, @@ -97,6 +125,9 @@ class CONTENT_EXPORT PepperFileSystemBrowserHost const std::string& fsid, PP_IsolatedFileSystemType_Private type); + void SendReplyForFileSystem( + ppapi::host::ReplyMessageContext reply_context, + int32_t pp_error); void SendReplyForIsolatedFileSystem( ppapi::host::ReplyMessageContext reply_context, const std::string& fsid, @@ -105,6 +136,15 @@ class CONTENT_EXPORT PepperFileSystemBrowserHost void SetFileSystemContext( scoped_refptr<fileapi::FileSystemContext> file_system_context); + int32_t CreateQuotaReservation(const base::Closure& callback); + void GotQuotaReservation( + const base::Closure& callback, + scoped_refptr<QuotaReservation> quota_reservation); + + void ReserveQuota(int32_t amount); + void GotReservedQuota(int64_t amount, + const QuotaReservation::OffsetMap& max_written_offsets); + std::string GetPluginMimeType() const; // Returns plugin ID generated from plugin's MIME type. @@ -114,12 +154,24 @@ class CONTENT_EXPORT PepperFileSystemBrowserHost PP_FileSystemType type_; bool called_open_; // whether open has been called. - bool opened_; // whether open has succeeded. + bool opened_; // whether open succeeded. GURL root_url_; scoped_refptr<fileapi::FileSystemContext> file_system_context_; scoped_ptr<fileapi::FileSystemOperationRunner> file_system_operation_runner_; + // Used only for file systems with quota. + // When a PepperFileIOHost calls OpenQuotaFile, we add the id and a non-owning + // pointer to this map. CloseQuotaFile must be called when before the host is + // destroyed. + typedef std::map<int32_t, PepperFileIOHost*> FileMap; + FileMap files_; + std::queue<QuotaRequest> pending_quota_requests_; + int64_t reserved_quota_; + bool reserving_quota_; + // Access only on the FileSystemContext's default_file_task_runner(). + scoped_refptr<QuotaReservation> quota_reservation_; + std::string fsid_; // used only for isolated filesystems. base::WeakPtrFactory<PepperFileSystemBrowserHost> weak_factory_; diff --git a/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc b/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc index 7e010d6dbb..ba8a8b9136 100644 --- a/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc +++ b/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc @@ -194,7 +194,7 @@ int32_t PepperFlashFileMessageFilter::OnCreateDir( base::PLATFORM_FILE_ERROR_ACCESS_DENIED); } - bool result = file_util::CreateDirectory(full_path); + bool result = base::CreateDirectory(full_path); return ppapi::PlatformFileErrorToPepperError(result ? base::PLATFORM_FILE_OK : base::PLATFORM_FILE_ERROR_ACCESS_DENIED); } @@ -210,7 +210,7 @@ int32_t PepperFlashFileMessageFilter::OnQueryFile( } base::PlatformFileInfo info; - bool result = file_util::GetFileInfo(full_path, &info); + bool result = base::GetFileInfo(full_path, &info); context->reply_msg = PpapiPluginMsg_FlashFile_QueryFileReply(info); return ppapi::PlatformFileErrorToPepperError(result ? base::PLATFORM_FILE_OK : base::PLATFORM_FILE_ERROR_ACCESS_DENIED); @@ -253,13 +253,13 @@ int32_t PepperFlashFileMessageFilter::OnCreateTemporaryFile( dir_path, base::Bind(&CanCreateReadWrite)); if (validated_dir_path.empty() || (!base::DirectoryExists(validated_dir_path) && - !file_util::CreateDirectory(validated_dir_path))) { + !base::CreateDirectory(validated_dir_path))) { return ppapi::PlatformFileErrorToPepperError( base::PLATFORM_FILE_ERROR_ACCESS_DENIED); } base::FilePath file_path; - if (!file_util::CreateTemporaryFileInDir(validated_dir_path, &file_path)) { + if (!base::CreateTemporaryFileInDir(validated_dir_path, &file_path)) { return ppapi::PlatformFileErrorToPepperError( base::PLATFORM_FILE_ERROR_FAILED); } diff --git a/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc b/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc index e5cdcc6b01..3530e1e1b5 100644 --- a/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc +++ b/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc @@ -73,7 +73,7 @@ void GetFontsInFamily_SlowBlocking(const std::string& family, LOGFONTW logfont; memset(&logfont, 0, sizeof(logfont)); logfont.lfCharSet = DEFAULT_CHARSET; - string16 family16 = UTF8ToUTF16(family); + base::string16 family16 = UTF8ToUTF16(family); memcpy(&logfont.lfFaceName, &family16[0], sizeof(logfont.lfFaceName)); base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL)); ::EnumFontFamiliesExW(hdc, &logfont, (FONTENUMPROCW)&EnumFontsInFamilyProc, diff --git a/content/browser/renderer_host/pepper/quota_file_io.cc b/content/browser/renderer_host/pepper/quota_file_io.cc deleted file mode 100644 index 0768574200..0000000000 --- a/content/browser/renderer_host/pepper/quota_file_io.cc +++ /dev/null @@ -1,359 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/renderer_host/pepper/quota_file_io.h" - -#include <algorithm> - -#include "base/bind.h" -#include "base/location.h" -#include "base/memory/weak_ptr.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/stl_util.h" -#include "base/task_runner_util.h" - -using base::PlatformFile; -using base::PlatformFileError; -using quota::StorageType; - -namespace content { - -namespace { -StorageType PPFileSystemTypeToQuotaStorageType(PP_FileSystemType type) { - switch (type) { - case PP_FILESYSTEMTYPE_LOCALPERSISTENT: - return quota::kStorageTypePersistent; - case PP_FILESYSTEMTYPE_LOCALTEMPORARY: - return quota::kStorageTypeTemporary; - default: - return quota::kStorageTypeUnknown; - } - NOTREACHED(); - return quota::kStorageTypeUnknown; -} - -int WriteAdapter(PlatformFile file, int64 offset, - scoped_ptr<char[]> data, int size) { - return base::WritePlatformFile(file, offset, data.get(), size); -} - -} // namespace - -class QuotaFileIO::PendingOperationBase { - public: - virtual ~PendingOperationBase() {} - - // Either one of Run() or DidFail() is called (the latter is called when - // there was more than one error during quota queries). - virtual void Run() = 0; - virtual void DidFail(PlatformFileError error) = 0; - - protected: - explicit PendingOperationBase(QuotaFileIO* quota_io) : quota_io_(quota_io) { - DCHECK(quota_io_); - quota_io_->WillUpdate(); - } - - QuotaFileIO* quota_io_; -}; - -class QuotaFileIO::WriteOperation : public PendingOperationBase { - public: - WriteOperation(QuotaFileIO* quota_io, - int64_t offset, - const char* buffer, - int32_t bytes_to_write, - const WriteCallback& callback) - : PendingOperationBase(quota_io), - offset_(offset), - bytes_to_write_(bytes_to_write), - callback_(callback), - finished_(false), - status_(base::PLATFORM_FILE_OK), - bytes_written_(0), - weak_factory_(this) { - // TODO(kinuko): Check the API convention if we really need to keep a copy - // of the buffer during the async write operations. - buffer_.reset(new char[bytes_to_write]); - memcpy(buffer_.get(), buffer, bytes_to_write); - } - virtual ~WriteOperation() {} - virtual void Run() OVERRIDE { - DCHECK(quota_io_); - if (quota_io_->CheckIfExceedsQuota(offset_ + bytes_to_write_)) { - DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); - return; - } - DCHECK(buffer_.get()); - - if (!base::PostTaskAndReplyWithResult( - quota_io_->delegate()->GetFileThreadMessageLoopProxy().get(), - FROM_HERE, - base::Bind(&WriteAdapter, - quota_io_->file_, - offset_, - base::Passed(&buffer_), - bytes_to_write_), - base::Bind(&WriteOperation::DidWrite, - weak_factory_.GetWeakPtr()))) { - DidFail(base::PLATFORM_FILE_ERROR_FAILED); - return; - } - } - - virtual void DidFail(PlatformFileError error) OVERRIDE { - DidFinish(error, 0); - } - - bool finished() const { return finished_; } - - virtual void WillRunCallback() { - base::MessageLoopProxy::current()->PostTask( - FROM_HERE, - base::Bind(&WriteOperation::RunCallback, weak_factory_.GetWeakPtr())); - } - - private: - void DidWrite(int bytes_written) { - base::PlatformFileError error = bytes_written > 0 ? - base::PLATFORM_FILE_OK : base::PLATFORM_FILE_ERROR_FAILED; - DidFinish(error, bytes_written); - } - - void DidFinish(PlatformFileError status, int bytes_written) { - finished_ = true; - status_ = status; - bytes_written_ = bytes_written; - int64_t max_offset = - (status != base::PLATFORM_FILE_OK) ? 0 : offset_ + bytes_written; - // This may delete itself by calling RunCallback. - quota_io_->DidWrite(this, max_offset); - } - - virtual void RunCallback() { - DCHECK_EQ(false, callback_.is_null()); - callback_.Run(status_, bytes_written_); - delete this; - } - - const int64_t offset_; - scoped_ptr<char[]> buffer_; - const int32_t bytes_to_write_; - WriteCallback callback_; - bool finished_; - PlatformFileError status_; - int64_t bytes_written_; - base::WeakPtrFactory<WriteOperation> weak_factory_; -}; - -class QuotaFileIO::SetLengthOperation : public PendingOperationBase { - public: - SetLengthOperation(QuotaFileIO* quota_io, - int64_t length, - const StatusCallback& callback) - : PendingOperationBase(quota_io), - length_(length), - callback_(callback), - weak_factory_(this) {} - - virtual ~SetLengthOperation() {} - - virtual void Run() OVERRIDE { - DCHECK(quota_io_); - if (quota_io_->CheckIfExceedsQuota(length_)) { - DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); - return; - } - - if (!base::FileUtilProxy::Truncate( - quota_io_->delegate()->GetFileThreadMessageLoopProxy().get(), - quota_io_->file_, - length_, - base::Bind(&SetLengthOperation::DidFinish, - weak_factory_.GetWeakPtr()))) { - DidFail(base::PLATFORM_FILE_ERROR_FAILED); - return; - } - } - - virtual void DidFail(PlatformFileError error) OVERRIDE { - DidFinish(error); - } - - private: - void DidFinish(PlatformFileError status) { - quota_io_->DidSetLength(status, length_); - DCHECK_EQ(false, callback_.is_null()); - callback_.Run(status); - delete this; - } - - int64_t length_; - StatusCallback callback_; - base::WeakPtrFactory<SetLengthOperation> weak_factory_; -}; - -// QuotaFileIO -------------------------------------------------------------- - -QuotaFileIO::QuotaFileIO( - Delegate* delegate, - PlatformFile file, - const GURL& file_url, - PP_FileSystemType type) - : delegate_(delegate), - file_(file), - file_url_(file_url), - storage_type_(PPFileSystemTypeToQuotaStorageType(type)), - cached_file_size_(0), - cached_available_space_(0), - outstanding_quota_queries_(0), - outstanding_errors_(0), - max_written_offset_(0), - inflight_operations_(0), - weak_factory_(this) { - DCHECK_NE(base::kInvalidPlatformFileValue, file_); - DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); -} - -QuotaFileIO::~QuotaFileIO() { - // Note that this doesn't dispatch pending callbacks. - STLDeleteContainerPointers(pending_operations_.begin(), - pending_operations_.end()); - STLDeleteContainerPointers(pending_callbacks_.begin(), - pending_callbacks_.end()); -} - -bool QuotaFileIO::Write( - int64_t offset, const char* buffer, int32_t bytes_to_write, - const WriteCallback& callback) { - if (bytes_to_write <= 0) - return false; - - WriteOperation* op = new WriteOperation( - this, offset, buffer, bytes_to_write, callback); - return RegisterOperationForQuotaChecks(op); -} - -bool QuotaFileIO::SetLength(int64_t length, const StatusCallback& callback) { - DCHECK(pending_operations_.empty()); - SetLengthOperation* op = new SetLengthOperation(this, length, callback); - return RegisterOperationForQuotaChecks(op); -} - -bool QuotaFileIO::RegisterOperationForQuotaChecks( - PendingOperationBase* op_ptr) { - scoped_ptr<PendingOperationBase> op(op_ptr); - if (pending_operations_.empty()) { - // This is the first pending quota check. Run querying the file size - // and available space. - outstanding_quota_queries_ = 0; - outstanding_errors_ = 0; - - // Query the file size. - ++outstanding_quota_queries_; - if (!base::FileUtilProxy::GetFileInfoFromPlatformFile( - delegate_->GetFileThreadMessageLoopProxy().get(), - file_, - base::Bind(&QuotaFileIO::DidQueryInfoForQuota, - weak_factory_.GetWeakPtr()))) { - // This makes the call fail synchronously; we do not fire the callback - // here but just delete the operation and return false. - return false; - } - - // Query the current available space. - ++outstanding_quota_queries_; - delegate_->QueryAvailableSpace( - file_url_.GetOrigin(), storage_type_, - base::Bind(&QuotaFileIO::DidQueryAvailableSpace, - weak_factory_.GetWeakPtr())); - } - pending_operations_.push_back(op.release()); - return true; -} - -void QuotaFileIO::DidQueryInfoForQuota( - base::PlatformFileError error_code, - const base::PlatformFileInfo& file_info) { - if (error_code != base::PLATFORM_FILE_OK) - ++outstanding_errors_; - cached_file_size_ = file_info.size; - DCHECK_GT(outstanding_quota_queries_, 0); - if (--outstanding_quota_queries_ == 0) - DidQueryForQuotaCheck(); -} - -void QuotaFileIO::DidQueryAvailableSpace(int64_t avail_space) { - cached_available_space_ = avail_space; - DCHECK_GT(outstanding_quota_queries_, 0); - if (--outstanding_quota_queries_ == 0) - DidQueryForQuotaCheck(); -} - -void QuotaFileIO::DidQueryForQuotaCheck() { - DCHECK(!pending_operations_.empty()); - DCHECK_GT(inflight_operations_, 0); - while (!pending_operations_.empty()) { - PendingOperationBase* op = pending_operations_.front(); - pending_operations_.pop_front(); - pending_callbacks_.push_back(op); - if (outstanding_errors_ > 0) { - op->DidFail(base::PLATFORM_FILE_ERROR_FAILED); - continue; - } - op->Run(); - } -} - -bool QuotaFileIO::CheckIfExceedsQuota(int64_t new_file_size) const { - DCHECK_GE(cached_file_size_, 0); - DCHECK_GE(cached_available_space_, 0); - return new_file_size - cached_file_size_ > cached_available_space_; -} - -void QuotaFileIO::WillUpdate() { - if (inflight_operations_++ == 0) { - delegate_->WillUpdateFile(file_url_); - DCHECK_EQ(0, max_written_offset_); - } -} - -void QuotaFileIO::DidWrite(WriteOperation* op, - int64_t written_offset_end) { - max_written_offset_ = std::max(max_written_offset_, written_offset_end); - DCHECK_GT(inflight_operations_, 0); - DCHECK(!pending_callbacks_.empty()); - // Fire callbacks for finished operations. - while (!pending_callbacks_.empty()) { - WriteOperation* op = static_cast<WriteOperation*>( - pending_callbacks_.front()); - if (!op->finished()) - break; - pending_callbacks_.pop_front(); - op->WillRunCallback(); - } - // If we have no more pending writes, notify the browser that we did - // update the file. - if (--inflight_operations_ == 0) { - DCHECK(pending_operations_.empty()); - int64_t growth = max_written_offset_ - cached_file_size_; - growth = growth < 0 ? 0 : growth; - - delegate_->DidUpdateFile(file_url_, growth); - max_written_offset_ = 0; - } -} - -void QuotaFileIO::DidSetLength(PlatformFileError error, int64_t new_file_size) { - DCHECK_EQ(1, inflight_operations_); - pending_callbacks_.pop_front(); - DCHECK(pending_callbacks_.empty()); - int64_t delta = (error != base::PLATFORM_FILE_OK) ? 0 : - new_file_size - cached_file_size_; - - delegate_->DidUpdateFile(file_url_, delta); - inflight_operations_ = 0; -} - -} // namespace content diff --git a/content/browser/renderer_host/pepper/quota_file_io.h b/content/browser/renderer_host/pepper/quota_file_io.h deleted file mode 100644 index 54229b87a4..0000000000 --- a/content/browser/renderer_host/pepper/quota_file_io.h +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_QUOTA_FILE_IO_H_ -#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_QUOTA_FILE_IO_H_ - -#include <deque> - -#include "base/callback_forward.h" -#include "base/files/file_util_proxy.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/platform_file.h" -#include "content/common/content_export.h" -#include "ppapi/c/pp_file_info.h" -#include "url/gurl.h" -#include "webkit/common/quota/quota_types.h" - -namespace base { -class MessageLoopProxy; -} - -namespace content { - -// This class is created per PPB_FileIO_Impl instance and provides -// write operations for quota-managed files (i.e. files of -// PP_FILESYSTEMTYPE_LOCAL{PERSISTENT,TEMPORARY}). -class QuotaFileIO { - public: - // For quota handlings for FileIO API. This will be owned by QuotaFileIO. - class Delegate { - public: - virtual ~Delegate() {} - typedef base::Callback<void (int64)> AvailableSpaceCallback; - virtual void QueryAvailableSpace( - const GURL& origin, - quota::StorageType type, - const AvailableSpaceCallback& callback) = 0; - virtual void WillUpdateFile(const GURL& file_path) = 0; - virtual void DidUpdateFile(const GURL& file_path, int64_t delta) = 0; - // Returns a MessageLoopProxy instance associated with the message loop of - // the file thread. - virtual scoped_refptr<base::MessageLoopProxy> - GetFileThreadMessageLoopProxy() = 0; - }; - - typedef base::FileUtilProxy::WriteCallback WriteCallback; - typedef base::FileUtilProxy::StatusCallback StatusCallback; - - CONTENT_EXPORT QuotaFileIO(Delegate* delegate, - base::PlatformFile file, - const GURL& path_url, - PP_FileSystemType type); - CONTENT_EXPORT ~QuotaFileIO(); - - // Performs write or setlength operation with quota checks. - // Returns true when the operation is successfully dispatched. - // |bytes_to_write| must be geater than zero. - // |callback| will be dispatched when the operation completes. - // Otherwise it returns false and |callback| will not be dispatched. - // |callback| will not be dispatched either when this instance is - // destroyed before the operation completes. - // SetLength cannot be called while there're any in-flight - // operations. For Write it is guaranteed that |callback| are - // always dispatched in the same order as Write being called. - CONTENT_EXPORT bool Write(int64_t offset, - const char* buffer, - int32_t bytes_to_write, - const WriteCallback& callback); - CONTENT_EXPORT bool SetLength(int64_t length, - const StatusCallback& callback); - - Delegate* delegate() const { return delegate_.get(); } - - private: - class PendingOperationBase; - class WriteOperation; - class SetLengthOperation; - - bool CheckIfExceedsQuota(int64_t new_file_size) const; - void WillUpdate(); - void DidWrite(WriteOperation* op, int64_t written_offset_end); - void DidSetLength(base::PlatformFileError error, int64_t new_file_size); - - bool RegisterOperationForQuotaChecks(PendingOperationBase* op); - void DidQueryInfoForQuota(base::PlatformFileError error_code, - const base::PlatformFileInfo& file_info); - void DidQueryAvailableSpace(int64_t avail_space); - void DidQueryForQuotaCheck(); - - scoped_ptr<Delegate> delegate_; - - // The file information associated to this instance. - base::PlatformFile file_; - GURL file_url_; - quota::StorageType storage_type_; - - // Pending operations that are waiting quota checks and pending - // callbacks that are to be fired after the operation; - // we use two separate queues for them so that we can safely dequeue the - // pending callbacks while enqueueing new operations. (This could - // happen when callbacks are dispatched synchronously due to error etc.) - std::deque<PendingOperationBase*> pending_operations_; - std::deque<PendingOperationBase*> pending_callbacks_; - - // Valid only while there're pending quota checks. - int64_t cached_file_size_; - int64_t cached_available_space_; - - // Quota-related queries and errors occurred during in-flight quota checks. - int outstanding_quota_queries_; - int outstanding_errors_; - - // For parallel writes bookkeeping. - int64_t max_written_offset_; - int inflight_operations_; - - base::WeakPtrFactory<QuotaFileIO> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(QuotaFileIO); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_QUOTA_FILE_IO_H_ diff --git a/content/browser/renderer_host/pepper/quota_file_io_unittest.cc b/content/browser/renderer_host/pepper/quota_file_io_unittest.cc deleted file mode 100644 index bcc08d3434..0000000000 --- a/content/browser/renderer_host/pepper/quota_file_io_unittest.cc +++ /dev/null @@ -1,426 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <deque> -#include <limits> -#include <string> - -#include "base/basictypes.h" -#include "base/bind.h" -#include "base/file_util.h" -#include "base/files/scoped_temp_dir.h" -#include "base/memory/weak_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/platform_file.h" -#include "content/browser/renderer_host/pepper/quota_file_io.h" -#include "content/test/ppapi_unittest.h" - -using base::MessageLoopProxy; -using base::PlatformFile; -using base::PlatformFileError; - -namespace content { - -namespace { -class QuotaMockDelegate : public QuotaFileIO::Delegate { - public: - typedef QuotaFileIO::Delegate::AvailableSpaceCallback Callback; - - QuotaMockDelegate() - : available_space_(0), - will_update_count_(0), - file_thread_(MessageLoopProxy::current()), - weak_factory_(this) { - } - virtual ~QuotaMockDelegate() {} - - virtual void QueryAvailableSpace( - const GURL& origin, - quota::StorageType type, - const Callback& callback) OVERRIDE { - DCHECK_EQ(false, callback.is_null()); - MessageLoopProxy::current()->PostTask( - FROM_HERE, base::Bind( - &QuotaMockDelegate::RunAvailableSpaceCallback, - weak_factory_.GetWeakPtr(), callback)); - } - - virtual void WillUpdateFile(const GURL& file_path) OVERRIDE { - file_path_ = file_path; - ++will_update_count_; - } - - virtual void DidUpdateFile(const GURL& file_path, int64_t delta) OVERRIDE { - ASSERT_EQ(file_path_, file_path); - ASSERT_GT(will_update_count_, 0); - --will_update_count_; - available_space_ -= delta; - } - - virtual scoped_refptr<base::MessageLoopProxy> - GetFileThreadMessageLoopProxy() OVERRIDE { - return file_thread_; - } - - void set_available_space(int64 available) { available_space_ = available; } - int64_t available_space() const { return available_space_; } - - private: - void RunAvailableSpaceCallback(const Callback& callback) { - callback.Run(available_space_); - } - - int64_t available_space_; - int will_update_count_; - GURL file_path_; - scoped_refptr<MessageLoopProxy> file_thread_; - base::WeakPtrFactory<QuotaMockDelegate> weak_factory_; -}; -} // namespace - -class QuotaFileIOTest : public PpapiUnittest { - public: - QuotaFileIOTest() - : delegate_(NULL), - weak_factory_(this) {} - - virtual void SetUp() OVERRIDE { - PpapiUnittest::SetUp(); - ASSERT_TRUE(dir_.CreateUniqueTempDir()); - base::FilePath path; - ASSERT_TRUE(file_util::CreateTemporaryFileInDir(dir_.path(), &path)); - int file_flags = base::PLATFORM_FILE_OPEN | - base::PLATFORM_FILE_READ | - base::PLATFORM_FILE_WRITE | - base::PLATFORM_FILE_WRITE_ATTRIBUTES; - bool created = false; - file_ = base::kInvalidPlatformFileValue; - PlatformFileError error = base::PLATFORM_FILE_OK; - file_ = base::CreatePlatformFile(path, file_flags, &created, &error); - ASSERT_EQ(base::PLATFORM_FILE_OK, error); - ASSERT_NE(base::kInvalidPlatformFileValue, file_); - ASSERT_FALSE(created); - delegate_ = new QuotaMockDelegate; // Owned by QuotaFileIO. - quota_file_io_.reset(new QuotaFileIO( - delegate_, file_, GURL(), PP_FILESYSTEMTYPE_LOCALTEMPORARY)); - } - - virtual void TearDown() OVERRIDE { - quota_file_io_.reset(); - if (file_ != base::kInvalidPlatformFileValue) - base::ClosePlatformFile(file_); - PpapiUnittest::TearDown(); - } - - protected: - void WriteTestBody() { - // Attempt to write zero bytes. - EXPECT_FALSE(quota_file_io_->Write( - 0, "data", 0, - base::Bind(&QuotaFileIOTest::DidWrite, weak_factory_.GetWeakPtr()))); - // Attempt to write negative number of bytes. - EXPECT_FALSE(quota_file_io_->Write( - 0, "data", std::numeric_limits<int32_t>::min(), - base::Bind(&QuotaFileIOTest::DidWrite, weak_factory_.GetWeakPtr()))); - - delegate()->set_available_space(100); - std::string read_buffer; - - // Write 8 bytes at offset 0 (-> length=8). - std::string data("12345678"); - Write(0, data); - base::MessageLoop::current()->RunUntilIdle(); - ASSERT_EQ(1U, num_results()); - EXPECT_EQ(static_cast<int>(data.size()), bytes_written().front()); - EXPECT_EQ(base::PLATFORM_FILE_OK, status().front()); - EXPECT_EQ(100 - 8, delegate()->available_space()); - reset_results(); - - EXPECT_EQ(8, GetPlatformFileSize()); - ReadPlatformFile(&read_buffer); - EXPECT_EQ(data, read_buffer); - - // Write 5 bytes at offset 5 (-> length=10). - data = "55555"; - Write(5, data); - base::MessageLoop::current()->RunUntilIdle(); - ASSERT_EQ(1U, num_results()); - EXPECT_EQ(static_cast<int>(data.size()), bytes_written().front()); - EXPECT_EQ(base::PLATFORM_FILE_OK, status().front()); - EXPECT_EQ(100 - 10, delegate()->available_space()); - reset_results(); - - EXPECT_EQ(10, GetPlatformFileSize()); - ReadPlatformFile(&read_buffer); - EXPECT_EQ("1234555555", read_buffer); - - // Write 7 bytes at offset 8 (-> length=15). - data = "9012345"; - Write(8, data); - base::MessageLoop::current()->RunUntilIdle(); - ASSERT_EQ(1U, num_results()); - EXPECT_EQ(static_cast<int>(data.size()), bytes_written().front()); - EXPECT_EQ(base::PLATFORM_FILE_OK, status().front()); - EXPECT_EQ(100 - 15, delegate()->available_space()); - reset_results(); - - EXPECT_EQ(15, GetPlatformFileSize()); - ReadPlatformFile(&read_buffer); - EXPECT_EQ("123455559012345", read_buffer); - - // Write 2 bytes at offset 2 (-> length=15). - data = "33"; - Write(2, data); - base::MessageLoop::current()->RunUntilIdle(); - ASSERT_EQ(1U, num_results()); - EXPECT_EQ(static_cast<int>(data.size()), bytes_written().front()); - EXPECT_EQ(base::PLATFORM_FILE_OK, status().front()); - EXPECT_EQ(100 - 15, delegate()->available_space()); - reset_results(); - - EXPECT_EQ(15, GetPlatformFileSize()); - ReadPlatformFile(&read_buffer); - EXPECT_EQ("123355559012345", read_buffer); - - // Write 4 bytes at offset 20 (-> length=24). - data = "XXXX"; - Write(20, data); - base::MessageLoop::current()->RunUntilIdle(); - ASSERT_EQ(1U, num_results()); - EXPECT_EQ(static_cast<int>(data.size()), bytes_written().front()); - EXPECT_EQ(base::PLATFORM_FILE_OK, status().front()); - EXPECT_EQ(100 - 24, delegate()->available_space()); - reset_results(); - - EXPECT_EQ(24, GetPlatformFileSize()); - ReadPlatformFile(&read_buffer); - EXPECT_EQ(std::string("123355559012345\0\0\0\0\0XXXX", 24), read_buffer); - - delegate()->set_available_space(5); - - // Quota error case. Write 7 bytes at offset 23 (-> length is unchanged) - data = "ABCDEFG"; - Write(23, data); - base::MessageLoop::current()->RunUntilIdle(); - ASSERT_EQ(1U, num_results()); - EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status().front()); - EXPECT_EQ(5, delegate()->available_space()); - reset_results(); - - // Overlapping write. Write 6 bytes at offset 2 (-> length is unchanged) - data = "ABCDEF"; - Write(2, data); - base::MessageLoop::current()->RunUntilIdle(); - ASSERT_EQ(1U, num_results()); - EXPECT_EQ(static_cast<int>(data.size()), bytes_written().front()); - EXPECT_EQ(base::PLATFORM_FILE_OK, status().front()); - EXPECT_EQ(5, delegate()->available_space()); - reset_results(); - - // Overlapping + extending the file size, but within the quota. - // Write 6 bytes at offset 23 (-> length=29). - Write(23, data); - base::MessageLoop::current()->RunUntilIdle(); - ASSERT_EQ(1U, num_results()); - EXPECT_EQ(static_cast<int>(data.size()), bytes_written().front()); - EXPECT_EQ(base::PLATFORM_FILE_OK, status().front()); - EXPECT_EQ(0, delegate()->available_space()); - reset_results(); - - EXPECT_EQ(29, GetPlatformFileSize()); - ReadPlatformFile(&read_buffer); - EXPECT_EQ(std::string("12ABCDEF9012345\0\0\0\0\0XXXABCDEF", 29), - read_buffer); - } - - void SetLengthTestBody() { - delegate()->set_available_space(100); - - SetLength(0); - base::MessageLoop::current()->RunUntilIdle(); - ASSERT_EQ(1U, num_results()); - EXPECT_EQ(base::PLATFORM_FILE_OK, status().front()); - EXPECT_EQ(0, GetPlatformFileSize()); - EXPECT_EQ(100, delegate()->available_space()); - reset_results(); - - SetLength(8); - base::MessageLoop::current()->RunUntilIdle(); - ASSERT_EQ(1U, num_results()); - EXPECT_EQ(base::PLATFORM_FILE_OK, status().front()); - EXPECT_EQ(100 - 8, delegate()->available_space()); - reset_results(); - - EXPECT_EQ(8, GetPlatformFileSize()); - - SetLength(16); - base::MessageLoop::current()->RunUntilIdle(); - ASSERT_EQ(1U, num_results()); - EXPECT_EQ(base::PLATFORM_FILE_OK, status().front()); - EXPECT_EQ(100 - 16, delegate()->available_space()); - reset_results(); - - EXPECT_EQ(16, GetPlatformFileSize()); - - SetLength(4); - base::MessageLoop::current()->RunUntilIdle(); - ASSERT_EQ(1U, num_results()); - EXPECT_EQ(base::PLATFORM_FILE_OK, status().front()); - EXPECT_EQ(100 - 4, delegate()->available_space()); - reset_results(); - - EXPECT_EQ(4, GetPlatformFileSize()); - - SetLength(0); - base::MessageLoop::current()->RunUntilIdle(); - ASSERT_EQ(1U, num_results()); - EXPECT_EQ(base::PLATFORM_FILE_OK, status().front()); - EXPECT_EQ(100, delegate()->available_space()); - reset_results(); - - EXPECT_EQ(0, GetPlatformFileSize()); - - delegate()->set_available_space(5); - - // Quota error case. - SetLength(7); - base::MessageLoop::current()->RunUntilIdle(); - ASSERT_EQ(1U, num_results()); - EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status().front()); - EXPECT_EQ(5, delegate()->available_space()); - reset_results(); - } - - QuotaMockDelegate* delegate() { - return delegate_; - } - - void Write(int64_t offset, const std::string& data) { - ASSERT_TRUE(quota_file_io_->Write( - offset, data.c_str(), data.size(), - base::Bind(&QuotaFileIOTest::DidWrite, weak_factory_.GetWeakPtr()))); - } - - void SetLength(int64_t length) { - ASSERT_TRUE(quota_file_io_->SetLength( - length, - base::Bind(&QuotaFileIOTest::DidSetLength, - weak_factory_.GetWeakPtr()))); - } - - void DidWrite(PlatformFileError status, int bytes_written) { - status_.push_back(status); - bytes_written_.push_back(bytes_written); - } - - void DidSetLength(PlatformFileError status) { - status_.push_back(status); - } - - size_t num_results() const { return status_.size(); } - const std::deque<int>& bytes_written() const { return bytes_written_; } - const std::deque<PlatformFileError>& status() const { return status_; } - - void reset_results() { - bytes_written_.clear(); - status_.clear(); - } - - void pop_result() { - bytes_written_.pop_front(); - status_.pop_front(); - } - - void ReadPlatformFile(std::string* data) { - data->clear(); - char buf[256]; - int32_t read_offset = 0; - for (;;) { - int rv = base::ReadPlatformFile(file_, read_offset, buf, sizeof(buf)); - ASSERT_GE(rv, 0); - if (rv == 0) - break; - read_offset += rv; - data->append(buf, rv); - } - } - - int64_t GetPlatformFileSize() { - base::PlatformFileInfo info; - EXPECT_TRUE(base::GetPlatformFileInfo(file_, &info)); - return info.size; - } - - void SetPlatformFileSize(int64_t length) { - EXPECT_TRUE(base::TruncatePlatformFile(file_, length)); - } - - private: - base::ScopedTempDir dir_; - PlatformFile file_; - scoped_ptr<QuotaFileIO> quota_file_io_; - std::deque<int> bytes_written_; - std::deque<PlatformFileError> status_; - QuotaMockDelegate* delegate_; - base::WeakPtrFactory<QuotaFileIOTest> weak_factory_; -}; - -TEST_F(QuotaFileIOTest, Write) { - WriteTestBody(); -} - -TEST_F(QuotaFileIOTest, SetLength) { - SetLengthTestBody(); -} - -TEST_F(QuotaFileIOTest, ParallelWrites) { - delegate()->set_available_space(22); - std::string read_buffer; - - const std::string data1[] = { - std::string("12345678"), - std::string("55555"), - std::string("9012345"), - }; - Write(0, data1[0]); - Write(5, data1[1]); - Write(8, data1[2]); - base::MessageLoop::current()->RunUntilIdle(); - - ASSERT_EQ(ARRAYSIZE_UNSAFE(data1), num_results()); - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data1); ++i) { - EXPECT_EQ(static_cast<int>(data1[i].size()), bytes_written().front()); - EXPECT_EQ(base::PLATFORM_FILE_OK, status().front()); - pop_result(); - } - - EXPECT_EQ(22 - 15, delegate()->available_space()); - EXPECT_EQ(15, GetPlatformFileSize()); - ReadPlatformFile(&read_buffer); - EXPECT_EQ("123455559012345", read_buffer); - - // The second write will fail for quota error. - const std::string data2[] = { - std::string("33"), - std::string("XXXX"), - }; - Write(2, data2[0]); - Write(20, data2[1]); - base::MessageLoop::current()->RunUntilIdle(); - - ASSERT_EQ(ARRAYSIZE_UNSAFE(data2), num_results()); - EXPECT_EQ(static_cast<int>(data2[0].size()), bytes_written().front()); - EXPECT_EQ(base::PLATFORM_FILE_OK, status().front()); - pop_result(); - EXPECT_EQ(0, bytes_written().front()); - EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status().front()); - pop_result(); - - EXPECT_EQ(22 - 15, delegate()->available_space()); - EXPECT_EQ(15, GetPlatformFileSize()); - ReadPlatformFile(&read_buffer); - EXPECT_EQ("123355559012345", read_buffer); -} - -} // namespace content diff --git a/content/browser/renderer_host/pepper/quota_reservation.cc b/content/browser/renderer_host/pepper/quota_reservation.cc new file mode 100644 index 0000000000..ed2821209c --- /dev/null +++ b/content/browser/renderer_host/pepper/quota_reservation.cc @@ -0,0 +1,129 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/pepper/quota_reservation.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "content/public/browser/browser_thread.h" +#include "webkit/browser/fileapi/quota/open_file_handle.h" +#include "webkit/browser/fileapi/quota/quota_reservation.h" +#include "webkit/common/fileapi/file_system_util.h" + +namespace content { + +// static +scoped_refptr<QuotaReservation> QuotaReservation::Create( + scoped_refptr<fileapi::FileSystemContext> file_system_context, + const GURL& origin_url, + fileapi::FileSystemType type) { + return scoped_refptr<QuotaReservation>(new QuotaReservation( + file_system_context, origin_url, type)); +} + +QuotaReservation::QuotaReservation( + scoped_refptr<fileapi::FileSystemContext> file_system_context, + const GURL& origin_url, + fileapi::FileSystemType file_system_type) + : file_system_context_(file_system_context) { + quota_reservation_ = + file_system_context->CreateQuotaReservationOnFileTaskRunner( + origin_url, + file_system_type); +} + +// For unit testing only. +QuotaReservation::QuotaReservation( + scoped_refptr<fileapi::QuotaReservation> quota_reservation, + const GURL& /* origin_url */, + fileapi::FileSystemType /* file_system_type */) + : quota_reservation_(quota_reservation) { +} + +QuotaReservation::~QuotaReservation() { + // We should have no open files at this point. + DCHECK(files_.size() == 0); + for (FileMap::iterator it = files_.begin(); it != files_.end(); ++ it) + delete it->second; +} + +int64_t QuotaReservation::OpenFile(int32_t id, + const base::FilePath& file_path) { + scoped_ptr<fileapi::OpenFileHandle> file_handle = + quota_reservation_->GetOpenFileHandle(file_path); + std::pair<FileMap::iterator, bool> insert_result = + files_.insert(std::make_pair(id, file_handle.get())); + if (insert_result.second) { + int64_t max_written_offset = file_handle->base_file_size(); + ignore_result(file_handle.release()); + return max_written_offset; + } + NOTREACHED(); + return 0; +} + +void QuotaReservation::CloseFile(int32_t id, + int64_t max_written_offset) { + FileMap::iterator it = files_.find(id); + if (it != files_.end()) { + it->second->UpdateMaxWrittenOffset(max_written_offset); + files_.erase(it); + } else { + NOTREACHED(); + } +} + +void QuotaReservation::ReserveQuota( + int64_t amount, + const OffsetMap& max_written_offsets, + const ReserveQuotaCallback& callback) { + for (FileMap::iterator it = files_.begin(); it != files_.end(); ++ it) { + OffsetMap::const_iterator offset_it = max_written_offsets.find(it->first); + if (offset_it != max_written_offsets.end()) + it->second->UpdateMaxWrittenOffset(offset_it->second); + else + NOTREACHED(); + } + + quota_reservation_->RefreshReservation( + amount, + base::Bind(&QuotaReservation::GotReservedQuota, + this, + callback)); +} + +void QuotaReservation::GotReservedQuota( + const ReserveQuotaCallback& callback, + base::PlatformFileError error) { + OffsetMap max_written_offsets; + for (FileMap::iterator it = files_.begin(); it != files_.end(); ++ it) { + max_written_offsets.insert( + std::make_pair(it->first, it->second->base_file_size())); + } + + if (file_system_context_) { + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(callback, + quota_reservation_->remaining_quota(), + max_written_offsets)); + } else { + // Unit testing code path. + callback.Run(quota_reservation_->remaining_quota(), max_written_offsets); + } +} + +void QuotaReservation::DeleteOnCorrectThread() const { + if (file_system_context_) { + file_system_context_->default_file_task_runner()->DeleteSoon( + FROM_HERE, + this); + } else { + // Unit testing code path. + delete this; + } +} + +} // namespace content diff --git a/content/browser/renderer_host/pepper/quota_reservation.h b/content/browser/renderer_host/pepper/quota_reservation.h new file mode 100644 index 0000000000..bd7e0eac58 --- /dev/null +++ b/content/browser/renderer_host/pepper/quota_reservation.h @@ -0,0 +1,100 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_QUOTA_RESERVATION_H_ +#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_QUOTA_RESERVATION_H_ + +#include <map> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/platform_file.h" +#include "content/common/content_export.h" +#include "ppapi/c/pp_stdint.h" // For int64_t on Windows. +#include "url/gurl.h" +#include "webkit/browser/fileapi/file_system_context.h" + +namespace base { +class FilePath; +} + +namespace fileapi { +class OpenFileHandle; +class QuotaReservation; +} + +namespace content { + +struct QuotaReservationDeleter; + +// This class holds a QuotaReservation and manages OpenFileHandles for checking +// quota. It should be created, used, and destroyed on a FileSystemContext's +// default_file_task_runner() instance. This is a RefCountedThreadSafe object +// because it needs to be passed to the file thread and kept alive during +// potentially long-running quota operations. +class CONTENT_EXPORT QuotaReservation + : public base::RefCountedThreadSafe<QuotaReservation, + QuotaReservationDeleter> { + public: + // Static method to facilitate construction on the file task runner. + static scoped_refptr<QuotaReservation> Create( + scoped_refptr<fileapi::FileSystemContext> file_system_context, + const GURL& origin_url, + fileapi::FileSystemType file_system_type); + + // Opens a file with the given id and path and returns its current size. + int64_t OpenFile(int32_t id, const base::FilePath& file_path); + // Closes the file opened by OpenFile with the given id. + void CloseFile(int32_t id, int64_t max_written_offset); + // Refreshes the quota reservation to a new amount. A map that associates file + // ids with maximum written offsets is provided as input. The callback will + // receive a similar map with the updated file sizes. + typedef std::map<int32_t, int64_t> OffsetMap; + typedef base::Callback<void(int64_t, const OffsetMap&)> ReserveQuotaCallback; + void ReserveQuota(int64_t amount, + const OffsetMap& max_written_offsets, + const ReserveQuotaCallback& callback); + private: + friend class base::RefCountedThreadSafe<QuotaReservation, + QuotaReservationDeleter>; + friend class base::DeleteHelper<QuotaReservation>; + friend struct QuotaReservationDeleter; + friend class QuotaReservationTest; + + QuotaReservation( + scoped_refptr<fileapi::FileSystemContext> file_system_context, + const GURL& origin_url, + fileapi::FileSystemType file_system_type); + + // For unit testing only. A QuotaReservation intended for unit testing will + // have file_system_context_ == NULL. + QuotaReservation( + scoped_refptr<fileapi::QuotaReservation> quota_reservation, + const GURL& origin_url, + fileapi::FileSystemType file_system_type); + + ~QuotaReservation(); + + void GotReservedQuota(const ReserveQuotaCallback& callback, + base::PlatformFileError error); + + void DeleteOnCorrectThread() const; + + scoped_refptr<fileapi::FileSystemContext> file_system_context_; + scoped_refptr<fileapi::QuotaReservation> quota_reservation_; + typedef std::map<int32_t, fileapi::OpenFileHandle*> FileMap; + FileMap files_; + + DISALLOW_COPY_AND_ASSIGN(QuotaReservation); +}; + +struct QuotaReservationDeleter { + static void Destruct(const QuotaReservation* quota_reservation) { + quota_reservation->DeleteOnCorrectThread(); + } +}; + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_QUOTA_RESERVATION_H_ diff --git a/content/browser/renderer_host/pepper/quota_reservation_unittest.cc b/content/browser/renderer_host/pepper/quota_reservation_unittest.cc new file mode 100644 index 0000000000..a9a5f71008 --- /dev/null +++ b/content/browser/renderer_host/pepper/quota_reservation_unittest.cc @@ -0,0 +1,238 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/pepper/quota_reservation.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/browser/fileapi/quota/quota_reservation.h" + +using fileapi::FileSystemType; +using fileapi::QuotaReservationManager; + +namespace content { + +namespace { + +const char kOrigin[] = "http://example.com"; +const FileSystemType kType = fileapi::kFileSystemTypeTemporary; + +const base::FilePath::StringType file1_name = FILE_PATH_LITERAL("file1"); +const base::FilePath::StringType file2_name = FILE_PATH_LITERAL("file2"); +const base::FilePath::StringType file3_name = FILE_PATH_LITERAL("file3"); +const int kFile1ID = 1; +const int kFile2ID = 2; +const int kFile3ID = 3; + +class FakeBackend : public QuotaReservationManager::QuotaBackend { + public: + FakeBackend() {} + virtual ~FakeBackend() {} + + virtual void ReserveQuota( + const GURL& origin, + FileSystemType type, + int64 delta, + const QuotaReservationManager::ReserveQuotaCallback& callback) OVERRIDE { + base::MessageLoopProxy::current()->PostTask( + FROM_HERE, + base::Bind(base::IgnoreResult(callback), base::PLATFORM_FILE_OK)); + } + + virtual void ReleaseReservedQuota(const GURL& origin, + FileSystemType type, + int64 size) OVERRIDE { + } + + virtual void CommitQuotaUsage(const GURL& origin, + FileSystemType type, + int64 delta) OVERRIDE { + } + + virtual void IncrementDirtyCount(const GURL& origin, + FileSystemType type) OVERRIDE {} + virtual void DecrementDirtyCount(const GURL& origin, + FileSystemType type) OVERRIDE {} + + private: + DISALLOW_COPY_AND_ASSIGN(FakeBackend); +}; + +} // namespace + +class QuotaReservationTest : public testing::Test { + public: + QuotaReservationTest() {} + virtual ~QuotaReservationTest() {} + + virtual void SetUp() OVERRIDE { + ASSERT_TRUE(work_dir_.CreateUniqueTempDir()); + + reservation_manager_.reset(new QuotaReservationManager( + scoped_ptr<QuotaReservationManager::QuotaBackend>(new FakeBackend))); + } + + virtual void TearDown() OVERRIDE { + reservation_manager_.reset(); + } + + base::FilePath MakeFilePath(base::FilePath::StringType file_name) { + return work_dir_.path().Append(file_name); + } + + scoped_refptr<QuotaReservation> CreateQuotaReservation( + scoped_refptr<fileapi::QuotaReservation> reservation, + const GURL& origin, + FileSystemType type) { + // Sets reservation_ as a side effect. + return scoped_refptr<QuotaReservation>( + new QuotaReservation(reservation, origin, type)); + } + + void SetFileSize(const base::FilePath::StringType& file_name, int64 size) { + bool created = false; + base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED; + base::PlatformFile file = CreatePlatformFile( + MakeFilePath(file_name), + base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE, + &created, &error); + ASSERT_EQ(base::PLATFORM_FILE_OK, error); + ASSERT_TRUE(base::TruncatePlatformFile(file, size)); + ASSERT_TRUE(base::ClosePlatformFile(file)); + } + + QuotaReservationManager* reservation_manager() { + return reservation_manager_.get(); + } + + private: + base::MessageLoop message_loop_; + base::ScopedTempDir work_dir_; + scoped_ptr<fileapi::QuotaReservationManager> reservation_manager_; + + DISALLOW_COPY_AND_ASSIGN(QuotaReservationTest); +}; + +void GotReservedQuota( + int64* reserved_quota_ptr, + QuotaReservation::OffsetMap* maximum_written_offsets_ptr, + int64 reserved_quota, + const QuotaReservation::OffsetMap& maximum_written_offsets) { + *reserved_quota_ptr = reserved_quota; + *maximum_written_offsets_ptr = maximum_written_offsets; +} + +void ReserveQuota( + scoped_refptr<QuotaReservation> quota_reservation, + int64 amount, + int64* reserved_quota, + QuotaReservation::OffsetMap* max_written_offsets) { + quota_reservation->ReserveQuota(amount, + *max_written_offsets, + base::Bind(&GotReservedQuota, + reserved_quota, + max_written_offsets)); + base::RunLoop().RunUntilIdle(); +} + +// Tests that: +// 1) We can reserve quota with no files open. +// 2) Open a file, grow it, close it, and reserve quota with correct sizes. +TEST_F(QuotaReservationTest, DISABLED_ReserveQuota) { + GURL origin(kOrigin); + FileSystemType type = kType; + + scoped_refptr<fileapi::QuotaReservation> reservation( + reservation_manager()->CreateReservation(origin, type)); + scoped_refptr<QuotaReservation> test = + CreateQuotaReservation(reservation, origin, type); + + // Reserve quota with no files open. + int64 amount = 100; + int64 reserved_quota; + QuotaReservation::OffsetMap max_written_offsets; + ReserveQuota(test, amount, &reserved_quota, &max_written_offsets); + EXPECT_EQ(amount, reserved_quota); + EXPECT_EQ(0U, max_written_offsets.size()); + + // Open a file, refresh the reservation, extend the file, and close it. + int64 file_size = 10; + SetFileSize(file1_name, file_size); + int64 open_file_size = test->OpenFile(kFile1ID, MakeFilePath(file1_name)); + EXPECT_EQ(file_size, open_file_size); + + max_written_offsets[kFile1ID] = file_size; // 1 file open. + ReserveQuota(test, amount, &reserved_quota, &max_written_offsets); + EXPECT_EQ(amount, reserved_quota); + EXPECT_EQ(1U, max_written_offsets.size()); + EXPECT_EQ(file_size, max_written_offsets[kFile1ID]); + + int64 new_file_size = 30; + SetFileSize(file1_name, new_file_size); + + EXPECT_EQ(amount, reservation->remaining_quota()); + test->CloseFile(kFile1ID, new_file_size); + EXPECT_EQ(amount - (new_file_size - file_size), + reservation->remaining_quota()); +} + +// Tests that: +// 1) We can open and close multiple files. +TEST_F(QuotaReservationTest, DISABLED_MultipleFiles) { + GURL origin(kOrigin); + FileSystemType type = kType; + + scoped_refptr<fileapi::QuotaReservation> reservation( + reservation_manager()->CreateReservation(origin, type)); + scoped_refptr<QuotaReservation> test = + CreateQuotaReservation(reservation, origin, type); + + // Open some files of different sizes. + int64 file1_size = 10; + SetFileSize(file1_name, file1_size); + int64 open_file1_size = test->OpenFile(kFile1ID, MakeFilePath(file1_name)); + EXPECT_EQ(file1_size, open_file1_size); + int64 file2_size = 20; + SetFileSize(file2_name, file2_size); + int64 open_file2_size = test->OpenFile(kFile2ID, MakeFilePath(file2_name)); + EXPECT_EQ(file2_size, open_file2_size); + int64 file3_size = 30; + SetFileSize(file3_name, file3_size); + int64 open_file3_size = test->OpenFile(kFile3ID, MakeFilePath(file3_name)); + EXPECT_EQ(file3_size, open_file3_size); + + // Reserve quota. + int64 amount = 100; + int64 reserved_quota; + QuotaReservation::OffsetMap max_written_offsets; + max_written_offsets[kFile1ID] = file1_size; // 3 files open. + max_written_offsets[kFile2ID] = file2_size; + max_written_offsets[kFile3ID] = file3_size; + + ReserveQuota(test, amount, &reserved_quota, &max_written_offsets); + EXPECT_EQ(amount, reserved_quota); + EXPECT_EQ(3U, max_written_offsets.size()); + EXPECT_EQ(file1_size, max_written_offsets[kFile1ID]); + EXPECT_EQ(file2_size, max_written_offsets[kFile2ID]); + EXPECT_EQ(file3_size, max_written_offsets[kFile3ID]); + + test->CloseFile(kFile2ID, file2_size); + + max_written_offsets.erase(max_written_offsets.find(kFile2ID)); + ReserveQuota(test, amount, &reserved_quota, &max_written_offsets); + EXPECT_EQ(amount, reserved_quota); + EXPECT_EQ(2U, max_written_offsets.size()); + EXPECT_EQ(file1_size, max_written_offsets[kFile1ID]); + EXPECT_EQ(file3_size, max_written_offsets[kFile3ID]); + + test->CloseFile(kFile1ID, file1_size); + test->CloseFile(kFile3ID, file3_size); +} + +} // namespace content diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index 3aca534e48..dd6a3c3079 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc @@ -33,6 +33,8 @@ #include "content/common/child_process_messages.h" #include "content/common/cookie_data.h" #include "content/common/desktop_notification_messages.h" +#include "content/common/frame_messages.h" +#include "content/common/gpu/client/gpu_memory_buffer_impl.h" #include "content/common/media/media_param_traits.h" #include "content/common/view_messages.h" #include "content/public/browser/browser_child_process_host.h" @@ -68,7 +70,9 @@ #include "ui/gfx/color_profile.h" #if defined(OS_MACOSX) +#include "content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h" #include "content/common/mac/font_descriptor.h" +#include "ui/gl/io_surface_support_mac.h" #else #include "gpu/GLES2/gl2extchromium.h" #include "third_party/khronos/GLES2/gl2.h" @@ -204,6 +208,23 @@ class OpenChannelToPpapiBrokerCallback int routing_id_; }; +#if defined(OS_MACOSX) +void AddBooleanValue(CFMutableDictionaryRef dictionary, + const CFStringRef key, + bool value) { + CFDictionaryAddValue( + dictionary, key, value ? kCFBooleanTrue : kCFBooleanFalse); +} + +void AddIntegerValue(CFMutableDictionaryRef dictionary, + const CFStringRef key, + int32 value) { + base::ScopedCFTypeRef<CFNumberRef> number( + CFNumberCreate(NULL, kCFNumberSInt32Type, &value)); + CFDictionaryAddValue(dictionary, key, number.get()); +} +#endif + } // namespace class RenderMessageFilter::OpenChannelToNpapiPluginCallback @@ -276,8 +297,8 @@ class RenderMessageFilter::OpenChannelToNpapiPluginCallback private: void WriteReplyAndDeleteThis(const IPC::ChannelHandle& handle) { - ViewHostMsg_OpenChannelToPlugin::WriteReplyParams(reply_msg(), - handle, info_); + FrameHostMsg_OpenChannelToPlugin::WriteReplyParams(reply_msg(), + handle, info_); filter()->OnCompletedOpenChannelToNpapiPlugin(this); SendReplyAndDeleteThis(); } @@ -380,8 +401,8 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message, IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl) #if defined(ENABLE_PLUGINS) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPlugins, OnGetPlugins) - IPC_MESSAGE_HANDLER(ViewHostMsg_GetPluginInfo, OnGetPluginInfo) - IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPlugin, + IPC_MESSAGE_HANDLER(FrameHostMsg_GetPluginInfo, OnGetPluginInfo) + IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_OpenChannelToPlugin, OnOpenChannelToPlugin) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPepperPlugin, OnOpenChannelToPepperPlugin) @@ -714,7 +735,7 @@ void RenderMessageFilter::GetPluginsCallback( } void RenderMessageFilter::OnGetPluginInfo( - int routing_id, + int render_frame_id, const GURL& url, const GURL& page_url, const std::string& mime_type, @@ -723,12 +744,12 @@ void RenderMessageFilter::OnGetPluginInfo( std::string* actual_mime_type) { bool allow_wildcard = true; *found = plugin_service_->GetPluginInfo( - render_process_id_, routing_id, resource_context_, + render_process_id_, render_frame_id, resource_context_, url, page_url, mime_type, allow_wildcard, NULL, info, actual_mime_type); } -void RenderMessageFilter::OnOpenChannelToPlugin(int routing_id, +void RenderMessageFilter::OnOpenChannelToPlugin(int render_frame_id, const GURL& url, const GURL& policy_url, const std::string& mime_type, @@ -738,7 +759,7 @@ void RenderMessageFilter::OnOpenChannelToPlugin(int routing_id, DCHECK(!ContainsKey(plugin_host_clients_, client)); plugin_host_clients_.insert(client); plugin_service_->OpenChannelToNpapiPlugin( - render_process_id_, routing_id, + render_process_id_, render_frame_id, url, policy_url, mime_type, client); } @@ -843,7 +864,7 @@ void RenderMessageFilter::OnGetMonitorColorProfile(std::vector<char>* profile) { void RenderMessageFilter::OnDownloadUrl(const IPC::Message& message, const GURL& url, const Referrer& referrer, - const string16& suggested_name) { + const base::string16& suggested_name) { scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo()); save_info->suggested_name = suggested_name; scoped_ptr<net::URLRequest> request( @@ -1112,7 +1133,7 @@ void RenderMessageFilter::OnDidLose3DContext( #if defined(OS_WIN) void RenderMessageFilter::OnPreCacheFontCharacters(const LOGFONT& font, - const string16& str) { + const base::string16& str) { // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too. // Except that for True Type fonts, // GetTextMetrics will not load the font in memory. @@ -1156,21 +1177,78 @@ void RenderMessageFilter::OnWebAudioMediaCodec( #endif void RenderMessageFilter::OnAllocateGpuMemoryBuffer( - uint32 buffer_size, + uint32 width, + uint32 height, + uint32 internalformat, gfx::GpuMemoryBufferHandle* handle) { - // TODO(reveman): Implement allocation of real GpuMemoryBuffer. - // Currently this function creates a fake GpuMemoryBuffer that is - // backed by shared memory and requires an upload before it can - // be used as a texture. The plan is to instead have this function - // allocate a real GpuMemoryBuffer in whatever form is supported - // by platform and drivers. - // - // Note: |buffer_size| likely needs to be replaced by a more - // specific buffer description but is enough for the shared memory - // backed GpuMemoryBuffer currently returned. + if (!GpuMemoryBufferImpl::IsFormatValid(internalformat)) { + handle->type = gfx::EMPTY_BUFFER; + return; + } + +#if defined(OS_MACOSX) + if (GpuMemoryBufferImplIOSurface::IsFormatSupported(internalformat)) { + IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); + if (io_surface_support) { + base::ScopedCFTypeRef<CFMutableDictionaryRef> properties; + properties.reset( + CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + AddIntegerValue(properties, + io_surface_support->GetKIOSurfaceWidth(), + width); + AddIntegerValue(properties, + io_surface_support->GetKIOSurfaceHeight(), + height); + AddIntegerValue(properties, + io_surface_support->GetKIOSurfaceBytesPerElement(), + GpuMemoryBufferImpl::BytesPerPixel(internalformat)); + AddIntegerValue(properties, + io_surface_support->GetKIOSurfacePixelFormat(), + GpuMemoryBufferImplIOSurface::PixelFormat( + internalformat)); + // TODO(reveman): Remove this when using a mach_port_t to transfer + // IOSurface to renderer process. crbug.com/323304 + AddBooleanValue(properties, + io_surface_support->GetKIOSurfaceIsGlobal(), + true); + + base::ScopedCFTypeRef<CFTypeRef> io_surface( + io_surface_support->IOSurfaceCreate(properties)); + if (io_surface) { + handle->type = gfx::IO_SURFACE_BUFFER; + handle->io_surface_id = io_surface_support->IOSurfaceGetID(io_surface); + + // TODO(reveman): This makes the assumption that the renderer will + // grab a reference to the surface before sending another message. + // crbug.com/325045 + last_io_surface_ = io_surface; + return; + } + } + } +#endif + + uint64 stride = static_cast<uint64>(width) * + GpuMemoryBufferImpl::BytesPerPixel(internalformat); + if (stride > std::numeric_limits<uint32>::max()) { + handle->type = gfx::EMPTY_BUFFER; + return; + } + + uint64 buffer_size = stride * static_cast<uint64>(height); + if (buffer_size > std::numeric_limits<size_t>::max()) { + handle->type = gfx::EMPTY_BUFFER; + return; + } + + // Fallback to fake GpuMemoryBuffer that is backed by shared memory and + // requires an upload before it can be used as a texture. handle->type = gfx::SHARED_MEMORY_BUFFER; ChildProcessHostImpl::AllocateSharedMemory( - buffer_size, PeerHandle(), &handle->handle); + static_cast<size_t>(buffer_size), PeerHandle(), &handle->handle); } } // namespace content diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h index 526849e102..ce135d928f 100644 --- a/content/browser/renderer_host/render_message_filter.h +++ b/content/browser/renderer_host/render_message_filter.h @@ -30,6 +30,7 @@ #include "ui/surface/transport_dib.h" #if defined(OS_MACOSX) +#include "base/mac/scoped_cftyperef.h" #include "content/common/mac/font_loader.h" #endif @@ -156,20 +157,20 @@ class RenderMessageFilter : public BrowserMessageFilter { #if defined(OS_WIN) void OnPreCacheFontCharacters(const LOGFONT& log_font, - const string16& characters); + const base::string16& characters); #endif void OnGetPlugins(bool refresh, IPC::Message* reply_msg); void GetPluginsCallback(IPC::Message* reply_msg, const std::vector<WebPluginInfo>& plugins); - void OnGetPluginInfo(int routing_id, + void OnGetPluginInfo(int render_frame_id, const GURL& url, const GURL& policy_url, const std::string& mime_type, bool* found, WebPluginInfo* info, std::string* actual_mime_type); - void OnOpenChannelToPlugin(int routing_id, + void OnOpenChannelToPlugin(int render_frame_id, const GURL& url, const GURL& policy_url, const std::string& mime_type, @@ -190,7 +191,7 @@ class RenderMessageFilter : public BrowserMessageFilter { void OnDownloadUrl(const IPC::Message& message, const GURL& url, const Referrer& referrer, - const string16& suggested_name); + const base::string16& suggested_name); void OnCheckNotificationPermission(const GURL& source_origin, int* permission_level); @@ -259,7 +260,9 @@ class RenderMessageFilter : public BrowserMessageFilter { uint32_t data_size); #endif - void OnAllocateGpuMemoryBuffer(uint32 buffer_size, + void OnAllocateGpuMemoryBuffer(uint32 width, + uint32 height, + uint32 internalformat, gfx::GpuMemoryBufferHandle* handle); // Cached resource request dispatcher host and plugin service, guaranteed to @@ -302,6 +305,10 @@ class RenderMessageFilter : public BrowserMessageFilter { media::AudioManager* audio_manager_; MediaInternals* media_internals_; +#if defined(OS_MACOSX) + base::ScopedCFTypeRef<CFTypeRef> last_io_surface_; +#endif + DISALLOW_COPY_AND_ASSIGN(RenderMessageFilter); }; diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 08e75cf2ad..231b59df69 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -101,7 +101,6 @@ #include "content/browser/speech/speech_recognition_dispatcher_host.h" #include "content/browser/storage_partition_impl.h" #include "content/browser/streams/stream_context.h" -#include "content/browser/tracing/trace_controller_impl.h" #include "content/browser/tracing/trace_message_filter.h" #include "content/browser/vibration/vibration_message_filter.h" #include "content/browser/webui/web_ui_controller_factory_registry.h" @@ -669,7 +668,7 @@ void RenderProcessHostImpl::CreateMessageFilters() { peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID()); AddFilter(peer_connection_tracker_host_.get()); AddFilter(new MediaStreamDispatcherHost( - GetID(), media_stream_manager)); + GetID(), browser_context->GetResourceContext(), media_stream_manager)); AddFilter( new DeviceRequestMessageFilter(resource_context, media_stream_manager)); #endif @@ -823,6 +822,10 @@ bool RenderProcessHostImpl::WaitForBackingStoreMsg( } void RenderProcessHostImpl::ReceivedBadMessage() { + CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kDisableKillAfterBadIPC)) + return; + if (run_renderer_in_process()) { // In single process mode it is better if we don't suicide but just // crash. @@ -966,7 +969,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( switches::kDisableUnprefixedMediaSource, switches::kDisableVp8AlphaPlayback, switches::kDisableWebAnimationsCSS, - switches::kDisableWebAudio, switches::kDisableWebKitMediaSource, switches::kDomAutomationController, switches::kEnableAcceleratedFixedRootBackground, @@ -1035,6 +1037,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( switches::kNoReferrers, switches::kNoSandbox, switches::kPpapiInProcess, + switches::kProfilerTiming, switches::kRegisterPepperPlugins, switches::kRendererAssertTest, switches::kRendererStartupDialog, @@ -1072,13 +1075,12 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( cc::switches::kEnablePerTilePainting, cc::switches::kEnablePinchVirtualViewport, cc::switches::kEnableTopControlsPositionCalculation, - cc::switches::kForceDirectLayerDrawing, - cc::switches::kLowResolutionContentsScaleFactor, cc::switches::kMaxTilesForInterestArea, cc::switches::kMaxUnusedResourceMemoryUsagePercentage, cc::switches::kNumRasterThreads, cc::switches::kShowCompositedLayerBorders, cc::switches::kShowFPSCounter, + cc::switches::kShowLayerAnimationBounds, cc::switches::kShowNonOccludingRects, cc::switches::kShowOccludingRects, cc::switches::kShowPropertyChangedRects, @@ -1123,6 +1125,13 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( switches::kMediaDrmEnableNonCompositing, switches::kNetworkCountryIso, #endif +#if defined(OS_ANDROID) && defined(ARCH_CPU_X86) + switches::kEnableWebAudio, +#else + // Need to be able to disable webaudio on other platforms where it + // is enabled by default. + switches::kDisableWebAudio, +#endif #if defined(OS_MACOSX) // Allow this to be set when invoking the browser and relayed along. switches::kEnableSandboxLogging, @@ -1131,6 +1140,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( switches::kChildCleanExit, #endif #if defined(OS_WIN) + switches::kEnableDirectWrite, switches::kEnableHighResolutionTime, #endif }; @@ -1191,8 +1201,11 @@ bool RenderProcessHostImpl::FastShutdownIfPossible() { if (!SuddenTerminationAllowed()) return false; - ProcessDied(false /* already_dead */); + // Set this before ProcessDied() so observers can tell if the render process + // died due to fast shutdown versus another cause. fast_shutdown_started_ = true; + + ProcessDied(false /* already_dead */); return true; } diff --git a/content/browser/renderer_host/render_sandbox_host_linux.cc b/content/browser/renderer_host/render_sandbox_host_linux.cc index b35ac7365b..d17b1caa7c 100644 --- a/content/browser/renderer_host/render_sandbox_host_linux.cc +++ b/content/browser/renderer_host/render_sandbox_host_linux.cc @@ -241,7 +241,7 @@ class SandboxIPCProcess { SendRendererReply(fds, reply, result_fd); if (result_fd >= 0) { - int err = HANDLE_EINTR(close(result_fd)); + int err = IGNORE_EINTR(close(result_fd)); DCHECK(!err); } } @@ -516,7 +516,7 @@ class SandboxIPCProcess { SendRendererReply(fds, reply, font_fd); if (font_fd >= 0) { - if (HANDLE_EINTR(close(font_fd)) < 0) + if (IGNORE_EINTR(close(font_fd)) < 0) PLOG(ERROR) << "close"; } } @@ -709,18 +709,17 @@ void RenderSandboxHostLinux::Init(const std::string& sandbox_path) { childs_lifeline_fd_ = pipefds[1]; // We need to be monothreaded before we fork(). -#if !defined(TOOLKIT_GTK) && !defined(OS_CHROMEOS) +#if !defined(TOOLKIT_GTK) // Exclude gtk port as TestSuite in base/tests/test_suite.cc is calling // gtk_init. - // Exclude ChromeOS because KioskTest spawns EmbeddedTestServer. // TODO(oshima): Remove ifdef when above issues are resolved. DCHECK_EQ(1, base::GetNumberOfThreads(base::GetCurrentProcessHandle())); #endif pid_ = fork(); if (pid_ == 0) { - if (HANDLE_EINTR(close(fds[0])) < 0) + if (IGNORE_EINTR(close(fds[0])) < 0) DPLOG(ERROR) << "close"; - if (HANDLE_EINTR(close(pipefds[1])) < 0) + if (IGNORE_EINTR(close(pipefds[1])) < 0) DPLOG(ERROR) << "close"; SandboxIPCProcess handler(child_lifeline_fd, browser_socket, sandbox_path); @@ -731,9 +730,9 @@ void RenderSandboxHostLinux::Init(const std::string& sandbox_path) { RenderSandboxHostLinux::~RenderSandboxHostLinux() { if (initialized_) { - if (HANDLE_EINTR(close(renderer_socket_)) < 0) + if (IGNORE_EINTR(close(renderer_socket_)) < 0) PLOG(ERROR) << "close"; - if (HANDLE_EINTR(close(childs_lifeline_fd_)) < 0) + if (IGNORE_EINTR(close(childs_lifeline_fd_)) < 0) PLOG(ERROR) << "close"; } } diff --git a/content/browser/renderer_host/render_view_host_delegate.cc b/content/browser/renderer_host/render_view_host_delegate.cc index d7b8ba5374..4786909c92 100644 --- a/content/browser/renderer_host/render_view_host_delegate.cc +++ b/content/browser/renderer_host/render_view_host_delegate.cc @@ -24,8 +24,8 @@ bool RenderViewHostDelegate::OnMessageReceived(RenderViewHost* render_view_host, } bool RenderViewHostDelegate::AddMessageToConsole( - int32 level, const string16& message, int32 line_no, - const string16& source_id) { + int32 level, const base::string16& message, int32 line_no, + const base::string16& source_id) { return false; } diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h index f3bf8aafea..a258c36740 100644 --- a/content/browser/renderer_host/render_view_host_delegate.h +++ b/content/browser/renderer_host/render_view_host_delegate.h @@ -151,14 +151,6 @@ class CONTENT_EXPORT RenderViewHostDelegate { // RenderView is going to be destroyed virtual void RenderViewDeleted(RenderViewHost* render_view_host) {} - // The RenderView started a provisional load for a given frame. - virtual void DidStartProvisionalLoadForFrame( - RenderViewHost* render_view_host, - int64 frame_id, - int64 parent_frame_id, - bool main_frame, - const GURL& url) {} - // The RenderView processed a redirect during a provisional load. // // TODO(creis): Remove this method and have the pre-rendering code listen to @@ -195,7 +187,7 @@ class CONTENT_EXPORT RenderViewHostDelegate { // The page's title was changed and should be updated. virtual void UpdateTitle(RenderViewHost* render_view_host, int32 page_id, - const string16& title, + const base::string16& title, base::i18n::TextDirection title_direction) {} // The page's encoding was changed and should be updated. @@ -281,23 +273,23 @@ class CONTENT_EXPORT RenderViewHostDelegate { // A javascript message, confirmation or prompt should be shown. virtual void RunJavaScriptMessage(RenderViewHost* rvh, - const string16& message, - const string16& default_prompt, + const base::string16& message, + const base::string16& default_prompt, const GURL& frame_url, JavaScriptMessageType type, IPC::Message* reply_msg, bool* did_suppress_message) {} virtual void RunBeforeUnloadConfirm(RenderViewHost* rvh, - const string16& message, + const base::string16& message, bool is_reload, IPC::Message* reply_msg) {} // A message was added to to the console. virtual bool AddMessageToConsole(int32 level, - const string16& message, + const base::string16& message, int32 line_no, - const string16& source_id); + const base::string16& source_id); // Return a dummy RendererPreferences object that will be used by the renderer // associated with the owning RenderViewHost. @@ -382,8 +374,9 @@ class CONTENT_EXPORT RenderViewHostDelegate { virtual void LostMouseLock() {} // The page is trying to open a new page (e.g. a popup window). The window - // should be created associated with the given route, but it should not be - // shown yet. That should happen in response to ShowCreatedWindow. + // should be created associated with the given |route_id| in process + // |render_process_id|, but it should not be shown yet. That should happen in + // response to ShowCreatedWindow. // |params.window_container_type| describes the type of RenderViewHost // container that is requested -- in particular, the window.open call may // have specified 'background' and 'persistent' in the feature string. @@ -394,21 +387,24 @@ class CONTENT_EXPORT RenderViewHostDelegate { // Note: this is not called "CreateWindow" because that will clash with // the Windows function which is actually a #define. virtual void CreateNewWindow( + int render_process_id, int route_id, int main_frame_route_id, const ViewHostMsg_CreateWindow_Params& params, SessionStorageNamespace* session_storage_namespace) {} // The page is trying to open a new widget (e.g. a select popup). The - // widget should be created associated with the given route, but it should - // not be shown yet. That should happen in response to ShowCreatedWidget. + // widget should be created associated with the given |route_id| in the + // process |render_process_id|, but it should not be shown yet. That should + // happen in response to ShowCreatedWidget. // |popup_type| indicates if the widget is a popup and what kind of popup it // is (select, autofill...). - virtual void CreateNewWidget(int route_id, + virtual void CreateNewWidget(int render_process_id, + int route_id, blink::WebPopupType popup_type) {} // Creates a full screen RenderWidget. Similar to above. - virtual void CreateNewFullscreenWidget(int route_id) {} + virtual void CreateNewFullscreenWidget(int render_process_id, int route_id) {} // Show a previously created page with the specified disposition and bounds. // The window is identified by the route_id passed to CreateNewWindow. diff --git a/content/browser/renderer_host/render_view_host_factory.cc b/content/browser/renderer_host/render_view_host_factory.cc index 5cffd134b8..fe51c7efe6 100644 --- a/content/browser/renderer_host/render_view_host_factory.cc +++ b/content/browser/renderer_host/render_view_host_factory.cc @@ -16,17 +16,19 @@ RenderViewHostFactory* RenderViewHostFactory::factory_ = NULL; RenderViewHost* RenderViewHostFactory::Create( SiteInstance* instance, RenderViewHostDelegate* delegate, + RenderFrameHostDelegate* frame_delegate, RenderWidgetHostDelegate* widget_delegate, int routing_id, int main_frame_routing_id, bool swapped_out, bool hidden) { if (factory_) { - return factory_->CreateRenderViewHost(instance, delegate, widget_delegate, - routing_id, main_frame_routing_id, - swapped_out); + return factory_->CreateRenderViewHost(instance, delegate, frame_delegate, + widget_delegate, routing_id, + main_frame_routing_id, swapped_out); } - return new RenderViewHostImpl(instance, delegate, widget_delegate, routing_id, + return new RenderViewHostImpl(instance, delegate, frame_delegate, + widget_delegate, routing_id, main_frame_routing_id, swapped_out, hidden); } diff --git a/content/browser/renderer_host/render_view_host_factory.h b/content/browser/renderer_host/render_view_host_factory.h index b0466355d4..cf6a0f1b3f 100644 --- a/content/browser/renderer_host/render_view_host_factory.h +++ b/content/browser/renderer_host/render_view_host_factory.h @@ -9,6 +9,7 @@ #include "content/common/content_export.h" namespace content { +class RenderFrameHostDelegate; class RenderViewHost; class RenderViewHostDelegate; class RenderWidgetHostDelegate; @@ -26,6 +27,7 @@ class RenderViewHostFactory { static RenderViewHost* Create( SiteInstance* instance, RenderViewHostDelegate* delegate, + RenderFrameHostDelegate* frame_delegate, RenderWidgetHostDelegate* widget_delegate, int routing_id, int main_frame_routing_id, @@ -46,6 +48,7 @@ class RenderViewHostFactory { virtual RenderViewHost* CreateRenderViewHost( SiteInstance* instance, RenderViewHostDelegate* delegate, + RenderFrameHostDelegate* frame_delegate, RenderWidgetHostDelegate* widget_delegate, int routing_id, int main_frame_routing_id, diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index b19cd19ec4..491944e87a 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc @@ -159,6 +159,7 @@ RenderViewHostImpl* RenderViewHostImpl::FromID(int render_process_id, RenderViewHostImpl::RenderViewHostImpl( SiteInstance* instance, RenderViewHostDelegate* delegate, + RenderFrameHostDelegate* frame_delegate, RenderWidgetHostDelegate* widget_delegate, int routing_id, int main_frame_routing_id, @@ -193,7 +194,11 @@ RenderViewHostImpl::RenderViewHostImpl( main_frame_routing_id = GetProcess()->GetNextRoutingID(); main_render_frame_host_ = RenderFrameHostFactory::Create( - this, delegate_->GetFrameTree(), main_frame_routing_id, is_swapped_out_); + this, frame_delegate, delegate_->GetFrameTree(), + delegate_->GetFrameTree()->root(), + main_frame_routing_id, is_swapped_out_); + delegate_->GetFrameTree()->root()->set_render_frame_host( + main_render_frame_host_.get(), false); GetProcess()->EnableSendQueue(); @@ -243,7 +248,7 @@ SiteInstance* RenderViewHostImpl::GetSiteInstance() const { } bool RenderViewHostImpl::CreateRenderView( - const string16& frame_name, + const base::string16& frame_name, int opener_route_id, int32 max_page_id) { TRACE_EVENT0("renderer_host", "RenderViewHostImpl::CreateRenderView"); @@ -343,8 +348,13 @@ WebPreferences RenderViewHostImpl::GetWebkitPrefs(const GURL& url) { !command_line.HasSwitch(switches::kDisableLocalStorage); prefs.databases_enabled = !command_line.HasSwitch(switches::kDisableDatabases); +#if defined(OS_ANDROID) && defined(ARCH_CPU_X86) + prefs.webaudio_enabled = + command_line.HasSwitch(switches::kEnableWebAudio); +#else prefs.webaudio_enabled = !command_line.HasSwitch(switches::kDisableWebAudio); +#endif prefs.experimental_webgl_enabled = GpuProcessHost::gpu_enabled() && @@ -948,8 +958,9 @@ void RenderViewHostImpl::DesktopNotificationPostDisplay(int callback_context) { callback_context)); } -void RenderViewHostImpl::DesktopNotificationPostError(int notification_id, - const string16& message) { +void RenderViewHostImpl::DesktopNotificationPostError( + int notification_id, + const base::string16& message) { Send(new DesktopNotificationMsg_PostError( GetRoutingID(), notification_id, message)); } @@ -965,15 +976,15 @@ void RenderViewHostImpl::DesktopNotificationPostClick(int notification_id) { } void RenderViewHostImpl::ExecuteJavascriptInWebFrame( - const string16& frame_xpath, - const string16& jscript) { + const base::string16& frame_xpath, + const base::string16& jscript) { Send(new ViewMsg_ScriptEvalRequest(GetRoutingID(), frame_xpath, jscript, 0, false)); } void RenderViewHostImpl::ExecuteJavascriptInWebFrameCallbackResult( - const string16& frame_xpath, - const string16& jscript, + const base::string16& frame_xpath, + const base::string16& jscript, const JavascriptResultCallback& callback) { static int next_id = 1; int key = next_id++; @@ -982,9 +993,10 @@ void RenderViewHostImpl::ExecuteJavascriptInWebFrameCallbackResult( javascript_callbacks_.insert(std::make_pair(key, callback)); } -void RenderViewHostImpl::JavaScriptDialogClosed(IPC::Message* reply_msg, - bool success, - const string16& user_input) { +void RenderViewHostImpl::JavaScriptDialogClosed( + IPC::Message* reply_msg, + bool success, + const base::string16& user_input) { GetProcess()->SetIgnoreInputEvents(false); bool is_waiting = is_waiting_for_beforeunload_ack_ || is_waiting_for_unload_ack_; @@ -1179,10 +1191,6 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) { if (delegate_->OnMessageReceived(this, msg)) return true; - // TODO(jochen): Consider removing message handlers that only add a this - // pointer and forward the messages to the RenderViewHostDelegate. The - // respective delegates can handle the messages themselves in their - // OnMessageReceived implementation. bool handled = true; bool msg_is_ok = true; IPC_BEGIN_MESSAGE_MAP_EX(RenderViewHostImpl, msg, msg_is_ok) @@ -1321,17 +1329,18 @@ void RenderViewHostImpl::CreateNewWindow( FilterURL(policy, GetProcess(), true, &validated_params.opener_security_origin); - delegate_->CreateNewWindow(route_id, main_frame_route_id, - validated_params, session_storage_namespace); + delegate_->CreateNewWindow( + GetProcess()->GetID(), route_id, main_frame_route_id, validated_params, + session_storage_namespace); } void RenderViewHostImpl::CreateNewWidget(int route_id, blink::WebPopupType popup_type) { - delegate_->CreateNewWidget(route_id, popup_type); + delegate_->CreateNewWidget(GetProcess()->GetID(), route_id, popup_type); } void RenderViewHostImpl::CreateNewFullscreenWidget(int route_id) { - delegate_->CreateNewFullscreenWidget(route_id); + delegate_->CreateNewFullscreenWidget(GetProcess()->GetID(), route_id); } void RenderViewHostImpl::OnShowView(int route_id, @@ -1410,8 +1419,7 @@ void RenderViewHostImpl::OnDidStartProvisionalLoadForFrame( int64 parent_frame_id, bool is_main_frame, const GURL& url) { - delegate_->DidStartProvisionalLoadForFrame( - this, frame_id, parent_frame_id, is_main_frame, url); + NOTREACHED(); } void RenderViewHostImpl::OnDidRedirectProvisionalLoad( @@ -1535,7 +1543,7 @@ void RenderViewHostImpl::OnUpdateState(int32 page_id, const PageState& state) { void RenderViewHostImpl::OnUpdateTitle( int32 page_id, - const string16& title, + const base::string16& title, blink::WebTextDirection title_direction) { if (title.length() > kMaxTitleChars) { NOTREACHED() << "Renderer sent too many characters in title."; @@ -1669,7 +1677,7 @@ void RenderViewHostImpl::OnDidChangeScrollOffsetPinningForMainFrame( void RenderViewHostImpl::OnDidChangeNumWheelEvents(int count) { } -void RenderViewHostImpl::OnSelectionChanged(const string16& text, +void RenderViewHostImpl::OnSelectionChanged(const base::string16& text, size_t offset, const gfx::Range& range) { if (view_) @@ -1695,8 +1703,8 @@ void RenderViewHostImpl::OnRouteMessageEvent( } void RenderViewHostImpl::OnRunJavaScriptMessage( - const string16& message, - const string16& default_prompt, + const base::string16& message, + const base::string16& default_prompt, const GURL& frame_url, JavaScriptMessageType type, IPC::Message* reply_msg) { @@ -1710,7 +1718,7 @@ void RenderViewHostImpl::OnRunJavaScriptMessage( } void RenderViewHostImpl::OnRunBeforeUnloadConfirm(const GURL& frame_url, - const string16& message, + const base::string16& message, bool is_reload, IPC::Message* reply_msg) { // While a JS before unload dialog is showing, tabs in the same process @@ -1789,9 +1797,9 @@ void RenderViewHostImpl::OnFocusedNodeChanged(bool is_editable_node) { void RenderViewHostImpl::OnAddMessageToConsole( int32 level, - const string16& message, + const base::string16& message, int32 line_no, - const string16& source_id) { + const base::string16& source_id) { if (delegate_->AddMessageToConsole(level, message, line_no, source_id)) return; @@ -2076,12 +2084,12 @@ void RenderViewHostImpl::ReloadFrame() { } void RenderViewHostImpl::Find(int request_id, - const string16& search_text, + const base::string16& search_text, const blink::WebFindOptions& options) { Send(new ViewMsg_Find(GetRoutingID(), request_id, search_text, options)); } -void RenderViewHostImpl::InsertCSS(const string16& frame_xpath, +void RenderViewHostImpl::InsertCSS(const base::string16& frame_xpath, const std::string& css) { Send(new ViewMsg_CSSInsertRequest(GetRoutingID(), frame_xpath, css)); } @@ -2203,15 +2211,6 @@ void RenderViewHostImpl::OnRequestDesktopNotificationPermission( void RenderViewHostImpl::OnShowDesktopNotification( const ShowDesktopNotificationHostMsgParams& params) { - // Disallow HTML notifications from javascript: and file: schemes as this - // allows unwanted cross-domain access. - GURL url = params.contents_url; - if (params.is_html && - (url.SchemeIs(kJavaScriptScheme) || - url.SchemeIs(chrome::kFileScheme))) { - return; - } - GetContentClient()->browser()->ShowDesktopNotification( params, GetProcess()->GetID(), GetRoutingID(), false); } diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h index 424a787ffa..44851eea0e 100644 --- a/content/browser/renderer_host/render_view_host_impl.h +++ b/content/browser/renderer_host/render_view_host_impl.h @@ -61,6 +61,7 @@ namespace content { class BrowserMediaPlayerManager; class ChildProcessSecurityPolicyImpl; class PageState; +class RenderFrameHostDelegate; class RenderFrameHostImpl; class RenderWidgetHostDelegate; class SessionStorageNamespace; @@ -118,6 +119,7 @@ class CONTENT_EXPORT RenderViewHostImpl RenderViewHostImpl( SiteInstance* instance, RenderViewHostDelegate* delegate, + RenderFrameHostDelegate* frame_delegate, RenderWidgetHostDelegate* widget_delegate, int routing_id, int main_frame_routing_id, @@ -133,8 +135,9 @@ class CONTENT_EXPORT RenderViewHostImpl virtual void DesktopNotificationPermissionRequestDone( int callback_context) OVERRIDE; virtual void DesktopNotificationPostDisplay(int callback_context) OVERRIDE; - virtual void DesktopNotificationPostError(int notification_id, - const string16& message) OVERRIDE; + virtual void DesktopNotificationPostError( + int notification_id, + const base::string16& message) OVERRIDE; virtual void DesktopNotificationPostClose(int notification_id, bool by_user) OVERRIDE; virtual void DesktopNotificationPostClick(int notification_id) OVERRIDE; @@ -172,17 +175,18 @@ class CONTENT_EXPORT RenderViewHostImpl virtual void ExecuteMediaPlayerActionAtLocation( const gfx::Point& location, const blink::WebMediaPlayerAction& action) OVERRIDE; - virtual void ExecuteJavascriptInWebFrame(const string16& frame_xpath, - const string16& jscript) OVERRIDE; + virtual void ExecuteJavascriptInWebFrame( + const base::string16& frame_xpath, + const base::string16& jscript) OVERRIDE; virtual void ExecuteJavascriptInWebFrameCallbackResult( - const string16& frame_xpath, - const string16& jscript, + const base::string16& frame_xpath, + const base::string16& jscript, const JavascriptResultCallback& callback) OVERRIDE; virtual void ExecutePluginActionAtLocation( const gfx::Point& location, const blink::WebPluginAction& action) OVERRIDE; virtual void ExitFullscreen() OVERRIDE; - virtual void Find(int request_id, const string16& search_text, + virtual void Find(int request_id, const base::string16& search_text, const blink::WebFindOptions& options) OVERRIDE; virtual void StopFinding(StopFindAction action) OVERRIDE; virtual void FirePageBeforeUnload(bool for_cross_site_transition) OVERRIDE; @@ -192,7 +196,7 @@ class CONTENT_EXPORT RenderViewHostImpl virtual RenderViewHostDelegate* GetDelegate() const OVERRIDE; virtual int GetEnabledBindings() const OVERRIDE; virtual SiteInstance* GetSiteInstance() const OVERRIDE; - virtual void InsertCSS(const string16& frame_xpath, + virtual void InsertCSS(const base::string16& frame_xpath, const std::string& css) OVERRIDE; virtual bool IsRenderViewLive() const OVERRIDE; virtual bool IsSubframe() const OVERRIDE; @@ -233,7 +237,7 @@ class CONTENT_EXPORT RenderViewHostImpl // The |opener_route_id| parameter indicates which RenderView created this // (MSG_ROUTING_NONE if none). If |max_page_id| is larger than -1, the // RenderView is told to start issuing page IDs at |max_page_id| + 1. - virtual bool CreateRenderView(const string16& frame_name, + virtual bool CreateRenderView(const base::string16& frame_name, int opener_route_id, int32 max_page_id); @@ -348,7 +352,7 @@ class CONTENT_EXPORT RenderViewHostImpl // closed by the user. void JavaScriptDialogClosed(IPC::Message* reply_msg, bool success, - const string16& user_input); + const base::string16& user_input); // Tells the renderer view to focus the first (last if reverse is true) node. void SetInitialFocus(bool reverse); @@ -534,7 +538,7 @@ class CONTENT_EXPORT RenderViewHostImpl void OnNavigate(const IPC::Message& msg); void OnUpdateState(int32 page_id, const PageState& state); void OnUpdateTitle(int32 page_id, - const string16& title, + const base::string16& title, blink::WebTextDirection title_direction); void OnUpdateEncoding(const std::string& encoding); void OnUpdateTargetURL(int32 page_id, const GURL& url); @@ -556,7 +560,7 @@ class CONTENT_EXPORT RenderViewHostImpl void OnDidChangeScrollOffsetPinningForMainFrame(bool is_pinned_to_left, bool is_pinned_to_right); void OnDidChangeNumWheelEvents(int count); - void OnSelectionChanged(const string16& text, + void OnSelectionChanged(const base::string16& text, size_t offset, const gfx::Range& range); void OnSelectionBoundsChanged( @@ -564,13 +568,13 @@ class CONTENT_EXPORT RenderViewHostImpl void OnPasteFromSelectionClipboard(); void OnRouteCloseEvent(); void OnRouteMessageEvent(const ViewMsg_PostMessage_Params& params); - void OnRunJavaScriptMessage(const string16& message, - const string16& default_prompt, + void OnRunJavaScriptMessage(const base::string16& message, + const base::string16& default_prompt, const GURL& frame_url, JavaScriptMessageType type, IPC::Message* reply_msg); void OnRunBeforeUnloadConfirm(const GURL& frame_url, - const string16& message, + const base::string16& message, bool is_reload, IPC::Message* reply_msg); void OnStartDragging(const DropData& drop_data, @@ -583,9 +587,9 @@ class CONTENT_EXPORT RenderViewHostImpl void OnTakeFocus(bool reverse); void OnFocusedNodeChanged(bool is_editable_node); void OnAddMessageToConsole(int32 level, - const string16& message, + const base::string16& message, int32 line_no, - const string16& source_id); + const base::string16& source_id); void OnUpdateInspectorSetting(const std::string& key, const std::string& value); void OnShouldCloseACK( diff --git a/content/browser/renderer_host/render_view_host_unittest.cc b/content/browser/renderer_host/render_view_host_unittest.cc index 67e08d2838..e81e67fc34 100644 --- a/content/browser/renderer_host/render_view_host_unittest.cc +++ b/content/browser/renderer_host/render_view_host_unittest.cc @@ -5,7 +5,6 @@ #include "base/path_service.h" #include "base/strings/utf_string_conversions.h" #include "content/browser/child_process_security_policy_impl.h" -#include "content/browser/renderer_host/test_render_view_host.h" #include "content/common/input_messages.h" #include "content/common/view_messages.h" #include "content/port/browser/render_view_host_delegate_view.h" @@ -16,6 +15,7 @@ #include "content/public/common/url_constants.h" #include "content/public/test/mock_render_process_host.h" #include "content/test/test_content_browser_client.h" +#include "content/test/test_render_view_host.h" #include "content/test/test_web_contents.h" #include "net/base/net_util.h" #include "third_party/WebKit/public/web/WebDragOperation.h" @@ -199,7 +199,7 @@ TEST_F(RenderViewHostTest, DragEnteredFileURLsStillBlocked) { GURL sensitive_file_url = net::FilePathToFileURL(sensitive_file_path); dropped_data.url = highlighted_file_url; dropped_data.filenames.push_back(DropData::FileInfo( - UTF8ToUTF16(dragged_file_path.AsUTF8Unsafe()), string16())); + UTF8ToUTF16(dragged_file_path.AsUTF8Unsafe()), base::string16())); rvh()->DragTargetDragEnter(dropped_data, client_point, screen_point, blink::WebDragOperationNone, 0); diff --git a/content/browser/renderer_host/render_widget_helper.cc b/content/browser/renderer_host/render_widget_helper.cc index 7f772e382b..10e4e0ffa1 100644 --- a/content/browser/renderer_host/render_widget_helper.cc +++ b/content/browser/renderer_host/render_widget_helper.cc @@ -381,7 +381,7 @@ void RenderWidgetHelper::FreeTransportDIB(TransportDIB::Id dib_id) { i = allocated_dibs_.find(dib_id); if (i != allocated_dibs_.end()) { - if (HANDLE_EINTR(close(i->second)) < 0) + if (IGNORE_EINTR(close(i->second)) < 0) PLOG(ERROR) << "close"; allocated_dibs_.erase(i); } else { @@ -392,7 +392,7 @@ void RenderWidgetHelper::FreeTransportDIB(TransportDIB::Id dib_id) { void RenderWidgetHelper::ClearAllocatedDIBs() { for (std::map<TransportDIB::Id, int>::iterator i = allocated_dibs_.begin(); i != allocated_dibs_.end(); ++i) { - if (HANDLE_EINTR(close(i->second)) < 0) + if (IGNORE_EINTR(close(i->second)) < 0) PLOG(ERROR) << "close: " << i->first; } diff --git a/content/browser/renderer_host/render_widget_host_browsertest.cc b/content/browser/renderer_host/render_widget_host_browsertest.cc index bfdf6a5450..f9b3fd3519 100644 --- a/content/browser/renderer_host/render_widget_host_browsertest.cc +++ b/content/browser/renderer_host/render_widget_host_browsertest.cc @@ -47,7 +47,8 @@ class RenderWidgetHostBrowserTest : public ContentBrowserTest { }; // Disabled on Windows and CrOS because it is flaky: crbug.com/272379. -#if defined(OS_WIN) || defined(OS_CHROMEOS) +// Disabled on Ozone due to flake: crbug.com/315392. +#if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(USE_OZONE) #define MAYBE_GetSnapshotFromRendererTest DISABLED_GetSnapshotFromRendererTest #else #define MAYBE_GetSnapshotFromRendererTest GetSnapshotFromRendererTest diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 67b3b1f228..78edc465cf 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc @@ -30,10 +30,11 @@ #include "content/browser/renderer_host/backing_store.h" #include "content/browser/renderer_host/backing_store_manager.h" #include "content/browser/renderer_host/dip_util.h" -#include "content/browser/renderer_host/input/immediate_input_router.h" +#include "content/browser/renderer_host/input/input_router_impl.h" #include "content/browser/renderer_host/input/synthetic_gesture.h" #include "content/browser/renderer_host/input/synthetic_gesture_controller.h" #include "content/browser/renderer_host/input/synthetic_gesture_target.h" +#include "content/browser/renderer_host/input/timeout_monitor.h" #include "content/browser/renderer_host/overscroll_controller.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_view_host_impl.h" @@ -212,9 +213,10 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate, is_threaded_compositing_enabled_ = IsThreadedCompositingEnabled(); - - g_routing_id_widget_map.Get().insert(std::make_pair( - RenderWidgetHostID(process->GetID(), routing_id_), this)); + std::pair<RoutingIDWidgetMap::iterator, bool> result = + g_routing_id_widget_map.Get().insert(std::make_pair( + RenderWidgetHostID(process->GetID(), routing_id_), this)); + CHECK(result.second) << "Inserting a duplicate item!"; process_->AddRoute(routing_id_, this); // If we're initially visible, tell the process host that we're alive. @@ -225,14 +227,20 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate, accessibility_mode_ = BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode(); - input_router_.reset( - new ImmediateInputRouter(process_, this, this, routing_id_)); + input_router_.reset(new InputRouterImpl(process_, this, this, routing_id_)); #if defined(USE_AURA) bool overscroll_enabled = CommandLine::ForCurrentProcess()-> GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0"; SetOverscrollControllerEnabled(overscroll_enabled); #endif + + if (GetProcess()->IsGuest() || !CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableHangMonitor)) { + hang_monitor_timeout_.reset(new TimeoutMonitor( + base::Bind(&RenderWidgetHostImpl::RendererIsUnresponsive, + weak_factory_.GetWeakPtr()))); + } } RenderWidgetHostImpl::~RenderWidgetHostImpl() { @@ -897,53 +905,21 @@ bool RenderWidgetHostImpl::ScheduleComposite() { return true; } -void RenderWidgetHostImpl::StartHangMonitorTimeout(TimeDelta delay) { - if (!GetProcess()->IsGuest() && CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableHangMonitor)) { - return; - } - - // Set time_when_considered_hung_ if it's null. Also, update - // time_when_considered_hung_ if the caller's request is sooner than the - // existing one. This will have the side effect that the existing timeout will - // be forgotten. - Time requested_end_time = Time::Now() + delay; - if (time_when_considered_hung_.is_null() || - time_when_considered_hung_ > requested_end_time) - time_when_considered_hung_ = requested_end_time; - - // If we already have a timer with the same or shorter duration, then we can - // wait for it to finish. - if (hung_renderer_timer_.IsRunning() && - hung_renderer_timer_.GetCurrentDelay() <= delay) { - // If time_when_considered_hung_ was null, this timer may fire early. - // CheckRendererIsUnresponsive handles that by calling - // StartHangMonitorTimeout with the remaining time. - // If time_when_considered_hung_ was non-null, it means we still haven't - // heard from the renderer so we leave time_when_considered_hung_ as is. - return; - } - - // Either the timer is not yet running, or we need to adjust the timer to - // fire sooner. - time_when_considered_hung_ = requested_end_time; - hung_renderer_timer_.Stop(); - hung_renderer_timer_.Start(FROM_HERE, delay, this, - &RenderWidgetHostImpl::CheckRendererIsUnresponsive); +void RenderWidgetHostImpl::StartHangMonitorTimeout(base::TimeDelta delay) { + if (hang_monitor_timeout_) + hang_monitor_timeout_->Start(delay); } void RenderWidgetHostImpl::RestartHangMonitorTimeout() { - // Setting to null will cause StartHangMonitorTimeout to restart the timer. - time_when_considered_hung_ = Time(); - StartHangMonitorTimeout( - TimeDelta::FromMilliseconds(hung_renderer_delay_ms_)); + if (hang_monitor_timeout_) + hang_monitor_timeout_->Restart( + base::TimeDelta::FromMilliseconds(hung_renderer_delay_ms_)); } void RenderWidgetHostImpl::StopHangMonitorTimeout() { - time_when_considered_hung_ = Time(); + if (hang_monitor_timeout_) + hang_monitor_timeout_->Stop(); RendererIsResponsive(); - // We do not bother to stop the hung_renderer_timer_ here in case it will be - // started again shortly, which happens to be the common use case. } void RenderWidgetHostImpl::EnableFullAccessibilityMode() { @@ -1256,8 +1232,7 @@ void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status, waiting_for_screen_rects_ack_ = false; // Reset to ensure that input routing works with a new renderer. - input_router_.reset( - new ImmediateInputRouter(process_, this, this, routing_id_)); + input_router_.reset(new InputRouterImpl(process_, this, this, routing_id_)); if (overscroll_controller_) overscroll_controller_->Reset(); @@ -1310,8 +1285,20 @@ void RenderWidgetHostImpl::SetInputMethodActive(bool activate) { Send(new ViewMsg_SetInputMethodActive(GetRoutingID(), activate)); } +void RenderWidgetHostImpl::CandidateWindowShown() { + Send(new ViewMsg_CandidateWindowShown(GetRoutingID())); +} + +void RenderWidgetHostImpl::CandidateWindowUpdated() { + Send(new ViewMsg_CandidateWindowUpdated(GetRoutingID())); +} + +void RenderWidgetHostImpl::CandidateWindowHidden() { + Send(new ViewMsg_CandidateWindowHidden(GetRoutingID())); +} + void RenderWidgetHostImpl::ImeSetComposition( - const string16& text, + const base::string16& text, const std::vector<blink::WebCompositionUnderline>& underlines, int selection_start, int selection_end) { @@ -1320,7 +1307,7 @@ void RenderWidgetHostImpl::ImeSetComposition( } void RenderWidgetHostImpl::ImeConfirmComposition( - const string16& text, + const base::string16& text, const gfx::Range& replacement_range, bool keep_selection) { Send(new ViewMsg_ImeConfirmComposition( @@ -1328,7 +1315,7 @@ void RenderWidgetHostImpl::ImeConfirmComposition( } void RenderWidgetHostImpl::ImeCancelComposition() { - Send(new ViewMsg_ImeSetComposition(GetRoutingID(), string16(), + Send(new ViewMsg_ImeSetComposition(GetRoutingID(), base::string16(), std::vector<blink::WebCompositionUnderline>(), 0, 0)); } @@ -1387,19 +1374,7 @@ void RenderWidgetHostImpl::Destroy() { delete this; } -void RenderWidgetHostImpl::CheckRendererIsUnresponsive() { - // If we received a call to StopHangMonitorTimeout. - if (time_when_considered_hung_.is_null()) - return; - - // If we have not waited long enough, then wait some more. - Time now = Time::Now(); - if (now < time_when_considered_hung_) { - StartHangMonitorTimeout(time_when_considered_hung_ - now); - return; - } - - // OK, looks like we have a hung renderer! +void RenderWidgetHostImpl::RendererIsUnresponsive() { NotificationService::current()->Notify( NOTIFICATION_RENDER_WIDGET_HOST_HANG, Source<RenderWidgetHost>(this), @@ -1432,7 +1407,7 @@ void RenderWidgetHostImpl::OnClose() { } void RenderWidgetHostImpl::OnSetTooltipText( - const string16& tooltip_text, + const base::string16& tooltip_text, WebTextDirection text_direction_hint) { // First, add directionality marks around tooltip text if necessary. // A naive solution would be to simply always wrap the text. However, on @@ -1447,7 +1422,7 @@ void RenderWidgetHostImpl::OnSetTooltipText( // trying to detect the directionality from the tooltip text rather than the // element direction. One could argue that would be a preferable solution // but we use the current approach to match Fx & IE's behavior. - string16 wrapped_tooltip_text = tooltip_text; + base::string16 wrapped_tooltip_text = tooltip_text; if (!tooltip_text.empty()) { if (text_direction_hint == blink::WebTextDirectionLeftToRight) { // Force the tooltip to have LTR directionality. @@ -1526,6 +1501,13 @@ bool RenderWidgetHostImpl::OnSwapCompositorFrame( uint32 output_surface_id = param.a; param.b.AssignTo(frame.get()); + bool fixed_page_scale = + frame->metadata.min_page_scale_factor == + frame->metadata.max_page_scale_factor; + int updated_view_flags = fixed_page_scale ? InputRouter::FIXED_PAGE_SCALE + : InputRouter::VIEW_FLAGS_NONE; + input_router_->OnViewUpdated(updated_view_flags); + if (view_) { view_->OnSwapCompositorFrame(output_surface_id, frame.Pass()); view_->DidReceiveRendererFrame(); @@ -1925,11 +1907,11 @@ void RenderWidgetHostImpl::ScrollBackingStoreRect(const gfx::Vector2d& delta, backing_store->ScrollBackingStore(delta, clip_rect, view_size); } -void RenderWidgetHostImpl::Replace(const string16& word) { +void RenderWidgetHostImpl::Replace(const base::string16& word) { Send(new InputMsg_Replace(routing_id_, word)); } -void RenderWidgetHostImpl::ReplaceMisspelling(const string16& word) { +void RenderWidgetHostImpl::ReplaceMisspelling(const base::string16& word) { Send(new InputMsg_ReplaceMisspelling(routing_id_, word)); } diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 36a63e3d41..d1231cac59 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h @@ -83,6 +83,7 @@ class OverscrollController; class RenderWidgetHostDelegate; class RenderWidgetHostViewPort; class SyntheticGestureController; +class TimeoutMonitor; struct EditCommand; // This implements the RenderWidgetHost interface that is exposed to @@ -164,8 +165,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost, int tag, const gfx::Size& page_size, const gfx::Size& desired_size) OVERRIDE; - virtual void Replace(const string16& word) OVERRIDE; - virtual void ReplaceMisspelling(const string16& word) OVERRIDE; + virtual void Replace(const base::string16& word) OVERRIDE; + virtual void ReplaceMisspelling(const base::string16& word) OVERRIDE; virtual void ResizeRectChanged(const gfx::Rect& new_rect) OVERRIDE; virtual void RestartHangMonitorTimeout() OVERRIDE; virtual void SetIgnoreInputEvents(bool ignore_input_events) OVERRIDE; @@ -312,6 +313,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost, // display input method windows under the cursor.) void SetInputMethodActive(bool activate); + // Notifies the renderer changes of IME candidate window state. + void CandidateWindowShown(); + void CandidateWindowUpdated(); + void CandidateWindowHidden(); + // Update the composition node of the renderer (or WebKit). // WebKit has a special node (a composition node) for input method to change // its text without affecting any other DOM nodes. When the input method @@ -328,7 +334,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost, // * when it receives a "preedit_changed" signal of GtkIMContext (on Linux); // * when markedText of NSTextInput is called (on Mac). void ImeSetComposition( - const string16& text, + const base::string16& text, const std::vector<blink::WebCompositionUnderline>& underlines, int selection_start, int selection_end); @@ -339,7 +345,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost, // (on Windows); // * when it receives a "commit" signal of GtkIMContext (on Linux); // * when insertText of NSTextInput is called (on Mac). - void ImeConfirmComposition(const string16& text, + void ImeConfirmComposition(const base::string16& text, const gfx::Range& replacement_range, bool keep_selection); @@ -631,9 +637,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost, // Tell this object to destroy itself. void Destroy(); - // Checks whether the renderer is hung and calls NotifyRendererUnresponsive - // if it is. - void CheckRendererIsUnresponsive(); + // Called by |hang_timeout_monitor_| on delayed response from the renderer. + void RendererIsUnresponsive(); // Called if we know the renderer is responsive. When we currently think the // renderer is unresponsive, this will clear that state and call @@ -646,7 +651,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost, void OnClose(); void OnUpdateScreenRectsAck(); void OnRequestMove(const gfx::Rect& pos); - void OnSetTooltipText(const string16& tooltip_text, + void OnSetTooltipText(const base::string16& tooltip_text, blink::WebTextDirection text_direction_hint); void OnPaintAtSizeAck(int tag, const gfx::Size& size); #if defined(OS_MACOSX) @@ -905,6 +910,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost, scoped_ptr<OverscrollController> overscroll_controller_; + scoped_ptr<TimeoutMonitor> hang_monitor_timeout_; + #if defined(OS_WIN) std::list<HWND> dummy_windows_for_activation_; #endif diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc index f1edc910ae..967c814271 100644 --- a/content/browser/renderer_host/render_widget_host_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_unittest.cc @@ -10,15 +10,14 @@ #include "content/browser/browser_thread_impl.h" #include "content/browser/renderer_host/backing_store.h" #include "content/browser/renderer_host/input/gesture_event_filter.h" -#include "content/browser/renderer_host/input/immediate_input_router.h" -#include "content/browser/renderer_host/input/synthetic_web_input_event_builders.h" +#include "content/browser/renderer_host/input/input_router_impl.h" #include "content/browser/renderer_host/input/tap_suppression_controller.h" #include "content/browser/renderer_host/input/tap_suppression_controller_client.h" #include "content/browser/renderer_host/input/touch_event_queue.h" #include "content/browser/renderer_host/overscroll_controller.h" #include "content/browser/renderer_host/overscroll_controller_delegate.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" -#include "content/browser/renderer_host/test_render_view_host.h" +#include "content/common/input/synthetic_web_input_event_builders.h" #include "content/common/input_messages.h" #include "content/common/view_messages.h" #include "content/port/browser/render_widget_host_view_port.h" @@ -29,6 +28,7 @@ #include "content/public/browser/notification_types.h" #include "content/public/test/mock_render_process_host.h" #include "content/public/test/test_browser_context.h" +#include "content/test/test_render_view_host.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/canvas.h" @@ -48,6 +48,7 @@ using base::TimeDelta; using blink::WebGestureEvent; using blink::WebInputEvent; +using blink::WebKeyboardEvent; using blink::WebMouseWheelEvent; using blink::WebTouchEvent; using blink::WebTouchPoint; @@ -165,6 +166,7 @@ class MockInputRouter : public InputRouter { return NULL; } virtual bool ShouldForwardTouchEvent() const OVERRIDE { return true; } + virtual void OnViewUpdated(int view_flags) OVERRIDE {} // IPC::Listener virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { @@ -197,8 +199,7 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl { int routing_id) : RenderWidgetHostImpl(delegate, process, routing_id, false), unresponsive_timer_fired_(false) { - immediate_input_router_ = - static_cast<ImmediateInputRouter*>(input_router_.get()); + input_router_impl_ = static_cast<InputRouterImpl*>(input_router_.get()); } // Allow poking at a few private members. @@ -258,11 +259,12 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl { } void DisableGestureDebounce() { - gesture_event_filter()->debounce_enabled_ = false; + gesture_event_filter()->set_debounce_enabled_for_testing(false); } void set_debounce_interval_time_ms(int delay_ms) { - gesture_event_filter()->debounce_interval_time_ms_ = delay_ms; + gesture_event_filter()-> + set_debounce_interval_time_ms_for_testing(delay_ms); } bool TouchEventQueueEmpty() const { @@ -316,24 +318,24 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl { } const TouchEventQueue* touch_event_queue() const { - return immediate_input_router_->touch_event_queue_.get(); + return input_router_impl_->touch_event_queue_.get(); } const GestureEventFilter* gesture_event_filter() const { - return immediate_input_router_->gesture_event_filter_.get(); + return input_router_impl_->gesture_event_filter_.get(); } GestureEventFilter* gesture_event_filter() { - return immediate_input_router_->gesture_event_filter_.get(); + return input_router_impl_->gesture_event_filter_.get(); } private: bool unresponsive_timer_fired_; - // |immediate_input_router_| and |mock_input_router_| are owned by - // RenderWidgetHostImpl |input_router_|. Below are provided for convenience so + // |input_router_impl_| and |mock_input_router_| are owned by + // RenderWidgetHostImpl. The handles below are provided for convenience so // that we don't have to reinterpret_cast it all the time. - ImmediateInputRouter* immediate_input_router_; + InputRouterImpl* input_router_impl_; MockInputRouter* mock_input_router_; scoped_ptr<TestOverscrollDelegate> overscroll_delegate_; @@ -651,7 +653,10 @@ class RenderWidgetHostTest : public testing::Test { } void SimulateKeyboardEvent(WebInputEvent::Type type) { - host_->ForwardKeyboardEvent(SyntheticWebKeyboardEventBuilder::Build(type)); + WebKeyboardEvent event = SyntheticWebKeyboardEventBuilder::Build(type); + NativeWebKeyboardEvent native_event; + memcpy(&native_event, &event, sizeof(event)); + host_->ForwardKeyboardEvent(native_event); } void SimulateMouseEvent(WebInputEvent::Type type) { diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index a4815046d5..171bacf9b4 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc @@ -14,6 +14,7 @@ #include "base/message_loop/message_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/worker_pool.h" +#include "cc/base/latency_info_swap_promise.h" #include "cc/layers/delegated_frame_provider.h" #include "cc/layers/delegated_renderer_layer.h" #include "cc/layers/layer.h" @@ -28,6 +29,7 @@ #include "content/browser/android/content_view_core_impl.h" #include "content/browser/android/in_process/synchronous_compositor_impl.h" #include "content/browser/android/overscroll_glow.h" +#include "content/browser/devtools/render_view_devtools_agent_host.h" #include "content/browser/gpu/gpu_data_manager_impl.h" #include "content/browser/gpu/gpu_process_host_ui_shim.h" #include "content/browser/gpu/gpu_surface_tracker.h" @@ -40,11 +42,14 @@ #include "content/common/gpu/gpu_messages.h" #include "content/common/input_messages.h" #include "content/common/view_messages.h" +#include "content/public/browser/devtools_agent_host.h" +#include "content/public/browser/render_view_host.h" #include "content/public/common/content_switches.h" #include "gpu/config/gpu_driver_bug_workaround_type.h" #include "skia/ext/image_operations.h" #include "third_party/khronos/GLES2/gl2.h" #include "third_party/khronos/GLES2/gl2ext.h" +#include "third_party/skia/include/core/SkCanvas.h" #include "ui/base/android/window_android.h" #include "ui/gfx/android/device_display_info.h" #include "ui/gfx/android/java_bitmap.h" @@ -111,7 +116,10 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid( texture_id_in_layer_(0), last_output_surface_id_(kUndefinedOutputSurfaceId), weak_ptr_factory_(this), - overscroll_effect_enabled_(true), + overscroll_effect_enabled_( + !CommandLine::ForCurrentProcess()-> + HasSwitch(switches::kDisableOverscrollEdgeEffect)), + overscroll_effect_(OverscrollGlow::Create(overscroll_effect_enabled_)), flush_input_requested_(false), accelerated_surface_route_id_(0), using_synchronous_compositor_(SynchronousCompositorImpl::FromID( @@ -122,16 +130,6 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid( layer_ = texture_layer_; } - overscroll_effect_enabled_ = !CommandLine::ForCurrentProcess()-> - HasSwitch(switches::kDisableOverscrollEdgeEffect); - // Don't block the main thread with effect resource loading. - // Actual effect creation is deferred until an overscroll event is received. - if (overscroll_effect_enabled_) { - base::WorkerPool::PostTask(FROM_HERE, - base::Bind(&OverscrollGlow::EnsureResources), - true); - } - host_->SetView(this); SetContentViewCore(content_view_core); ImageTransportFactoryAndroid::AddObserver(this); @@ -332,16 +330,15 @@ void RenderWidgetHostViewAndroid::Focus() { host_->Focus(); host_->SetInputMethodActive(true); ResetClipping(); - if (overscroll_effect_) - overscroll_effect_->SetEnabled(true); + if (overscroll_effect_enabled_) + overscroll_effect_->Enable(); } void RenderWidgetHostViewAndroid::Blur() { host_->ExecuteEditCommand("Unselect", ""); host_->SetInputMethodActive(false); host_->Blur(); - if (overscroll_effect_) - overscroll_effect_->SetEnabled(false); + overscroll_effect_->Disable(); } bool RenderWidgetHostViewAndroid::HasFocus() const { @@ -523,11 +520,11 @@ void RenderWidgetHostViewAndroid::Destroy() { } void RenderWidgetHostViewAndroid::SetTooltipText( - const string16& tooltip_text) { + const base::string16& tooltip_text) { // Tooltips don't makes sense on Android. } -void RenderWidgetHostViewAndroid::SelectionChanged(const string16& text, +void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text, size_t offset, const gfx::Range& range) { RenderWidgetHostViewBase::SelectionChanged(text, offset, range); @@ -573,7 +570,7 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface( const gfx::Rect& src_subrect, const gfx::Size& dst_size, const base::Callback<void(bool, const SkBitmap&)>& callback) { - if (!IsSurfaceAvailableForCopy()) { + if (!using_synchronous_compositor_ && !IsSurfaceAvailableForCopy()) { callback.Run(false, SkBitmap()); return; } @@ -589,6 +586,11 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface( gfx::Rect src_subrect_in_pixel = ConvertRectToPixel(device_scale_factor, src_subrect); + if (using_synchronous_compositor_) { + SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback); + return; + } + scoped_ptr<cc::CopyOutputRequest> request; if (src_subrect_in_pixel.size() == dst_size_in_pixel) { request = cc::CopyOutputRequest::CreateBitmapRequest(base::Bind( @@ -692,7 +694,7 @@ void RenderWidgetHostViewAndroid::SwapDelegatedFrame( frame_provider_ = new cc::DelegatedFrameProvider( resource_collection_.get(), frame_data.Pass()); delegated_renderer_layer_ = - cc::DelegatedRendererLayer::Create(NULL, frame_provider_); + cc::DelegatedRendererLayer::Create(frame_provider_); layer_ = delegated_renderer_layer_; if (are_layers_attached_) AttachLayers(); @@ -779,8 +781,11 @@ void RenderWidgetHostViewAndroid::OnSwapCompositorFrame( texture_size_in_layer_ = frame->gl_frame_data->size; ComputeContentsSize(frame->metadata); - if (layer_->layer_tree_host()) - layer_->layer_tree_host()->SetLatencyInfo(frame->metadata.latency_info); + if (layer_->layer_tree_host()) { + scoped_ptr<cc::SwapPromise> swap_promise( + new cc::LatencyInfoSwapPromise(frame->metadata.latency_info)); + layer_->layer_tree_host()->QueueSwapPromise(swap_promise.Pass()); + } BuffersSwapped(frame->gl_frame_data->mailbox, output_surface_id, callback); } @@ -791,6 +796,44 @@ void RenderWidgetHostViewAndroid::SynchronousFrameMetadata( // compositor flow. UpdateContentViewCoreFrameMetadata(frame_metadata); ComputeContentsSize(frame_metadata); + + // DevTools ScreenCast support for Android WebView. + if (DevToolsAgentHost::HasFor(RenderViewHost::From(GetRenderWidgetHost()))) { + scoped_refptr<DevToolsAgentHost> dtah = + DevToolsAgentHost::GetOrCreateFor( + RenderViewHost::From(GetRenderWidgetHost())); + // Unblock the compositor. + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&RenderViewDevToolsAgentHost::SynchronousSwapCompositorFrame, + static_cast<RenderViewDevToolsAgentHost*>(dtah.get()), + frame_metadata)); + } +} + +void RenderWidgetHostViewAndroid::SynchronousCopyContents( + const gfx::Rect& src_subrect_in_pixel, + const gfx::Size& dst_size_in_pixel, + const base::Callback<void(bool, const SkBitmap&)>& callback) { + SynchronousCompositor* compositor = + SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(), + host_->GetRoutingID()); + if (!compositor) { + callback.Run(false, SkBitmap()); + return; + } + + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, + dst_size_in_pixel.width(), + dst_size_in_pixel.height()); + bitmap.allocPixels(); + SkCanvas canvas(bitmap); + canvas.scale( + (float)dst_size_in_pixel.width() / (float)src_subrect_in_pixel.width(), + (float)dst_size_in_pixel.height() / (float)src_subrect_in_pixel.height()); + compositor->DemandDrawSw(&canvas); + callback.Run(true, bitmap); } void RenderWidgetHostViewAndroid::UpdateContentViewCoreFrameMetadata( @@ -856,6 +899,8 @@ void RenderWidgetHostViewAndroid::AttachLayers() { return; content_view_core_->AttachLayer(layer_); + if (overscroll_effect_enabled_) + overscroll_effect_->Enable(); } void RenderWidgetHostViewAndroid::RemoveLayers() { @@ -864,38 +909,16 @@ void RenderWidgetHostViewAndroid::RemoveLayers() { if (!layer_.get()) return; - if (overscroll_effect_) - content_view_core_->RemoveLayer(overscroll_effect_->root_layer()); - content_view_core_->RemoveLayer(layer_); + overscroll_effect_->Disable(); } bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) { - if (!overscroll_effect_) - return false; - - bool overscroll_running = overscroll_effect_->Animate(frame_time); - if (!overscroll_running) - content_view_core_->RemoveLayer(overscroll_effect_->root_layer()); - - return overscroll_running; -} - -void RenderWidgetHostViewAndroid::CreateOverscrollEffectIfNecessary() { - if (!overscroll_effect_enabled_ || overscroll_effect_) - return; - - overscroll_effect_ = OverscrollGlow::Create(true, content_size_in_layer_); - - // Prevent future creation attempts on failure. - if (!overscroll_effect_) - overscroll_effect_enabled_ = false; + return overscroll_effect_->Animate(frame_time); } void RenderWidgetHostViewAndroid::UpdateAnimationSize( const cc::CompositorFrameMetadata& frame_metadata) { - if (!overscroll_effect_) - return; // Disable edge effects for axes on which scrolling is impossible. gfx::SizeF ceiled_viewport_size = gfx::ToCeiledSize(frame_metadata.viewport_size); @@ -906,19 +929,6 @@ void RenderWidgetHostViewAndroid::UpdateAnimationSize( overscroll_effect_->set_size(content_size_in_layer_); } -void RenderWidgetHostViewAndroid::ScheduleAnimationIfNecessary() { - if (!content_view_core_ || !overscroll_effect_) - return; - - if (overscroll_effect_->NeedsAnimate() && are_layers_attached_) { - if (!overscroll_effect_->root_layer()->parent()) - content_view_core_->AttachLayer(overscroll_effect_->root_layer()); - content_view_core_->SetNeedsAnimate(); - } else { - content_view_core_->RemoveLayer(overscroll_effect_->root_layer()); - } -} - void RenderWidgetHostViewAndroid::AcceleratedSurfacePostSubBuffer( const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, int gpu_host_id) { @@ -1143,8 +1153,8 @@ void RenderWidgetHostViewAndroid::SendMouseWheelEvent( void RenderWidgetHostViewAndroid::SendGestureEvent( const blink::WebGestureEvent& event) { // Sending a gesture that may trigger overscroll should resume the effect. - if (overscroll_effect_) - overscroll_effect_->SetEnabled(true); + if (overscroll_effect_enabled_) + overscroll_effect_->Enable(); if (host_) host_->ForwardGestureEvent(event); @@ -1212,14 +1222,15 @@ SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const { void RenderWidgetHostViewAndroid::OnOverscrolled( gfx::Vector2dF accumulated_overscroll, gfx::Vector2dF current_fling_velocity) { - CreateOverscrollEffectIfNecessary(); - if (!overscroll_effect_) + if (!content_view_core_ || !are_layers_attached_) return; - overscroll_effect_->OnOverscrolled(base::TimeTicks::Now(), - accumulated_overscroll, - current_fling_velocity); - ScheduleAnimationIfNecessary(); + if (overscroll_effect_->OnOverscrolled(content_view_core_->GetLayer(), + base::TimeTicks::Now(), + accumulated_overscroll, + current_fling_velocity)) { + content_view_core_->SetNeedsAnimate(); + } } void RenderWidgetHostViewAndroid::SetContentViewCore( diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h index c01120ffa9..db1bc5523e 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.h +++ b/content/browser/renderer_host/render_widget_host_view_android.h @@ -15,7 +15,6 @@ #include "base/memory/weak_ptr.h" #include "base/process/process.h" #include "cc/layers/delegated_frame_resource_collection.h" -#include "cc/layers/delegated_renderer_layer_client.h" #include "cc/layers/texture_layer_client.h" #include "cc/output/begin_frame_args.h" #include "content/browser/accessibility/browser_accessibility_manager.h" @@ -112,8 +111,8 @@ class RenderWidgetHostViewAndroid virtual void RenderProcessGone(base::TerminationStatus status, int error_code) OVERRIDE; virtual void Destroy() OVERRIDE; - virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE; - virtual void SelectionChanged(const string16& text, + virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE; + virtual void SelectionChanged(const base::string16& text, size_t offset, const gfx::Range& range) OVERRIDE; virtual void SelectionBoundsChanged( @@ -257,9 +256,7 @@ class RenderWidgetHostViewAndroid void AttachLayers(); void RemoveLayers(); - void CreateOverscrollEffectIfNecessary(); void UpdateAnimationSize(const cc::CompositorFrameMetadata& frame_metadata); - void ScheduleAnimationIfNecessary(); // Called after async screenshot task completes. Scales and crops the result // of the copy. @@ -272,6 +269,12 @@ class RenderWidgetHostViewAndroid const base::Callback<void(bool, const SkBitmap&)>& callback, scoped_ptr<cc::CopyOutputResult> result); + // DevTools ScreenCast support for Android WebView. + void SynchronousCopyContents( + const gfx::Rect& src_subrect_in_pixel, + const gfx::Size& dst_size_in_pixel, + const base::Callback<void(bool, const SkBitmap&)>& callback); + // The model object. RenderWidgetHostImpl* host_; @@ -323,8 +326,9 @@ class RenderWidgetHostViewAndroid std::queue<base::Closure> ack_callbacks_; + const bool overscroll_effect_enabled_; // Used to render overscroll overlays. - bool overscroll_effect_enabled_; + // Note: |overscroll_effect_| will never be NULL, even if it's never enabled. scoped_ptr<OverscrollGlow> overscroll_effect_; bool flush_input_requested_; diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 81bea27603..7b1bdf55be 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc @@ -4,6 +4,7 @@ #include "content/browser/renderer_host/render_widget_host_view_aura.h" +#include "base/auto_reset.h" #include "base/basictypes.h" #include "base/bind.h" #include "base/callback_helpers.h" @@ -450,6 +451,7 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host) : host_(RenderWidgetHostImpl::From(host)), window_(new aura::Window(this)), in_shutdown_(false), + in_bounds_changed_(false), is_fullscreen_(false), popup_parent_host_view_(NULL), popup_child_host_view_(NULL), @@ -990,7 +992,8 @@ void RenderWidgetHostViewAura::Destroy() { delete window_; } -void RenderWidgetHostViewAura::SetTooltipText(const string16& tooltip_text) { +void RenderWidgetHostViewAura::SetTooltipText( + const base::string16& tooltip_text) { tooltip_ = tooltip_text; aura::Window* root_window = window_->GetRootWindow(); aura::client::TooltipClient* tooltip_client = @@ -1002,7 +1005,7 @@ void RenderWidgetHostViewAura::SetTooltipText(const string16& tooltip_text) { } } -void RenderWidgetHostViewAura::SelectionChanged(const string16& text, +void RenderWidgetHostViewAura::SelectionChanged(const base::string16& text, size_t offset, const gfx::Range& range) { RenderWidgetHostViewBase::SelectionChanged(text, offset, range); @@ -1082,16 +1085,33 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame( return; } + // Try get a texture to reuse. + scoped_refptr<OwnedMailbox> subscriber_texture; + if (frame_subscriber_) { + if (!idle_frame_subscriber_textures_.empty()) { + subscriber_texture = idle_frame_subscriber_textures_.back(); + idle_frame_subscriber_textures_.pop_back(); + } else if (GLHelper* helper = + ImageTransportFactory::GetInstance()->GetGLHelper()) { + subscriber_texture = new OwnedMailbox(helper); + } + } + scoped_ptr<cc::CopyOutputRequest> request = cc::CopyOutputRequest::CreateRequest(base::Bind( &RenderWidgetHostViewAura:: - CopyFromCompositingSurfaceHasResultForVideo, + CopyFromCompositingSurfaceHasResultForVideo, AsWeakPtr(), // For caching the ReadbackYUVInterface on this class. + subscriber_texture, target, callback)); gfx::Rect src_subrect_in_pixel = ConvertRectToPixel(current_device_scale_factor_, src_subrect); request->set_area(src_subrect_in_pixel); + if (subscriber_texture) { + request->SetTextureMailbox(cc::TextureMailbox( + subscriber_texture->mailbox(), subscriber_texture->sync_point())); + } window_->layer()->RequestCopyOfOutput(request.Pass()); } @@ -1115,10 +1135,10 @@ void RenderWidgetHostViewAura::BeginFrameSubscription( } void RenderWidgetHostViewAura::EndFrameSubscription() { + idle_frame_subscriber_textures_.clear(); frame_subscriber_.reset(); } - void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() { // Delay processing the state change until we either get a software frame if // switching to software mode or receive a buffers swapped notification @@ -1148,7 +1168,10 @@ void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) { if (HasDisplayPropertyChanged(window_)) host_->InvalidateScreenInfo(); - window_->SetBounds(rect); + // Don't recursively call SetBounds if this bounds update is the result of + // a Window::SetBoundsInternal call. + if (!in_bounds_changed_) + window_->SetBounds(rect); host_->WasResized(); MaybeCreateResizeLock(); if (touch_editing_client_) { @@ -1405,7 +1428,13 @@ void RenderWidgetHostViewAura::SwapDelegatedFrame( resource_collection_ = new cc::DelegatedFrameResourceCollection; resource_collection_->SetClient(this); } - if (!frame_provider_.get() || frame_size != frame_provider_->frame_size()) { + // If the physical frame size changes, we need a new |frame_provider_|. If + // the physical frame size is the same, but the size in DIP changed, we + // need to adjust the scale at which the frames will be drawn, and we do + // this by making a new |frame_provider_| also to ensure the scale change + // is presented in sync with the new frame content. + if (!frame_provider_.get() || frame_size != frame_provider_->frame_size() || + frame_size_in_dip != current_frame_size_) { frame_provider_ = new cc::DelegatedFrameProvider( resource_collection_.get(), frame_data.Pass()); window_->layer()->SetShowDelegatedContent(frame_provider_.get(), @@ -1872,17 +1901,34 @@ void RenderWidgetHostViewAura::PrepareBitmapCopyOutputResult( callback.Run(true, bitmap); } -static void CopyFromCompositingSurfaceFinishedForVideo( +void RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinishedForVideo( + base::WeakPtr<RenderWidgetHostViewAura> rwhva, const base::Callback<void(bool)>& callback, + scoped_refptr<OwnedMailbox> subscriber_texture, scoped_ptr<cc::SingleReleaseCallback> release_callback, bool result) { - release_callback->Run(0, false); callback.Run(result); + + GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper(); + uint32 sync_point = gl_helper ? gl_helper->InsertSyncPoint() : 0; + if (release_callback) { + DCHECK(!subscriber_texture); + release_callback->Run(sync_point, false); + } else { + // If there's no release callback, then the texture is from + // idle_frame_subscriber_textures_ and we can put it back there. + DCHECK(subscriber_texture); + subscriber_texture->UpdateSyncPoint(sync_point); + if (rwhva && rwhva->frame_subscriber_ && subscriber_texture->texture_id()) + rwhva->idle_frame_subscriber_textures_.push_back(subscriber_texture); + subscriber_texture = NULL; + } } // static void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo( base::WeakPtr<RenderWidgetHostViewAura> rwhva, + scoped_refptr<OwnedMailbox> subscriber_texture, scoped_refptr<media::VideoFrame> video_frame, const base::Callback<void(bool)>& callback, scoped_ptr<cc::CopyOutputResult> result) { @@ -1890,7 +1936,6 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo( if (!rwhva) return; - if (result->IsEmpty()) return; if (result->size().IsEmpty()) @@ -1993,8 +2038,10 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo( ignore_result(scoped_callback_runner.Release()); base::Callback<void(bool result)> finished_callback = base::Bind( - &CopyFromCompositingSurfaceFinishedForVideo, + &RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinishedForVideo, + rwhva->AsWeakPtr(), callback, + subscriber_texture, base::Passed(&release_callback)); yuv_readback_pipeline->ReadbackYUV( texture_mailbox.name(), @@ -2180,8 +2227,10 @@ void RenderWidgetHostViewAura::SetCompositionText( } void RenderWidgetHostViewAura::ConfirmCompositionText() { - if (host_ && has_composition_text_) - host_->ImeConfirmComposition(string16(), gfx::Range::InvalidRange(), false); + if (host_ && has_composition_text_) { + host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(), + false); + } has_composition_text_ = false; } @@ -2191,7 +2240,7 @@ void RenderWidgetHostViewAura::ClearCompositionText() { has_composition_text_ = false; } -void RenderWidgetHostViewAura::InsertText(const string16& text) { +void RenderWidgetHostViewAura::InsertText(const base::string16& text) { DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE); if (host_) host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false); @@ -2326,7 +2375,7 @@ bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) { bool RenderWidgetHostViewAura::GetTextFromRange( const gfx::Range& range, - string16* text) const { + base::string16* text) const { gfx::Range selection_text_range(selection_text_offset_, selection_text_offset_ + selection_text_.length()); @@ -2386,12 +2435,15 @@ void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) { } void RenderWidgetHostViewAura::OnCandidateWindowShown() { + host_->CandidateWindowShown(); } void RenderWidgetHostViewAura::OnCandidateWindowUpdated() { + host_->CandidateWindowUpdated(); } void RenderWidgetHostViewAura::OnCandidateWindowHidden() { + host_->CandidateWindowHidden(); } //////////////////////////////////////////////////////////////////////////////// @@ -2428,6 +2480,7 @@ gfx::Size RenderWidgetHostViewAura::GetMaximumSize() const { void RenderWidgetHostViewAura::OnBoundsChanged(const gfx::Rect& old_bounds, const gfx::Rect& new_bounds) { + base::AutoReset<bool> in_bounds_changed(&in_bounds_changed_, true); // We care about this only in fullscreen mode, where there is no // WebContentsViewAura. We are sized via SetSize() or SetBounds() by // WebContentsViewAura in other cases. @@ -2976,6 +3029,17 @@ void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus, (screen->GetDisplayNearestWindow(window_).id() != screen->GetDisplayNearestWindow(gained_focus).id()); if (is_fullscreen_ && !in_shutdown_ && !focusing_other_display) { +#if defined(OS_WIN) + // On Windows, if we are switching to a non Aura Window on a different + // screen we should not close the fullscreen window. + if (!gained_focus) { + POINT point = {0}; + ::GetCursorPos(&point); + if (screen->GetDisplayNearestWindow(window_).id() != + screen->GetDisplayNearestPoint(gfx::Point(point)).id()) + return; + } +#endif in_shutdown_ = true; host_->Shutdown(); } @@ -3132,6 +3196,8 @@ void RenderWidgetHostViewAura::OnLostResources() { current_surface_ = NULL; UpdateExternalTexture(); + idle_frame_subscriber_textures_.clear(); + // Make sure all ImageTransportClients are deleted now that the context those // are using is becoming invalid. This sends pending ACKs and needs to happen // after calling UpdateExternalTexture() which syncs with the impl thread. @@ -3238,8 +3304,10 @@ bool RenderWidgetHostViewAura::NeedsInputGrab() { void RenderWidgetHostViewAura::FinishImeCompositionSession() { if (!has_composition_text_) return; - if (host_) - host_->ImeConfirmComposition(string16(), gfx::Range::InvalidRange(), false); + if (host_) { + host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(), + false); + } ImeCancelComposition(); } @@ -3348,6 +3416,11 @@ void RenderWidgetHostViewAura::AddedToRootWindow() { } if (current_surface_.get()) UpdateExternalTexture(); + if (HasFocus()) { + ui::InputMethod* input_method = GetInputMethod(); + if (input_method) + input_method->SetFocusedTextInputClient(this); + } } void RenderWidgetHostViewAura::RemovingFromRootWindow() { diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index 385495a9c4..86db86410d 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h @@ -20,6 +20,7 @@ #include "cc/resources/texture_mailbox.h" #include "content/browser/accessibility/browser_accessibility_manager.h" #include "content/browser/aura/image_transport_factory.h" +#include "content/browser/aura/owned_mailbox.h" #include "content/browser/renderer_host/delegated_frame_evictor.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/renderer_host/software_frame_manager.h" @@ -192,8 +193,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura virtual void RenderProcessGone(base::TerminationStatus status, int error_code) OVERRIDE; virtual void Destroy() OVERRIDE; - virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE; - virtual void SelectionChanged(const string16& text, + virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE; + virtual void SelectionChanged(const base::string16& text, size_t offset, const gfx::Range& range) OVERRIDE; virtual void SelectionBoundsChanged( @@ -258,7 +259,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura const ui::CompositionText& composition) OVERRIDE; virtual void ConfirmCompositionText() OVERRIDE; virtual void ClearCompositionText() OVERRIDE; - virtual void InsertText(const string16& text) OVERRIDE; + virtual void InsertText(const base::string16& text) OVERRIDE; virtual void InsertChar(char16 ch, int flags) OVERRIDE; virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE; virtual ui::TextInputType GetTextInputType() const OVERRIDE; @@ -274,7 +275,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE; virtual bool DeleteRange(const gfx::Range& range) OVERRIDE; virtual bool GetTextFromRange(const gfx::Range& range, - string16* text) const OVERRIDE; + base::string16* text) const OVERRIDE; virtual void OnInputMethodChanged() OVERRIDE; virtual bool ChangeTextDirectionAndLayoutAlignment( base::i18n::TextDirection direction) OVERRIDE; @@ -395,6 +396,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange); FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, DiscardDelegatedFrames); + FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SoftwareDPIChange); class WindowObserver; friend class WindowObserver; @@ -487,9 +489,16 @@ class CONTENT_EXPORT RenderWidgetHostViewAura scoped_ptr<cc::CopyOutputResult> result); static void CopyFromCompositingSurfaceHasResultForVideo( base::WeakPtr<RenderWidgetHostViewAura> rwhva, + scoped_refptr<OwnedMailbox> subscriber_texture, scoped_refptr<media::VideoFrame> video_frame, const base::Callback<void(bool)>& callback, scoped_ptr<cc::CopyOutputResult> result); + static void CopyFromCompositingSurfaceFinishedForVideo( + base::WeakPtr<RenderWidgetHostViewAura> rwhva, + const base::Callback<void(bool)>& callback, + scoped_refptr<OwnedMailbox> subscriber_texture, + scoped_ptr<cc::SingleReleaseCallback> release_callback, + bool result); ui::Compositor* GetCompositor() const; @@ -575,6 +584,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAura // after requesting shutdown for another reason (e.g. Escape key). bool in_shutdown_; + // True if in the process of handling a window bounds changed notification. + bool in_bounds_changed_; + // Is this a fullscreen view? bool is_fullscreen_; @@ -619,7 +631,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura bool accept_return_character_; // Current tooltip text. - string16 tooltip_; + base::string16 tooltip_; std::vector<base::Closure> on_compositing_did_commit_callbacks_; @@ -747,6 +759,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura // Subscriber that listens to frame presentation events. scoped_ptr<RenderWidgetHostViewFrameSubscriber> frame_subscriber_; + std::vector<scoped_refptr<OwnedMailbox> > idle_frame_subscriber_textures_; // YUV readback pipeline. scoped_ptr<content::ReadbackYUVInterface> diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index ee93871692..120956067d 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc @@ -973,8 +973,8 @@ TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) { // Swap another frame, with a different surface id. EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect)); - view_->OnSwapCompositorFrame( - 3, MakeDelegatedFrame(1.f, frame_size, view_rect)); + view_->OnSwapCompositorFrame(3, + MakeDelegatedFrame(1.f, frame_size, view_rect)); testing::Mock::VerifyAndClearExpectations(&observer); view_->RunOnCompositingDidCommit(); @@ -1080,4 +1080,35 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFrames) { } } +TEST_F(RenderWidgetHostViewAuraTest, SoftwareDPIChange) { + gfx::Rect view_rect(100, 100); + gfx::Size frame_size(100, 100); + + view_->InitAsChild(NULL); + aura::client::ParentWindowWithContext( + view_->GetNativeView(), + parent_view_->GetNativeView()->GetRootWindow(), + gfx::Rect()); + view_->SetSize(view_rect.size()); + view_->WasShown(); + + // With a 1x DPI UI and 1x DPI Renderer. + view_->OnSwapCompositorFrame( + 1, MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size))); + + // Save the frame provider. + scoped_refptr<cc::DelegatedFrameProvider> frame_provider = + view_->frame_provider_; + + // This frame will have the same number of physical pixels, but has a new + // scale on it. + view_->OnSwapCompositorFrame( + 1, MakeDelegatedFrame(2.f, frame_size, gfx::Rect(frame_size))); + + // When we get a new frame with the same frame size in physical pixels, but a + // different scale, we should generate a new frame provider, as the final + // result will need to be scaled differently to the screen. + EXPECT_NE(frame_provider.get(), view_->frame_provider_.get()); +} + } // namespace content diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc index b96182c7d9..8347b6d57f 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.cc +++ b/content/browser/renderer_host/render_widget_host_view_base.cc @@ -118,7 +118,7 @@ LRESULT CALLBACK PluginWrapperWindowProc(HWND window, unsigned int message, bool IsPluginWrapperWindow(HWND window) { return gfx::GetClassNameW(window) == - string16(kWrapperNativeWindowClassName); + base::string16(kWrapperNativeWindowClassName); } // Create an intermediate window between the given HWND and its parent. @@ -421,7 +421,7 @@ float RenderWidgetHostViewBase::GetOverdrawBottomHeight() const { return 0.f; } -void RenderWidgetHostViewBase::SelectionChanged(const string16& text, +void RenderWidgetHostViewBase::SelectionChanged(const base::string16& text, size_t offset, const gfx::Range& range) { selection_text_ = text; @@ -439,9 +439,9 @@ void RenderWidgetHostViewBase::SetShowingContextMenu(bool showing) { showing_context_menu_ = showing; } -string16 RenderWidgetHostViewBase::GetSelectedText() const { +base::string16 RenderWidgetHostViewBase::GetSelectedText() const { if (!selection_range_.IsValid()) - return string16(); + return base::string16(); return selection_text_.substr( selection_range_.GetMin() - selection_text_offset_, selection_range_.length()); diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h index 0a6fd1ac22..eadf92b87d 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.h +++ b/content/browser/renderer_host/render_widget_host_view_base.h @@ -47,7 +47,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase // RenderWidgetHostViewPort implementation. virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; - virtual void SelectionChanged(const string16& text, + virtual void SelectionChanged(const base::string16& text, size_t offset, const gfx::Range& range) OVERRIDE; virtual void SetBackground(const SkBitmap& background) OVERRIDE; @@ -56,7 +56,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase virtual float GetOverdrawBottomHeight() const OVERRIDE; virtual bool IsShowingContextMenu() const OVERRIDE; virtual void SetShowingContextMenu(bool showing_menu) OVERRIDE; - virtual string16 GetSelectedText() const OVERRIDE; + virtual base::string16 GetSelectedText() const OVERRIDE; virtual bool IsMouseLocked() OVERRIDE; virtual void UnhandledWheelEvent( const blink::WebMouseWheelEvent& event) OVERRIDE; @@ -140,7 +140,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase bool showing_context_menu_; // A buffer containing the text inside and around the current selection range. - string16 selection_text_; + base::string16 selection_text_; // The offset of the text stored in |selection_text_| relative to the start of // the web page. diff --git a/content/browser/renderer_host/render_widget_host_view_gtk.cc b/content/browser/renderer_host/render_widget_host_view_gtk.cc index 494ba38f86..e50bd04565 100644 --- a/content/browser/renderer_host/render_widget_host_view_gtk.cc +++ b/content/browser/renderer_host/render_widget_host_view_gtk.cc @@ -929,14 +929,15 @@ void RenderWidgetHostViewGtk::Destroy() { base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); } -void RenderWidgetHostViewGtk::SetTooltipText(const string16& tooltip_text) { +void RenderWidgetHostViewGtk::SetTooltipText( + const base::string16& tooltip_text) { // Maximum number of characters we allow in a tooltip. const int kMaxTooltipLength = 8 << 10; // Clamp the tooltip length to kMaxTooltipLength so that we don't // accidentally DOS the user with a mega tooltip (since GTK doesn't do // this itself). // I filed https://bugzilla.gnome.org/show_bug.cgi?id=604641 upstream. - const string16 clamped_tooltip = + const base::string16 clamped_tooltip = gfx::TruncateString(tooltip_text, kMaxTooltipLength); if (clamped_tooltip.empty()) { @@ -947,7 +948,7 @@ void RenderWidgetHostViewGtk::SetTooltipText(const string16& tooltip_text) { } } -void RenderWidgetHostViewGtk::SelectionChanged(const string16& text, +void RenderWidgetHostViewGtk::SelectionChanged(const base::string16& text, size_t offset, const gfx::Range& range) { RenderWidgetHostViewBase::SelectionChanged(text, offset, range); @@ -1347,13 +1348,20 @@ bool RenderWidgetHostViewGtk::LockMouse() { } // Clear the tooltip window. - SetTooltipText(string16()); + SetTooltipText(base::string16()); // Ensure that the widget center location will be relevant for this mouse // lock session. It is updated whenever the window geometry moves // but may be out of date due to switching tabs. MarkCachedWidgetCenterStale(); + // Ensure that if we were previously warping the cursor to a specific point + // that we no longer track doing so when entering lock. It should be cleared + // by the cursor moving to the warp point, and this shouldn't be necessary. + // But, this is a small effort to ensure robustness in the event a warp isn't + // completed. + mouse_is_being_warped_to_unlocked_position_ = false; + return true; } @@ -1411,7 +1419,7 @@ bool RenderWidgetHostViewGtk::RetrieveSurrounding(std::string* text, *text = base::UTF16ToUTF8AndAdjustOffset( base::StringPiece16(selection_text_), &offset); - if (offset == string16::npos) { + if (offset == base::string16::npos) { NOTREACHED() << "Invalid offset in UTF16 string."; return false; } @@ -1484,7 +1492,7 @@ void RenderWidgetHostViewGtk::ModifyEventMovementAndCoords( event->windowY = unlocked_mouse_position_.y(); event->globalX = unlocked_global_mouse_position_.x(); event->globalY = unlocked_global_mouse_position_.y(); - } else { + } else if (!mouse_is_being_warped_to_unlocked_position_) { unlocked_mouse_position_.SetPoint(event->windowX, event->windowY); unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY); } diff --git a/content/browser/renderer_host/render_widget_host_view_gtk.h b/content/browser/renderer_host/render_widget_host_view_gtk.h index 9bb2755e39..e01181ab4c 100644 --- a/content/browser/renderer_host/render_widget_host_view_gtk.h +++ b/content/browser/renderer_host/render_widget_host_view_gtk.h @@ -93,8 +93,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGtk int error_code) OVERRIDE; virtual void Destroy() OVERRIDE; virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) {} - virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE; - virtual void SelectionChanged(const string16& text, + virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE; + virtual void SelectionChanged(const base::string16& text, size_t offset, const gfx::Range& range) OVERRIDE; virtual void SelectionBoundsChanged( diff --git a/content/browser/renderer_host/render_widget_host_view_guest.cc b/content/browser/renderer_host/render_widget_host_view_guest.cc index 629938495b..907119de3c 100644 --- a/content/browser/renderer_host/render_widget_host_view_guest.cc +++ b/content/browser/renderer_host/render_widget_host_view_guest.cc @@ -169,7 +169,8 @@ void RenderWidgetHostViewGuest::Destroy() { platform_view_->Destroy(); } -void RenderWidgetHostViewGuest::SetTooltipText(const string16& tooltip_text) { +void RenderWidgetHostViewGuest::SetTooltipText( + const base::string16& tooltip_text) { platform_view_->SetTooltipText(tooltip_text); } @@ -324,7 +325,7 @@ void RenderWidgetHostViewGuest::DidUpdateBackingStore( NOTREACHED(); } -void RenderWidgetHostViewGuest::SelectionChanged(const string16& text, +void RenderWidgetHostViewGuest::SelectionChanged(const base::string16& text, size_t offset, const gfx::Range& range) { platform_view_->SelectionChanged(text, offset, range); @@ -346,9 +347,10 @@ BackingStore* RenderWidgetHostViewGuest::AllocBackingStore( void RenderWidgetHostViewGuest::CopyFromCompositingSurface( const gfx::Rect& src_subrect, - const gfx::Size& /* dst_size */, + const gfx::Size& dst_size, const base::Callback<void(bool, const SkBitmap&)>& callback) { - callback.Run(false, SkBitmap()); + CHECK(guest_); + guest_->CopyFromCompositingSurface(src_subrect, dst_size, callback); } void RenderWidgetHostViewGuest::CopyFromCompositingSurfaceToVideoFrame( diff --git a/content/browser/renderer_host/render_widget_host_view_guest.h b/content/browser/renderer_host/render_widget_host_view_guest.h index e406b50fa5..ac9fa0ee2c 100644 --- a/content/browser/renderer_host/render_widget_host_view_guest.h +++ b/content/browser/renderer_host/render_widget_host_view_guest.h @@ -98,8 +98,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest int error_code) OVERRIDE; virtual void Destroy() OVERRIDE; virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) {} - virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE; - virtual void SelectionChanged(const string16& text, + virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE; + virtual void SelectionChanged(const base::string16& text, size_t offset, const gfx::Range& range) OVERRIDE; virtual void SelectionBoundsChanged( diff --git a/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc b/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc index a112634b69..b99743aa5f 100644 --- a/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_guest_unittest.cc @@ -8,11 +8,11 @@ #include "base/message_loop/message_loop.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" #include "content/browser/renderer_host/render_widget_host_impl.h" -#include "content/browser/renderer_host/test_render_view_host.h" #include "content/common/view_messages.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/test/mock_render_process_host.h" #include "content/public/test/test_browser_context.h" +#include "content/test/test_render_view_host.h" #include "testing/gtest/include/gtest/gtest.h" namespace content { diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 4a667b0ab2..00c4282eca 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h @@ -108,10 +108,10 @@ class RenderWidgetHostViewMacEditCommandHelper; NSRange selectedRange_; // Text to be inserted which was generated by handling a key down event. - string16 textToBeInserted_; + base::string16 textToBeInserted_; // Marked text which was generated by handling a key down event. - string16 markedText_; + base::string16 markedText_; // Underline information of the |markedText_|. std::vector<blink::WebCompositionUnderline> underlines_; @@ -264,8 +264,8 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase, virtual void RenderProcessGone(base::TerminationStatus status, int error_code) OVERRIDE; virtual void Destroy() OVERRIDE; - virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE; - virtual void SelectionChanged(const string16& text, + virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE; + virtual void SelectionChanged(const base::string16& text, size_t offset, const gfx::Range& range) OVERRIDE; virtual void SelectionBoundsChanged( @@ -338,7 +338,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase, void EnableCoreAnimation(); // Sends completed plugin IME notification and text back to the renderer. - void PluginImeCompositionCompleted(const string16& text, int plugin_id); + void PluginImeCompositionCompleted(const base::string16& text, int plugin_id); const std::string& selected_text() const { return selected_text_; } @@ -355,6 +355,15 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase, // Called when a GPU error is detected. Deletes all compositing state. void GotAcceleratedCompositingError(); + // Sets the overlay view, which should be drawn in the same IOSurface + // atop of this view, if both views are drawing accelerated content. + // Overlay is stored as a weak ptr. + void SetOverlayView(RenderWidgetHostViewMac* overlay, + const gfx::Point& offset); + + // Removes the previously set overlay view. + void RemoveOverlayView(); + // Returns true and stores first rectangle for character range if the // requested |range| is already cached, otherwise returns false. // Exposed for testing. @@ -526,7 +535,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase, bool is_loading_; // The text to be shown in the tooltip, supplied by the renderer. - string16 tooltip_text_; + base::string16 tooltip_text_; // Factory used to safely scope delayed calls to ShutdownHost(). base::WeakPtrFactory<RenderWidgetHostViewMac> weak_factory_; @@ -551,6 +560,27 @@ class RenderWidgetHostViewMac : public RenderWidgetHostViewBase, base::WeakPtrFactory<RenderWidgetHostViewMac> pending_swap_buffers_acks_weak_factory_; + // The overlay view which is rendered above this one in the same + // accelerated IOSurface. + // Overlay view has |underlay_view_| set to this view. + base::WeakPtr<RenderWidgetHostViewMac> overlay_view_; + + // Offset at which overlay view should be rendered. + gfx::Point overlay_view_offset_; + + // The underlay view which this view is rendered above in the same + // accelerated IOSurface. + // Underlay view has |overlay_view_| set to this view. + base::WeakPtr<RenderWidgetHostViewMac> underlay_view_; + + // Set to true when |underlay_view_| has drawn this view. After that point, + // this view should not draw again until |underlay_view_| is changed. + bool underlay_view_has_drawn_; + + // Factory used to safely reference overlay view set in SetOverlayView. + base::WeakPtrFactory<RenderWidgetHostViewMac> + overlay_view_weak_factory_; + // The earliest time at which the next swap ack may be sent. Only relevant // when swaps are not being throttled by the renderer (when threaded // compositing is off). diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index acfd3b6aee..9b5de7fdcf 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm @@ -418,6 +418,8 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget) weak_factory_(this), fullscreen_parent_host_view_(NULL), pending_swap_buffers_acks_weak_factory_(this), + underlay_view_has_drawn_(false), + overlay_view_weak_factory_(this), next_swap_ack_time_(base::Time::Now()), software_frame_weak_ptr_factory_(this) { software_frame_manager_.reset(new SoftwareFrameManager( @@ -1019,7 +1021,8 @@ void RenderWidgetHostViewMac::Destroy() { // Called from the renderer to tell us what the tooltip text should be. It // calls us frequently so we need to cache the value to prevent doing a lot // of repeat work. -void RenderWidgetHostViewMac::SetTooltipText(const string16& tooltip_text) { +void RenderWidgetHostViewMac::SetTooltipText( + const base::string16& tooltip_text) { if (tooltip_text != tooltip_text_ && [[cocoa_view_ window] isKeyWindow]) { tooltip_text_ = tooltip_text; @@ -1027,7 +1030,7 @@ void RenderWidgetHostViewMac::SetTooltipText(const string16& tooltip_text) { // Windows; we're just trying to be polite. Don't persist the trimmed // string, as then the comparison above will always fail and we'll try to // set it again every single time the mouse moves. - string16 display_text = tooltip_text_; + base::string16 display_text = tooltip_text_; if (tooltip_text_.length() > kMaxTooltipLength) display_text = tooltip_text_.substr(0, kMaxTooltipLength); @@ -1060,7 +1063,7 @@ void RenderWidgetHostViewMac::StopSpeaking() { // RenderWidgetHostViewCocoa uses the stored selection text, // which implements NSServicesRequests protocol. // -void RenderWidgetHostViewMac::SelectionChanged(const string16& text, +void RenderWidgetHostViewMac::SelectionChanged(const base::string16& text, size_t offset, const gfx::Range& range) { if (range.is_empty() || text.empty()) { @@ -1245,7 +1248,7 @@ bool RenderWidgetHostViewMac::PostProcessEventForPluginIme( } void RenderWidgetHostViewMac::PluginImeCompositionCompleted( - const string16& text, int plugin_id) { + const base::string16& text, int plugin_id) { if (render_widget_host_) { render_widget_host_->Send(new ViewMsg_PluginImeCompositionCompleted( render_widget_host_->GetRoutingID(), text, plugin_id)); @@ -1418,6 +1421,14 @@ bool RenderWidgetHostViewMac::DrawIOSurfaceWithoutCoreAnimation() { forParameter:NSOpenGLCPSurfaceOrder]; } + // Instead of drawing, request that underlay view redraws. + if (underlay_view_ && + underlay_view_->compositing_iosurface_ && + underlay_view_has_drawn_) { + [underlay_view_->cocoa_view() setNeedsDisplay:YES]; + return true; + } + CGLError cgl_error = CGLSetCurrentContext( compositing_iosurface_context_->cgl_context()); if (cgl_error != kCGLNoError) { @@ -1426,12 +1437,35 @@ bool RenderWidgetHostViewMac::DrawIOSurfaceWithoutCoreAnimation() { } [compositing_iosurface_context_->nsgl_context() setView:cocoa_view_]; - return compositing_iosurface_->DrawIOSurface( + bool has_overlay = overlay_view_ && overlay_view_->compositing_iosurface_; + + gfx::Rect view_rect(NSRectToCGRect([cocoa_view_ frame])); + if (!compositing_iosurface_->DrawIOSurface( compositing_iosurface_context_, - gfx::Rect(NSRectToCGRect([cocoa_view_ frame])), + view_rect, scale_factor(), frame_subscriber(), - true); + !has_overlay)) { + return false; + } + + if (has_overlay) { + overlay_view_->underlay_view_has_drawn_ = true; + gfx::Rect overlay_view_rect( + NSRectToCGRect([overlay_view_->cocoa_view() frame])); + overlay_view_rect.set_x(overlay_view_offset_.x()); + overlay_view_rect.set_y(view_rect.height() - + overlay_view_rect.height() - + overlay_view_offset_.y()); + return overlay_view_->compositing_iosurface_->DrawIOSurface( + compositing_iosurface_context_, + overlay_view_rect, + overlay_view_->scale_factor(), + overlay_view_->frame_subscriber(), + true); + } + + return true; } void RenderWidgetHostViewMac::GotAcceleratedCompositingError() { @@ -1448,6 +1482,29 @@ void RenderWidgetHostViewMac::GotAcceleratedCompositingError() { // repeatedly. } +void RenderWidgetHostViewMac::SetOverlayView( + RenderWidgetHostViewMac* overlay, const gfx::Point& offset) { + if (overlay_view_) + overlay_view_->underlay_view_.reset(); + + overlay_view_ = overlay->overlay_view_weak_factory_.GetWeakPtr(); + overlay_view_offset_ = offset; + overlay_view_->underlay_view_ = overlay_view_weak_factory_.GetWeakPtr(); + overlay_view_->underlay_view_has_drawn_ = false; + + [cocoa_view_ setNeedsDisplay:YES]; + [[cocoa_view_ window] disableScreenUpdatesUntilFlush]; +} + +void RenderWidgetHostViewMac::RemoveOverlayView() { + if (overlay_view_) { + overlay_view_->underlay_view_.reset(); + overlay_view_.reset(); + } + [cocoa_view_ setNeedsDisplay:YES]; + [[cocoa_view_ window] disableScreenUpdatesUntilFlush]; +} + void RenderWidgetHostViewMac::GetVSyncParameters( base::TimeTicks* timebase, base::TimeDelta* interval) { if (compositing_iosurface_) { @@ -1745,7 +1802,7 @@ bool RenderWidgetHostViewMac::LockMouse() { [NSCursor hide]; // Clear the tooltip window. - SetTooltipText(string16()); + SetTooltipText(base::string16()); return true; } @@ -1956,7 +2013,6 @@ void RenderWidgetHostViewMac::FrameSwapped() { // RenderWidgetHostViewCocoa --------------------------------------------------- @implementation RenderWidgetHostViewCocoa - @synthesize selectedRange = selectedRange_; @synthesize suppressNextEscapeKeyUp = suppressNextEscapeKeyUp_; @synthesize markedRange = markedRange_; @@ -1965,6 +2021,7 @@ void RenderWidgetHostViewMac::FrameSwapped() { - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r { self = [super initWithFrame:NSZeroRect]; if (self) { + self.acceptsTouchEvents = YES; editCommand_helper_.reset(new RenderWidgetHostViewMacEditCommandHelper); editCommand_helper_->AddEditingSelectorsToClass([self class]); @@ -2018,8 +2075,8 @@ void RenderWidgetHostViewMac::FrameSwapped() { } - (void)scrollOffsetPinnedToLeft:(BOOL)left toRight:(BOOL)right { - if (delegate_ && [delegate_ respondsToSelector: - @selector(scrollOffsetPinnedToLeft:toRight:)]) { + if (delegate_ && [delegate_ + respondsToSelector:@selector(scrollOffsetPinnedToLeft:toRight:)]) { [delegate_ scrollOffsetPinnedToLeft:left toRight:right]; } } @@ -2098,10 +2155,16 @@ void RenderWidgetHostViewMac::FrameSwapped() { // The cursor is over a nonWebContentView - ignore this mouse event. return YES; } - if ([view isKindOfClass:[self class]] && ![view isEqual:self]) { + if ([view isKindOfClass:[self class]] && ![view isEqual:self] && + !hasOpenMouseDown_) { // The cursor is over an overlapping render widget. This check is done by // both views so the one that's returned by -hitTest: will end up // processing the event. + // Note that while dragging, we only get events for the render view where + // drag started, even if mouse is actually over another view or outside + // the window. Cocoa does this for us. We should handle these events and + // not ignore (since there is no other render view to handle them). Thus + // the |!hasOpenMouseDown_| check above. return YES; } view = [view superview]; @@ -2393,7 +2456,7 @@ void RenderWidgetHostViewMac::FrameSwapped() { } else if (oldHasMarkedText && !hasMarkedText_ && !textInserted) { if (unmarkTextCalled_) { widgetHost->ImeConfirmComposition( - string16(), gfx::Range::InvalidRange(), false); + base::string16(), gfx::Range::InvalidRange(), false); } else { widgetHost->ImeCancelComposition(); } @@ -2479,6 +2542,47 @@ void RenderWidgetHostViewMac::FrameSwapped() { } } +- (void)beginGestureWithEvent:(NSEvent*)event { + [delegate_ beginGestureWithEvent:event]; +} +- (void)endGestureWithEvent:(NSEvent*)event { + [delegate_ endGestureWithEvent:event]; +} +- (void)touchesMovedWithEvent:(NSEvent*)event { + [delegate_ touchesMovedWithEvent:event]; +} +- (void)touchesBeganWithEvent:(NSEvent*)event { + [delegate_ touchesBeganWithEvent:event]; +} +- (void)touchesCancelledWithEvent:(NSEvent*)event { + [delegate_ touchesCancelledWithEvent:event]; +} +- (void)touchesEndedWithEvent:(NSEvent*)event { + [delegate_ touchesEndedWithEvent:event]; +} + +// This method handles 2 different types of hardware events. +// (Apple does not distinguish between them). +// a. Scrolling the middle wheel of a mouse. +// b. Swiping on the track pad. +// +// This method is responsible for 2 types of behavior: +// a. Scrolling the content of window. +// b. Navigating forwards/backwards in history. +// +// This is a brief description of the logic: +// 1. If the content can be scrolled, scroll the content. +// (This requires a roundtrip to blink to determine whether the content +// can be scrolled.) +// Once this logic is triggered, the navigate logic cannot be triggered +// until the gesture finishes. +// 2. If the user is making a horizontal swipe, start the navigate +// forward/backwards UI. +// Once this logic is triggered, the user can either cancel or complete +// the gesture. If the user completes the gesture, all remaining touches +// are swallowed, and not allowed to scroll the content. If the user +// cancels the gesture, all remaining touches are forwarded to the content +// scroll logic. The user cannot trigger the navigation logic again. - (void)scrollWheel:(NSEvent*)event { if (delegate_ && [delegate_ respondsToSelector:@selector(handleEvent:)]) { BOOL handled = [delegate_ handleEvent:event]; @@ -2493,13 +2597,14 @@ void RenderWidgetHostViewMac::FrameSwapped() { if (base::mac::IsOSLionOrLater() && [event phase] == NSEventPhaseBegan && !endWheelMonitor_) { endWheelMonitor_ = - [NSEvent addLocalMonitorForEventsMatchingMask:NSScrollWheelMask - handler:^(NSEvent* blockEvent) { - [self shortCircuitScrollWheelEvent:blockEvent]; - return blockEvent; - }]; + [NSEvent addLocalMonitorForEventsMatchingMask:NSScrollWheelMask + handler:^(NSEvent* blockEvent) { + [self shortCircuitScrollWheelEvent:blockEvent]; + return blockEvent; + }]; } + // This is responsible for content scrolling! if (renderWidgetHostView_->render_widget_host_) { const WebMouseWheelEvent& webEvent = WebInputEventFactory::mouseWheelEvent(event, self); @@ -2931,8 +3036,9 @@ void RenderWidgetHostViewMac::FrameSwapped() { } - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { - if (delegate_ && [delegate_ respondsToSelector: - @selector(validateUserInterfaceItem:isValidItem:)]) { + if (delegate_ && + [delegate_ respondsToSelector:@selector(validateUserInterfaceItem: + isValidItem:)]) { BOOL valid; BOOL known = [delegate_ validateUserInterfaceItem:item isValidItem:&valid]; @@ -3506,7 +3612,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName; // called in keyEvent: method. if (!handlingKeyDown_) { renderWidgetHostView_->render_widget_host_->ImeConfirmComposition( - string16(), gfx::Range::InvalidRange(), false); + base::string16(), gfx::Range::InvalidRange(), false); } else { unmarkTextCalled_ = YES; } @@ -3744,7 +3850,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName; if (renderWidgetHostView_->render_widget_host_) renderWidgetHostView_->render_widget_host_->ImeConfirmComposition( - string16(), gfx::Range::InvalidRange(), false); + base::string16(), gfx::Range::InvalidRange(), false); [self cancelComposition]; } @@ -3757,7 +3863,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName; if (!active) { [[ComplexTextInputPanel sharedComplexTextInputPanel] cancelComposition]; renderWidgetHostView_->PluginImeCompositionCompleted( - string16(), focusedPluginIdentifier_); + base::string16(), focusedPluginIdentifier_); } } @@ -3792,7 +3898,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName; if (pluginImeActive_ && ![[ComplexTextInputPanel sharedComplexTextInputPanel] inComposition]) { renderWidgetHostView_->PluginImeCompositionCompleted( - string16(), focusedPluginIdentifier_); + base::string16(), focusedPluginIdentifier_); pluginImeActive_ = NO; } } diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm index ad37bfdd35..2515496216 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm @@ -9,7 +9,6 @@ #include "base/strings/utf_string_conversions.h" #include "content/browser/browser_thread_impl.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" -#include "content/browser/renderer_host/test_render_view_host.h" #include "content/common/gpu/gpu_messages.h" #include "content/common/input_messages.h" #include "content/common/view_messages.h" @@ -18,6 +17,7 @@ #include "content/public/test/mock_render_process_host.h" #include "content/public/test/test_browser_context.h" #include "content/public/test/test_utils.h" +#include "content/test/test_render_view_host.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/test/cocoa_test_event_utils.h" @@ -83,6 +83,12 @@ typedef NSUInteger NSEventPhase; - (void)gotUnhandledWheelEvent { unhandledWheelEventReceived_ = true; } +- (void)touchesBeganWithEvent:(NSEvent*)event{} +- (void)touchesMovedWithEvent:(NSEvent*)event{} +- (void)touchesCancelledWithEvent:(NSEvent*)event{} +- (void)touchesEndedWithEvent:(NSEvent*)event{} +- (void)beginGestureWithEvent:(NSEvent*)event{} +- (void)endGestureWithEvent:(NSEvent*)event{} @end @@ -318,7 +324,7 @@ TEST_F(RenderWidgetHostViewMacTest, AcceleratorDestroy) { } TEST_F(RenderWidgetHostViewMacTest, GetFirstRectForCharacterRangeCaretCase) { - const string16 kDummyString = UTF8ToUTF16("hogehoge"); + const base::string16 kDummyString = UTF8ToUTF16("hogehoge"); const size_t kDummyOffset = 0; gfx::Rect caret_rect(10, 11, 0, 10); diff --git a/content/browser/renderer_host/render_widget_host_view_win.cc b/content/browser/renderer_host/render_widget_host_view_win.cc index c07a989409..8238a82b4c 100644 --- a/content/browser/renderer_host/render_widget_host_view_win.cc +++ b/content/browser/renderer_host/render_widget_host_view_win.cc @@ -836,14 +836,15 @@ void RenderWidgetHostViewWin::Destroy() { DestroyWindow(); } -void RenderWidgetHostViewWin::SetTooltipText(const string16& tooltip_text) { +void RenderWidgetHostViewWin::SetTooltipText( + const base::string16& tooltip_text) { if (!render_widget_host_->is_hidden()) EnsureTooltip(); // Clamp the tooltip length to kMaxTooltipLength so that we don't // accidentally DOS the user with a mega tooltip (since Windows doesn't seem // to do this itself). - const string16 new_tooltip_text = + const base::string16 new_tooltip_text = gfx::TruncateString(tooltip_text, kMaxTooltipLength); if (new_tooltip_text != tooltip_text_) { @@ -1017,7 +1018,7 @@ void RenderWidgetHostViewWin::ClearCompositionText() { NOTIMPLEMENTED(); } -void RenderWidgetHostViewWin::InsertText(const string16& text) { +void RenderWidgetHostViewWin::InsertText(const base::string16& text) { if (!base::win::IsTSFAwareRequired()) { NOTREACHED(); return; @@ -1153,7 +1154,7 @@ bool RenderWidgetHostViewWin::DeleteRange(const gfx::Range& range) { } bool RenderWidgetHostViewWin::GetTextFromRange(const gfx::Range& range, - string16* text) const { + base::string16* text) const { if (!base::win::IsTSFAwareRequired()) { NOTREACHED(); return false; diff --git a/content/browser/renderer_host/render_widget_host_view_win.h b/content/browser/renderer_host/render_widget_host_view_win.h index 72b22aa756..b9a87bf61e 100644 --- a/content/browser/renderer_host/render_widget_host_view_win.h +++ b/content/browser/renderer_host/render_widget_host_view_win.h @@ -202,7 +202,7 @@ class RenderWidgetHostViewWin // called by WebContentsImpl before DestroyWindow virtual void WillWmDestroy() OVERRIDE; virtual void Destroy() OVERRIDE; - virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE; + virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE; virtual BackingStore* AllocBackingStore(const gfx::Size& size) OVERRIDE; virtual void CopyFromCompositingSurface( const gfx::Rect& src_subrect, @@ -270,7 +270,7 @@ class RenderWidgetHostViewWin const ui::CompositionText& composition) OVERRIDE; virtual void ConfirmCompositionText() OVERRIDE; virtual void ClearCompositionText() OVERRIDE; - virtual void InsertText(const string16& text) OVERRIDE; + virtual void InsertText(const base::string16& text) OVERRIDE; virtual void InsertChar(char16 ch, int flags) OVERRIDE; virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE; virtual ui::TextInputType GetTextInputType() const OVERRIDE; @@ -286,7 +286,7 @@ class RenderWidgetHostViewWin virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE; virtual bool DeleteRange(const gfx::Range& range) OVERRIDE; virtual bool GetTextFromRange(const gfx::Range& range, - string16* text) const OVERRIDE; + base::string16* text) const OVERRIDE; virtual void OnInputMethodChanged() OVERRIDE; virtual bool ChangeTextDirectionAndLayoutAlignment( base::i18n::TextDirection direction) OVERRIDE; @@ -516,7 +516,7 @@ class RenderWidgetHostViewWin // Tooltips // The text to be shown in the tooltip, supplied by the renderer. - string16 tooltip_text_; + base::string16 tooltip_text_; // The tooltip control hwnd HWND tooltip_hwnd_; // Whether or not a tooltip is currently visible. We use this to track diff --git a/content/browser/renderer_host/test_backing_store.cc b/content/browser/renderer_host/test_backing_store.cc deleted file mode 100644 index 74fa44d487..0000000000 --- a/content/browser/renderer_host/test_backing_store.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/renderer_host/test_backing_store.h" - -namespace content { - -TestBackingStore::TestBackingStore(RenderWidgetHost* widget, - const gfx::Size& size) - : BackingStore(widget, size) { -} - -TestBackingStore::~TestBackingStore() { -} - -void TestBackingStore::PaintToBackingStore( - RenderProcessHost* process, - TransportDIB::Id bitmap, - const gfx::Rect& bitmap_rect, - const std::vector<gfx::Rect>& copy_rects, - float scale_factor, - const base::Closure& completion_callback, - bool* scheduled_completion_callback) { - *scheduled_completion_callback = false; -} - -bool TestBackingStore::CopyFromBackingStore(const gfx::Rect& rect, - skia::PlatformBitmap* output) { - return false; -} - -void TestBackingStore::ScrollBackingStore(const gfx::Vector2d& delta, - const gfx::Rect& clip_rect, - const gfx::Size& view_size) { -} - -} // namespace content diff --git a/content/browser/renderer_host/test_backing_store.h b/content/browser/renderer_host/test_backing_store.h deleted file mode 100644 index 4b76851c74..0000000000 --- a/content/browser/renderer_host/test_backing_store.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_TEST_TEST_BACKING_STORE_H_ -#define CONTENT_BROWSER_RENDERER_HOST_TEST_TEST_BACKING_STORE_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "content/browser/renderer_host/backing_store.h" - -namespace content { - -class TestBackingStore : public BackingStore { - public: - TestBackingStore(RenderWidgetHost* widget, const gfx::Size& size); - virtual ~TestBackingStore(); - - // BackingStore implementation. - virtual void PaintToBackingStore( - RenderProcessHost* process, - TransportDIB::Id bitmap, - const gfx::Rect& bitmap_rect, - const std::vector<gfx::Rect>& copy_rects, - float scale_factor, - const base::Closure& completion_callback, - bool* scheduled_completion_callback) OVERRIDE; - virtual bool CopyFromBackingStore(const gfx::Rect& rect, - skia::PlatformBitmap* output) OVERRIDE; - virtual void ScrollBackingStore(const gfx::Vector2d& delta, - const gfx::Rect& clip_rect, - const gfx::Size& view_size) OVERRIDE; - private: - DISALLOW_COPY_AND_ASSIGN(TestBackingStore); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_TEST_TEST_BACKING_STORE_H_ diff --git a/content/browser/renderer_host/test_render_view_host.cc b/content/browser/renderer_host/test_render_view_host.cc deleted file mode 100644 index 19d5958179..0000000000 --- a/content/browser/renderer_host/test_render_view_host.cc +++ /dev/null @@ -1,432 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/renderer_host/test_render_view_host.h" - -#include "base/memory/scoped_ptr.h" -#include "content/browser/dom_storage/dom_storage_context_wrapper.h" -#include "content/browser/dom_storage/session_storage_namespace_impl.h" -#include "content/browser/renderer_host/test_backing_store.h" -#include "content/browser/site_instance_impl.h" -#include "content/common/dom_storage/dom_storage_types.h" -#include "content/common/view_messages.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/navigation_controller.h" -#include "content/public/browser/storage_partition.h" -#include "content/public/common/content_client.h" -#include "content/public/common/page_state.h" -#include "content/test/test_web_contents.h" -#include "media/base/video_frame.h" -#include "ui/gfx/rect.h" -#include "webkit/common/webpreferences.h" - -namespace content { - -namespace { - -const int64 kFrameId = 13UL; - -} // namespace - - -void InitNavigateParams(ViewHostMsg_FrameNavigate_Params* params, - int page_id, - const GURL& url, - PageTransition transition) { - params->page_id = page_id; - params->url = url; - params->referrer = Referrer(); - params->transition = transition; - params->redirects = std::vector<GURL>(); - params->should_update_history = false; - params->searchable_form_url = GURL(); - params->searchable_form_encoding = std::string(); - params->security_info = std::string(); - params->gesture = NavigationGestureUser; - params->was_within_same_page = false; - params->is_post = false; - params->page_state = PageState::CreateFromURL(url); -} - -TestRenderWidgetHostView::TestRenderWidgetHostView(RenderWidgetHost* rwh) - : rwh_(RenderWidgetHostImpl::From(rwh)), - is_showing_(false), - did_swap_compositor_frame_(false) { - rwh_->SetView(this); -} - -TestRenderWidgetHostView::~TestRenderWidgetHostView() { -} - -RenderWidgetHost* TestRenderWidgetHostView::GetRenderWidgetHost() const { - return NULL; -} - -gfx::NativeView TestRenderWidgetHostView::GetNativeView() const { - return NULL; -} - -gfx::NativeViewId TestRenderWidgetHostView::GetNativeViewId() const { - return 0; -} - -gfx::NativeViewAccessible TestRenderWidgetHostView::GetNativeViewAccessible() { - return NULL; -} - -bool TestRenderWidgetHostView::HasFocus() const { - return true; -} - -bool TestRenderWidgetHostView::IsSurfaceAvailableForCopy() const { - return true; -} - -void TestRenderWidgetHostView::Show() { - is_showing_ = true; -} - -void TestRenderWidgetHostView::Hide() { - is_showing_ = false; -} - -bool TestRenderWidgetHostView::IsShowing() { - return is_showing_; -} - -void TestRenderWidgetHostView::RenderProcessGone(base::TerminationStatus status, - int error_code) { - delete this; -} - -void TestRenderWidgetHostView::Destroy() { delete this; } - -gfx::Rect TestRenderWidgetHostView::GetViewBounds() const { - return gfx::Rect(); -} - -BackingStore* TestRenderWidgetHostView::AllocBackingStore( - const gfx::Size& size) { - return new TestBackingStore(rwh_, size); -} - -void TestRenderWidgetHostView::CopyFromCompositingSurface( - const gfx::Rect& src_subrect, - const gfx::Size& dst_size, - const base::Callback<void(bool, const SkBitmap&)>& callback) { - callback.Run(false, SkBitmap()); -} - -void TestRenderWidgetHostView::CopyFromCompositingSurfaceToVideoFrame( - const gfx::Rect& src_subrect, - const scoped_refptr<media::VideoFrame>& target, - const base::Callback<void(bool)>& callback) { - callback.Run(false); -} - -bool TestRenderWidgetHostView::CanCopyToVideoFrame() const { - return false; -} - -void TestRenderWidgetHostView::OnAcceleratedCompositingStateChange() { -} - -void TestRenderWidgetHostView::AcceleratedSurfaceInitialized(int host_id, - int route_id) { -} - -void TestRenderWidgetHostView::AcceleratedSurfaceBuffersSwapped( - const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, - int gpu_host_id) { -} - -void TestRenderWidgetHostView::AcceleratedSurfacePostSubBuffer( - const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, - int gpu_host_id) { -} - -void TestRenderWidgetHostView::AcceleratedSurfaceSuspend() { -} - -bool TestRenderWidgetHostView::HasAcceleratedSurface( - const gfx::Size& desired_size) { - return false; -} - -#if defined(OS_MACOSX) - -void TestRenderWidgetHostView::AboutToWaitForBackingStoreMsg() { -} - -void TestRenderWidgetHostView::SetActive(bool active) { - // <viettrungluu@gmail.com>: Do I need to do anything here? -} - -bool TestRenderWidgetHostView::SupportsSpeech() const { - return false; -} - -void TestRenderWidgetHostView::SpeakSelection() { -} - -bool TestRenderWidgetHostView::IsSpeaking() const { - return false; -} - -void TestRenderWidgetHostView::StopSpeaking() { -} - -bool TestRenderWidgetHostView::PostProcessEventForPluginIme( - const NativeWebKeyboardEvent& event) { - return false; -} - -#elif defined(OS_WIN) && !defined(USE_AURA) -void TestRenderWidgetHostView::WillWmDestroy() { -} -#endif - -gfx::Rect TestRenderWidgetHostView::GetBoundsInRootWindow() { - return gfx::Rect(); -} - -#if defined(TOOLKIT_GTK) -GdkEventButton* TestRenderWidgetHostView::GetLastMouseDown() { - return NULL; -} - -gfx::NativeView TestRenderWidgetHostView::BuildInputMethodsGtkMenu() { - return NULL; -} -#endif // defined(TOOLKIT_GTK) - -void TestRenderWidgetHostView::OnSwapCompositorFrame( - uint32 output_surface_id, - scoped_ptr<cc::CompositorFrame> frame) { - did_swap_compositor_frame_ = true; -} - - -gfx::GLSurfaceHandle TestRenderWidgetHostView::GetCompositingSurface() { - return gfx::GLSurfaceHandle(); -} - -#if defined(OS_WIN) && !defined(USE_AURA) -void TestRenderWidgetHostView::SetClickthroughRegion(SkRegion* region) { -} -#endif - -bool TestRenderWidgetHostView::LockMouse() { - return false; -} - -void TestRenderWidgetHostView::UnlockMouse() { -} - -#if defined(OS_WIN) && defined(USE_AURA) -void TestRenderWidgetHostView::SetParentNativeViewAccessible( - gfx::NativeViewAccessible accessible_parent) { -} - -gfx::NativeViewId TestRenderWidgetHostView::GetParentForWindowlessPlugin() - const { - return 0; -} -#endif - -TestRenderViewHost::TestRenderViewHost( - SiteInstance* instance, - RenderViewHostDelegate* delegate, - RenderWidgetHostDelegate* widget_delegate, - int routing_id, - int main_frame_routing_id, - bool swapped_out) - : RenderViewHostImpl(instance, - delegate, - widget_delegate, - routing_id, - main_frame_routing_id, - swapped_out, - false /* hidden */), - render_view_created_(false), - delete_counter_(NULL), - simulate_fetch_via_proxy_(false), - simulate_history_list_was_cleared_(false), - contents_mime_type_("text/html"), - opener_route_id_(MSG_ROUTING_NONE) { - // TestRenderWidgetHostView installs itself into this->view_ in its - // constructor, and deletes itself when TestRenderWidgetHostView::Destroy() is - // called. - new TestRenderWidgetHostView(this); - - main_frame_id_ = kFrameId; -} - -TestRenderViewHost::~TestRenderViewHost() { - if (delete_counter_) - ++*delete_counter_; -} - -bool TestRenderViewHost::CreateRenderView( - const string16& frame_name, - int opener_route_id, - int32 max_page_id) { - DCHECK(!render_view_created_); - render_view_created_ = true; - opener_route_id_ = opener_route_id; - return true; -} - -bool TestRenderViewHost::IsRenderViewLive() const { - return render_view_created_; -} - -void TestRenderViewHost::SendNavigate(int page_id, const GURL& url) { - SendNavigateWithTransition(page_id, url, PAGE_TRANSITION_LINK); -} - -void TestRenderViewHost::SendFailedNavigate(int page_id, const GURL& url) { - SendNavigateWithTransitionAndResponseCode( - page_id, url, PAGE_TRANSITION_LINK, 500); -} - -void TestRenderViewHost::SendNavigateWithTransition( - int page_id, const GURL& url, PageTransition transition) { - SendNavigateWithTransitionAndResponseCode(page_id, url, transition, 200); -} - -void TestRenderViewHost::SendNavigateWithOriginalRequestURL( - int page_id, const GURL& url, const GURL& original_request_url) { - OnDidStartProvisionalLoadForFrame(kFrameId, -1, true, url); - SendNavigateWithParameters(page_id, url, PAGE_TRANSITION_LINK, - original_request_url, 200, 0); -} - -void TestRenderViewHost::SendNavigateWithFile( - int page_id, const GURL& url, const base::FilePath& file_path) { - SendNavigateWithParameters(page_id, url, PAGE_TRANSITION_LINK, - url, 200, &file_path); -} - -void TestRenderViewHost::SendNavigateWithTransitionAndResponseCode( - int page_id, const GURL& url, PageTransition transition, - int response_code) { - // DidStartProvisionalLoad may delete the pending entry that holds |url|, - // so we keep a copy of it to use in SendNavigateWithParameters. - GURL url_copy(url); - OnDidStartProvisionalLoadForFrame(kFrameId, -1, true, url_copy); - SendNavigateWithParameters(page_id, url_copy, transition, url_copy, - response_code, 0); -} - -void TestRenderViewHost::SendNavigateWithParameters( - int page_id, const GURL& url, PageTransition transition, - const GURL& original_request_url, int response_code, - const base::FilePath* file_path_for_history_item) { - ViewHostMsg_FrameNavigate_Params params; - params.page_id = page_id; - params.frame_id = kFrameId; - params.url = url; - params.referrer = Referrer(); - params.transition = transition; - params.redirects = std::vector<GURL>(); - params.should_update_history = true; - params.searchable_form_url = GURL(); - params.searchable_form_encoding = std::string(); - params.security_info = std::string(); - params.gesture = NavigationGestureUser; - params.contents_mime_type = contents_mime_type_; - params.is_post = false; - params.was_within_same_page = false; - params.http_status_code = response_code; - params.socket_address.set_host("2001:db8::1"); - params.socket_address.set_port(80); - params.was_fetched_via_proxy = simulate_fetch_via_proxy_; - params.history_list_was_cleared = simulate_history_list_was_cleared_; - params.original_request_url = original_request_url; - - params.page_state = PageState::CreateForTesting( - url, - false, - file_path_for_history_item ? "data" : NULL, - file_path_for_history_item); - - ViewHostMsg_FrameNavigate msg(1, params); - OnNavigate(msg); -} - -void TestRenderViewHost::SendShouldCloseACK(bool proceed) { - base::TimeTicks now = base::TimeTicks::Now(); - OnShouldCloseACK(proceed, now, now); -} - -void TestRenderViewHost::SetContentsMimeType(const std::string& mime_type) { - contents_mime_type_ = mime_type; -} - -void TestRenderViewHost::SimulateSwapOutACK() { - OnSwappedOut(false); -} - -void TestRenderViewHost::SimulateWasHidden() { - WasHidden(); -} - -void TestRenderViewHost::SimulateWasShown() { - WasShown(); -} - -void TestRenderViewHost::TestOnStartDragging( - const DropData& drop_data) { - blink::WebDragOperationsMask drag_operation = blink::WebDragOperationEvery; - DragEventSourceInfo event_info; - OnStartDragging(drop_data, drag_operation, SkBitmap(), gfx::Vector2d(), - event_info); -} - -void TestRenderViewHost::TestOnUpdateStateWithFile( - int process_id, - const base::FilePath& file_path) { - OnUpdateState(process_id, - PageState::CreateForTesting(GURL("http://www.google.com"), - false, - "data", - &file_path)); -} - -void TestRenderViewHost::set_simulate_fetch_via_proxy(bool proxy) { - simulate_fetch_via_proxy_ = proxy; -} - -void TestRenderViewHost::set_simulate_history_list_was_cleared(bool cleared) { - simulate_history_list_was_cleared_ = cleared; -} - -RenderViewHostImplTestHarness::RenderViewHostImplTestHarness() { - std::vector<ui::ScaleFactor> scale_factors; - scale_factors.push_back(ui::SCALE_FACTOR_100P); - scoped_set_supported_scale_factors_.reset( - new ui::test::ScopedSetSupportedScaleFactors(scale_factors)); -} - -RenderViewHostImplTestHarness::~RenderViewHostImplTestHarness() { -} - -TestRenderViewHost* RenderViewHostImplTestHarness::test_rvh() { - return static_cast<TestRenderViewHost*>(rvh()); -} - -TestRenderViewHost* RenderViewHostImplTestHarness::pending_test_rvh() { - return static_cast<TestRenderViewHost*>(pending_rvh()); -} - -TestRenderViewHost* RenderViewHostImplTestHarness::active_test_rvh() { - return static_cast<TestRenderViewHost*>(active_rvh()); -} - -TestWebContents* RenderViewHostImplTestHarness::contents() { - return static_cast<TestWebContents*>(web_contents()); -} - -} // namespace content diff --git a/content/browser/renderer_host/test_render_view_host.h b/content/browser/renderer_host/test_render_view_host.h deleted file mode 100644 index 97bcd6e703..0000000000 --- a/content/browser/renderer_host/test_render_view_host.h +++ /dev/null @@ -1,385 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_TEST_RENDER_VIEW_HOST_H_ -#define CONTENT_BROWSER_RENDERER_HOST_TEST_RENDER_VIEW_HOST_H_ - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/gtest_prod_util.h" -#include "build/build_config.h" -#include "content/browser/renderer_host/render_view_host_impl.h" -#include "content/browser/renderer_host/render_widget_host_view_base.h" -#include "content/public/common/page_transition_types.h" -#include "content/public/test/test_renderer_host.h" -#include "ui/base/layout.h" -#include "ui/gfx/vector2d_f.h" - -// This file provides a testing framework for mocking out the RenderProcessHost -// layer. It allows you to test RenderViewHost, WebContentsImpl, -// NavigationController, and other layers above that without running an actual -// renderer process. -// -// To use, derive your test base class from RenderViewHostImplTestHarness. - -struct ViewHostMsg_FrameNavigate_Params; - -namespace gfx { -class Rect; -} - -namespace content { - -class SiteInstance; -class TestWebContents; - -// Utility function to initialize ViewHostMsg_NavigateParams_Params -// with given |page_id|, |url| and |transition_type|. -void InitNavigateParams(ViewHostMsg_FrameNavigate_Params* params, - int page_id, - const GURL& url, - PageTransition transition_type); - -// TestRenderViewHostView ------------------------------------------------------ - -// Subclass the RenderViewHost's view so that we can call Show(), etc., -// without having side-effects. -class TestRenderWidgetHostView : public RenderWidgetHostViewBase { - public: - explicit TestRenderWidgetHostView(RenderWidgetHost* rwh); - virtual ~TestRenderWidgetHostView(); - - // RenderWidgetHostView implementation. - virtual void InitAsChild(gfx::NativeView parent_view) OVERRIDE {} - virtual RenderWidgetHost* GetRenderWidgetHost() const OVERRIDE; - virtual void SetSize(const gfx::Size& size) OVERRIDE {} - virtual void SetBounds(const gfx::Rect& rect) OVERRIDE {} - virtual gfx::NativeView GetNativeView() const OVERRIDE; - virtual gfx::NativeViewId GetNativeViewId() const OVERRIDE; - virtual gfx::NativeViewAccessible GetNativeViewAccessible() OVERRIDE; - virtual bool HasFocus() const OVERRIDE; - virtual bool IsSurfaceAvailableForCopy() const OVERRIDE; - virtual void Show() OVERRIDE; - virtual void Hide() OVERRIDE; - virtual bool IsShowing() OVERRIDE; - virtual gfx::Rect GetViewBounds() const OVERRIDE; -#if defined(OS_MACOSX) - virtual void SetActive(bool active) OVERRIDE; - virtual void SetTakesFocusOnlyOnMouseDown(bool flag) OVERRIDE {} - virtual void SetWindowVisibility(bool visible) OVERRIDE {} - virtual void WindowFrameChanged() OVERRIDE {} - virtual void ShowDefinitionForSelection() OVERRIDE {} - virtual bool SupportsSpeech() const OVERRIDE; - virtual void SpeakSelection() OVERRIDE; - virtual bool IsSpeaking() const OVERRIDE; - virtual void StopSpeaking() OVERRIDE; -#endif // defined(OS_MACOSX) -#if defined(TOOLKIT_GTK) - virtual GdkEventButton* GetLastMouseDown() OVERRIDE; - virtual gfx::NativeView BuildInputMethodsGtkMenu() OVERRIDE; -#endif // defined(TOOLKIT_GTK) - virtual void OnSwapCompositorFrame( - uint32 output_surface_id, - scoped_ptr<cc::CompositorFrame> frame) OVERRIDE; - - // RenderWidgetHostViewPort implementation. - virtual void InitAsPopup(RenderWidgetHostView* parent_host_view, - const gfx::Rect& pos) OVERRIDE {} - virtual void InitAsFullscreen( - RenderWidgetHostView* reference_host_view) OVERRIDE {} - virtual void WasShown() OVERRIDE {} - virtual void WasHidden() OVERRIDE {} - virtual void MovePluginWindows( - const gfx::Vector2d& scroll_offset, - const std::vector<WebPluginGeometry>& moves) OVERRIDE {} - virtual void Focus() OVERRIDE {} - virtual void Blur() OVERRIDE {} - virtual void SetIsLoading(bool is_loading) OVERRIDE {} - virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE {} - virtual void TextInputTypeChanged(ui::TextInputType type, - ui::TextInputMode input_mode, - bool can_compose_inline) OVERRIDE {} - virtual void ImeCancelComposition() OVERRIDE {} -#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA) - virtual void ImeCompositionRangeChanged( - const gfx::Range& range, - const std::vector<gfx::Rect>& character_bounds) OVERRIDE {} -#endif - virtual void DidUpdateBackingStore( - const gfx::Rect& scroll_rect, - const gfx::Vector2d& scroll_delta, - const std::vector<gfx::Rect>& rects, - const ui::LatencyInfo& latency_info) OVERRIDE {} - virtual void RenderProcessGone(base::TerminationStatus status, - int error_code) OVERRIDE; - virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) { } - virtual void Destroy() OVERRIDE; - virtual void SetTooltipText(const string16& tooltip_text) OVERRIDE {} - virtual void SelectionBoundsChanged( - const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE {} - virtual void ScrollOffsetChanged() OVERRIDE {} - virtual BackingStore* AllocBackingStore(const gfx::Size& size) OVERRIDE; - virtual void CopyFromCompositingSurface( - const gfx::Rect& src_subrect, - const gfx::Size& dst_size, - const base::Callback<void(bool, const SkBitmap&)>& callback) OVERRIDE; - virtual void CopyFromCompositingSurfaceToVideoFrame( - const gfx::Rect& src_subrect, - const scoped_refptr<media::VideoFrame>& target, - const base::Callback<void(bool)>& callback) OVERRIDE; - virtual bool CanCopyToVideoFrame() const OVERRIDE; - virtual void OnAcceleratedCompositingStateChange() OVERRIDE; - virtual void AcceleratedSurfaceInitialized(int host_id, - int route_id) OVERRIDE; - virtual void AcceleratedSurfaceBuffersSwapped( - const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, - int gpu_host_id) OVERRIDE; - virtual void AcceleratedSurfacePostSubBuffer( - const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, - int gpu_host_id) OVERRIDE; - virtual void AcceleratedSurfaceSuspend() OVERRIDE; - virtual void AcceleratedSurfaceRelease() OVERRIDE {} - virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE; -#if defined(OS_MACOSX) - virtual void AboutToWaitForBackingStoreMsg() OVERRIDE; - virtual bool PostProcessEventForPluginIme( - const NativeWebKeyboardEvent& event) OVERRIDE; -#elif defined(OS_ANDROID) - virtual void ShowDisambiguationPopup( - const gfx::Rect& target_rect, - const SkBitmap& zoomed_bitmap) OVERRIDE {} - virtual void HasTouchEventHandlers(bool need_touch_events) OVERRIDE {} -#elif defined(OS_WIN) && !defined(USE_AURA) - virtual void WillWmDestroy() OVERRIDE; -#endif - virtual void GetScreenInfo(blink::WebScreenInfo* results) OVERRIDE {} - virtual gfx::Rect GetBoundsInRootWindow() OVERRIDE; - virtual void SetHasHorizontalScrollbar( - bool has_horizontal_scrollbar) OVERRIDE { } - virtual void SetScrollOffsetPinning( - bool is_pinned_to_left, bool is_pinned_to_right) OVERRIDE { } - virtual void OnAccessibilityEvents( - const std::vector<AccessibilityHostMsg_EventParams>& params) OVERRIDE {} - virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE; -#if defined(OS_WIN) && !defined(USE_AURA) - virtual void SetClickthroughRegion(SkRegion* region) OVERRIDE; -#endif - virtual bool LockMouse() OVERRIDE; - virtual void UnlockMouse() OVERRIDE; -#if defined(OS_WIN) && defined(USE_AURA) - virtual void SetParentNativeViewAccessible( - gfx::NativeViewAccessible accessible_parent) OVERRIDE; - virtual gfx::NativeViewId GetParentForWindowlessPlugin() const OVERRIDE; -#endif - - bool is_showing() const { return is_showing_; } - bool did_swap_compositor_frame() const { return did_swap_compositor_frame_; } - - protected: - RenderWidgetHostImpl* rwh_; - - private: - bool is_showing_; - bool did_swap_compositor_frame_; -}; - -#if defined(COMPILER_MSVC) -// See comment for same warning on RenderViewHostImpl. -#pragma warning(push) -#pragma warning(disable: 4250) -#endif - -// TestRenderViewHost ---------------------------------------------------------- - -// TODO(brettw) this should use a TestWebContents which should be generalized -// from the WebContentsImpl test. We will probably also need that class' version -// of CreateRenderViewForRenderManager when more complicated tests start using -// this. -// -// Note that users outside of content must use this class by getting -// the separate RenderViewHostTester interface via -// RenderViewHostTester::For(rvh) on the RenderViewHost they want to -// drive tests on. -// -// Users within content may directly static_cast from a -// RenderViewHost* to a TestRenderViewHost*. -// -// The reasons we do it this way rather than extending the parallel -// inheritance hierarchy we have for RenderWidgetHost/RenderViewHost -// vs. RenderWidgetHostImpl/RenderViewHostImpl are: -// -// a) Extending the parallel class hierarchy further would require -// more classes to use virtual inheritance. This is a complexity that -// is better to avoid, especially when it would be introduced in the -// production code solely to facilitate testing code. -// -// b) While users outside of content only need to drive tests on a -// RenderViewHost, content needs a test version of the full -// RenderViewHostImpl so that it can test all methods on that concrete -// class (e.g. overriding a method such as -// RenderViewHostImpl::CreateRenderView). This would have complicated -// the dual class hierarchy even further. -// -// The reason we do it this way instead of using composition is -// similar to (b) above, essentially it gets very tricky. By using -// the split interface we avoid complexity within content and maintain -// reasonable utility for embedders. -class TestRenderViewHost - : public RenderViewHostImpl, - public RenderViewHostTester { - public: - TestRenderViewHost(SiteInstance* instance, - RenderViewHostDelegate* delegate, - RenderWidgetHostDelegate* widget_delegate, - int routing_id, - int main_frame_routing_id, - bool swapped_out); - virtual ~TestRenderViewHost(); - - // RenderViewHostTester implementation. Note that CreateRenderView - // is not specified since it is synonymous with the one from - // RenderViewHostImpl, see below. - virtual void SendNavigate(int page_id, const GURL& url) OVERRIDE; - virtual void SendFailedNavigate(int page_id, const GURL& url) OVERRIDE; - virtual void SendNavigateWithTransition(int page_id, const GURL& url, - PageTransition transition) OVERRIDE; - virtual void SendShouldCloseACK(bool proceed) OVERRIDE; - virtual void SetContentsMimeType(const std::string& mime_type) OVERRIDE; - virtual void SimulateSwapOutACK() OVERRIDE; - virtual void SimulateWasHidden() OVERRIDE; - virtual void SimulateWasShown() OVERRIDE; - - // Calls OnNavigate on the RenderViewHost with the given information, - // including a custom original request URL. Sets the rest of the - // parameters in the message to the "typical" values. This is a helper - // function for simulating the most common types of loads. - void SendNavigateWithOriginalRequestURL( - int page_id, const GURL& url, const GURL& original_request_url); - - void SendNavigateWithFile( - int page_id, const GURL& url, const base::FilePath& file_path); - - void TestOnUpdateStateWithFile( - int process_id, const base::FilePath& file_path); - - void TestOnStartDragging(const DropData& drop_data); - - // If set, *delete_counter is incremented when this object destructs. - void set_delete_counter(int* delete_counter) { - delete_counter_ = delete_counter; - } - - // Sets whether the RenderView currently exists or not. This controls the - // return value from IsRenderViewLive, which the rest of the system uses to - // check whether the RenderView has crashed or not. - void set_render_view_created(bool created) { - render_view_created_ = created; - } - - // Returns whether the RenderViewHost is currently waiting to hear the result - // of a before unload handler from the renderer. - bool is_waiting_for_beforeunload_ack() const { - return is_waiting_for_beforeunload_ack_; - } - - // Returns whether the RenderViewHost is currently waiting to hear the result - // of an unload handler from the renderer. - bool is_waiting_for_unload_ack() const { - return is_waiting_for_unload_ack_; - } - - // Sets whether the RenderViewHost is currently swapped out, and thus - // filtering messages from the renderer. - void set_is_swapped_out(bool is_swapped_out) { - is_swapped_out_ = is_swapped_out; - } - - // If set, navigations will appear to have loaded through a proxy - // (ViewHostMsg_FrameNavigte_Params::was_fetched_via_proxy). - // False by default. - void set_simulate_fetch_via_proxy(bool proxy); - - // If set, navigations will appear to have cleared the history list in the - // RenderView (ViewHostMsg_FrameNavigate_Params::history_list_was_cleared). - // False by default. - void set_simulate_history_list_was_cleared(bool cleared); - - // The opener route id passed to CreateRenderView(). - int opener_route_id() const { return opener_route_id_; } - - // RenderViewHost overrides -------------------------------------------------- - - virtual bool CreateRenderView(const string16& frame_name, - int opener_route_id, - int32 max_page_id) OVERRIDE; - virtual bool IsRenderViewLive() const OVERRIDE; - - private: - FRIEND_TEST_ALL_PREFIXES(RenderViewHostTest, FilterNavigate); - - void SendNavigateWithTransitionAndResponseCode(int page_id, - const GURL& url, - PageTransition transition, - int response_code); - - // Calls OnNavigate on the RenderViewHost with the given information. - // Sets the rest of the parameters in the message to the "typical" values. - // This is a helper function for simulating the most common types of loads. - void SendNavigateWithParameters( - int page_id, - const GURL& url, - PageTransition transition, - const GURL& original_request_url, - int response_code, - const base::FilePath* file_path_for_history_item); - - // Tracks if the caller thinks if it created the RenderView. This is so we can - // respond to IsRenderViewLive appropriately. - bool render_view_created_; - - // See set_delete_counter() above. May be NULL. - int* delete_counter_; - - // See set_simulate_fetch_via_proxy() above. - bool simulate_fetch_via_proxy_; - - // See set_simulate_history_list_was_cleared() above. - bool simulate_history_list_was_cleared_; - - // See SetContentsMimeType() above. - std::string contents_mime_type_; - - // See opener_route_id() above. - int opener_route_id_; - - DISALLOW_COPY_AND_ASSIGN(TestRenderViewHost); -}; - -#if defined(COMPILER_MSVC) -#pragma warning(pop) -#endif - -// Adds methods to get straight at the impl classes. -class RenderViewHostImplTestHarness : public RenderViewHostTestHarness { - public: - RenderViewHostImplTestHarness(); - virtual ~RenderViewHostImplTestHarness(); - - TestRenderViewHost* test_rvh(); - TestRenderViewHost* pending_test_rvh(); - TestRenderViewHost* active_test_rvh(); - TestWebContents* contents(); - - private: - typedef scoped_ptr<ui::test::ScopedSetSupportedScaleFactors> - ScopedSetSupportedScaleFactors; - ScopedSetSupportedScaleFactors scoped_set_supported_scale_factors_; - DISALLOW_COPY_AND_ASSIGN(RenderViewHostImplTestHarness); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_TEST_RENDER_VIEW_HOST_H_ diff --git a/content/browser/renderer_host/web_input_event_aura.cc b/content/browser/renderer_host/web_input_event_aura.cc index 5127c07fb1..f35d37740e 100644 --- a/content/browser/renderer_host/web_input_event_aura.cc +++ b/content/browser/renderer_host/web_input_event_aura.cc @@ -9,6 +9,10 @@ #include "ui/events/event.h" #include "ui/events/event_utils.h" +#if defined(USE_OZONE) +#include "ui/events/keycodes/keyboard_code_conversion.h" +#endif + namespace content { #if defined(USE_X11) || defined(USE_OZONE) @@ -101,7 +105,9 @@ blink::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent( if (webkit_event.windowsKeyCode == ui::VKEY_RETURN) webkit_event.unmodifiedText[0] = '\r'; else - webkit_event.unmodifiedText[0] = character; + webkit_event.unmodifiedText[0] = ui::GetCharacterFromKeyCode( + ui::KeyboardCodeFromNative(native_event), + ui::EventFlagsFromNative(native_event)); if (webkit_event.modifiers & blink::WebInputEvent::ControlKey) { webkit_event.text[0] = diff --git a/content/browser/renderer_host/webmenurunner_mac.mm b/content/browser/renderer_host/webmenurunner_mac.mm index a81d2c9e2f..bb33a007aa 100644 --- a/content/browser/renderer_host/webmenurunner_mac.mm +++ b/content/browser/renderer_host/webmenurunner_mac.mm @@ -82,6 +82,14 @@ [[NSAttributedString alloc] initWithString:title attributes:attrs]); [menuItem setAttributedTitle:attrTitle]; + // We set the title as well as the attributed title here. The attributed title + // will be displayed in the menu, but typeahead will use the non-attributed + // string that doesn't contain any leading or trailing whitespace. This is + // what Apple uses in WebKit as well: + // http://trac.webkit.org/browser/trunk/Source/WebKit2/UIProcess/mac/WebPopupMenuProxyMac.mm#L90 + NSCharacterSet* whitespaceSet = [NSCharacterSet whitespaceCharacterSet]; + [menuItem setTitle:[title stringByTrimmingCharactersInSet:whitespaceSet]]; + [menuItem setTag:[menu_ numberOfItems] - 1]; } diff --git a/content/browser/resource_context_impl.cc b/content/browser/resource_context_impl.cc index c026d936ac..c2f22073e0 100644 --- a/content/browser/resource_context_impl.cc +++ b/content/browser/resource_context_impl.cc @@ -55,6 +55,10 @@ ResourceContext::~ResourceContext() { DetachUserDataThread(); } +std::string ResourceContext::GetMediaDeviceIDSalt() { + return std::string(); +} + scoped_ptr<net::ClientCertStore> ResourceContext::CreateClientCertStore() { return scoped_ptr<net::ClientCertStore>(); } diff --git a/content/browser/resources/gpu/info_view.js b/content/browser/resources/gpu/info_view.js index 13afa4af02..e736d8e49a 100644 --- a/content/browser/resources/gpu/info_view.js +++ b/content/browser/resources/gpu/info_view.js @@ -92,6 +92,7 @@ cr.define('gpu', function() { 'flash_stage3d_baseline': 'Flash Stage3D Baseline profile', 'texture_sharing': 'Texture Sharing', 'video_decode': 'Video Decode', + 'video_encode': 'Video Encode', 'video': 'Video', // GPU Switching 'gpu_switching': 'GPU Switching', diff --git a/content/browser/resources/media/dump_creator.js b/content/browser/resources/media/dump_creator.js index 5daddabc61..af17cf3a4e 100644 --- a/content/browser/resources/media/dump_creator.js +++ b/content/browser/resources/media/dump_creator.js @@ -55,12 +55,12 @@ var DumpCreator = (function() { this.root_.appendChild(content); content.innerHTML = '<button disabled></button> Status: <span></span>' + - '<div><form><button>' + + '<div><a><button>' + 'Download the PeerConnection updates and stats data' + - '</button></form></div>'; + '</button></a></div>'; content.getElementsByTagName('button')[0].addEventListener( 'click', this.onRtpToggled_.bind(this)); - content.getElementsByTagName('button')[1].addEventListener( + content.getElementsByTagName('a')[0].addEventListener( 'click', this.onDownloadData_.bind(this)); this.updateDisplay_(); @@ -77,8 +77,8 @@ var DumpCreator = (function() { new Blob([JSON.stringify(peerConnectionDataStore, null, ' ')], {type: 'octet/stream'}); var URL = window.webkitURL.createObjectURL(textBlob); - this.root_.getElementsByTagName('form')[0].action = URL; - // The default action of the button will submit the form. + this.root_.getElementsByTagName('a')[0].href = URL; + // The default action of the anchor will download the URL. }, /** diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc index 2eb7b51885..dacc1e6efd 100644 --- a/content/browser/security_exploit_browsertest.cc +++ b/content/browser/security_exploit_browsertest.cc @@ -3,11 +3,19 @@ // found in the LICENSE file. #include "base/command_line.h" +#include "base/containers/hash_tables.h" +#include "content/browser/dom_storage/dom_storage_context_wrapper.h" +#include "content/browser/dom_storage/session_storage_namespace_impl.h" +#include "content/browser/renderer_host/render_view_host_factory.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/view_messages.h" +#include "content/public/browser/browser_context.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" +#include "content/public/browser/storage_partition.h" #include "content/public/common/content_switches.h" +#include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" #include "content/shell/browser/shell.h" #include "content/test/content_browser_test.h" @@ -15,6 +23,61 @@ namespace content { +namespace { + +// This is a helper function for the tests which attempt to create a +// duplicate RenderViewHost or RenderWidgetHost. It tries to create two objects +// with the same process and routing ids, which causes a collision. +// It creates a couple of windows in process 1, which causes a few routing ids +// to be allocated. Then a cross-process navigation is initiated, which causes a +// new process 2 to be created and have a pending RenderViewHost for it. The +// routing id of the RenderViewHost which is target for a duplicate is set +// into |target_routing_id| and the pending RenderViewHost which is used for +// the attempt is the return value. +RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell, + int* target_routing_id) { + GURL foo("http://foo.com/files/simple_page.html"); + + // Start off with initial navigation, so we get the first process allocated. + NavigateToURL(shell, foo); + + // Open another window, so we generate some more routing ids. + ShellAddedObserver shell2_observer; + EXPECT_TRUE(ExecuteScript( + shell->web_contents(), "window.open(document.URL + '#2');")); + Shell* shell2 = shell2_observer.GetShell(); + + // The new window must be in the same process, but have a new routing id. + EXPECT_EQ(shell->web_contents()->GetRenderViewHost()->GetProcess()->GetID(), + shell2->web_contents()->GetRenderViewHost()->GetProcess()->GetID()); + *target_routing_id = + shell2->web_contents()->GetRenderViewHost()->GetRoutingID(); + EXPECT_NE(*target_routing_id, + shell->web_contents()->GetRenderViewHost()->GetRoutingID()); + + // Now, simulate a link click coming from the renderer. + GURL extension_url("https://bar.com/files/simple_page.html"); + WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell->web_contents()); + wc->RequestOpenURL( + shell->web_contents()->GetRenderViewHost(), extension_url, + Referrer(), CURRENT_TAB, wc->GetFrameTree()->root()->frame_id(), + false, true); + + // Since the navigation above requires a cross-process swap, there will be a + // pending RenderViewHost. Ensure it exists and is in a different process + // than the initial page. + RenderViewHostImpl* pending_rvh = + wc->GetRenderManagerForTesting()->pending_render_view_host(); + EXPECT_TRUE(pending_rvh != NULL); + EXPECT_NE(shell->web_contents()->GetRenderViewHost()->GetProcess()->GetID(), + pending_rvh->GetProcess()->GetID()); + + return pending_rvh; +} + +} // namespace + + // The goal of these tests will be to "simulate" exploited renderer processes, // which can send arbitrary IPC messages and confuse browser process internal // state, leading to security bugs. We are trying to verify that the browser @@ -52,4 +115,54 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, SetWebUIProperty) { terminated.Wait(); } +// This is a test for crbug.com/312016 attempting to create duplicate +// RenderViewHosts. SetupForDuplicateHosts sets up this test case and leaves +// it in a state with pending RenderViewHost. Before the commit of the new +// pending RenderViewHost, this test case creates a new window through the new +// process. +IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, + AttemptDuplicateRenderViewHost) { + int duplicate_routing_id = MSG_ROUTING_NONE; + RenderViewHostImpl* pending_rvh = + PrepareToDuplicateHosts(shell(), &duplicate_routing_id); + EXPECT_NE(MSG_ROUTING_NONE, duplicate_routing_id); + + // Since this test executes on the UI thread and hopping threads might cause + // different timing in the test, let's simulate a CreateNewWindow call coming + // from the IO thread. + ViewHostMsg_CreateWindow_Params params; + DOMStorageContextWrapper* dom_storage_context = + static_cast<DOMStorageContextWrapper*>( + BrowserContext::GetStoragePartition( + shell()->web_contents()->GetBrowserContext(), + pending_rvh->GetSiteInstance())->GetDOMStorageContext()); + SessionStorageNamespaceImpl* session_storage = + new SessionStorageNamespaceImpl(dom_storage_context); + // Cause a deliberate collision in routing ids. + int main_frame_routing_id = duplicate_routing_id + 1; + pending_rvh->CreateNewWindow( + duplicate_routing_id, main_frame_routing_id, params, session_storage); + + // If the above operation doesn't cause a crash, the test has succeeded! } + +// This is a test for crbug.com/312016. It tries to create two RenderWidgetHosts +// with the same process and routing ids, which causes a collision. It is almost +// identical to the AttemptDuplicateRenderViewHost test case. +IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, + AttemptDuplicateRenderWidgetHost) { + int duplicate_routing_id = MSG_ROUTING_NONE; + RenderViewHostImpl* pending_rvh = + PrepareToDuplicateHosts(shell(), &duplicate_routing_id); + EXPECT_NE(MSG_ROUTING_NONE, duplicate_routing_id); + + // Since this test executes on the UI thread and hopping threads might cause + // different timing in the test, let's simulate a CreateNewWidget call coming + // from the IO thread. Use the existing window routing id to cause a + // deliberate collision. + pending_rvh->CreateNewWidget(duplicate_routing_id, blink::WebPopupTypeSelect); + + // If the above operation doesn't crash, the test has succeeded! +} + +} // namespace content diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc new file mode 100644 index 0000000000..0799884598 --- /dev/null +++ b/content/browser/service_worker/embedded_worker_instance.cc @@ -0,0 +1,99 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/service_worker/embedded_worker_instance.h" + +#include "content/browser/service_worker/embedded_worker_registry.h" +#include "url/gurl.h" + +namespace content { + +EmbeddedWorkerInstance::~EmbeddedWorkerInstance() { + registry_->RemoveWorker(embedded_worker_id_); +} + +bool EmbeddedWorkerInstance::Start( + int64 service_worker_version_id, + const GURL& script_url) { + DCHECK(status_ == STOPPED); + if (!ChooseProcess()) + return false; + status_ = STARTING; + bool success = registry_->StartWorker( + process_id_, + embedded_worker_id_, + service_worker_version_id, + script_url); + if (!success) { + status_ = STOPPED; + process_id_ = -1; + } + return success; +} + +bool EmbeddedWorkerInstance::Stop() { + DCHECK(status_ == STARTING || status_ == RUNNING); + const bool success = registry_->StopWorker(process_id_, embedded_worker_id_); + if (success) + status_ = STOPPING; + return success; +} + +void EmbeddedWorkerInstance::AddProcessReference(int process_id) { + ProcessRefMap::iterator found = process_refs_.find(process_id); + if (found == process_refs_.end()) + found = process_refs_.insert(std::make_pair(process_id, 0)).first; + ++found->second; +} + +void EmbeddedWorkerInstance::ReleaseProcessReference(int process_id) { + ProcessRefMap::iterator found = process_refs_.find(process_id); + if (found == process_refs_.end()) { + NOTREACHED() << "Releasing unknown process ref " << process_id; + return; + } + if (--found->second == 0) + process_refs_.erase(found); +} + +EmbeddedWorkerInstance::EmbeddedWorkerInstance( + EmbeddedWorkerRegistry* registry, + int embedded_worker_id) + : registry_(registry), + embedded_worker_id_(embedded_worker_id), + status_(STOPPED), + process_id_(-1), + thread_id_(-1) { +} + +void EmbeddedWorkerInstance::OnStarted(int thread_id) { + DCHECK(status_ == STARTING); + status_ = RUNNING; + thread_id_ = thread_id; +} + +void EmbeddedWorkerInstance::OnStopped() { + status_ = STOPPED; + process_id_ = -1; + thread_id_ = -1; +} + +bool EmbeddedWorkerInstance::ChooseProcess() { + DCHECK_EQ(-1, process_id_); + // Naive implementation; chooses a process which has the biggest number of + // associated providers (so that hopefully likely live longer). + ProcessRefMap::iterator max_ref_iter = process_refs_.end(); + for (ProcessRefMap::iterator iter = process_refs_.begin(); + iter != process_refs_.end(); ++iter) { + if (max_ref_iter == process_refs_.end() || + max_ref_iter->second < iter->second) + max_ref_iter = iter; + } + if (max_ref_iter == process_refs_.end()) + return false; + process_id_ = max_ref_iter->first; + return true; +} + +} // namespace content diff --git a/content/browser/service_worker/embedded_worker_instance.h b/content/browser/service_worker/embedded_worker_instance.h new file mode 100644 index 0000000000..fb0fe19bb6 --- /dev/null +++ b/content/browser/service_worker/embedded_worker_instance.h @@ -0,0 +1,102 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_H_ +#define CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_H_ + +#include <map> + +#include "base/basictypes.h" +#include "base/callback_forward.h" +#include "base/gtest_prod_util.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "content/common/content_export.h" + +class GURL; + +namespace content { + +class EmbeddedWorkerRegistry; + +// This gives an interface to control one EmbeddedWorker instance, which +// may be 'in-waiting' or running in one of the child processes added by +// AddProcessReference(). +class CONTENT_EXPORT EmbeddedWorkerInstance { + public: + enum Status { + STOPPED, + STARTING, + RUNNING, + STOPPING, + }; + + ~EmbeddedWorkerInstance(); + + // Starts the worker. It is invalid to call this when the worker is + // not in STOPPED status. + // This returns false if starting a worker fails immediately, e.g. when + // IPC couldn't be sent to the worker or no process was available. + bool Start(int64 service_worker_version_id, + const GURL& script_url); + + // Stops the worker. It is invalid to call this when the worker is + // not in STARTING or RUNNING status. + // This returns false if stopping a worker fails immediately, e.g. when + // IPC couldn't be sent to the worker. + bool Stop(); + + // Add or remove |process_id| to the internal process set where this + // worker can be started. + void AddProcessReference(int process_id); + void ReleaseProcessReference(int process_id); + + int embedded_worker_id() const { return embedded_worker_id_; } + Status status() const { return status_; } + int process_id() const { return process_id_; } + int thread_id() const { return thread_id_; } + + private: + friend class EmbeddedWorkerRegistry; + FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest, StartAndStop); + + typedef std::map<int, int> ProcessRefMap; + + // Constructor is called via EmbeddedWorkerRegistry::CreateWorker(). + // This instance holds a ref of |registry|. + EmbeddedWorkerInstance(EmbeddedWorkerRegistry* registry, + int embedded_worker_id); + + // Called back from Registry when the worker instance has ack'ed that + // its WorkerGlobalScope is actually started on |thread_id| in the + // child process. + // This will change the internal status from STARTING to RUNNING. + void OnStarted(int thread_id); + + // Called back from Registry when the worker instance has ack'ed that + // its WorkerGlobalScope is actually stopped in the child process. + // This will change the internal status from STARTING or RUNNING to + // STOPPED. + void OnStopped(); + + // Chooses a process to start this worker and populate process_id_. + // Returns false when no process is available. + bool ChooseProcess(); + + scoped_refptr<EmbeddedWorkerRegistry> registry_; + const int embedded_worker_id_; + Status status_; + + // Current running information. -1 indicates the worker is not running. + int process_id_; + int thread_id_; + + ProcessRefMap process_refs_; + + DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstance); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_H_ diff --git a/content/browser/service_worker/embedded_worker_instance_unittest.cc b/content/browser/service_worker/embedded_worker_instance_unittest.cc new file mode 100644 index 0000000000..45b2f29dc7 --- /dev/null +++ b/content/browser/service_worker/embedded_worker_instance_unittest.cc @@ -0,0 +1,137 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/basictypes.h" +#include "base/stl_util.h" +#include "content/browser/service_worker/embedded_worker_instance.h" +#include "content/browser/service_worker/embedded_worker_registry.h" +#include "content/browser/service_worker/service_worker_context_core.h" +#include "content/common/service_worker_messages.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "ipc/ipc_message.h" +#include "ipc/ipc_sender.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { + +namespace { + +typedef std::vector<IPC::Message*> MessageList; + +class FakeSender : public IPC::Sender { + public: + FakeSender() {} + virtual ~FakeSender() { + STLDeleteContainerPointers(sent_messages_.begin(), sent_messages_.end()); + } + + // IPC::Sender implementation. + virtual bool Send(IPC::Message* message) OVERRIDE { + sent_messages_.push_back(message); + return true; + } + + const MessageList& sent_messages() { return sent_messages_; } + + private: + MessageList sent_messages_; + DISALLOW_COPY_AND_ASSIGN(FakeSender); +}; + +} // namespace + +class EmbeddedWorkerInstanceTest : public testing::Test { + protected: + EmbeddedWorkerInstanceTest() + : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} + + virtual void SetUp() OVERRIDE { + context_.reset(new ServiceWorkerContextCore(base::FilePath(), NULL)); + } + + virtual void TearDown() OVERRIDE { + context_.reset(); + } + + EmbeddedWorkerRegistry* embedded_worker_registry() { + DCHECK(context_); + return context_->embedded_worker_registry(); + } + + TestBrowserThreadBundle thread_bundle_; + scoped_ptr<ServiceWorkerContextCore> context_; + + DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceTest); +}; + +TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) { + scoped_ptr<EmbeddedWorkerInstance> worker = + embedded_worker_registry()->CreateWorker(); + EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status()); + + FakeSender fake_sender; + const int process_id = 11; + const int thread_id = 33; + const int64 service_worker_version_id = 55L; + const GURL url("http://example.com/worker.js"); + + // This fails as we have no available process yet. + EXPECT_FALSE(worker->Start(service_worker_version_id, url)); + EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status()); + + // Simulate adding one process to the worker. + worker->AddProcessReference(process_id); + embedded_worker_registry()->AddChildProcessSender(process_id, &fake_sender); + + // Start should succeed. + EXPECT_TRUE(worker->Start(service_worker_version_id, url)); + EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status()); + + // Simulate an upcall from embedded worker to notify that it's started. + worker->OnStarted(thread_id); + EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status()); + EXPECT_EQ(process_id, worker->process_id()); + EXPECT_EQ(thread_id, worker->thread_id()); + + // Stop the worker. + EXPECT_TRUE(worker->Stop()); + EXPECT_EQ(EmbeddedWorkerInstance::STOPPING, worker->status()); + + // Simulate an upcall from embedded worker to notify that it's stopped. + worker->OnStopped(); + EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status()); + + // Verify that we've sent two messages to start and terminate the worker. + const MessageList& messages = fake_sender.sent_messages(); + ASSERT_EQ(2U, messages.size()); + ASSERT_EQ(ServiceWorkerMsg_StartWorker::ID, messages[0]->type()); + ASSERT_EQ(ServiceWorkerMsg_TerminateWorker::ID, messages[1]->type()); +} + +TEST_F(EmbeddedWorkerInstanceTest, ChooseProcess) { + scoped_ptr<EmbeddedWorkerInstance> worker = + embedded_worker_registry()->CreateWorker(); + EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status()); + + FakeSender fake_sender; + + // Simulate adding processes to the worker. + // Process 1 has 1 ref, 2 has 2 refs and 3 has 3 refs. + worker->AddProcessReference(1); + worker->AddProcessReference(2); + worker->AddProcessReference(2); + worker->AddProcessReference(3); + worker->AddProcessReference(3); + worker->AddProcessReference(3); + embedded_worker_registry()->AddChildProcessSender(1, &fake_sender); + embedded_worker_registry()->AddChildProcessSender(2, &fake_sender); + embedded_worker_registry()->AddChildProcessSender(3, &fake_sender); + + // Process 3 has the biggest # of references and it should be chosen. + EXPECT_TRUE(worker->Start(1L, GURL("http://example.com/worker.js"))); + EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status()); + EXPECT_EQ(3, worker->process_id()); +} + +} // namespace content diff --git a/content/browser/service_worker/embedded_worker_registry.cc b/content/browser/service_worker/embedded_worker_registry.cc new file mode 100644 index 0000000000..f8f0fbe7d5 --- /dev/null +++ b/content/browser/service_worker/embedded_worker_registry.cc @@ -0,0 +1,70 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/service_worker/embedded_worker_registry.h" + +#include "base/stl_util.h" +#include "content/browser/service_worker/embedded_worker_instance.h" +#include "content/browser/service_worker/service_worker_context_core.h" +#include "content/common/service_worker_messages.h" +#include "ipc/ipc_message.h" +#include "ipc/ipc_sender.h" + +namespace content { + +EmbeddedWorkerRegistry::EmbeddedWorkerRegistry( + base::WeakPtr<ServiceWorkerContextCore> context) + : context_(context), + next_embedded_worker_id_(0) {} + +scoped_ptr<EmbeddedWorkerInstance> EmbeddedWorkerRegistry::CreateWorker() { + scoped_ptr<EmbeddedWorkerInstance> worker( + new EmbeddedWorkerInstance(this, next_embedded_worker_id_)); + worker_map_[next_embedded_worker_id_++] = worker.get(); + return worker.Pass(); +} + +void EmbeddedWorkerRegistry::RemoveWorker(int embedded_worker_id) { + DCHECK(ContainsKey(worker_map_, embedded_worker_id)); + worker_map_.erase(embedded_worker_id); +} + +bool EmbeddedWorkerRegistry::StartWorker( + int process_id, + int embedded_worker_id, + int64 service_worker_version_id, + const GURL& script_url) { + return Send(process_id, + new ServiceWorkerMsg_StartWorker(embedded_worker_id, + service_worker_version_id, + script_url)); +} + +bool EmbeddedWorkerRegistry::StopWorker(int process_id, + int embedded_worker_id) { + return Send(process_id, + new ServiceWorkerMsg_TerminateWorker(embedded_worker_id)); +} + +void EmbeddedWorkerRegistry::AddChildProcessSender( + int process_id, IPC::Sender* sender) { + process_sender_map_[process_id] = sender; +} + +void EmbeddedWorkerRegistry::RemoveChildProcessSender(int process_id) { + process_sender_map_.erase(process_id); +} + +EmbeddedWorkerRegistry::~EmbeddedWorkerRegistry() {} + +bool EmbeddedWorkerRegistry::Send(int process_id, IPC::Message* message) { + if (!context_) + return false; + ProcessToSenderMap::iterator found = process_sender_map_.find(process_id); + if (found == process_sender_map_.end()) + return false; + return found->second->Send(message); +} + +} // namespace content diff --git a/content/browser/service_worker/embedded_worker_registry.h b/content/browser/service_worker/embedded_worker_registry.h new file mode 100644 index 0000000000..8860e374b5 --- /dev/null +++ b/content/browser/service_worker/embedded_worker_registry.h @@ -0,0 +1,77 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_REGISTRY_H_ +#define CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_REGISTRY_H_ + +#include <map> + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "content/common/content_export.h" + +class GURL; + +namespace IPC { +class Message; +class Sender; +} + +namespace content { + +class EmbeddedWorkerInstance; +class ServiceWorkerContextCore; + +// Acts as a thin stub between MessageFilter and each EmbeddedWorkerInstance, +// which sends/receives messages to/from each EmbeddedWorker in child process. +// +// Hangs off ServiceWorkerContextCore (its reference is also held by each +// EmbeddedWorkerInstance). Operated only on IO thread. +class CONTENT_EXPORT EmbeddedWorkerRegistry + : public NON_EXPORTED_BASE(base::RefCounted<EmbeddedWorkerRegistry>) { + public: + explicit EmbeddedWorkerRegistry( + base::WeakPtr<ServiceWorkerContextCore> context); + + // Creates and removes a new worker instance entry for bookkeeping. + // This doesn't actually start or stop the worker. + scoped_ptr<EmbeddedWorkerInstance> CreateWorker(); + void RemoveWorker(int embedded_worker_id); + + // Called from EmbeddedWorkerInstance, relayed to the child process. + bool StartWorker(int process_id, + int embedded_worker_id, + int64 service_worker_version_id, + const GURL& script_url); + bool StopWorker(int process_id, + int embedded_worker_id); + + // Keeps a map from process_id to sender information. + void AddChildProcessSender(int process_id, IPC::Sender* sender); + void RemoveChildProcessSender(int process_id); + + private: + friend class base::RefCounted<EmbeddedWorkerRegistry>; + + ~EmbeddedWorkerRegistry(); + bool Send(int process_id, IPC::Message* message); + + typedef std::map<int, EmbeddedWorkerInstance*> WorkerInstanceMap; + typedef std::map<int, IPC::Sender*> ProcessToSenderMap; + + base::WeakPtr<ServiceWorkerContextCore> context_; + + WorkerInstanceMap worker_map_; + ProcessToSenderMap process_sender_map_; + + int next_embedded_worker_id_; + + DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerRegistry); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_SERVICE_WORKER_EMBEDDED_WORKER_REGISTRY_H_ diff --git a/content/browser/service_worker/service_worker_context.h b/content/browser/service_worker/service_worker_context.h index ce8bad90c1..d9f51f3165 100644 --- a/content/browser/service_worker/service_worker_context.h +++ b/content/browser/service_worker/service_worker_context.h @@ -5,18 +5,22 @@ #ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_H_ #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_H_ +#include "base/basictypes.h" + namespace content { // Represents the per-BrowserContext ServiceWorker data. class ServiceWorkerContext { public: - // TODO(michaeln): This class is a place holder for content/public api // which will come later. Promote this class when we get there. protected: ServiceWorkerContext() {} virtual ~ServiceWorkerContext() {} + + private: + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContext); }; } // namespace content diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc index 22ae500705..8d1e7a8796 100644 --- a/content/browser/service_worker/service_worker_context_core.cc +++ b/content/browser/service_worker/service_worker_context_core.cc @@ -6,29 +6,25 @@ #include "base/command_line.h" #include "base/files/file_path.h" +#include "base/strings/string_util.h" +#include "content/browser/service_worker/embedded_worker_registry.h" #include "content/browser/service_worker/service_worker_provider_host.h" +#include "content/browser/service_worker/service_worker_register_job.h" +#include "content/browser/service_worker/service_worker_registration.h" +#include "content/browser/service_worker/service_worker_storage.h" +#include "content/public/browser/browser_thread.h" #include "content/public/common/content_switches.h" -#include "webkit/browser/quota/quota_manager.h" +#include "url/gurl.h" namespace content { -namespace { - -const base::FilePath::CharType kServiceWorkerDirectory[] = - FILE_PATH_LITERAL("ServiceWorker"); - -} // namespace - ServiceWorkerContextCore::ServiceWorkerContextCore( - const base::FilePath& user_data_directory, + const base::FilePath& path, quota::QuotaManagerProxy* quota_manager_proxy) - : quota_manager_proxy_(quota_manager_proxy) { - if (!user_data_directory.empty()) - path_ = user_data_directory.Append(kServiceWorkerDirectory); -} + : storage_(new ServiceWorkerStorage(path, quota_manager_proxy)), + embedded_worker_registry_(new EmbeddedWorkerRegistry(AsWeakPtr())) {} -ServiceWorkerContextCore::~ServiceWorkerContextCore() { -} +ServiceWorkerContextCore::~ServiceWorkerContextCore() {} ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost( int process_id, int provider_id) { @@ -67,4 +63,51 @@ bool ServiceWorkerContextCore::IsEnabled() { switches::kEnableServiceWorker); } +void ServiceWorkerContextCore::RegisterServiceWorker( + const GURL& pattern, + const GURL& script_url, + const RegistrationCallback& callback) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + storage_->Register(pattern, + script_url, + base::Bind(&ServiceWorkerContextCore::RegistrationComplete, + AsWeakPtr(), + callback)); +} + +void ServiceWorkerContextCore::UnregisterServiceWorker( + const GURL& pattern, + const UnregistrationCallback& callback) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + storage_->Unregister( + pattern, + base::Bind(&ServiceWorkerContextCore::UnregistrationComplete, + AsWeakPtr(), + callback)); +} + +void ServiceWorkerContextCore::RegistrationComplete( + const ServiceWorkerContextCore::RegistrationCallback& callback, + ServiceWorkerRegistrationStatus status, + const scoped_refptr<ServiceWorkerRegistration>& registration) { + if (status != REGISTRATION_OK) { + DCHECK(!registration); + callback.Run(status, -1L); + } + + callback.Run(status, registration->id()); +} + +void ServiceWorkerContextCore::UnregistrationComplete( + const UnregistrationCallback& callback, + ServiceWorkerRegistrationStatus status) { + // Unregistering a non-existent registration is a no-op. + if (status == REGISTRATION_OK || status == REGISTRATION_NOT_FOUND) + callback.Run(REGISTRATION_OK); + else + callback.Run(status); +} + } // namespace content diff --git a/content/browser/service_worker/service_worker_context_core.h b/content/browser/service_worker/service_worker_context_core.h index 8d6f44250d..0351c2e74e 100644 --- a/content/browser/service_worker/service_worker_context_core.h +++ b/content/browser/service_worker/service_worker_context_core.h @@ -5,13 +5,20 @@ #ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_CORE_H_ #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_CORE_H_ +#include <map> + +#include "base/callback.h" #include "base/files/file_path.h" #include "base/id_map.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "content/browser/service_worker/service_worker_provider_host.h" +#include "content/browser/service_worker/service_worker_registration_status.h" +#include "content/browser/service_worker/service_worker_storage.h" #include "content/common/content_export.h" +class GURL; + namespace base { class FilePath; } @@ -22,7 +29,10 @@ class QuotaManagerProxy; namespace content { +class EmbeddedWorkerRegistry; class ServiceWorkerProviderHost; +class ServiceWorkerRegistration; +class ServiceWorkerStorage; // This class manages data associated with service workers. // The class is single threaded and should only be used on the IO thread. @@ -33,11 +43,20 @@ class CONTENT_EXPORT ServiceWorkerContextCore : NON_EXPORTED_BASE( public base::SupportsWeakPtr<ServiceWorkerContextCore>) { public: - // Given an empty |user_data_directory|, nothing will be stored on disk. + typedef base::Callback<void(ServiceWorkerRegistrationStatus status, + int64 registration_id)> RegistrationCallback; + typedef base::Callback< + void(ServiceWorkerRegistrationStatus status)> UnregistrationCallback; + + // This is owned by the StoragePartition, which will supply it with + // the local path on disk. Given an empty |user_data_directory|, + // nothing will be stored on disk. ServiceWorkerContextCore(const base::FilePath& user_data_directory, quota::QuotaManagerProxy* quota_manager_proxy); ~ServiceWorkerContextCore(); + ServiceWorkerStorage* storage() { return storage_.get(); } + // The context class owns the set of ProviderHosts. ServiceWorkerProviderHost* GetProviderHost(int process_id, int provider_id); void AddProviderHost(scoped_ptr<ServiceWorkerProviderHost> provider_host); @@ -47,6 +66,19 @@ class CONTENT_EXPORT ServiceWorkerContextCore // Checks the cmdline flag. bool IsEnabled(); + // The callback will be called on the IO thread. + void RegisterServiceWorker(const GURL& pattern, + const GURL& script_url, + const RegistrationCallback& callback); + + // The callback will be called on the IO thread. + void UnregisterServiceWorker(const GURL& pattern, + const UnregistrationCallback& callback); + + EmbeddedWorkerRegistry* embedded_worker_registry() { + return embedded_worker_registry_.get(); + } + private: typedef IDMap<ServiceWorkerProviderHost, IDMapOwnPointer> ProviderMap; typedef IDMap<ProviderMap, IDMapOwnPointer> ProcessToProviderMap; @@ -55,9 +87,18 @@ class CONTENT_EXPORT ServiceWorkerContextCore return providers_.Lookup(process_id); } + void RegistrationComplete( + const RegistrationCallback& callback, + ServiceWorkerRegistrationStatus status, + const scoped_refptr<ServiceWorkerRegistration>& registration); + void UnregistrationComplete(const UnregistrationCallback& callback, + ServiceWorkerRegistrationStatus status); + ProcessToProviderMap providers_; - scoped_refptr<quota::QuotaManagerProxy> quota_manager_proxy_; - base::FilePath path_; + scoped_ptr<ServiceWorkerStorage> storage_; + scoped_refptr<EmbeddedWorkerRegistry> embedded_worker_registry_; + + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextCore); }; } // namespace content diff --git a/content/browser/service_worker/service_worker_context_unittest.cc b/content/browser/service_worker/service_worker_context_unittest.cc new file mode 100644 index 0000000000..e7c230f93a --- /dev/null +++ b/content/browser/service_worker/service_worker_context_unittest.cc @@ -0,0 +1,168 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/service_worker/service_worker_context.h" + +#include "base/files/scoped_temp_dir.h" +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "content/browser/browser_thread_impl.h" +#include "content/browser/service_worker/service_worker_context_core.h" +#include "content/browser/service_worker/service_worker_registration.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "content/public/test/test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { + +namespace { + +void SaveResponseCallback(bool* called, + int64* store_result, + ServiceWorkerRegistrationStatus status, + int64 result) { + *called = true; + *store_result = result; +} + +ServiceWorkerContextCore::RegistrationCallback MakeRegisteredCallback( + bool* called, + int64* store_result) { + return base::Bind(&SaveResponseCallback, called, store_result); +} + +void CallCompletedCallback(bool* called, ServiceWorkerRegistrationStatus) { + *called = true; +} + +ServiceWorkerContextCore::UnregistrationCallback MakeUnregisteredCallback( + bool* called) { + return base::Bind(&CallCompletedCallback, called); +} + +} // namespace + +class ServiceWorkerContextTest : public testing::Test { + public: + ServiceWorkerContextTest() + : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} + + virtual void SetUp() OVERRIDE { + context_.reset(new ServiceWorkerContextCore(base::FilePath(), NULL)); + } + + virtual void TearDown() OVERRIDE { context_.reset(); } + + protected: + TestBrowserThreadBundle browser_thread_bundle_; + scoped_ptr<ServiceWorkerContextCore> context_; +}; + +void RegistrationCallback( + scoped_refptr<ServiceWorkerRegistration>* registration, + const scoped_refptr<ServiceWorkerRegistration>& result) { + *registration = result; +} + +// Make sure basic registration is working. +TEST_F(ServiceWorkerContextTest, Register) { + int64 registration_id = -1L; + bool called = false; + context_->RegisterServiceWorker( + GURL("http://www.example.com/*"), + GURL("http://www.example.com/service_worker.js"), + MakeRegisteredCallback(&called, ®istration_id)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + ASSERT_NE(-1L, registration_id); +} + +// Make sure registrations are cleaned up when they are unregistered. +TEST_F(ServiceWorkerContextTest, Unregister) { + GURL pattern("http://www.example.com/*"); + + bool called = false; + int64 registration_id = -1L; + context_->RegisterServiceWorker( + pattern, + GURL("http://www.example.com/service_worker.js"), + MakeRegisteredCallback(&called, ®istration_id)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + called = false; + context_->UnregisterServiceWorker(pattern, MakeUnregisteredCallback(&called)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); +} + +// Make sure that when a new registration replaces an existing +// registration, that the old one is cleaned up. +TEST_F(ServiceWorkerContextTest, RegisterNewScript) { + GURL pattern("http://www.example.com/*"); + + bool called = false; + int64 old_registration_id = -1L; + context_->RegisterServiceWorker( + pattern, + GURL("http://www.example.com/service_worker.js"), + MakeRegisteredCallback(&called, &old_registration_id)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + called = false; + int64 new_registration_id = -1L; + context_->RegisterServiceWorker( + pattern, + GURL("http://www.example.com/service_worker_new.js"), + MakeRegisteredCallback(&called, &new_registration_id)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + ASSERT_NE(old_registration_id, new_registration_id); +} + +// Make sure that when registering a duplicate pattern+script_url +// combination, that the same registration is used. +TEST_F(ServiceWorkerContextTest, RegisterDuplicateScript) { + GURL pattern("http://www.example.com/*"); + GURL script_url("http://www.example.com/service_worker.js"); + + bool called = false; + int64 old_registration_id = -1L; + context_->RegisterServiceWorker( + pattern, + script_url, + MakeRegisteredCallback(&called, &old_registration_id)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + called = false; + int64 new_registration_id = -1L; + context_->RegisterServiceWorker( + pattern, + script_url, + MakeRegisteredCallback(&called, &new_registration_id)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + ASSERT_EQ(old_registration_id, new_registration_id); +} + +} // namespace content diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc index 696c5c1867..9f6b139f93 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.cc +++ b/content/browser/service_worker/service_worker_dispatcher_host.cc @@ -5,6 +5,7 @@ #include "content/browser/service_worker/service_worker_dispatcher_host.h" #include "base/strings/utf_string_conversions.h" +#include "content/browser/service_worker/embedded_worker_registry.h" #include "content/browser/service_worker/service_worker_context_core.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_provider_host.h" @@ -37,8 +38,11 @@ ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost( } ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() { - if (context_) + if (context_) { context_->RemoveAllProviderHostsForProcess(render_process_id_); + context_->embedded_worker_registry()->RemoveChildProcessSender( + render_process_id_); + } } void ServiceWorkerDispatcherHost::Init( @@ -51,6 +55,8 @@ void ServiceWorkerDispatcherHost::Init( return; } context_ = context_wrapper->context()->AsWeakPtr(); + context_->embedded_worker_registry()->AddChildProcessSender( + render_process_id_, this); } void ServiceWorkerDispatcherHost::OnDestruct() const { @@ -83,7 +89,7 @@ bool ServiceWorkerDispatcherHost::OnMessageReceived( void ServiceWorkerDispatcherHost::OnRegisterServiceWorker( int32 thread_id, int32 request_id, - const GURL& scope, + const GURL& pattern, const GURL& script_url) { if (!context_ || !context_->IsEnabled()) { Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError( @@ -97,7 +103,7 @@ void ServiceWorkerDispatcherHost::OnRegisterServiceWorker( // TODO(alecflett): This check is insufficient for release. Add a // ServiceWorker-specific policy query in // ChildProcessSecurityImpl. See http://crbug.com/311631. - if (scope.GetOrigin() != script_url.GetOrigin()) { + if (pattern.GetOrigin() != script_url.GetOrigin()) { Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError( thread_id, request_id, @@ -110,9 +116,10 @@ void ServiceWorkerDispatcherHost::OnRegisterServiceWorker( thread_id, request_id, NextWorkerId())); } -void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(int32 thread_id, - int32 request_id, - const GURL& scope) { +void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker( + int32 thread_id, + int32 request_id, + const GURL& pattern) { // TODO(alecflett): This check is insufficient for release. Add a // ServiceWorker-specific policy query in // ChildProcessSecurityImpl. See http://crbug.com/311631. diff --git a/content/browser/service_worker/service_worker_dispatcher_host.h b/content/browser/service_worker/service_worker_dispatcher_host.h index bb0abf81f7..563e733d3e 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.h +++ b/content/browser/service_worker/service_worker_dispatcher_host.h @@ -38,11 +38,11 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter { // IPC Message handlers void OnRegisterServiceWorker(int32 thread_id, int32 request_id, - const GURL& scope, + const GURL& pattern, const GURL& script_url); void OnUnregisterServiceWorker(int32 thread_id, int32 request_id, - const GURL& scope); + const GURL& pattern); void OnProviderCreated(int provider_id); void OnProviderDestroyed(int provider_id); diff --git a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc index 2276a5aceb..dd50c9149e 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc +++ b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. diff --git a/content/browser/service_worker/service_worker_register_job.cc b/content/browser/service_worker/service_worker_register_job.cc new file mode 100644 index 0000000000..51ae40ff6a --- /dev/null +++ b/content/browser/service_worker/service_worker_register_job.cc @@ -0,0 +1,118 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/service_worker/service_worker_register_job.h" + +#include "content/browser/service_worker/service_worker_registration.h" +#include "content/public/browser/browser_thread.h" +#include "url/gurl.h" + +namespace content { + +ServiceWorkerRegisterJob::ServiceWorkerRegisterJob( + const base::WeakPtr<ServiceWorkerStorage>& storage, + const RegistrationCompleteCallback& callback) + : storage_(storage), callback_(callback), weak_factory_(this) {} + +ServiceWorkerRegisterJob::~ServiceWorkerRegisterJob() {} + +void ServiceWorkerRegisterJob::StartRegister(const GURL& pattern, + const GURL& script_url) { + // Set up a chain of callbacks, in reverse order. Each of these + // callbacks may be called asynchronously by the previous callback. + ServiceWorkerStorage::RegistrationCallback finish_registration(base::Bind( + &ServiceWorkerRegisterJob::RegisterComplete, weak_factory_.GetWeakPtr())); + + ServiceWorkerStorage::UnregistrationCallback register_new( + base::Bind(&ServiceWorkerRegisterJob::RegisterPatternAndContinue, + weak_factory_.GetWeakPtr(), + pattern, + script_url, + finish_registration)); + + ServiceWorkerStorage::RegistrationCallback unregister_old( + base::Bind(&ServiceWorkerRegisterJob::UnregisterPatternAndContinue, + weak_factory_.GetWeakPtr(), + pattern, + script_url, + register_new)); + + storage_->FindRegistrationForPattern(pattern, unregister_old); +} + +void ServiceWorkerRegisterJob::StartUnregister(const GURL& pattern) { + // Set up a chain of callbacks, in reverse order. Each of these + // callbacks may be called asynchronously by the previous callback. + ServiceWorkerStorage::UnregistrationCallback finish_unregistration( + base::Bind(&ServiceWorkerRegisterJob::UnregisterComplete, + weak_factory_.GetWeakPtr())); + + ServiceWorkerStorage::RegistrationCallback unregister( + base::Bind(&ServiceWorkerRegisterJob::UnregisterPatternAndContinue, + weak_factory_.GetWeakPtr(), + pattern, + GURL(), + finish_unregistration)); + + storage_->FindRegistrationForPattern(pattern, unregister); +} + +void ServiceWorkerRegisterJob::RegisterPatternAndContinue( + const GURL& pattern, + const GURL& script_url, + const ServiceWorkerStorage::RegistrationCallback& callback, + ServiceWorkerRegistrationStatus previous_status) { + if (previous_status != REGISTRATION_OK && + previous_status != REGISTRATION_NOT_FOUND) { + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(callback, + previous_status, + scoped_refptr<ServiceWorkerRegistration>())); + } + + // TODO: Eventually RegisterInternal will be replaced by an asynchronous + // operation. Pass its resulting status through 'callback'. + scoped_refptr<ServiceWorkerRegistration> registration = + storage_->RegisterInternal(pattern, script_url); + BrowserThread::PostTask(BrowserThread::IO, + FROM_HERE, + base::Bind(callback, REGISTRATION_OK, registration)); +} + +void ServiceWorkerRegisterJob::UnregisterPatternAndContinue( + const GURL& pattern, + const GURL& new_script_url, + const ServiceWorkerStorage::UnregistrationCallback& callback, + ServiceWorkerRegistrationStatus previous_status, + const scoped_refptr<ServiceWorkerRegistration>& previous_registration) { + DCHECK(previous_status == REGISTRATION_OK || + previous_status == REGISTRATION_NOT_FOUND); + + // The previous registration may not exist, which is ok. + if (previous_status == REGISTRATION_OK && + (new_script_url.is_empty() || + previous_registration->script_url() != new_script_url)) { + // TODO: Eventually UnregisterInternal will be replaced by an + // asynchronous operation. Pass its resulting status though + // 'callback'. + storage_->UnregisterInternal(pattern); + } + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, base::Bind(callback, previous_status)); +} + +void ServiceWorkerRegisterJob::UnregisterComplete( + ServiceWorkerRegistrationStatus status) { + callback_.Run(this, status, NULL); +} + +void ServiceWorkerRegisterJob::RegisterComplete( + ServiceWorkerRegistrationStatus status, + const scoped_refptr<ServiceWorkerRegistration>& registration) { + callback_.Run(this, status, registration); +} + +} // namespace content diff --git a/content/browser/service_worker/service_worker_register_job.h b/content/browser/service_worker/service_worker_register_job.h new file mode 100644 index 0000000000..f1e35d0709 --- /dev/null +++ b/content/browser/service_worker/service_worker_register_job.h @@ -0,0 +1,79 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTER_JOB_H_ +#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTER_JOB_H_ + +#include "base/memory/weak_ptr.h" +#include "content/browser/service_worker/service_worker_registration_status.h" +#include "content/browser/service_worker/service_worker_storage.h" + +namespace content { + +// A ServiceWorkerRegisterJob lives only for the lifetime of a single +// registration or unregistration. +class ServiceWorkerRegisterJob { + public: + typedef base::Callback<void( + ServiceWorkerRegisterJob* job, + ServiceWorkerRegistrationStatus status, + ServiceWorkerRegistration* registration)> RegistrationCompleteCallback; + + // All type of jobs (Register and Unregister) complete through a + // single call to this callback on the IO thread. + ServiceWorkerRegisterJob(const base::WeakPtr<ServiceWorkerStorage>& storage, + const RegistrationCompleteCallback& callback); + ~ServiceWorkerRegisterJob(); + + // The Registration flow includes most or all of the following, + // depending on what is already registered: + // - creating a ServiceWorkerRegistration instance if there isn't + // already something registered + // - creating a ServiceWorkerVersion for the new registration instance. + // - starting a worker for the ServiceWorkerVersion + // - telling the Version to evaluate the script + // - firing the 'install' event at the ServiceWorkerVersion + // - firing the 'activate' event at the ServiceWorkerVersion + // - Waiting for older ServiceWorkerVersions to deactivate + // - designating the new version to be the 'active' version + // This method should be called once and only once per job. + void StartRegister(const GURL& pattern, const GURL& script_url); + + // The Unregistration process is primarily cleanup, removing + // everything that was created during the Registration process, + // including the ServiceWorkerRegistration itself. + // This method should be called once and only once per job. + void StartUnregister(const GURL& pattern); + + private: + // These are all steps in the registration and unregistration pipeline. + void RegisterPatternAndContinue( + const GURL& pattern, + const GURL& script_url, + const ServiceWorkerStorage::RegistrationCallback& callback, + ServiceWorkerRegistrationStatus previous_status); + + void UnregisterPatternAndContinue( + const GURL& pattern, + const GURL& script_url, + const ServiceWorkerStorage::UnregistrationCallback& callback, + ServiceWorkerRegistrationStatus previous_status, + const scoped_refptr<ServiceWorkerRegistration>& previous_registration); + + // These methods are the last internal callback in the callback + // chain, and ultimately call callback_. + void UnregisterComplete(ServiceWorkerRegistrationStatus status); + void RegisterComplete( + ServiceWorkerRegistrationStatus status, + const scoped_refptr<ServiceWorkerRegistration>& registration); + + const base::WeakPtr<ServiceWorkerStorage> storage_; + const RegistrationCompleteCallback callback_; + base::WeakPtrFactory<ServiceWorkerRegisterJob> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegisterJob); +}; +} // namespace content + +#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTER_JOB_H_ diff --git a/content/browser/service_worker/service_worker_registration_status.h b/content/browser/service_worker/service_worker_registration_status.h new file mode 100644 index 0000000000..82ab553ad1 --- /dev/null +++ b/content/browser/service_worker/service_worker_registration_status.h @@ -0,0 +1,21 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_STATUS_H_ +#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_STATUS_H_ + +namespace content { + +// This enum is used to describe the final state of a ServiceWorkerRegistration. +enum ServiceWorkerRegistrationStatus { + REGISTRATION_OK, + REGISTRATION_NOT_FOUND, + REGISTRATION_INSTALL_FAILED, + REGISTRATION_ACTIVATE_FAILED, + REGISTRATION_FAILED, +}; + +} // namespace content + +#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_STATUS_H_ diff --git a/content/browser/service_worker/service_worker_registration_unittest.cc b/content/browser/service_worker/service_worker_registration_unittest.cc index 1ad7895b7b..3fb6611a2f 100644 --- a/content/browser/service_worker/service_worker_registration_unittest.cc +++ b/content/browser/service_worker/service_worker_registration_unittest.cc @@ -26,7 +26,8 @@ class ServiceWorkerRegistrationTest : public testing::Test { }; TEST_F(ServiceWorkerRegistrationTest, Shutdown) { - int64 registration_id = -1L; + const int64 registration_id = -1L; + const int64 version_id = -1L; scoped_refptr<ServiceWorkerRegistration> registration = new ServiceWorkerRegistration( GURL("http://www.example.com/*"), @@ -34,7 +35,7 @@ TEST_F(ServiceWorkerRegistrationTest, Shutdown) { registration_id); scoped_refptr<ServiceWorkerVersion> active_version = - new ServiceWorkerVersion(registration); + new ServiceWorkerVersion(registration, NULL, version_id); registration->set_active_version(active_version); registration->Shutdown(); @@ -54,12 +55,14 @@ TEST_F(ServiceWorkerRegistrationTest, ActivatePending) { GURL("http://www.example.com/service_worker.js"), registration_id); + const int64 version_1_id = 1L; + const int64 version_2_id = 2L; scoped_refptr<ServiceWorkerVersion> version_1 = - new ServiceWorkerVersion(registration); + new ServiceWorkerVersion(registration, NULL, version_1_id); registration->set_active_version(version_1); scoped_refptr<ServiceWorkerVersion> version_2 = - new ServiceWorkerVersion(registration); + new ServiceWorkerVersion(registration, NULL, version_2_id); registration->set_pending_version(version_2); registration->ActivatePendingVersion(); diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc new file mode 100644 index 0000000000..dc8c7b1f45 --- /dev/null +++ b/content/browser/service_worker/service_worker_storage.cc @@ -0,0 +1,190 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/service_worker/service_worker_storage.h" + +#include <string> + +#include "base/strings/string_util.h" +#include "content/browser/service_worker/service_worker_register_job.h" +#include "content/browser/service_worker/service_worker_registration.h" +#include "content/public/browser/browser_thread.h" +#include "webkit/browser/quota/quota_manager.h" + +namespace { +// This is temporary until we figure out how registration ids will be +// calculated. +int64 NextRegistrationId() { + static int64 worker_id = 0; + return worker_id++; +} +} // namespace + +namespace content { + +const base::FilePath::CharType kServiceWorkerDirectory[] = + FILE_PATH_LITERAL("ServiceWorker"); + +ServiceWorkerStorage::ServiceWorkerStorage( + const base::FilePath& path, + quota::QuotaManagerProxy* quota_manager_proxy) + : quota_manager_proxy_(quota_manager_proxy), weak_factory_(this) { + if (!path.empty()) + path_ = path.Append(kServiceWorkerDirectory); +} + +ServiceWorkerStorage::~ServiceWorkerStorage() { + for (PatternToRegistrationMap::const_iterator iter = + registration_by_pattern_.begin(); + iter != registration_by_pattern_.end(); + ++iter) { + iter->second->Shutdown(); + } + registration_by_pattern_.clear(); +} + +void ServiceWorkerStorage::FindRegistrationForPattern( + const GURL& pattern, + const RegistrationCallback& callback) { + PatternToRegistrationMap::const_iterator match = + registration_by_pattern_.find(pattern); + if (match == registration_by_pattern_.end()) { + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(callback, + REGISTRATION_NOT_FOUND, + scoped_refptr<ServiceWorkerRegistration>())); + return; + } + BrowserThread::PostTask(BrowserThread::IO, + FROM_HERE, + base::Bind(callback, REGISTRATION_OK, match->second)); +} + +void ServiceWorkerStorage::FindRegistrationForDocument( + const GURL& document_url, + const RegistrationCallback& callback) { + // TODO(alecflett): This needs to be synchronous in the fast path, + // but asynchronous in the slow path (when the patterns have to be + // loaded from disk). For now it is always pessimistically async. + for (PatternToRegistrationMap::const_iterator it = + registration_by_pattern_.begin(); + it != registration_by_pattern_.end(); + ++it) { + if (PatternMatches(it->first, document_url)) { + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(callback, + REGISTRATION_OK, + scoped_refptr<ServiceWorkerRegistration>(it->second))); + return; + } + } + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(callback, + REGISTRATION_NOT_FOUND, + scoped_refptr<ServiceWorkerRegistration>())); +} + +void ServiceWorkerStorage::Register(const GURL& pattern, + const GURL& script_url, + const RegistrationCallback& callback) { + scoped_ptr<ServiceWorkerRegisterJob> job(new ServiceWorkerRegisterJob( + weak_factory_.GetWeakPtr(), + base::Bind(&ServiceWorkerStorage::RegisterComplete, + weak_factory_.GetWeakPtr(), + callback))); + job->StartRegister(pattern, script_url); + registration_jobs_.push_back(job.release()); +} + +void ServiceWorkerStorage::Unregister(const GURL& pattern, + const UnregistrationCallback& callback) { + scoped_ptr<ServiceWorkerRegisterJob> job(new ServiceWorkerRegisterJob( + weak_factory_.GetWeakPtr(), + base::Bind(&ServiceWorkerStorage::UnregisterComplete, + weak_factory_.GetWeakPtr(), + callback))); + job->StartUnregister(pattern); + registration_jobs_.push_back(job.release()); +} + +scoped_refptr<ServiceWorkerRegistration> ServiceWorkerStorage::RegisterInternal( + const GURL& pattern, + const GURL& script_url) { + + PatternToRegistrationMap::const_iterator current( + registration_by_pattern_.find(pattern)); + DCHECK(current == registration_by_pattern_.end() || + current->second->script_url() == script_url); + + if (current == registration_by_pattern_.end()) { + scoped_refptr<ServiceWorkerRegistration> registration( + new ServiceWorkerRegistration( + pattern, script_url, NextRegistrationId())); + // TODO(alecflett): version upgrade path. + registration_by_pattern_[pattern] = registration; + return registration; + } + + return current->second; +} + +void ServiceWorkerStorage::UnregisterInternal(const GURL& pattern) { + PatternToRegistrationMap::iterator match = + registration_by_pattern_.find(pattern); + if (match != registration_by_pattern_.end()) { + match->second->Shutdown(); + registration_by_pattern_.erase(match); + } +} + +bool ServiceWorkerStorage::PatternMatches(const GURL& pattern, + const GURL& url) { + // This is a really basic, naive + // TODO(alecflett): Formalize what pattern matches mean. + // Temporarily borrowed directly from appcache::Namespace::IsMatch(). + // We have to escape '?' characters since MatchPattern also treats those + // as wildcards which we don't want here, we only do '*'s. + std::string pattern_spec(pattern.spec()); + if (pattern.has_query()) + ReplaceSubstringsAfterOffset(&pattern_spec, 0, "?", "\\?"); + return MatchPattern(url.spec(), pattern_spec); +} + +void ServiceWorkerStorage::EraseJob(ServiceWorkerRegisterJob* job) { + ScopedVector<ServiceWorkerRegisterJob>::iterator job_position = + registration_jobs_.begin(); + for (; job_position != registration_jobs_.end(); ++job_position) { + if (*job_position == job) { + registration_jobs_.erase(job_position); + return; + } + } + NOTREACHED() << "Deleting non-existent job. "; +} + +void ServiceWorkerStorage::UnregisterComplete( + const UnregistrationCallback& callback, + ServiceWorkerRegisterJob* job, + ServiceWorkerRegistrationStatus status, + ServiceWorkerRegistration* previous_registration) { + callback.Run(status); + EraseJob(job); +} + +void ServiceWorkerStorage::RegisterComplete( + const RegistrationCallback& callback, + ServiceWorkerRegisterJob* job, + ServiceWorkerRegistrationStatus status, + ServiceWorkerRegistration* registration) { + callback.Run(status, registration); + EraseJob(job); +} + +} // namespace content diff --git a/content/browser/service_worker/service_worker_storage.h b/content/browser/service_worker/service_worker_storage.h new file mode 100644 index 0000000000..d700ee225b --- /dev/null +++ b/content/browser/service_worker/service_worker_storage.h @@ -0,0 +1,102 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_STORAGE_H_ +#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_STORAGE_H_ + +#include <map> + +#include "base/bind.h" +#include "base/files/file_path.h" +#include "base/gtest_prod_util.h" +#include "base/memory/scoped_vector.h" +#include "content/browser/service_worker/service_worker_registration_status.h" +#include "content/common/content_export.h" +#include "url/gurl.h" + +namespace quota { +class QuotaManagerProxy; +} + +namespace content { + +class ServiceWorkerRegistration; +class ServiceWorkerRegisterJob; + +// This class provides an interface to load registration data and +// instantiate ServiceWorkerRegistration objects. Any asynchronous +// operations are run through instances of ServiceWorkerRegisterJob. +class CONTENT_EXPORT ServiceWorkerStorage { + public: + ServiceWorkerStorage(const base::FilePath& path, + quota::QuotaManagerProxy* quota_manager_proxy); + ~ServiceWorkerStorage(); + + typedef base::Callback<void(ServiceWorkerRegistrationStatus status, + const scoped_refptr<ServiceWorkerRegistration>& + registration)> RegistrationCallback; + typedef base::Callback< + void(ServiceWorkerRegistrationStatus status)> UnregistrationCallback; + + void FindRegistrationForDocument(const GURL& document_url, + const RegistrationCallback& callback); + void FindRegistrationForPattern(const GURL& pattern, + const RegistrationCallback& callback); + + void Register(const GURL& pattern, + const GURL& script_url, + const RegistrationCallback& callback); + + void Unregister(const GURL& pattern, const UnregistrationCallback& callback); + + private: + friend class ServiceWorkerRegisterJob; + FRIEND_TEST_ALL_PREFIXES(ServiceWorkerStorageTest, PatternMatches); + + typedef std::map<GURL, scoped_refptr<ServiceWorkerRegistration> > + PatternToRegistrationMap; + typedef ScopedVector<ServiceWorkerRegisterJob> RegistrationJobList; + + // TODO(alecflett): These are temporary internal methods providing + // synchronous in-memory registration. Eventually these will be + // replaced by asynchronous methods that persist registration to disk. + scoped_refptr<ServiceWorkerRegistration> RegisterInternal( + const GURL& pattern, + const GURL& script_url); + void UnregisterInternal(const GURL& pattern); + static bool PatternMatches(const GURL& pattern, const GURL& script_url); + + // Jobs are removed whenever they are finished or canceled. + void EraseJob(ServiceWorkerRegisterJob* job); + + // Called at ServiceWorkerRegisterJob completion. + void RegisterComplete(const RegistrationCallback& callback, + ServiceWorkerRegisterJob* job, + ServiceWorkerRegistrationStatus status, + ServiceWorkerRegistration* registration); + + // Called at ServiceWorkerRegisterJob completion. + void UnregisterComplete(const UnregistrationCallback& callback, + ServiceWorkerRegisterJob* job, + ServiceWorkerRegistrationStatus status, + ServiceWorkerRegistration* registration); + + // This is the in-memory registration. Eventually the registration will be + // persisted to disk. + // A list of currently running jobs. This is a temporary structure until we + // start managing overlapping registrations explicitly. + RegistrationJobList registration_jobs_; + + // in-memory map, to eventually be replaced with persistence + PatternToRegistrationMap registration_by_pattern_; + scoped_refptr<quota::QuotaManagerProxy> quota_manager_proxy_; + base::FilePath path_; + base::WeakPtrFactory<ServiceWorkerStorage> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerStorage); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_STORAGE_H_ diff --git a/content/browser/service_worker/service_worker_storage_unittest.cc b/content/browser/service_worker/service_worker_storage_unittest.cc new file mode 100644 index 0000000000..e82ff3c1d8 --- /dev/null +++ b/content/browser/service_worker/service_worker_storage_unittest.cc @@ -0,0 +1,354 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/service_worker/service_worker_storage.h" + +#include "base/files/scoped_temp_dir.h" +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "content/browser/browser_thread_impl.h" +#include "content/browser/service_worker/service_worker_registration.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "content/public/test/test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { + +namespace { + +void SaveRegistrationCallback( + ServiceWorkerRegistrationStatus expected_status, + bool* called, + scoped_refptr<ServiceWorkerRegistration>* registration, + ServiceWorkerRegistrationStatus status, + const scoped_refptr<ServiceWorkerRegistration>& result) { + EXPECT_EQ(expected_status, status); + *called = true; + *registration = result; +} + +// Creates a callback which both keeps track of if it's been called, +// as well as the resulting registration. Whent the callback is fired, +// it ensures that the resulting status matches the expectation. +// 'called' is useful for making sure a sychronous callback is or +// isn't called. +ServiceWorkerStorage::RegistrationCallback SaveRegistration( + ServiceWorkerRegistrationStatus expected_status, + bool* called, + scoped_refptr<ServiceWorkerRegistration>* registration) { + *called = false; + return base::Bind( + &SaveRegistrationCallback, expected_status, called, registration); +} + +void SaveUnregistrationCallback(ServiceWorkerRegistrationStatus expected_status, + bool* called, + ServiceWorkerRegistrationStatus status) { + EXPECT_EQ(expected_status, status); + *called = true; +} + +ServiceWorkerStorage::UnregistrationCallback SaveUnregistration( + ServiceWorkerRegistrationStatus expected_status, + bool* called) { + *called = false; + return base::Bind(&SaveUnregistrationCallback, expected_status, called); +} + +} // namespace + +class ServiceWorkerStorageTest : public testing::Test { + public: + ServiceWorkerStorageTest() + : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} + + virtual void SetUp() OVERRIDE { + storage_.reset(new ServiceWorkerStorage(base::FilePath(), NULL)); + } + + virtual void TearDown() OVERRIDE { storage_.reset(); } + + protected: + TestBrowserThreadBundle browser_thread_bundle_; + scoped_ptr<ServiceWorkerStorage> storage_; +}; + +TEST_F(ServiceWorkerStorageTest, PatternMatches) { + ASSERT_TRUE(ServiceWorkerStorage::PatternMatches( + GURL("http://www.example.com/*"), GURL("http://www.example.com/"))); + ASSERT_TRUE(ServiceWorkerStorage::PatternMatches( + GURL("http://www.example.com/*"), + GURL("http://www.example.com/page.html"))); + + ASSERT_FALSE(ServiceWorkerStorage::PatternMatches( + GURL("http://www.example.com/*"), GURL("https://www.example.com/"))); + ASSERT_FALSE(ServiceWorkerStorage::PatternMatches( + GURL("http://www.example.com/*"), + GURL("https://www.example.com/page.html"))); + + ASSERT_FALSE(ServiceWorkerStorage::PatternMatches( + GURL("http://www.example.com/*"), GURL("http://www.foo.com/"))); + ASSERT_FALSE(ServiceWorkerStorage::PatternMatches( + GURL("http://www.example.com/*"), GURL("https://www.foo.com/page.html"))); +} + +TEST_F(ServiceWorkerStorageTest, SameDocumentSameRegistration) { + scoped_refptr<ServiceWorkerRegistration> original_registration; + bool called; + storage_->Register( + GURL("http://www.example.com/*"), + GURL("http://www.example.com/service_worker.js"), + SaveRegistration(REGISTRATION_OK, &called, &original_registration)); + EXPECT_FALSE(called); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(called); + + scoped_refptr<ServiceWorkerRegistration> registration1; + storage_->FindRegistrationForDocument( + GURL("http://www.example.com/"), + SaveRegistration(REGISTRATION_OK, &called, ®istration1)); + scoped_refptr<ServiceWorkerRegistration> registration2; + storage_->FindRegistrationForDocument( + GURL("http://www.example.com/"), + SaveRegistration(REGISTRATION_OK, &called, ®istration2)); + + ServiceWorkerRegistration* null_registration(NULL); + ASSERT_EQ(null_registration, registration1); + ASSERT_EQ(null_registration, registration2); + EXPECT_FALSE(called); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(called); + ASSERT_NE(null_registration, registration1); + ASSERT_NE(null_registration, registration2); + + ASSERT_EQ(registration1, registration2); +} + +TEST_F(ServiceWorkerStorageTest, SameMatchSameRegistration) { + bool called; + scoped_refptr<ServiceWorkerRegistration> original_registration; + storage_->Register( + GURL("http://www.example.com/*"), + GURL("http://www.example.com/service_worker.js"), + SaveRegistration(REGISTRATION_OK, &called, &original_registration)); + EXPECT_FALSE(called); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(called); + ASSERT_NE(static_cast<ServiceWorkerRegistration*>(NULL), + original_registration.get()); + + scoped_refptr<ServiceWorkerRegistration> registration1; + storage_->FindRegistrationForDocument( + GURL("http://www.example.com/one"), + SaveRegistration(REGISTRATION_OK, &called, ®istration1)); + + EXPECT_FALSE(called); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(called); + + scoped_refptr<ServiceWorkerRegistration> registration2; + storage_->FindRegistrationForDocument( + GURL("http://www.example.com/two"), + SaveRegistration(REGISTRATION_OK, &called, ®istration2)); + EXPECT_FALSE(called); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(called); + + ASSERT_EQ(registration1, registration2); +} + +TEST_F(ServiceWorkerStorageTest, DifferentMatchDifferentRegistration) { + bool called1; + scoped_refptr<ServiceWorkerRegistration> original_registration1; + storage_->Register( + GURL("http://www.example.com/one/*"), + GURL("http://www.example.com/service_worker.js"), + SaveRegistration(REGISTRATION_OK, &called1, &original_registration1)); + + bool called2; + scoped_refptr<ServiceWorkerRegistration> original_registration2; + storage_->Register( + GURL("http://www.example.com/two/*"), + GURL("http://www.example.com/service_worker.js"), + SaveRegistration(REGISTRATION_OK, &called2, &original_registration2)); + + EXPECT_FALSE(called1); + EXPECT_FALSE(called2); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(called2); + EXPECT_TRUE(called1); + + scoped_refptr<ServiceWorkerRegistration> registration1; + storage_->FindRegistrationForDocument( + GURL("http://www.example.com/one/"), + SaveRegistration(REGISTRATION_OK, &called1, ®istration1)); + scoped_refptr<ServiceWorkerRegistration> registration2; + storage_->FindRegistrationForDocument( + GURL("http://www.example.com/two/"), + SaveRegistration(REGISTRATION_OK, &called2, ®istration2)); + + EXPECT_FALSE(called1); + EXPECT_FALSE(called2); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(called2); + EXPECT_TRUE(called1); + + ASSERT_NE(registration1, registration2); +} + +// Make sure basic registration is working. +TEST_F(ServiceWorkerStorageTest, Register) { + bool called = false; + scoped_refptr<ServiceWorkerRegistration> registration; + storage_->Register(GURL("http://www.example.com/*"), + GURL("http://www.example.com/service_worker.js"), + SaveRegistration(REGISTRATION_OK, &called, ®istration)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + ASSERT_NE(scoped_refptr<ServiceWorkerRegistration>(NULL), registration); +} + +// Make sure registrations are cleaned up when they are unregistered. +TEST_F(ServiceWorkerStorageTest, Unregister) { + GURL pattern("http://www.example.com/*"); + + bool called; + scoped_refptr<ServiceWorkerRegistration> registration; + storage_->Register(pattern, + GURL("http://www.example.com/service_worker.js"), + SaveRegistration(REGISTRATION_OK, &called, ®istration)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + storage_->Unregister(pattern, SaveUnregistration(REGISTRATION_OK, &called)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + ASSERT_TRUE(registration->HasOneRef()); + + storage_->FindRegistrationForPattern( + pattern, + SaveRegistration(REGISTRATION_NOT_FOUND, &called, ®istration)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + ASSERT_EQ(scoped_refptr<ServiceWorkerRegistration>(NULL), registration); +} + +// Make sure that when a new registration replaces an existing +// registration, that the old one is cleaned up. +TEST_F(ServiceWorkerStorageTest, RegisterNewScript) { + GURL pattern("http://www.example.com/*"); + + bool called; + scoped_refptr<ServiceWorkerRegistration> old_registration; + storage_->Register( + pattern, + GURL("http://www.example.com/service_worker.js"), + SaveRegistration(REGISTRATION_OK, &called, &old_registration)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + scoped_refptr<ServiceWorkerRegistration> old_registration_by_pattern; + storage_->FindRegistrationForPattern( + pattern, + SaveRegistration(REGISTRATION_OK, &called, &old_registration_by_pattern)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + ASSERT_EQ(old_registration, old_registration_by_pattern); + old_registration_by_pattern = NULL; + + scoped_refptr<ServiceWorkerRegistration> new_registration; + storage_->Register( + pattern, + GURL("http://www.example.com/service_worker_new.js"), + SaveRegistration(REGISTRATION_OK, &called, &new_registration)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + ASSERT_TRUE(old_registration->HasOneRef()); + + ASSERT_NE(old_registration, new_registration); + + scoped_refptr<ServiceWorkerRegistration> new_registration_by_pattern; + storage_->FindRegistrationForPattern( + pattern, SaveRegistration(REGISTRATION_OK, &called, &new_registration)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + ASSERT_NE(new_registration_by_pattern, old_registration); +} + +// Make sure that when registering a duplicate pattern+script_url +// combination, that the same registration is used. +TEST_F(ServiceWorkerStorageTest, RegisterDuplicateScript) { + GURL pattern("http://www.example.com/*"); + GURL script_url("http://www.example.com/service_worker.js"); + + bool called; + scoped_refptr<ServiceWorkerRegistration> old_registration; + storage_->Register( + pattern, + script_url, + SaveRegistration(REGISTRATION_OK, &called, &old_registration)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + scoped_refptr<ServiceWorkerRegistration> old_registration_by_pattern; + storage_->FindRegistrationForPattern( + pattern, + SaveRegistration(REGISTRATION_OK, &called, &old_registration_by_pattern)); + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + ASSERT_TRUE(old_registration_by_pattern); + + scoped_refptr<ServiceWorkerRegistration> new_registration; + storage_->Register( + pattern, + script_url, + SaveRegistration(REGISTRATION_OK, &called, &new_registration)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + ASSERT_EQ(old_registration, new_registration); + + ASSERT_FALSE(old_registration->HasOneRef()); + + scoped_refptr<ServiceWorkerRegistration> new_registration_by_pattern; + storage_->FindRegistrationForPattern( + pattern, + SaveRegistration(REGISTRATION_OK, &called, &new_registration_by_pattern)); + + ASSERT_FALSE(called); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(called); + + ASSERT_EQ(new_registration, old_registration); +} + +} // namespace content diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index fa3ad3d6bb..a91ac6e9aa 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc @@ -4,19 +4,53 @@ #include "content/browser/service_worker/service_worker_version.h" +#include "base/stl_util.h" +#include "content/browser/service_worker/embedded_worker_instance.h" +#include "content/browser/service_worker/embedded_worker_registry.h" +#include "content/browser/service_worker/service_worker_context_core.h" #include "content/browser/service_worker/service_worker_registration.h" namespace content { ServiceWorkerVersion::ServiceWorkerVersion( - ServiceWorkerRegistration* registration) - : is_shutdown_(false), registration_(registration) {} + ServiceWorkerRegistration* registration, + EmbeddedWorkerRegistry* worker_registry, + int64 version_id) + : version_id_(version_id), + is_shutdown_(false), + registration_(registration) { + if (worker_registry) + embedded_worker_ = worker_registry->CreateWorker(); +} ServiceWorkerVersion::~ServiceWorkerVersion() { DCHECK(is_shutdown_); } void ServiceWorkerVersion::Shutdown() { is_shutdown_ = true; registration_ = NULL; + embedded_worker_.reset(); +} + +void ServiceWorkerVersion::StartWorker() { + DCHECK(!is_shutdown_); + DCHECK(registration_); + embedded_worker_->Start(version_id_, registration_->script_url()); +} + +void ServiceWorkerVersion::StopWorker() { + DCHECK(!is_shutdown_); + embedded_worker_->Stop(); +} + +void ServiceWorkerVersion::OnAssociateProvider( + ServiceWorkerProviderHost* provider_host) { + DCHECK(!is_shutdown_); + embedded_worker_->AddProcessReference(provider_host->process_id()); +} + +void ServiceWorkerVersion::OnUnassociateProvider( + ServiceWorkerProviderHost* provider_host) { + embedded_worker_->ReleaseProcessReference(provider_host->process_id()); } } // namespace content diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h index 93f4459b38..46b75bd686 100644 --- a/content/browser/service_worker/service_worker_version.h +++ b/content/browser/service_worker/service_worker_version.h @@ -8,12 +8,16 @@ #include "base/basictypes.h" #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "content/common/content_export.h" class GURL; namespace content { +class EmbeddedWorkerInstance; +class EmbeddedWorkerRegistry; +class ServiceWorkerProviderHost; class ServiceWorkerRegistration; // This class corresponds to a specific version of a ServiceWorker @@ -51,19 +55,40 @@ class ServiceWorkerRegistration; class CONTENT_EXPORT ServiceWorkerVersion : NON_EXPORTED_BASE(public base::RefCounted<ServiceWorkerVersion>) { public: - explicit ServiceWorkerVersion(ServiceWorkerRegistration* registration); + ServiceWorkerVersion( + ServiceWorkerRegistration* registration, + EmbeddedWorkerRegistry* worker_registry, + int64 version_id); + + int64 version_id() const { return version_id_; } void Shutdown(); bool is_shutdown() const { return is_shutdown_; } + // Starts and stops an embedded worker for this version. + void StartWorker(); + void StopWorker(); + + // Called when this version is associated to a provider host. + // Non-null |provider_host| must be given. + void OnAssociateProvider(ServiceWorkerProviderHost* provider_host); + void OnUnassociateProvider(ServiceWorkerProviderHost* provider_host); + private: - ~ServiceWorkerVersion(); friend class base::RefCounted<ServiceWorkerVersion>; + ~ServiceWorkerVersion(); + + const int64 version_id_; + bool is_shutdown_; scoped_refptr<ServiceWorkerRegistration> registration_; + scoped_ptr<EmbeddedWorkerInstance> embedded_worker_; + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersion); }; + } // namespace content + #endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_VERSION_H_ diff --git a/content/browser/session_history_browsertest.cc b/content/browser/session_history_browsertest.cc index 7d006b606f..bec8293a6b 100644 --- a/content/browser/session_history_browsertest.cc +++ b/content/browser/session_history_browsertest.cc @@ -99,7 +99,7 @@ class SessionHistoryTest : public ContentBrowserTest { void NavigateAndCheckTitle(const char* filename, const std::string& expected_title) { - string16 expected_title16(ASCIIToUTF16(expected_title)); + base::string16 expected_title16(ASCIIToUTF16(expected_title)); TitleWatcher title_watcher(shell()->web_contents(), expected_title16); NavigateToURL(shell(), GetURL(filename)); ASSERT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); diff --git a/content/browser/site_instance_impl_unittest.cc b/content/browser/site_instance_impl_unittest.cc index 5524091328..ac3c1927c9 100644 --- a/content/browser/site_instance_impl_unittest.cc +++ b/content/browser/site_instance_impl_unittest.cc @@ -12,7 +12,6 @@ #include "content/browser/frame_host/navigation_entry_impl.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_view_host_impl.h" -#include "content/browser/renderer_host/test_render_view_host.h" #include "content/browser/site_instance_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/browser/webui/web_ui_controller_factory_registry.h" @@ -26,6 +25,7 @@ #include "content/public/test/test_browser_thread.h" #include "content/test/test_content_browser_client.h" #include "content/test/test_content_client.h" +#include "content/test/test_render_view_host.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/url_util.h" @@ -204,7 +204,8 @@ TEST_F(SiteInstanceTest, SiteInstanceDestructor) { EXPECT_EQ(0, site_delete_counter); NavigationEntryImpl* e1 = new NavigationEntryImpl( - instance, 0, url, Referrer(), string16(), PAGE_TRANSITION_LINK, false); + instance, 0, url, Referrer(), base::string16(), PAGE_TRANSITION_LINK, + false); // Redundantly setting e1's SiteInstance shouldn't affect the ref count. e1->set_site_instance(instance); @@ -212,7 +213,8 @@ TEST_F(SiteInstanceTest, SiteInstanceDestructor) { // Add a second reference NavigationEntryImpl* e2 = new NavigationEntryImpl( - instance, 0, url, Referrer(), string16(), PAGE_TRANSITION_LINK, false); + instance, 0, url, Referrer(), base::string16(), PAGE_TRANSITION_LINK, + false); // Now delete both entries and be sure the SiteInstance goes away. delete e1; @@ -264,7 +266,8 @@ TEST_F(SiteInstanceTest, CloneNavigationEntry) { &browsing_delete_counter); NavigationEntryImpl* e1 = new NavigationEntryImpl( - instance1, 0, url, Referrer(), string16(), PAGE_TRANSITION_LINK, false); + instance1, 0, url, Referrer(), base::string16(), PAGE_TRANSITION_LINK, + false); // Clone the entry NavigationEntryImpl* e2 = new NavigationEntryImpl(*e1); diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index f32e1e9382..cca1df07c0 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc @@ -36,11 +36,11 @@ class SitePerProcessWebContentsObserver: public WebContentsObserver { virtual void DidFailProvisionalLoad( int64 frame_id, - const string16& frame_unique_name, + const base::string16& frame_unique_name, bool is_main_frame, const GURL& validated_url, int error_code, - const string16& error_description, + const base::string16& error_description, RenderViewHost* render_view_host) OVERRIDE { navigation_url_ = validated_url; navigation_succeeded_ = false; @@ -48,7 +48,7 @@ class SitePerProcessWebContentsObserver: public WebContentsObserver { virtual void DidCommitProvisionalLoadForFrame( int64 frame_id, - const string16& frame_unique_name, + const base::string16& frame_unique_name, bool is_main_frame, const GURL& url, PageTransition transition_type, diff --git a/content/browser/speech/google_one_shot_remote_engine.cc b/content/browser/speech/google_one_shot_remote_engine.cc index a421e79c22..575dd5fda6 100644 --- a/content/browser/speech/google_one_shot_remote_engine.cc +++ b/content/browser/speech/google_one_shot_remote_engine.cc @@ -121,7 +121,7 @@ bool ParseServerResponse(const std::string& response_body, const base::DictionaryValue* hypothesis_value = static_cast<const base::DictionaryValue*>(hypothesis); - string16 utterance; + base::string16 utterance; if (!hypothesis_value->GetString(kUtteranceString, &utterance)) { LOG(WARNING) << "ParseServerResponse: Missing utterance value."; diff --git a/content/browser/speech/proto/speech_proto.target.darwin-arm.mk b/content/browser/speech/proto/speech_proto.target.darwin-arm.mk index 9edd835b89..4b08958944 100644 --- a/content/browser/speech/proto/speech_proto.target.darwin-arm.mk +++ b/content/browser/speech/proto/speech_proto.target.darwin-arm.mk @@ -91,6 +91,7 @@ MY_CFLAGS_Debug := \ MY_DEFS_Debug := \ '-DANGLE_DX11' \ + '-DV8_DEPRECATION_WARNINGS' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ '-DDISABLE_NACL' \ @@ -100,9 +101,11 @@ MY_DEFS_Debug := \ '-DENABLE_CONFIGURATION_POLICY' \ '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ + '-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ + '-DENABLE_PRINTING=1' \ '-DENABLE_MANAGED_USERS=1' \ '-DPROTOBUF_USE_DLLS' \ '-DGOOGLE_PROTOBUF_NO_RTTI' \ @@ -179,6 +182,7 @@ MY_CFLAGS_Release := \ MY_DEFS_Release := \ '-DANGLE_DX11' \ + '-DV8_DEPRECATION_WARNINGS' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ '-DDISABLE_NACL' \ @@ -188,9 +192,11 @@ MY_DEFS_Release := \ '-DENABLE_CONFIGURATION_POLICY' \ '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ + '-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ + '-DENABLE_PRINTING=1' \ '-DENABLE_MANAGED_USERS=1' \ '-DPROTOBUF_USE_DLLS' \ '-DGOOGLE_PROTOBUF_NO_RTTI' \ diff --git a/content/browser/speech/proto/speech_proto.target.darwin-mips.mk b/content/browser/speech/proto/speech_proto.target.darwin-mips.mk index 268927fbcf..8df7587882 100644 --- a/content/browser/speech/proto/speech_proto.target.darwin-mips.mk +++ b/content/browser/speech/proto/speech_proto.target.darwin-mips.mk @@ -91,6 +91,7 @@ MY_CFLAGS_Debug := \ MY_DEFS_Debug := \ '-DANGLE_DX11' \ + '-DV8_DEPRECATION_WARNINGS' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ '-DDISABLE_NACL' \ @@ -100,9 +101,11 @@ MY_DEFS_Debug := \ '-DENABLE_CONFIGURATION_POLICY' \ '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ + '-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ + '-DENABLE_PRINTING=1' \ '-DENABLE_MANAGED_USERS=1' \ '-DPROTOBUF_USE_DLLS' \ '-DGOOGLE_PROTOBUF_NO_RTTI' \ @@ -179,6 +182,7 @@ MY_CFLAGS_Release := \ MY_DEFS_Release := \ '-DANGLE_DX11' \ + '-DV8_DEPRECATION_WARNINGS' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ '-DDISABLE_NACL' \ @@ -188,9 +192,11 @@ MY_DEFS_Release := \ '-DENABLE_CONFIGURATION_POLICY' \ '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ + '-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ + '-DENABLE_PRINTING=1' \ '-DENABLE_MANAGED_USERS=1' \ '-DPROTOBUF_USE_DLLS' \ '-DGOOGLE_PROTOBUF_NO_RTTI' \ diff --git a/content/browser/speech/proto/speech_proto.target.darwin-x86.mk b/content/browser/speech/proto/speech_proto.target.darwin-x86.mk index 0e9a25cdc3..f9a8d83119 100644 --- a/content/browser/speech/proto/speech_proto.target.darwin-x86.mk +++ b/content/browser/speech/proto/speech_proto.target.darwin-x86.mk @@ -93,6 +93,7 @@ MY_CFLAGS_Debug := \ MY_DEFS_Debug := \ '-DANGLE_DX11' \ + '-DV8_DEPRECATION_WARNINGS' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ '-DDISABLE_NACL' \ @@ -102,9 +103,11 @@ MY_DEFS_Debug := \ '-DENABLE_CONFIGURATION_POLICY' \ '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ + '-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ + '-DENABLE_PRINTING=1' \ '-DENABLE_MANAGED_USERS=1' \ '-DPROTOBUF_USE_DLLS' \ '-DGOOGLE_PROTOBUF_NO_RTTI' \ @@ -184,6 +187,7 @@ MY_CFLAGS_Release := \ MY_DEFS_Release := \ '-DANGLE_DX11' \ + '-DV8_DEPRECATION_WARNINGS' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ '-DDISABLE_NACL' \ @@ -193,9 +197,11 @@ MY_DEFS_Release := \ '-DENABLE_CONFIGURATION_POLICY' \ '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ + '-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ + '-DENABLE_PRINTING=1' \ '-DENABLE_MANAGED_USERS=1' \ '-DPROTOBUF_USE_DLLS' \ '-DGOOGLE_PROTOBUF_NO_RTTI' \ diff --git a/content/browser/speech/proto/speech_proto.target.linux-arm.mk b/content/browser/speech/proto/speech_proto.target.linux-arm.mk index 9edd835b89..4b08958944 100644 --- a/content/browser/speech/proto/speech_proto.target.linux-arm.mk +++ b/content/browser/speech/proto/speech_proto.target.linux-arm.mk @@ -91,6 +91,7 @@ MY_CFLAGS_Debug := \ MY_DEFS_Debug := \ '-DANGLE_DX11' \ + '-DV8_DEPRECATION_WARNINGS' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ '-DDISABLE_NACL' \ @@ -100,9 +101,11 @@ MY_DEFS_Debug := \ '-DENABLE_CONFIGURATION_POLICY' \ '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ + '-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ + '-DENABLE_PRINTING=1' \ '-DENABLE_MANAGED_USERS=1' \ '-DPROTOBUF_USE_DLLS' \ '-DGOOGLE_PROTOBUF_NO_RTTI' \ @@ -179,6 +182,7 @@ MY_CFLAGS_Release := \ MY_DEFS_Release := \ '-DANGLE_DX11' \ + '-DV8_DEPRECATION_WARNINGS' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ '-DDISABLE_NACL' \ @@ -188,9 +192,11 @@ MY_DEFS_Release := \ '-DENABLE_CONFIGURATION_POLICY' \ '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ + '-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ + '-DENABLE_PRINTING=1' \ '-DENABLE_MANAGED_USERS=1' \ '-DPROTOBUF_USE_DLLS' \ '-DGOOGLE_PROTOBUF_NO_RTTI' \ diff --git a/content/browser/speech/proto/speech_proto.target.linux-mips.mk b/content/browser/speech/proto/speech_proto.target.linux-mips.mk index 268927fbcf..8df7587882 100644 --- a/content/browser/speech/proto/speech_proto.target.linux-mips.mk +++ b/content/browser/speech/proto/speech_proto.target.linux-mips.mk @@ -91,6 +91,7 @@ MY_CFLAGS_Debug := \ MY_DEFS_Debug := \ '-DANGLE_DX11' \ + '-DV8_DEPRECATION_WARNINGS' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ '-DDISABLE_NACL' \ @@ -100,9 +101,11 @@ MY_DEFS_Debug := \ '-DENABLE_CONFIGURATION_POLICY' \ '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ + '-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ + '-DENABLE_PRINTING=1' \ '-DENABLE_MANAGED_USERS=1' \ '-DPROTOBUF_USE_DLLS' \ '-DGOOGLE_PROTOBUF_NO_RTTI' \ @@ -179,6 +182,7 @@ MY_CFLAGS_Release := \ MY_DEFS_Release := \ '-DANGLE_DX11' \ + '-DV8_DEPRECATION_WARNINGS' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ '-DDISABLE_NACL' \ @@ -188,9 +192,11 @@ MY_DEFS_Release := \ '-DENABLE_CONFIGURATION_POLICY' \ '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ + '-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ + '-DENABLE_PRINTING=1' \ '-DENABLE_MANAGED_USERS=1' \ '-DPROTOBUF_USE_DLLS' \ '-DGOOGLE_PROTOBUF_NO_RTTI' \ diff --git a/content/browser/speech/proto/speech_proto.target.linux-x86.mk b/content/browser/speech/proto/speech_proto.target.linux-x86.mk index 0e9a25cdc3..f9a8d83119 100644 --- a/content/browser/speech/proto/speech_proto.target.linux-x86.mk +++ b/content/browser/speech/proto/speech_proto.target.linux-x86.mk @@ -93,6 +93,7 @@ MY_CFLAGS_Debug := \ MY_DEFS_Debug := \ '-DANGLE_DX11' \ + '-DV8_DEPRECATION_WARNINGS' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ '-DDISABLE_NACL' \ @@ -102,9 +103,11 @@ MY_DEFS_Debug := \ '-DENABLE_CONFIGURATION_POLICY' \ '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ + '-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ + '-DENABLE_PRINTING=1' \ '-DENABLE_MANAGED_USERS=1' \ '-DPROTOBUF_USE_DLLS' \ '-DGOOGLE_PROTOBUF_NO_RTTI' \ @@ -184,6 +187,7 @@ MY_CFLAGS_Release := \ MY_DEFS_Release := \ '-DANGLE_DX11' \ + '-DV8_DEPRECATION_WARNINGS' \ '-D_FILE_OFFSET_BITS=64' \ '-DNO_TCMALLOC' \ '-DDISABLE_NACL' \ @@ -193,9 +197,11 @@ MY_DEFS_Release := \ '-DENABLE_CONFIGURATION_POLICY' \ '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \ '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \ + '-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \ '-DUSE_OPENSSL=1' \ '-DENABLE_EGLIMAGE=1' \ '-DCLD_VERSION=1' \ + '-DENABLE_PRINTING=1' \ '-DENABLE_MANAGED_USERS=1' \ '-DPROTOBUF_USE_DLLS' \ '-DGOOGLE_PROTOBUF_NO_RTTI' \ diff --git a/content/browser/speech/speech_recognition_manager_impl.cc b/content/browser/speech/speech_recognition_manager_impl.cc index bdc9d1ce21..6ecfa7041a 100644 --- a/content/browser/speech/speech_recognition_manager_impl.cc +++ b/content/browser/speech/speech_recognition_manager_impl.cc @@ -672,7 +672,7 @@ bool SpeechRecognitionManagerImpl::HasAudioInputDevices() { return audio_manager_->HasAudioInputDevices(); } -string16 SpeechRecognitionManagerImpl::GetAudioInputDeviceModel() { +base::string16 SpeechRecognitionManagerImpl::GetAudioInputDeviceModel() { return audio_manager_->GetAudioInputDeviceModel(); } diff --git a/content/browser/speech/speech_recognition_manager_impl.h b/content/browser/speech/speech_recognition_manager_impl.h index 7db7d24d84..d471cf3f29 100644 --- a/content/browser/speech/speech_recognition_manager_impl.h +++ b/content/browser/speech/speech_recognition_manager_impl.h @@ -75,7 +75,7 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl : int render_view_id, int request_id) const OVERRIDE; virtual bool HasAudioInputDevices() OVERRIDE; - virtual string16 GetAudioInputDeviceModel() OVERRIDE; + virtual base::string16 GetAudioInputDeviceModel() OVERRIDE; virtual void ShowAudioInputSettings() OVERRIDE; // SpeechRecognitionEventListener methods. diff --git a/content/browser/speech/speech_recognizer_impl_android.cc b/content/browser/speech/speech_recognizer_impl_android.cc index c771cefba5..2e8c57e87b 100644 --- a/content/browser/speech/speech_recognizer_impl_android.cc +++ b/content/browser/speech/speech_recognizer_impl_android.cc @@ -146,7 +146,7 @@ void SpeechRecognizerImplAndroid::OnAudioEnd(JNIEnv* env, jobject obj) { void SpeechRecognizerImplAndroid::OnRecognitionResults(JNIEnv* env, jobject obj, jobjectArray strings, jfloatArray floats, jboolean provisional) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - std::vector<string16> options; + std::vector<base::string16> options; AppendJavaStringArrayToStringVector(env, strings, &options); std::vector<float> scores(options.size(), 0.0); if (floats != NULL) diff --git a/content/browser/ssl/ssl_manager.cc b/content/browser/ssl/ssl_manager.cc index 9dd91d7ae6..b1eb51e320 100644 --- a/content/browser/ssl/ssl_manager.cc +++ b/content/browser/ssl/ssl_manager.cc @@ -124,11 +124,14 @@ void SSLManager::DidCommitProvisionalLoad(const LoadCommittedDetails& details) { net::CertStatus ssl_cert_status; int ssl_security_bits; int ssl_connection_status; + SignedCertificateTimestampIDStatusList + ssl_signed_certificate_timestamp_ids; DeserializeSecurityInfo(details.serialized_security_info, &ssl_cert_id, &ssl_cert_status, &ssl_security_bits, - &ssl_connection_status); + &ssl_connection_status, + &ssl_signed_certificate_timestamp_ids); // We may not have an entry if this is a navigation to an initial blank // page. Reset the SSL information and add the new data we have. @@ -137,6 +140,8 @@ void SSLManager::DidCommitProvisionalLoad(const LoadCommittedDetails& details) { entry->GetSSL().cert_status = ssl_cert_status; entry->GetSSL().security_bits = ssl_security_bits; entry->GetSSL().connection_status = ssl_connection_status; + entry->GetSSL().signed_certificate_timestamp_ids = + ssl_signed_certificate_timestamp_ids; } } diff --git a/content/browser/storage_partition_impl_map.cc b/content/browser/storage_partition_impl_map.cc index 90f9497223..85934f117b 100644 --- a/content/browser/storage_partition_impl_map.cc +++ b/content/browser/storage_partition_impl_map.cc @@ -290,8 +290,8 @@ void BlockingGarbageCollect( base::FileEnumerator enumerator(storage_root, false, kAllFileTypes); base::FilePath trash_directory; - if (!file_util::CreateTemporaryDirInDir(storage_root, kTrashDirname, - &trash_directory)) { + if (!base::CreateTemporaryDirInDir(storage_root, kTrashDirname, + &trash_directory)) { // Unable to continue without creating the trash directory so give up. return; } diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc index 911f835ab7..ef3b67912a 100644 --- a/content/browser/storage_partition_impl_unittest.cc +++ b/content/browser/storage_partition_impl_unittest.cc @@ -202,7 +202,7 @@ class RemoveLocalStorageTester { // stores data in the host file system. base::FilePath storage_path = profile_->GetPath().AppendASCII("Local Storage"); - file_util::CreateDirectory(storage_path); + base::CreateDirectory(storage_path); // Write some files. file_util::WriteFile(storage_path.Append(kDomStorageOrigin1), NULL, 0); @@ -210,12 +210,16 @@ class RemoveLocalStorageTester { file_util::WriteFile(storage_path.Append(kDomStorageOrigin3), NULL, 0); // Tweak their dates. - file_util::SetLastModifiedTime(storage_path.Append(kDomStorageOrigin1), - base::Time::Now()); - file_util::SetLastModifiedTime(storage_path.Append(kDomStorageOrigin2), - base::Time::Now() - base::TimeDelta::FromDays(1)); - file_util::SetLastModifiedTime(storage_path.Append(kDomStorageOrigin3), - base::Time::Now() - base::TimeDelta::FromDays(60)); + base::Time now = base::Time::Now(); + base::TouchFile(storage_path.Append(kDomStorageOrigin1), now, now); + + base::Time one_day_ago = now - base::TimeDelta::FromDays(1); + base::TouchFile(storage_path.Append(kDomStorageOrigin2), + one_day_ago, one_day_ago); + + base::Time sixty_days_ago = now - base::TimeDelta::FromDays(60); + base::TouchFile(storage_path.Append(kDomStorageOrigin3), + sixty_days_ago, sixty_days_ago); } private: diff --git a/content/browser/tracing/trace_controller_impl.cc b/content/browser/tracing/trace_controller_impl.cc deleted file mode 100644 index 8b8433848a..0000000000 --- a/content/browser/tracing/trace_controller_impl.cc +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/tracing/trace_controller_impl.h" - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/debug/trace_event.h" -#include "base/strings/string_number_conversions.h" -#include "components/tracing/tracing_messages.h" -#include "content/browser/tracing/trace_message_filter.h" -#include "content/browser/tracing/trace_subscriber_stdio.h" -#include "content/common/child_process_messages.h" -#include "content/public/browser/browser_message_filter.h" -#include "content/public/common/content_switches.h" - -using base::debug::TraceLog; - -namespace content { - -namespace { - -base::LazyInstance<TraceControllerImpl>::Leaky g_controller = - LAZY_INSTANCE_INITIALIZER; - -} // namespace - -TraceController* TraceController::GetInstance() { - return TraceControllerImpl::GetInstance(); -} - -TraceControllerImpl::TraceControllerImpl() : - subscriber_(NULL), - pending_end_ack_count_(0), - pending_bpf_ack_count_(0), - maximum_bpf_(0.0f), - is_tracing_(false), - is_get_category_groups_(false), - category_filter_( - base::debug::CategoryFilter::kDefaultCategoryFilterString) { - TraceLog::GetInstance()->SetNotificationCallback( - base::Bind(&TraceControllerImpl::OnTraceNotification, - base::Unretained(this))); -} - -TraceControllerImpl::~TraceControllerImpl() { - // No need to SetNotificationCallback(nil) on the TraceLog since this is a - // Leaky instance. - NOTREACHED(); -} - -TraceControllerImpl* TraceControllerImpl::GetInstance() { - return g_controller.Pointer(); -} - -bool TraceControllerImpl::GetKnownCategoryGroupsAsync( - TraceSubscriber* subscriber) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - // Known categories come back from child processes with the EndTracingAck - // message. So to get known categories, just begin and end tracing immediately - // afterwards. This will ping all the child processes for categories. - is_get_category_groups_ = true; - bool success = BeginTracing(subscriber, "*", - TraceLog::GetInstance()->trace_options()) && - EndTracingAsync(subscriber); - is_get_category_groups_ = success; - return success; -} - -bool TraceControllerImpl::BeginTracing(TraceSubscriber* subscriber, - const std::string& category_patterns, - base::debug::TraceLog::Options options) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - if (!can_begin_tracing(subscriber)) - return false; - -#if defined(OS_ANDROID) - if (!is_get_category_groups_) - TraceLog::GetInstance()->AddClockSyncMetadataEvent(); -#endif - - // Enable tracing - TraceLog::GetInstance()->SetEnabled( - base::debug::CategoryFilter(category_patterns), options); - - OnTracingBegan(subscriber); - - return true; -} - -bool TraceControllerImpl::EndTracingAsync(TraceSubscriber* subscriber) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - if (!can_end_tracing() || subscriber != subscriber_) - return false; - - // Disable local trace early to avoid traces during end-tracing process from - // interfering with the process. - TraceLog::GetInstance()->SetDisabled(); - -#if defined(OS_ANDROID) - if (!is_get_category_groups_) - TraceLog::GetInstance()->AddClockSyncMetadataEvent(); -#endif - - // There could be a case where there are no child processes and filters_ - // is empty. In that case we can immediately tell the subscriber that tracing - // has ended. To avoid recursive calls back to the subscriber, we will just - // use the existing asynchronous OnEndTracingAck code. - // Count myself (local trace) in pending_end_ack_count_, acked below. - pending_end_ack_count_ = filters_.size() + 1; - - // Handle special case of zero child processes. - if (pending_end_ack_count_ == 1) { - // Ack asynchronously now, because we don't have any children to wait for. - std::vector<std::string> category_groups; - TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&TraceControllerImpl::OnEndTracingAck, - base::Unretained(this), category_groups)); - } - - // Notify all child processes. - for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { - it->get()->SendEndTracing(); - } - - return true; -} - -bool TraceControllerImpl::GetTraceBufferPercentFullAsync( - TraceSubscriber* subscriber) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - if (!can_get_buffer_percent_full() || subscriber != subscriber_) - return false; - - maximum_bpf_ = 0.0f; - pending_bpf_ack_count_ = filters_.size() + 1; - - // Handle special case of zero child processes. - if (pending_bpf_ack_count_ == 1) { - // Ack asynchronously now, because we don't have any children to wait for. - float bpf = TraceLog::GetInstance()->GetBufferPercentFull(); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&TraceControllerImpl::OnTraceBufferPercentFullReply, - base::Unretained(this), bpf)); - } - - // Message all child processes. - for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { - it->get()->SendGetTraceBufferPercentFull(); - } - - return true; -} - -bool TraceControllerImpl::SetWatchEvent(TraceSubscriber* subscriber, - const std::string& category_name, - const std::string& event_name) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (subscriber != subscriber_) - return false; - - watch_category_ = category_name; - watch_name_ = event_name; - - TraceLog::GetInstance()->SetWatchEvent(category_name, event_name); - for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) - it->get()->SendSetWatchEvent(category_name, event_name); - - return true; -} - -bool TraceControllerImpl::CancelWatchEvent(TraceSubscriber* subscriber) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (subscriber != subscriber_) - return false; - - watch_category_.clear(); - watch_name_.clear(); - - TraceLog::GetInstance()->CancelWatchEvent(); - for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) - it->get()->SendCancelWatchEvent(); - - return true; -} - -void TraceControllerImpl::CancelSubscriber(TraceSubscriber* subscriber) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - if (subscriber == subscriber_) { - subscriber_ = NULL; - // End tracing if necessary. - if (is_tracing_ && pending_end_ack_count_ == 0) - EndTracingAsync(NULL); - } -} - -void TraceControllerImpl::AddFilter(TraceMessageFilter* filter) { - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&TraceControllerImpl::AddFilter, base::Unretained(this), - make_scoped_refptr(filter))); - return; - } - - filters_.insert(filter); - if (is_tracing_enabled()) { - std::string cf_str = category_filter_.ToString(); - filter->SendBeginTracing(cf_str, trace_options_); - if (!watch_category_.empty()) - filter->SendSetWatchEvent(watch_category_, watch_name_); - } -} - -void TraceControllerImpl::RemoveFilter(TraceMessageFilter* filter) { - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&TraceControllerImpl::RemoveFilter, base::Unretained(this), - make_scoped_refptr(filter))); - return; - } - - filters_.erase(filter); -} - -void TraceControllerImpl::OnTracingBegan(TraceSubscriber* subscriber) { - is_tracing_ = true; - - subscriber_ = subscriber; - - category_filter_ = TraceLog::GetInstance()->GetCurrentCategoryFilter(); - trace_options_ = TraceLog::GetInstance()->trace_options(); - - // Notify all child processes. - for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { - it->get()->SendBeginTracing(category_filter_.ToString(), trace_options_); - } -} - -void TraceControllerImpl::OnEndTracingAck( - const std::vector<std::string>& known_category_groups) { - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&TraceControllerImpl::OnEndTracingAck, - base::Unretained(this), known_category_groups)); - return; - } - - // Merge known_category_groups with known_category_groups_ - known_category_groups_.insert(known_category_groups.begin(), - known_category_groups.end()); - - if (pending_end_ack_count_ == 0) - return; - - - if (--pending_end_ack_count_ == 1) { - // All acks from subprocesses have been received. Now flush the local trace. - // During or after this call, our OnLocalTraceDataCollected will be - // called with the last of the local trace data. - TraceLog::GetInstance()->Flush( - base::Bind(&TraceControllerImpl::OnLocalTraceDataCollected, - base::Unretained(this))); - } - - if (pending_end_ack_count_ == 0) { - // All acks (including from the subprocesses and the local trace) have been - // received. - is_tracing_ = false; - - // Trigger callback if one is set. - if (subscriber_) { - if (is_get_category_groups_) - subscriber_->OnKnownCategoriesCollected(known_category_groups_); - else - subscriber_->OnEndTracingComplete(); - // Clear subscriber so that others can use TraceController. - subscriber_ = NULL; - } - - is_get_category_groups_ = false; - } -} - -void TraceControllerImpl::OnTraceDataCollected( - const scoped_refptr<base::RefCountedString>& events_str_ptr) { - // OnTraceDataCollected may be called from any browser thread, either by the - // local event trace system or from child processes via TraceMessageFilter. - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&TraceControllerImpl::OnTraceDataCollected, - base::Unretained(this), events_str_ptr)); - return; - } - - // Drop trace events if we are just getting categories. - if (subscriber_ && !is_get_category_groups_) - subscriber_->OnTraceDataCollected(events_str_ptr); -} - -void TraceControllerImpl::OnLocalTraceDataCollected( - const scoped_refptr<base::RefCountedString>& events_str_ptr, - bool has_more_events) { - if (events_str_ptr->data().size()) - OnTraceDataCollected(events_str_ptr); - - if (!has_more_events) { - // Simulate an EndTrackingAck for the local trace. - std::vector<std::string> category_groups; - TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups); - OnEndTracingAck(category_groups); - } -} - -void TraceControllerImpl::OnTraceNotification(int notification) { - // OnTraceNotification may be called from any browser thread, either by the - // local event trace system or from child processes via TraceMessageFilter. - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&TraceControllerImpl::OnTraceNotification, - base::Unretained(this), notification)); - return; - } - - if (notification & base::debug::TraceLog::TRACE_BUFFER_FULL) { - // EndTracingAsync may return false if tracing is already in the process - // of being ended. That is ok. - EndTracingAsync(subscriber_); - } - if (notification & base::debug::TraceLog::EVENT_WATCH_NOTIFICATION) { - if (subscriber_) - subscriber_->OnEventWatchNotification(); - } -} - -void TraceControllerImpl::OnTraceBufferPercentFullReply(float percent_full) { - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&TraceControllerImpl::OnTraceBufferPercentFullReply, - base::Unretained(this), percent_full)); - return; - } - - if (pending_bpf_ack_count_ == 0) - return; - - maximum_bpf_ = (maximum_bpf_ > percent_full)? maximum_bpf_ : percent_full; - - if (--pending_bpf_ack_count_ == 0) { - // Trigger callback if one is set. - if (subscriber_) - subscriber_->OnTraceBufferPercentFullReply(maximum_bpf_); - } - - if (pending_bpf_ack_count_ == 1) { - // The last ack represents local trace, so we need to ack it now. Note that - // this code only executes if there were child processes. - float bpf = TraceLog::GetInstance()->GetBufferPercentFull(); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&TraceControllerImpl::OnTraceBufferPercentFullReply, - base::Unretained(this), bpf)); - } -} - -} // namespace content diff --git a/content/browser/tracing/trace_controller_impl.h b/content/browser/tracing/trace_controller_impl.h deleted file mode 100644 index c058a04df1..0000000000 --- a/content/browser/tracing/trace_controller_impl.h +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_TRACING_TRACE_CONTROLLER_IMPL_H_ -#define CONTENT_BROWSER_TRACING_TRACE_CONTROLLER_IMPL_H_ - -#include <set> -#include <string> -#include <vector> - -#include "base/debug/trace_event.h" -#include "base/lazy_instance.h" -#include "content/public/browser/trace_controller.h" - -class CommandLine; - -namespace content { -class TraceMessageFilter; - -class TraceControllerImpl : public TraceController { - public: - static TraceControllerImpl* GetInstance(); - - // TraceController implementation: - virtual bool BeginTracing(TraceSubscriber* subscriber, - const std::string& category_patterns, - base::debug::TraceLog::Options options) OVERRIDE; - virtual bool EndTracingAsync(TraceSubscriber* subscriber) OVERRIDE; - virtual bool GetTraceBufferPercentFullAsync( - TraceSubscriber* subscriber) OVERRIDE; - virtual bool SetWatchEvent(TraceSubscriber* subscriber, - const std::string& category_name, - const std::string& event_name) OVERRIDE; - virtual bool CancelWatchEvent(TraceSubscriber* subscriber) OVERRIDE; - virtual void CancelSubscriber(TraceSubscriber* subscriber) OVERRIDE; - virtual bool GetKnownCategoryGroupsAsync(TraceSubscriber* subscriber) - OVERRIDE; - - private: - typedef std::set<scoped_refptr<TraceMessageFilter> > FilterMap; - - friend struct base::DefaultLazyInstanceTraits<TraceControllerImpl>; - friend class TraceMessageFilter; - - TraceControllerImpl(); - virtual ~TraceControllerImpl(); - - bool is_tracing_enabled() const { - return can_end_tracing(); - } - - bool can_end_tracing() const { - return is_tracing_ && pending_end_ack_count_ == 0; - } - - // Can get Buffer Percent Full - bool can_get_buffer_percent_full() const { - return is_tracing_ && - pending_end_ack_count_ == 0 && - pending_bpf_ack_count_ == 0; - } - - bool can_begin_tracing(TraceSubscriber* subscriber) const { - return !is_tracing_ && - (subscriber_ == NULL || subscriber == subscriber_); - } - - // Methods for use by TraceMessageFilter. - - void AddFilter(TraceMessageFilter* filter); - void RemoveFilter(TraceMessageFilter* filter); - void OnTracingBegan(TraceSubscriber* subscriber); - void OnEndTracingAck(const std::vector<std::string>& known_category_groups); - void OnTraceDataCollected( - const scoped_refptr<base::RefCountedString>& events_str_ptr); - void OnTraceNotification(int notification); - void OnTraceBufferPercentFullReply(float percent_full); - - // Callback of TraceLog::Flush() for the local trace. - void OnLocalTraceDataCollected( - const scoped_refptr<base::RefCountedString>& events_str_ptr, - bool has_more_events); - - FilterMap filters_; - TraceSubscriber* subscriber_; - // Pending acks for EndTracingAsync: - int pending_end_ack_count_; - // Pending acks for GetTraceBufferPercentFullAsync: - int pending_bpf_ack_count_; - float maximum_bpf_; - bool is_tracing_; - bool is_get_category_groups_; - std::set<std::string> known_category_groups_; - std::string watch_category_; - std::string watch_name_; - base::debug::TraceLog::Options trace_options_; - base::debug::CategoryFilter category_filter_; - - DISALLOW_COPY_AND_ASSIGN(TraceControllerImpl); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_TRACING_TRACE_CONTROLLER_IMPL_H_ diff --git a/content/browser/tracing/trace_message_filter.cc b/content/browser/tracing/trace_message_filter.cc index 00fffb9900..35f23dc102 100644 --- a/content/browser/tracing/trace_message_filter.cc +++ b/content/browser/tracing/trace_message_filter.cc @@ -5,7 +5,6 @@ #include "content/browser/tracing/trace_message_filter.h" #include "components/tracing/tracing_messages.h" -#include "content/browser/tracing/trace_controller_impl.h" #include "content/browser/tracing/tracing_controller_impl.h" namespace content { @@ -17,6 +16,8 @@ TraceMessageFilter::TraceMessageFilter() : is_awaiting_buffer_percent_full_ack_(false) { } +TraceMessageFilter::~TraceMessageFilter() {} + void TraceMessageFilter::OnChannelClosing() { if (has_child_) { if (is_awaiting_end_ack_) @@ -28,8 +29,7 @@ void TraceMessageFilter::OnChannelClosing() { if (is_awaiting_buffer_percent_full_ack_) OnTraceBufferPercentFullReply(0.0f); - TraceControllerImpl::GetInstance()->RemoveFilter(this); - TracingControllerImpl::GetInstance()->RemoveFilter(this); + TracingControllerImpl::GetInstance()->RemoveTraceMessageFilter(this); } } @@ -47,8 +47,8 @@ bool TraceMessageFilter::OnMessageReceived(const IPC::Message& message, OnTraceDataCollected) IPC_MESSAGE_HANDLER(TracingHostMsg_MonitoringTraceDataCollected, OnMonitoringTraceDataCollected) - IPC_MESSAGE_HANDLER(TracingHostMsg_TraceNotification, - OnTraceNotification) + IPC_MESSAGE_HANDLER(TracingHostMsg_WatchEventMatched, + OnWatchEventMatched) IPC_MESSAGE_HANDLER(TracingHostMsg_TraceBufferPercentFullReply, OnTraceBufferPercentFullReply) IPC_MESSAGE_UNHANDLED(handled = false) @@ -109,12 +109,9 @@ void TraceMessageFilter::SendCancelWatchEvent() { Send(new TracingMsg_CancelWatchEvent); } -TraceMessageFilter::~TraceMessageFilter() {} - void TraceMessageFilter::OnChildSupportsTracing() { has_child_ = true; - TraceControllerImpl::GetInstance()->AddFilter(this); - TracingControllerImpl::GetInstance()->AddFilter(this); + TracingControllerImpl::GetInstance()->AddTraceMessageFilter(this); } void TraceMessageFilter::OnEndTracingAck( @@ -123,7 +120,6 @@ void TraceMessageFilter::OnEndTracingAck( // child process is compromised. if (is_awaiting_end_ack_) { is_awaiting_end_ack_ = false; - TraceControllerImpl::GetInstance()->OnEndTracingAck(known_categories); TracingControllerImpl::GetInstance()->OnDisableRecordingAcked( known_categories); } else { @@ -145,7 +141,6 @@ void TraceMessageFilter::OnCaptureMonitoringSnapshotAcked() { void TraceMessageFilter::OnTraceDataCollected(const std::string& data) { scoped_refptr<base::RefCountedString> data_ptr(new base::RefCountedString()); data_ptr->data() = data; - TraceControllerImpl::GetInstance()->OnTraceDataCollected(data_ptr); TracingControllerImpl::GetInstance()->OnTraceDataCollected(data_ptr); } @@ -157,15 +152,13 @@ void TraceMessageFilter::OnMonitoringTraceDataCollected( data_ptr); } -void TraceMessageFilter::OnTraceNotification(int notification) { - TraceControllerImpl::GetInstance()->OnTraceNotification(notification); +void TraceMessageFilter::OnWatchEventMatched() { + TracingControllerImpl::GetInstance()->OnWatchEventMatched(); } void TraceMessageFilter::OnTraceBufferPercentFullReply(float percent_full) { if (is_awaiting_buffer_percent_full_ack_) { is_awaiting_buffer_percent_full_ack_ = false; - TraceControllerImpl::GetInstance()->OnTraceBufferPercentFullReply( - percent_full); TracingControllerImpl::GetInstance()->OnTraceBufferPercentFullReply( percent_full); } else { diff --git a/content/browser/tracing/trace_message_filter.h b/content/browser/tracing/trace_message_filter.h index c8290d952c..0f9e18ed9c 100644 --- a/content/browser/tracing/trace_message_filter.h +++ b/content/browser/tracing/trace_message_filter.h @@ -45,7 +45,7 @@ class TraceMessageFilter : public BrowserMessageFilter { void OnChildSupportsTracing(); void OnEndTracingAck(const std::vector<std::string>& known_categories); void OnCaptureMonitoringSnapshotAcked(); - void OnTraceNotification(int notification); + void OnWatchEventMatched(); void OnTraceBufferPercentFullReply(float percent_full); void OnTraceDataCollected(const std::string& data); void OnMonitoringTraceDataCollected(const std::string& data); diff --git a/content/browser/tracing/trace_subscriber_stdio.cc b/content/browser/tracing/trace_subscriber_stdio.cc deleted file mode 100644 index da81660939..0000000000 --- a/content/browser/tracing/trace_subscriber_stdio.cc +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/tracing/trace_subscriber_stdio.h" - -#include "base/bind.h" -#include "base/debug/trace_event.h" -#include "base/file_util.h" -#include "base/logging.h" -#include "base/threading/sequenced_worker_pool.h" -#include "content/public/browser/browser_thread.h" - -namespace content { - -// All method calls on this class are done on a SequencedWorkerPool thread. -class TraceSubscriberStdio::TraceSubscriberStdioWorker - : public base::RefCountedThreadSafe<TraceSubscriberStdioWorker> { - public: - TraceSubscriberStdioWorker(const base::FilePath& path, - FileType file_type, - bool has_system_trace) - : path_(path), - file_type_(file_type), - has_system_trace_(has_system_trace), - file_(0), - needs_comma_(false), - wrote_trace_(false), - has_pending_system_trace_(false), - wrote_system_trace_(false) {} - - void OnTraceStart() { - DCHECK(!file_); - file_ = file_util::OpenFile(path_, "w+"); - if (!IsValid()) { - LOG(ERROR) << "Failed to open performance trace file: " << path_.value(); - return; - } - - VLOG(0) << "Logging performance trace to file: " << path_.value(); - if (file_type_ == FILE_TYPE_PROPERTY_LIST) - WriteString("{\"traceEvents\":"); - WriteString("["); - } - - void OnTraceData(const scoped_refptr<base::RefCountedString>& data_ptr) { - if (!IsValid()) - return; - DCHECK(!data_ptr->data().empty()); - if (needs_comma_) - WriteString(","); - WriteString(data_ptr->data()); - needs_comma_ = true; - } - - void OnSystemTraceData( - const scoped_refptr<base::RefCountedString>& data_ptr) { - if (wrote_trace_) { - WriteSystemTrace(data_ptr); - End(); - } else { - pending_system_trace_ = data_ptr; - has_pending_system_trace_ = true; - } - } - - void OnTraceEnd() { - if (!IsValid()) - return; - WriteString("]"); - - wrote_trace_ = true; - - if (!has_system_trace_ || wrote_system_trace_) { - End(); - return; - } - - WriteString(","); - if (has_pending_system_trace_) { - WriteSystemTrace(pending_system_trace_); - End(); - } - } - - private: - friend class base::RefCountedThreadSafe<TraceSubscriberStdioWorker>; - - ~TraceSubscriberStdioWorker() { - CloseFile(); - } - - bool IsValid() const { - return file_ && (0 == ferror(file_)); - } - - void CloseFile() { - if (file_) { - fclose(file_); - file_ = 0; - - } - } - - void End() { - if (file_type_ == FILE_TYPE_PROPERTY_LIST) - WriteString("}"); - CloseFile(); - } - - void WriteSystemTrace(const scoped_refptr<base::RefCountedString>& data_ptr) { - // Newlines need to be replaced with the string "\n" to be parsed correctly. - // Double quotes need to be replaced with the string "\"". - // System logs are ASCII. - const std::string& data = data_ptr->data(); - const char* chars = data.c_str(); - WriteString("\"systemTraceEvents\":\""); - size_t old_index = 0; - for (size_t new_index = data.find_first_of("\n\""); - std::string::npos != new_index; - old_index = new_index + 1, - new_index = data.find_first_of("\n\"", old_index)) { - WriteChars(chars + old_index, new_index - old_index); - if (chars[new_index] == '\n') - WriteChars("\\n", 2); - else - WriteChars("\\\"", 2); - } - WriteChars(chars + old_index, data.size() - old_index); - WriteString("\""); - wrote_system_trace_ = true; - } - - void WriteChars(const char* output_chars, size_t size) { - if (size == 0) - return; - - if (IsValid()) { - size_t written = fwrite(output_chars, 1, size, file_); - if (written != size) { - LOG(ERROR) << "Error " << ferror(file_) << " in fwrite() to trace file"; - CloseFile(); - } - } - } - - void WriteString(const std::string& output_str) { - WriteChars(output_str.data(), output_str.size()); - } - - base::FilePath path_; - const FileType file_type_; - const bool has_system_trace_; - FILE* file_; - bool needs_comma_; - bool wrote_trace_; - bool has_pending_system_trace_; - bool wrote_system_trace_; - scoped_refptr<base::RefCountedString> pending_system_trace_; - DISALLOW_COPY_AND_ASSIGN(TraceSubscriberStdioWorker); -}; - -TraceSubscriberStdio::TraceSubscriberStdio(const base::FilePath& path, - FileType file_type, - bool has_system_trace) - : worker_(new TraceSubscriberStdioWorker(path, - file_type, - has_system_trace)) { - if (has_system_trace) - CHECK_EQ(FILE_TYPE_PROPERTY_LIST, file_type); - BrowserThread::PostBlockingPoolSequencedTask( - __FILE__, FROM_HERE, - base::Bind(&TraceSubscriberStdioWorker::OnTraceStart, worker_)); -} - -TraceSubscriberStdio::~TraceSubscriberStdio() { -} - -void TraceSubscriberStdio::OnEndTracingComplete() { - BrowserThread::PostBlockingPoolSequencedTask( - __FILE__, FROM_HERE, - base::Bind(&TraceSubscriberStdioWorker::OnTraceEnd, worker_)); -} - -void TraceSubscriberStdio::OnTraceDataCollected( - const scoped_refptr<base::RefCountedString>& data_ptr) { - BrowserThread::PostBlockingPoolSequencedTask( - __FILE__, FROM_HERE, - base::Bind(&TraceSubscriberStdioWorker::OnTraceData, worker_, data_ptr)); -} - -void TraceSubscriberStdio::OnEndSystemTracing( - const scoped_refptr<base::RefCountedString>& events_str_ptr) { - BrowserThread::PostBlockingPoolSequencedTask( - __FILE__, FROM_HERE, - base::Bind(&TraceSubscriberStdioWorker::OnSystemTraceData, - worker_, - events_str_ptr)); -} - -} // namespace content diff --git a/content/browser/tracing/trace_subscriber_stdio.h b/content/browser/tracing/trace_subscriber_stdio.h deleted file mode 100644 index b9fc4f74c1..0000000000 --- a/content/browser/tracing/trace_subscriber_stdio.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_TRACING_TRACE_SUBSCRIBER_STDIO_H_ -#define CONTENT_BROWSER_TRACING_TRACE_SUBSCRIBER_STDIO_H_ - -#include <string> - -#include "base/compiler_specific.h" -#include "content/public/browser/trace_subscriber.h" -#include "content/common/content_export.h" - -namespace base { -class FilePath; -} - -namespace content { - -// Stdio implementation of TraceSubscriber. Use this to write traces to a file. -class CONTENT_EXPORT TraceSubscriberStdio - : NON_EXPORTED_BASE(public TraceSubscriber) { - public: - enum FileType { - // Output file as array, representing trace events: - // [event1, event2, ...] - FILE_TYPE_ARRAY, - // Output file as property list with one or two items: - // {traceEvents: [event1, event2, ...], - // systemTraceEvents: "event1\nevent2\n..." // optional} - FILE_TYPE_PROPERTY_LIST - }; - - // has_system_trace indicates whether system trace events are expected. - TraceSubscriberStdio(const base::FilePath& path, - FileType file_type, - bool has_system_trace); - virtual ~TraceSubscriberStdio(); - - // Implementation of TraceSubscriber - virtual void OnEndTracingComplete() OVERRIDE; - virtual void OnTraceDataCollected( - const scoped_refptr<base::RefCountedString>& data_ptr) OVERRIDE; - - // To be used as callback to DebugDaemonClient::RequestStopSystemTracing(). - virtual void OnEndSystemTracing( - const scoped_refptr<base::RefCountedString>& events_str_ptr); - - private: - class TraceSubscriberStdioWorker; - scoped_refptr<TraceSubscriberStdioWorker> worker_; - DISALLOW_COPY_AND_ASSIGN(TraceSubscriberStdio); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_TRACING_TRACE_SUBSCRIBER_STDIO_H_ diff --git a/content/browser/tracing/trace_subscriber_stdio_unittest.cc b/content/browser/tracing/trace_subscriber_stdio_unittest.cc deleted file mode 100644 index 10e51a968d..0000000000 --- a/content/browser/tracing/trace_subscriber_stdio_unittest.cc +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/tracing/trace_subscriber_stdio.h" - -#include "base/file_util.h" -#include "base/files/scoped_temp_dir.h" -#include "base/threading/sequenced_worker_pool.h" -#include "content/public/browser/browser_thread.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace content { - -class TraceSubscriberStdioTest : public ::testing::Test {}; - -TEST_F(TraceSubscriberStdioTest, CanWriteArray) { - base::ScopedTempDir trace_dir; - ASSERT_TRUE(trace_dir.CreateUniqueTempDir()); - base::FilePath trace_file(trace_dir.path().AppendASCII("trace.txt")); - { - TraceSubscriberStdio subscriber(trace_file, - TraceSubscriberStdio::FILE_TYPE_ARRAY, - false); - - std::string foo("foo"); - subscriber.OnTraceDataCollected( - make_scoped_refptr(base::RefCountedString::TakeString(&foo))); - - std::string bar("bar"); - subscriber.OnTraceDataCollected( - make_scoped_refptr(base::RefCountedString::TakeString(&bar))); - - subscriber.OnEndTracingComplete(); - } - BrowserThread::GetBlockingPool()->FlushForTesting(); - std::string result; - EXPECT_TRUE(base::ReadFileToString(trace_file, &result)); - EXPECT_EQ("[foo,bar]", result); -} - -TEST_F(TraceSubscriberStdioTest, CanWritePropertyList) { - base::ScopedTempDir trace_dir; - ASSERT_TRUE(trace_dir.CreateUniqueTempDir()); - base::FilePath trace_file(trace_dir.path().AppendASCII("trace.txt")); - { - TraceSubscriberStdio subscriber( - trace_file, - TraceSubscriberStdio::FILE_TYPE_PROPERTY_LIST, - false); - - std::string foo("foo"); - subscriber.OnTraceDataCollected( - make_scoped_refptr(base::RefCountedString::TakeString(&foo))); - - std::string bar("bar"); - subscriber.OnTraceDataCollected( - make_scoped_refptr(base::RefCountedString::TakeString(&bar))); - - subscriber.OnEndTracingComplete(); - } - BrowserThread::GetBlockingPool()->FlushForTesting(); - std::string result; - EXPECT_TRUE(base::ReadFileToString(trace_file, &result)); - EXPECT_EQ("{\"traceEvents\":[foo,bar]}", result); -} - -TEST_F(TraceSubscriberStdioTest, CanWriteSystemDataFirst) { - base::ScopedTempDir trace_dir; - ASSERT_TRUE(trace_dir.CreateUniqueTempDir()); - base::FilePath trace_file(trace_dir.path().AppendASCII("trace.txt")); - { - TraceSubscriberStdio subscriber( - trace_file, - TraceSubscriberStdio::FILE_TYPE_PROPERTY_LIST, - true); - - std::string foo("foo"); - subscriber.OnTraceDataCollected( - make_scoped_refptr(base::RefCountedString::TakeString(&foo))); - - std::string bar("bar"); - subscriber.OnTraceDataCollected( - make_scoped_refptr(base::RefCountedString::TakeString(&bar))); - - std::string systemTrace("event1\nev\"ent\"2\n"); - subscriber.OnEndSystemTracing( - make_scoped_refptr(base::RefCountedString::TakeString(&systemTrace))); - subscriber.OnEndTracingComplete(); - } - BrowserThread::GetBlockingPool()->FlushForTesting(); - std::string result; - EXPECT_TRUE(base::ReadFileToString(trace_file, &result)); - EXPECT_EQ( - "{\"traceEvents\":[foo,bar],\"" - "systemTraceEvents\":\"event1\\nev\\\"ent\\\"2\\n\"}", - result); -} - -TEST_F(TraceSubscriberStdioTest, CanWriteSystemDataLast) { - base::ScopedTempDir trace_dir; - ASSERT_TRUE(trace_dir.CreateUniqueTempDir()); - base::FilePath trace_file(trace_dir.path().AppendASCII("trace.txt")); - { - TraceSubscriberStdio subscriber( - trace_file, - TraceSubscriberStdio::FILE_TYPE_PROPERTY_LIST, - true); - - std::string foo("foo"); - subscriber.OnTraceDataCollected( - make_scoped_refptr(base::RefCountedString::TakeString(&foo))); - - std::string bar("bar"); - subscriber.OnTraceDataCollected( - make_scoped_refptr(base::RefCountedString::TakeString(&bar))); - - std::string systemTrace("event1\nev\"ent\"2\n"); - subscriber.OnEndTracingComplete(); - subscriber.OnEndSystemTracing( - make_scoped_refptr(base::RefCountedString::TakeString(&systemTrace))); - } - BrowserThread::GetBlockingPool()->FlushForTesting(); - std::string result; - EXPECT_TRUE(base::ReadFileToString(trace_file, &result)); - EXPECT_EQ( - "{\"traceEvents\":[foo,bar],\"" - "systemTraceEvents\":\"event1\\nev\\\"ent\\\"2\\n\"}", - result); -} - -} // namespace content diff --git a/content/browser/tracing/tracing_controller_browsertest.cc b/content/browser/tracing/tracing_controller_browsertest.cc index 0affc2726a..bccf90af44 100644 --- a/content/browser/tracing/tracing_controller_browsertest.cc +++ b/content/browser/tracing/tracing_controller_browsertest.cc @@ -51,7 +51,7 @@ class TracingControllerTest : public ContentBrowserTest { disable_recording_done_callback_count_++; EXPECT_TRUE(PathExists(file_path)); int64 file_size; - file_util::GetFileSize(file_path, &file_size); + base::GetFileSize(file_path, &file_size); EXPECT_TRUE(file_size > 0); quit_callback.Run(); last_actual_recording_file_path_ = file_path; @@ -72,7 +72,7 @@ class TracingControllerTest : public ContentBrowserTest { capture_monitoring_snapshot_done_callback_count_++; EXPECT_TRUE(PathExists(file_path)); int64 file_size; - file_util::GetFileSize(file_path, &file_size); + base::GetFileSize(file_path, &file_size); EXPECT_TRUE(file_size > 0); quit_callback.Run(); last_actual_monitoring_file_path_ = file_path; @@ -122,8 +122,7 @@ class TracingControllerTest : public ContentBrowserTest { base::Unretained(this), run_loop.QuitClosure()); bool result = controller->EnableRecording( - base::debug::CategoryFilter(""), TracingController::Options(), - callback); + "", TracingController::DEFAULT_OPTIONS, callback); ASSERT_TRUE(result); run_loop.Run(); EXPECT_EQ(enable_recording_done_callback_count(), 1); @@ -155,8 +154,7 @@ class TracingControllerTest : public ContentBrowserTest { base::Unretained(this), run_loop.QuitClosure()); bool result = controller->EnableMonitoring( - base::debug::CategoryFilter(""), TracingController::ENABLE_SAMPLING, - callback); + "", TracingController::ENABLE_SAMPLING, callback); ASSERT_TRUE(result); run_loop.Run(); EXPECT_EQ(enable_monitoring_done_callback_count(), 1); @@ -169,7 +167,8 @@ class TracingControllerTest : public ContentBrowserTest { CaptureMonitoringSnapshotDoneCallbackTest, base::Unretained(this), run_loop.QuitClosure()); - controller->CaptureMonitoringSnapshot(result_file_path, callback); + ASSERT_TRUE(controller->CaptureMonitoringSnapshot(result_file_path, + callback)); run_loop.Run(); EXPECT_EQ(capture_monitoring_snapshot_done_callback_count(), 1); } @@ -208,7 +207,7 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest, GetCategories) { base::Bind(&TracingControllerTest::GetCategoriesDoneCallbackTest, base::Unretained(this), run_loop.QuitClosure()); - controller->GetCategories(callback); + ASSERT_TRUE(controller->GetCategories(callback)); run_loop.Run(); EXPECT_EQ(get_categories_done_callback_count(), 1); } @@ -220,7 +219,7 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest, EnableAndDisableRecording) { IN_PROC_BROWSER_TEST_F(TracingControllerTest, EnableAndDisableRecordingWithFilePath) { base::FilePath file_path; - file_util::CreateTemporaryFile(&file_path); + base::CreateTemporaryFile(&file_path); TestEnableAndDisableRecording(file_path); EXPECT_EQ(file_path.value(), last_actual_recording_file_path().value()); } @@ -231,7 +230,7 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest, TracingController* controller = TracingController::GetInstance(); EXPECT_TRUE(controller->EnableRecording( - base::debug::CategoryFilter(""), TracingController::Options(), + "", TracingController::DEFAULT_OPTIONS, TracingController::EnableRecordingDoneCallback())); EXPECT_TRUE(controller->DisableRecording( base::FilePath(), TracingController::TracingFileResultCallback())); @@ -246,7 +245,7 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest, IN_PROC_BROWSER_TEST_F(TracingControllerTest, EnableCaptureAndDisableMonitoringWithFilePath) { base::FilePath file_path; - file_util::CreateTemporaryFile(&file_path); + base::CreateTemporaryFile(&file_path); TestEnableCaptureAndDisableMonitoring(file_path); EXPECT_EQ(file_path.value(), last_actual_monitoring_file_path().value()); } @@ -258,7 +257,7 @@ IN_PROC_BROWSER_TEST_F( TracingController* controller = TracingController::GetInstance(); EXPECT_TRUE(controller->EnableMonitoring( - base::debug::CategoryFilter(""), TracingController::ENABLE_SAMPLING, + "", TracingController::ENABLE_SAMPLING, TracingController::EnableMonitoringDoneCallback())); controller->CaptureMonitoringSnapshot( base::FilePath(), TracingController::TracingFileResultCallback()); diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc index 1340b67e99..bc7cee2f93 100644 --- a/content/browser/tracing/tracing_controller_impl.cc +++ b/content/browser/tracing/tracing_controller_impl.cc @@ -5,6 +5,7 @@ #include "content/browser/tracing/tracing_controller_impl.h" #include "base/bind.h" +#include "base/debug/trace_event.h" #include "base/file_util.h" #include "base/json/string_escape.h" #include "base/strings/string_number_conversions.h" @@ -66,8 +67,8 @@ TracingControllerImpl::ResultFile::ResultFile(const base::FilePath& path) void TracingControllerImpl::ResultFile::OpenTask() { if (path_.empty()) - file_util::CreateTemporaryFile(&path_); - file_ = file_util::OpenFile(path_, "w"); + base::CreateTemporaryFile(&path_); + file_ = base::OpenFile(path_, "w"); if (!file_) { LOG(ERROR) << "Failed to open " << path_.value(); return; @@ -103,7 +104,7 @@ void TracingControllerImpl::ResultFile::CloseTask( const char* trailout = "]}"; size_t written = fwrite(trailout, strlen(trailout), 1, file_); DCHECK(written == 1); - file_util::CloseFile(file_); + base::CloseFile(file_); file_ = NULL; BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); @@ -118,9 +119,7 @@ TracingControllerImpl::TracingControllerImpl() : // Tracing may have been enabled by ContentMainRunner if kTraceStartup // is specified in command line. is_recording_(TraceLog::GetInstance()->IsEnabled()), - is_monitoring_(false), - category_filter_( - base::debug::CategoryFilter::kDefaultCategoryFilterString) { + is_monitoring_(false) { } TracingControllerImpl::~TracingControllerImpl() { @@ -132,7 +131,7 @@ TracingControllerImpl* TracingControllerImpl::GetInstance() { return g_controller.Pointer(); } -void TracingControllerImpl::GetCategories( +bool TracingControllerImpl::GetCategories( const GetCategoriesDoneCallback& callback) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -140,14 +139,19 @@ void TracingControllerImpl::GetCategories( // message. So to get known categories, just begin and end tracing immediately // afterwards. This will ping all the child processes for categories. pending_get_categories_done_callback_ = callback; - EnableRecording(base::debug::CategoryFilter("*"), - TracingController::Options(), - EnableRecordingDoneCallback()); - DisableRecording(base::FilePath(), TracingFileResultCallback()); + if (!EnableRecording("*", TracingController::Options(), + EnableRecordingDoneCallback())) { + pending_get_categories_done_callback_.Reset(); + return false; + } + + bool ok = DisableRecording(base::FilePath(), TracingFileResultCallback()); + DCHECK(ok); + return true; } bool TracingControllerImpl::EnableRecording( - const base::debug::CategoryFilter& filter, + const std::string& category_filter, TracingController::Options options, const EnableRecordingDoneCallback& callback) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -168,13 +172,14 @@ bool TracingControllerImpl::EnableRecording( } // TODO(haraken): How to handle ENABLE_SYSTRACE? - TraceLog::GetInstance()->SetEnabled(filter, trace_options); + TraceLog::GetInstance()->SetEnabled( + base::debug::CategoryFilter(category_filter), trace_options); is_recording_ = true; - category_filter_ = TraceLog::GetInstance()->GetCurrentCategoryFilter(); // Notify all child processes. - for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { - it->get()->SendBeginTracing(category_filter_.ToString(), trace_options); + for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); + it != trace_message_filters_.end(); ++it) { + it->get()->SendBeginTracing(category_filter, trace_options); } if (!callback.is_null()) @@ -204,15 +209,13 @@ bool TracingControllerImpl::DisableRecording( if (!callback.is_null() || !result_file_path.empty()) result_file_.reset(new ResultFile(result_file_path)); - // There could be a case where there are no child processes and filters_ - // is empty. In that case we can immediately tell the subscriber that tracing - // has ended. To avoid recursive calls back to the subscriber, we will just - // use the existing asynchronous OnDisableRecordingAcked code. // Count myself (local trace) in pending_disable_recording_ack_count_, // acked below. - pending_disable_recording_ack_count_ = filters_.size() + 1; + pending_disable_recording_ack_count_ = trace_message_filters_.size() + 1; - // Handle special case of zero child processes. + // Handle special case of zero child processes by immediately telling the + // caller that tracing has ended. Use asynchronous OnDisableRecordingAcked + // to avoid recursive call back to the caller. if (pending_disable_recording_ack_count_ == 1) { // Ack asynchronously now, because we don't have any children to wait for. std::vector<std::string> category_groups; @@ -223,14 +226,15 @@ bool TracingControllerImpl::DisableRecording( } // Notify all child processes. - for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { + for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); + it != trace_message_filters_.end(); ++it) { it->get()->SendEndTracing(); } return true; } bool TracingControllerImpl::EnableMonitoring( - const base::debug::CategoryFilter& filter, + const std::string& category_filter, TracingController::Options options, const EnableMonitoringDoneCallback& callback) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -248,12 +252,14 @@ bool TracingControllerImpl::EnableMonitoring( monitoring_tracing_options |= base::debug::TraceLog::MONITOR_SAMPLING; TraceLog::GetInstance()->SetEnabled( - filter, base::debug::TraceLog::Options(monitoring_tracing_options)); + base::debug::CategoryFilter(category_filter), + static_cast<TraceLog::Options>(monitoring_tracing_options)); // Notify all child processes. - for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { - it->get()->SendEnableMonitoring(filter.ToString(), - base::debug::TraceLog::Options(monitoring_tracing_options)); + for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); + it != trace_message_filters_.end(); ++it) { + it->get()->SendEnableMonitoring(category_filter, + static_cast<TraceLog::Options>(monitoring_tracing_options)); } if (!callback.is_null()) @@ -272,7 +278,8 @@ bool TracingControllerImpl::DisableMonitoring( TraceLog::GetInstance()->SetDisabled(); // Notify all child processes. - for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { + for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); + it != trace_message_filters_.end(); ++it) { it->get()->SendDisableMonitoring(); } @@ -283,34 +290,34 @@ bool TracingControllerImpl::DisableMonitoring( void TracingControllerImpl::GetMonitoringStatus( bool* out_enabled, - base::debug::CategoryFilter* out_filter, + std::string* out_category_filter, TracingController::Options* out_options) { NOTIMPLEMENTED(); } -void TracingControllerImpl::CaptureMonitoringSnapshot( +bool TracingControllerImpl::CaptureMonitoringSnapshot( const base::FilePath& result_file_path, const TracingFileResultCallback& callback) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (!can_disable_monitoring()) - return; + return false; if (callback.is_null() && result_file_path.empty()) - return; + return false; pending_capture_monitoring_snapshot_done_callback_ = callback; monitoring_snapshot_file_.reset(new ResultFile(result_file_path)); - // There could be a case where there are no child processes and filters_ - // is empty. In that case we can immediately tell the subscriber that tracing - // has ended. To avoid recursive calls back to the subscriber, we will just - // use the existing asynchronous OnCaptureMonitoringSnapshotAcked code. // Count myself in pending_capture_monitoring_snapshot_ack_count_, // acked below. - pending_capture_monitoring_snapshot_ack_count_ = filters_.size() + 1; + pending_capture_monitoring_snapshot_ack_count_ = + trace_message_filters_.size() + 1; - // Handle special case of zero child processes. + // Handle special case of zero child processes by immediately telling the + // caller that capturing snapshot has ended. Use asynchronous + // OnCaptureMonitoringSnapshotAcked to avoid recursive call back to the + // caller. if (pending_capture_monitoring_snapshot_ack_count_ == 1) { // Ack asynchronously now, because we don't have any children to wait for. BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, @@ -319,13 +326,16 @@ void TracingControllerImpl::CaptureMonitoringSnapshot( } // Notify all child processes. - for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { + for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); + it != trace_message_filters_.end(); ++it) { it->get()->SendCaptureMonitoringSnapshot(); } #if defined(OS_ANDROID) TraceLog::GetInstance()->AddClockSyncMetadataEvent(); #endif + + return true; } bool TracingControllerImpl::GetTraceBufferPercentFull( @@ -338,7 +348,8 @@ bool TracingControllerImpl::GetTraceBufferPercentFull( pending_trace_buffer_percent_full_callback_ = callback; // Count myself in pending_trace_buffer_percent_full_ack_count_, acked below. - pending_trace_buffer_percent_full_ack_count_ = filters_.size() + 1; + pending_trace_buffer_percent_full_ack_count_ = + trace_message_filters_.size() + 1; maximum_trace_buffer_percent_full_ = 0; // Handle special case of zero child processes. @@ -350,36 +361,86 @@ bool TracingControllerImpl::GetTraceBufferPercentFull( } // Notify all child processes. - for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { + for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); + it != trace_message_filters_.end(); ++it) { it->get()->SendGetTraceBufferPercentFull(); } return true; } -void TracingControllerImpl::AddFilter(TraceMessageFilter* filter) { +bool TracingControllerImpl::SetWatchEvent( + const std::string& category_name, + const std::string& event_name, + const WatchEventCallback& callback) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (callback.is_null()) + return false; + + watch_category_name_ = category_name; + watch_event_name_ = event_name; + watch_event_callback_ = callback; + + TraceLog::GetInstance()->SetWatchEvent( + category_name, event_name, + base::Bind(&TracingControllerImpl::OnWatchEventMatched, + base::Unretained(this))); + + for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); + it != trace_message_filters_.end(); ++it) { + it->get()->SendSetWatchEvent(category_name, event_name); + } + return true; +} + +bool TracingControllerImpl::CancelWatchEvent() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (!can_cancel_watch_event()) + return false; + + for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin(); + it != trace_message_filters_.end(); ++it) { + it->get()->SendCancelWatchEvent(); + } + + watch_event_callback_.Reset(); + return true; +} + +void TracingControllerImpl::AddTraceMessageFilter( + TraceMessageFilter* trace_message_filter) { if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&TracingControllerImpl::AddFilter, base::Unretained(this), - make_scoped_refptr(filter))); + base::Bind(&TracingControllerImpl::AddTraceMessageFilter, + base::Unretained(this), + make_scoped_refptr(trace_message_filter))); return; } - filters_.insert(filter); + trace_message_filters_.insert(trace_message_filter); + if (can_cancel_watch_event()) { + trace_message_filter->SendSetWatchEvent(watch_category_name_, + watch_event_name_); + } if (can_disable_recording()) { - std::string cf_str = category_filter_.ToString(); - filter->SendBeginTracing(cf_str, TraceLog::GetInstance()->trace_options()); + trace_message_filter->SendBeginTracing( + TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString(), + TraceLog::GetInstance()->trace_options()); } } -void TracingControllerImpl::RemoveFilter(TraceMessageFilter* filter) { +void TracingControllerImpl::RemoveTraceMessageFilter( + TraceMessageFilter* trace_message_filter) { if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&TracingControllerImpl::RemoveFilter, base::Unretained(this), - make_scoped_refptr(filter))); + base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter, + base::Unretained(this), + make_scoped_refptr(trace_message_filter))); return; } - filters_.erase(filter); + trace_message_filters_.erase(trace_message_filter); } void TracingControllerImpl::OnDisableRecordingAcked( @@ -405,6 +466,7 @@ void TracingControllerImpl::OnDisableRecordingAcked( TraceLog::GetInstance()->Flush( base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, base::Unretained(this))); + return; } if (pending_disable_recording_ack_count_ != 0) @@ -456,6 +518,7 @@ void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked() { TraceLog::GetInstance()->FlushButLeaveBufferIntact( base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected, base::Unretained(this))); + return; } if (pending_capture_monitoring_snapshot_ack_count_ != 0) @@ -569,4 +632,16 @@ void TracingControllerImpl::OnTraceBufferPercentFullReply(float percent_full) { } } +void TracingControllerImpl::OnWatchEventMatched() { + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&TracingControllerImpl::OnWatchEventMatched, + base::Unretained(this))); + return; + } + + if (!watch_event_callback_.is_null()) + watch_event_callback_.Run(); +} + } // namespace content diff --git a/content/browser/tracing/tracing_controller_impl.h b/content/browser/tracing/tracing_controller_impl.h index 7eab907ce9..ed3c8fd651 100644 --- a/content/browser/tracing/tracing_controller_impl.h +++ b/content/browser/tracing/tracing_controller_impl.h @@ -11,9 +11,12 @@ #include "base/files/file_path.h" #include "base/lazy_instance.h" -#include "content/public/browser/trace_subscriber.h" #include "content/public/browser/tracing_controller.h" +namespace base { +class RefCountedString; +} + namespace content { class TraceMessageFilter; @@ -23,32 +26,36 @@ class TracingControllerImpl : public TracingController { static TracingControllerImpl* GetInstance(); // TracingController implementation. - virtual void GetCategories( + virtual bool GetCategories( const GetCategoriesDoneCallback& callback) OVERRIDE; virtual bool EnableRecording( - const base::debug::CategoryFilter& filter, + const std::string& category_filter, TracingController::Options options, const EnableRecordingDoneCallback& callback) OVERRIDE; virtual bool DisableRecording( const base::FilePath& result_file_path, const TracingFileResultCallback& callback) OVERRIDE; - virtual bool EnableMonitoring(const base::debug::CategoryFilter& filter, + virtual bool EnableMonitoring(const std::string& category_filter, TracingController::Options options, const EnableMonitoringDoneCallback& callback) OVERRIDE; virtual bool DisableMonitoring( const DisableMonitoringDoneCallback& callback) OVERRIDE; virtual void GetMonitoringStatus( bool* out_enabled, - base::debug::CategoryFilter* out_filter, + std::string* out_category_filter, TracingController::Options* out_options) OVERRIDE; - virtual void CaptureMonitoringSnapshot( + virtual bool CaptureMonitoringSnapshot( const base::FilePath& result_file_path, const TracingFileResultCallback& callback) OVERRIDE; virtual bool GetTraceBufferPercentFull( const GetTraceBufferPercentFullCallback& callback) OVERRIDE; + virtual bool SetWatchEvent(const std::string& category_name, + const std::string& event_name, + const WatchEventCallback& callback) OVERRIDE; + virtual bool CancelWatchEvent() OVERRIDE; private: - typedef std::set<scoped_refptr<TraceMessageFilter> > FilterMap; + typedef std::set<scoped_refptr<TraceMessageFilter> > TraceMessageFilterMap; class ResultFile; friend struct base::DefaultLazyInstanceTraits<TracingControllerImpl>; @@ -77,9 +84,13 @@ class TracingControllerImpl : public TracingController { return pending_trace_buffer_percent_full_callback_.is_null(); } + bool can_cancel_watch_event() const { + return !watch_event_callback_.is_null(); + } + // Methods for use by TraceMessageFilter. - void AddFilter(TraceMessageFilter* filter); - void RemoveFilter(TraceMessageFilter* filter); + void AddTraceMessageFilter(TraceMessageFilter* trace_message_filter); + void RemoveTraceMessageFilter(TraceMessageFilter* trace_message_filter); void OnTraceDataCollected( const scoped_refptr<base::RefCountedString>& events_str_ptr); @@ -102,10 +113,11 @@ class TracingControllerImpl : public TracingController { void OnCaptureMonitoringSnapshotAcked(); void OnMonitoringSnapshotFileClosed(); - void OnTraceNotification(int notification); void OnTraceBufferPercentFullReply(float percent_full); - FilterMap filters_; + void OnWatchEventMatched(); + + TraceMessageFilterMap trace_message_filters_; // Pending acks for DisableRecording. int pending_disable_recording_ack_count_; // Pending acks for CaptureMonitoringSnapshot. @@ -122,8 +134,11 @@ class TracingControllerImpl : public TracingController { TracingFileResultCallback pending_capture_monitoring_snapshot_done_callback_; GetTraceBufferPercentFullCallback pending_trace_buffer_percent_full_callback_; + std::string watch_category_name_; + std::string watch_event_name_; + WatchEventCallback watch_event_callback_; + std::set<std::string> known_category_groups_; - base::debug::CategoryFilter category_filter_; scoped_ptr<ResultFile> result_file_; scoped_ptr<ResultFile> monitoring_snapshot_file_; DISALLOW_COPY_AND_ASSIGN(TracingControllerImpl); diff --git a/content/browser/tracing/tracing_ui.cc b/content/browser/tracing/tracing_ui.cc index 6e471c28a8..e59f5667cb 100644 --- a/content/browser/tracing/tracing_ui.cc +++ b/content/browser/tracing/tracing_ui.cc @@ -86,11 +86,10 @@ bool OnBeginRecording(const std::string& data64, if (use_continuous_tracing) tracing_options |= TracingController::RECORD_CONTINUOUSLY; - base::debug::CategoryFilter category_filter(category_filter_string); return TracingController::GetInstance()->EnableRecording( - category_filter, + category_filter_string, static_cast<TracingController::Options>(tracing_options), - base::Bind(OnRecordingEnabledAck, callback)); + base::Bind(&OnRecordingEnabledAck, callback)); } void OnRecordingEnabledAck(const WebUIDataSource::GotDataCallback& callback) { diff --git a/content/browser/web_contents/touch_editable_impl_aura.cc b/content/browser/web_contents/touch_editable_impl_aura.cc index 6f856251d0..ed002c7d9c 100644 --- a/content/browser/web_contents/touch_editable_impl_aura.cc +++ b/content/browser/web_contents/touch_editable_impl_aura.cc @@ -307,7 +307,7 @@ bool TouchEditableImplAura::IsCommandIdEnabled(int command_id) const { case IDS_APP_COPY: return has_selection; case IDS_APP_PASTE: { - string16 result; + base::string16 result; ui::Clipboard::GetForCurrentThread()->ReadText( ui::CLIPBOARD_TYPE_COPY_PASTE, &result); return editable && !result.empty(); diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc new file mode 100644 index 0000000000..88922b1922 --- /dev/null +++ b/content/browser/web_contents/web_contents_android.cc @@ -0,0 +1,58 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/web_contents/web_contents_android.h" + +#include "base/android/jni_android.h" +#include "base/logging.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/web_contents.h" +#include "jni/WebContentsImpl_jni.h" + +using base::android::AttachCurrentThread; + +namespace content { + +// static +WebContents* WebContents::FromJavaWebContents( + jobject jweb_contents_android) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (!jweb_contents_android) + return NULL; + + WebContentsAndroid* web_contents_android = + reinterpret_cast<WebContentsAndroid*>( + Java_WebContentsImpl_getNativePointer(AttachCurrentThread(), + jweb_contents_android)); + if (!web_contents_android) + return NULL; + return web_contents_android->web_contents(); +} + +// static +bool WebContentsAndroid::Register(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +WebContentsAndroid::WebContentsAndroid(WebContents* web_contents) + : web_contents_(web_contents), + navigation_controller_(&(web_contents->GetController())) { + JNIEnv* env = AttachCurrentThread(); + obj_.Reset(env, + Java_WebContentsImpl_create( + env, + reinterpret_cast<intptr_t>(this), + navigation_controller_.GetJavaObject().obj()).obj()); +} + +WebContentsAndroid::~WebContentsAndroid() { + Java_WebContentsImpl_destroy(AttachCurrentThread(), obj_.obj()); +} + +base::android::ScopedJavaLocalRef<jobject> +WebContentsAndroid::GetJavaObject() { + return base::android::ScopedJavaLocalRef<jobject>(obj_); +} + +} // namespace content diff --git a/content/browser/web_contents/web_contents_android.h b/content/browser/web_contents/web_contents_android.h new file mode 100644 index 0000000000..a9595e2a4d --- /dev/null +++ b/content/browser/web_contents/web_contents_android.h @@ -0,0 +1,46 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_ANDROID_H_ +#define CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_ANDROID_H_ + +#include <jni.h> + +#include "base/android/scoped_java_ref.h" +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/supports_user_data.h" +#include "content/browser/frame_host/navigation_controller_android.h" +#include "content/common/content_export.h" + +namespace content { + +class WebContents; + +// Android wrapper around WebContents that provides safer passage from java and +// back to native and provides java with a means of communicating with its +// native counterpart. +class CONTENT_EXPORT WebContentsAndroid + : public base::SupportsUserData::Data { + public: + static bool Register(JNIEnv* env); + + explicit WebContentsAndroid(WebContents* web_contents); + virtual ~WebContentsAndroid(); + + WebContents* web_contents() const { return web_contents_; } + + base::android::ScopedJavaLocalRef<jobject> GetJavaObject(); + + private: + WebContents* web_contents_; + NavigationControllerAndroid navigation_controller_; + base::android::ScopedJavaGlobalRef<jobject> obj_; + + DISALLOW_COPY_AND_ASSIGN(WebContentsAndroid); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_WEB_CONTENTS_WEB_CONTENTS_ANDROID_H_ diff --git a/content/browser/web_contents/web_contents_delegate_unittest.cc b/content/browser/web_contents/web_contents_delegate_unittest.cc index d5d60c3725..0de5919edd 100644 --- a/content/browser/web_contents/web_contents_delegate_unittest.cc +++ b/content/browser/web_contents/web_contents_delegate_unittest.cc @@ -5,10 +5,10 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" -#include "content/browser/renderer_host/test_render_view_host.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/test/test_browser_context.h" +#include "content/test/test_render_view_host.h" #include "testing/gtest/include/gtest/gtest.h" namespace content { diff --git a/content/browser/web_contents/web_contents_drag_win.cc b/content/browser/web_contents/web_contents_drag_win.cc index 72c17583ed..ffc8713f86 100644 --- a/content/browser/web_contents/web_contents_drag_win.cc +++ b/content/browser/web_contents/web_contents_drag_win.cc @@ -227,7 +227,7 @@ void WebContentsDragWin::PrepareDragForDownload( const GURL& page_url, const std::string& page_encoding) { // Parse the download metadata. - string16 mime_type; + base::string16 mime_type; base::FilePath file_name; GURL download_url; if (!ParseDownloadMetadata(drop_data.download_metadata, @@ -247,8 +247,8 @@ void WebContentsDragWin::PrepareDragForDownload( UTF16ToUTF8(mime_type), default_name); base::FilePath temp_dir_path; - if (!file_util::CreateNewTempDirectory( - FILE_PATH_LITERAL("chrome_drag"), &temp_dir_path)) + if (!base::CreateNewTempDirectory(FILE_PATH_LITERAL("chrome_drag"), + &temp_dir_path)) return; base::FilePath download_path = temp_dir_path.Append(generated_download_file_name); @@ -284,7 +284,7 @@ void WebContentsDragWin::PrepareDragForFileContents( // Images without ALT text will only have a file extension so we need to // synthesize one from the provided extension and URL. if (file_name.BaseName().RemoveExtension().empty()) { - const string16 extension = file_name.Extension(); + const base::string16 extension = file_name.Extension(); // Retrieve the name from the URL. file_name = base::FilePath( net::GetSuggestedFilename(drop_data.url, "", "", "", "", "")); diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index b83285caf6..d9ac631726 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -12,6 +12,7 @@ #include "base/logging.h" #include "base/metrics/histogram.h" #include "base/metrics/stats_counters.h" +#include "base/process/process.h" #include "base/strings/string16.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -29,7 +30,8 @@ #include "content/browser/download/save_package.h" #include "content/browser/frame_host/interstitial_page_impl.h" #include "content/browser/frame_host/navigation_entry_impl.h" -#include "content/browser/frame_host/navigator.h" +#include "content/browser/frame_host/navigator_impl.h" +#include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/host_zoom_map_impl.h" #include "content/browser/loader/resource_dispatcher_host_impl.h" #include "content/browser/message_port_message_filter.h" @@ -45,6 +47,7 @@ #include "content/browser/webui/web_ui_impl.h" #include "content/common/browser_plugin/browser_plugin_constants.h" #include "content/common/browser_plugin/browser_plugin_messages.h" +#include "content/common/frame_messages.h" #include "content/common/image_messages.h" #include "content/common/ssl_status_serialization.h" #include "content/common/view_messages.h" @@ -73,6 +76,7 @@ #include "content/public/common/content_constants.h" #include "content/public/common/content_switches.h" #include "content/public/common/page_zoom.h" +#include "content/public/common/result_codes.h" #include "content/public/common/url_constants.h" #include "net/base/mime_util.h" #include "net/base/net_util.h" @@ -89,6 +93,7 @@ #if defined(OS_ANDROID) #include "content/browser/android/date_time_chooser_android.h" #include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h" +#include "content/browser/web_contents/web_contents_android.h" #include "content/common/java_bridge_messages.h" #include "content/public/browser/android/content_view_core.h" #endif @@ -154,6 +159,10 @@ namespace { const char kDotGoogleDotCom[] = ".google.com"; +#if defined(OS_ANDROID) +const char kWebContentsAndroidKey[] = "web_contents_android"; +#endif // OS_ANDROID + base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> > g_created_callbacks = LAZY_INSTANCE_INITIALIZER; @@ -343,12 +352,13 @@ WebContentsImpl::WebContentsImpl( #if defined(OS_WIN) && defined(USE_AURA) accessible_parent_(NULL), #endif - frame_tree_(new Navigator(&controller_, this), this, this, this), + frame_tree_(new NavigatorImpl(&controller_, this), + this, this, this, this), is_loading_(false), crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING), crashed_error_code_(0), waiting_for_response_(false), - load_state_(net::LOAD_STATE_IDLE, string16()), + load_state_(net::LOAD_STATE_IDLE, base::string16()), upload_size_(0), upload_position_(0), displayed_insecure_content_(false), @@ -363,7 +373,7 @@ WebContentsImpl::WebContentsImpl( maximum_zoom_percent_(static_cast<int>(kMaximumZoomFactor * 100)), temporary_zoom_settings_(false), color_chooser_identifier_(0), - message_source_(NULL), + render_view_message_source_(NULL), fullscreen_widget_routing_id_(MSG_ROUTING_NONE) { for (size_t i = 0; i < g_created_callbacks.Get().size(); i++) g_created_callbacks.Get().at(i).Run(this); @@ -471,6 +481,13 @@ RenderFrameHostManager* WebContentsImpl::GetRenderManagerForTesting() { bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host, const IPC::Message& message) { + return OnMessageReceived(render_view_host, NULL, message); +} + +bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host, + RenderFrameHost* render_frame_host, + const IPC::Message& message) { + DCHECK(render_view_host || render_frame_host); if (GetWebUI() && static_cast<WebUIImpl*>(GetWebUI())->OnMessageReceived(message)) { return true; @@ -483,11 +500,13 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host, return true; // Message handlers should be aware of which RenderViewHost sent the - // message, which is temporarily stored in message_source_. - message_source_ = render_view_host; + // message, which is temporarily stored in render_view_message_source_. + render_view_message_source_ = render_view_host; bool handled = true; bool message_is_ok = true; IPC_BEGIN_MESSAGE_MAP_EX(WebContentsImpl, message, message_is_ok) + IPC_MESSAGE_HANDLER(FrameHostMsg_PepperPluginHung, OnPepperPluginHung) + IPC_MESSAGE_HANDLER(FrameHostMsg_PluginCrashed, OnPluginCrashed) IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache, OnDidLoadResourceFromMemoryCache) IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent, @@ -506,13 +525,11 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host, IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterProtocolHandler, OnRegisterProtocolHandler) IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply, OnFindReply) - IPC_MESSAGE_HANDLER(ViewHostMsg_CrashedPlugin, OnCrashedPlugin) IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed, OnAppCacheAccessed) IPC_MESSAGE_HANDLER(ViewHostMsg_OpenColorChooser, OnOpenColorChooser) IPC_MESSAGE_HANDLER(ViewHostMsg_EndColorChooser, OnEndColorChooser) IPC_MESSAGE_HANDLER(ViewHostMsg_SetSelectedColorInColorChooser, OnSetSelectedColorInColorChooser) - IPC_MESSAGE_HANDLER(ViewHostMsg_PepperPluginHung, OnPepperPluginHung) IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend, OnWebUISend) IPC_MESSAGE_HANDLER(ViewHostMsg_RequestPpapiBrokerPermission, OnRequestPpapiBrokerPermission) @@ -535,7 +552,7 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host, OnFirstVisuallyNonEmptyPaint) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP_EX() - message_source_ = NULL; + render_view_message_source_ = NULL; if (!message_is_ok) { RecordAction(UserMetricsAction("BadMessageTerminate_RVD")); @@ -606,6 +623,10 @@ RenderProcessHost* WebContentsImpl::GetRenderProcessHost() const { return host ? host->GetProcess() : NULL; } +RenderFrameHost* WebContentsImpl::GetMainFrame() { + return frame_tree_.root()->render_frame_host(); +} + RenderViewHost* WebContentsImpl::GetRenderViewHost() const { return GetRenderManager()->current_host(); } @@ -727,7 +748,7 @@ gfx::NativeViewAccessible accessible_parent) { } #endif -const string16& WebContentsImpl::GetTitle() const { +const base::string16& WebContentsImpl::GetTitle() const { // Transient entries take precedence. They are used for interstitial pages // that are shown on top of existing pages. NavigationEntry* entry = controller_.GetTransientEntry(); @@ -744,7 +765,7 @@ const string16& WebContentsImpl::GetTitle() const { entry = controller_.GetVisibleEntry(); if (!(entry && entry->IsViewSourceMode())) { // Give the Web UI the chance to override our title. - const string16& title = our_web_ui->GetOverriddenTitle(); + const base::string16& title = our_web_ui->GetOverriddenTitle(); if (!title.empty()) return title; } @@ -832,7 +853,7 @@ const net::LoadStateWithParam& WebContentsImpl::GetLoadState() const { return load_state_; } -const string16& WebContentsImpl::GetLoadStateHost() const { +const base::string16& WebContentsImpl::GetLoadStateHost() const { return load_state_host_; } @@ -1252,6 +1273,7 @@ void WebContentsImpl::LostMouseLock() { } void WebContentsImpl::CreateNewWindow( + int render_process_id, int route_id, int main_frame_route_id, const ViewHostMsg_CreateWindow_Params& params, @@ -1262,11 +1284,30 @@ void WebContentsImpl::CreateNewWindow( // SiteInstance in its own BrowsingInstance. bool is_guest = GetRenderProcessHost()->IsGuest(); + // If the opener is to be suppressed, the new window can be in any process. + // Since routing ids are process specific, we must not have one passed in + // as argument here. + DCHECK(!params.opener_suppressed || route_id == MSG_ROUTING_NONE); + scoped_refptr<SiteInstance> site_instance = params.opener_suppressed && !is_guest ? SiteInstance::CreateForURL(GetBrowserContext(), params.target_url) : GetSiteInstance(); + // A message to create a new window can only come from the active process for + // this WebContentsImpl instance. If any other process sends the request, + // it is invalid and the process must be terminated. + if (GetRenderProcessHost()->GetID() != render_process_id) { + base::ProcessHandle process_handle = + RenderProcessHost::FromID(render_process_id)->GetHandle(); + if (process_handle != base::kNullProcessHandle) { + RecordAction( + UserMetricsAction("Terminate_ProcessMismatch_CreateNewWindow")); + base::KillProcess(process_handle, content::RESULT_CODE_KILLED, false); + } + return; + } + // We must assign the SessionStorageNamespace before calling Init(). // // http://crbug.com/142685 @@ -1371,19 +1412,36 @@ void WebContentsImpl::CreateNewWindow( } } -void WebContentsImpl::CreateNewWidget(int route_id, +void WebContentsImpl::CreateNewWidget(int render_process_id, + int route_id, blink::WebPopupType popup_type) { - CreateNewWidget(route_id, false, popup_type); + CreateNewWidget(render_process_id, route_id, false, popup_type); } -void WebContentsImpl::CreateNewFullscreenWidget(int route_id) { - CreateNewWidget(route_id, true, blink::WebPopupTypeNone); +void WebContentsImpl::CreateNewFullscreenWidget(int render_process_id, + int route_id) { + CreateNewWidget(render_process_id, route_id, true, blink::WebPopupTypeNone); } -void WebContentsImpl::CreateNewWidget(int route_id, +void WebContentsImpl::CreateNewWidget(int render_process_id, + int route_id, bool is_fullscreen, blink::WebPopupType popup_type) { RenderProcessHost* process = GetRenderProcessHost(); + // A message to create a new widget can only come from the active process for + // this WebContentsImpl instance. If any other process sends the request, + // it is invalid and the process must be terminated. + if (process->GetID() != render_process_id) { + base::ProcessHandle process_handle = + RenderProcessHost::FromID(render_process_id)->GetHandle(); + if (process_handle != base::kNullProcessHandle) { + RecordAction( + UserMetricsAction("Terminate_ProcessMismatch_CreateNewWidget")); + base::KillProcess(process_handle, content::RESULT_CODE_KILLED, false); + } + return; + } + RenderWidgetHostImpl* widget_host = new RenderWidgetHostImpl(this, process, route_id, IsHidden()); created_widgets_.insert(widget_host); @@ -1978,68 +2036,37 @@ void WebContentsImpl::SetFocusToLocationBar(bool select_all) { delegate_->SetFocusToLocationBar(select_all); } -void WebContentsImpl::DidStartProvisionalLoadForFrame( - RenderViewHost* render_view_host, +void WebContentsImpl::DidStartProvisionalLoad( + RenderFrameHostImpl* render_frame_host, int64 frame_id, int64 parent_frame_id, bool is_main_frame, - const GURL& url) { - bool is_error_page = (url.spec() == kUnreachableWebDataURL); - bool is_iframe_srcdoc = (url.spec() == kAboutSrcDocURL); - GURL validated_url(url); - RenderProcessHost* render_process_host = - render_view_host->GetProcess(); - RenderViewHost::FilterURL(render_process_host, false, &validated_url); - - if (is_main_frame) { + const GURL& validated_url, + bool is_error_page, + bool is_iframe_srcdoc) { + if (is_main_frame) DidChangeLoadProgress(0); - // If there is no browser-initiated pending entry for this navigation and it - // is not for the error URL, create a pending entry using the current - // SiteInstance, and ensure the address bar updates accordingly. We don't - // know the referrer or extra headers at this point, but the referrer will - // be set properly upon commit. - NavigationEntryImpl* pending_entry = - NavigationEntryImpl::FromNavigationEntry(controller_.GetPendingEntry()); - bool has_browser_initiated_pending_entry = pending_entry && - !pending_entry->is_renderer_initiated(); - if (!has_browser_initiated_pending_entry && !is_error_page) { - NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry( - controller_.CreateNavigationEntry(validated_url, - content::Referrer(), - content::PAGE_TRANSITION_LINK, - true /* is_renderer_initiated */, - std::string(), - GetBrowserContext())); - entry->set_site_instance( - static_cast<SiteInstanceImpl*>(GetSiteInstance())); - // TODO(creis): If there's a pending entry already, find a safe way to - // update it instead of replacing it and copying over things like this. - if (pending_entry) { - entry->set_transferred_global_request_id( - pending_entry->transferred_global_request_id()); - entry->set_should_replace_entry(pending_entry->should_replace_entry()); - entry->set_redirect_chain(pending_entry->redirect_chain()); - } - controller_.SetPendingEntry(entry); - NotifyNavigationStateChanged(content::INVALIDATE_TYPE_URL); - } - } - // Notify observers about the start of the provisional load. FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidStartProvisionalLoadForFrame(frame_id, parent_frame_id, is_main_frame, validated_url, is_error_page, - is_iframe_srcdoc, render_view_host)); + is_iframe_srcdoc, render_frame_host->render_view_host())); if (is_main_frame) { - // Notify observers about the provisional change in the main frame URL. - FOR_EACH_OBSERVER(WebContentsObserver, observers_, - ProvisionalChangeToMainFrameUrl(validated_url, - render_view_host)); + FOR_EACH_OBSERVER( + WebContentsObserver, + observers_, + ProvisionalChangeToMainFrameUrl(validated_url, + render_frame_host->render_view_host())); } } +void WebContentsImpl::NotifyChangedNavigationState( + InvalidateTypes changed_flags) { + NotifyNavigationStateChanged(changed_flags); +} + void WebContentsImpl::DidRedirectProvisionalLoad( RenderViewHost* render_view_host, int32 page_id, @@ -2149,8 +2176,11 @@ void WebContentsImpl::OnDidLoadResourceFromMemoryCache( net::CertStatus cert_status = 0; int security_bits = -1; int connection_status = 0; + SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids; DeserializeSecurityInfo(security_info, &cert_id, &cert_status, - &security_bits, &connection_status); + &security_bits, &connection_status, + &signed_certificate_timestamp_ids); + // TODO(alcutter,eranm): Pass signed_certificate_timestamp_ids into details LoadFromMemoryCacheDetails details( url, GetRenderProcessHost()->GetID(), cert_id, cert_status, http_method, mime_type, resource_type); @@ -2195,8 +2225,9 @@ void WebContentsImpl::OnDidRunInsecureContent( } void WebContentsImpl::OnDocumentLoadedInFrame(int64 frame_id) { - FOR_EACH_OBSERVER(WebContentsObserver, observers_, - DocumentLoadedInFrame(frame_id, message_source_)); + FOR_EACH_OBSERVER( + WebContentsObserver, observers_, + DocumentLoadedInFrame(frame_id, render_view_message_source_)); } void WebContentsImpl::OnDidFinishLoad( @@ -2204,11 +2235,12 @@ void WebContentsImpl::OnDidFinishLoad( const GURL& url, bool is_main_frame) { GURL validated_url(url); - RenderProcessHost* render_process_host = message_source_->GetProcess(); + RenderProcessHost* render_process_host = + render_view_message_source_->GetProcess(); RenderViewHost::FilterURL(render_process_host, false, &validated_url); FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidFinishLoad(frame_id, validated_url, is_main_frame, - message_source_)); + render_view_message_source_)); } void WebContentsImpl::OnDidFailLoadWithError( @@ -2216,14 +2248,15 @@ void WebContentsImpl::OnDidFailLoadWithError( const GURL& url, bool is_main_frame, int error_code, - const string16& error_description) { + const base::string16& error_description) { GURL validated_url(url); - RenderProcessHost* render_process_host = message_source_->GetProcess(); + RenderProcessHost* render_process_host = + render_view_message_source_->GetProcess(); RenderViewHost::FilterURL(render_process_host, false, &validated_url); FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidFailLoad(frame_id, validated_url, is_main_frame, error_code, error_description, - message_source_)); + render_view_message_source_)); } void WebContentsImpl::OnGoToEntryAtOffset(int offset) { @@ -2277,7 +2310,7 @@ void WebContentsImpl::OnJSOutOfMemory() { void WebContentsImpl::OnRegisterProtocolHandler(const std::string& protocol, const GURL& url, - const string16& title, + const base::string16& title, bool user_gesture) { if (!delegate_) return; @@ -2315,27 +2348,30 @@ void WebContentsImpl::OnOpenDateTimeDialog( date_time_chooser_->ShowDialog(ContentViewCore::FromWebContents(this), GetRenderViewHost(), value.dialog_type, - value.year, - value.month, - value.day, - value.hour, - value.minute, - value.second, - value.milli, - value.week, + value.dialog_value, value.minimum, value.maximum, - value.step); + value.step, + value.suggestions); } void WebContentsImpl::OnJavaBridgeGetChannelHandle(IPC::Message* reply_msg) { java_bridge_dispatcher_host_manager_->OnGetChannelHandle( - message_source_, reply_msg); + render_view_message_source_, reply_msg); } #endif -void WebContentsImpl::OnCrashedPlugin(const base::FilePath& plugin_path, +void WebContentsImpl::OnPepperPluginHung(int plugin_child_id, + const base::FilePath& path, + bool is_hung) { + UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1); + + FOR_EACH_OBSERVER(WebContentsObserver, observers_, + PluginHungStatusChanged(plugin_child_id, path, is_hung)); +} + +void WebContentsImpl::OnPluginCrashed(const base::FilePath& plugin_path, base::ProcessId plugin_pid) { FOR_EACH_OBSERVER(WebContentsObserver, observers_, PluginCrashed(plugin_path, plugin_pid)); @@ -2348,9 +2384,12 @@ void WebContentsImpl::OnAppCacheAccessed(const GURL& manifest_url, AppCacheAccessed(manifest_url, blocked_by_policy)); } -void WebContentsImpl::OnOpenColorChooser(int color_chooser_id, - SkColor color) { - ColorChooser* new_color_chooser = delegate_->OpenColorChooser(this, color); +void WebContentsImpl::OnOpenColorChooser( + int color_chooser_id, + SkColor color, + const std::vector<ColorSuggestion>& suggestions) { + ColorChooser* new_color_chooser = + delegate_->OpenColorChooser(this, color, suggestions); if (color_chooser_ == new_color_chooser) return; color_chooser_.reset(new_color_chooser); @@ -2370,15 +2409,6 @@ void WebContentsImpl::OnSetSelectedColorInColorChooser(int color_chooser_id, color_chooser_->SetSelectedColor(color); } -void WebContentsImpl::OnPepperPluginHung(int plugin_child_id, - const base::FilePath& path, - bool is_hung) { - UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1); - - FOR_EACH_OBSERVER(WebContentsObserver, observers_, - PluginHungStatusChanged(plugin_child_id, path, is_hung)); -} - // This exists for render views that don't have a WebUI, but do have WebUI // bindings enabled. void WebContentsImpl::OnWebUISend(const GURL& source_url, @@ -2470,11 +2500,13 @@ void WebContentsImpl::OnMediaNotification(int64 player_cookie, "Playing audio"); } - if (blocker) - power_save_blockers_[message_source_][player_cookie] = blocker.release(); + if (blocker) { + power_save_blockers_[render_view_message_source_][player_cookie] = + blocker.release(); + } } else { - delete power_save_blockers_[message_source_][player_cookie]; - power_save_blockers_[message_source_].erase(player_cookie); + delete power_save_blockers_[render_view_message_source_][player_cookie]; + power_save_blockers_[render_view_message_source_].erase(player_cookie); } #endif // !defined(OS_CHROMEOS) } @@ -2510,7 +2542,8 @@ void WebContentsImpl::SetIsLoading(RenderViewHost* render_view_host, return; if (!is_loading) { - load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE, string16()); + load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE, + base::string16()); load_state_host_.clear(); upload_size_ = 0; upload_position_ = 0; @@ -2612,11 +2645,11 @@ void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) { } bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl* entry, - const string16& title) { + const base::string16& title) { // For file URLs without a title, use the pathname instead. In the case of a // synthesized title, we don't want the update to count toward the "one set // per page of the title to history." - string16 final_title; + base::string16 final_title; bool explicit_set; if (entry && entry->GetURL().SchemeIsFile() && title.empty()) { final_title = UTF8ToUTF16(entry->GetURL().ExtractFileName()); @@ -2700,6 +2733,25 @@ void WebContentsImpl::NotifyNavigationEntryCommitted( WebContentsObserver, observers_, NavigationEntryCommitted(load_details)); } +bool WebContentsImpl::OnMessageReceived(RenderFrameHost* render_frame_host, + const IPC::Message& message) { + return OnMessageReceived(NULL, render_frame_host, message); +} + +void WebContentsImpl::RenderFrameCreated(RenderFrameHost* render_frame_host) { + // Note this is only for subframes, the notification for the main frame + // happens in RenderViewCreated. + FOR_EACH_OBSERVER(WebContentsObserver, + observers_, + RenderFrameCreated(render_frame_host)); +} + +void WebContentsImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) { + FOR_EACH_OBSERVER(WebContentsObserver, + observers_, + RenderFrameDeleted(render_frame_host)); +} + RenderViewHostDelegateView* WebContentsImpl::GetDelegateView() { return render_view_host_delegate_view_; } @@ -2760,6 +2812,13 @@ void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) { FOR_EACH_OBSERVER( WebContentsObserver, observers_, RenderViewCreated(render_view_host)); + + // We tell the observers now instead of when the main RenderFrameHostImpl is + // constructed because otherwise it would be too early (i.e. IPCs sent to the + // frame would be dropped because it's not created yet). + RenderFrameHost* main_frame = GetMainFrame(); + FOR_EACH_OBSERVER( + WebContentsObserver, observers_, RenderFrameCreated(main_frame)); } void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) { @@ -2969,7 +3028,7 @@ void WebContentsImpl::UpdateState(RenderViewHost* rvh, void WebContentsImpl::UpdateTitle(RenderViewHost* rvh, int32 page_id, - const string16& title, + const base::string16& title, base::i18n::TextDirection title_direction) { // If we have a title, that's a pretty good indication that we've started // getting useful data. @@ -3182,13 +3241,6 @@ void WebContentsImpl::RequestTransferURL( // Navigations in Web UI pages count as browser-initiated navigations. params.is_renderer_initiated = false; - - // TODO(creis): Remove this line. In the short term, it fixes a regression - // (http://crbug.com/313572) by partially reverting r231370. - // The underlying problem is that WebDataSource::replacesCurrentHistoryItem - // should be returning false when the CWS goes to the sign-in page. - // See http://crbug.com/311721. - params.should_replace_current_entry = false; } new_contents = OpenURL(params); @@ -3285,8 +3337,8 @@ void WebContentsImpl::RouteMessageEvent( void WebContentsImpl::RunJavaScriptMessage( RenderViewHost* rvh, - const string16& message, - const string16& default_prompt, + const base::string16& message, + const base::string16& default_prompt, const GURL& frame_url, JavaScriptMessageType javascript_message_type, IPC::Message* reply_msg, @@ -3324,7 +3376,7 @@ void WebContentsImpl::RunJavaScriptMessage( if (suppress_this_message) { // If we are suppressing messages, just reply as if the user immediately // pressed "Cancel". - OnDialogClosed(rvh, reply_msg, false, string16()); + OnDialogClosed(rvh, reply_msg, false, base::string16()); } // OnDialogClosed (two lines up) may have caused deletion of this object (see @@ -3332,7 +3384,7 @@ void WebContentsImpl::RunJavaScriptMessage( } void WebContentsImpl::RunBeforeUnloadConfirm(RenderViewHost* rvh, - const string16& message, + const base::string16& message, bool is_reload, IPC::Message* reply_msg) { RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh); @@ -3346,7 +3398,7 @@ void WebContentsImpl::RunBeforeUnloadConfirm(RenderViewHost* rvh, !delegate_->GetJavaScriptDialogManager(); if (suppress_this_message) { // The reply must be sent to the RVH that sent the request. - rvhi->JavaScriptDialogClosed(reply_msg, true, string16()); + rvhi->JavaScriptDialogClosed(reply_msg, true, base::string16()); return; } @@ -3359,9 +3411,9 @@ void WebContentsImpl::RunBeforeUnloadConfirm(RenderViewHost* rvh, } bool WebContentsImpl::AddMessageToConsole(int32 level, - const string16& message, + const base::string16& message, int32 line_no, - const string16& source_id) { + const base::string16& source_id) { if (!delegate_) return false; return delegate_->AddMessageToConsole(this, level, message, line_no, @@ -3584,7 +3636,7 @@ bool WebContentsImpl::CreateRenderViewForRenderManager( GetMaxPageIDForSiteInstance(render_view_host->GetSiteInstance()); if (!static_cast<RenderViewHostImpl*>( - render_view_host)->CreateRenderView(string16(), + render_view_host)->CreateRenderView(base::string16(), opener_route_id, max_page_id)) { return false; @@ -3603,6 +3655,19 @@ bool WebContentsImpl::CreateRenderViewForRenderManager( } #if defined(OS_ANDROID) +base::android::ScopedJavaLocalRef<jobject> +WebContentsImpl::GetJavaWebContents() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + WebContentsAndroid* web_contents_android = + static_cast<WebContentsAndroid*>(GetUserData(kWebContentsAndroidKey)); + if (!web_contents_android) { + web_contents_android = new WebContentsAndroid(this); + SetUserData(kWebContentsAndroidKey, web_contents_android); + } + return web_contents_android->GetJavaObject(); +} + bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() { return CreateRenderViewForRenderManager(GetRenderViewHost(), MSG_ROUTING_NONE); @@ -3612,7 +3677,7 @@ bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() { void WebContentsImpl::OnDialogClosed(RenderViewHost* rvh, IPC::Message* reply_msg, bool success, - const string16& user_input) { + const base::string16& user_input) { if (is_showing_before_unload_dialog_ && !success) { // If a beforeunload dialog is canceled, we need to stop the throbber from // spinning, since we forced it to start spinning in Navigate. diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 1717077f9a..e790f1524b 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h @@ -19,6 +19,7 @@ #include "content/browser/frame_host/navigation_controller_delegate.h" #include "content/browser/frame_host/navigation_controller_impl.h" #include "content/browser/frame_host/navigator_delegate.h" +#include "content/browser/frame_host/render_frame_host_delegate.h" #include "content/browser/frame_host/render_frame_host_manager.h" #include "content/browser/renderer_host/render_view_host_delegate.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" @@ -49,7 +50,6 @@ class DownloadItem; class InterstitialPageImpl; class JavaBridgeDispatcherHostManager; class JavaScriptDialogManager; -class Navigator; class PowerSaveBlocker; class RenderViewHost; class RenderViewHostDelegateView; @@ -65,6 +65,7 @@ class WebContentsImpl; class WebContentsObserver; class WebContentsViewPort; class WebContentsViewDelegate; +struct ColorSuggestion; struct FaviconURL; struct LoadNotificationDetails; @@ -77,6 +78,7 @@ WebContentsViewPort* CreateWebContentsView( class CONTENT_EXPORT WebContentsImpl : public NON_EXPORTED_BASE(WebContents), + public NON_EXPORTED_BASE(RenderFrameHostDelegate), public RenderViewHostDelegate, public RenderWidgetHostDelegate, public RenderFrameHostManager::Delegate, @@ -171,6 +173,7 @@ class CONTENT_EXPORT WebContentsImpl virtual const NavigationControllerImpl& GetController() const OVERRIDE; virtual BrowserContext* GetBrowserContext() const OVERRIDE; virtual RenderProcessHost* GetRenderProcessHost() const OVERRIDE; + virtual RenderFrameHost* GetMainFrame() OVERRIDE; virtual RenderViewHost* GetRenderViewHost() const OVERRIDE; virtual void GetRenderViewHostAtPosition( int x, @@ -192,7 +195,7 @@ class CONTENT_EXPORT WebContentsImpl virtual void SetParentNativeViewAccessible( gfx::NativeViewAccessible accessible_parent) OVERRIDE; #endif - virtual const string16& GetTitle() const OVERRIDE; + virtual const base::string16& GetTitle() const OVERRIDE; virtual int32 GetMaxPageID() OVERRIDE; virtual int32 GetMaxPageIDForSiteInstance( SiteInstance* site_instance) OVERRIDE; @@ -201,7 +204,7 @@ class CONTENT_EXPORT WebContentsImpl virtual bool IsLoading() const OVERRIDE; virtual bool IsWaitingForResponse() const OVERRIDE; virtual const net::LoadStateWithParam& GetLoadState() const OVERRIDE; - virtual const string16& GetLoadStateHost() const OVERRIDE; + virtual const base::string16& GetLoadStateHost() const OVERRIDE; virtual uint64 GetUploadSize() const OVERRIDE; virtual uint64 GetUploadPosition() const OVERRIDE; virtual std::set<GURL> GetSitesInTab() const OVERRIDE; @@ -265,6 +268,10 @@ class CONTENT_EXPORT WebContentsImpl bool is_favicon, uint32_t max_bitmap_size, const ImageDownloadCallback& callback) OVERRIDE; +#if defined(OS_ANDROID) + virtual base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents() + OVERRIDE; +#endif // Implementation of PageNavigator. virtual WebContents* OpenURL(const OpenURLParams& params) OVERRIDE; @@ -272,8 +279,13 @@ class CONTENT_EXPORT WebContentsImpl // Implementation of IPC::Sender. virtual bool Send(IPC::Message* message) OVERRIDE; - // RenderViewHostDelegate ---------------------------------------------------- + // RenderFrameHostDelegate --------------------------------------------------- + virtual bool OnMessageReceived(RenderFrameHost* render_frame_host, + const IPC::Message& message) OVERRIDE; + virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) OVERRIDE; + virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) OVERRIDE; + // RenderViewHostDelegate ---------------------------------------------------- virtual RenderViewHostDelegateView* GetDelegateView() OVERRIDE; virtual RenderViewHostDelegate::RendererManagement* GetRendererManagementDelegate() OVERRIDE; @@ -290,12 +302,6 @@ class CONTENT_EXPORT WebContentsImpl base::TerminationStatus status, int error_code) OVERRIDE; virtual void RenderViewDeleted(RenderViewHost* render_view_host) OVERRIDE; - virtual void DidStartProvisionalLoadForFrame( - RenderViewHost* render_view_host, - int64 frame_id, - int64 parent_frame_id, - bool main_frame, - const GURL& url) OVERRIDE; virtual void DidRedirectProvisionalLoad( RenderViewHost* render_view_host, int32 page_id, @@ -317,7 +323,7 @@ class CONTENT_EXPORT WebContentsImpl const PageState& page_state) OVERRIDE; virtual void UpdateTitle(RenderViewHost* render_view_host, int32 page_id, - const string16& title, + const base::string16& title, base::i18n::TextDirection title_direction) OVERRIDE; virtual void UpdateEncoding(RenderViewHost* render_view_host, const std::string& encoding) OVERRIDE; @@ -358,20 +364,20 @@ class CONTENT_EXPORT WebContentsImpl RenderViewHost* rvh, const ViewMsg_PostMessage_Params& params) OVERRIDE; virtual void RunJavaScriptMessage(RenderViewHost* rvh, - const string16& message, - const string16& default_prompt, + const base::string16& message, + const base::string16& default_prompt, const GURL& frame_url, JavaScriptMessageType type, IPC::Message* reply_msg, bool* did_suppress_message) OVERRIDE; virtual void RunBeforeUnloadConfirm(RenderViewHost* rvh, - const string16& message, + const base::string16& message, bool is_reload, IPC::Message* reply_msg) OVERRIDE; virtual bool AddMessageToConsole(int32 level, - const string16& message, + const base::string16& message, int32 line_no, - const string16& source_id) OVERRIDE; + const base::string16& source_id) OVERRIDE; virtual RendererPreferences GetRendererPrefs( BrowserContext* browser_context) const OVERRIDE; virtual WebPreferences GetWebkitPrefs() OVERRIDE; @@ -405,13 +411,16 @@ class CONTENT_EXPORT WebContentsImpl bool last_unlocked_by_target) OVERRIDE; virtual void LostMouseLock() OVERRIDE; virtual void CreateNewWindow( + int render_process_id, int route_id, int main_frame_route_id, const ViewHostMsg_CreateWindow_Params& params, SessionStorageNamespace* session_storage_namespace) OVERRIDE; - virtual void CreateNewWidget(int route_id, + virtual void CreateNewWidget(int render_process_id, + int route_id, blink::WebPopupType popup_type) OVERRIDE; - virtual void CreateNewFullscreenWidget(int route_id) OVERRIDE; + virtual void CreateNewFullscreenWidget(int render_process_id, + int route_id) OVERRIDE; virtual void ShowCreatedWindow(int route_id, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, @@ -427,6 +436,19 @@ class CONTENT_EXPORT WebContentsImpl SiteInstance* instance) OVERRIDE; virtual FrameTree* GetFrameTree() OVERRIDE; + // NavigatorDelegate --------------------------------------------------------- + + virtual void DidStartProvisionalLoad( + RenderFrameHostImpl* render_frame_host, + int64 frame_id, + int64 parent_frame_id, + bool is_main_frame, + const GURL& validated_url, + bool is_error_page, + bool is_iframe_srcdoc) OVERRIDE; + virtual void NotifyChangedNavigationState( + InvalidateTypes changed_flags) OVERRIDE; + // RenderWidgetHostDelegate -------------------------------------------------- virtual void RenderWidgetDeleted( @@ -593,12 +615,16 @@ class CONTENT_EXPORT WebContentsImpl void OnDialogClosed(RenderViewHost* rvh, IPC::Message* reply_msg, bool success, - const string16& user_input); + const base::string16& user_input); // Callback function when requesting permission to access the PPAPI broker. // |result| is true if permission was granted. void OnPpapiBrokerPermissionResult(int routing_id, bool result); + bool OnMessageReceived(RenderViewHost* render_view_host, + RenderFrameHost* render_frame_host, + const IPC::Message& message); + // IPC message handlers. void OnDidLoadResourceFromMemoryCache(const GURL& url, const std::string& security_info, @@ -616,7 +642,7 @@ class CONTENT_EXPORT WebContentsImpl const GURL& url, bool is_main_frame, int error_code, - const string16& error_description); + const base::string16& error_description); void OnGoToEntryAtOffset(int offset); void OnUpdateZoomLimits(int minimum_percent, int maximum_percent, @@ -626,7 +652,7 @@ class CONTENT_EXPORT WebContentsImpl void OnRegisterProtocolHandler(const std::string& protocol, const GURL& url, - const string16& title, + const base::string16& title, bool user_gesture); void OnFindReply(int request_id, int number_of_matches, @@ -642,15 +668,17 @@ class CONTENT_EXPORT WebContentsImpl const ViewHostMsg_DateTimeDialogValue_Params& value); void OnJavaBridgeGetChannelHandle(IPC::Message* reply_msg); #endif - void OnCrashedPlugin(const base::FilePath& plugin_path, + void OnPepperPluginHung(int plugin_child_id, + const base::FilePath& path, + bool is_hung); + void OnPluginCrashed(const base::FilePath& plugin_path, base::ProcessId plugin_pid); void OnAppCacheAccessed(const GURL& manifest_url, bool blocked_by_policy); - void OnOpenColorChooser(int color_chooser_id, SkColor color); + void OnOpenColorChooser(int color_chooser_id, + SkColor color, + const std::vector<ColorSuggestion>& suggestions); void OnEndColorChooser(int color_chooser_id); void OnSetSelectedColorInColorChooser(int color_chooser_id, SkColor color); - void OnPepperPluginHung(int plugin_child_id, - const base::FilePath& path, - bool is_hung); void OnWebUISend(const GURL& source_url, const std::string& name, const base::ListValue& args); @@ -711,7 +739,7 @@ class CONTENT_EXPORT WebContentsImpl // or the dedicated set title message. It returns true if the new title is // different and was therefore updated. bool UpdateTitleForEntry(NavigationEntryImpl* entry, - const string16& title); + const base::string16& title); // Causes the WebContentsImpl to navigate in the right renderer to |entry|, // which must be already part of the entries in the navigation controller. @@ -726,7 +754,8 @@ class CONTENT_EXPORT WebContentsImpl int CreateOpenerRenderViews(SiteInstance* instance); // Helper for CreateNewWidget/CreateNewFullscreenWidget. - void CreateNewWidget(int route_id, + void CreateNewWidget(int render_process_id, + int route_id, bool is_fullscreen, blink::WebPopupType popup_type); @@ -873,7 +902,7 @@ class CONTENT_EXPORT WebContentsImpl // The current load state and the URL associated with it. net::LoadStateWithParam load_state_; - string16 load_state_host_; + base::string16 load_state_host_; // Upload progress, for displaying in the status bar. // Set to zero when there is no significant upload happening. uint64 upload_size_; @@ -882,7 +911,7 @@ class CONTENT_EXPORT WebContentsImpl // Data for current page ----------------------------------------------------- // When a title cannot be taken from any entry, this title will be used. - string16 page_title_when_no_navigation_entry_; + base::string16 page_title_when_no_navigation_entry_; // When a navigation occurs, we record its contents MIME type. It can be // used to check whether we can do something for some special contents. @@ -971,9 +1000,10 @@ class CONTENT_EXPORT WebContentsImpl // member variables that are gone. NotificationRegistrar registrar_; - // Used during IPC message dispatching so that the handlers can get a pointer - // to the RVH through which the message was received. - RenderViewHost* message_source_; + // Used during IPC message dispatching from the RenderView so that the + // handlers can get a pointer to the RVH through which the message was + // received. + RenderViewHost* render_view_message_source_; // All live RenderWidgetHostImpls that are created by this object and may // outlive it. diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc index d5ac7057c1..7926b4c424 100644 --- a/content/browser/web_contents/web_contents_impl_unittest.cc +++ b/content/browser/web_contents/web_contents_impl_unittest.cc @@ -7,7 +7,6 @@ #include "content/browser/frame_host/interstitial_page_impl.h" #include "content/browser/frame_host/navigation_entry_impl.h" #include "content/browser/renderer_host/render_view_host_impl.h" -#include "content/browser/renderer_host/test_render_view_host.h" #include "content/browser/site_instance_impl.h" #include "content/browser/webui/web_ui_controller_factory_registry.h" #include "content/common/view_messages.h" @@ -27,6 +26,7 @@ #include "content/public/test/test_utils.h" #include "content/test/test_content_browser_client.h" #include "content/test/test_content_client.h" +#include "content/test/test_render_view_host.h" #include "content/test/test_web_contents.h" #include "testing/gtest/include/gtest/gtest.h" @@ -183,7 +183,7 @@ class TestInterstitialPage : public InterstitialPageImpl { virtual RenderViewHost* CreateRenderViewHost() OVERRIDE { return new TestRenderViewHost( SiteInstance::Create(web_contents()->GetBrowserContext()), - this, this, MSG_ROUTING_NONE, MSG_ROUTING_NONE, false); + this, this, this, MSG_ROUTING_NONE, MSG_ROUTING_NONE, false); } virtual WebContentsView* CreateWebContentsView() OVERRIDE { @@ -284,7 +284,7 @@ class TestWebContentsObserver : public WebContentsObserver { const GURL& validated_url, bool is_main_frame, int error_code, - const string16& error_description, + const base::string16& error_description, RenderViewHost* render_view_host) OVERRIDE { last_url_ = validated_url; } @@ -318,12 +318,12 @@ TEST_F(WebContentsImplTest, DontUseTitleFromPendingEntry) { const GURL kGURL("chrome://blah"); controller().LoadURL( kGURL, Referrer(), PAGE_TRANSITION_TYPED, std::string()); - EXPECT_EQ(string16(), contents()->GetTitle()); + EXPECT_EQ(base::string16(), contents()->GetTitle()); } TEST_F(WebContentsImplTest, UseTitleFromPendingEntryIfSet) { const GURL kGURL("chrome://blah"); - const string16 title = ASCIIToUTF16("My Title"); + const base::string16 title = ASCIIToUTF16("My Title"); controller().LoadURL( kGURL, Referrer(), PAGE_TRANSITION_TYPED, std::string()); @@ -2152,7 +2152,7 @@ TEST_F(WebContentsImplTest, FilterURLs) { // Check that an IPC with about:whatever is correctly normalized. other_contents->TestDidFailLoadWithError( - 1, url_from_ipc, true, 1, string16()); + 1, url_from_ipc, true, 1, base::string16()); EXPECT_EQ(url_normalized, other_observer.last_url()); } diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc index fc27aceed0..f66b5ec14f 100644 --- a/content/browser/web_contents/web_contents_view_android.cc +++ b/content/browser/web_contents/web_contents_view_android.cc @@ -80,7 +80,7 @@ void WebContentsViewAndroid::GetContainerBounds(gfx::Rect* out) const { *out = rwhv->GetViewBounds(); } -void WebContentsViewAndroid::SetPageTitle(const string16& title) { +void WebContentsViewAndroid::SetPageTitle(const base::string16& title) { if (content_view_core_) content_view_core_->SetTitle(title); } diff --git a/content/browser/web_contents/web_contents_view_android.h b/content/browser/web_contents/web_contents_view_android.h index bcfc0cf472..849ca6dc8d 100644 --- a/content/browser/web_contents/web_contents_view_android.h +++ b/content/browser/web_contents/web_contents_view_android.h @@ -57,7 +57,7 @@ class WebContentsViewAndroid : public WebContentsViewPort, RenderWidgetHost* render_widget_host) OVERRIDE; virtual RenderWidgetHostView* CreateViewForPopupWidget( RenderWidgetHost* render_widget_host) OVERRIDE; - virtual void SetPageTitle(const string16& title) OVERRIDE; + virtual void SetPageTitle(const base::string16& title) OVERRIDE; virtual void RenderViewCreated(RenderViewHost* host) OVERRIDE; virtual void RenderViewSwappedIn(RenderViewHost* host) OVERRIDE; virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE; diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc index 353da78864..75ca4e6fca 100644 --- a/content/browser/web_contents/web_contents_view_aura.cc +++ b/content/browser/web_contents/web_contents_view_aura.cc @@ -249,7 +249,7 @@ void PrepareDragForFileContents(const DropData& drop_data, // Images without ALT text will only have a file extension so we need to // synthesize one from the provided extension and URL. if (file_name.BaseName().RemoveExtension().empty()) { - const string16 extension = file_name.Extension(); + const base::string16 extension = file_name.Extension(); // Retrieve the name from the URL. file_name = base::FilePath(net::GetSuggestedFilename( drop_data.url, "", "", "", "", "")).ReplaceExtension(extension); @@ -296,20 +296,20 @@ void PrepareDragData(const DropData& drop_data, // Utility to fill a DropData object from ui::OSExchangeData. void PrepareDropData(DropData* drop_data, const ui::OSExchangeData& data) { - string16 plain_text; + base::string16 plain_text; data.GetString(&plain_text); if (!plain_text.empty()) drop_data->text = base::NullableString16(plain_text, false); GURL url; - string16 url_title; + base::string16 url_title; data.GetURLAndTitle(&url, &url_title); if (url.is_valid()) { drop_data->url = url; drop_data->url_title = url_title; } - string16 html; + base::string16 html; GURL html_base_url; data.GetHtml(&html, &html_base_url); if (!html.empty()) @@ -1298,7 +1298,7 @@ RenderWidgetHostView* WebContentsViewAura::CreateViewForPopupWidget( return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host); } -void WebContentsViewAura::SetPageTitle(const string16& title) { +void WebContentsViewAura::SetPageTitle(const base::string16& title) { window_->set_title(title); } diff --git a/content/browser/web_contents/web_contents_view_aura.h b/content/browser/web_contents/web_contents_view_aura.h index 7d377b0559..a0597d38fa 100644 --- a/content/browser/web_contents/web_contents_view_aura.h +++ b/content/browser/web_contents/web_contents_view_aura.h @@ -118,7 +118,7 @@ class CONTENT_EXPORT WebContentsViewAura RenderWidgetHost* render_widget_host) OVERRIDE; virtual RenderWidgetHostView* CreateViewForPopupWidget( RenderWidgetHost* render_widget_host) OVERRIDE; - virtual void SetPageTitle(const string16& title) OVERRIDE; + virtual void SetPageTitle(const base::string16& title) OVERRIDE; virtual void RenderViewCreated(RenderViewHost* host) OVERRIDE; virtual void RenderViewSwappedIn(RenderViewHost* host) OVERRIDE; virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE; diff --git a/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/content/browser/web_contents/web_contents_view_aura_browsertest.cc index 3214c13c11..687ce57606 100644 --- a/content/browser/web_contents/web_contents_view_aura_browsertest.cc +++ b/content/browser/web_contents/web_contents_view_aura_browsertest.cc @@ -196,14 +196,14 @@ class WebContentsViewAuraTest : public ContentBrowserTest { { // Do a swipe-right now. That should navigate backwards. - string16 expected_title = ASCIIToUTF16("Title: #1"); + base::string16 expected_title = ASCIIToUTF16("Title: #1"); content::TitleWatcher title_watcher(web_contents, expected_title); generator.GestureScrollSequence( gfx::Point(bounds.x() + 2, bounds.y() + 10), gfx::Point(bounds.right() - 10, bounds.y() + 10), base::TimeDelta::FromMilliseconds(kScrollDurationMs), kScrollSteps); - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); value = content::ExecuteScriptAndGetValue(view_host, "get_current()"); ASSERT_TRUE(value->GetAsInteger(&index)); @@ -214,14 +214,14 @@ class WebContentsViewAuraTest : public ContentBrowserTest { { // Do a fling-right now. That should navigate backwards. - string16 expected_title = ASCIIToUTF16("Title:"); + base::string16 expected_title = ASCIIToUTF16("Title:"); content::TitleWatcher title_watcher(web_contents, expected_title); generator.GestureScrollSequence( gfx::Point(bounds.x() + 2, bounds.y() + 10), gfx::Point(bounds.right() - 10, bounds.y() + 10), base::TimeDelta::FromMilliseconds(kScrollDurationMs), kScrollSteps); - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); value = content::ExecuteScriptAndGetValue(view_host, "get_current()"); ASSERT_TRUE(value->GetAsInteger(&index)); @@ -232,14 +232,14 @@ class WebContentsViewAuraTest : public ContentBrowserTest { { // Do a swipe-left now. That should navigate forward. - string16 expected_title = ASCIIToUTF16("Title: #1"); + base::string16 expected_title = ASCIIToUTF16("Title: #1"); content::TitleWatcher title_watcher(web_contents, expected_title); generator.GestureScrollSequence( gfx::Point(bounds.right() - 10, bounds.y() + 10), gfx::Point(bounds.x() + 2, bounds.y() + 10), base::TimeDelta::FromMilliseconds(kScrollDurationMs), kScrollSteps); - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); value = content::ExecuteScriptAndGetValue(view_host, "get_current()"); ASSERT_TRUE(value->GetAsInteger(&index)); @@ -438,7 +438,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, OverscrollScreenshot) { { // Now, swipe right to navigate backwards. This should navigate away from // index 3 to index 2, and index 3 should have a screenshot. - string16 expected_title = ASCIIToUTF16("Title: #2"); + base::string16 expected_title = ASCIIToUTF16("Title: #2"); content::TitleWatcher title_watcher(web_contents, expected_title); aura::Window* content = web_contents->GetView()->GetContentNativeView(); gfx::Rect bounds = content->GetBoundsInRootWindow(); @@ -448,7 +448,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, OverscrollScreenshot) { gfx::Point(bounds.right() - 10, bounds.y() + 10), base::TimeDelta::FromMilliseconds(20), 1); - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); EXPECT_EQ(2, GetCurrentIndex()); screenshot_manager()->WaitUntilScreenshotIsReady(); @@ -469,10 +469,10 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, OverscrollScreenshot) { { // Navigate back in history. - string16 expected_title = ASCIIToUTF16("Title: #3"); + base::string16 expected_title = ASCIIToUTF16("Title: #3"); content::TitleWatcher title_watcher(web_contents, expected_title); web_contents->GetController().GoBack(); - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); EXPECT_EQ(3, GetCurrentIndex()); screenshot_manager()->WaitUntilScreenshotIsReady(); @@ -641,7 +641,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, // Do a swipe left to start a forward navigation. Then quickly do a swipe // right. - string16 expected_title = ASCIIToUTF16("Title: #2"); + base::string16 expected_title = ASCIIToUTF16("Title: #2"); content::TitleWatcher title_watcher(web_contents, expected_title); NavigationWatcher nav_watcher(web_contents); @@ -657,7 +657,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, gfx::Point(bounds.right() - 10, bounds.y() + 10), base::TimeDelta::FromMilliseconds(2000), 10); - string16 actual_title = title_watcher.WaitAndGetTitle(); + base::string16 actual_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, actual_title); EXPECT_EQ(2, GetCurrentIndex()); diff --git a/content/browser/web_contents/web_contents_view_gtk.cc b/content/browser/web_contents/web_contents_view_gtk.cc index 4e3874fd1e..bf4dcb7fd3 100644 --- a/content/browser/web_contents/web_contents_view_gtk.cc +++ b/content/browser/web_contents/web_contents_view_gtk.cc @@ -246,7 +246,7 @@ RenderWidgetHostView* WebContentsViewGtk::CreateViewForPopupWidget( return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host); } -void WebContentsViewGtk::SetPageTitle(const string16& title) { +void WebContentsViewGtk::SetPageTitle(const base::string16& title) { // Set the window name to include the page title so it's easier to spot // when debugging (e.g. via xwininfo -tree). gfx::NativeView content_view = GetContentNativeView(); diff --git a/content/browser/web_contents/web_contents_view_gtk.h b/content/browser/web_contents/web_contents_view_gtk.h index 41f84ab7af..7a8d25e450 100644 --- a/content/browser/web_contents/web_contents_view_gtk.h +++ b/content/browser/web_contents/web_contents_view_gtk.h @@ -66,7 +66,7 @@ class CONTENT_EXPORT WebContentsViewGtk RenderWidgetHost* render_widget_host) OVERRIDE; virtual RenderWidgetHostView* CreateViewForPopupWidget( RenderWidgetHost* render_widget_host) OVERRIDE; - virtual void SetPageTitle(const string16& title) OVERRIDE; + virtual void SetPageTitle(const base::string16& title) OVERRIDE; virtual void RenderViewCreated(RenderViewHost* host) OVERRIDE; virtual void RenderViewSwappedIn(RenderViewHost* host) OVERRIDE; virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE; diff --git a/content/browser/web_contents/web_contents_view_guest.cc b/content/browser/web_contents/web_contents_view_guest.cc index ac236da041..cbfb7903da 100644 --- a/content/browser/web_contents/web_contents_view_guest.cc +++ b/content/browser/web_contents/web_contents_view_guest.cc @@ -106,6 +106,15 @@ void WebContentsViewGuest::SetAllowOverlappingViews(bool overlapping) { bool WebContentsViewGuest::GetAllowOverlappingViews() const { return platform_view_->GetAllowOverlappingViews(); } + +void WebContentsViewGuest::SetOverlayView( + WebContentsView* overlay, const gfx::Point& offset) { + platform_view_->SetOverlayView(overlay, offset); +} + +void WebContentsViewGuest::RemoveOverlayView() { + platform_view_->RemoveOverlayView(); +} #endif void WebContentsViewGuest::CreateView(const gfx::Size& initial_size, @@ -142,7 +151,7 @@ RenderWidgetHostView* WebContentsViewGuest::CreateViewForPopupWidget( return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host); } -void WebContentsViewGuest::SetPageTitle(const string16& title) { +void WebContentsViewGuest::SetPageTitle(const base::string16& title) { } void WebContentsViewGuest::RenderViewCreated(RenderViewHost* host) { diff --git a/content/browser/web_contents/web_contents_view_guest.h b/content/browser/web_contents/web_contents_view_guest.h index 1e1d812e37..68fb473d70 100644 --- a/content/browser/web_contents/web_contents_view_guest.h +++ b/content/browser/web_contents/web_contents_view_guest.h @@ -56,6 +56,9 @@ class CONTENT_EXPORT WebContentsViewGuest #if defined(OS_MACOSX) virtual void SetAllowOverlappingViews(bool overlapping) OVERRIDE; virtual bool GetAllowOverlappingViews() const OVERRIDE; + virtual void SetOverlayView(WebContentsView* overlay, + const gfx::Point& offset) OVERRIDE; + virtual void RemoveOverlayView() OVERRIDE; #endif // WebContentsViewPort implementation ---------------------------------------- @@ -65,7 +68,7 @@ class CONTENT_EXPORT WebContentsViewGuest RenderWidgetHost* render_widget_host) OVERRIDE; virtual RenderWidgetHostView* CreateViewForPopupWidget( RenderWidgetHost* render_widget_host) OVERRIDE; - virtual void SetPageTitle(const string16& title) OVERRIDE; + virtual void SetPageTitle(const base::string16& title) OVERRIDE; virtual void RenderViewCreated(RenderViewHost* host) OVERRIDE; virtual void RenderViewSwappedIn(RenderViewHost* host) OVERRIDE; virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE; diff --git a/content/browser/web_contents/web_contents_view_mac.h b/content/browser/web_contents/web_contents_view_mac.h index 3d0b94f92e..0dadbad9eb 100644 --- a/content/browser/web_contents/web_contents_view_mac.h +++ b/content/browser/web_contents/web_contents_view_mac.h @@ -80,6 +80,9 @@ class WebContentsViewMac : public WebContentsViewPort, virtual gfx::Rect GetViewBounds() const OVERRIDE; virtual void SetAllowOverlappingViews(bool overlapping) OVERRIDE; virtual bool GetAllowOverlappingViews() const OVERRIDE; + virtual void SetOverlayView(WebContentsView* overlay, + const gfx::Point& offset) OVERRIDE; + virtual void RemoveOverlayView() OVERRIDE; // WebContentsViewPort implementation ---------------------------------------- virtual void CreateView( @@ -88,7 +91,7 @@ class WebContentsViewMac : public WebContentsViewPort, RenderWidgetHost* render_widget_host) OVERRIDE; virtual RenderWidgetHostView* CreateViewForPopupWidget( RenderWidgetHost* render_widget_host) OVERRIDE; - virtual void SetPageTitle(const string16& title) OVERRIDE; + virtual void SetPageTitle(const base::string16& title) OVERRIDE; virtual void RenderViewCreated(RenderViewHost* host) OVERRIDE; virtual void RenderViewSwappedIn(RenderViewHost* host) OVERRIDE; virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE; @@ -121,6 +124,9 @@ class WebContentsViewMac : public WebContentsViewPort, WebContentsViewDelegate* delegate() { return delegate_.get(); } private: + // Updates overlay view on current RenderWidgetHostView. + void UpdateRenderWidgetHostViewOverlay(); + // The WebContentsImpl whose contents we display. WebContentsImpl* web_contents_; @@ -137,6 +143,17 @@ class WebContentsViewMac : public WebContentsViewPort, // Whether to allow overlapping views. bool allow_overlapping_views_; + // The overlay view which is rendered above this one. + // Overlay view has |underlay_view_| set to this view. + WebContentsViewMac* overlay_view_; + + // The offset of overlay view relative to this view. + gfx::Point overlay_view_offset_; + + // The underlay view which this view is rendered above. + // Underlay view has |overlay_view_| set to this view. + WebContentsViewMac* underlay_view_; + DISALLOW_COPY_AND_ASSIGN(WebContentsViewMac); }; diff --git a/content/browser/web_contents/web_contents_view_mac.mm b/content/browser/web_contents/web_contents_view_mac.mm index 4283ca958d..527ebc024d 100644 --- a/content/browser/web_contents/web_contents_view_mac.mm +++ b/content/browser/web_contents/web_contents_view_mac.mm @@ -81,7 +81,9 @@ WebContentsViewMac::WebContentsViewMac(WebContentsImpl* web_contents, WebContentsViewDelegate* delegate) : web_contents_(web_contents), delegate_(delegate), - allow_overlapping_views_(false) { + allow_overlapping_views_(false), + overlay_view_(NULL), + underlay_view_(NULL) { } WebContentsViewMac::~WebContentsViewMac() { @@ -277,6 +279,54 @@ bool WebContentsViewMac::GetAllowOverlappingViews() const { return allow_overlapping_views_; } +void WebContentsViewMac::SetOverlayView( + WebContentsView* overlay, const gfx::Point& offset) { + DCHECK(!underlay_view_); + if (overlay_view_) + RemoveOverlayView(); + + overlay_view_ = static_cast<WebContentsViewMac*>(overlay); + DCHECK(!overlay_view_->overlay_view_); + overlay_view_->underlay_view_ = this; + overlay_view_offset_ = offset; + UpdateRenderWidgetHostViewOverlay(); +} + +void WebContentsViewMac::RemoveOverlayView() { + DCHECK(overlay_view_); + + RenderWidgetHostViewMac* rwhv = static_cast<RenderWidgetHostViewMac*>( + web_contents_->GetRenderWidgetHostView()); + if (rwhv) + rwhv->RemoveOverlayView(); + + overlay_view_->underlay_view_ = NULL; + overlay_view_ = NULL; +} + +void WebContentsViewMac::UpdateRenderWidgetHostViewOverlay() { + RenderWidgetHostViewMac* rwhv = static_cast<RenderWidgetHostViewMac*>( + web_contents_->GetRenderWidgetHostView()); + if (!rwhv) + return; + + if (overlay_view_) { + RenderWidgetHostViewMac* overlay_rwhv = + static_cast<RenderWidgetHostViewMac*>( + overlay_view_->web_contents_->GetRenderWidgetHostView()); + if (overlay_rwhv) + rwhv->SetOverlayView(overlay_rwhv, overlay_view_offset_); + } + + if (underlay_view_) { + RenderWidgetHostViewMac* underlay_rwhv = + static_cast<RenderWidgetHostViewMac*>( + underlay_view_->web_contents_->GetRenderWidgetHostView()); + if (underlay_rwhv) + underlay_rwhv->SetOverlayView(rwhv, underlay_view_->overlay_view_offset_); + } +} + void WebContentsViewMac::CreateView( const gfx::Size& initial_size, gfx::NativeView context) { WebContentsViewCocoa* view = @@ -332,7 +382,7 @@ RenderWidgetHostView* WebContentsViewMac::CreateViewForPopupWidget( return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host); } -void WebContentsViewMac::SetPageTitle(const string16& title) { +void WebContentsViewMac::SetPageTitle(const base::string16& title) { // Meaningless on the Mac; widgets don't have a "title" attribute } @@ -345,6 +395,7 @@ void WebContentsViewMac::RenderViewCreated(RenderViewHost* host) { } void WebContentsViewMac::RenderViewSwappedIn(RenderViewHost* host) { + UpdateRenderWidgetHostViewOverlay(); } void WebContentsViewMac::SetOverscrollControllerEnabled(bool enabled) { diff --git a/content/browser/web_contents/web_contents_view_win.cc b/content/browser/web_contents/web_contents_view_win.cc index 92548d2dca..8360d8c5f5 100644 --- a/content/browser/web_contents/web_contents_view_win.cc +++ b/content/browser/web_contents/web_contents_view_win.cc @@ -228,7 +228,7 @@ RenderWidgetHostView* WebContentsViewWin::CreateViewForPopupWidget( return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host); } -void WebContentsViewWin::SetPageTitle(const string16& title) { +void WebContentsViewWin::SetPageTitle(const base::string16& title) { // It's possible to get this after the hwnd has been destroyed. if (GetNativeView()) ::SetWindowText(GetNativeView(), title.c_str()); diff --git a/content/browser/web_contents/web_contents_view_win.h b/content/browser/web_contents/web_contents_view_win.h index 505addddec..9b052e20a2 100644 --- a/content/browser/web_contents/web_contents_view_win.h +++ b/content/browser/web_contents/web_contents_view_win.h @@ -73,7 +73,7 @@ class CONTENT_EXPORT WebContentsViewWin RenderWidgetHost* render_widget_host) OVERRIDE; virtual RenderWidgetHostView* CreateViewForPopupWidget( RenderWidgetHost* render_widget_host) OVERRIDE; - virtual void SetPageTitle(const string16& title) OVERRIDE; + virtual void SetPageTitle(const base::string16& title) OVERRIDE; virtual void RenderViewCreated(RenderViewHost* host) OVERRIDE; virtual void RenderViewSwappedIn(RenderViewHost* host) OVERRIDE; virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE; diff --git a/content/browser/web_contents/web_drag_dest_gtk.cc b/content/browser/web_contents/web_drag_dest_gtk.cc index bb9a4d42a7..738d6b59a8 100644 --- a/content/browser/web_contents/web_drag_dest_gtk.cc +++ b/content/browser/web_contents/web_drag_dest_gtk.cc @@ -204,7 +204,8 @@ void WebDragDestGtk::OnDragDataReceived( if (url.SchemeIs(chrome::kFileScheme) && net::FileURLToFilePath(url, &file_path)) { drop_data_->filenames.push_back( - DropData::FileInfo(UTF8ToUTF16(file_path.value()), string16())); + DropData::FileInfo(UTF8ToUTF16(file_path.value()), + base::string16())); // This is a hack. Some file managers also populate text/plain with // a file URL when dragging files, so we clear it to avoid exposing // it to the web content. diff --git a/content/browser/web_contents/web_drag_dest_mac.mm b/content/browser/web_contents/web_drag_dest_mac.mm index b3fefcad00..8768bed657 100644 --- a/content/browser/web_contents/web_drag_dest_mac.mm +++ b/content/browser/web_contents/web_drag_dest_mac.mm @@ -290,7 +290,7 @@ int GetModifierFlags() { if (exists) { data->filenames.push_back( DropData::FileInfo( - base::SysNSStringToUTF16(filename), string16())); + base::SysNSStringToUTF16(filename), base::string16())); } } } diff --git a/content/browser/web_contents/web_drag_dest_mac_unittest.mm b/content/browser/web_contents/web_drag_dest_mac_unittest.mm index 48719de7b7..a7dcedecb0 100644 --- a/content/browser/web_contents/web_drag_dest_mac_unittest.mm +++ b/content/browser/web_contents/web_drag_dest_mac_unittest.mm @@ -6,9 +6,9 @@ #import "base/mac/scoped_nsobject.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" -#include "content/browser/renderer_host/test_render_view_host.h" #import "content/browser/web_contents/web_drag_dest_mac.h" #include "content/public/common/drop_data.h" +#include "content/test/test_render_view_host.h" #include "content/test/test_web_contents.h" #include "testing/gtest/include/gtest/gtest.h" #import "third_party/mozilla/NSPasteboard+Utils.h" @@ -85,7 +85,7 @@ TEST_F(WebDragDestTest, URL) { NSString* url = nil; NSString* title = nil; GURL result_url; - string16 result_title; + base::string16 result_title; // Put a URL on the pasteboard and check it. pboard = [NSPasteboard pasteboardWithUniqueName]; diff --git a/content/browser/web_contents/web_drag_source_gtk.h b/content/browser/web_contents/web_drag_source_gtk.h index 577f60b086..8a7c7b28a9 100644 --- a/content/browser/web_contents/web_drag_source_gtk.h +++ b/content/browser/web_contents/web_drag_source_gtk.h @@ -92,7 +92,7 @@ class CONTENT_EXPORT WebDragSourceGtk : GdkDragContext* drag_context_; // The file mime type for a drag-out download. - string16 wide_download_mime_type_; + base::string16 wide_download_mime_type_; // The file name to be saved to for a drag-out download. base::FilePath download_file_name_; diff --git a/content/browser/web_contents/web_drag_source_mac.mm b/content/browser/web_contents/web_drag_source_mac.mm index 805e73bdd4..c66732050c 100644 --- a/content/browser/web_contents/web_drag_source_mac.mm +++ b/content/browser/web_contents/web_drag_source_mac.mm @@ -49,10 +49,10 @@ namespace { // |NSURLPboardType|. NSString* const kNSURLTitlePboardType = @"public.url-name"; -// Converts a string16 into a FilePath. Use this method instead of +// Converts a base::string16 into a FilePath. Use this method instead of // -[NSString fileSystemRepresentation] to prevent exceptions from being thrown. // See http://crbug.com/78782 for more info. -base::FilePath FilePathFromFilename(const string16& filename) { +base::FilePath FilePathFromFilename(const base::string16& filename) { NSString* str = SysUTF16ToNSString(filename); char buf[MAXPATHLEN]; if (![str getFileSystemRepresentation:buf maxLength:sizeof(buf)]) @@ -71,7 +71,7 @@ base::FilePath GetFileNameFromDragData(const DropData& drop_data) { // synthesize one from the provided extension and URL. if (file_name.empty()) { // Retrieve the name from the URL. - string16 suggested_filename = + base::string16 suggested_filename = net::GetSuggestedFilename(drop_data.url, "", "", "", "", ""); const std::string extension = file_name.Extension(); file_name = FilePathFromFilename(suggested_filename); @@ -147,7 +147,7 @@ void PromiseWriterHelper(const DropData& drop_data, - (void)lazyWriteToPasteboard:(NSPasteboard*)pboard forType:(NSString*)type { // NSHTMLPboardType requires the character set to be declared. Otherwise, it // assumes US-ASCII. Awesome. - const string16 kHtmlHeader = ASCIIToUTF16( + const base::string16 kHtmlHeader = ASCIIToUTF16( "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\">"); // Be extra paranoid; avoid crashing. @@ -386,7 +386,7 @@ void PromiseWriterHelper(const DropData& drop_data, downloadFileName_ = GetFileNameFromDragData(*dropData_); net::GetMimeTypeFromExtension(downloadFileName_.Extension(), &mimeType); } else { - string16 mimeType16; + base::string16 mimeType16; base::FilePath fileName; if (content::ParseDownloadMetadata( dropData_->download_metadata, diff --git a/content/browser/webui/web_ui_data_source_impl.cc b/content/browser/webui/web_ui_data_source_impl.cc index 6a5b602562..6775eb739d 100644 --- a/content/browser/webui/web_ui_data_source_impl.cc +++ b/content/browser/webui/web_ui_data_source_impl.cc @@ -95,7 +95,7 @@ WebUIDataSourceImpl::~WebUIDataSourceImpl() { } void WebUIDataSourceImpl::AddString(const std::string& name, - const string16& value) { + const base::string16& value) { localized_strings_.SetString(name, value); } diff --git a/content/browser/webui/web_ui_data_source_impl.h b/content/browser/webui/web_ui_data_source_impl.h index 1f8100469e..91ec087cfc 100644 --- a/content/browser/webui/web_ui_data_source_impl.h +++ b/content/browser/webui/web_ui_data_source_impl.h @@ -28,7 +28,7 @@ class CONTENT_EXPORT WebUIDataSourceImpl public: // WebUIDataSource implementation: virtual void AddString(const std::string& name, - const string16& value) OVERRIDE; + const base::string16& value) OVERRIDE; virtual void AddString(const std::string& name, const std::string& value) OVERRIDE; virtual void AddLocalizedString(const std::string& name, int ids) OVERRIDE; diff --git a/content/browser/webui/web_ui_data_source_unittest.cc b/content/browser/webui/web_ui_data_source_unittest.cc index f384a43e94..a5da7eb821 100644 --- a/content/browser/webui/web_ui_data_source_unittest.cc +++ b/content/browser/webui/web_ui_data_source_unittest.cc @@ -25,10 +25,10 @@ class TestClient : public TestContentClient { TestClient() {} virtual ~TestClient() {} - virtual string16 GetLocalizedString(int message_id) const OVERRIDE { + virtual base::string16 GetLocalizedString(int message_id) const OVERRIDE { if (message_id == kDummyStringId) return UTF8ToUTF16(kDummyString); - return string16(); + return base::string16(); } diff --git a/content/browser/webui/web_ui_impl.cc b/content/browser/webui/web_ui_impl.cc index e54a6d8c27..4774e4f17a 100644 --- a/content/browser/webui/web_ui_impl.cc +++ b/content/browser/webui/web_ui_impl.cc @@ -27,10 +27,10 @@ namespace content { const WebUI::TypeID WebUI::kNoWebUI = NULL; // static -string16 WebUI::GetJavascriptCall( +base::string16 WebUI::GetJavascriptCall( const std::string& function_name, const std::vector<const Value*>& arg_list) { - string16 parameters; + base::string16 parameters; std::string json; for (size_t i = 0; i < arg_list.size(); ++i) { if (i > 0) @@ -106,11 +106,11 @@ ui::ScaleFactor WebUIImpl::GetDeviceScaleFactor() const { return GetScaleFactorForView(web_contents_->GetRenderWidgetHostView()); } -const string16& WebUIImpl::GetOverriddenTitle() const { +const base::string16& WebUIImpl::GetOverriddenTitle() const { return overridden_title_; } -void WebUIImpl::OverrideTitle(const string16& title) { +void WebUIImpl::OverrideTitle(const base::string16& title) { overridden_title_ = title; } @@ -144,7 +144,7 @@ void WebUIImpl::SetController(WebUIController* controller) { void WebUIImpl::CallJavascriptFunction(const std::string& function_name) { DCHECK(IsStringASCII(function_name)); - string16 javascript = ASCIIToUTF16(function_name + "();"); + base::string16 javascript = ASCIIToUTF16(function_name + "();"); ExecuteJavascript(javascript); } @@ -230,7 +230,7 @@ void WebUIImpl::AddMessageHandler(WebUIMessageHandler* handler) { handlers_.push_back(handler); } -void WebUIImpl::ExecuteJavascript(const string16& javascript) { +void WebUIImpl::ExecuteJavascript(const base::string16& javascript) { static_cast<RenderViewHostImpl*>( web_contents_->GetRenderViewHost())->ExecuteJavascriptInWebFrame( ASCIIToUTF16(frame_xpath_), javascript); diff --git a/content/browser/webui/web_ui_impl.h b/content/browser/webui/web_ui_impl.h index a359117ced..8715e43e22 100644 --- a/content/browser/webui/web_ui_impl.h +++ b/content/browser/webui/web_ui_impl.h @@ -33,8 +33,8 @@ class CONTENT_EXPORT WebUIImpl : public WebUI, virtual WebUIController* GetController() const OVERRIDE; virtual void SetController(WebUIController* controller) OVERRIDE; virtual ui::ScaleFactor GetDeviceScaleFactor() const OVERRIDE; - virtual const string16& GetOverriddenTitle() const OVERRIDE; - virtual void OverrideTitle(const string16& title) OVERRIDE; + virtual const base::string16& GetOverriddenTitle() const OVERRIDE; + virtual void OverrideTitle(const base::string16& title) OVERRIDE; virtual PageTransition GetLinkTransitionType() const OVERRIDE; virtual void SetLinkTransitionType(PageTransition type) OVERRIDE; virtual int GetBindings() const OVERRIDE; @@ -78,7 +78,7 @@ class CONTENT_EXPORT WebUIImpl : public WebUI, const base::ListValue& args); // Execute a string of raw Javascript on the page. - void ExecuteJavascript(const string16& javascript); + void ExecuteJavascript(const base::string16& javascript); // A map of message name -> message handling callback. typedef std::map<std::string, MessageCallback> MessageCallbackMap; @@ -86,7 +86,7 @@ class CONTENT_EXPORT WebUIImpl : public WebUI, // Options that may be overridden by individual Web UI implementations. The // bool options default to false. See the public getters for more information. - string16 overridden_title_; // Defaults to empty string. + base::string16 overridden_title_; // Defaults to empty string. PageTransition link_transition_type_; // Defaults to LINK. int bindings_; // The bindings from BindingsPolicy that should be enabled for // this page. diff --git a/content/browser/webui/web_ui_message_handler.cc b/content/browser/webui/web_ui_message_handler.cc index db554c0ed8..57b2c46b86 100644 --- a/content/browser/webui/web_ui_message_handler.cc +++ b/content/browser/webui/web_ui_message_handler.cc @@ -36,12 +36,12 @@ bool WebUIMessageHandler::ExtractDoubleValue(const ListValue* value, return false; } -string16 WebUIMessageHandler::ExtractStringValue(const ListValue* value) { - string16 string16_value; +base::string16 WebUIMessageHandler::ExtractStringValue(const ListValue* value) { + base::string16 string16_value; if (value->GetString(0, &string16_value)) return string16_value; NOTREACHED(); - return string16(); + return base::string16(); } } // namespace content diff --git a/content/browser/webui/web_ui_message_handler_unittest.cc b/content/browser/webui/web_ui_message_handler_unittest.cc index e38acd7e31..33cdb61fb1 100644 --- a/content/browser/webui/web_ui_message_handler_unittest.cc +++ b/content/browser/webui/web_ui_message_handler_unittest.cc @@ -14,9 +14,9 @@ namespace content { TEST(WebUIMessageHandlerTest, ExtractIntegerValue) { ListValue list; int value, zero_value = 0, neg_value = -1234, pos_value = 1234; - string16 zero_string(UTF8ToUTF16("0")); - string16 neg_string(UTF8ToUTF16("-1234")); - string16 pos_string(UTF8ToUTF16("1234")); + base::string16 zero_string(UTF8ToUTF16("0")); + base::string16 neg_string(UTF8ToUTF16("-1234")); + base::string16 pos_string(UTF8ToUTF16("1234")); list.Append(new base::FundamentalValue(zero_value)); EXPECT_TRUE(WebUIMessageHandler::ExtractIntegerValue(&list, &value)); @@ -51,9 +51,9 @@ TEST(WebUIMessageHandlerTest, ExtractIntegerValue) { TEST(WebUIMessageHandlerTest, ExtractDoubleValue) { base::ListValue list; double value, zero_value = 0.0, neg_value = -1234.5, pos_value = 1234.5; - string16 zero_string(UTF8ToUTF16("0")); - string16 neg_string(UTF8ToUTF16("-1234.5")); - string16 pos_string(UTF8ToUTF16("1234.5")); + base::string16 zero_string(UTF8ToUTF16("0")); + base::string16 neg_string(UTF8ToUTF16("-1234.5")); + base::string16 pos_string(UTF8ToUTF16("1234.5")); list.Append(new base::FundamentalValue(zero_value)); EXPECT_TRUE(WebUIMessageHandler::ExtractDoubleValue(&list, &value)); @@ -87,10 +87,10 @@ TEST(WebUIMessageHandlerTest, ExtractDoubleValue) { TEST(WebUIMessageHandlerTest, ExtractStringValue) { base::ListValue list; - string16 in_string(UTF8ToUTF16( + base::string16 in_string(UTF8ToUTF16( "The facts, though interesting, are irrelevant.")); list.Append(new base::StringValue(in_string)); - string16 out_string = WebUIMessageHandler::ExtractStringValue(&list); + base::string16 out_string = WebUIMessageHandler::ExtractStringValue(&list); EXPECT_EQ(in_string, out_string); } diff --git a/content/browser/worker_host/test/worker_browsertest.cc b/content/browser/worker_host/test/worker_browsertest.cc index a71a28e1f9..acd00fba10 100644 --- a/content/browser/worker_host/test/worker_browsertest.cc +++ b/content/browser/worker_host/test/worker_browsertest.cc @@ -42,10 +42,10 @@ class WorkerTest : public ContentBrowserTest { const std::string& test_case, const std::string& query) { GURL url = GetTestURL(test_case, query); - const string16 expected_title = ASCIIToUTF16("OK"); + const base::string16 expected_title = ASCIIToUTF16("OK"); TitleWatcher title_watcher(window->web_contents(), expected_title); NavigateToURL(window, url); - string16 final_title = title_watcher.WaitAndGetTitle(); + base::string16 final_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, final_title); } @@ -275,10 +275,10 @@ IN_PROC_BROWSER_TEST_F(WorkerTest, WebSocketSharedWorker) { // Run test. Shell* window = shell(); - const string16 expected_title = ASCIIToUTF16("OK"); + const base::string16 expected_title = ASCIIToUTF16("OK"); TitleWatcher title_watcher(window->web_contents(), expected_title); NavigateToURL(window, url); - string16 final_title = title_watcher.WaitAndGetTitle(); + base::string16 final_title = title_watcher.WaitAndGetTitle(); EXPECT_EQ(expected_title, final_title); } diff --git a/content/browser/worker_host/worker_process_host.cc b/content/browser/worker_host/worker_process_host.cc index 08277da2a4..fae589bf47 100644 --- a/content/browser/worker_host/worker_process_host.cc +++ b/content/browser/worker_host/worker_process_host.cc @@ -372,8 +372,8 @@ void WorkerProcessHost::OnWorkerContextClosed(int worker_route_id) { void WorkerProcessHost::OnAllowDatabase(int worker_route_id, const GURL& url, - const string16& name, - const string16& display_name, + const base::string16& name, + const base::string16& display_name, unsigned long estimated_size, bool* result) { *result = GetContentClient()->browser()->AllowWorkerDatabase( @@ -390,7 +390,7 @@ void WorkerProcessHost::OnAllowFileSystem(int worker_route_id, void WorkerProcessHost::OnAllowIndexedDB(int worker_route_id, const GURL& url, - const string16& name, + const base::string16& name, bool* result) { *result = GetContentClient()->browser()->AllowWorkerIndexedDB( url, name, resource_context_, GetRenderViewIDsForWorker(worker_route_id)); @@ -572,7 +572,7 @@ net::URLRequestContext* WorkerProcessHost::GetRequestContext( WorkerProcessHost::WorkerInstance::WorkerInstance( const GURL& url, - const string16& name, + const base::string16& name, int worker_route_id, int parent_process_id, int64 main_resource_appcache_id, @@ -593,7 +593,7 @@ WorkerProcessHost::WorkerInstance::WorkerInstance( WorkerProcessHost::WorkerInstance::WorkerInstance( const GURL& url, bool shared, - const string16& name, + const base::string16& name, ResourceContext* resource_context, const WorkerStoragePartition& partition) : url_(url), @@ -618,7 +618,7 @@ WorkerProcessHost::WorkerInstance::~WorkerInstance() { // b) the names are both empty, and the urls are equal bool WorkerProcessHost::WorkerInstance::Matches( const GURL& match_url, - const string16& match_name, + const base::string16& match_name, const WorkerStoragePartition& partition, ResourceContext* resource_context) const { // Only match open shared workers. diff --git a/content/browser/worker_host/worker_process_host.h b/content/browser/worker_host/worker_process_host.h index 0a9ea6005b..c3fa64d6d7 100644 --- a/content/browser/worker_host/worker_process_host.h +++ b/content/browser/worker_host/worker_process_host.h @@ -57,7 +57,7 @@ class WorkerProcessHost : public BrowserChildProcessHostDelegate, class WorkerInstance { public: WorkerInstance(const GURL& url, - const string16& name, + const base::string16& name, int worker_route_id, int parent_process_id, int64 main_resource_appcache_id, @@ -66,7 +66,7 @@ class WorkerProcessHost : public BrowserChildProcessHostDelegate, // Used for pending instances. Rest of the parameters are ignored. WorkerInstance(const GURL& url, bool shared, - const string16& name, + const base::string16& name, ResourceContext* resource_context, const WorkerStoragePartition& partition); ~WorkerInstance(); @@ -92,7 +92,7 @@ class WorkerProcessHost : public BrowserChildProcessHostDelegate, // applies to shared workers. bool Matches( const GURL& url, - const string16& name, + const base::string16& name, const WorkerStoragePartition& partition, ResourceContext* resource_context) const; @@ -107,7 +107,7 @@ class WorkerProcessHost : public BrowserChildProcessHostDelegate, bool closed() const { return closed_; } void set_closed(bool closed) { closed_ = closed; } const GURL& url() const { return url_; } - const string16 name() const { return name_; } + const base::string16 name() const { return name_; } int worker_route_id() const { return worker_route_id_; } int parent_process_id() const { return parent_process_id_; } int64 main_resource_appcache_id() const { @@ -127,7 +127,7 @@ class WorkerProcessHost : public BrowserChildProcessHostDelegate, // Set of all filters (clients) associated with this worker. GURL url_; bool closed_; - string16 name_; + base::string16 name_; int worker_route_id_; int parent_process_id_; int64 main_resource_appcache_id_; @@ -196,8 +196,8 @@ class WorkerProcessHost : public BrowserChildProcessHostDelegate, void OnWorkerContextClosed(int worker_route_id); void OnAllowDatabase(int worker_route_id, const GURL& url, - const string16& name, - const string16& display_name, + const base::string16& name, + const base::string16& display_name, unsigned long estimated_size, bool* result); void OnAllowFileSystem(int worker_route_id, @@ -205,7 +205,7 @@ class WorkerProcessHost : public BrowserChildProcessHostDelegate, bool* result); void OnAllowIndexedDB(int worker_route_id, const GURL& url, - const string16& name, + const base::string16& name, bool* result); void OnForceKillWorkerProcess(); diff --git a/content/browser/worker_host/worker_service_impl.cc b/content/browser/worker_host/worker_service_impl.cc index d2ab272922..3ebab469ff 100644 --- a/content/browser/worker_host/worker_service_impl.cc +++ b/content/browser/worker_host/worker_service_impl.cc @@ -650,7 +650,7 @@ void WorkerServiceImpl::NotifyWorkerProcessCreated() { WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance( const GURL& url, - const string16& name, + const base::string16& name, const WorkerStoragePartition& partition, ResourceContext* resource_context) { for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { @@ -667,7 +667,7 @@ WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance( WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindPendingInstance( const GURL& url, - const string16& name, + const base::string16& name, const WorkerStoragePartition& partition, ResourceContext* resource_context) { // Walk the pending instances looking for a matching pending worker. @@ -684,7 +684,7 @@ WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindPendingInstance( void WorkerServiceImpl::RemovePendingInstances( const GURL& url, - const string16& name, + const base::string16& name, const WorkerStoragePartition& partition, ResourceContext* resource_context) { // Walk the pending instances looking for a matching pending worker. @@ -701,7 +701,7 @@ void WorkerServiceImpl::RemovePendingInstances( WorkerProcessHost::WorkerInstance* WorkerServiceImpl::CreatePendingInstance( const GURL& url, - const string16& name, + const base::string16& name, ResourceContext* resource_context, const WorkerStoragePartition& partition) { // Look for an existing pending shared worker. diff --git a/content/browser/worker_host/worker_service_impl.h b/content/browser/worker_host/worker_service_impl.h index 9da0d19cd2..4d5127aec2 100644 --- a/content/browser/worker_host/worker_service_impl.h +++ b/content/browser/worker_host/worker_service_impl.h @@ -108,23 +108,23 @@ class CONTENT_EXPORT WorkerServiceImpl // APIs for manipulating our set of pending shared worker instances. WorkerProcessHost::WorkerInstance* CreatePendingInstance( const GURL& url, - const string16& name, + const base::string16& name, ResourceContext* resource_context, const WorkerStoragePartition& worker_partition); WorkerProcessHost::WorkerInstance* FindPendingInstance( const GURL& url, - const string16& name, + const base::string16& name, const WorkerStoragePartition& worker_partition, ResourceContext* resource_context); void RemovePendingInstances( const GURL& url, - const string16& name, + const base::string16& name, const WorkerStoragePartition& worker_partition, ResourceContext* resource_context); WorkerProcessHost::WorkerInstance* FindSharedWorkerInstance( const GURL& url, - const string16& name, + const base::string16& name, const WorkerStoragePartition& worker_partition, ResourceContext* resource_context); |