diff options
author | Andras Becsi <andras.becsi@digia.com> | 2014-03-18 13:16:26 +0100 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-03-20 15:55:39 +0100 |
commit | 3f0f86b0caed75241fa71c95a5d73bc0164348c5 (patch) | |
tree | 92b9fb00f2e9e90b0be2262093876d4f43b6cd13 /chromium/content/renderer | |
parent | e90d7c4b152c56919d963987e2503f9909a666d2 (diff) |
Update to new stable branch 1750
This also includes an updated ninja and chromium dependencies
needed on Windows.
Change-Id: Icd597d80ed3fa4425933c9f1334c3c2e31291c42
Reviewed-by: Zoltan Arvai <zarvai@inf.u-szeged.hu>
Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
Diffstat (limited to 'chromium/content/renderer')
533 files changed, 22219 insertions, 14068 deletions
diff --git a/chromium/content/renderer/DEPS b/chromium/content/renderer/DEPS index 2da21ae9152..10db7729647 100644 --- a/chromium/content/renderer/DEPS +++ b/chromium/content/renderer/DEPS @@ -1,6 +1,7 @@ include_rules = [ "+content/public/renderer", "+content/child", + "+gin", "+jingle/glue", "+media", # For audio input/output and audio/video decoding. "+third_party/hyphen/hyphen.h", diff --git a/chromium/content/renderer/OWNERS b/chromium/content/renderer/OWNERS index 5c44d85d058..b3105d08b3c 100644 --- a/chromium/content/renderer/OWNERS +++ b/chromium/content/renderer/OWNERS @@ -1,5 +1,4 @@ jamesr@chromium.org -jochen@chromium.org # Mac Sandbox profiles. per-file *.sb=set noparent diff --git a/chromium/content/renderer/accessibility/accessibility_node_serializer.cc b/chromium/content/renderer/accessibility/accessibility_node_serializer.cc index 87fd1494010..39fa24520f5 100644 --- a/chromium/content/renderer/accessibility/accessibility_node_serializer.cc +++ b/chromium/content/renderer/accessibility/accessibility_node_serializer.cc @@ -23,12 +23,12 @@ #include "third_party/WebKit/public/web/WebInputElement.h" #include "third_party/WebKit/public/web/WebNode.h" -using WebKit::WebAXObject; -using WebKit::WebDocument; -using WebKit::WebDocumentType; -using WebKit::WebElement; -using WebKit::WebNode; -using WebKit::WebVector; +using blink::WebAXObject; +using blink::WebDocument; +using blink::WebDocumentType; +using blink::WebElement; +using blink::WebNode; +using blink::WebVector; namespace content { namespace { @@ -55,71 +55,71 @@ bool IsParentUnignoredOf(const WebAXObject& ancestor, uint32 ConvertState(const WebAXObject& o) { uint32 state = 0; if (o.isChecked()) - state |= (1 << WebKit::WebAXStateChecked); + state |= (1 << blink::WebAXStateChecked); if (o.isCollapsed()) - state |= (1 << WebKit::WebAXStateCollapsed); + state |= (1 << blink::WebAXStateCollapsed); if (o.canSetFocusAttribute()) - state |= (1 << WebKit::WebAXStateFocusable); + state |= (1 << blink::WebAXStateFocusable); if (o.isFocused()) - state |= (1 << WebKit::WebAXStateFocused); + state |= (1 << blink::WebAXStateFocused); - if (o.role() == WebKit::WebAXRolePopUpButton || + if (o.role() == blink::WebAXRolePopUpButton || o.ariaHasPopup()) { - state |= (1 << WebKit::WebAXStateHaspopup); + state |= (1 << blink::WebAXStateHaspopup); if (!o.isCollapsed()) - state |= (1 << WebKit::WebAXStateExpanded); + state |= (1 << blink::WebAXStateExpanded); } if (o.isHovered()) - state |= (1 << WebKit::WebAXStateHovered); + state |= (1 << blink::WebAXStateHovered); if (o.isIndeterminate()) - state |= (1 << WebKit::WebAXStateIndeterminate); + state |= (1 << blink::WebAXStateIndeterminate); if (!o.isVisible()) - state |= (1 << WebKit::WebAXStateInvisible); + state |= (1 << blink::WebAXStateInvisible); if (o.isLinked()) - state |= (1 << WebKit::WebAXStateLinked); + state |= (1 << blink::WebAXStateLinked); if (o.isMultiSelectable()) - state |= (1 << WebKit::WebAXStateMultiselectable); + state |= (1 << blink::WebAXStateMultiselectable); if (o.isOffScreen()) - state |= (1 << WebKit::WebAXStateOffscreen); + state |= (1 << blink::WebAXStateOffscreen); if (o.isPressed()) - state |= (1 << WebKit::WebAXStatePressed); + state |= (1 << blink::WebAXStatePressed); if (o.isPasswordField()) - state |= (1 << WebKit::WebAXStateProtected); + state |= (1 << blink::WebAXStateProtected); if (o.isReadOnly()) - state |= (1 << WebKit::WebAXStateReadonly); + state |= (1 << blink::WebAXStateReadonly); if (o.isRequired()) - state |= (1 << WebKit::WebAXStateRequired); + state |= (1 << blink::WebAXStateRequired); if (o.canSetSelectedAttribute()) - state |= (1 << WebKit::WebAXStateSelectable); + state |= (1 << blink::WebAXStateSelectable); if (o.isSelected()) - state |= (1 << WebKit::WebAXStateSelected); + state |= (1 << blink::WebAXStateSelected); if (o.isVisited()) - state |= (1 << WebKit::WebAXStateVisited); + state |= (1 << blink::WebAXStateVisited); if (o.isEnabled()) - state |= (1 << WebKit::WebAXStateEnabled); + state |= (1 << blink::WebAXStateEnabled); if (o.isVertical()) - state |= (1 << WebKit::WebAXStateVertical); + state |= (1 << blink::WebAXStateVertical); if (o.isVisited()) - state |= (1 << WebKit::WebAXStateVisited); + state |= (1 << blink::WebAXStateVisited); return state; } @@ -143,7 +143,7 @@ void SerializeAccessibilityNode( dst->AddStringAttribute(dst->ATTR_VALUE, UTF16ToUTF8(src.stringValue())); } - if (dst->role == WebKit::WebAXRoleColorWell) { + if (dst->role == blink::WebAXRoleColorWell) { int r, g, b; src.colorValue(r, g, b); dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_RED, r); @@ -151,6 +151,32 @@ void SerializeAccessibilityNode( dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_BLUE, b); } + if (dst->role == blink::WebAXRoleInlineTextBox) { + dst->AddIntAttribute(dst->ATTR_TEXT_DIRECTION, src.textDirection()); + + WebVector<int> src_character_offsets; + src.characterOffsets(src_character_offsets); + std::vector<int32> character_offsets; + character_offsets.reserve(src_character_offsets.size()); + for (size_t i = 0; i < src_character_offsets.size(); ++i) + character_offsets.push_back(src_character_offsets[i]); + dst->AddIntListAttribute(dst->ATTR_CHARACTER_OFFSETS, character_offsets); + + WebVector<int> src_word_starts; + WebVector<int> src_word_ends; + src.wordBoundaries(src_word_starts, src_word_ends); + std::vector<int32> word_starts; + std::vector<int32> word_ends; + word_starts.reserve(src_word_starts.size()); + word_ends.reserve(src_word_starts.size()); + for (size_t i = 0; i < src_word_starts.size(); ++i) { + word_starts.push_back(src_word_starts[i]); + word_ends.push_back(src_word_ends[i]); + } + dst->AddIntListAttribute(dst->ATTR_WORD_STARTS, word_starts); + dst->AddIntListAttribute(dst->ATTR_WORD_ENDS, word_ends); + } + if (src.accessKey().length()) dst->AddStringAttribute(dst->ATTR_ACCESS_KEY, UTF16ToUTF8(src.accessKey())); if (src.actionVerb().length()) @@ -182,18 +208,18 @@ void SerializeAccessibilityNode( if (!src.url().isEmpty()) dst->AddStringAttribute(dst->ATTR_URL, src.url().spec()); - if (dst->role == WebKit::WebAXRoleHeading) + if (dst->role == blink::WebAXRoleHeading) dst->AddIntAttribute(dst->ATTR_HIERARCHICAL_LEVEL, src.headingLevel()); - else if ((dst->role == WebKit::WebAXRoleTreeItem || - dst->role == WebKit::WebAXRoleRow) && + else if ((dst->role == blink::WebAXRoleTreeItem || + dst->role == blink::WebAXRoleRow) && src.hierarchicalLevel() > 0) { dst->AddIntAttribute(dst->ATTR_HIERARCHICAL_LEVEL, src.hierarchicalLevel()); } // Treat the active list box item as focused. - if (dst->role == WebKit::WebAXRoleListBoxOption && + if (dst->role == blink::WebAXRoleListBoxOption && src.isSelectedOptionActive()) { - dst->state |= (1 << WebKit::WebAXStateFocused); + dst->state |= (1 << blink::WebAXStateFocused); } if (src.canvasHasFallbackContent()) @@ -211,7 +237,7 @@ void SerializeAccessibilityNode( is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME")); if (LowerCaseEqualsASCII(element.getAttribute("aria-expanded"), "true")) - dst->state |= (1 << WebKit::WebAXStateExpanded); + dst->state |= (1 << blink::WebAXStateExpanded); // TODO(ctguil): The tagName in WebKit is lower cased but // HTMLElement::nodeName calls localNameUpper. Consider adding @@ -226,9 +252,9 @@ void SerializeAccessibilityNode( dst->html_attributes.push_back(std::make_pair(name, value)); } - if (dst->role == WebKit::WebAXRoleEditableText || - dst->role == WebKit::WebAXRoleTextArea || - dst->role == WebKit::WebAXRoleTextField) { + if (dst->role == blink::WebAXRoleEditableText || + dst->role == blink::WebAXRoleTextArea || + dst->role == blink::WebAXRoleTextField) { dst->AddIntAttribute(dst->ATTR_TEXT_SEL_START, src.selectionStart()); dst->AddIntAttribute(dst->ATTR_TEXT_SEL_END, src.selectionEnd()); @@ -316,10 +342,10 @@ void SerializeAccessibilityNode( container_live_relevant); } - if (dst->role == WebKit::WebAXRoleProgressIndicator || - dst->role == WebKit::WebAXRoleScrollBar || - dst->role == WebKit::WebAXRoleSlider || - dst->role == WebKit::WebAXRoleSpinButton) { + if (dst->role == blink::WebAXRoleProgressIndicator || + dst->role == blink::WebAXRoleScrollBar || + dst->role == blink::WebAXRoleSlider || + dst->role == blink::WebAXRoleSpinButton) { dst->AddFloatAttribute(dst->ATTR_VALUE_FOR_RANGE, src.valueForRange()); dst->AddFloatAttribute(dst->ATTR_MAX_VALUE_FOR_RANGE, src.maxValueForRange()); @@ -327,8 +353,8 @@ void SerializeAccessibilityNode( src.minValueForRange()); } - if (dst->role == WebKit::WebAXRoleDocument || - dst->role == WebKit::WebAXRoleWebArea) { + if (dst->role == blink::WebAXRoleDocument || + dst->role == blink::WebAXRoleWebArea) { dst->AddStringAttribute(dst->ATTR_HTML_TAG, "#document"); const WebDocument& document = src.document(); if (name.empty()) @@ -361,7 +387,7 @@ void SerializeAccessibilityNode( dst->AddIntAttribute(dst->ATTR_SCROLL_Y_MAX, max_offset.height()); } - if (dst->role == WebKit::WebAXRoleTable) { + if (dst->role == blink::WebAXRoleTable) { int column_count = src.columnCount(); int row_count = src.rowCount(); if (column_count > 0 && row_count > 0) { @@ -391,23 +417,23 @@ void SerializeAccessibilityNode( } } - if (dst->role == WebKit::WebAXRoleRow) { + if (dst->role == blink::WebAXRoleRow) { dst->AddIntAttribute(dst->ATTR_TABLE_ROW_INDEX, src.rowIndex()); WebAXObject header = src.rowHeader(); if (!header.isDetached()) dst->AddIntAttribute(dst->ATTR_TABLE_ROW_HEADER_ID, header.axID()); } - if (dst->role == WebKit::WebAXRoleColumn) { + if (dst->role == blink::WebAXRoleColumn) { dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_INDEX, src.columnIndex()); WebAXObject header = src.columnHeader(); if (!header.isDetached()) dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_HEADER_ID, header.axID()); } - if (dst->role == WebKit::WebAXRoleCell || - dst->role == WebKit::WebAXRoleRowHeader || - dst->role == WebKit::WebAXRoleColumnHeader) { + if (dst->role == blink::WebAXRoleCell || + dst->role == blink::WebAXRoleRowHeader || + dst->role == blink::WebAXRoleColumnHeader) { dst->AddIntAttribute(dst->ATTR_TABLE_CELL_COLUMN_INDEX, src.cellColumnIndex()); dst->AddIntAttribute(dst->ATTR_TABLE_CELL_COLUMN_SPAN, @@ -440,10 +466,10 @@ bool ShouldIncludeChildNode( const WebAXObject& parent, const WebAXObject& child) { switch(parent.role()) { - case WebKit::WebAXRoleSlider: - case WebKit::WebAXRoleEditableText: - case WebKit::WebAXRoleTextArea: - case WebKit::WebAXRoleTextField: + case blink::WebAXRoleSlider: + case blink::WebAXRoleEditableText: + case blink::WebAXRoleTextArea: + case blink::WebAXRoleTextField: return false; default: break; diff --git a/chromium/content/renderer/accessibility/accessibility_node_serializer.h b/chromium/content/renderer/accessibility/accessibility_node_serializer.h index 24e7e9e9ab1..374a79df334 100644 --- a/chromium/content/renderer/accessibility/accessibility_node_serializer.h +++ b/chromium/content/renderer/accessibility/accessibility_node_serializer.h @@ -11,12 +11,12 @@ namespace content { void SerializeAccessibilityNode( - const WebKit::WebAXObject& src, + const blink::WebAXObject& src, AccessibilityNodeData* dst); bool ShouldIncludeChildNode( - const WebKit::WebAXObject& parent, - const WebKit::WebAXObject& child); + const blink::WebAXObject& parent, + const blink::WebAXObject& child); } // namespace content diff --git a/chromium/content/renderer/accessibility/renderer_accessibility.cc b/chromium/content/renderer/accessibility/renderer_accessibility.cc index cf2ecd68327..18eb78fc6a6 100644 --- a/chromium/content/renderer/accessibility/renderer_accessibility.cc +++ b/chromium/content/renderer/accessibility/renderer_accessibility.cc @@ -12,10 +12,10 @@ #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebView.h" -using WebKit::WebAXObject; -using WebKit::WebDocument; -using WebKit::WebFrame; -using WebKit::WebView; +using blink::WebAXObject; +using blink::WebDocument; +using blink::WebFrame; +using blink::WebView; namespace content { @@ -44,59 +44,59 @@ WebDocument RendererAccessibility::GetMainDocument() { #ifndef NDEBUG const std::string RendererAccessibility::AccessibilityEventToString( - WebKit::WebAXEvent event) { + blink::WebAXEvent event) { switch (event) { - case WebKit::WebAXEventActiveDescendantChanged: + case blink::WebAXEventActiveDescendantChanged: return "active descendant changed"; - case WebKit::WebAXEventAriaAttributeChanged: + case blink::WebAXEventAriaAttributeChanged: return "aria attribute changed"; - case WebKit::WebAXEventAutocorrectionOccured: + case blink::WebAXEventAutocorrectionOccured: return "autocorrection occurred"; - case WebKit::WebAXEventBlur: + case blink::WebAXEventBlur: return "blur"; - case WebKit::WebAXEventAlert: + case blink::WebAXEventAlert: return "alert"; - case WebKit::WebAXEventCheckedStateChanged: + case blink::WebAXEventCheckedStateChanged: return "check state changed"; - case WebKit::WebAXEventChildrenChanged: + case blink::WebAXEventChildrenChanged: return "children changed"; - case WebKit::WebAXEventFocus: + case blink::WebAXEventFocus: return "focus changed"; - case WebKit::WebAXEventInvalidStatusChanged: + case blink::WebAXEventInvalidStatusChanged: return "invalid status changed"; - case WebKit::WebAXEventLayoutComplete: + case blink::WebAXEventLayoutComplete: return "layout complete"; - case WebKit::WebAXEventLiveRegionChanged: + case blink::WebAXEventLiveRegionChanged: return "live region changed"; - case WebKit::WebAXEventLoadComplete: + case blink::WebAXEventLoadComplete: return "load complete"; - case WebKit::WebAXEventMenuListItemSelected: + case blink::WebAXEventMenuListItemSelected: return "menu list item selected"; - case WebKit::WebAXEventMenuListValueChanged: + case blink::WebAXEventMenuListValueChanged: return "menu list changed"; - case WebKit::WebAXEventShow: + case blink::WebAXEventShow: return "object show"; - case WebKit::WebAXEventHide: + case blink::WebAXEventHide: return "object hide"; - case WebKit::WebAXEventRowCountChanged: + case blink::WebAXEventRowCountChanged: return "row count changed"; - case WebKit::WebAXEventRowCollapsed: + case blink::WebAXEventRowCollapsed: return "row collapsed"; - case WebKit::WebAXEventRowExpanded: + case blink::WebAXEventRowExpanded: return "row expanded"; - case WebKit::WebAXEventScrolledToAnchor: + case blink::WebAXEventScrolledToAnchor: return "scrolled to anchor"; - case WebKit::WebAXEventSelectedChildrenChanged: + case blink::WebAXEventSelectedChildrenChanged: return "selected children changed"; - case WebKit::WebAXEventSelectedTextChanged: + case blink::WebAXEventSelectedTextChanged: return "selected text changed"; - case WebKit::WebAXEventTextChanged: + case blink::WebAXEventTextChanged: return "text changed"; - case WebKit::WebAXEventTextInserted: + case blink::WebAXEventTextInserted: return "text inserted"; - case WebKit::WebAXEventTextRemoved: + case blink::WebAXEventTextRemoved: return "text removed"; - case WebKit::WebAXEventValueChanged: + case blink::WebAXEventValueChanged: return "value changed"; default: NOTREACHED(); diff --git a/chromium/content/renderer/accessibility/renderer_accessibility.h b/chromium/content/renderer/accessibility/renderer_accessibility.h index 93799eaf60c..cc157ff0671 100644 --- a/chromium/content/renderer/accessibility/renderer_accessibility.h +++ b/chromium/content/renderer/accessibility/renderer_accessibility.h @@ -9,7 +9,7 @@ #include "content/public/renderer/render_view_observer.h" #include "third_party/WebKit/public/web/WebAXObject.h" -namespace WebKit { +namespace blink { class WebDocument; }; @@ -55,15 +55,15 @@ class CONTENT_EXPORT RendererAccessibility : public RenderViewObserver { // Called when an accessibility notification occurs in WebKit. virtual void HandleWebAccessibilityEvent( - const WebKit::WebAXObject& obj, WebKit::WebAXEvent event) = 0; + const blink::WebAXObject& obj, blink::WebAXEvent event) = 0; protected: // Returns the main top-level document for this page, or NULL if there's // no view or frame. - WebKit::WebDocument GetMainDocument(); + blink::WebDocument GetMainDocument(); #ifndef NDEBUG - const std::string AccessibilityEventToString(WebKit::WebAXEvent event); + const std::string AccessibilityEventToString(blink::WebAXEvent event); #endif // The RenderViewImpl that owns us. diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc b/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc index 7f91243a47a..6cc5550c7e7 100644 --- a/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc +++ b/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc @@ -14,8 +14,8 @@ #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebView.h" -using WebKit::WebAXObject; -using WebKit::WebDocument; +using blink::WebAXObject; +using blink::WebDocument; namespace content { @@ -102,7 +102,7 @@ TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) { SetMode(AccessibilityModeEditableTextOnly); // Set a minimum size and give focus so simulated events work. - view()->webwidget()->resize(WebKit::WebSize(500, 500)); + view()->webwidget()->resize(blink::WebSize(500, 500)); view()->webwidget()->setFocus(true); std::string html = @@ -125,16 +125,16 @@ TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) { AccessibilityHostMsg_EventParams event; GetLastAccEvent(&event); EXPECT_EQ(event.event_type, - WebKit::WebAXEventLayoutComplete); + blink::WebAXEventLayoutComplete); EXPECT_EQ(event.id, 1); EXPECT_EQ(event.nodes.size(), 2U); EXPECT_EQ(event.nodes[0].id, 1); EXPECT_EQ(event.nodes[0].role, - WebKit::WebAXRoleRootWebArea); + blink::WebAXRoleRootWebArea); EXPECT_EQ(event.nodes[0].state, - (1U << WebKit::WebAXStateReadonly) | - (1U << WebKit::WebAXStateFocusable) | - (1U << WebKit::WebAXStateFocused)); + (1U << blink::WebAXStateReadonly) | + (1U << blink::WebAXStateFocusable) | + (1U << blink::WebAXStateFocused)); EXPECT_EQ(event.nodes[0].child_ids.size(), 1U); } @@ -146,21 +146,21 @@ TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) { AccessibilityHostMsg_EventParams event; GetLastAccEvent(&event); EXPECT_EQ(event.event_type, - WebKit::WebAXEventFocus); + blink::WebAXEventFocus); EXPECT_EQ(event.id, 3); EXPECT_EQ(event.nodes[0].id, 1); EXPECT_EQ(event.nodes[0].role, - WebKit::WebAXRoleRootWebArea); + blink::WebAXRoleRootWebArea); EXPECT_EQ(event.nodes[0].state, - (1U << WebKit::WebAXStateReadonly) | - (1U << WebKit::WebAXStateFocusable)); + (1U << blink::WebAXStateReadonly) | + (1U << blink::WebAXStateFocusable)); EXPECT_EQ(event.nodes[0].child_ids.size(), 1U); EXPECT_EQ(event.nodes[1].id, 3); EXPECT_EQ(event.nodes[1].role, - WebKit::WebAXRoleGroup); + blink::WebAXRoleGroup); EXPECT_EQ(event.nodes[1].state, - (1U << WebKit::WebAXStateFocusable) | - (1U << WebKit::WebAXStateFocused)); + (1U << blink::WebAXStateFocusable) | + (1U << blink::WebAXStateFocused)); } // Check other editable text nodes. @@ -172,8 +172,8 @@ TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) { GetLastAccEvent(&event); EXPECT_EQ(event.id, 4); EXPECT_EQ(event.nodes[1].state, - (1U << WebKit::WebAXStateFocusable) | - (1U << WebKit::WebAXStateFocused)); + (1U << blink::WebAXStateFocusable) | + (1U << blink::WebAXStateFocused)); } { @@ -184,8 +184,8 @@ TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) { GetLastAccEvent(&event); EXPECT_EQ(event.id, 5); EXPECT_EQ(event.nodes[1].state, - (1U << WebKit::WebAXStateFocusable) | - (1U << WebKit::WebAXStateFocused)); + (1U << blink::WebAXStateFocusable) | + (1U << blink::WebAXStateFocused)); } { @@ -196,8 +196,8 @@ TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) { GetLastAccEvent(&event); EXPECT_EQ(event.id, 6); EXPECT_EQ(event.nodes[1].state, - (1U << WebKit::WebAXStateFocusable) | - (1U << WebKit::WebAXStateFocused)); + (1U << blink::WebAXStateFocusable) | + (1U << blink::WebAXStateFocused)); } // Try focusing things that aren't editable text. @@ -209,9 +209,9 @@ TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) { GetLastAccEvent(&event); EXPECT_EQ(event.id, 7); EXPECT_EQ(event.nodes[1].state, - (1U << WebKit::WebAXStateFocusable) | - (1U << WebKit::WebAXStateFocused) | - (1U << WebKit::WebAXStateReadonly)); + (1U << blink::WebAXStateFocusable) | + (1U << blink::WebAXStateFocused) | + (1U << blink::WebAXStateReadonly)); } { @@ -222,9 +222,9 @@ TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) { GetLastAccEvent(&event); EXPECT_EQ(event.id, 8); EXPECT_EQ(event.nodes[1].state, - (1U << WebKit::WebAXStateFocusable) | - (1U << WebKit::WebAXStateFocused) | - (1U << WebKit::WebAXStateReadonly)); + (1U << blink::WebAXStateFocusable) | + (1U << blink::WebAXStateFocused) | + (1U << blink::WebAXStateReadonly)); } // Clear focus. @@ -269,7 +269,7 @@ TEST_F(RendererAccessibilityTest, SendFullAccessibilityTreeOnReload) { WebAXObject root_obj = document.accessibilityObject(); accessibility->HandleWebAccessibilityEvent( root_obj, - WebKit::WebAXEventLayoutComplete); + blink::WebAXEventLayoutComplete); accessibility->SendPendingAccessibilityEvents(); EXPECT_EQ(4, accessibility->browser_tree_node_count()); EXPECT_EQ(1, CountAccessibilityNodesSentToBrowser()); @@ -289,7 +289,7 @@ TEST_F(RendererAccessibilityTest, SendFullAccessibilityTreeOnReload) { sink_->ClearMessages(); accessibility->HandleWebAccessibilityEvent( root_obj, - WebKit::WebAXEventLayoutComplete); + blink::WebAXEventLayoutComplete); accessibility->SendPendingAccessibilityEvents(); EXPECT_EQ(4, accessibility->browser_tree_node_count()); EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser()); @@ -304,7 +304,7 @@ TEST_F(RendererAccessibilityTest, SendFullAccessibilityTreeOnReload) { const WebAXObject& first_child = root_obj.childAt(0); accessibility->HandleWebAccessibilityEvent( first_child, - WebKit::WebAXEventLiveRegionChanged); + blink::WebAXEventLiveRegionChanged); accessibility->SendPendingAccessibilityEvents(); EXPECT_EQ(4, accessibility->browser_tree_node_count()); EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser()); @@ -332,8 +332,8 @@ TEST_F(RendererAccessibilityTest, scoped_ptr<TestRendererAccessibilityComplete> accessibility( new TestRendererAccessibilityComplete(view())); accessibility->SendPendingAccessibilityEvents(); - EXPECT_EQ(3, accessibility->browser_tree_node_count()); - EXPECT_EQ(3, CountAccessibilityNodesSentToBrowser()); + EXPECT_EQ(5, accessibility->browser_tree_node_count()); + EXPECT_EQ(5, CountAccessibilityNodesSentToBrowser()); // Post a "value changed" event, but then swap out // before sending it. It shouldn't send the event while @@ -343,7 +343,7 @@ TEST_F(RendererAccessibilityTest, WebAXObject root_obj = document.accessibilityObject(); accessibility->HandleWebAccessibilityEvent( root_obj, - WebKit::WebAXEventValueChanged); + blink::WebAXEventValueChanged); view()->OnSwapOut(); accessibility->SendPendingAccessibilityEvents(); EXPECT_FALSE(sink_->GetUniqueMessageMatching( @@ -405,7 +405,7 @@ TEST_F(RendererAccessibilityTest, HideAccessibilityObject) { sink_->ClearMessages(); accessibility->HandleWebAccessibilityEvent( node_a, - WebKit::WebAXEventChildrenChanged); + blink::WebAXEventChildrenChanged); accessibility->SendPendingAccessibilityEvents(); EXPECT_EQ(3, accessibility->browser_tree_node_count()); @@ -455,7 +455,7 @@ TEST_F(RendererAccessibilityTest, ShowAccessibilityObject) { WebAXObject node_a = root_obj.childAt(0); accessibility->HandleWebAccessibilityEvent( node_a, - WebKit::WebAXEventChildrenChanged); + blink::WebAXEventChildrenChanged); accessibility->SendPendingAccessibilityEvents(); EXPECT_EQ(4, accessibility->browser_tree_node_count()); @@ -479,8 +479,8 @@ TEST_F(RendererAccessibilityTest, DetachAccessibilityObject) { scoped_ptr<TestRendererAccessibilityComplete> accessibility( new TestRendererAccessibilityComplete(view())); accessibility->SendPendingAccessibilityEvents(); - EXPECT_EQ(5, accessibility->browser_tree_node_count()); - EXPECT_EQ(5, CountAccessibilityNodesSentToBrowser()); + EXPECT_EQ(7, accessibility->browser_tree_node_count()); + EXPECT_EQ(7, CountAccessibilityNodesSentToBrowser()); // Initially, the accessibility tree looks like this: // @@ -488,7 +488,9 @@ TEST_F(RendererAccessibilityTest, DetachAccessibilityObject) { // +--Body // +--Anonymous Block // +--Static Text "1" + // +--Inline Text Box "1" // +--Static Text "2" + // +--Inline Text Box "2" WebDocument document = view()->GetWebView()->mainFrame()->document(); WebAXObject root_obj = document.accessibilityObject(); WebAXObject body = root_obj.childAt(0); @@ -507,7 +509,7 @@ TEST_F(RendererAccessibilityTest, DetachAccessibilityObject) { sink_->ClearMessages(); accessibility->HandleWebAccessibilityEvent( body, - WebKit::WebAXEventChildrenChanged); + blink::WebAXEventChildrenChanged); accessibility->SendPendingAccessibilityEvents(); @@ -516,17 +518,19 @@ TEST_F(RendererAccessibilityTest, DetachAccessibilityObject) { // Document // +--Body // +--Static Text "1" + // +--Inline Text Box "1" // +--Static Text "2" + // +--Inline Text Box "2" // // We just assert that there are now four nodes in the // accessibility tree and that only three nodes needed // to be updated (the body, the static text 1, and // the static text 2). - EXPECT_EQ(4, accessibility->browser_tree_node_count()); + EXPECT_EQ(6, accessibility->browser_tree_node_count()); AccessibilityHostMsg_EventParams event; GetLastAccEvent(&event); - ASSERT_EQ(3U, event.nodes.size()); + ASSERT_EQ(5U, event.nodes.size()); EXPECT_EQ(body.axID(), event.nodes[0].id); EXPECT_EQ(text_1.axID(), event.nodes[1].id); diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_complete.cc b/chromium/content/renderer/accessibility/renderer_accessibility_complete.cc index d70a00a4820..bf8466dd871 100644 --- a/chromium/content/renderer/accessibility/renderer_accessibility_complete.cc +++ b/chromium/content/renderer/accessibility/renderer_accessibility_complete.cc @@ -17,14 +17,14 @@ #include "third_party/WebKit/public/web/WebNode.h" #include "third_party/WebKit/public/web/WebView.h" -using WebKit::WebAXObject; -using WebKit::WebDocument; -using WebKit::WebFrame; -using WebKit::WebNode; -using WebKit::WebPoint; -using WebKit::WebRect; -using WebKit::WebSize; -using WebKit::WebView; +using blink::WebAXObject; +using blink::WebDocument; +using blink::WebFrame; +using blink::WebNode; +using blink::WebPoint; +using blink::WebRect; +using blink::WebSize; +using blink::WebView; namespace content { @@ -37,17 +37,30 @@ RendererAccessibilityComplete::RendererAccessibilityComplete( ack_pending_(false) { WebAXObject::enableAccessibility(); +#if !defined(OS_ANDROID) + // Skip inline text boxes on Android - since there are no native Android + // APIs that compute the bounds of a range of text, it's a waste to + // include these in the AX tree. + WebAXObject::enableInlineTextBoxAccessibility(); +#endif + const WebDocument& document = GetMainDocument(); if (!document.isNull()) { // It's possible that the webview has already loaded a webpage without // accessibility being enabled. Initialize the browser's cached // accessibility tree by sending it a notification. HandleWebAccessibilityEvent(document.accessibilityObject(), - WebKit::WebAXEventLayoutComplete); + blink::WebAXEventLayoutComplete); } } RendererAccessibilityComplete::~RendererAccessibilityComplete() { + if (browser_root_) { + ClearBrowserTreeNode(browser_root_); + browser_id_map_.erase(browser_root_->id); + delete browser_root_; + } + DCHECK(browser_id_map_.empty()); } bool RendererAccessibilityComplete::OnMessageReceived( @@ -80,11 +93,11 @@ void RendererAccessibilityComplete::FocusedNodeChanged(const WebNode& node) { // When focus is cleared, implicitly focus the document. // TODO(dmazzoni): Make WebKit send this notification instead. HandleWebAccessibilityEvent(document.accessibilityObject(), - WebKit::WebAXEventBlur); + blink::WebAXEventBlur); } } -void RendererAccessibilityComplete::DidFinishLoad(WebKit::WebFrame* frame) { +void RendererAccessibilityComplete::DidFinishLoad(blink::WebFrame* frame) { const WebDocument& document = GetMainDocument(); if (document.isNull()) return; @@ -95,12 +108,12 @@ void RendererAccessibilityComplete::DidFinishLoad(WebKit::WebFrame* frame) { // TODO(dmazzoni): remove this once rdar://5794454 is fixed. WebAXObject new_root = document.accessibilityObject(); if (!browser_root_ || new_root.axID() != browser_root_->id) - HandleWebAccessibilityEvent(new_root, WebKit::WebAXEventLayoutComplete); + HandleWebAccessibilityEvent(new_root, blink::WebAXEventLayoutComplete); } void RendererAccessibilityComplete::HandleWebAccessibilityEvent( - const WebKit::WebAXObject& obj, - WebKit::WebAXEvent event) { + const blink::WebAXObject& obj, + blink::WebAXEvent event) { const WebDocument& document = GetMainDocument(); if (document.isNull()) return; @@ -116,7 +129,7 @@ void RendererAccessibilityComplete::HandleWebAccessibilityEvent( if (!obj.equals(document.accessibilityObject())) { HandleWebAccessibilityEvent( document.accessibilityObject(), - WebKit::WebAXEventLayoutComplete); + blink::WebAXEventLayoutComplete); } } @@ -188,7 +201,7 @@ void RendererAccessibilityComplete::SendPendingAccessibilityEvents() { // doesn't also send us events for each child that changed // selection state, so make sure we re-send that whole subtree. if (event.event_type == - WebKit::WebAXEventSelectedChildrenChanged) { + blink::WebAXEventSelectedChildrenChanged) { base::hash_map<int32, BrowserTreeNode*>::iterator iter = browser_id_map_.find(obj.axID()); if (iter != browser_id_map_.end()) @@ -207,7 +220,7 @@ void RendererAccessibilityComplete::SendPendingAccessibilityEvents() { obj.axID() != root_id) { obj = obj.parentObject(); if (event.event_type == - WebKit::WebAXEventChildrenChanged) { + blink::WebAXEventChildrenChanged) { event.id = obj.axID(); } } @@ -266,7 +279,7 @@ void RendererAccessibilityComplete::SendPendingAccessibilityEvents() { if (logging_) { AccessibilityNodeDataTreeNode tree; MakeAccessibilityNodeDataTree(event_msg.nodes, &tree); - LOG(INFO) << "Accessibility update: \n" + VLOG(0) << "Accessibility update: \n" << "routing id=" << routing_id() << " event=" << AccessibilityEventToString(event.event_type) @@ -308,7 +321,7 @@ void RendererAccessibilityComplete::AppendLocationChangeEvents( return; AccessibilityHostMsg_EventParams event_msg; - event_msg.event_type = static_cast<WebKit::WebAXEvent>(-1); + event_msg.event_type = static_cast<blink::WebAXEvent>(-1); event_msg.id = root_object.axID(); event_msg.nodes.resize(location_changes.size()); for (size_t i = 0; i < location_changes.size(); i++) { @@ -328,7 +341,7 @@ RendererAccessibilityComplete::CreateBrowserTreeNode() { } void RendererAccessibilityComplete::SerializeChangedNodes( - const WebKit::WebAXObject& obj, + const blink::WebAXObject& obj, std::vector<AccessibilityNodeData>* dst, std::set<int>* ids_serialized) { if (ids_serialized->find(obj.axID()) != ids_serialized->end()) @@ -431,7 +444,7 @@ void RendererAccessibilityComplete::SerializeChangedNodes( AccessibilityNodeData* serialized_node = &dst->back(); SerializeAccessibilityNode(obj, serialized_node); if (serialized_node->id == browser_root_->id) - serialized_node->role = WebKit::WebAXRoleRootWebArea; + serialized_node->role = blink::WebAXRoleRootWebArea; // Iterate over the children, make note of the ones that are new // and need to be serialized, and update the BrowserTreeNode @@ -457,7 +470,6 @@ void RendererAccessibilityComplete::SerializeChangedNodes( serialized_node->child_ids.push_back(child_id); if (browser_child_id_map.find(child_id) != browser_child_id_map.end()) { BrowserTreeNode* reused_child = browser_child_id_map[child_id]; - reused_child->location = obj.boundingBoxRect(); browser_node->children.push_back(reused_child); } else { BrowserTreeNode* new_child = CreateBrowserTreeNode(); @@ -527,7 +539,7 @@ void RendererAccessibilityComplete::OnScrollToMakeVisible( // https://bugs.webkit.org/show_bug.cgi?id=73460 HandleWebAccessibilityEvent( document.accessibilityObject(), - WebKit::WebAXEventLayoutComplete); + blink::WebAXEventLayoutComplete); } void RendererAccessibilityComplete::OnScrollToPoint( @@ -553,7 +565,7 @@ void RendererAccessibilityComplete::OnScrollToPoint( // https://bugs.webkit.org/show_bug.cgi?id=73460 HandleWebAccessibilityEvent( document.accessibilityObject(), - WebKit::WebAXEventLayoutComplete); + blink::WebAXEventLayoutComplete); } void RendererAccessibilityComplete::OnSetTextSelection( @@ -572,11 +584,11 @@ void RendererAccessibilityComplete::OnSetTextSelection( } // TODO(dmazzoni): support elements other than <input>. - WebKit::WebNode node = obj.node(); + blink::WebNode node = obj.node(); if (!node.isNull() && node.isElementNode()) { - WebKit::WebElement element = node.to<WebKit::WebElement>(); - WebKit::WebInputElement* input_element = - WebKit::toWebInputElement(&element); + blink::WebElement element = node.to<blink::WebElement>(); + blink::WebInputElement* input_element = + blink::toWebInputElement(&element); if (input_element && input_element->isTextField()) input_element->setSelectionRange(start_offset, end_offset); } diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_complete.h b/chromium/content/renderer/accessibility/renderer_accessibility_complete.h index 174062a4cac..d23c7ba4e5e 100644 --- a/chromium/content/renderer/accessibility/renderer_accessibility_complete.h +++ b/chromium/content/renderer/accessibility/renderer_accessibility_complete.h @@ -16,7 +16,7 @@ #include "third_party/WebKit/public/web/WebAXEnums.h" #include "third_party/WebKit/public/web/WebAXObject.h" -namespace WebKit { +namespace blink { class WebDocument; class WebNode; }; @@ -40,12 +40,12 @@ class CONTENT_EXPORT RendererAccessibilityComplete // RenderView::Observer implementation. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - virtual void FocusedNodeChanged(const WebKit::WebNode& node) OVERRIDE; - virtual void DidFinishLoad(WebKit::WebFrame* frame) OVERRIDE; + virtual void FocusedNodeChanged(const blink::WebNode& node) OVERRIDE; + virtual void DidFinishLoad(blink::WebFrame* frame) OVERRIDE; // RendererAccessibility. virtual void HandleWebAccessibilityEvent( - const WebKit::WebAXObject& obj, WebKit::WebAXEvent event) OVERRIDE; + const blink::WebAXObject& obj, blink::WebAXEvent event) OVERRIDE; // In order to keep track of what nodes the browser knows about, we keep a // representation of the browser tree - just IDs and parent/child @@ -78,7 +78,7 @@ class CONTENT_EXPORT RendererAccessibilityComplete // |obj|, based on what object ids we know the browser already has. // The set of ids serialized is added to |ids_serialized|, and any // ids previously in that set are not serialized again. - void SerializeChangedNodes(const WebKit::WebAXObject& obj, + void SerializeChangedNodes(const blink::WebAXObject& obj, std::vector<AccessibilityNodeData>* dst, std::set<int>* ids_serialized); @@ -97,19 +97,19 @@ class CONTENT_EXPORT RendererAccessibilityComplete void OnFatalError(); // Checks if a WebKit accessibility object is an editable text node. - bool IsEditableText(const WebKit::WebAXObject& node); + bool IsEditableText(const blink::WebAXObject& node); // Recursively explore the tree of WebKit accessibility objects rooted // at |src|, and for each editable text node encountered, add a // corresponding WebAccessibility node as a child of |dst|. void RecursiveAddEditableTextNodesToTree( - const WebKit::WebAXObject& src, + const blink::WebAXObject& src, AccessibilityNodeData* dst); // Build a tree of serializable AccessibilityNodeData nodes to send to the // browser process, given a WebAXObject node from WebKit. // Modifies |dst| in-place, it's assumed to be empty. - void BuildAccessibilityTree(const WebKit::WebAXObject& src, + void BuildAccessibilityTree(const blink::WebAXObject& src, bool include_children, AccessibilityNodeData* dst); diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.cc b/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.cc index cea316e6710..b8d1f688b96 100644 --- a/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.cc +++ b/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.cc @@ -12,11 +12,11 @@ #include "third_party/WebKit/public/web/WebNode.h" #include "third_party/WebKit/public/web/WebView.h" -using WebKit::WebDocument; -using WebKit::WebElement; -using WebKit::WebFrame; -using WebKit::WebNode; -using WebKit::WebView; +using blink::WebDocument; +using blink::WebElement; +using blink::WebFrame; +using blink::WebNode; +using blink::WebView; namespace { // The root node will always have id 1. Let each child node have a new @@ -36,7 +36,7 @@ RendererAccessibilityFocusOnly::~RendererAccessibilityFocusOnly() { } void RendererAccessibilityFocusOnly::HandleWebAccessibilityEvent( - const WebKit::WebAXObject& obj, WebKit::WebAXEvent event) { + const blink::WebAXObject& obj, blink::WebAXEvent event) { // Do nothing. } @@ -45,7 +45,7 @@ void RendererAccessibilityFocusOnly::FocusedNodeChanged(const WebNode& node) { HandleFocusedNodeChanged(node, true); } -void RendererAccessibilityFocusOnly::DidFinishLoad(WebKit::WebFrame* frame) { +void RendererAccessibilityFocusOnly::DidFinishLoad(blink::WebFrame* frame) { WebView* view = render_view()->GetWebView(); if (view->focusedFrame() != frame) return; @@ -88,8 +88,8 @@ void RendererAccessibilityFocusOnly::HandleFocusedNodeChanged( // event, which doesn't post a native event on Windows. event.event_type = send_focus_event ? - WebKit::WebAXEventFocus : - WebKit::WebAXEventLayoutComplete; + blink::WebAXEventFocus : + blink::WebAXEventLayoutComplete; // Set the id that the event applies to: the root node if nothing // has focus, otherwise the focused node. @@ -101,17 +101,17 @@ void RendererAccessibilityFocusOnly::HandleFocusedNodeChanged( // Always include the root of the tree, the document. It always has id 1. root.id = 1; - root.role = WebKit::WebAXRoleRootWebArea; + root.role = blink::WebAXRoleRootWebArea; root.state = - (1 << WebKit::WebAXStateReadonly) | - (1 << WebKit::WebAXStateFocusable); + (1 << blink::WebAXStateReadonly) | + (1 << blink::WebAXStateFocusable); if (!node_has_focus) - root.state |= (1 << WebKit::WebAXStateFocused); + root.state |= (1 << blink::WebAXStateFocused); root.location = gfx::Rect(render_view_->size()); root.child_ids.push_back(next_id_); child.id = next_id_; - child.role = WebKit::WebAXRoleGroup; + child.role = blink::WebAXRoleGroup; if (!node.isNull() && node.isElementNode()) { child.location = gfx::Rect( @@ -124,15 +124,15 @@ void RendererAccessibilityFocusOnly::HandleFocusedNodeChanged( if (node_has_focus) { child.state = - (1 << WebKit::WebAXStateFocusable) | - (1 << WebKit::WebAXStateFocused); + (1 << blink::WebAXStateFocusable) | + (1 << blink::WebAXStateFocused); if (!node_is_editable_text) - child.state |= (1 << WebKit::WebAXStateReadonly); + child.state |= (1 << blink::WebAXStateReadonly); } #ifndef NDEBUG if (logging_) { - LOG(INFO) << "Accessibility update: \n" + VLOG(0) << "Accessibility update: \n" << "routing id=" << routing_id() << " event=" << AccessibilityEventToString(event.event_type) diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.h b/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.h index 1d01e1df7ca..c8e09c58b91 100644 --- a/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.h +++ b/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.h @@ -54,14 +54,14 @@ class RendererAccessibilityFocusOnly : public RendererAccessibility { // RendererAccessibility implementation. virtual void HandleWebAccessibilityEvent( - const WebKit::WebAXObject& obj, WebKit::WebAXEvent event) OVERRIDE; + const blink::WebAXObject& obj, blink::WebAXEvent event) OVERRIDE; // RenderView::Observer implementation. - virtual void FocusedNodeChanged(const WebKit::WebNode& node) OVERRIDE; - virtual void DidFinishLoad(WebKit::WebFrame* frame) OVERRIDE; + virtual void FocusedNodeChanged(const blink::WebNode& node) OVERRIDE; + virtual void DidFinishLoad(blink::WebFrame* frame) OVERRIDE; private: - void HandleFocusedNodeChanged(const WebKit::WebNode& node, + void HandleFocusedNodeChanged(const blink::WebNode& node, bool send_focus_event); int next_id_; diff --git a/chromium/content/renderer/active_notification_tracker.cc b/chromium/content/renderer/active_notification_tracker.cc index 9f0b6e0b872..ff2d9cf6561 100644 --- a/chromium/content/renderer/active_notification_tracker.cc +++ b/chromium/content/renderer/active_notification_tracker.cc @@ -9,8 +9,8 @@ #include "third_party/WebKit/public/web/WebNotification.h" #include "third_party/WebKit/public/web/WebNotificationPermissionCallback.h" -using WebKit::WebNotification; -using WebKit::WebNotificationPermissionCallback; +using blink::WebNotification; +using blink::WebNotificationPermissionCallback; namespace content { @@ -38,7 +38,7 @@ bool ActiveNotificationTracker::GetNotification( } int ActiveNotificationTracker::RegisterNotification( - const WebKit::WebNotification& proxy) { + const blink::WebNotification& proxy) { if (reverse_notification_table_.find(proxy) != reverse_notification_table_.end()) { return reverse_notification_table_[proxy]; @@ -66,16 +66,6 @@ void ActiveNotificationTracker::Clear() { } } -void ActiveNotificationTracker::DetachAll() { - ReverseTable::iterator iter; - for (iter = reverse_notification_table_.begin(); - iter != reverse_notification_table_.end(); - ++iter) { - WebNotification notification(iter->first); - notification.detachPresenter(); - } -} - WebNotificationPermissionCallback* ActiveNotificationTracker::GetCallback( int id) { return callback_table_.Lookup(id); diff --git a/chromium/content/renderer/active_notification_tracker.h b/chromium/content/renderer/active_notification_tracker.h index 6591eae334f..b6305a56754 100644 --- a/chromium/content/renderer/active_notification_tracker.h +++ b/chromium/content/renderer/active_notification_tracker.h @@ -13,7 +13,7 @@ #include "content/common/content_export.h" #include "third_party/WebKit/public/web/WebNotification.h" -namespace WebKit { +namespace blink { class WebNotificationPermissionCallback; } @@ -28,31 +28,27 @@ class CONTENT_EXPORT ActiveNotificationTracker { ~ActiveNotificationTracker(); // Methods for tracking active notification objects. - int RegisterNotification(const WebKit::WebNotification& notification); + int RegisterNotification(const blink::WebNotification& notification); void UnregisterNotification(int id); - bool GetId(const WebKit::WebNotification& notification, int& id); - bool GetNotification(int id, WebKit::WebNotification* notification); + bool GetId(const blink::WebNotification& notification, int& id); + bool GetNotification(int id, blink::WebNotification* notification); // Methods for tracking active permission requests. int RegisterPermissionRequest( - WebKit::WebNotificationPermissionCallback* callback); + blink::WebNotificationPermissionCallback* callback); void OnPermissionRequestComplete(int id); - WebKit::WebNotificationPermissionCallback* GetCallback(int id); + blink::WebNotificationPermissionCallback* GetCallback(int id); // Clears out all active notifications. Useful on page navigation. void Clear(); - // Detaches all active notifications from their presenter. Necessary - // when the Presenter is destroyed. - void DetachAll(); - private: - typedef std::map<WebKit::WebNotification, int> ReverseTable; + typedef std::map<blink::WebNotification, int> ReverseTable; // Tracking maps for active notifications and permission requests. - IDMap<WebKit::WebNotification> notification_table_; + IDMap<blink::WebNotification> notification_table_; ReverseTable reverse_notification_table_; - IDMap<WebKit::WebNotificationPermissionCallback> callback_table_; + IDMap<blink::WebNotificationPermissionCallback> callback_table_; DISALLOW_COPY_AND_ASSIGN(ActiveNotificationTracker); }; diff --git a/chromium/content/renderer/active_notification_tracker_unittest.cc b/chromium/content/renderer/active_notification_tracker_unittest.cc index 714a0d110e4..88e8dcd054a 100644 --- a/chromium/content/renderer/active_notification_tracker_unittest.cc +++ b/chromium/content/renderer/active_notification_tracker_unittest.cc @@ -10,13 +10,13 @@ namespace content { TEST(ActiveNotificationTrackerTest, TestLookupAndClear) { ActiveNotificationTracker tracker; - WebKit::WebNotification notification1; + blink::WebNotification notification1; int id1 = tracker.RegisterNotification(notification1); - WebKit::WebNotification notification2; + blink::WebNotification notification2; int id2 = tracker.RegisterNotification(notification2); - WebKit::WebNotification result; + blink::WebNotification result; tracker.GetNotification(id1, &result); EXPECT_TRUE(result == notification1); diff --git a/chromium/content/renderer/android/OWNERS b/chromium/content/renderer/android/OWNERS index 7b7df6dc836..29d0acf8c4e 100644 --- a/chromium/content/renderer/android/OWNERS +++ b/chromium/content/renderer/android/OWNERS @@ -1,4 +1,3 @@ bulach@chromium.org -joth@chromium.org tedchoc@chromium.org yfriedman@chromium.org diff --git a/chromium/content/renderer/android/address_detector.cc b/chromium/content/renderer/android/address_detector.cc index afc7ab6c301..fdc70b136ae 100644 --- a/chromium/content/renderer/android/address_detector.cc +++ b/chromium/content/renderer/android/address_detector.cc @@ -36,20 +36,23 @@ size_t AddressDetector::GetMaximumContentLength() { return kMaxAddressLength; } -std::string AddressDetector::GetContentText(const string16& text) { +std::string AddressDetector::GetContentText(const base::string16& text) { // Get the address and replace unicode bullets with commas. - string16 address_16 = CollapseWhitespace(text, false); + base::string16 address_16 = CollapseWhitespace(text, false); std::replace(address_16.begin(), address_16.end(), static_cast<char16>(0x2022), static_cast<char16>(',')); return UTF16ToUTF8(address_16); } -bool AddressDetector::FindContent(const string16::const_iterator& begin, - const string16::const_iterator& end, size_t* start_pos, size_t* end_pos, +bool AddressDetector::FindContent( + const base::string16::const_iterator& begin, + const base::string16::const_iterator& end, + size_t* start_pos, + size_t* end_pos, std::string* content_text) { if (address_parser::FindAddress(begin, end, start_pos, end_pos)) { content_text->assign( - GetContentText(string16(begin + *start_pos, begin + *end_pos))); + GetContentText(base::string16(begin + *start_pos, begin + *end_pos))); return true; } return false; diff --git a/chromium/content/renderer/android/address_detector.h b/chromium/content/renderer/android/address_detector.h index 2619503af91..eea777f1329 100644 --- a/chromium/content/renderer/android/address_detector.h +++ b/chromium/content/renderer/android/address_detector.h @@ -19,15 +19,15 @@ class AddressDetector : public ContentDetector { private: // Implementation of ContentDetector. - virtual bool FindContent(const string16::const_iterator& begin, - const string16::const_iterator& end, + virtual bool FindContent(const base::string16::const_iterator& begin, + const base::string16::const_iterator& end, size_t* start_pos, size_t* end_pos, std::string* content_text) OVERRIDE; virtual GURL GetIntentURL(const std::string& content_text) OVERRIDE; virtual size_t GetMaximumContentLength() OVERRIDE; - std::string GetContentText(const string16& text); + std::string GetContentText(const base::string16& text); DISALLOW_COPY_AND_ASSIGN(AddressDetector); }; diff --git a/chromium/content/renderer/android/content_detector.cc b/chromium/content/renderer/android/content_detector.cc index 95caba55a94..e5d2f05df71 100644 --- a/chromium/content/renderer/android/content_detector.cc +++ b/chromium/content/renderer/android/content_detector.cc @@ -9,14 +9,14 @@ #include "third_party/WebKit/public/web/WebHitTestResult.h" #include "third_party/WebKit/public/web/WebSurroundingText.h" -using WebKit::WebRange; -using WebKit::WebSurroundingText; +using blink::WebRange; +using blink::WebSurroundingText; namespace content { ContentDetector::Result::Result() : valid(false) {} -ContentDetector::Result::Result(const WebKit::WebRange& content_boundaries, +ContentDetector::Result::Result(const blink::WebRange& content_boundaries, const std::string& text, const GURL& intent_url) : valid(true), @@ -28,12 +28,12 @@ ContentDetector::Result::Result(const WebKit::WebRange& content_boundaries, ContentDetector::Result::~Result() {} ContentDetector::Result ContentDetector::FindTappedContent( - const WebKit::WebHitTestResult& hit_test) { + const blink::WebHitTestResult& hit_test) { if (hit_test.isNull()) return Result(); std::string content_text; - WebKit::WebRange range = FindContentRange(hit_test, &content_text); + blink::WebRange range = FindContentRange(hit_test, &content_text); if (range.isNull()) return Result(); @@ -42,7 +42,7 @@ ContentDetector::Result ContentDetector::FindTappedContent( } WebRange ContentDetector::FindContentRange( - const WebKit::WebHitTestResult& hit_test, + const blink::WebHitTestResult& hit_test, std::string* content_text) { // As the surrounding text extractor looks at maxLength/2 characters on // either side of the hit point, we need to double max content length here. @@ -52,7 +52,7 @@ WebRange ContentDetector::FindContentRange( if (surrounding_text.isNull()) return WebRange(); - string16 content = surrounding_text.textContent(); + base::string16 content = surrounding_text.textContent(); if (content.empty()) return WebRange(); diff --git a/chromium/content/renderer/android/content_detector.h b/chromium/content/renderer/android/content_detector.h index d17a5855b23..28a153af8a0 100644 --- a/chromium/content/renderer/android/content_detector.h +++ b/chromium/content/renderer/android/content_detector.h @@ -8,7 +8,7 @@ #include "third_party/WebKit/public/web/WebRange.h" #include "url/gurl.h" -namespace WebKit { +namespace blink { class WebHitTestResult; } @@ -20,13 +20,13 @@ class ContentDetector { // Holds the content detection results. struct Result { Result(); - Result(const WebKit::WebRange& content_boundaries, + Result(const blink::WebRange& content_boundaries, const std::string& text, const GURL& intent_url); ~Result(); bool valid; - WebKit::WebRange content_boundaries; + blink::WebRange content_boundaries; std::string text; // Processed text of the content. GURL intent_url; // URL of the intent that should process this content. }; @@ -35,7 +35,7 @@ class ContentDetector { // Returns a WebKit range delimiting the contents found around the tapped // position. If no content is found a null range will be returned. - Result FindTappedContent(const WebKit::WebHitTestResult& hit_test); + Result FindTappedContent(const blink::WebHitTestResult& hit_test); protected: ContentDetector() {} @@ -44,8 +44,8 @@ class ContentDetector { // if the desired content is found. The start and end positions relative to // the input iterators are returned in start_pos and end_pos. // The end position is assumed to be non-inclusive. - virtual bool FindContent(const string16::const_iterator& begin, - const string16::const_iterator& end, + virtual bool FindContent(const base::string16::const_iterator& begin, + const base::string16::const_iterator& end, size_t* start_pos, size_t* end_pos, std::string* content_text) = 0; @@ -57,7 +57,7 @@ class ContentDetector { // position in order to search for content. virtual size_t GetMaximumContentLength() = 0; - WebKit::WebRange FindContentRange(const WebKit::WebHitTestResult& hit_test, + blink::WebRange FindContentRange(const blink::WebHitTestResult& hit_test, std::string* content_text); DISALLOW_COPY_AND_ASSIGN(ContentDetector); diff --git a/chromium/content/renderer/android/email_detector.cc b/chromium/content/renderer/android/email_detector.cc index 28b8af4d901..dba1f4245c7 100644 --- a/chromium/content/renderer/android/email_detector.cc +++ b/chromium/content/renderer/android/email_detector.cc @@ -42,12 +42,12 @@ GURL EmailDetector::GetIntentURL(const std::string& content_text) { net::EscapeQueryParamValue(content_text, true)); } -bool EmailDetector::FindContent(const string16::const_iterator& begin, - const string16::const_iterator& end, +bool EmailDetector::FindContent(const base::string16::const_iterator& begin, + const base::string16::const_iterator& end, size_t* start_pos, size_t* end_pos, std::string* content_text) { - string16 utf16_input = string16(begin, end); + base::string16 utf16_input = base::string16(begin, end); icu::UnicodeString pattern(kEmailRegex); icu::UnicodeString input(utf16_input.data(), utf16_input.length()); UErrorCode status = U_ZERO_ERROR; diff --git a/chromium/content/renderer/android/email_detector.h b/chromium/content/renderer/android/email_detector.h index dbd6de3fb71..ff469e865cd 100644 --- a/chromium/content/renderer/android/email_detector.h +++ b/chromium/content/renderer/android/email_detector.h @@ -23,8 +23,8 @@ class CONTENT_EXPORT EmailDetector : public ContentDetector { friend class EmailDetectorTest; // Implementation of ContentDetector. - virtual bool FindContent(const string16::const_iterator& begin, - const string16::const_iterator& end, + virtual bool FindContent(const base::string16::const_iterator& begin, + const base::string16::const_iterator& end, size_t* start_pos, size_t* end_pos, std::string* content_text) OVERRIDE; diff --git a/chromium/content/renderer/android/email_detector_unittest.cc b/chromium/content/renderer/android/email_detector_unittest.cc index f3ed10ff56b..45bcc9bf483 100644 --- a/chromium/content/renderer/android/email_detector_unittest.cc +++ b/chromium/content/renderer/android/email_detector_unittest.cc @@ -13,8 +13,8 @@ class EmailDetectorTest : public testing::Test { public: static void FindAndCheckEmail(const std::string& content, const std::string& expected) { - string16 content_16 = UTF8ToUTF16(content); - string16 result_16; + base::string16 content_16 = UTF8ToUTF16(content); + base::string16 result_16; size_t start, end; EmailDetector detector; std::string content_text; diff --git a/chromium/content/renderer/android/phone_number_detector.cc b/chromium/content/renderer/android/phone_number_detector.cc index 19c526f9bd0..843adfaad1d 100644 --- a/chromium/content/renderer/android/phone_number_detector.cc +++ b/chromium/content/renderer/android/phone_number_detector.cc @@ -54,12 +54,13 @@ GURL PhoneNumberDetector::GetIntentURL(const std::string& content_text) { net::EscapeQueryParamValue(content_text, true)); } -bool PhoneNumberDetector::FindContent(const string16::const_iterator& begin, - const string16::const_iterator& end, - size_t* start_pos, - size_t* end_pos, - std::string* content_text) { - string16 utf16_input = string16(begin, end); +bool PhoneNumberDetector::FindContent( + const base::string16::const_iterator& begin, + const base::string16::const_iterator& end, + size_t* start_pos, + size_t* end_pos, + std::string* content_text) { + base::string16 utf16_input = base::string16(begin, end); std::string utf8_input = UTF16ToUTF8(utf16_input); PhoneNumberMatcher matcher(utf8_input, region_code_); diff --git a/chromium/content/renderer/android/phone_number_detector.h b/chromium/content/renderer/android/phone_number_detector.h index 1ccf47d6158..081a427628e 100644 --- a/chromium/content/renderer/android/phone_number_detector.h +++ b/chromium/content/renderer/android/phone_number_detector.h @@ -24,8 +24,8 @@ class CONTENT_EXPORT PhoneNumberDetector : public ContentDetector { friend class PhoneNumberDetectorTest; // Implementation of ContentDetector. - virtual bool FindContent(const string16::const_iterator& begin, - const string16::const_iterator& end, + virtual bool FindContent(const base::string16::const_iterator& begin, + const base::string16::const_iterator& end, size_t* start_pos, size_t* end_pos, std::string* content_text) OVERRIDE; diff --git a/chromium/content/renderer/android/phone_number_detector_unittest.cc b/chromium/content/renderer/android/phone_number_detector_unittest.cc index 387cedec1b4..e248f0e451f 100644 --- a/chromium/content/renderer/android/phone_number_detector_unittest.cc +++ b/chromium/content/renderer/android/phone_number_detector_unittest.cc @@ -13,8 +13,8 @@ class PhoneNumberDetectorTest : public testing::Test { public: static std::string FindNumber(const std::string& content, const std::string& region) { - string16 content_16 = UTF8ToUTF16(content); - string16 result_16; + base::string16 content_16 = UTF8ToUTF16(content); + base::string16 result_16; size_t start, end; PhoneNumberDetector detector(region); std::string content_text; @@ -26,8 +26,8 @@ class PhoneNumberDetectorTest : public testing::Test { static std::string FindAndFormatNumber(const std::string& content, const std::string& region) { - string16 content_16 = UTF8ToUTF16(content); - string16 result_16; + base::string16 content_16 = UTF8ToUTF16(content); + base::string16 result_16; size_t start, end; PhoneNumberDetector detector(region); std::string content_text; diff --git a/chromium/content/renderer/bmp_image_decoder_unittest.cc b/chromium/content/renderer/bmp_image_decoder_unittest.cc index 019eeb53c97..666196ad84b 100644 --- a/chromium/content/renderer/bmp_image_decoder_unittest.cc +++ b/chromium/content/renderer/bmp_image_decoder_unittest.cc @@ -10,8 +10,8 @@ class BMPImageDecoderTest : public ImageDecoderTest { BMPImageDecoderTest() : ImageDecoderTest("bmp") { } protected: - virtual WebKit::WebImageDecoder* CreateWebKitImageDecoder() const OVERRIDE { - return new WebKit::WebImageDecoder(WebKit::WebImageDecoder::TypeBMP); + virtual blink::WebImageDecoder* CreateWebKitImageDecoder() const OVERRIDE { + return new blink::WebImageDecoder(blink::WebImageDecoder::TypeBMP); } // The BMPImageDecoderTest tests are really slow under Valgrind. diff --git a/chromium/content/renderer/browser_plugin/browser_plugin.cc b/chromium/content/renderer/browser_plugin/browser_plugin.cc index 71aac853dbb..5f88fe142f9 100644 --- a/chromium/content/renderer/browser_plugin/browser_plugin.cc +++ b/chromium/content/renderer/browser_plugin/browser_plugin.cc @@ -43,13 +43,13 @@ #include "base/sys_info.h" #endif -using WebKit::WebCanvas; -using WebKit::WebPluginContainer; -using WebKit::WebPluginParams; -using WebKit::WebPoint; -using WebKit::WebRect; -using WebKit::WebURL; -using WebKit::WebVector; +using blink::WebCanvas; +using blink::WebPluginContainer; +using blink::WebPluginParams; +using blink::WebPoint; +using blink::WebRect; +using blink::WebURL; +using blink::WebVector; namespace content { @@ -59,17 +59,15 @@ static std::string GetInternalEventName(const char* event_name) { return base::StringPrintf("-internal-%s", event_name); } -typedef std::map<WebKit::WebPluginContainer*, +typedef std::map<blink::WebPluginContainer*, BrowserPlugin*> PluginContainerMap; static base::LazyInstance<PluginContainerMap> g_plugin_container_map = LAZY_INSTANCE_INITIALIZER; } // namespace -BrowserPlugin::BrowserPlugin( - RenderViewImpl* render_view, - WebKit::WebFrame* frame, - const WebPluginParams& params) +BrowserPlugin::BrowserPlugin(RenderViewImpl* render_view, + blink::WebFrame* frame) : guest_instance_id_(browser_plugin::kInstanceIDNone), attached_(false), render_view_(render_view->AsWeakPtr()), @@ -90,6 +88,7 @@ BrowserPlugin::BrowserPlugin( mouse_locked_(false), browser_plugin_manager_(render_view->GetBrowserPluginManager()), compositing_enabled_(false), + embedder_frame_url_(frame->document().url()), weak_ptr_factory_(this) { } @@ -107,7 +106,7 @@ BrowserPlugin::~BrowserPlugin() { /*static*/ BrowserPlugin* BrowserPlugin::FromContainer( - WebKit::WebPluginContainer* container) { + blink::WebPluginContainer* container) { PluginContainerMap* browser_plugins = g_plugin_container_map.Pointer(); PluginContainerMap::iterator it = browser_plugins->find(container); return it == browser_plugins->end() ? NULL : it->second; @@ -121,6 +120,8 @@ bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(BrowserPluginMsg_BuffersSwapped, OnBuffersSwapped) IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginMsg_CompositorFrameSwapped, OnCompositorFrameSwapped(message)) + IPC_MESSAGE_HANDLER(BrowserPluginMsg_CopyFromCompositingSurface, + OnCopyFromCompositingSurface) IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestContentWindowReady, OnGuestContentWindowReady) IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestGone, OnGuestGone) @@ -140,14 +141,14 @@ void BrowserPlugin::UpdateDOMAttribute(const std::string& attribute_name, if (!container()) return; - WebKit::WebElement element = container()->element(); - WebKit::WebString web_attribute_name = - WebKit::WebString::fromUTF8(attribute_name); + blink::WebElement element = container()->element(); + blink::WebString web_attribute_name = + blink::WebString::fromUTF8(attribute_name); if (!HasDOMAttribute(attribute_name) || (std::string(element.getAttribute(web_attribute_name).utf8()) != attribute_value)) { element.setAttribute(web_attribute_name, - WebKit::WebString::fromUTF8(attribute_value)); + blink::WebString::fromUTF8(attribute_value)); } } @@ -156,7 +157,7 @@ void BrowserPlugin::RemoveDOMAttribute(const std::string& attribute_name) { return; container()->element().removeAttribute( - WebKit::WebString::fromUTF8(attribute_name)); + blink::WebString::fromUTF8(attribute_name)); } std::string BrowserPlugin::GetDOMAttributeValue( @@ -165,7 +166,7 @@ std::string BrowserPlugin::GetDOMAttributeValue( return std::string(); return container()->element().getAttribute( - WebKit::WebString::fromUTF8(attribute_name)).utf8(); + blink::WebString::fromUTF8(attribute_name)).utf8(); } bool BrowserPlugin::HasDOMAttribute(const std::string& attribute_name) const { @@ -173,13 +174,17 @@ bool BrowserPlugin::HasDOMAttribute(const std::string& attribute_name) const { return false; return container()->element().hasAttribute( - WebKit::WebString::fromUTF8(attribute_name)); + blink::WebString::fromUTF8(attribute_name)); } std::string BrowserPlugin::GetNameAttribute() const { return GetDOMAttributeValue(browser_plugin::kAttributeName); } +bool BrowserPlugin::GetAllowTransparencyAttribute() const { + return HasDOMAttribute(browser_plugin::kAttributeAllowTransparency); +} + std::string BrowserPlugin::GetSrcAttribute() const { return GetDOMAttributeValue(browser_plugin::kAttributeSrc); } @@ -257,6 +262,21 @@ void BrowserPlugin::ParseNameAttribute() { GetNameAttribute())); } +void BrowserPlugin::ParseAllowTransparencyAttribute() { + if (!HasGuestInstanceID()) + return; + + bool opaque = !GetAllowTransparencyAttribute(); + + if (compositing_helper_) + compositing_helper_->SetContentsOpaque(opaque); + + browser_plugin_manager()->Send(new BrowserPluginHostMsg_SetContentsOpaque( + render_view_routing_id_, + guest_instance_id_, + opaque)); +} + bool BrowserPlugin::ParseSrcAttribute(std::string* error_message) { if (!valid_partition_id_) { *error_message = browser_plugin::kErrorInvalidPartition; @@ -370,10 +390,12 @@ void BrowserPlugin::Attach(scoped_ptr<base::DictionaryValue> extra_params) { BrowserPluginHostMsg_Attach_Params attach_params; attach_params.focused = ShouldGuestBeFocused(); attach_params.visible = visible_; + attach_params.opaque = !GetAllowTransparencyAttribute(); attach_params.name = GetNameAttribute(); attach_params.storage_partition_id = storage_partition_id_; attach_params.persist_storage = persist_storage_; attach_params.src = GetSrcAttribute(); + attach_params.embedder_frame_url = embedder_frame_url_; GetDamageBufferWithSizeParams(&attach_params.auto_size_params, &attach_params.resize_guest_params, false); @@ -436,6 +458,23 @@ void BrowserPlugin::OnCompositorFrameSwapped(const IPC::Message& message) { param.e /* host_id */); } +void BrowserPlugin::OnCopyFromCompositingSurface(int guest_instance_id, + int request_id, + gfx::Rect source_rect, + gfx::Size dest_size) { + if (!compositing_enabled_) { + browser_plugin_manager()->Send( + new BrowserPluginHostMsg_CopyFromCompositingSurfaceAck( + render_view_routing_id_, + guest_instance_id_, + request_id, + SkBitmap())); + return; + } + compositing_helper_->CopyFromCompositingSurface(request_id, source_rect, + dest_size); +} + void BrowserPlugin::OnGuestContentWindowReady(int guest_instance_id, int content_window_routing_id) { DCHECK(content_window_routing_id != MSG_ROUTING_NONE); @@ -445,6 +484,14 @@ void BrowserPlugin::OnGuestContentWindowReady(int guest_instance_id, void BrowserPlugin::OnGuestGone(int guest_instance_id) { guest_crashed_ = true; + // Turn off compositing so we can display the sad graphic. Changes to + // compositing state will show up at a later time after a layout and commit. + EnableCompositing(false); + if (compositing_helper_) { + compositing_helper_->OnContainerDestroy(); + compositing_helper_ = NULL; + } + // Queue up showing the sad graphic to give content embedders an opportunity // to fire their listeners and potentially overlay the webview with custom // behavior. If the BrowserPlugin is destroyed in the meantime, then the @@ -479,8 +526,8 @@ void BrowserPlugin::OnShouldAcceptTouchEvents(int guest_instance_id, bool accept) { if (container()) { container()->requestTouchEventType(accept ? - WebKit::WebPluginContainer::TouchEventRequestTypeRaw : - WebKit::WebPluginContainer::TouchEventRequestTypeNone); + blink::WebPluginContainer::TouchEventRequestTypeRaw : + blink::WebPluginContainer::TouchEventRequestTypeNone); } } @@ -634,29 +681,29 @@ NPObject* BrowserPlugin::GetContentWindow() const { content_window_routing_id_); if (!guest_render_view) return NULL; - WebKit::WebFrame* guest_frame = guest_render_view->GetWebView()->mainFrame(); + blink::WebFrame* guest_frame = guest_render_view->GetWebView()->mainFrame(); return guest_frame->windowObject(); } // static -bool BrowserPlugin::AttachWindowTo(const WebKit::WebNode& node, int window_id) { +bool BrowserPlugin::AttachWindowTo(const blink::WebNode& node, int window_id) { if (node.isNull()) return false; if (!node.isElementNode()) return false; - WebKit::WebElement shim_element = node.toConst<WebKit::WebElement>(); + blink::WebElement shim_element = node.toConst<blink::WebElement>(); // The shim containing the BrowserPlugin must be attached to a document. if (shim_element.document().isNull()) return false; - WebKit::WebNode shadow_root = shim_element.shadowRoot(); + blink::WebNode shadow_root = shim_element.shadowRoot(); if (shadow_root.isNull() || !shadow_root.hasChildNodes()) return false; - WebKit::WebNode plugin_element = shadow_root.firstChild(); - WebKit::WebPluginContainer* plugin_container = + blink::WebNode plugin_element = shadow_root.firstChild(); + blink::WebPluginContainer* plugin_container = plugin_element.pluginContainer(); if (!plugin_container) return false; @@ -743,8 +790,6 @@ void BrowserPlugin::ShowSadGraphic() { // NULL so we shouldn't attempt to access it. if (container_) container_->invalidate(); - // Turn off compositing so we can display the sad graphic. - EnableCompositing(false); } void BrowserPlugin::ParseAttributes() { @@ -780,7 +825,7 @@ void BrowserPlugin::TriggerEvent(const std::string& event_name, if (!container()) return; - WebKit::WebFrame* frame = container()->element().document().frame(); + blink::WebFrame* frame = container()->element().document().frame(); if (!frame) return; @@ -801,18 +846,22 @@ void BrowserPlugin::TriggerEvent(const std::string& event_name, return; } - WebKit::WebDOMEvent dom_event = frame->document().createEvent("CustomEvent"); - WebKit::WebDOMCustomEvent event = dom_event.to<WebKit::WebDOMCustomEvent>(); + blink::WebDOMEvent dom_event = frame->document().createEvent("CustomEvent"); + blink::WebDOMCustomEvent event = dom_event.to<blink::WebDOMCustomEvent>(); // The events triggered directly from the plugin <object> are internal events // whose implementation details can (and likely will) change over time. The // wrapper/shim (e.g. <webview> tag) should receive these events, and expose a // more appropriate (and stable) event to the consumers as part of the API. event.initCustomEvent( - WebKit::WebString::fromUTF8(GetInternalEventName(event_name.c_str())), - false, false, - WebKit::WebSerializedScriptValue::serialize( - v8::String::New(json_string.c_str(), json_string.size()))); + blink::WebString::fromUTF8(GetInternalEventName(event_name.c_str())), + false, + false, + blink::WebSerializedScriptValue::serialize( + v8::String::NewFromUtf8(context->GetIsolate(), + json_string.c_str(), + v8::String::kNormalString, + json_string.size()))); container()->element().dispatchEvent(event); } @@ -833,7 +882,7 @@ bool BrowserPlugin::ShouldGuestBeFocused() const { return plugin_focused_ && embedder_focused; } -WebKit::WebPluginContainer* BrowserPlugin::container() const { +blink::WebPluginContainer* BrowserPlugin::container() const { return container_; } @@ -874,21 +923,24 @@ void BrowserPlugin::EnableCompositing(bool enable) { render_view_routing_id_); } } else { - // We're switching back to the software path. We create a new damage - // buffer that can accommodate the current size of the container. - BrowserPluginHostMsg_ResizeGuest_Params params; - // Request a full repaint from the guest even if its size is not actually - // changing. - PopulateResizeGuestParameters(¶ms, - plugin_rect(), - true /* needs_repaint */); - paint_ack_received_ = false; - browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest( - render_view_routing_id_, - guest_instance_id_, - params)); + if (paint_ack_received_) { + // We're switching back to the software path. We create a new damage + // buffer that can accommodate the current size of the container. + BrowserPluginHostMsg_ResizeGuest_Params params; + // Request a full repaint from the guest even if its size is not actually + // changing. + PopulateResizeGuestParameters(¶ms, + plugin_rect(), + true /* needs_repaint */); + paint_ack_received_ = false; + browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest( + render_view_routing_id_, + guest_instance_id_, + params)); + } } compositing_helper_->EnableCompositing(enable); + compositing_helper_->SetContentsOpaque(!GetAllowTransparencyAttribute()); } void BrowserPlugin::destroy() { @@ -916,7 +968,7 @@ NPObject* BrowserPlugin::scriptableObject() { NPObject* browser_plugin_np_object(bindings_->np_object()); // The object is expected to be retained before it is returned. - WebKit::WebBindings::retainObject(browser_plugin_np_object); + blink::WebBindings::retainObject(browser_plugin_np_object); return browser_plugin_np_object; } @@ -932,6 +984,10 @@ bool BrowserPlugin::supportsEditCommands() const { return true; } +bool BrowserPlugin::supportsInputMethod() const { + return true; +} + bool BrowserPlugin::canProcessDrag() const { return true; } @@ -988,7 +1044,7 @@ bool BrowserPlugin::InBounds(const gfx::Point& position) const { gfx::Point BrowserPlugin::ToLocalCoordinates(const gfx::Point& point) const { if (container_) - return container_->windowToLocalPoint(WebKit::WebPoint(point)); + return container_->windowToLocalPoint(blink::WebPoint(point)); return gfx::Point(point.x() - plugin_rect_.x(), point.y() - plugin_rect_.y()); } @@ -1000,6 +1056,7 @@ bool BrowserPlugin::ShouldForwardToBrowserPlugin( case BrowserPluginMsg_Attach_ACK::ID: case BrowserPluginMsg_BuffersSwapped::ID: case BrowserPluginMsg_CompositorFrameSwapped::ID: + case BrowserPluginMsg_CopyFromCompositingSurface::ID: case BrowserPluginMsg_GuestContentWindowReady::ID: case BrowserPluginMsg_GuestGone::ID: case BrowserPluginMsg_SetCursor::ID: @@ -1180,34 +1237,34 @@ bool BrowserPlugin::acceptsInputEvents() { return true; } -bool BrowserPlugin::handleInputEvent(const WebKit::WebInputEvent& event, - WebKit::WebCursorInfo& cursor_info) { +bool BrowserPlugin::handleInputEvent(const blink::WebInputEvent& event, + blink::WebCursorInfo& cursor_info) { if (guest_crashed_ || !HasGuestInstanceID()) return false; - if (event.type == WebKit::WebInputEvent::ContextMenu) + if (event.type == blink::WebInputEvent::ContextMenu) return true; - const WebKit::WebInputEvent* modified_event = &event; - scoped_ptr<WebKit::WebTouchEvent> touch_event; + const blink::WebInputEvent* modified_event = &event; + scoped_ptr<blink::WebTouchEvent> touch_event; // WebKit gives BrowserPlugin a list of touches that are down, but the browser // process expects a list of all touches. We modify the TouchEnd event here to // match these expectations. - if (event.type == WebKit::WebInputEvent::TouchEnd) { - const WebKit::WebTouchEvent* orig_touch_event = - static_cast<const WebKit::WebTouchEvent*>(&event); - touch_event.reset(new WebKit::WebTouchEvent()); - memcpy(touch_event.get(), orig_touch_event, sizeof(WebKit::WebTouchEvent)); + if (event.type == blink::WebInputEvent::TouchEnd) { + const blink::WebTouchEvent* orig_touch_event = + static_cast<const blink::WebTouchEvent*>(&event); + touch_event.reset(new blink::WebTouchEvent()); + memcpy(touch_event.get(), orig_touch_event, sizeof(blink::WebTouchEvent)); if (touch_event->changedTouchesLength > 0) { memcpy(&touch_event->touches[touch_event->touchesLength], &touch_event->changedTouches, - touch_event->changedTouchesLength * sizeof(WebKit::WebTouchPoint)); + touch_event->changedTouchesLength * sizeof(blink::WebTouchPoint)); } touch_event->touchesLength += touch_event->changedTouchesLength; modified_event = touch_event.get(); } - if (WebKit::WebInputEvent::isKeyboardEventType(event.type) && + if (blink::WebInputEvent::isKeyboardEventType(event.type) && !edit_commands_.empty()) { browser_plugin_manager()->Send( new BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent( @@ -1226,11 +1283,11 @@ bool BrowserPlugin::handleInputEvent(const WebKit::WebInputEvent& event, return true; } -bool BrowserPlugin::handleDragStatusUpdate(WebKit::WebDragStatus drag_status, - const WebKit::WebDragData& drag_data, - WebKit::WebDragOperationsMask mask, - const WebKit::WebPoint& position, - const WebKit::WebPoint& screen) { +bool BrowserPlugin::handleDragStatusUpdate(blink::WebDragStatus drag_status, + const blink::WebDragData& drag_data, + blink::WebDragOperationsMask mask, + const blink::WebPoint& position, + const blink::WebPoint& screen) { if (guest_crashed_ || !HasGuestInstanceID()) return false; browser_plugin_manager()->Send( @@ -1245,7 +1302,7 @@ bool BrowserPlugin::handleDragStatusUpdate(WebKit::WebDragStatus drag_status, } void BrowserPlugin::didReceiveResponse( - const WebKit::WebURLResponse& response) { + const blink::WebURLResponse& response) { } void BrowserPlugin::didReceiveData(const char* data, int data_length) { @@ -1254,20 +1311,20 @@ void BrowserPlugin::didReceiveData(const char* data, int data_length) { void BrowserPlugin::didFinishLoading() { } -void BrowserPlugin::didFailLoading(const WebKit::WebURLError& error) { +void BrowserPlugin::didFailLoading(const blink::WebURLError& error) { } -void BrowserPlugin::didFinishLoadingFrameRequest(const WebKit::WebURL& url, +void BrowserPlugin::didFinishLoadingFrameRequest(const blink::WebURL& url, void* notify_data) { } void BrowserPlugin::didFailLoadingFrameRequest( - const WebKit::WebURL& url, + const blink::WebURL& url, void* notify_data, - const WebKit::WebURLError& error) { + const blink::WebURLError& error) { } -bool BrowserPlugin::executeEditCommand(const WebKit::WebString& name) { +bool BrowserPlugin::executeEditCommand(const blink::WebString& name) { browser_plugin_manager()->Send(new BrowserPluginHostMsg_ExecuteEditCommand( render_view_routing_id_, guest_instance_id_, @@ -1277,13 +1334,61 @@ bool BrowserPlugin::executeEditCommand(const WebKit::WebString& name) { return true; } -bool BrowserPlugin::executeEditCommand(const WebKit::WebString& name, - const WebKit::WebString& value) { +bool BrowserPlugin::executeEditCommand(const blink::WebString& name, + const blink::WebString& value) { edit_commands_.push_back(EditCommand(name.utf8(), value.utf8())); // BrowserPlugin swallows edit commands. return true; } +bool BrowserPlugin::setComposition( + const blink::WebString& text, + const blink::WebVector<blink::WebCompositionUnderline>& underlines, + int selectionStart, + int selectionEnd) { + if (!HasGuestInstanceID()) + return false; + std::vector<blink::WebCompositionUnderline> std_underlines; + for (size_t i = 0; i < underlines.size(); ++i) { + std_underlines.push_back(underlines[i]); + } + browser_plugin_manager()->Send(new BrowserPluginHostMsg_ImeSetComposition( + render_view_routing_id_, + guest_instance_id_, + text.utf8(), + std_underlines, + selectionStart, + selectionEnd)); + // TODO(kochi): This assumes the IPC handling always succeeds. + return true; +} + +bool BrowserPlugin::confirmComposition( + const blink::WebString& text, + blink::WebWidget::ConfirmCompositionBehavior selectionBehavior) { + if (!HasGuestInstanceID()) + return false; + bool keep_selection = (selectionBehavior == blink::WebWidget::KeepSelection); + browser_plugin_manager()->Send(new BrowserPluginHostMsg_ImeConfirmComposition( + render_view_routing_id_, + guest_instance_id_, + text.utf8(), + keep_selection)); + // TODO(kochi): This assumes the IPC handling always succeeds. + return true; +} + +void BrowserPlugin::extendSelectionAndDelete(int before, int after) { + if (!HasGuestInstanceID()) + return; + browser_plugin_manager()->Send( + new BrowserPluginHostMsg_ExtendSelectionAndDelete( + render_view_routing_id_, + guest_instance_id_, + before, + after)); +} + void BrowserPlugin::OnLockMouseACK(bool succeeded) { mouse_locked_ = succeeded; browser_plugin_manager()->Send(new BrowserPluginHostMsg_LockMouse_ACK( @@ -1300,7 +1405,7 @@ void BrowserPlugin::OnMouseLockLost() { } bool BrowserPlugin::HandleMouseLockedInputEvent( - const WebKit::WebMouseEvent& event) { + const blink::WebMouseEvent& event) { browser_plugin_manager()->Send( new BrowserPluginHostMsg_HandleInputEvent(render_view_routing_id_, guest_instance_id_, diff --git a/chromium/content/renderer/browser_plugin/browser_plugin.h b/chromium/content/renderer/browser_plugin/browser_plugin.h index ba30ac909d8..d2b21aa7742 100644 --- a/chromium/content/renderer/browser_plugin/browser_plugin.h +++ b/chromium/content/renderer/browser_plugin/browser_plugin.h @@ -14,12 +14,13 @@ #include "base/memory/shared_memory.h" #endif #include "base/values.h" -#include "content/public/common/browser_plugin_permission_type.h" #include "content/renderer/browser_plugin/browser_plugin_backing_store.h" #include "content/renderer/browser_plugin/browser_plugin_bindings.h" #include "content/renderer/mouse_lock_dispatcher.h" #include "content/renderer/render_view_impl.h" +#include "third_party/WebKit/public/web/WebCompositionUnderline.h" #include "third_party/WebKit/public/web/WebDragStatus.h" +#include "third_party/WebKit/public/web/WebWidget.h" struct BrowserPluginHostMsg_AutoSize_Params; struct BrowserPluginHostMsg_ResizeGuest_Params; @@ -34,7 +35,7 @@ class BrowserPluginManager; class MockBrowserPlugin; class CONTENT_EXPORT BrowserPlugin : - NON_EXPORTED_BASE(public WebKit::WebPlugin), + NON_EXPORTED_BASE(public blink::WebPlugin), public MouseLockDispatcher::LockTarget { public: RenderViewImpl* render_view() const { return render_view_.get(); } @@ -42,7 +43,7 @@ class CONTENT_EXPORT BrowserPlugin : int guest_instance_id() const { return guest_instance_id_; } bool attached() const { return attached_; } - static BrowserPlugin* FromContainer(WebKit::WebPluginContainer* container); + static BrowserPlugin* FromContainer(blink::WebPluginContainer* container); bool OnMessageReceived(const IPC::Message& msg); @@ -61,6 +62,11 @@ class CONTENT_EXPORT BrowserPlugin : std::string GetNameAttribute() const; // Parse the name attribute value. void ParseNameAttribute(); + // Get the allowtransparency attribute value. + bool GetAllowTransparencyAttribute() const; + // Parse the allowtransparency attribute and adjust transparency of + // BrowserPlugin accordingly. + void ParseAllowTransparencyAttribute(); // Get the src attribute value of the BrowserPlugin instance. std::string GetSrcAttribute() const; // Parse the src attribute value of the BrowserPlugin instance. @@ -102,7 +108,7 @@ class CONTENT_EXPORT BrowserPlugin : // Attaches the window identified by |window_id| to the the given node // encapsulating a BrowserPlugin. - static bool AttachWindowTo(const WebKit::WebNode& node, + static bool AttachWindowTo(const blink::WebNode& node, int window_id); // Informs the guest of an updated focus state. @@ -139,55 +145,65 @@ class CONTENT_EXPORT BrowserPlugin : // Returns whether a message should be forwarded to BrowserPlugin. static bool ShouldForwardToBrowserPlugin(const IPC::Message& message); - // WebKit::WebPlugin implementation. - virtual WebKit::WebPluginContainer* container() const OVERRIDE; - virtual bool initialize(WebKit::WebPluginContainer* container) OVERRIDE; + // blink::WebPlugin implementation. + virtual blink::WebPluginContainer* container() const OVERRIDE; + virtual bool initialize(blink::WebPluginContainer* container) OVERRIDE; virtual void destroy() OVERRIDE; virtual NPObject* scriptableObject() OVERRIDE; virtual struct _NPP* pluginNPP() OVERRIDE; virtual bool supportsKeyboardFocus() const OVERRIDE; virtual bool supportsEditCommands() const OVERRIDE; + virtual bool supportsInputMethod() const OVERRIDE; virtual bool canProcessDrag() const OVERRIDE; virtual void paint( - WebKit::WebCanvas* canvas, - const WebKit::WebRect& rect) OVERRIDE; + blink::WebCanvas* canvas, + const blink::WebRect& rect) OVERRIDE; virtual void updateGeometry( - const WebKit::WebRect& frame_rect, - const WebKit::WebRect& clip_rect, - const WebKit::WebVector<WebKit::WebRect>& cut_outs_rects, + const blink::WebRect& frame_rect, + const blink::WebRect& clip_rect, + const blink::WebVector<blink::WebRect>& cut_outs_rects, bool is_visible) OVERRIDE; virtual void updateFocus(bool focused) OVERRIDE; virtual void updateVisibility(bool visible) OVERRIDE; virtual bool acceptsInputEvents() OVERRIDE; virtual bool handleInputEvent( - const WebKit::WebInputEvent& event, - WebKit::WebCursorInfo& cursor_info) OVERRIDE; - virtual bool handleDragStatusUpdate(WebKit::WebDragStatus drag_status, - const WebKit::WebDragData& drag_data, - WebKit::WebDragOperationsMask mask, - const WebKit::WebPoint& position, - const WebKit::WebPoint& screen) OVERRIDE; + const blink::WebInputEvent& event, + blink::WebCursorInfo& cursor_info) OVERRIDE; + virtual bool handleDragStatusUpdate(blink::WebDragStatus drag_status, + const blink::WebDragData& drag_data, + blink::WebDragOperationsMask mask, + const blink::WebPoint& position, + const blink::WebPoint& screen) OVERRIDE; virtual void didReceiveResponse( - const WebKit::WebURLResponse& response) OVERRIDE; + const blink::WebURLResponse& response) OVERRIDE; virtual void didReceiveData(const char* data, int data_length) OVERRIDE; virtual void didFinishLoading() OVERRIDE; - virtual void didFailLoading(const WebKit::WebURLError& error) OVERRIDE; + virtual void didFailLoading(const blink::WebURLError& error) OVERRIDE; virtual void didFinishLoadingFrameRequest( - const WebKit::WebURL& url, + const blink::WebURL& url, void* notify_data) OVERRIDE; virtual void didFailLoadingFrameRequest( - const WebKit::WebURL& url, + const blink::WebURL& url, void* notify_data, - const WebKit::WebURLError& error) OVERRIDE; - virtual bool executeEditCommand(const WebKit::WebString& name) OVERRIDE; - virtual bool executeEditCommand(const WebKit::WebString& name, - const WebKit::WebString& value) OVERRIDE; + const blink::WebURLError& error) OVERRIDE; + virtual bool executeEditCommand(const blink::WebString& name) OVERRIDE; + virtual bool executeEditCommand(const blink::WebString& name, + const blink::WebString& value) OVERRIDE; + virtual bool setComposition( + const blink::WebString& text, + const blink::WebVector<blink::WebCompositionUnderline>& underlines, + int selectionStart, + int selectionEnd) OVERRIDE; + virtual bool confirmComposition( + const blink::WebString& text, + blink::WebWidget::ConfirmCompositionBehavior selectionBehavior) OVERRIDE; + virtual void extendSelectionAndDelete(int before, int after) OVERRIDE; // MouseLockDispatcher::LockTarget implementation. virtual void OnLockMouseACK(bool succeeded) OVERRIDE; virtual void OnMouseLockLost() OVERRIDE; virtual bool HandleMouseLockedInputEvent( - const WebKit::WebMouseEvent& event) OVERRIDE; + const blink::WebMouseEvent& event) OVERRIDE; private: friend class base::DeleteHelper<BrowserPlugin>; @@ -199,16 +215,11 @@ class CONTENT_EXPORT BrowserPlugin : friend class MockBrowserPlugin; // A BrowserPlugin object is a controller that represents an instance of a - // browser plugin within the embedder renderer process. Each BrowserPlugin - // within a RenderView has a unique instance_id that is used to track per- - // BrowserPlugin state in the browser process. Once a BrowserPlugin does - // an initial navigation or is attached to a newly created guest, it acquires - // a guest_instance_id as well. The guest instance ID uniquely identifies a - // guest WebContents that's hosted by this BrowserPlugin. - BrowserPlugin( - RenderViewImpl* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params); + // browser plugin within the embedder renderer process. Once a BrowserPlugin + // does an initial navigation or is attached to a newly created guest, it + // acquires a guest_instance_id as well. The guest instance ID uniquely + // identifies a guest WebContents that's hosted by this BrowserPlugin. + BrowserPlugin(RenderViewImpl* render_view, blink::WebFrame* frame); virtual ~BrowserPlugin(); @@ -287,6 +298,10 @@ class CONTENT_EXPORT BrowserPlugin : void OnBuffersSwapped(int instance_id, const BrowserPluginMsg_BuffersSwapped_Params& params); void OnCompositorFrameSwapped(const IPC::Message& message); + void OnCopyFromCompositingSurface(int instance_id, + int request_id, + gfx::Rect source_rect, + gfx::Size dest_size); void OnGuestContentWindowReady(int instance_id, int content_window_routing_id); void OnGuestGone(int instance_id); @@ -308,7 +323,7 @@ class CONTENT_EXPORT BrowserPlugin : // If the |render_view_| is destroyed before the BrowserPlugin is destroyed // then we will attempt to access a NULL pointer. int render_view_routing_id_; - WebKit::WebPluginContainer* container_; + blink::WebPluginContainer* container_; scoped_ptr<BrowserPluginBindings> bindings_; scoped_ptr<BrowserPluginBackingStore> backing_store_; scoped_ptr<base::SharedMemory> current_damage_buffer_; @@ -339,9 +354,6 @@ class CONTENT_EXPORT BrowserPlugin : bool before_first_navigation_; bool mouse_locked_; - typedef std::pair<int, base::WeakPtr<BrowserPlugin> > TrackedV8ObjectID; - std::map<int, TrackedV8ObjectID*> tracked_v8_objects_; - // BrowserPlugin outlives RenderViewImpl in Chrome Apps and so we need to // store the BrowserPlugin's BrowserPluginManager in a member variable to // avoid accessing the RenderViewImpl. @@ -354,6 +366,9 @@ class CONTENT_EXPORT BrowserPlugin : // Used to identify the plugin to WebBindings. scoped_ptr<struct _NPP> npp_; + // URL for the embedder frame. + GURL embedder_frame_url_; + // Weak factory used in v8 |MakeWeak| callback, since the v8 callback might // get called after BrowserPlugin has been destroyed. base::WeakPtrFactory<BrowserPlugin> weak_ptr_factory_; diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_bindings.cc b/chromium/content/renderer/browser_plugin/browser_plugin_bindings.cc index 5dd5231703c..2e0ab773315 100644 --- a/chromium/content/renderer/browser_plugin/browser_plugin_bindings.cc +++ b/chromium/content/renderer/browser_plugin/browser_plugin_bindings.cc @@ -28,12 +28,12 @@ #include "third_party/npapi/bindings/npapi.h" #include "v8/include/v8.h" -using WebKit::WebBindings; -using WebKit::WebElement; -using WebKit::WebDOMEvent; -using WebKit::WebDOMMessageEvent; -using WebKit::WebPluginContainer; -using WebKit::WebString; +using blink::WebBindings; +using blink::WebElement; +using blink::WebDOMEvent; +using blink::WebDOMMessageEvent; +using blink::WebPluginContainer; +using blink::WebString; namespace content { @@ -242,7 +242,7 @@ class BrowserPluginBindingAttach: public BrowserPluginMethodBinding { return false; scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); - v8::Handle<v8::Value> obj(WebKit::WebBindings::toV8Value(&args[0])); + v8::Handle<v8::Value> obj(blink::WebBindings::toV8Value(&args[0])); scoped_ptr<base::Value> value( converter->FromV8Value(obj, bindings->instance()->render_view()-> GetWebView()->mainFrame()->mainWorldScriptContext())); @@ -272,7 +272,7 @@ class BrowserPluginBindingAttachWindowTo : public BrowserPluginMethodBinding { virtual bool Invoke(BrowserPluginBindings* bindings, const NPVariant* args, NPVariant* result) OVERRIDE { - WebKit::WebNode node; + blink::WebNode node; WebBindings::getNode(NPVARIANT_TO_OBJECT(args[0]), &node); int window_id = IntFromNPVariant(args[1]); BOOLEAN_TO_NPVARIANT(BrowserPlugin::AttachWindowTo(node, window_id), @@ -312,6 +312,41 @@ class BrowserPluginPropertyBinding { DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBinding); }; +class BrowserPluginPropertyBindingAllowTransparency + : public BrowserPluginPropertyBinding { + public: + BrowserPluginPropertyBindingAllowTransparency() + : BrowserPluginPropertyBinding( + browser_plugin::kAttributeAllowTransparency) { + } + virtual bool GetProperty(BrowserPluginBindings* bindings, + NPVariant* result) OVERRIDE { + bool allow_transparency = + bindings->instance()->GetAllowTransparencyAttribute(); + BOOLEAN_TO_NPVARIANT(allow_transparency, *result); + return true; + } + virtual bool SetProperty(BrowserPluginBindings* bindings, + NPObject* np_obj, + const NPVariant* variant) OVERRIDE { + std::string value = StringFromNPVariant(*variant); + if (!bindings->instance()->HasDOMAttribute(name())) { + UpdateDOMAttribute(bindings, value); + bindings->instance()->ParseAllowTransparencyAttribute(); + } else { + UpdateDOMAttribute(bindings, value); + } + return true; + } + virtual void RemoveProperty(BrowserPluginBindings* bindings, + NPObject* np_obj) OVERRIDE { + bindings->instance()->RemoveDOMAttribute(name()); + bindings->instance()->ParseAllowTransparencyAttribute(); + } + private: + DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingAllowTransparency); +}; + class BrowserPluginPropertyBindingAutoSize : public BrowserPluginPropertyBinding { public: @@ -638,6 +673,8 @@ BrowserPluginBindings::BrowserPluginBindings(BrowserPlugin* instance) method_bindings_.push_back(new BrowserPluginBindingAttach); method_bindings_.push_back(new BrowserPluginBindingAttachWindowTo); + property_bindings_.push_back( + new BrowserPluginPropertyBindingAllowTransparency); property_bindings_.push_back(new BrowserPluginPropertyBindingAutoSize); property_bindings_.push_back(new BrowserPluginPropertyBindingContentWindow); property_bindings_.push_back(new BrowserPluginPropertyBindingMaxHeight); diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_browsertest.cc b/chromium/content/renderer/browser_plugin/browser_plugin_browsertest.cc index d12b45bdfc2..36ee92cf0fa 100644 --- a/chromium/content/renderer/browser_plugin/browser_plugin_browsertest.cc +++ b/chromium/content/renderer/browser_plugin/browser_plugin_browsertest.cc @@ -16,14 +16,15 @@ #include "content/renderer/render_thread_impl.h" #include "content/renderer/renderer_webkitplatformsupport_impl.h" #include "skia/ext/platform_canvas.h" -#include "third_party/WebKit/public/web/WebCursorInfo.h" +#include "third_party/WebKit/public/platform/WebCursorInfo.h" #include "third_party/WebKit/public/web/WebInputEvent.h" #include "third_party/WebKit/public/web/WebScriptSource.h" namespace { const char kHTMLForBrowserPluginObject[] = "<object id='browserplugin' width='640px' height='480px'" - " src='foo' type='%s'>"; + " src='foo' type='%s'></object>" + "<script>document.querySelector('object').nonExistentAttribute;</script>"; const char kHTMLForBrowserPluginWithAllAttributes[] = "<object id='browserplugin' width='640' height='480' type='%s'" @@ -61,7 +62,7 @@ class TestContentRendererClient : public ContentRendererClient { virtual ~TestContentRendererClient() { } virtual bool AllowBrowserPlugin( - WebKit::WebPluginContainer* container) OVERRIDE { + blink::WebPluginContainer* container) OVERRIDE { // Allow BrowserPlugin for tests. return true; } @@ -114,7 +115,7 @@ std::string BrowserPluginTest::ExecuteScriptAndReturnString( const std::string& script) { v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); v8::Handle<v8::Value> value = GetMainFrame()->executeScriptAndReturnValue( - WebKit::WebScriptSource(WebKit::WebString::fromUTF8(script.c_str()))); + blink::WebScriptSource(blink::WebString::fromUTF8(script.c_str()))); if (value.IsEmpty() || !value->IsString()) return std::string(); @@ -129,7 +130,7 @@ int BrowserPluginTest::ExecuteScriptAndReturnInt( const std::string& script) { v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); v8::Handle<v8::Value> value = GetMainFrame()->executeScriptAndReturnValue( - WebKit::WebScriptSource(WebKit::WebString::fromUTF8(script.c_str()))); + blink::WebScriptSource(blink::WebString::fromUTF8(script.c_str()))); if (value.IsEmpty() || !value->IsInt32()) return 0; @@ -142,7 +143,7 @@ bool BrowserPluginTest::ExecuteScriptAndReturnBool( const std::string& script, bool* result) { v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); v8::Handle<v8::Value> value = GetMainFrame()->executeScriptAndReturnValue( - WebKit::WebScriptSource(WebKit::WebString::fromUTF8(script.c_str()))); + blink::WebScriptSource(blink::WebString::fromUTF8(script.c_str()))); if (value.IsEmpty() || !value->IsBoolean()) return false; diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc b/chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc index c7e1ae88432..a3ce8444df1 100644 --- a/chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc +++ b/chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.cc @@ -4,19 +4,25 @@ #include "content/renderer/browser_plugin/browser_plugin_compositing_helper.h" +#include "cc/layers/delegated_frame_provider.h" +#include "cc/layers/delegated_frame_resource_collection.h" #include "cc/layers/delegated_renderer_layer.h" #include "cc/layers/solid_color_layer.h" #include "cc/layers/texture_layer.h" #include "cc/output/context_provider.h" +#include "cc/output/copy_output_request.h" +#include "cc/output/copy_output_result.h" #include "cc/resources/single_release_callback.h" #include "content/common/browser_plugin/browser_plugin_messages.h" #include "content/common/gpu/client/context_provider_command_buffer.h" #include "content/renderer/browser_plugin/browser_plugin_manager.h" #include "content/renderer/render_thread_impl.h" +#include "skia/ext/image_operations.h" #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" #include "third_party/WebKit/public/web/WebPluginContainer.h" #include "third_party/khronos/GLES2/gl2.h" #include "ui/gfx/size_conversions.h" +#include "ui/gfx/skia_util.h" #include "webkit/renderer/compositor_bindings/web_layer_impl.h" namespace content { @@ -30,7 +36,7 @@ BrowserPluginCompositingHelper::SwapBuffersInfo::SwapBuffersInfo() } BrowserPluginCompositingHelper::BrowserPluginCompositingHelper( - WebKit::WebPluginContainer* container, + blink::WebPluginContainer* container, BrowserPluginManager* manager, int instance_id, int host_routing_id) @@ -41,6 +47,8 @@ BrowserPluginCompositingHelper::BrowserPluginCompositingHelper( last_host_id_(0), last_mailbox_valid_(false), ack_pending_(true), + software_ack_pending_(false), + opaque_(true), container_(container), browser_plugin_manager_(manager) { } @@ -48,12 +56,45 @@ BrowserPluginCompositingHelper::BrowserPluginCompositingHelper( BrowserPluginCompositingHelper::~BrowserPluginCompositingHelper() { } +void BrowserPluginCompositingHelper::CopyFromCompositingSurface( + int request_id, + gfx::Rect source_rect, + gfx::Size dest_size) { + CHECK(background_layer_); + scoped_ptr<cc::CopyOutputRequest> request = + cc::CopyOutputRequest::CreateBitmapRequest(base::Bind( + &BrowserPluginCompositingHelper::CopyFromCompositingSurfaceHasResult, + this, + request_id, + dest_size)); + request->set_area(source_rect); + background_layer_->RequestCopyOfOutput(request.Pass()); +} + void BrowserPluginCompositingHelper::DidCommitCompositorFrame() { - if (!delegated_layer_.get() || !ack_pending_) + if (software_ack_pending_) { + cc::CompositorFrameAck ack; + if (!unacked_software_frames_.empty()) { + ack.last_software_frame_id = unacked_software_frames_.back(); + unacked_software_frames_.pop_back(); + } + + browser_plugin_manager_->Send( + new BrowserPluginHostMsg_CompositorFrameACK( + host_routing_id_, + instance_id_, + last_route_id_, + last_output_surface_id_, + last_host_id_, + ack)); + + software_ack_pending_ = false; + } + if (!resource_collection_.get() || !ack_pending_) return; cc::CompositorFrameAck ack; - delegated_layer_->TakeUnusedResourcesForChildCompositor(&ack.resources); + resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources); browser_plugin_manager_->Send( new BrowserPluginHostMsg_CompositorFrameACK( @@ -79,7 +120,7 @@ void BrowserPluginCompositingHelper::EnableCompositing(bool enable) { container_->setWebLayer(enable ? web_layer_.get() : NULL); } -void BrowserPluginCompositingHelper::CheckSizeAndAdjustLayerBounds( +void BrowserPluginCompositingHelper::CheckSizeAndAdjustLayerProperties( const gfx::Size& new_size, float device_scale_factor, cc::Layer* layer) { @@ -92,6 +133,10 @@ void BrowserPluginCompositingHelper::CheckSizeAndAdjustLayerBounds( gfx::ScaleSize(buffer_size_, 1.0f / device_scale_factor)); layer->SetBounds(device_scale_adjusted_size); } + + // Manually manage background layer for transparent webview. + if (!opaque_) + background_layer_->SetIsDrawable(false); } void BrowserPluginCompositingHelper::MailboxReleased( @@ -112,6 +157,9 @@ void BrowserPluginCompositingHelper::MailboxReleased( last_route_id_ != mailbox.route_id) return; + if (mailbox.type == SOFTWARE_COMPOSITOR_FRAME) + unacked_software_frames_.push_back(mailbox.software_frame_id); + // We need to send an ACK to for every buffer sent to us. // However, if a buffer is freed up from // the compositor in cases like switching back to SW mode without a new @@ -152,20 +200,8 @@ void BrowserPluginCompositingHelper::MailboxReleased( ack)); break; } - case SOFTWARE_COMPOSITOR_FRAME: { - cc::CompositorFrameAck ack; - ack.last_software_frame_id = mailbox.software_frame_id; - - browser_plugin_manager_->Send( - new BrowserPluginHostMsg_CompositorFrameACK( - host_routing_id_, - instance_id_, - mailbox.route_id, - mailbox.output_surface_id, - mailbox.host_id, - ack)); + case SOFTWARE_COMPOSITOR_FRAME: break; - } } } @@ -174,6 +210,13 @@ void BrowserPluginCompositingHelper::OnContainerDestroy() { container_->setWebLayer(NULL); container_ = NULL; + if (resource_collection_) + resource_collection_->SetClient(NULL); + + ack_pending_ = false; + software_ack_pending_ = false; + resource_collection_ = NULL; + frame_provider_ = NULL; texture_layer_ = NULL; delegated_layer_ = NULL; background_layer_ = NULL; @@ -208,7 +251,7 @@ void BrowserPluginCompositingHelper::OnBuffersSwappedPrivate( if (!texture_layer_.get()) { texture_layer_ = cc::TextureLayer::CreateForMailbox(NULL); texture_layer_->SetIsDrawable(true); - texture_layer_->SetContentsOpaque(true); + SetContentsOpaque(opaque_); background_layer_->AddChild(texture_layer_); } @@ -223,9 +266,9 @@ void BrowserPluginCompositingHelper::OnBuffersSwappedPrivate( // when a new buffer arrives. // Visually, this will either display a smaller part of the buffer // or introduce a gutter around it. - CheckSizeAndAdjustLayerBounds(mailbox.size, - device_scale_factor, - texture_layer_.get()); + CheckSizeAndAdjustLayerProperties(mailbox.size, + device_scale_factor, + texture_layer_.get()); bool is_software_frame = mailbox.type == SOFTWARE_COMPOSITOR_FRAME; bool current_mailbox_valid = is_software_frame ? @@ -310,39 +353,80 @@ void BrowserPluginCompositingHelper::OnCompositorFrameSwapped( LOG(ERROR) << "Failed to map shared memory of size " << size_in_bytes; // Send ACK right away. - ack_pending_ = true; + software_ack_pending_ = true; MailboxReleased(swap_info, 0, false); + DidCommitCompositorFrame(); return; } swap_info.shared_memory = shared_memory.release(); OnBuffersSwappedPrivate(swap_info, 0, frame->metadata.device_scale_factor); + software_ack_pending_ = true; + last_route_id_ = route_id; + last_output_surface_id_ = output_surface_id; + last_host_id_ = host_id; return; } DCHECK(!texture_layer_.get()); - if (!delegated_layer_.get()) { - delegated_layer_ = cc::DelegatedRendererLayer::Create(NULL); - delegated_layer_->SetIsDrawable(true); - delegated_layer_->SetContentsOpaque(true); + cc::DelegatedFrameData* frame_data = frame->delegated_frame_data.get(); + // Do nothing if we are getting destroyed or have no frame data. + if (!frame_data || !background_layer_) + return; + + DCHECK(!frame_data->render_pass_list.empty()); + cc::RenderPass* root_pass = frame_data->render_pass_list.back(); + gfx::Size frame_size = root_pass->output_rect.size(); + + if (last_route_id_ != route_id || + last_output_surface_id_ != output_surface_id || + last_host_id_ != host_id) { + // Resource ids are scoped by the output surface. + // If the originating output surface doesn't match the last one, it + // indicates the guest's output surface may have been recreated, in which + // case we should recreate the DelegatedRendererLayer, to avoid matching + // resources from the old one with resources from the new one which would + // have the same id. + frame_provider_ = NULL; + + // Drop the cc::DelegatedFrameResourceCollection so that we will not return + // any resources from the old output surface with the new output surface id. + if (resource_collection_) { + resource_collection_->SetClient(NULL); + + if (resource_collection_->LoseAllResources()) + SendReturnedDelegatedResources(); + resource_collection_ = NULL; + } + last_output_surface_id_ = output_surface_id; + last_route_id_ = route_id; + last_host_id_ = host_id; + } + if (!resource_collection_) { + resource_collection_ = new cc::DelegatedFrameResourceCollection; + resource_collection_->SetClient(this); + } + if (!frame_provider_.get() || frame_provider_->frame_size() != frame_size) { + frame_provider_ = new cc::DelegatedFrameProvider( + resource_collection_.get(), frame->delegated_frame_data.Pass()); + if (delegated_layer_.get()) + delegated_layer_->RemoveFromParent(); + delegated_layer_ = + cc::DelegatedRendererLayer::Create(frame_provider_.get()); + delegated_layer_->SetIsDrawable(true); + SetContentsOpaque(opaque_); background_layer_->AddChild(delegated_layer_); + } else { + frame_provider_->SetFrameData(frame->delegated_frame_data.Pass()); } - cc::DelegatedFrameData *frame_data = frame->delegated_frame_data.get(); - if (!frame_data) - return; - - CheckSizeAndAdjustLayerBounds( + CheckSizeAndAdjustLayerProperties( frame_data->render_pass_list.back()->output_rect.size(), frame->metadata.device_scale_factor, delegated_layer_.get()); - delegated_layer_->SetFrameData(frame->delegated_frame_data.Pass()); - last_route_id_ = route_id; - last_output_surface_id_ = output_surface_id; - last_host_id_ = host_id; ack_pending_ = true; } @@ -353,4 +437,57 @@ void BrowserPluginCompositingHelper::UpdateVisibility(bool visible) { delegated_layer_->SetIsDrawable(visible); } +void BrowserPluginCompositingHelper::UnusedResourcesAreAvailable() { + if (ack_pending_) + return; + + SendReturnedDelegatedResources(); +} + +void BrowserPluginCompositingHelper::SendReturnedDelegatedResources() { + cc::CompositorFrameAck ack; + if (resource_collection_) + resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources); + DCHECK(!ack.resources.empty()); + + browser_plugin_manager_->Send( + new BrowserPluginHostMsg_ReclaimCompositorResources( + host_routing_id_, + instance_id_, + last_route_id_, + last_output_surface_id_, + last_host_id_, + ack)); +} + +void BrowserPluginCompositingHelper::SetContentsOpaque(bool opaque) { + opaque_ = opaque; + + if (texture_layer_.get()) + texture_layer_->SetContentsOpaque(opaque_); + if (delegated_layer_.get()) + delegated_layer_->SetContentsOpaque(opaque_); +} + +void BrowserPluginCompositingHelper::CopyFromCompositingSurfaceHasResult( + int request_id, + gfx::Size dest_size, + scoped_ptr<cc::CopyOutputResult> result) { + scoped_ptr<SkBitmap> bitmap; + if (result && result->HasBitmap() && !result->size().IsEmpty()) + bitmap = result->TakeBitmap(); + + SkBitmap resized_bitmap; + if (bitmap) { + resized_bitmap = skia::ImageOperations::Resize(*bitmap, + skia::ImageOperations::RESIZE_BEST, + dest_size.width(), + dest_size.height()); + } + browser_plugin_manager_->Send( + new BrowserPluginHostMsg_CopyFromCompositingSurfaceAck( + host_routing_id_, instance_id_, request_id, + resized_bitmap)); +} + } // namespace content diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.h b/chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.h index 268a9b46259..7f9a473a619 100644 --- a/chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.h +++ b/chromium/content/renderer/browser_plugin/browser_plugin_compositing_helper.h @@ -6,9 +6,11 @@ #define CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_COMPOSITING_HELPER_H_ #include <string> +#include <vector> #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "cc/layers/delegated_frame_resource_collection.h" #include "content/common/content_export.h" #include "gpu/command_buffer/common/mailbox.h" #include "ui/gfx/size.h" @@ -19,28 +21,40 @@ class SharedMemory; namespace cc { class CompositorFrame; +class CopyOutputResult; class Layer; class SolidColorLayer; class TextureLayer; +class DelegatedFrameProvider; +class DelegatedFrameResourceCollection; class DelegatedRendererLayer; } -namespace WebKit { +namespace blink { class WebPluginContainer; class WebLayer; } +namespace gfx { +class Rect; +class Size; +} + namespace content { class BrowserPluginManager; class CONTENT_EXPORT BrowserPluginCompositingHelper : - public base::RefCounted<BrowserPluginCompositingHelper> { + public base::RefCounted<BrowserPluginCompositingHelper>, + public cc::DelegatedFrameResourceCollectionClient { public: - BrowserPluginCompositingHelper(WebKit::WebPluginContainer* container, + BrowserPluginCompositingHelper(blink::WebPluginContainer* container, BrowserPluginManager* manager, int instance_id, int host_routing_id); + void CopyFromCompositingSurface(int request_id, + gfx::Rect source_rect, + gfx::Size dest_size); void DidCommitCompositorFrame(); void EnableCompositing(bool); void OnContainerDestroy(); @@ -54,6 +68,11 @@ class CONTENT_EXPORT BrowserPluginCompositingHelper : uint32 output_surface_id, int host_id); void UpdateVisibility(bool); + + // cc::DelegatedFrameProviderClient implementation. + virtual void UnusedResourcesAreAvailable() OVERRIDE; + void SetContentsOpaque(bool); + protected: // Friend RefCounted so that the dtor can be non-public. friend class base::RefCounted<BrowserPluginCompositingHelper>; @@ -75,16 +94,22 @@ class CONTENT_EXPORT BrowserPluginCompositingHelper : unsigned software_frame_id; base::SharedMemory* shared_memory; }; - ~BrowserPluginCompositingHelper(); - void CheckSizeAndAdjustLayerBounds(const gfx::Size& new_size, - float device_scale_factor, - cc::Layer* layer); + virtual ~BrowserPluginCompositingHelper(); + void CheckSizeAndAdjustLayerProperties(const gfx::Size& new_size, + float device_scale_factor, + cc::Layer* layer); void OnBuffersSwappedPrivate(const SwapBuffersInfo& mailbox, unsigned sync_point, float device_scale_factor); void MailboxReleased(SwapBuffersInfo mailbox, unsigned sync_point, bool lost_resource); + void SendReturnedDelegatedResources(); + void CopyFromCompositingSurfaceHasResult( + int request_id, + gfx::Size dest_size, + scoped_ptr<cc::CopyOutputResult> result); + int instance_id_; int host_routing_id_; int last_route_id_; @@ -92,14 +117,20 @@ class CONTENT_EXPORT BrowserPluginCompositingHelper : int last_host_id_; bool last_mailbox_valid_; bool ack_pending_; + bool software_ack_pending_; + bool opaque_; + std::vector<unsigned> unacked_software_frames_; gfx::Size buffer_size_; + scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection_; + scoped_refptr<cc::DelegatedFrameProvider> frame_provider_; + scoped_refptr<cc::SolidColorLayer> background_layer_; scoped_refptr<cc::TextureLayer> texture_layer_; scoped_refptr<cc::DelegatedRendererLayer> delegated_layer_; - scoped_ptr<WebKit::WebLayer> web_layer_; - WebKit::WebPluginContainer* container_; + scoped_ptr<blink::WebLayer> web_layer_; + blink::WebPluginContainer* container_; scoped_refptr<BrowserPluginManager> browser_plugin_manager_; }; diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_manager.h b/chromium/content/renderer/browser_plugin/browser_plugin_manager.h index 7e08a1ef4a9..8a57c3d5407 100644 --- a/chromium/content/renderer/browser_plugin/browser_plugin_manager.h +++ b/chromium/content/renderer/browser_plugin/browser_plugin_manager.h @@ -12,7 +12,7 @@ #include "content/public/renderer/render_view_observer.h" #include "ipc/ipc_sender.h" -namespace WebKit { +namespace blink { class WebFrame; struct WebPluginParams; } @@ -45,9 +45,7 @@ class CONTENT_EXPORT BrowserPluginManager // BrowserPluginManager via AddBrowserPlugin. When it is destroyed, it is // responsible for removing its association via RemoveBrowserPlugin. virtual BrowserPlugin* CreateBrowserPlugin( - RenderViewImpl* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params) = 0; + RenderViewImpl* render_view, blink::WebFrame* frame) = 0; // Asynchronously requests a new browser-process-allocated instance ID. // After the browser process allocates an ID, it calls back into the diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.cc b/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.cc index e7732f8afe9..542af453d35 100644 --- a/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.cc +++ b/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.cc @@ -24,9 +24,8 @@ BrowserPluginManagerImpl::~BrowserPluginManagerImpl() { BrowserPlugin* BrowserPluginManagerImpl::CreateBrowserPlugin( RenderViewImpl* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params) { - return new BrowserPlugin(render_view, frame, params); + blink::WebFrame* frame) { + return new BrowserPlugin(render_view, frame); } void BrowserPluginManagerImpl::AllocateInstanceID( diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.h b/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.h index 30ee72cfc98..a046995af63 100644 --- a/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.h +++ b/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.h @@ -23,8 +23,7 @@ class BrowserPluginManagerImpl : public BrowserPluginManager { // BrowserPluginManager implementation. virtual BrowserPlugin* CreateBrowserPlugin( RenderViewImpl* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params) OVERRIDE; + blink::WebFrame* frame) OVERRIDE; virtual void AllocateInstanceID( const base::WeakPtr<BrowserPlugin>& browser_plugin) OVERRIDE; diff --git a/chromium/content/renderer/browser_plugin/mock_browser_plugin.cc b/chromium/content/renderer/browser_plugin/mock_browser_plugin.cc index 39b2d2dc047..a19d0aa516e 100644 --- a/chromium/content/renderer/browser_plugin/mock_browser_plugin.cc +++ b/chromium/content/renderer/browser_plugin/mock_browser_plugin.cc @@ -8,9 +8,8 @@ namespace content { MockBrowserPlugin::MockBrowserPlugin(RenderViewImpl* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params) - : BrowserPlugin(render_view, frame, params) { + blink::WebFrame* frame) + : BrowserPlugin(render_view, frame) { } MockBrowserPlugin::~MockBrowserPlugin() {} diff --git a/chromium/content/renderer/browser_plugin/mock_browser_plugin.h b/chromium/content/renderer/browser_plugin/mock_browser_plugin.h index acd001b64ca..ee0f5542f9e 100644 --- a/chromium/content/renderer/browser_plugin/mock_browser_plugin.h +++ b/chromium/content/renderer/browser_plugin/mock_browser_plugin.h @@ -12,8 +12,7 @@ namespace content { class MockBrowserPlugin : public BrowserPlugin { public: MockBrowserPlugin(RenderViewImpl* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params); + blink::WebFrame* frame); virtual ~MockBrowserPlugin(); diff --git a/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.cc b/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.cc index 9007f6e00e1..4a606862ef1 100644 --- a/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.cc +++ b/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.cc @@ -21,10 +21,8 @@ MockBrowserPluginManager::~MockBrowserPluginManager() { } BrowserPlugin* MockBrowserPluginManager::CreateBrowserPlugin( - RenderViewImpl* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params) { - return new MockBrowserPlugin(render_view, frame, params); + RenderViewImpl* render_view, blink::WebFrame* frame) { + return new MockBrowserPlugin(render_view, frame); } void MockBrowserPluginManager::AllocateInstanceID( diff --git a/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.h b/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.h index 78ae0bef9b2..83d55a5d352 100644 --- a/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.h +++ b/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.h @@ -19,9 +19,7 @@ class MockBrowserPluginManager : public BrowserPluginManager { // BrowserPluginManager implementation. virtual BrowserPlugin* CreateBrowserPlugin( - RenderViewImpl* render_view, - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params) OVERRIDE; + RenderViewImpl* render_view, blink::WebFrame* frame) OVERRIDE; virtual void AllocateInstanceID( const base::WeakPtr<BrowserPlugin>& browser_plugin) OVERRIDE; diff --git a/chromium/content/renderer/clipboard_client.h b/chromium/content/renderer/clipboard_client.h index 1e00af61449..14a00076092 100644 --- a/chromium/content/renderer/clipboard_client.h +++ b/chromium/content/renderer/clipboard_client.h @@ -33,41 +33,43 @@ class ClipboardClient { virtual ui::Clipboard* GetClipboard() = 0; // Get a sequence number which uniquely identifies clipboard state. - virtual uint64 GetSequenceNumber(ui::Clipboard::Buffer buffer) = 0; + virtual uint64 GetSequenceNumber(ui::ClipboardType type) = 0; // Tests whether the clipboard contains a certain format virtual bool IsFormatAvailable(const ui::Clipboard::FormatType& format, - ui::Clipboard::Buffer buffer) = 0; + ui::ClipboardType type) = 0; // Clear the contents of the clipboard. - virtual void Clear(ui::Clipboard::Buffer buffer) = 0; + virtual void Clear(ui::ClipboardType type) = 0; // Reads the available types from the clipboard, if available. - virtual void ReadAvailableTypes(ui::Clipboard::Buffer buffer, + virtual void ReadAvailableTypes(ui::ClipboardType type, std::vector<base::string16>* types, bool* contains_filenames) = 0; // Reads UNICODE text from the clipboard, if available. - virtual void ReadText(ui::Clipboard::Buffer buffer, + virtual void ReadText(ui::ClipboardType type, base::string16* result) = 0; // Reads ASCII text from the clipboard, if available. - virtual void ReadAsciiText(ui::Clipboard::Buffer buffer, + virtual void ReadAsciiText(ui::ClipboardType type, std::string* result) = 0; // Reads HTML from the clipboard, if available. - virtual void ReadHTML(ui::Clipboard::Buffer buffer, base::string16* markup, - GURL* url, uint32* fragment_start, + virtual void ReadHTML(ui::ClipboardType type, + base::string16* markup, + GURL* url, + uint32* fragment_start, uint32* fragment_end) = 0; // Reads RTF from the clipboard, if available. - virtual void ReadRTF(ui::Clipboard::Buffer buffer, std::string* result) = 0; + virtual void ReadRTF(ui::ClipboardType type, std::string* result) = 0; // Reads and image from the clipboard, if available. - virtual void ReadImage(ui::Clipboard::Buffer buffer, std::string* data) = 0; + virtual void ReadImage(ui::ClipboardType type, std::string* data) = 0; // Reads a custom data type from the clipboard, if available. - virtual void ReadCustomData(ui::Clipboard::Buffer buffer, + virtual void ReadCustomData(ui::ClipboardType clipboard_type, const base::string16& type, base::string16* data) = 0; diff --git a/chromium/content/renderer/clipboard_utils.cc b/chromium/content/renderer/clipboard_utils.cc new file mode 100644 index 00000000000..28c04c99a7e --- /dev/null +++ b/chromium/content/renderer/clipboard_utils.cc @@ -0,0 +1,39 @@ +// 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/renderer/clipboard_utils.h" + +#include "base/strings/utf_string_conversions.h" +#include "net/base/escape.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/platform/WebURL.h" + +namespace content { + +std::string URLToMarkup(const blink::WebURL& url, + const blink::WebString& title) { + std::string markup("<a href=\""); + markup.append(url.spec()); + markup.append("\">"); + // TODO(darin): HTML escape this + markup.append(net::EscapeForHTML(UTF16ToUTF8(title))); + markup.append("</a>"); + return markup; +} + +std::string URLToImageMarkup(const blink::WebURL& url, + const blink::WebString& title) { + std::string markup("<img src=\""); + markup.append(net::EscapeForHTML(url.spec())); + markup.append("\""); + if (!title.isEmpty()) { + markup.append(" alt=\""); + markup.append(net::EscapeForHTML(UTF16ToUTF8(title))); + markup.append("\""); + } + markup.append("/>"); + return markup; +} + +} // namespace content diff --git a/chromium/content/renderer/clipboard_utils.h b/chromium/content/renderer/clipboard_utils.h new file mode 100644 index 00000000000..3acf7b43ebb --- /dev/null +++ b/chromium/content/renderer/clipboard_utils.h @@ -0,0 +1,27 @@ +// 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_RENDERER_CLIPBOARD_UTILS_H_ +#define CONTENT_RENDERER_CLIPBOARD_UTILS_H_ + +#include <string> + +#include "content/common/content_export.h" + +namespace blink { +class WebString; +class WebURL; +} + +namespace content { + +CONTENT_EXPORT std::string URLToMarkup(const blink::WebURL& url, + const blink::WebString& title); + +CONTENT_EXPORT std::string URLToImageMarkup(const blink::WebURL& url, + const blink::WebString& title); + +} // namespace content + +#endif // CONTENT_RENDERER_CLIPBOARD_UTILS_H_ diff --git a/chromium/content/renderer/context_menu_params_builder.cc b/chromium/content/renderer/context_menu_params_builder.cc index e8cd0789cc1..2f22745475d 100644 --- a/chromium/content/renderer/context_menu_params_builder.cc +++ b/chromium/content/renderer/context_menu_params_builder.cc @@ -16,7 +16,7 @@ namespace content { // static ContextMenuParams ContextMenuParamsBuilder::Build( - const WebKit::WebContextMenuData& data) { + const blink::WebContextMenuData& data) { ContextMenuParams params; params.media_type = data.mediaType; params.x = data.mousePosition.x; @@ -35,11 +35,9 @@ ContextMenuParams ContextMenuParamsBuilder::Build( params.speech_input_enabled = data.isSpeechInputEnabled; params.spellcheck_enabled = data.isSpellCheckingEnabled; params.is_editable = data.isEditable; -#if defined(OS_MACOSX) params.writing_direction_default = data.writingDirectionDefault; params.writing_direction_left_to_right = data.writingDirectionLeftToRight; params.writing_direction_right_to_left = data.writingDirectionRightToLeft; -#endif // OS_MACOSX params.edit_flags = data.editFlags; params.frame_charset = data.frameEncoding.utf8(); params.referrer_policy = data.referrerPolicy; @@ -55,7 +53,7 @@ ContextMenuParams ContextMenuParamsBuilder::Build( params.frame_page_state = HistoryItemToPageState(data.frameHistoryItem); if (!params.link_url.is_empty()) { - WebKit::WebNode selectedNode = data.node; + blink::WebNode selectedNode = data.node; // If there are other embedded tags (like <a ..>Some <b>text</b></a>) // we need to extract the parent <a/> node. @@ -63,7 +61,7 @@ ContextMenuParams ContextMenuParamsBuilder::Build( selectedNode = selectedNode.parentNode(); } - WebKit::WebElement selectedElement = selectedNode.to<WebKit::WebElement>(); + blink::WebElement selectedElement = selectedNode.to<blink::WebElement>(); if (selectedNode.isLink() && !selectedElement.isNull()) { params.link_text = selectedElement.innerText(); } else { @@ -76,10 +74,10 @@ ContextMenuParams ContextMenuParamsBuilder::Build( // Deserialize the SSL info. if (!data.securityInfo.isEmpty()) { DeserializeSecurityInfo(data.securityInfo, - ¶ms.security_info.cert_id, - ¶ms.security_info.cert_status, - ¶ms.security_info.security_bits, - ¶ms.security_info.connection_status); + ¶ms.security_info.cert_id, ¶ms.security_info.cert_status, + ¶ms.security_info.security_bits, + ¶ms.security_info.connection_status, + ¶ms.security_info.signed_certificate_timestamp_ids); } return params; diff --git a/chromium/content/renderer/context_menu_params_builder.h b/chromium/content/renderer/context_menu_params_builder.h index 414d61bcd76..624f85505c8 100644 --- a/chromium/content/renderer/context_menu_params_builder.h +++ b/chromium/content/renderer/context_menu_params_builder.h @@ -5,7 +5,7 @@ #ifndef CONTENT_RENDERER_CONTEXT_MENU_PARAMS_BUILDER_H_ #define CONTENT_RENDERER_CONTEXT_MENU_PARAMS_BUILDER_H_ -namespace WebKit { +namespace blink { struct WebContextMenuData; } @@ -14,7 +14,7 @@ struct ContextMenuParams; class ContextMenuParamsBuilder { public: - static ContextMenuParams Build(const WebKit::WebContextMenuData& data); + static ContextMenuParams Build(const blink::WebContextMenuData& data); }; } // namespace content diff --git a/chromium/content/renderer/cpp_bound_class_unittest.cc b/chromium/content/renderer/cpp_bound_class_unittest.cc index 2c0f75f881c..8b05fea12bf 100644 --- a/chromium/content/renderer/cpp_bound_class_unittest.cc +++ b/chromium/content/renderer/cpp_bound_class_unittest.cc @@ -59,7 +59,7 @@ class TestObserver : public RenderViewObserver { public: explicit TestObserver(RenderView* render_view) : RenderViewObserver(render_view) {} - virtual void DidClearWindowObject(WebKit::WebFrame* frame) OVERRIDE { + virtual void DidClearWindowObject(blink::WebFrame* frame) OVERRIDE { example_bound_class_.BindToJavascript(frame, "example"); } void set_fallback_method_enabled(bool use_fallback) { @@ -80,7 +80,7 @@ class CppBoundClassTest : public RenderViewTest { observer_.reset(new TestObserver(view_)); observer_->set_fallback_method_enabled(useFallback()); - WebKit::WebURLRequest url_request; + blink::WebURLRequest url_request; url_request.initialize(); url_request.setURL(GURL(kAboutBlankURL)); @@ -104,7 +104,7 @@ class CppBoundClassTest : public RenderViewTest { void CheckTrue(const std::string& expression) { int was_page_a = -1; - string16 check_page_a = + base::string16 check_page_a = ASCIIToUTF16(std::string("Number(") + expression + ")"); EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a, &was_page_a)); EXPECT_EQ(1, was_page_a); diff --git a/chromium/content/renderer/cursor_utils.cc b/chromium/content/renderer/cursor_utils.cc index 80351c94a3b..27bda233bfd 100644 --- a/chromium/content/renderer/cursor_utils.cc +++ b/chromium/content/renderer/cursor_utils.cc @@ -5,10 +5,10 @@ #include "content/renderer/cursor_utils.h" #include "build/build_config.h" -#include "third_party/WebKit/public/web/WebCursorInfo.h" +#include "third_party/WebKit/public/platform/WebCursorInfo.h" #include "webkit/common/cursors/webcursor.h" -using WebKit::WebCursorInfo; +using blink::WebCursorInfo; namespace content { diff --git a/chromium/content/renderer/cursor_utils.h b/chromium/content/renderer/cursor_utils.h index 2e594afc0c5..e19f7586fa1 100644 --- a/chromium/content/renderer/cursor_utils.h +++ b/chromium/content/renderer/cursor_utils.h @@ -7,20 +7,20 @@ class WebCursor; -namespace WebKit { +namespace blink { struct WebCursorInfo; } namespace content { -// Adapts our cursor info to WebKit::WebCursorInfo. +// Adapts our cursor info to blink::WebCursorInfo. bool GetWebKitCursorInfo(const WebCursor& cursor, - WebKit::WebCursorInfo* webkit_cursor_info); + blink::WebCursorInfo* webkit_cursor_info); -// Adapts WebKit::CursorInfo to our cursor. +// Adapts blink::CursorInfo to our cursor. void InitializeCursorFromWebKitCursorInfo( WebCursor* cursor, - const WebKit::WebCursorInfo& webkit_cursor_info); + const blink::WebCursorInfo& webkit_cursor_info); } // namespace content diff --git a/chromium/content/renderer/date_time_formatter.cc b/chromium/content/renderer/date_time_formatter.cc deleted file mode 100644 index a0ce77b91cf..00000000000 --- a/chromium/content/renderer/date_time_formatter.cc +++ /dev/null @@ -1,300 +0,0 @@ -// Copyright (c) 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/renderer/date_time_formatter.h" - -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "third_party/WebKit/public/platform/WebCString.h" -#include "third_party/WebKit/public/web/WebDateTimeChooserParams.h" -#include "third_party/icu/source/i18n/unicode/smpdtfmt.h" - - -namespace content { - -void DateTimeFormatter::CreatePatternMap() { - // Initialize all the UI elements with empty patterns, - // then fill in the ones that are actually date/time inputs and - // are implemented. - for (int i = 0 ; i <= ui::TEXT_INPUT_TYPE_MAX; ++i) { - patterns_[i] = ""; - } - patterns_[ui::TEXT_INPUT_TYPE_DATE] = "yyyy-MM-dd"; - patterns_[ui::TEXT_INPUT_TYPE_DATE_TIME] = "yyyy-MM-dd'T'HH:mm'Z'"; - patterns_[ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL] = "yyyy-MM-dd'T'HH:mm"; - patterns_[ui::TEXT_INPUT_TYPE_MONTH] = "yyyy-MM"; - patterns_[ui::TEXT_INPUT_TYPE_TIME] = "HH:mm"; - patterns_[ui::TEXT_INPUT_TYPE_WEEK] = "Y-'W'ww"; -} - -// Returns true if icu_value parses as a valid for the specified date/time -// pattern. The date/time pattern given is for icu::SimpleDateFormat. -static bool TryPattern(const char* pattern, - const icu::UnicodeString& icu_value) { - icu::UnicodeString time_pattern = pattern; - UErrorCode success = U_ZERO_ERROR; - icu::SimpleDateFormat formatter(time_pattern, success); - formatter.parse(icu_value, success); - return success == U_ZERO_ERROR; -} - -// For a time value represented as a string find the longest time -// pattern which matches it. A valid time can have hours and minutes -// or hours, minutes and seconds or hour, minutes, seconds and upto 3 -// digits of fractional seconds. Specify step in milliseconds, it is 1000 -// times the value specified as "step" in the "<input type=time step=...> -// HTML fragment. A value of 60000 or more indicates that seconds -// are not expected and a value of 1000 or more indicates that fractional -// seconds are not expected. -static const char* FindLongestTimePatternWhichMatches(const std::string& value, - double step) { - const char* pattern = "HH:mm"; - if (step >= 60000) - return pattern; - - icu::UnicodeString icu_value = icu::UnicodeString::fromUTF8( - icu::StringPiece(value.data(), value.size())); - const char* last_pattern = pattern; - pattern = "HH:mm:ss"; - if (!TryPattern(pattern, icu_value)) - return last_pattern; - if (step >= 1000) - return pattern; - last_pattern = pattern; - pattern = "HH:mm:ss.S"; - if (!TryPattern(pattern, icu_value)) - return last_pattern; - last_pattern = pattern; - pattern = "HH:mm:ss.SS"; - if (!TryPattern(pattern, icu_value)) - return last_pattern; - last_pattern = pattern; - pattern = "HH:mm:ss.SSS"; - if (!TryPattern(pattern, icu_value)) - return last_pattern; - return pattern; -} - -DateTimeFormatter::DateTimeFormatter( - const WebKit::WebDateTimeChooserParams& source) - : formatted_string_(source.currentValue.utf8()) { - CreatePatternMap(); - if (source.type == WebKit::WebDateTimeInputTypeTime) - time_pattern_ = - FindLongestTimePatternWhichMatches(formatted_string_, source.step); - ExtractType(source); - if (!ParseValues()) { - type_ = ui::TEXT_INPUT_TYPE_NONE; - ClearAll(); - LOG(WARNING) << "Problems parsing input <" << formatted_string_ << ">"; - } -} - -DateTimeFormatter::DateTimeFormatter(ui::TextInputType type, - int year, - int month, - int day, - int hour, - int minute, - int second, - int milli, - int week_year, - int week) - : type_(type), - year_(year), - month_(month), - day_(day), - hour_(hour), - minute_(minute), - second_(second), - milli_(milli), - week_year_(week_year), - week_(week) { - CreatePatternMap(); - if (type_ == ui::TEXT_INPUT_TYPE_TIME && (second != 0 || milli != 0)) { - if (milli == 0) - time_pattern_ = "HH:mm:ss"; - else if (milli % 100 == 0) - time_pattern_ = "HH:mm:ss.S"; - else if (milli % 10 == 0) - time_pattern_ = "HH:mm:ss.SS"; - else - time_pattern_ = "HH:mm:ss.SSS"; - pattern_ = &time_pattern_; - } else { - pattern_ = type_ > 0 && type_ <= ui::TEXT_INPUT_TYPE_MAX ? - &patterns_[type_] : &patterns_[ui::TEXT_INPUT_TYPE_NONE]; - } - - formatted_string_ = FormatString(); -} - -DateTimeFormatter::~DateTimeFormatter() { -} - -int DateTimeFormatter::GetYear() const { - return year_; -} - -int DateTimeFormatter::GetMonth() const { - return month_; -} - -int DateTimeFormatter::GetDay() const { - return day_; -} - -int DateTimeFormatter::GetHour() const { - return hour_; -} - -int DateTimeFormatter::GetMinute() const { - return minute_; -} - -int DateTimeFormatter::GetSecond() const { - return second_; -} - -int DateTimeFormatter::GetMilli() const { return milli_; } - -int DateTimeFormatter::GetWeekYear() const { return week_year_; } - -int DateTimeFormatter::GetWeek() const { - return week_; -} - -ui::TextInputType DateTimeFormatter::GetType() const { - return type_; -} - -const std::string& DateTimeFormatter::GetFormattedValue() const { - return formatted_string_; -} - -const std::string DateTimeFormatter::FormatString() const { - UErrorCode success = U_ZERO_ERROR; - if (year_ == 0 && month_ == 0 && day_ == 0 && hour_ == 0 && minute_ == 0 && - second_ == 0 && milli_ == 0 && week_year_ == 0 && week_ == 0) { - return std::string(); - } - - std::string result; - icu::GregorianCalendar calendar(success); - if (success <= U_ZERO_ERROR) { - if (type_ == ui::TEXT_INPUT_TYPE_WEEK) { - // An ISO week starts with Monday. - calendar.setFirstDayOfWeek(UCAL_MONDAY); - // ISO 8601 defines that the week with the year's first Thursday is the - // first week. - calendar.setMinimalDaysInFirstWeek(4); - calendar.set(UCAL_YEAR_WOY, week_year_); - calendar.set(UCAL_WEEK_OF_YEAR, week_); - } else { - calendar.set(UCAL_YEAR, year_); - calendar.set(UCAL_MONTH, month_); - calendar.set(UCAL_DATE, day_); - calendar.set(UCAL_HOUR_OF_DAY, hour_); - calendar.set(UCAL_MINUTE, minute_); - calendar.set(UCAL_SECOND, second_); - calendar.set(UCAL_MILLISECOND, milli_); - } - icu::SimpleDateFormat formatter(*pattern_, success); - icu::UnicodeString formatted_time; - formatter.format(calendar, formatted_time, NULL, success); - UTF16ToUTF8(formatted_time.getBuffer(), - static_cast<size_t>(formatted_time.length()), - &result); - if (success <= U_ZERO_ERROR) - return result; - } - LOG(WARNING) << "Calendar not created: error " << success; - return std::string(); -} - -void DateTimeFormatter::ExtractType( - const WebKit::WebDateTimeChooserParams& source) { - switch (source.type) { - case WebKit::WebDateTimeInputTypeDate: - type_ = ui::TEXT_INPUT_TYPE_DATE; - break; - case WebKit::WebDateTimeInputTypeDateTime: - type_ = ui::TEXT_INPUT_TYPE_DATE_TIME; - break; - case WebKit::WebDateTimeInputTypeDateTimeLocal: - type_ = ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL; - break; - case WebKit::WebDateTimeInputTypeMonth: - type_ = ui::TEXT_INPUT_TYPE_MONTH; - break; - case WebKit::WebDateTimeInputTypeTime: - type_ = ui::TEXT_INPUT_TYPE_TIME; - break; - case WebKit::WebDateTimeInputTypeWeek: - type_ = ui::TEXT_INPUT_TYPE_WEEK; - break; - case WebKit::WebDateTimeInputTypeNone: - default: - type_ = ui::TEXT_INPUT_TYPE_NONE; - } -} - -// Not all fields are defined in all configurations and ICU might store -// garbage if success <= U_ZERO_ERROR so the output is sanitized here. -int DateTimeFormatter::ExtractValue( - const icu::Calendar* calendar, UCalendarDateFields value) const { - UErrorCode success = U_ZERO_ERROR; - int result = calendar->get(value, success); - return (success <= U_ZERO_ERROR) ? result : 0; -} - -bool DateTimeFormatter::ParseValues() { - if (type_ == ui::TEXT_INPUT_TYPE_NONE) { - ClearAll(); - return false; - } - - if (formatted_string_.empty()) { - ClearAll(); - return true; - } - - UErrorCode success = U_ZERO_ERROR; - icu::UnicodeString icu_value = icu::UnicodeString::fromUTF8( - icu::StringPiece(formatted_string_.data(), formatted_string_.size())); - if (type_ > 0 && type_ <= ui::TEXT_INPUT_TYPE_MAX) { - const icu::UnicodeString pattern = - type_ == ui::TEXT_INPUT_TYPE_TIME ? time_pattern_ : patterns_[type_]; - icu::SimpleDateFormat formatter(pattern, success); - formatter.parse(icu_value, success); - if (success <= U_ZERO_ERROR) { - const icu::Calendar* cal = formatter.getCalendar(); - year_ = ExtractValue(cal, UCAL_YEAR); - month_ = ExtractValue(cal, UCAL_MONTH); - day_ = ExtractValue(cal, UCAL_DATE); - hour_ = ExtractValue(cal, UCAL_HOUR_OF_DAY); // 24h format - minute_ = ExtractValue(cal, UCAL_MINUTE); - second_ = ExtractValue(cal, UCAL_SECOND); - milli_ = ExtractValue(cal, UCAL_MILLISECOND); - week_year_ = ExtractValue(cal, UCAL_YEAR_WOY); - week_ = ExtractValue(cal, UCAL_WEEK_OF_YEAR); - } - } - - return (success <= U_ZERO_ERROR); -} - -void DateTimeFormatter::ClearAll() { - year_ = 0; - month_ = 0; - day_ = 0; - hour_ = 0; - minute_ = 0; - second_ = 0; - milli_ = 0; - week_year_ = 0; - week_ = 0; -} - -} // namespace content diff --git a/chromium/content/renderer/date_time_formatter.h b/chromium/content/renderer/date_time_formatter.h deleted file mode 100644 index b2b73410216..00000000000 --- a/chromium/content/renderer/date_time_formatter.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 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_RENDERER_DATE_TIME_FORMATTER_H_ -#define CONTENT_RENDERER_DATE_TIME_FORMATTER_H_ - -#include <string> - -#include "base/basictypes.h" -#include "content/common/content_export.h" -#include "third_party/icu/source/common/unicode/unistr.h" -#include "third_party/icu/source/i18n/unicode/gregocal.h" -#include "ui/base/ime/text_input_type.h" - -namespace WebKit { -struct WebDateTimeChooserParams; -} // namespace WebKit - -namespace content { - -// Converts between a text string representing a date/time and -// a set of year/month/day/hour/minute/second/milli and vice versa. -// It is timezone agnostic. -class CONTENT_EXPORT DateTimeFormatter { - public: - explicit DateTimeFormatter(const WebKit::WebDateTimeChooserParams& source); - DateTimeFormatter(ui::TextInputType type, - int year, - int month, - int day, - int hour, - int minute, - int second, - int milli, - int week_year, - int week); - ~DateTimeFormatter(); - - int GetYear() const; - int GetMonth() const; - int GetDay() const; - int GetHour() const; - int GetMinute() const; - int GetSecond() const; - int GetMilli() const; - int GetWeekYear() const; - int GetWeek() const; - ui::TextInputType GetType() const; - const std::string& GetFormattedValue() const; - - private: - void CreatePatternMap(); - bool ParseValues(); - const std::string FormatString() const; - int ExtractValue( - const icu::Calendar* calendar, UCalendarDateFields value) const; - void ExtractType(const WebKit::WebDateTimeChooserParams& source); - void ClearAll(); - - ui::TextInputType type_; - icu::UnicodeString patterns_[ui::TEXT_INPUT_TYPE_MAX + 1]; - icu::UnicodeString time_pattern_; - int year_; - int month_; - int day_; - int hour_; - int minute_; - int second_; - int milli_; - int week_year_; - int week_; - const icu::UnicodeString* pattern_; - std::string formatted_string_; - - DISALLOW_COPY_AND_ASSIGN(DateTimeFormatter); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_DATE_TIME_FORMATTER_H_ diff --git a/chromium/content/renderer/date_time_formatter_unittest.cc b/chromium/content/renderer/date_time_formatter_unittest.cc deleted file mode 100644 index 0d8b07f2420..00000000000 --- a/chromium/content/renderer/date_time_formatter_unittest.cc +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (c) 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 <map> - -#include "content/renderer/date_time_formatter.h" -#include "content/renderer/renderer_date_time_picker.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/WebKit/public/web/WebDateTimeChooserParams.h" -#include "third_party/icu/source/common/unicode/unistr.h" -#include "ui/base/ime/text_input_type.h" - -namespace content { - -class RendererDateTimePickerTest { -}; - -TEST(RendererDateTimePickerTest, TestParserValidStringInputs) { - WebKit::WebDateTimeChooserParams params; - params.currentValue = "2010-07"; - params.type = WebKit::WebDateTimeInputTypeMonth; - DateTimeFormatter sut(params); - EXPECT_EQ(2010, sut.GetYear()); - - // Month field is 0 based - EXPECT_EQ(6, sut.GetMonth()); - - // Month input defaults to the first day of the month (1 based) - EXPECT_EQ(1, sut.GetDay()); - EXPECT_EQ(0, sut.GetHour()); - EXPECT_EQ(0, sut.GetMinute()); - EXPECT_EQ(0, sut.GetSecond()); - EXPECT_EQ(2010, sut.GetWeekYear()); - EXPECT_EQ(26, sut.GetWeek()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_MONTH, sut.GetType()); - - params.currentValue = "2012-05-25"; - params.type = WebKit::WebDateTimeInputTypeDate; - DateTimeFormatter sut2(params); - EXPECT_EQ(2012, sut2.GetYear()); - EXPECT_EQ(4, sut2.GetMonth()); - EXPECT_EQ(25, sut2.GetDay()); - EXPECT_EQ(0, sut2.GetHour()); - EXPECT_EQ(0, sut2.GetMinute()); - EXPECT_EQ(0, sut2.GetSecond()); - EXPECT_EQ(2012, sut2.GetWeekYear()); - EXPECT_EQ(21, sut2.GetWeek()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_DATE, sut2.GetType()); - - params.currentValue = "2013-05-21T12:15"; - params.type = WebKit::WebDateTimeInputTypeDateTimeLocal; - DateTimeFormatter sut3(params); - EXPECT_EQ(2013, sut3.GetYear()); - EXPECT_EQ(4, sut3.GetMonth()); - EXPECT_EQ(21, sut3.GetDay()); - EXPECT_EQ(12, sut3.GetHour()); - EXPECT_EQ(15, sut3.GetMinute()); - EXPECT_EQ(0, sut3.GetSecond()); - EXPECT_EQ(2013, sut3.GetWeekYear()); - EXPECT_EQ(21, sut3.GetWeek()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL, sut3.GetType()); - - params.currentValue = "2013-W15"; - params.type = WebKit::WebDateTimeInputTypeWeek; - DateTimeFormatter sut4(params); - EXPECT_EQ(2013, sut4.GetYear()); - EXPECT_EQ(3, sut4.GetMonth()); - EXPECT_EQ(7, sut4.GetDay()); - EXPECT_EQ(0, sut4.GetHour()); - EXPECT_EQ(0, sut4.GetMinute()); - EXPECT_EQ(0, sut4.GetSecond()); - EXPECT_EQ(2013, sut4.GetWeekYear()); - EXPECT_EQ(15, sut4.GetWeek()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_WEEK, sut4.GetType()); - - params.currentValue = "12:15"; - params.type = WebKit::WebDateTimeInputTypeTime; - DateTimeFormatter sut5(params); - EXPECT_EQ(12, sut5.GetHour()); - EXPECT_EQ(15, sut5.GetMinute()); - EXPECT_EQ(0, sut5.GetSecond()); - EXPECT_EQ(0, sut5.GetMilli()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_TIME, sut5.GetType()); - - params.currentValue = "12:15:02"; - params.type = WebKit::WebDateTimeInputTypeTime; - DateTimeFormatter sut6(params); - EXPECT_EQ(12, sut6.GetHour()); - EXPECT_EQ(15, sut6.GetMinute()); - EXPECT_EQ(02, sut6.GetSecond()); - EXPECT_EQ(0, sut6.GetMilli()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_TIME, sut6.GetType()); - - params.currentValue = "12:15:02.1"; - params.type = WebKit::WebDateTimeInputTypeTime; - DateTimeFormatter sut7(params); - EXPECT_EQ(12, sut7.GetHour()); - EXPECT_EQ(15, sut7.GetMinute()); - EXPECT_EQ(02, sut7.GetSecond()); - EXPECT_EQ(100, sut7.GetMilli()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_TIME, sut7.GetType()); - - params.currentValue = "12:15:02.123"; - params.type = WebKit::WebDateTimeInputTypeTime; - DateTimeFormatter sut8(params); - EXPECT_EQ(12, sut8.GetHour()); - EXPECT_EQ(15, sut8.GetMinute()); - EXPECT_EQ(02, sut8.GetSecond()); - EXPECT_EQ(123, sut8.GetMilli()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_TIME, sut8.GetType()); -} - - -TEST(RendererDateTimePickerTest, TestParserInvalidStringInputs) { - - // Random non parsable text - WebKit::WebDateTimeChooserParams params; - params.currentValue = "<script injection"; - params.type = WebKit::WebDateTimeInputTypeMonth; - DateTimeFormatter sut(params); - EXPECT_EQ(0, sut.GetYear()); - EXPECT_EQ(0, sut.GetMonth()); - EXPECT_EQ(0, sut.GetDay()); - EXPECT_EQ(0, sut.GetHour()); - EXPECT_EQ(0, sut.GetMinute()); - EXPECT_EQ(0, sut.GetSecond()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, sut.GetType()); - - // unimplemented type - params.currentValue = "week 23"; - params.type = WebKit::WebDateTimeInputTypeWeek; // Not implemented - DateTimeFormatter sut2(params); - EXPECT_EQ(0, sut2.GetYear()); - EXPECT_EQ(0, sut2.GetMonth()); - EXPECT_EQ(0, sut2.GetDay()); - EXPECT_EQ(0, sut2.GetHour()); - EXPECT_EQ(0, sut2.GetMinute()); - EXPECT_EQ(0, sut2.GetSecond()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, sut2.GetType()); - - // type is a subset of pattern - params.currentValue = "2012-05-25"; - params.type = WebKit::WebDateTimeInputTypeDateTimeLocal; - DateTimeFormatter sut3(params); - EXPECT_EQ(0, sut3.GetYear()); - EXPECT_EQ(0, sut3.GetMonth()); - EXPECT_EQ(0, sut3.GetDay()); - EXPECT_EQ(0, sut3.GetHour()); - EXPECT_EQ(0, sut3.GetMinute()); - EXPECT_EQ(0, sut3.GetSecond()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, sut3.GetType()); - - // type is a superset of pattern - params.currentValue = "2013-05-21T12:15"; - params.type = WebKit::WebDateTimeInputTypeMonth; - DateTimeFormatter sut4(params); - EXPECT_EQ(2013, sut4.GetYear()); - EXPECT_EQ(4, sut4.GetMonth()); - EXPECT_EQ(1, sut4.GetDay()); - EXPECT_EQ(0, sut4.GetHour()); - EXPECT_EQ(0, sut4.GetMinute()); - EXPECT_EQ(0, sut4.GetSecond()); - EXPECT_EQ(ui::TEXT_INPUT_TYPE_MONTH, sut4.GetType()); -} - - -TEST(RendererDateTimePickerTest, TestParserValidDateInputs) { - DateTimeFormatter sut( - ui::TEXT_INPUT_TYPE_MONTH, 2012, 11, 1, 0, 0, 0, 0, 0, 0); - EXPECT_EQ("2012-12", sut.GetFormattedValue()); - - DateTimeFormatter sut2( - ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL, 2013, 3, 23, 15, 47, 0, 0, 0, 0); - EXPECT_EQ("2013-04-23T15:47", sut2.GetFormattedValue()); - - DateTimeFormatter sut3( - ui::TEXT_INPUT_TYPE_WEEK, 0, 0, 0, 0, 0, 0, 0, 2012, 2); - EXPECT_EQ("2012-W02", sut3.GetFormattedValue()); -} - -TEST(RendererDateTimePickerTest, TestParserValidTimeInputs) { - DateTimeFormatter sut( - ui::TEXT_INPUT_TYPE_TIME, 0, 0, 0, 12, 15, 0, 0, 0, 0); - EXPECT_EQ("12:15", sut.GetFormattedValue()); - - DateTimeFormatter sut2( - ui::TEXT_INPUT_TYPE_TIME, 0, 0, 0, 12, 15, 02, 0, 0, 0); - EXPECT_EQ("12:15:02", sut2.GetFormattedValue()); - - DateTimeFormatter sut3( - ui::TEXT_INPUT_TYPE_TIME, 0, 0, 0, 12, 15, 02, 123, 0, 0); - EXPECT_EQ("12:15:02.123", sut3.GetFormattedValue()); -} - -TEST(RendererDateTimePickerTest, TestParserInvalidDateInputs) { - DateTimeFormatter sut(ui::TEXT_INPUT_TYPE_WEEK, 0, 0, 0, 0, 0, 0, 0, 0, 0); - EXPECT_EQ("", sut.GetFormattedValue()); - - DateTimeFormatter sut2( - ui::TEXT_INPUT_TYPE_NONE, 2013, 3, 23, 0, 0, 0, 0, 0, 0); - EXPECT_EQ("", sut2.GetFormattedValue()); - - DateTimeFormatter sut3( - ui::TEXT_INPUT_TYPE_NONE, 2013, 14, 32, 0, 0, 0, 0, 0, 0); - EXPECT_EQ("", sut3.GetFormattedValue()); - - DateTimeFormatter sut4(ui::TEXT_INPUT_TYPE_DATE, 0, 0, 0, 0, 0, 0, 0, 0, 0); - EXPECT_EQ("", sut4.GetFormattedValue()); - - DateTimeFormatter sut5(ui::TEXT_INPUT_TYPE_TIME, 0, 0, 0, 0, 0, 0, 0, 0, 0); - EXPECT_EQ("", sut5.GetFormattedValue()); - - DateTimeFormatter sut6( - ui::TEXT_INPUT_TYPE_PASSWORD, 23, 0, 0, 0, 5, 0, 0, 0, 0); - EXPECT_EQ("", sut6.GetFormattedValue()); - - DateTimeFormatter sut7(ui::TEXT_INPUT_TYPE_MAX, 23, 0, 0, 0, 5, 0, 0, 0, 0); - EXPECT_EQ("", sut7.GetFormattedValue()); - - DateTimeFormatter sut8( - static_cast<ui::TextInputType>(10000), 23, 0, 0, 0, 5, 0, 0, 0, 0); - EXPECT_EQ("", sut8.GetFormattedValue()); -} -} // namespace content diff --git a/chromium/content/renderer/date_time_suggestion_builder.cc b/chromium/content/renderer/date_time_suggestion_builder.cc new file mode 100644 index 00000000000..7dff00d7824 --- /dev/null +++ b/chromium/content/renderer/date_time_suggestion_builder.cc @@ -0,0 +1,22 @@ +// 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/renderer/date_time_suggestion_builder.h" + +#include "content/common/date_time_suggestion.h" +#include "third_party/WebKit/public/web/WebDateTimeSuggestion.h" + +namespace content { + +// static +DateTimeSuggestion DateTimeSuggestionBuilder::Build( + const blink::WebDateTimeSuggestion& suggestion) { + DateTimeSuggestion result; + result.value = suggestion.value; + result.localized_value = suggestion.localizedValue; + result.label = suggestion.label; + return result; +} + +} // namespace content diff --git a/chromium/content/renderer/date_time_suggestion_builder.h b/chromium/content/renderer/date_time_suggestion_builder.h new file mode 100644 index 00000000000..5087051fb04 --- /dev/null +++ b/chromium/content/renderer/date_time_suggestion_builder.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. + +#ifndef CONTENT_RENDERER_DATE_TIME_SUGGESTION_BUILDER_H_ +#define CONTENT_RENDERER_DATE_TIME_SUGGESTION_BUILDER_H_ + +namespace blink { +struct WebDateTimeSuggestion; +} // namespace blink + +namespace content { +struct DateTimeSuggestion; + +class DateTimeSuggestionBuilder { + public: + static DateTimeSuggestion Build( + const blink::WebDateTimeSuggestion& suggestion); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_DATE_TIME_SUGGESTION_BUILDER_H_ diff --git a/chromium/content/renderer/device_orientation/device_motion_event_pump.cc b/chromium/content/renderer/device_orientation/device_motion_event_pump.cc index e7ad8cacb7b..c60bd7a1265 100644 --- a/chromium/content/renderer/device_orientation/device_motion_event_pump.cc +++ b/chromium/content/renderer/device_orientation/device_motion_event_pump.cc @@ -22,7 +22,7 @@ DeviceMotionEventPump::~DeviceMotionEventPump() { } bool DeviceMotionEventPump::SetListener( - WebKit::WebDeviceMotionListener* listener) { + blink::WebDeviceMotionListener* listener) { listener_ = listener; return listener_ ? RequestStart() : Stop(); } @@ -39,7 +39,7 @@ bool DeviceMotionEventPump::OnControlMessageReceived( void DeviceMotionEventPump::FireEvent() { DCHECK(listener_); - WebKit::WebDeviceMotionData data; + blink::WebDeviceMotionData data; if (reader_->GetLatestData(&data) && data.allAvailableSensorsAreActive) listener_->didChangeDeviceMotion(data); } diff --git a/chromium/content/renderer/device_orientation/device_motion_event_pump.h b/chromium/content/renderer/device_orientation/device_motion_event_pump.h index 4fa453de819..f262ad42685 100644 --- a/chromium/content/renderer/device_orientation/device_motion_event_pump.h +++ b/chromium/content/renderer/device_orientation/device_motion_event_pump.h @@ -10,13 +10,13 @@ #include "content/renderer/shared_memory_seqlock_reader.h" #include "third_party/WebKit/public/platform/WebDeviceMotionData.h" -namespace WebKit { +namespace blink { class WebDeviceMotionListener; } namespace content { -typedef SharedMemorySeqLockReader<WebKit::WebDeviceMotionData> +typedef SharedMemorySeqLockReader<blink::WebDeviceMotionData> DeviceMotionSharedMemoryReader; class CONTENT_EXPORT DeviceMotionEventPump : public DeviceSensorEventPump { @@ -27,7 +27,7 @@ class CONTENT_EXPORT DeviceMotionEventPump : public DeviceSensorEventPump { // Sets the listener to receive updates for device motion data at // regular intervals. Returns true if the registration was successful. - bool SetListener(WebKit::WebDeviceMotionListener* listener); + bool SetListener(blink::WebDeviceMotionListener* listener); // RenderProcessObserver implementation. virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE; @@ -38,7 +38,7 @@ class CONTENT_EXPORT DeviceMotionEventPump : public DeviceSensorEventPump { virtual bool SendStartMessage() OVERRIDE; virtual bool SendStopMessage() OVERRIDE; - WebKit::WebDeviceMotionListener* listener_; + blink::WebDeviceMotionListener* listener_; scoped_ptr<DeviceMotionSharedMemoryReader> reader_; }; diff --git a/chromium/content/renderer/device_orientation/device_motion_event_pump_unittest.cc b/chromium/content/renderer/device_orientation/device_motion_event_pump_unittest.cc index 066294b0aeb..6cb78b61a90 100644 --- a/chromium/content/renderer/device_orientation/device_motion_event_pump_unittest.cc +++ b/chromium/content/renderer/device_orientation/device_motion_event_pump_unittest.cc @@ -7,7 +7,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" -#include "content/common/device_motion_hardware_buffer.h" +#include "content/common/device_orientation/device_motion_hardware_buffer.h" #include "content/public/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/WebDeviceMotionListener.h" @@ -17,14 +17,14 @@ namespace content { class DeviceMotionEventPumpTest : public testing::Test { }; -class MockDeviceMotionListener : public WebKit::WebDeviceMotionListener { +class MockDeviceMotionListener : public blink::WebDeviceMotionListener { public: MockDeviceMotionListener(); virtual ~MockDeviceMotionListener() { } virtual void didChangeDeviceMotion( - const WebKit::WebDeviceMotionData&) OVERRIDE; + const blink::WebDeviceMotionData&) OVERRIDE; bool did_change_device_motion_; - WebKit::WebDeviceMotionData data_; + blink::WebDeviceMotionData data_; }; MockDeviceMotionListener::MockDeviceMotionListener() @@ -33,7 +33,7 @@ MockDeviceMotionListener::MockDeviceMotionListener() } void MockDeviceMotionListener::didChangeDeviceMotion( - const WebKit::WebDeviceMotionData& data) { + const blink::WebDeviceMotionData& data) { memcpy(&data_, &data, sizeof(data)); did_change_device_motion_ = true; } @@ -71,7 +71,7 @@ TEST_F(DeviceMotionEventPumpTest, MAYBE_DidStartPolling) { memset(buffer, 0, sizeof(DeviceMotionHardwareBuffer)); shared_memory.ShareToProcess(base::kNullProcessHandle, &handle); - WebKit::WebDeviceMotionData& data = buffer->data; + blink::WebDeviceMotionData& data = buffer->data; data.accelerationX = 1; data.hasAccelerationX = true; data.accelerationY = 2; @@ -87,7 +87,7 @@ TEST_F(DeviceMotionEventPumpTest, MAYBE_DidStartPolling) { RunAllPendingInMessageLoop(); motion_pump->SetListener(0); - WebKit::WebDeviceMotionData& received_data = listener->data_; + blink::WebDeviceMotionData& received_data = listener->data_; EXPECT_TRUE(listener->did_change_device_motion_); EXPECT_TRUE(received_data.hasAccelerationX); EXPECT_EQ(1, (double)received_data.accelerationX); @@ -128,7 +128,7 @@ TEST_F(DeviceMotionEventPumpTest, MAYBE_DidStartPollingNotAllSensorsActive) { memset(buffer, 0, sizeof(DeviceMotionHardwareBuffer)); shared_memory.ShareToProcess(base::kNullProcessHandle, &handle); - WebKit::WebDeviceMotionData& data = buffer->data; + blink::WebDeviceMotionData& data = buffer->data; data.accelerationX = 1; data.hasAccelerationX = true; data.accelerationY = 2; @@ -144,7 +144,7 @@ TEST_F(DeviceMotionEventPumpTest, MAYBE_DidStartPollingNotAllSensorsActive) { RunAllPendingInMessageLoop(); motion_pump->SetListener(0); - WebKit::WebDeviceMotionData& received_data = listener->data_; + blink::WebDeviceMotionData& received_data = listener->data_; // No change in device motion because allAvailableSensorsAreActive is false. EXPECT_FALSE(listener->did_change_device_motion_); EXPECT_FALSE(received_data.hasAccelerationX); diff --git a/chromium/content/renderer/device_orientation/device_orientation_event_pump.cc b/chromium/content/renderer/device_orientation/device_orientation_event_pump.cc index ca45537dfc2..14930433439 100644 --- a/chromium/content/renderer/device_orientation/device_orientation_event_pump.cc +++ b/chromium/content/renderer/device_orientation/device_orientation_event_pump.cc @@ -26,7 +26,7 @@ DeviceOrientationEventPump::~DeviceOrientationEventPump() { } bool DeviceOrientationEventPump::SetListener( - WebKit::WebDeviceOrientationListener* listener) { + blink::WebDeviceOrientationListener* listener) { listener_ = listener; return listener_ ? RequestStart() : Stop(); } @@ -43,7 +43,7 @@ bool DeviceOrientationEventPump::OnControlMessageReceived( void DeviceOrientationEventPump::FireEvent() { DCHECK(listener_); - WebKit::WebDeviceOrientationData data; + blink::WebDeviceOrientationData data; if (reader_->GetLatestData(&data) && ShouldFireEvent(data)) { memcpy(&data_, &data, sizeof(data)); listener_->didChangeDeviceOrientation(data); @@ -59,7 +59,7 @@ static bool IsSignificantlyDifferent(bool hasAngle1, double angle1, } bool DeviceOrientationEventPump::ShouldFireEvent( - const WebKit::WebDeviceOrientationData& data) const { + const blink::WebDeviceOrientationData& data) const { return data.allAvailableSensorsAreActive && (IsSignificantlyDifferent( data_.hasAlpha, data_.alpha, data.hasAlpha, data.alpha) || diff --git a/chromium/content/renderer/device_orientation/device_orientation_event_pump.h b/chromium/content/renderer/device_orientation/device_orientation_event_pump.h index 26658ff5d4d..ac7f31cd3b0 100644 --- a/chromium/content/renderer/device_orientation/device_orientation_event_pump.h +++ b/chromium/content/renderer/device_orientation/device_orientation_event_pump.h @@ -10,13 +10,13 @@ #include "content/renderer/shared_memory_seqlock_reader.h" #include "third_party/WebKit/public/platform/WebDeviceOrientationData.h" -namespace WebKit { +namespace blink { class WebDeviceOrientationListener; } namespace content { -typedef SharedMemorySeqLockReader<WebKit::WebDeviceOrientationData> +typedef SharedMemorySeqLockReader<blink::WebDeviceOrientationData> DeviceOrientationSharedMemoryReader; class CONTENT_EXPORT DeviceOrientationEventPump : public DeviceSensorEventPump { @@ -31,7 +31,7 @@ class CONTENT_EXPORT DeviceOrientationEventPump : public DeviceSensorEventPump { // Sets the listener to receive updates for device orientation data at // regular intervals. Returns true if the registration was successful. - bool SetListener(WebKit::WebDeviceOrientationListener* listener); + bool SetListener(blink::WebDeviceOrientationListener* listener); // RenderProcessObserver implementation. virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE; @@ -42,10 +42,10 @@ class CONTENT_EXPORT DeviceOrientationEventPump : public DeviceSensorEventPump { virtual bool SendStartMessage() OVERRIDE; virtual bool SendStopMessage() OVERRIDE; - bool ShouldFireEvent(const WebKit::WebDeviceOrientationData& data) const; + bool ShouldFireEvent(const blink::WebDeviceOrientationData& data) const; - WebKit::WebDeviceOrientationListener* listener_; - WebKit::WebDeviceOrientationData data_; + blink::WebDeviceOrientationListener* listener_; + blink::WebDeviceOrientationData data_; scoped_ptr<DeviceOrientationSharedMemoryReader> reader_; }; diff --git a/chromium/content/renderer/device_orientation/device_orientation_event_pump_unittest.cc b/chromium/content/renderer/device_orientation/device_orientation_event_pump_unittest.cc index 2d137ad3a14..402cd077568 100644 --- a/chromium/content/renderer/device_orientation/device_orientation_event_pump_unittest.cc +++ b/chromium/content/renderer/device_orientation/device_orientation_event_pump_unittest.cc @@ -14,15 +14,15 @@ namespace content { class MockDeviceOrientationListener - : public WebKit::WebDeviceOrientationListener { + : public blink::WebDeviceOrientationListener { public: MockDeviceOrientationListener(); virtual ~MockDeviceOrientationListener() { } virtual void didChangeDeviceOrientation( - const WebKit::WebDeviceOrientationData&) OVERRIDE; + const blink::WebDeviceOrientationData&) OVERRIDE; void ResetDidChangeOrientation(); bool did_change_device_orientation_; - WebKit::WebDeviceOrientationData data_; + blink::WebDeviceOrientationData data_; }; MockDeviceOrientationListener::MockDeviceOrientationListener() @@ -31,7 +31,7 @@ MockDeviceOrientationListener::MockDeviceOrientationListener() } void MockDeviceOrientationListener::didChangeDeviceOrientation( - const WebKit::WebDeviceOrientationData& data) { + const blink::WebDeviceOrientationData& data) { memcpy(&data_, &data, sizeof(data)); did_change_device_orientation_ = true; } @@ -50,6 +50,11 @@ class DeviceOrientationEventPumpForTesting : public DeviceOrientationEventPump { } virtual bool SendStartMessage() OVERRIDE { return true; } virtual bool SendStopMessage() OVERRIDE { return true; } + virtual void FireEvent() OVERRIDE { + DeviceOrientationEventPump::FireEvent(); + Stop(); + base::MessageLoop::current()->QuitWhenIdle(); + } }; class DeviceOrientationEventPumpTest : public testing::Test { @@ -70,7 +75,7 @@ class DeviceOrientationEventPumpTest : public testing::Test { } void InitBuffer() { - WebKit::WebDeviceOrientationData& data = buffer_->data; + blink::WebDeviceOrientationData& data = buffer_->data; data.alpha = 1; data.hasAlpha = true; data.beta = 2; @@ -94,17 +99,15 @@ class DeviceOrientationEventPumpTest : public testing::Test { #define MAYBE_DidStartPolling DidStartPolling #endif TEST_F(DeviceOrientationEventPumpTest, MAYBE_DidStartPolling) { - base::MessageLoop loop(base::MessageLoop::TYPE_UI); - InitBuffer(); + base::MessageLoop loop; + InitBuffer(); orientation_pump_->SetListener(listener_.get()); orientation_pump_->OnDidStart(handle_); - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds( - orientation_pump_->GetDelayMillis() * 2)); - RunAllPendingInMessageLoop(); - orientation_pump_->SetListener(0); - WebKit::WebDeviceOrientationData& received_data = listener_->data_; + base::MessageLoop::current()->Run(); + + blink::WebDeviceOrientationData& received_data = listener_->data_; EXPECT_TRUE(listener_->did_change_device_orientation_); EXPECT_TRUE(received_data.allAvailableSensorsAreActive); EXPECT_EQ(1, (double)received_data.alpha); @@ -125,16 +128,15 @@ TEST_F(DeviceOrientationEventPumpTest, MAYBE_DidStartPolling) { #endif TEST_F(DeviceOrientationEventPumpTest, MAYBE_UpdateRespectsOrientationThreshold) { - base::MessageLoop loop(base::MessageLoop::TYPE_UI); - InitBuffer(); + base::MessageLoop loop; + InitBuffer(); orientation_pump_->SetListener(listener_.get()); orientation_pump_->OnDidStart(handle_); - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds( - orientation_pump_->GetDelayMillis() * 2)); - RunAllPendingInMessageLoop(); - WebKit::WebDeviceOrientationData& received_data = listener_->data_; + base::MessageLoop::current()->Run(); + + blink::WebDeviceOrientationData& received_data = listener_->data_; EXPECT_TRUE(listener_->did_change_device_orientation_); EXPECT_TRUE(received_data.allAvailableSensorsAreActive); EXPECT_EQ(1, (double)received_data.alpha); @@ -148,9 +150,10 @@ TEST_F(DeviceOrientationEventPumpTest, 1 + DeviceOrientationEventPump::kOrientationThreshold / 2.0; listener_->ResetDidChangeOrientation(); - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds( - orientation_pump_->GetDelayMillis() * 2)); - RunAllPendingInMessageLoop(); + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(&DeviceOrientationEventPumpForTesting::FireEvent, + base::Unretained(orientation_pump_.get()))); + base::MessageLoop::current()->Run(); EXPECT_FALSE(listener_->did_change_device_orientation_); EXPECT_TRUE(received_data.allAvailableSensorsAreActive); @@ -165,10 +168,10 @@ TEST_F(DeviceOrientationEventPumpTest, 1 + DeviceOrientationEventPump::kOrientationThreshold; listener_->ResetDidChangeOrientation(); - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds( - orientation_pump_->GetDelayMillis() * 2)); - RunAllPendingInMessageLoop(); - orientation_pump_->SetListener(0); + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(&DeviceOrientationEventPumpForTesting::FireEvent, + base::Unretained(orientation_pump_.get()))); + base::MessageLoop::current()->Run(); EXPECT_TRUE(listener_->did_change_device_orientation_); EXPECT_EQ(1 + DeviceOrientationEventPump::kOrientationThreshold, diff --git a/chromium/content/renderer/device_orientation/device_sensor_event_pump.cc b/chromium/content/renderer/device_orientation/device_sensor_event_pump.cc index e4c0eb0599d..8e82d8f5825 100644 --- a/chromium/content/renderer/device_orientation/device_sensor_event_pump.cc +++ b/chromium/content/renderer/device_orientation/device_sensor_event_pump.cc @@ -9,7 +9,10 @@ namespace content { -const int DeviceSensorEventPump::kDefaultPumpDelayMillis = 40; +// Default interval between successive polls, should take into account the +// value of |kInertialSensorIntervalMillis| in +// content/browser/device_orientation/inertial_sensor_consts.h. +const int DeviceSensorEventPump::kDefaultPumpDelayMillis = 50; int DeviceSensorEventPump::GetDelayMillis() const { return pump_delay_millis_; diff --git a/chromium/content/renderer/device_orientation_dispatcher.cc b/chromium/content/renderer/device_orientation_dispatcher.cc deleted file mode 100644 index 72d86882544..00000000000 --- a/chromium/content/renderer/device_orientation_dispatcher.cc +++ /dev/null @@ -1,94 +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/renderer/device_orientation_dispatcher.h" - -#include "content/common/device_orientation/device_orientation_messages.h" -#include "content/renderer/render_view_impl.h" -#include "third_party/WebKit/public/web/WebDeviceOrientation.h" -#include "third_party/WebKit/public/web/WebDeviceOrientationController.h" - -namespace content { - -DeviceOrientationDispatcher::DeviceOrientationDispatcher( - RenderViewImpl* render_view) - : RenderViewObserver(render_view), started_(false) {} - -DeviceOrientationDispatcher::~DeviceOrientationDispatcher() { - if (started_) - stopUpdating(); -} - -bool DeviceOrientationDispatcher::OnMessageReceived(const IPC::Message& msg) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(DeviceOrientationDispatcher, msg) - IPC_MESSAGE_HANDLER(DeviceOrientationMsg_Updated, - OnDeviceOrientationUpdated) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - -void DeviceOrientationDispatcher::setController( - WebKit::WebDeviceOrientationController* controller) { - controller_.reset(controller); -} - -void DeviceOrientationDispatcher::startUpdating() { - Send(new DeviceOrientationHostMsg_StartUpdating(routing_id())); - started_ = true; -} - -void DeviceOrientationDispatcher::stopUpdating() { - Send(new DeviceOrientationHostMsg_StopUpdating(routing_id())); - started_ = false; -} - -WebKit::WebDeviceOrientation DeviceOrientationDispatcher::lastOrientation() - const { - return last_orientation_; -} - -namespace { -bool OrientationsEqual(const DeviceOrientationMsg_Updated_Params& a, - WebKit::WebDeviceOrientation* b) { - if (a.can_provide_alpha != b->canProvideAlpha()) - return false; - if (a.can_provide_alpha && a.alpha != b->alpha()) - return false; - if (a.can_provide_beta != b->canProvideBeta()) - return false; - if (a.can_provide_beta && a.beta != b->beta()) - return false; - if (a.can_provide_gamma != b->canProvideGamma()) - return false; - if (a.can_provide_gamma && a.gamma != b->gamma()) - return false; - if (a.can_provide_absolute != b->canProvideAbsolute()) - return false; - if (a.can_provide_absolute && a.absolute != b->absolute()) - return false; - - return true; -} -} // namespace - -void DeviceOrientationDispatcher::OnDeviceOrientationUpdated( - const DeviceOrientationMsg_Updated_Params& p) { - if (!last_orientation_.isNull() && OrientationsEqual(p, &last_orientation_)) - return; - - last_orientation_.setNull(false); - if (p.can_provide_alpha) - last_orientation_.setAlpha(p.alpha); - if (p.can_provide_beta) - last_orientation_.setBeta(p.beta); - if (p.can_provide_gamma) - last_orientation_.setGamma(p.gamma); - if (p.can_provide_absolute) - last_orientation_.setAbsolute(p.absolute); - controller_->didChangeDeviceOrientation(last_orientation_); -} - -} // namespace content diff --git a/chromium/content/renderer/device_orientation_dispatcher.h b/chromium/content/renderer/device_orientation_dispatcher.h deleted file mode 100644 index 5ee3342ebf3..00000000000 --- a/chromium/content/renderer/device_orientation_dispatcher.h +++ /dev/null @@ -1,46 +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_RENDERER_DEVICE_ORIENTATION_DISPATCHER_H_ -#define CONTENT_RENDERER_DEVICE_ORIENTATION_DISPATCHER_H_ - -#include "third_party/WebKit/public/web/WebDeviceOrientationClient.h" -#include "third_party/WebKit/public/web/WebDeviceOrientation.h" - -#include "base/memory/scoped_ptr.h" -#include "content/public/renderer/render_view_observer.h" - -struct DeviceOrientationMsg_Updated_Params; - -namespace content { -class RenderViewImpl; - -class DeviceOrientationDispatcher : public RenderViewObserver, - public WebKit::WebDeviceOrientationClient { - public: - explicit DeviceOrientationDispatcher(RenderViewImpl* render_view); - virtual ~DeviceOrientationDispatcher(); - - private: - // RenderView::Observer implementation. - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - - // From WebKit::WebDeviceOrientationClient. - virtual void setController( - WebKit::WebDeviceOrientationController* controller); - virtual void startUpdating(); - virtual void stopUpdating(); - virtual WebKit::WebDeviceOrientation lastOrientation() const; - - void OnDeviceOrientationUpdated( - const DeviceOrientationMsg_Updated_Params& p); - - scoped_ptr<WebKit::WebDeviceOrientationController> controller_; - WebKit::WebDeviceOrientation last_orientation_; - bool started_; -}; - -} // namespace content - -#endif // CONTENT_RENDERER_DEVICE_ORIENTATION_DISPATCHER_H_ diff --git a/chromium/content/renderer/devtools/devtools_agent.cc b/chromium/content/renderer/devtools/devtools_agent.cc index 635acc18641..a2415441e25 100644 --- a/chromium/content/renderer/devtools/devtools_agent.cc +++ b/chromium/content/renderer/devtools/devtools_agent.cc @@ -12,9 +12,11 @@ #include "base/process/process.h" #include "base/strings/string_number_conversions.h" #include "content/common/devtools_messages.h" +#include "content/common/gpu/gpu_messages.h" #include "content/common/view_messages.h" #include "content/renderer/devtools/devtools_agent_filter.h" #include "content/renderer/devtools/devtools_client.h" +#include "content/renderer/render_thread_impl.h" #include "content/renderer/render_view_impl.h" #include "third_party/WebKit/public/platform/WebPoint.h" #include "third_party/WebKit/public/platform/WebString.h" @@ -22,26 +24,29 @@ #include "third_party/WebKit/public/web/WebConsoleMessage.h" #include "third_party/WebKit/public/web/WebDevToolsAgent.h" #include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebSettings.h" #include "third_party/WebKit/public/web/WebView.h" #if defined(USE_TCMALLOC) #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h" #endif -using WebKit::WebConsoleMessage; -using WebKit::WebDevToolsAgent; -using WebKit::WebDevToolsAgentClient; -using WebKit::WebFrame; -using WebKit::WebPoint; -using WebKit::WebString; -using WebKit::WebCString; -using WebKit::WebVector; -using WebKit::WebView; +using blink::WebConsoleMessage; +using blink::WebDevToolsAgent; +using blink::WebDevToolsAgentClient; +using blink::WebFrame; +using blink::WebPoint; +using blink::WebString; +using blink::WebCString; +using blink::WebVector; +using blink::WebView; using base::debug::TraceLog; namespace content { +base::subtle::AtomicWord DevToolsAgent::event_callback_; + namespace { class WebKitClientMessageLoopImpl @@ -69,7 +74,8 @@ base::LazyInstance<IdToAgentMap>::Leaky DevToolsAgent::DevToolsAgent(RenderViewImpl* render_view) : RenderViewObserver(render_view), is_attached_(false), - is_devtools_client_(false) { + is_devtools_client_(false), + gpu_route_id_(MSG_ROUTING_NONE) { g_agent_for_routing_id.Get()[routing_id()] = this; render_view->webview()->setDevToolsAgentClient(this); @@ -79,6 +85,7 @@ DevToolsAgent::DevToolsAgent(RenderViewImpl* render_view) DevToolsAgent::~DevToolsAgent() { g_agent_for_routing_id.Get().erase(routing_id()); + setTraceEventCallback(NULL); } // Called on the Renderer thread. @@ -93,6 +100,7 @@ bool DevToolsAgent::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(DevToolsAgentMsg_InspectElement, OnInspectElement) IPC_MESSAGE_HANDLER(DevToolsAgentMsg_AddMessageToConsole, OnAddMessageToConsole) + IPC_MESSAGE_HANDLER(DevToolsAgentMsg_GpuTasksChunk, OnGpuTasksChunk) IPC_MESSAGE_HANDLER(DevToolsMsg_SetupDevToolsClient, OnSetupDevToolsClient) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -105,7 +113,7 @@ bool DevToolsAgent::OnMessageReceived(const IPC::Message& message) { } void DevToolsAgent::sendMessageToInspectorFrontend( - const WebKit::WebString& message) { + const blink::WebString& message) { Send(new DevToolsClientMsg_DispatchOnInspectorFrontend(routing_id(), message.utf8())); } @@ -115,11 +123,11 @@ int DevToolsAgent::hostIdentifier() { } void DevToolsAgent::saveAgentRuntimeState( - const WebKit::WebString& state) { + const blink::WebString& state) { Send(new DevToolsHostMsg_SaveAgentRuntimeState(routing_id(), state.utf8())); } -WebKit::WebDevToolsAgentClient::WebKitClientMessageLoop* +blink::WebDevToolsAgentClient::WebKitClientMessageLoop* DevToolsAgent::createClientMessageLoop() { return new WebKitClientMessageLoopImpl(); } @@ -134,19 +142,94 @@ void DevToolsAgent::clearBrowserCookies() { void DevToolsAgent::setTraceEventCallback(TraceEventCallback cb) { TraceLog* trace_log = TraceLog::GetInstance(); - trace_log->SetEventCallback(cb); + base::subtle::NoBarrier_Store(&event_callback_, + reinterpret_cast<base::subtle::AtomicWord>(cb)); if (!!cb) { - trace_log->SetEnabled(base::debug::CategoryFilter( + trace_log->SetEventCallbackEnabled(base::debug::CategoryFilter( base::debug::CategoryFilter::kDefaultCategoryFilterString), - TraceLog::RECORD_UNTIL_FULL); + TraceEventCallbackWrapper); } else { - trace_log->SetDisabled(); + trace_log->SetEventCallbackDisabled(); + } +} + +// static +void DevToolsAgent::TraceEventCallbackWrapper( + base::TimeTicks timestamp, + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int num_args, + const char* const arg_names[], + const unsigned char arg_types[], + const unsigned long long arg_values[], + unsigned char flags) { + TraceEventCallback callback = + reinterpret_cast<TraceEventCallback>( + base::subtle::NoBarrier_Load(&event_callback_)); + if (callback) { + double timestamp_seconds = (timestamp - base::TimeTicks()).InSecondsF(); + callback(phase, category_group_enabled, name, id, num_args, + arg_names, arg_types, arg_values, flags, timestamp_seconds); } } +void DevToolsAgent::startGPUEventsRecording() { + GpuChannelHost* gpu_channel_host = + RenderThreadImpl::current()->GetGpuChannel(); + if (!gpu_channel_host) + return; + DCHECK(gpu_route_id_ == MSG_ROUTING_NONE); + gpu_channel_host->Send( + new GpuChannelMsg_DevToolsStartEventsRecording(&gpu_route_id_)); + DCHECK(gpu_route_id_ != MSG_ROUTING_NONE); + if (gpu_route_id_ != MSG_ROUTING_NONE) { + gpu_channel_host->AddRoute(gpu_route_id_, AsWeakPtr()); + } +} + +void DevToolsAgent::stopGPUEventsRecording() { + GpuChannelHost* gpu_channel_host = + RenderThreadImpl::current()->GetGpuChannel(); + if (!gpu_channel_host || gpu_route_id_ == MSG_ROUTING_NONE) + return; + gpu_channel_host->Send(new GpuChannelMsg_DevToolsStopEventsRecording()); + gpu_channel_host->RemoveRoute(gpu_route_id_); + gpu_route_id_ = MSG_ROUTING_NONE; +} + +void DevToolsAgent::OnGpuTasksChunk(const std::vector<GpuTaskInfo>& tasks) { + WebDevToolsAgent* web_agent = GetWebAgent(); + if (!web_agent) + return; + for (size_t i = 0; i < tasks.size(); i++) { + const GpuTaskInfo& task = tasks[i]; + WebDevToolsAgent::GPUEvent event(task.timestamp, task.phase, task.foreign, + static_cast<size_t>(task.used_gpu_memory_bytes)); + web_agent->processGPUEvent(event); + } +} + +void DevToolsAgent::enableDeviceEmulation( + const blink::WebRect& device_rect, + const blink::WebRect& view_rect, + float device_scale_factor, + bool fit_to_view) { + RenderViewImpl* impl = static_cast<RenderViewImpl*>(render_view()); + impl->webview()->settings()->setForceCompositingMode(true); + impl->EnableScreenMetricsEmulation(gfx::Rect(device_rect), + gfx::Rect(view_rect), device_scale_factor, fit_to_view); +} + +void DevToolsAgent::disableDeviceEmulation() { + RenderViewImpl* impl = static_cast<RenderViewImpl*>(render_view()); + impl->DisableScreenMetricsEmulation(); +} + #if defined(USE_TCMALLOC) && !defined(OS_WIN) static void AllocationVisitor(void* data, const void* ptr) { - typedef WebKit::WebDevToolsAgentClient::AllocatedObjectVisitor Visitor; + typedef blink::WebDevToolsAgentClient::AllocatedObjectVisitor Visitor; Visitor* visitor = reinterpret_cast<Visitor*>(data); visitor->visitObject(ptr); } @@ -192,6 +275,7 @@ void DevToolsAgent::OnDetach() { } void DevToolsAgent::OnDispatchOnInspectorBackend(const std::string& message) { + TRACE_EVENT0("devtools", "DevToolsAgent::OnDispatchOnInspectorBackend"); WebDevToolsAgent* web_agent = GetWebAgent(); if (web_agent) web_agent->dispatchOnInspectorBackend(WebString::fromUTF8(message)); diff --git a/chromium/content/renderer/devtools/devtools_agent.h b/chromium/content/renderer/devtools/devtools_agent.h index 4ac22db97f9..68f3bc4fc2c 100644 --- a/chromium/content/renderer/devtools/devtools_agent.h +++ b/chromium/content/renderer/devtools/devtools_agent.h @@ -6,16 +6,22 @@ #define CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_AGENT_H_ #include <string> +#include <vector> +#include "base/atomicops.h" #include "base/basictypes.h" +#include "base/memory/weak_ptr.h" +#include "base/time/time.h" #include "content/public/common/console_message_level.h" #include "content/public/renderer/render_view_observer.h" #include "third_party/WebKit/public/web/WebDevToolsAgentClient.h" -namespace WebKit { +namespace blink { class WebDevToolsAgent; } +struct GpuTaskInfo; + namespace content { class RenderViewImpl; @@ -24,7 +30,8 @@ class RenderViewImpl; // agents infrastructure are flowing through this communication agent. // There is a corresponding DevToolsClient object on the client side. class DevToolsAgent : public RenderViewObserver, - public WebKit::WebDevToolsAgentClient { + public base::SupportsWeakPtr<DevToolsAgent>, + public blink::WebDevToolsAgentClient { public: explicit DevToolsAgent(RenderViewImpl* render_view); virtual ~DevToolsAgent(); @@ -32,27 +39,39 @@ class DevToolsAgent : public RenderViewObserver, // Returns agent instance for its host id. static DevToolsAgent* FromHostId(int host_id); - WebKit::WebDevToolsAgent* GetWebAgent(); + blink::WebDevToolsAgent* GetWebAgent(); bool IsAttached(); private: - friend class DevToolsAgentFilter; - // RenderView::Observer implementation. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; // WebDevToolsAgentClient implementation - virtual void sendMessageToInspectorFrontend(const WebKit::WebString& data); + virtual void sendMessageToInspectorFrontend(const blink::WebString& data); virtual int hostIdentifier(); - virtual void saveAgentRuntimeState(const WebKit::WebString& state); - virtual WebKit::WebDevToolsAgentClient::WebKitClientMessageLoop* + virtual void saveAgentRuntimeState(const blink::WebString& state); + virtual blink::WebDevToolsAgentClient::WebKitClientMessageLoop* createClientMessageLoop(); virtual void clearBrowserCache(); virtual void clearBrowserCookies(); virtual void visitAllocatedObjects(AllocatedObjectVisitor* visitor); - virtual void setTraceEventCallback(TraceEventCallback cb); + + typedef void (*TraceEventCallback)( + char phase, const unsigned char*, const char* name, unsigned long long id, + int numArgs, const char* const* argNames, const unsigned char* argTypes, + const unsigned long long* argValues, + unsigned char flags, double timestamp); + virtual void setTraceEventCallback(TraceEventCallback cb) OVERRIDE; + virtual void startGPUEventsRecording() OVERRIDE; + virtual void stopGPUEventsRecording() OVERRIDE; + + virtual void enableDeviceEmulation( + const blink::WebRect& device_rect, + const blink::WebRect& view_rect, float device_scale_factor, + bool fit_to_view); + virtual void disableDeviceEmulation(); void OnAttach(); void OnReattach(const std::string& agent_state); @@ -61,11 +80,27 @@ class DevToolsAgent : public RenderViewObserver, void OnInspectElement(int x, int y); void OnAddMessageToConsole(ConsoleMessageLevel level, const std::string& message); + void OnGpuTasksChunk(const std::vector<GpuTaskInfo>& tasks); void ContinueProgram(); void OnSetupDevToolsClient(); + static void TraceEventCallbackWrapper( + base::TimeTicks timestamp, + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int num_args, + const char* const arg_names[], + const unsigned char arg_types[], + const unsigned long long arg_values[], + unsigned char flags); + bool is_attached_; bool is_devtools_client_; + int32 gpu_route_id_; + + static base::subtle::AtomicWord /* TraceEventCallback */ event_callback_; DISALLOW_COPY_AND_ASSIGN(DevToolsAgent); }; diff --git a/chromium/content/renderer/devtools/devtools_agent_filter.cc b/chromium/content/renderer/devtools/devtools_agent_filter.cc index 1613ad8c477..fc9e34f8a8a 100644 --- a/chromium/content/renderer/devtools/devtools_agent_filter.cc +++ b/chromium/content/renderer/devtools/devtools_agent_filter.cc @@ -11,8 +11,8 @@ #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/web/WebDevToolsAgent.h" -using WebKit::WebDevToolsAgent; -using WebKit::WebString; +using blink::WebDevToolsAgent; +using blink::WebString; namespace content { diff --git a/chromium/content/renderer/devtools/devtools_client.cc b/chromium/content/renderer/devtools/devtools_client.cc index 5793d2c7ebf..3d51312b8d0 100644 --- a/chromium/content/renderer/devtools/devtools_client.cc +++ b/chromium/content/renderer/devtools/devtools_client.cc @@ -16,10 +16,9 @@ #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/web/WebDevToolsFrontend.h" #include "ui/base/ui_base_switches.h" -#include "webkit/common/appcache/appcache_interfaces.h" -using WebKit::WebDevToolsFrontend; -using WebKit::WebString; +using blink::WebDevToolsFrontend; +using blink::WebString; namespace content { @@ -31,7 +30,6 @@ DevToolsClient::DevToolsClient(RenderViewImpl* render_view) render_view->webview(), this, ASCIIToUTF16(command_line.GetSwitchValueASCII(switches::kLang)))); - appcache::AddSupportedScheme(chrome::kChromeDevToolsScheme); } DevToolsClient::~DevToolsClient() { diff --git a/chromium/content/renderer/devtools/devtools_client.h b/chromium/content/renderer/devtools/devtools_client.h index 1c9d3f8fc20..be1e902cdff 100644 --- a/chromium/content/renderer/devtools/devtools_client.h +++ b/chromium/content/renderer/devtools/devtools_client.h @@ -12,7 +12,7 @@ #include "content/public/renderer/render_view_observer.h" #include "third_party/WebKit/public/web/WebDevToolsFrontendClient.h" -namespace WebKit { +namespace blink { class WebDevToolsFrontend; class WebString; } @@ -29,7 +29,7 @@ class RenderViewImpl; // code in glue class CONTENT_EXPORT DevToolsClient : public RenderViewObserver, - NON_EXPORTED_BASE(public WebKit::WebDevToolsFrontendClient) { + NON_EXPORTED_BASE(public blink::WebDevToolsFrontendClient) { public: explicit DevToolsClient(RenderViewImpl* render_view); virtual ~DevToolsClient(); @@ -39,14 +39,14 @@ class CONTENT_EXPORT DevToolsClient virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; // WebDevToolsFrontendClient implementation. - virtual void sendMessageToBackend(const WebKit::WebString&) OVERRIDE; - virtual void sendMessageToEmbedder(const WebKit::WebString&) OVERRIDE; + virtual void sendMessageToBackend(const blink::WebString&) OVERRIDE; + virtual void sendMessageToEmbedder(const blink::WebString&) OVERRIDE; virtual bool isUnderTest() OVERRIDE; void OnDispatchOnInspectorFrontend(const std::string& message); - scoped_ptr<WebKit::WebDevToolsFrontend> web_tools_frontend_; + scoped_ptr<blink::WebDevToolsFrontend> web_tools_frontend_; DISALLOW_COPY_AND_ASSIGN(DevToolsClient); }; diff --git a/chromium/content/renderer/disambiguation_popup_helper.cc b/chromium/content/renderer/disambiguation_popup_helper.cc index 88f2e51d11c..9fff7b9b99c 100644 --- a/chromium/content/renderer/disambiguation_popup_helper.cc +++ b/chromium/content/renderer/disambiguation_popup_helper.cc @@ -7,8 +7,8 @@ #include "third_party/WebKit/public/platform/WebRect.h" #include "ui/gfx/size_conversions.h" -using WebKit::WebRect; -using WebKit::WebVector; +using blink::WebRect; +using blink::WebVector; namespace { diff --git a/chromium/content/renderer/disambiguation_popup_helper.h b/chromium/content/renderer/disambiguation_popup_helper.h index 535683d691a..0238f8a562c 100644 --- a/chromium/content/renderer/disambiguation_popup_helper.h +++ b/chromium/content/renderer/disambiguation_popup_helper.h @@ -13,7 +13,7 @@ class Rect; class Size; } -namespace WebKit { +namespace blink { struct WebRect; } @@ -24,7 +24,7 @@ class DisambiguationPopupHelper { public: CONTENT_EXPORT static float ComputeZoomAreaAndScaleFactor( const gfx::Rect& tap_rect, - const WebKit::WebVector<WebKit::WebRect>& target_rects, + const blink::WebVector<blink::WebRect>& target_rects, const gfx::Size& screen_size, const gfx::Size& visible_content_size, float total_scale, diff --git a/chromium/content/renderer/disambiguation_popup_helper_unittest.cc b/chromium/content/renderer/disambiguation_popup_helper_unittest.cc index 0b6d0020ae3..8cbbe4b5ab3 100644 --- a/chromium/content/renderer/disambiguation_popup_helper_unittest.cc +++ b/chromium/content/renderer/disambiguation_popup_helper_unittest.cc @@ -33,7 +33,7 @@ class DisambiguationPopupHelperUnittest : public testing::Test { TEST_F(DisambiguationPopupHelperUnittest, ClipByViewport) { gfx::Rect tap_rect(1000, 1000, 10, 10); - WebKit::WebVector<WebKit::WebRect> target_rects(static_cast<size_t>(1)); + blink::WebVector<blink::WebRect> target_rects(static_cast<size_t>(1)); target_rects[0] = gfx::Rect(-20, -20, 10, 10); gfx::Rect zoom_rect; @@ -50,7 +50,7 @@ TEST_F(DisambiguationPopupHelperUnittest, ClipByViewport) { TEST_F(DisambiguationPopupHelperUnittest, MiniTarget) { gfx::Rect tap_rect(-5, -5, 20, 20); - WebKit::WebVector<WebKit::WebRect> target_rects(static_cast<size_t>(1)); + blink::WebVector<blink::WebRect> target_rects(static_cast<size_t>(1)); target_rects[0] = gfx::Rect(10, 10, 1, 1); gfx::Rect zoom_rect; @@ -68,7 +68,7 @@ TEST_F(DisambiguationPopupHelperUnittest, MiniTarget) { TEST_F(DisambiguationPopupHelperUnittest, LongLinks) { gfx::Rect tap_rect(10, 10, 20, 20); - WebKit::WebVector<WebKit::WebRect> target_rects(static_cast<size_t>(2)); + blink::WebVector<blink::WebRect> target_rects(static_cast<size_t>(2)); target_rects[0] = gfx::Rect(15, 15, 1000, 5); target_rects[1] = gfx::Rect(15, 25, 1000, 5); diff --git a/chromium/content/renderer/dom_serializer_browsertest.cc b/chromium/content/renderer/dom_serializer_browsertest.cc index 69dfc6533be..16bd30fb77f 100644 --- a/chromium/content/renderer/dom_serializer_browsertest.cc +++ b/chromium/content/renderer/dom_serializer_browsertest.cc @@ -35,21 +35,21 @@ #include "third_party/WebKit/public/web/WebPageSerializerClient.h" #include "third_party/WebKit/public/web/WebView.h" -using WebKit::WebCString; -using WebKit::WebData; -using WebKit::WebDocument; -using WebKit::WebElement; -using WebKit::WebFrame; -using WebKit::WebNode; -using WebKit::WebNodeCollection; -using WebKit::WebNodeList; -using WebKit::WebPageSerializer; -using WebKit::WebPageSerializerClient; -using WebKit::WebNode; -using WebKit::WebString; -using WebKit::WebURL; -using WebKit::WebView; -using WebKit::WebVector; +using blink::WebCString; +using blink::WebData; +using blink::WebDocument; +using blink::WebElement; +using blink::WebFrame; +using blink::WebNode; +using blink::WebNodeCollection; +using blink::WebNodeList; +using blink::WebPageSerializer; +using blink::WebPageSerializerClient; +using blink::WebNode; +using blink::WebString; +using blink::WebURL; +using blink::WebView; +using blink::WebVector; namespace content { @@ -150,7 +150,7 @@ class LoadObserver : public RenderViewObserver { : RenderViewObserver(render_view), quit_closure_(quit_closure) {} - virtual void DidFinishLoad(WebKit::WebFrame* frame) OVERRIDE { + virtual void DidFinishLoad(blink::WebFrame* frame) OVERRIDE { if (frame == render_view()->GetWebView()->mainFrame()) quit_closure_.Run(); } @@ -269,18 +269,18 @@ class DomSerializerTests : public ContentBrowserTest, // Find corresponding WebFrame according to page_url. WebFrame* web_frame = FindSubFrameByURL(GetWebView(), page_url); ASSERT_TRUE(web_frame != NULL); - // Add input file URl to links_. - links_.assign(&page_url,1); - // Add dummy file path to local_path_. + WebVector<WebURL> links; + links.assign(&page_url, 1); WebString file_path = base::FilePath(FILE_PATH_LITERAL("c:\\dummy.htm")).AsUTF16Unsafe(); - local_paths_.assign(&file_path, 1); + WebVector<WebString> local_paths; + local_paths.assign(&file_path, 1); // Start serializing DOM. bool result = WebPageSerializer::serialize(web_frame, recursive_serialization, static_cast<WebPageSerializerClient*>(this), - links_, - local_paths_, + links, + local_paths, local_directory_name_.AsUTF16Unsafe()); ASSERT_TRUE(result); ASSERT_TRUE(serialized_); @@ -770,11 +770,6 @@ class DomSerializerTests : public ContentBrowserTest, SerializationFinishStatusMap serialization_finish_status_; // Flag indicates whether the process of serializing DOM is finished or not. bool serialized_; - // The links_ contain dummy original URLs of all saved links. - WebVector<WebURL> links_; - // The local_paths_ contain dummy corresponding local file paths of all saved - // links, which matched links_ one by one. - WebVector<WebString> local_paths_; // The local_directory_name_ is dummy relative path of directory which // contain all saved auxiliary files included all sub frames and resources. const base::FilePath local_directory_name_; @@ -912,8 +907,12 @@ IN_PROC_BROWSER_TEST_F(DomSerializerTests, SerializeHTMLDOMWithEntitiesInText) { // Test situation of html entities in attribute value when serializing // HTML DOM. // This test started to fail at WebKit r65388. See http://crbug.com/52279. +// +// TODO(tiger@opera.com): Disabled in preparation of page serializer merge -- +// Some attributes are handled differently in the merged serializer. +// Bug: http://crbug.com/328354 IN_PROC_BROWSER_TEST_F(DomSerializerTests, - SerializeHTMLDOMWithEntitiesInAttributeValue) { + DISABLE_SerializeHTMLDOMWithEntitiesInAttributeValue) { // Need to spin up the renderer and also navigate to a file url so that the // renderer code doesn't attempt a fork when it sees a load to file scheme // from non-file scheme. @@ -947,7 +946,12 @@ IN_PROC_BROWSER_TEST_F(DomSerializerTests, // When serializing, we should comment the BASE tag, append a new BASE tag. // rewrite all the savable URLs to relative local path, and change other URLs // to absolute URLs. -IN_PROC_BROWSER_TEST_F(DomSerializerTests, SerializeHTMLDOMWithBaseTag) { +// +// TODO(tiger@opera.com): Disabled in preparation of page serializer merge -- +// Base tags are handled a bit different in merged version. +// Bug: http://crbug.com/328354 +IN_PROC_BROWSER_TEST_F(DomSerializerTests, + DISABLE_SerializeHTMLDOMWithBaseTag) { base::FilePath page_file_path = GetTestFilePath( "dom_serializer", "html_doc_has_base_tag.htm"); diff --git a/chromium/content/renderer/dom_storage/dom_storage_cached_area.cc b/chromium/content/renderer/dom_storage/dom_storage_cached_area.cc index a01d3c6f7fb..2923fcb1def 100644 --- a/chromium/content/renderer/dom_storage/dom_storage_cached_area.cc +++ b/chromium/content/renderer/dom_storage/dom_storage_cached_area.cc @@ -12,6 +12,12 @@ namespace content { +namespace { + +static const int kMaxLogGetMessagesToSend = 16 * 1024; + +} // namespace + DOMStorageCachedArea::DOMStorageCachedArea(int64 namespace_id, const GURL& origin, DOMStorageProxy* proxy) @@ -19,6 +25,7 @@ DOMStorageCachedArea::DOMStorageCachedArea(int64 namespace_id, namespace_id_(namespace_id), origin_(origin), proxy_(proxy), + remaining_log_get_messages_(0), weak_factory_(this) {} DOMStorageCachedArea::~DOMStorageCachedArea() {} @@ -38,7 +45,12 @@ base::NullableString16 DOMStorageCachedArea::GetItem( int connection_id, const base::string16& key) { PrimeIfNeeded(connection_id); - return map_->GetItem(key); + base::NullableString16 result = map_->GetItem(key); + if (remaining_log_get_messages_ > 0) { + remaining_log_get_messages_--; + proxy_->LogGetItem(connection_id, key, result); + } + return result; } bool DOMStorageCachedArea::SetItem(int connection_id, @@ -155,9 +167,11 @@ void DOMStorageCachedArea::Prime(int connection_id) { // Ignore all mutations until OnLoadComplete time. ignore_all_mutations_ = true; DOMStorageValuesMap values; + bool send_log_get_messages = false; base::TimeTicks before = base::TimeTicks::Now(); proxy_->LoadArea(connection_id, &values, + &send_log_get_messages, base::Bind(&DOMStorageCachedArea::OnLoadComplete, weak_factory_.GetWeakPtr())); base::TimeDelta time_to_prime = base::TimeTicks::Now() - before; @@ -167,6 +181,8 @@ void DOMStorageCachedArea::Prime(int connection_id) { time_to_prime); map_ = new DOMStorageMap(kPerStorageAreaQuota); map_->SwapValues(&values); + if (send_log_get_messages) + remaining_log_get_messages_ = kMaxLogGetMessagesToSend; size_t local_storage_size_kb = map_->bytes_used() / 1024; // Track localStorage size, from 0-6MB. Note that the maximum size should be diff --git a/chromium/content/renderer/dom_storage/dom_storage_cached_area.h b/chromium/content/renderer/dom_storage/dom_storage_cached_area.h index b9910388553..6942534cf87 100644 --- a/chromium/content/renderer/dom_storage/dom_storage_cached_area.h +++ b/chromium/content/renderer/dom_storage/dom_storage_cached_area.h @@ -51,6 +51,9 @@ class CONTENT_EXPORT DOMStorageCachedArea size_t MemoryBytesUsedByCache() const; + // Resets the object back to its newly constructed state. + void Reset(); + private: friend class DOMStorageCachedAreaTest; friend class base::RefCounted<DOMStorageCachedArea>; @@ -63,9 +66,6 @@ class CONTENT_EXPORT DOMStorageCachedArea Prime(connection_id); } - // Resets the object back to its newly constructed state. - void Reset(); - // Async completion callbacks for proxied operations. // These are used to maintain cache consistency by preventing // mutation events from other processes from overwriting local @@ -86,6 +86,11 @@ class CONTENT_EXPORT DOMStorageCachedArea GURL origin_; scoped_refptr<DOMStorageMap> map_; scoped_refptr<DOMStorageProxy> proxy_; + // Sometimes, we need to send messages to the browser for each get access, + // for logging purposes. However, we only do this for a fixed maximum number + // of gets. Here, we keep track of how many remaining get log messages we + // need to send. + int remaining_log_get_messages_; base::WeakPtrFactory<DOMStorageCachedArea> weak_factory_; }; diff --git a/chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc b/chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc index ada36d72b20..04b5a286edc 100644 --- a/chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc +++ b/chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc @@ -25,11 +25,13 @@ class MockProxy : public DOMStorageProxy { virtual void LoadArea(int connection_id, DOMStorageValuesMap* values, + bool* send_log_get_messages, const CompletionCallback& callback) OVERRIDE { pending_callbacks_.push_back(callback); observed_load_area_ = true; observed_connection_id_ = connection_id; *values = load_area_return_values_; + *send_log_get_messages = false; } virtual void SetItem(int connection_id, @@ -45,6 +47,11 @@ class MockProxy : public DOMStorageProxy { observed_page_url_ = page_url; } + virtual void LogGetItem(int connection_id, + const base::string16& key, + const base::NullableString16& value) OVERRIDE { + } + virtual void RemoveItem(int connection_id, const base::string16& key, const GURL& page_url, diff --git a/chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc b/chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc index a8a37c989a4..477251c33a9 100644 --- a/chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc +++ b/chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc @@ -103,16 +103,20 @@ class DomStorageDispatcher::ProxyImpl : public DOMStorageProxy { void CloseCachedArea(DOMStorageCachedArea* area); DOMStorageCachedArea* LookupCachedArea( int64 namespace_id, const GURL& origin); + void ResetAllCachedAreas(int64 namespace_id); void CompleteOnePendingCallback(bool success); void Shutdown(); // DOMStorageProxy interface for use by DOMStorageCachedArea. virtual void LoadArea(int connection_id, DOMStorageValuesMap* values, + bool* send_log_get_messages, const CompletionCallback& callback) OVERRIDE; - virtual void SetItem(int connection_id, const string16& key, - const string16& value, const GURL& page_url, + virtual void SetItem(int connection_id, const base::string16& key, + const base::string16& value, const GURL& page_url, const CompletionCallback& callback) OVERRIDE; - virtual void RemoveItem(int connection_id, const string16& key, + virtual void LogGetItem(int connection_id, const base::string16& key, + const base::NullableString16& value) OVERRIDE; + virtual void RemoveItem(int connection_id, const base::string16& key, const GURL& page_url, const CompletionCallback& callback) OVERRIDE; virtual void ClearArea(int connection_id, @@ -125,9 +129,11 @@ class DomStorageDispatcher::ProxyImpl : public DOMStorageProxy { struct CachedAreaHolder { scoped_refptr<DOMStorageCachedArea> area_; int open_count_; + int64 namespace_id_; CachedAreaHolder() : open_count_(0) {} - CachedAreaHolder(DOMStorageCachedArea* area, int count) - : area_(area), open_count_(count) {} + CachedAreaHolder(DOMStorageCachedArea* area, int count, + int64 namespace_id) + : area_(area), open_count_(count), namespace_id_(namespace_id) {} }; typedef std::map<std::string, CachedAreaHolder> CachedAreaMap; typedef std::list<CompletionCallback> CallbackList; @@ -139,7 +145,7 @@ class DomStorageDispatcher::ProxyImpl : public DOMStorageProxy { // to more reliably commit changes during shutdown. void PushPendingCallback(const CompletionCallback& callback) { if (pending_callbacks_.empty()) - WebKit::Platform::current()->suddenTerminationChanged(false); + blink::Platform::current()->suddenTerminationChanged(false); pending_callbacks_.push_back(callback); } @@ -147,7 +153,7 @@ class DomStorageDispatcher::ProxyImpl : public DOMStorageProxy { CompletionCallback callback = pending_callbacks_.front(); pending_callbacks_.pop_front(); if (pending_callbacks_.empty()) - WebKit::Platform::current()->suddenTerminationChanged(true); + blink::Platform::current()->suddenTerminationChanged(true); return callback; } @@ -183,7 +189,7 @@ DOMStorageCachedArea* DomStorageDispatcher::ProxyImpl::OpenCachedArea( } scoped_refptr<DOMStorageCachedArea> area = new DOMStorageCachedArea(namespace_id, origin, this); - cached_areas_[key] = CachedAreaHolder(area.get(), 1); + cached_areas_[key] = CachedAreaHolder(area.get(), 1, namespace_id); return area.get(); } @@ -208,6 +214,15 @@ DOMStorageCachedArea* DomStorageDispatcher::ProxyImpl::LookupCachedArea( return holder->area_.get(); } +void DomStorageDispatcher::ProxyImpl::ResetAllCachedAreas(int64 namespace_id) { + for (CachedAreaMap::iterator it = cached_areas_.begin(); + it != cached_areas_.end(); + ++it) { + if (it->second.namespace_id_ == namespace_id) + it->second.area_->Reset(); + } +} + void DomStorageDispatcher::ProxyImpl::CompleteOnePendingCallback(bool success) { PopPendingCallback().Run(success); } @@ -221,24 +236,30 @@ void DomStorageDispatcher::ProxyImpl::Shutdown() { } void DomStorageDispatcher::ProxyImpl::LoadArea( - int connection_id, DOMStorageValuesMap* values, + int connection_id, DOMStorageValuesMap* values, bool* send_log_get_messages, const CompletionCallback& callback) { PushPendingCallback(callback); throttling_filter_->SendThrottled(new DOMStorageHostMsg_LoadStorageArea( - connection_id, values)); + connection_id, values, send_log_get_messages)); } void DomStorageDispatcher::ProxyImpl::SetItem( - 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, const CompletionCallback& callback) { PushPendingCallback(callback); throttling_filter_->SendThrottled(new DOMStorageHostMsg_SetItem( connection_id, key, value, page_url)); } +void DomStorageDispatcher::ProxyImpl::LogGetItem( + int connection_id, const base::string16& key, + const base::NullableString16& value) { + sender_->Send(new DOMStorageHostMsg_LogGetItem(connection_id, key, value)); +} + void DomStorageDispatcher::ProxyImpl::RemoveItem( - int connection_id, const string16& key, const GURL& page_url, + int connection_id, const base::string16& key, const GURL& page_url, const CompletionCallback& callback) { PushPendingCallback(callback); throttling_filter_->SendThrottled(new DOMStorageHostMsg_RemoveItem( @@ -284,6 +305,8 @@ bool DomStorageDispatcher::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(DOMStorageMsg_Event, OnStorageEvent) IPC_MESSAGE_HANDLER(DOMStorageMsg_AsyncOperationComplete, OnAsyncOperationComplete) + IPC_MESSAGE_HANDLER(DOMStorageMsg_ResetCachedValues, + OnResetCachedValues) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -306,7 +329,7 @@ void DomStorageDispatcher::OnStorageEvent( } if (params.namespace_id == kLocalStorageNamespaceId) { - WebKit::WebStorageEventDispatcher::dispatchLocalStorageEvent( + blink::WebStorageEventDispatcher::dispatchLocalStorageEvent( params.key, params.old_value, params.new_value, @@ -317,7 +340,7 @@ void DomStorageDispatcher::OnStorageEvent( } else { WebStorageNamespaceImpl session_namespace_for_event_dispatch(params.namespace_id); - WebKit::WebStorageEventDispatcher::dispatchSessionStorageEvent( + blink::WebStorageEventDispatcher::dispatchSessionStorageEvent( params.key, params.old_value, params.new_value, @@ -333,4 +356,8 @@ void DomStorageDispatcher::OnAsyncOperationComplete(bool success) { proxy_->CompleteOnePendingCallback(success); } +void DomStorageDispatcher::OnResetCachedValues(int64 namespace_id) { + proxy_->ResetAllCachedAreas(namespace_id); +} + } // namespace content diff --git a/chromium/content/renderer/dom_storage/dom_storage_dispatcher.h b/chromium/content/renderer/dom_storage/dom_storage_dispatcher.h index f395d575f5c..70595ca12fd 100644 --- a/chromium/content/renderer/dom_storage/dom_storage_dispatcher.h +++ b/chromium/content/renderer/dom_storage/dom_storage_dispatcher.h @@ -42,6 +42,7 @@ class DomStorageDispatcher { // IPC message handlers void OnStorageEvent(const DOMStorageMsg_Event_Params& params); void OnAsyncOperationComplete(bool success); + void OnResetCachedValues(int64 namespace_id); scoped_refptr<ProxyImpl> proxy_; }; diff --git a/chromium/content/renderer/dom_storage/dom_storage_proxy.h b/chromium/content/renderer/dom_storage/dom_storage_proxy.h index 80cd87cdcc4..118aab34da3 100644 --- a/chromium/content/renderer/dom_storage/dom_storage_proxy.h +++ b/chromium/content/renderer/dom_storage/dom_storage_proxy.h @@ -21,6 +21,7 @@ class DOMStorageProxy : public base::RefCounted<DOMStorageProxy> { virtual void LoadArea(int connection_id, DOMStorageValuesMap* values, + bool* send_log_get_messages, const CompletionCallback& callback) = 0; virtual void SetItem(int connection_id, @@ -29,6 +30,10 @@ class DOMStorageProxy : public base::RefCounted<DOMStorageProxy> { const GURL& page_url, const CompletionCallback& callback) = 0; + virtual void LogGetItem(int connection_id, + const base::string16& key, + const base::NullableString16& value) = 0; + virtual void RemoveItem(int connection_id, const base::string16& key, const GURL& page_url, diff --git a/chromium/content/renderer/dom_storage/webstoragearea_impl.cc b/chromium/content/renderer/dom_storage/webstoragearea_impl.cc index d5bf07dbaf9..c3075352dd5 100644 --- a/chromium/content/renderer/dom_storage/webstoragearea_impl.cc +++ b/chromium/content/renderer/dom_storage/webstoragearea_impl.cc @@ -14,8 +14,8 @@ #include "content/renderer/render_thread_impl.h" #include "third_party/WebKit/public/platform/WebURL.h" -using WebKit::WebString; -using WebKit::WebURL; +using blink::WebString; +using blink::WebURL; namespace content { diff --git a/chromium/content/renderer/dom_storage/webstoragearea_impl.h b/chromium/content/renderer/dom_storage/webstoragearea_impl.h index 7854562603e..24056ce26e5 100644 --- a/chromium/content/renderer/dom_storage/webstoragearea_impl.h +++ b/chromium/content/renderer/dom_storage/webstoragearea_impl.h @@ -16,7 +16,7 @@ namespace content { class DOMStorageCachedArea; -class WebStorageAreaImpl : public WebKit::WebStorageArea { +class WebStorageAreaImpl : public blink::WebStorageArea { public: static WebStorageAreaImpl* FromConnectionId(int id); @@ -25,14 +25,14 @@ class WebStorageAreaImpl : public WebKit::WebStorageArea { // See WebStorageArea.h for documentation on these functions. virtual unsigned length(); - virtual WebKit::WebString key(unsigned index); - virtual WebKit::WebString getItem(const WebKit::WebString& key); + virtual blink::WebString key(unsigned index); + virtual blink::WebString getItem(const blink::WebString& key); virtual void setItem( - const WebKit::WebString& key, const WebKit::WebString& value, - const WebKit::WebURL& page_url, WebStorageArea::Result& result); + const blink::WebString& key, const blink::WebString& value, + const blink::WebURL& page_url, WebStorageArea::Result& result); virtual void removeItem( - const WebKit::WebString& key, const WebKit::WebURL& page_url); - virtual void clear(const WebKit::WebURL& url); + const blink::WebString& key, const blink::WebURL& page_url); + virtual void clear(const blink::WebURL& url); virtual size_t memoryBytesUsedByCache() const; private: diff --git a/chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc b/chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc index d5f1dc5bc8e..531263d6f84 100644 --- a/chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc +++ b/chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc @@ -10,9 +10,9 @@ #include "third_party/WebKit/public/platform/WebString.h" #include "url/gurl.h" -using WebKit::WebStorageArea; -using WebKit::WebStorageNamespace; -using WebKit::WebString; +using blink::WebStorageArea; +using blink::WebStorageNamespace; +using blink::WebString; namespace content { diff --git a/chromium/content/renderer/dom_storage/webstoragenamespace_impl.h b/chromium/content/renderer/dom_storage/webstoragenamespace_impl.h index 52c1b355f9b..364e6480352 100644 --- a/chromium/content/renderer/dom_storage/webstoragenamespace_impl.h +++ b/chromium/content/renderer/dom_storage/webstoragenamespace_impl.h @@ -10,7 +10,7 @@ namespace content { -class WebStorageNamespaceImpl : public WebKit::WebStorageNamespace { +class WebStorageNamespaceImpl : public blink::WebStorageNamespace { public: // The default constructor creates a local storage namespace, the second // constructor should be used for session storage namepaces. @@ -19,9 +19,9 @@ class WebStorageNamespaceImpl : public WebKit::WebStorageNamespace { virtual ~WebStorageNamespaceImpl(); // See WebStorageNamespace.h for documentation on these functions. - virtual WebKit::WebStorageArea* createStorageArea( - const WebKit::WebString& origin); - virtual WebKit::WebStorageNamespace* copy(); + virtual blink::WebStorageArea* createStorageArea( + const blink::WebString& origin); + virtual blink::WebStorageNamespace* copy(); virtual bool isSameNamespace(const WebStorageNamespace&) const; private: diff --git a/chromium/content/renderer/drop_data_builder.cc b/chromium/content/renderer/drop_data_builder.cc index 56bc81a9964..f9e5c420d3c 100644 --- a/chromium/content/renderer/drop_data_builder.cc +++ b/chromium/content/renderer/drop_data_builder.cc @@ -11,15 +11,15 @@ #include "third_party/WebKit/public/platform/WebVector.h" #include "ui/base/clipboard/clipboard.h" -using WebKit::WebDragData; -using WebKit::WebVector; +using blink::WebDragData; +using blink::WebVector; namespace content { //static DropData DropDataBuilder::Build(const WebDragData& drag_data) { DropData result; - result.referrer_policy = WebKit::WebReferrerPolicyDefault; + result.referrer_policy = blink::WebReferrerPolicyDefault; const WebVector<WebDragData::Item>& item_list = drag_data.items(); for (size_t i = 0; i < item_list.size(); ++i) { diff --git a/chromium/content/renderer/drop_data_builder.h b/chromium/content/renderer/drop_data_builder.h index 4870d47f927..2dfb7b92375 100644 --- a/chromium/content/renderer/drop_data_builder.h +++ b/chromium/content/renderer/drop_data_builder.h @@ -5,7 +5,7 @@ #ifndef CONTENT_RENDERER_DROP_DATA_BUILDER_H_ #define CONTENT_RENDERER_DROP_DATA_BUILDER_H_ -namespace WebKit { +namespace blink { class WebDragData; } @@ -14,7 +14,7 @@ struct DropData; class DropDataBuilder { public: - static DropData Build(const WebKit::WebDragData& data); + static DropData Build(const blink::WebDragData& data); }; } // namespace content diff --git a/chromium/content/renderer/external_popup_menu.cc b/chromium/content/renderer/external_popup_menu.cc index 08d71e98261..01909131341 100644 --- a/chromium/content/renderer/external_popup_menu.cc +++ b/chromium/content/renderer/external_popup_menu.cc @@ -14,16 +14,31 @@ namespace content { ExternalPopupMenu::ExternalPopupMenu( RenderViewImpl* render_view, - const WebKit::WebPopupMenuInfo& popup_menu_info, - WebKit::WebExternalPopupMenuClient* popup_menu_client) + const blink::WebPopupMenuInfo& popup_menu_info, + blink::WebExternalPopupMenuClient* popup_menu_client) : render_view_(render_view), popup_menu_info_(popup_menu_info), - popup_menu_client_(popup_menu_client) { + popup_menu_client_(popup_menu_client), + origin_scale_for_emulation_(0) { } -void ExternalPopupMenu::show(const WebKit::WebRect& bounds) { +void ExternalPopupMenu::SetOriginScaleAndOffsetForEmulation( + float scale, const gfx::Point& offset) { + origin_scale_for_emulation_ = scale; + origin_offset_for_emulation_ = offset; +} + +void ExternalPopupMenu::show(const blink::WebRect& bounds) { + blink::WebRect rect = bounds; + if (origin_scale_for_emulation_) { + rect.x *= origin_scale_for_emulation_; + rect.y *= origin_scale_for_emulation_; + } + rect.x += origin_offset_for_emulation_.x(); + rect.y += origin_offset_for_emulation_.y(); + ViewHostMsg_ShowPopup_Params popup_params; - popup_params.bounds = bounds; + popup_params.bounds = rect; popup_params.item_height = popup_menu_info_.itemHeight; popup_params.item_font_size = popup_menu_info_.itemFontSize; popup_params.selected_item = popup_menu_info_.selectedIndex; diff --git a/chromium/content/renderer/external_popup_menu.h b/chromium/content/renderer/external_popup_menu.h index 729205fba9f..32137008416 100644 --- a/chromium/content/renderer/external_popup_menu.h +++ b/chromium/content/renderer/external_popup_menu.h @@ -10,22 +10,26 @@ #include "base/basictypes.h" #include "third_party/WebKit/public/web/WebExternalPopupMenu.h" #include "third_party/WebKit/public/web/WebPopupMenuInfo.h" +#include "ui/gfx/point.h" -namespace WebKit { +namespace blink { class WebExternalPopupMenuClient; } namespace content { class RenderViewImpl; -class ExternalPopupMenu : public WebKit::WebExternalPopupMenu { +class ExternalPopupMenu : public blink::WebExternalPopupMenu { public: ExternalPopupMenu(RenderViewImpl* render_view, - const WebKit::WebPopupMenuInfo& popup_menu_info, - WebKit::WebExternalPopupMenuClient* popup_menu_client); + const blink::WebPopupMenuInfo& popup_menu_info, + blink::WebExternalPopupMenuClient* popup_menu_client); virtual ~ExternalPopupMenu() {} + void SetOriginScaleAndOffsetForEmulation( + float scale, const gfx::Point& offset); + #if defined(OS_MACOSX) // Called when the user has selected an item. |selected_item| is -1 if the // user canceled the popup. @@ -37,14 +41,19 @@ class ExternalPopupMenu : public WebKit::WebExternalPopupMenu { void DidSelectItems(bool canceled, const std::vector<int>& selected_indices); #endif - // WebKit::WebExternalPopupMenu implementation: - virtual void show(const WebKit::WebRect& bounds); + // blink::WebExternalPopupMenu implementation: + virtual void show(const blink::WebRect& bounds); virtual void close(); private: RenderViewImpl* render_view_; - WebKit::WebPopupMenuInfo popup_menu_info_; - WebKit::WebExternalPopupMenuClient* popup_menu_client_; + blink::WebPopupMenuInfo popup_menu_info_; + blink::WebExternalPopupMenuClient* popup_menu_client_; + + // Popups may be displaced when screen metrics emulation is enabled. + // These scale and offset are used to properly adjust popup position. + float origin_scale_for_emulation_; + gfx::Point origin_offset_for_emulation_; DISALLOW_COPY_AND_ASSIGN(ExternalPopupMenu); }; diff --git a/chromium/content/renderer/external_popup_menu_browsertest.cc b/chromium/content/renderer/external_popup_menu_browsertest.cc index 30e539732d9..2e3e66456d2 100644 --- a/chromium/content/renderer/external_popup_menu_browsertest.cc +++ b/chromium/content/renderer/external_popup_menu_browsertest.cc @@ -31,7 +31,7 @@ class ExternalPopupMenuTest : public RenderViewTest { virtual void SetUp() { RenderViewTest::SetUp(); // We need to set this explictly as RenderMain is not run. - WebKit::WebView::setUseExternalPopupMenus(true); + blink::WebView::setUseExternalPopupMenus(true); std::string html = "<select id='mySelect' onchange='selectChanged(this)'>" " <option>zero</option>" @@ -52,12 +52,12 @@ class ExternalPopupMenuTest : public RenderViewTest { LoadHTML(html.c_str()); // Set a minimum size and give focus so simulated events work. - view()->webwidget()->resize(WebKit::WebSize(500, 500)); + view()->webwidget()->resize(blink::WebSize(500, 500)); view()->webwidget()->setFocus(true); } int GetSelectedIndex() { - string16 script(ASCIIToUTF16(kSelectID)); + base::string16 script(ASCIIToUTF16(kSelectID)); script.append(ASCIIToUTF16(".selectedIndex")); int selected_index = -1; ExecuteJavaScriptAndReturnIntValue(script, &selected_index); diff --git a/chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.cc b/chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.cc index cbcab0900bd..0fef535e752 100644 --- a/chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.cc +++ b/chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.cc @@ -6,12 +6,14 @@ #include "base/bind.h" #include "base/bind_helpers.h" -#include "content/renderer/fetchers/resource_fetcher.h" +#include "base/time/time.h" +#include "content/public/renderer/resource_fetcher.h" +#include "third_party/WebKit/public/platform/WebURLResponse.h" -using WebKit::WebFrame; -using WebKit::WebURLError; -using WebKit::WebURLRequest; -using WebKit::WebURLResponse; +using blink::WebFrame; +using blink::WebURLError; +using blink::WebURLRequest; +using blink::WebURLResponse; namespace content { @@ -29,19 +31,16 @@ AltErrorPageResourceFetcher::AltErrorPageResourceFetcher( callback_(callback), original_request_(original_request), original_error_(original_error) { - fetcher_.reset(new ResourceFetcherWithTimeout( - url, frame, WebURLRequest::TargetIsMainFrame, kDownloadTimeoutSec, + fetcher_.reset(ResourceFetcher::Create( + url, frame, WebURLRequest::TargetIsMainFrame, base::Bind(&AltErrorPageResourceFetcher::OnURLFetchComplete, base::Unretained(this)))); + fetcher_->SetTimeout(base::TimeDelta::FromSeconds(kDownloadTimeoutSec)); } AltErrorPageResourceFetcher::~AltErrorPageResourceFetcher() { } -void AltErrorPageResourceFetcher::Cancel() { - fetcher_->Cancel(); -} - void AltErrorPageResourceFetcher::OnURLFetchComplete( const WebURLResponse& response, const std::string& data) { diff --git a/chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.h b/chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.h index 6d828572eec..5f23f288028 100644 --- a/chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.h +++ b/chromium/content/renderer/fetchers/alt_error_page_resource_fetcher.h @@ -11,13 +11,13 @@ #include "third_party/WebKit/public/platform/WebURLRequest.h" #include "url/gurl.h" -namespace WebKit { +namespace blink { class WebFrame; class WebURLResponse; } namespace content { -class ResourceFetcherWithTimeout; +class ResourceFetcher; // Used for downloading alternate dns error pages. Once downloading is done // (or fails), the webview delegate is notified. @@ -26,39 +26,36 @@ class AltErrorPageResourceFetcher { // This will be called when the alternative error page has been fetched, // successfully or not. If there is a failure, the third parameter (the // data) will be empty. - typedef base::Callback<void(WebKit::WebFrame*, - const WebKit::WebURLRequest&, - const WebKit::WebURLError&, + typedef base::Callback<void(blink::WebFrame*, + const blink::WebURLRequest&, + const blink::WebURLError&, const std::string&)> Callback; AltErrorPageResourceFetcher( const GURL& url, - WebKit::WebFrame* frame, - const WebKit::WebURLRequest& original_request, - const WebKit::WebURLError& original_error, + blink::WebFrame* frame, + const blink::WebURLRequest& original_request, + const blink::WebURLError& original_error, const Callback& callback); ~AltErrorPageResourceFetcher(); - // Stop any pending loads. - void Cancel(); - private: - void OnURLFetchComplete(const WebKit::WebURLResponse& response, + void OnURLFetchComplete(const blink::WebURLResponse& response, const std::string& data); // Does the actual fetching. - scoped_ptr<ResourceFetcherWithTimeout> fetcher_; + scoped_ptr<ResourceFetcher> fetcher_; - WebKit::WebFrame* frame_; + blink::WebFrame* frame_; Callback callback_; // The original request. If loading the alternate error page fails, it's // needed to generate the error page. - WebKit::WebURLRequest original_request_; + blink::WebURLRequest original_request_; // The error associated with this load. If there's an error talking with the // alt error page server, we need this to complete the original load. - WebKit::WebURLError original_error_; + blink::WebURLError original_error_; DISALLOW_COPY_AND_ASSIGN(AltErrorPageResourceFetcher); }; diff --git a/chromium/content/renderer/fetchers/image_resource_fetcher.cc b/chromium/content/renderer/fetchers/image_resource_fetcher.cc index 0ce0d4e4242..f43b3d84e84 100644 --- a/chromium/content/renderer/fetchers/image_resource_fetcher.cc +++ b/chromium/content/renderer/fetchers/image_resource_fetcher.cc @@ -8,13 +8,15 @@ #include "base/bind_helpers.h" #include "base/debug/crash_logging.h" #include "content/child/image_decoder.h" +#include "content/public/renderer/resource_fetcher.h" +#include "third_party/WebKit/public/platform/WebURLResponse.h" #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/size.h" -using WebKit::WebFrame; -using WebKit::WebURLRequest; -using WebKit::WebURLResponse; +using blink::WebFrame; +using blink::WebURLRequest; +using blink::WebURLResponse; namespace content { @@ -29,7 +31,7 @@ ImageResourceFetcher::ImageResourceFetcher( id_(id), image_url_(image_url), image_size_(image_size) { - fetcher_.reset(new ResourceFetcher( + fetcher_.reset(ResourceFetcher::Create( image_url, frame, target_type, base::Bind(&ImageResourceFetcher::OnURLFetchComplete, base::Unretained(this)))); @@ -39,8 +41,6 @@ ImageResourceFetcher::ImageResourceFetcher( } ImageResourceFetcher::~ImageResourceFetcher() { - if (!fetcher_->completed()) - fetcher_->Cancel(); } void ImageResourceFetcher::OnURLFetchComplete( diff --git a/chromium/content/renderer/fetchers/image_resource_fetcher.h b/chromium/content/renderer/fetchers/image_resource_fetcher.h index 2ddb20da540..2edcf3296fc 100644 --- a/chromium/content/renderer/fetchers/image_resource_fetcher.h +++ b/chromium/content/renderer/fetchers/image_resource_fetcher.h @@ -7,12 +7,21 @@ #include "base/basictypes.h" #include "base/callback.h" -#include "content/renderer/fetchers/resource_fetcher.h" +#include "base/memory/scoped_ptr.h" +#include "third_party/WebKit/public/platform/WebURLRequest.h" +#include "url/gurl.h" class SkBitmap; +namespace blink { +class WebFrame; +class WebURLResponse; +} + namespace content { +class ResourceFetcher; + // ImageResourceFetcher handles downloading an image for a webview. Once // downloading is done the supplied callback is notified. ImageResourceFetcher // is used to download the favicon and images for web apps. @@ -22,10 +31,10 @@ class ImageResourceFetcher { ImageResourceFetcher( const GURL& image_url, - WebKit::WebFrame* frame, + blink::WebFrame* frame, int id, int image_size, - WebKit::WebURLRequest::TargetType target_type, + blink::WebURLRequest::TargetType target_type, const Callback& callback); virtual ~ImageResourceFetcher(); @@ -38,7 +47,7 @@ class ImageResourceFetcher { private: // ResourceFetcher::Callback. Decodes the image and invokes callback_. - void OnURLFetchComplete(const WebKit::WebURLResponse& response, + void OnURLFetchComplete(const blink::WebURLResponse& response, const std::string& data); Callback callback_; diff --git a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc index 304abe890d7..ea0e6d03052 100644 --- a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc +++ b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc @@ -7,13 +7,15 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "content/child/image_decoder.h" +#include "content/public/renderer/resource_fetcher.h" +#include "third_party/WebKit/public/platform/WebURLResponse.h" #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/size.h" -using WebKit::WebFrame; -using WebKit::WebURLRequest; -using WebKit::WebURLResponse; +using blink::WebFrame; +using blink::WebURLRequest; +using blink::WebURLResponse; namespace content { @@ -27,15 +29,13 @@ MultiResolutionImageResourceFetcher::MultiResolutionImageResourceFetcher( id_(id), http_status_code_(0), image_url_(image_url) { - fetcher_.reset(new ResourceFetcher( + fetcher_.reset(ResourceFetcher::Create( image_url, frame, target_type, base::Bind(&MultiResolutionImageResourceFetcher::OnURLFetchComplete, base::Unretained(this)))); } MultiResolutionImageResourceFetcher::~MultiResolutionImageResourceFetcher() { - if (!fetcher_->completed()) - fetcher_->Cancel(); } void MultiResolutionImageResourceFetcher::OnURLFetchComplete( diff --git a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h index 3e7c326b496..1b329500342 100644 --- a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h +++ b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h @@ -5,28 +5,38 @@ #ifndef CONTENT_RENDERER_FETCHERS_MULTI_RESOLUTION_IMAGE_RESOURCE_FETCHER_H_ #define CONTENT_RENDERER_FETCHERS_MULTI_RESOLUTION_IMAGE_RESOURCE_FETCHER_H_ +#include <string> #include <vector> #include "base/basictypes.h" #include "base/callback.h" -#include "content/renderer/fetchers/resource_fetcher.h" +#include "base/memory/scoped_ptr.h" +#include "third_party/WebKit/public/platform/WebURLRequest.h" +#include "url/gurl.h" class SkBitmap; +namespace blink { +class WebFrame; +class WebURLResponse; +} + namespace content { +class ResourceFetcher; + // A resource fetcher that returns all (differently-sized) frames in // an image. Useful for favicons. -class MultiResolutionImageResourceFetcher{ +class MultiResolutionImageResourceFetcher { public: typedef base::Callback<void(MultiResolutionImageResourceFetcher*, const std::vector<SkBitmap>&)> Callback; MultiResolutionImageResourceFetcher( const GURL& image_url, - WebKit::WebFrame* frame, + blink::WebFrame* frame, int id, - WebKit::WebURLRequest::TargetType target_type, + blink::WebURLRequest::TargetType target_type, const Callback& callback); virtual ~MultiResolutionImageResourceFetcher(); @@ -42,7 +52,7 @@ class MultiResolutionImageResourceFetcher{ private: // ResourceFetcher::Callback. Decodes the image and invokes callback_. - void OnURLFetchComplete(const WebKit::WebURLResponse& response, + void OnURLFetchComplete(const blink::WebURLResponse& response, const std::string& data); Callback callback_; diff --git a/chromium/content/renderer/fetchers/resource_fetcher.h b/chromium/content/renderer/fetchers/resource_fetcher.h deleted file mode 100644 index 5900973adda..00000000000 --- a/chromium/content/renderer/fetchers/resource_fetcher.h +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (c) 2011 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. -// -// A wrapper around ResourceHandle and ResourceHandleClient that simplifies -// the download of an HTTP object. The interface is modeled after URLFetcher -// in the /chrome/browser. -// -// ResourceFetcher::Delegate::OnURLFetchComplete will be called async after -// the ResourceFetcher object is created. - -#ifndef CONTENT_RENDERER_FETCHERS_RESOURCE_FETCHER_H_ -#define CONTENT_RENDERER_FETCHERS_RESOURCE_FETCHER_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/timer/timer.h" -#include "content/common/content_export.h" -#include "third_party/WebKit/public/platform/WebURLLoaderClient.h" -#include "third_party/WebKit/public/platform/WebURLRequest.h" -#include "third_party/WebKit/public/platform/WebURLResponse.h" -#include "url/gurl.h" - -class GURL; - -namespace WebKit { -class WebFrame; -class WebURLLoader; -struct WebURLError; -} - -namespace content { - -class CONTENT_EXPORT ResourceFetcher - : NON_EXPORTED_BASE(public WebKit::WebURLLoaderClient) { - public: - // This will be called when the URL has been fetched, successfully or not. - // If there is a failure, response and data will both be empty. |response| - // and |data| are both valid until the URLFetcher instance is destroyed. - typedef base::Callback<void(const WebKit::WebURLResponse&, - const std::string&)> Callback; - - // We need a frame to make requests. - ResourceFetcher( - const GURL& url, WebKit::WebFrame* frame, - WebKit::WebURLRequest::TargetType target_type, - const Callback& callback); - virtual ~ResourceFetcher(); - - // Stop the request and don't call the callback. - void Cancel(); - - bool completed() const { return completed_; } - - protected: - // WebURLLoaderClient methods: - virtual void willSendRequest( - WebKit::WebURLLoader* loader, WebKit::WebURLRequest& new_request, - const WebKit::WebURLResponse& redirect_response); - virtual void didSendData( - WebKit::WebURLLoader* loader, unsigned long long bytes_sent, - unsigned long long total_bytes_to_be_sent); - virtual void didReceiveResponse( - WebKit::WebURLLoader* loader, const WebKit::WebURLResponse& response); - virtual void didReceiveCachedMetadata( - WebKit::WebURLLoader* loader, const char* data, int data_length); - - virtual void didReceiveData( - WebKit::WebURLLoader* loader, const char* data, int data_length, - int encoded_data_length); - virtual void didFinishLoading( - WebKit::WebURLLoader* loader, double finishTime); - virtual void didFail( - WebKit::WebURLLoader* loader, const WebKit::WebURLError& error); - - scoped_ptr<WebKit::WebURLLoader> loader_; - - // URL we're fetching - GURL url_; - - // Target type - WebKit::WebURLRequest::TargetType target_type_; - - // A copy of the original resource response - WebKit::WebURLResponse response_; - - // Set to true once the request is compelte. - bool completed_; - - private: - // Start the actual download. - void Start(WebKit::WebFrame* frame); - - void RunCallback(const WebKit::WebURLResponse& response, - const std::string& data); - - // Callback when we're done - Callback callback_; - - // Buffer to hold the content from the server. - std::string data_; - - // Buffer to hold metadata from the cache. - std::string metadata_; -}; - -///////////////////////////////////////////////////////////////////////////// -// A resource fetcher with a timeout -class CONTENT_EXPORT ResourceFetcherWithTimeout - : NON_EXPORTED_BASE(public ResourceFetcher) { - public: - ResourceFetcherWithTimeout(const GURL& url, - WebKit::WebFrame* frame, - WebKit::WebURLRequest::TargetType target_type, - int timeout_secs, - const Callback& callback); - virtual ~ResourceFetcherWithTimeout(); - - private: - // Callback for timer that limits how long we wait for the alternate error - // page server. If this timer fires and the request hasn't completed, we - // kill the request. - void TimeoutFired(); - - // Limit how long we wait for the alternate error page server. - base::OneShotTimer<ResourceFetcherWithTimeout> timeout_timer_; -}; - -} // namespace content - -#endif // CONTENT_RENDERER_FETCHERS_RESOURCE_FETCHER_H_ diff --git a/chromium/content/renderer/fetchers/resource_fetcher.cc b/chromium/content/renderer/fetchers/resource_fetcher_impl.cc index 455f59eb272..5c59de3739d 100644 --- a/chromium/content/renderer/fetchers/resource_fetcher.cc +++ b/chromium/content/renderer/fetchers/resource_fetcher_impl.cc @@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/fetchers/resource_fetcher.h" +#include "content/renderer/fetchers/resource_fetcher_impl.h" #include "base/logging.h" +#include "base/time/time.h" #include "third_party/WebKit/public/platform/Platform.h" #include "third_party/WebKit/public/platform/WebURL.h" #include "third_party/WebKit/public/platform/WebURLError.h" @@ -15,51 +16,59 @@ #include "third_party/WebKit/public/web/WebKit.h" using base::TimeDelta; -using WebKit::WebFrame; -using WebKit::WebURLError; -using WebKit::WebURLLoader; -using WebKit::WebURLRequest; -using WebKit::WebURLResponse; +using blink::WebFrame; +using blink::WebURLError; +using blink::WebURLLoader; +using blink::WebURLRequest; +using blink::WebURLResponse; namespace content { -ResourceFetcher::ResourceFetcher(const GURL& url, WebFrame* frame, - WebURLRequest::TargetType target_type, - const Callback& callback) - : url_(url), - target_type_(target_type), - completed_(false), +// static +ResourceFetcher* ResourceFetcher::Create( + const GURL& url, WebFrame* frame, WebURLRequest::TargetType target_type, + const Callback& callback) { + return new ResourceFetcherImpl(url, frame, target_type, callback); +} + +ResourceFetcherImpl::ResourceFetcherImpl(const GURL& url, WebFrame* frame, + WebURLRequest::TargetType target_type, + const Callback& callback) + : completed_(false), callback_(callback) { // Can't do anything without a frame. However, delegate can be NULL (so we // can do a http request and ignore the results). DCHECK(frame); - Start(frame); + Start(url, frame, target_type); } -ResourceFetcher::~ResourceFetcher() { +ResourceFetcherImpl::~ResourceFetcherImpl() { if (!completed_ && loader_) loader_->cancel(); } -void ResourceFetcher::Cancel() { - if (!completed_) { - loader_->cancel(); - completed_ = true; - } +void ResourceFetcherImpl::SetTimeout(const base::TimeDelta& timeout) { + DCHECK(loader_); + DCHECK(!completed_); + timeout_timer_.Start(FROM_HERE, timeout, this, + &ResourceFetcherImpl::TimeoutFired); } -void ResourceFetcher::Start(WebFrame* frame) { - WebURLRequest request(url_); - request.setTargetType(target_type_); +void ResourceFetcherImpl::Start(const GURL& url, WebFrame* frame, + WebURLRequest::TargetType target_type) { + WebURLRequest request(url); + request.setTargetType(target_type); request.setFirstPartyForCookies(frame->document().firstPartyForCookies()); frame->dispatchWillSendRequest(request); - loader_.reset(WebKit::Platform::current()->createURLLoader()); + loader_.reset(blink::Platform::current()->createURLLoader()); loader_->loadAsynchronously(request, this); } -void ResourceFetcher::RunCallback(const WebURLResponse& response, - const std::string& data) { +void ResourceFetcherImpl::RunCallback(const WebURLResponse& response, + const std::string& data) { + completed_ = true; + timeout_timer_.Stop(); if (callback_.is_null()) return; @@ -69,26 +78,32 @@ void ResourceFetcher::RunCallback(const WebURLResponse& response, callback.Run(response, data); } +void ResourceFetcherImpl::TimeoutFired() { + DCHECK(!completed_); + loader_->cancel(); + RunCallback(WebURLResponse(), std::string()); +} + ///////////////////////////////////////////////////////////////////////////// // WebURLLoaderClient methods -void ResourceFetcher::willSendRequest( +void ResourceFetcherImpl::willSendRequest( WebURLLoader* loader, WebURLRequest& new_request, const WebURLResponse& redirect_response) { } -void ResourceFetcher::didSendData( +void ResourceFetcherImpl::didSendData( WebURLLoader* loader, unsigned long long bytes_sent, unsigned long long total_bytes_to_be_sent) { } -void ResourceFetcher::didReceiveResponse( +void ResourceFetcherImpl::didReceiveResponse( WebURLLoader* loader, const WebURLResponse& response) { DCHECK(!completed_); response_ = response; } -void ResourceFetcher::didReceiveData( +void ResourceFetcherImpl::didReceiveData( WebURLLoader* loader, const char* data, int data_length, int encoded_data_length) { DCHECK(!completed_); @@ -97,7 +112,7 @@ void ResourceFetcher::didReceiveData( data_.append(data, data_length); } -void ResourceFetcher::didReceiveCachedMetadata( +void ResourceFetcherImpl::didReceiveCachedMetadata( WebURLLoader* loader, const char* data, int data_length) { DCHECK(!completed_); DCHECK(data_length > 0); @@ -105,41 +120,19 @@ void ResourceFetcher::didReceiveCachedMetadata( metadata_.assign(data, data_length); } -void ResourceFetcher::didFinishLoading( +void ResourceFetcherImpl::didFinishLoading( WebURLLoader* loader, double finishTime) { DCHECK(!completed_); - completed_ = true; RunCallback(response_, data_); } -void ResourceFetcher::didFail(WebURLLoader* loader, const WebURLError& error) { +void ResourceFetcherImpl::didFail(WebURLLoader* loader, + const WebURLError& error) { DCHECK(!completed_); - completed_ = true; // Go ahead and tell our delegate that we're done. RunCallback(WebURLResponse(), std::string()); } -///////////////////////////////////////////////////////////////////////////// -// A resource fetcher with a timeout - -ResourceFetcherWithTimeout::ResourceFetcherWithTimeout( - const GURL& url, WebFrame* frame, WebURLRequest::TargetType target_type, - int timeout_secs, const Callback& callback) - : ResourceFetcher(url, frame, target_type, callback) { - timeout_timer_.Start(FROM_HERE, TimeDelta::FromSeconds(timeout_secs), this, - &ResourceFetcherWithTimeout::TimeoutFired); -} - -ResourceFetcherWithTimeout::~ResourceFetcherWithTimeout() { -} - -void ResourceFetcherWithTimeout::TimeoutFired() { - if (!completed_) { - loader_->cancel(); - didFail(NULL, WebURLError()); - } -} - } // namespace content diff --git a/chromium/content/renderer/fetchers/resource_fetcher_impl.h b/chromium/content/renderer/fetchers/resource_fetcher_impl.h new file mode 100644 index 00000000000..2aa5d23a723 --- /dev/null +++ b/chromium/content/renderer/fetchers/resource_fetcher_impl.h @@ -0,0 +1,102 @@ +// Copyright (c) 2011 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_RENDERER_FETCHERS_RESOURCE_FETCHER_H_ +#define CONTENT_RENDERER_FETCHERS_RESOURCE_FETCHER_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "base/timer/timer.h" +#include "content/public/renderer/resource_fetcher.h" +#include "third_party/WebKit/public/platform/WebURLLoaderClient.h" +#include "third_party/WebKit/public/platform/WebURLRequest.h" +#include "third_party/WebKit/public/platform/WebURLResponse.h" + +class GURL; + +namespace blink { +class WebFrame; +class WebURLLoader; +struct WebURLError; +} + +namespace content { + +class ResourceFetcherImpl : public ResourceFetcher, + public blink::WebURLLoaderClient { + public: + // ResourceFetcher implementation: + virtual void SetTimeout(const base::TimeDelta& timeout) OVERRIDE; + + private: + friend class ResourceFetcher; + + ResourceFetcherImpl( + const GURL& url, blink::WebFrame* frame, + blink::WebURLRequest::TargetType target_type, + const Callback& callback); + + virtual ~ResourceFetcherImpl(); + + // Start the actual download. + void Start(const GURL& url, blink::WebFrame* frame, + blink::WebURLRequest::TargetType target_type); + + void RunCallback(const blink::WebURLResponse& response, + const std::string& data); + + // Callback for timer that limits how long we wait for the server. If this + // timer fires and the request hasn't completed, we kill the request. + void TimeoutFired(); + + // WebURLLoaderClient methods: + virtual void willSendRequest( + blink::WebURLLoader* loader, blink::WebURLRequest& new_request, + const blink::WebURLResponse& redirect_response); + virtual void didSendData( + blink::WebURLLoader* loader, unsigned long long bytes_sent, + unsigned long long total_bytes_to_be_sent); + virtual void didReceiveResponse( + blink::WebURLLoader* loader, const blink::WebURLResponse& response); + virtual void didReceiveCachedMetadata( + blink::WebURLLoader* loader, const char* data, int data_length); + + virtual void didReceiveData( + blink::WebURLLoader* loader, const char* data, int data_length, + int encoded_data_length); + virtual void didFinishLoading( + blink::WebURLLoader* loader, double finishTime); + virtual void didFail( + blink::WebURLLoader* loader, const blink::WebURLError& error); + + scoped_ptr<blink::WebURLLoader> loader_; + + // Set to true once the request is complete. + bool completed_; + + // Buffer to hold the content from the server. + std::string data_; + + // A copy of the original resource response. + blink::WebURLResponse response_; + + // Callback when we're done. + Callback callback_; + + // Buffer to hold metadata from the cache. + std::string metadata_; + + // Limit how long to wait for the server. + base::OneShotTimer<ResourceFetcherImpl> timeout_timer_; + + DISALLOW_COPY_AND_ASSIGN(ResourceFetcherImpl); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_FETCHERS_RESOURCE_FETCHER_H_ diff --git a/chromium/content/renderer/gamepad_shared_memory_reader.cc b/chromium/content/renderer/gamepad_shared_memory_reader.cc index f4e81941ae5..23edeb3a223 100644 --- a/chromium/content/renderer/gamepad_shared_memory_reader.cc +++ b/chromium/content/renderer/gamepad_shared_memory_reader.cc @@ -35,14 +35,14 @@ GamepadSharedMemoryReader::GamepadSharedMemoryReader() static_cast<GamepadHardwareBuffer*>(memory); } -void GamepadSharedMemoryReader::SampleGamepads(WebKit::WebGamepads& gamepads) { +void GamepadSharedMemoryReader::SampleGamepads(blink::WebGamepads& gamepads) { // ========== // DANGER // ========== // // This logic is duplicated in Pepper as well. If you change it, that also // needs to be in sync. See ppapi/proxy/gamepad_resource.cc. - WebKit::WebGamepads read_into; + blink::WebGamepads read_into; TRACE_EVENT0("GAMEPAD", "SampleGamepads"); if (!base::SharedMemory::IsHandleValid(renderer_shared_memory_handle_)) @@ -82,7 +82,7 @@ void GamepadSharedMemoryReader::SampleGamepads(WebKit::WebGamepads& gamepads) { // gamepads to prevent fingerprinting. The actual data is not cleared. // WebKit will only copy out data into the JS buffers for connected // gamepads so this is sufficient. - for (unsigned i = 0; i < WebKit::WebGamepads::itemsLengthCap; i++) + for (unsigned i = 0; i < blink::WebGamepads::itemsLengthCap; i++) gamepads.items[i].connected = false; } } diff --git a/chromium/content/renderer/gamepad_shared_memory_reader.h b/chromium/content/renderer/gamepad_shared_memory_reader.h index 8c10b90797d..08dc41a8c91 100644 --- a/chromium/content/renderer/gamepad_shared_memory_reader.h +++ b/chromium/content/renderer/gamepad_shared_memory_reader.h @@ -17,7 +17,7 @@ class GamepadSharedMemoryReader { public: GamepadSharedMemoryReader(); virtual ~GamepadSharedMemoryReader(); - void SampleGamepads(WebKit::WebGamepads&); + void SampleGamepads(blink::WebGamepads&); private: base::SharedMemoryHandle renderer_shared_memory_handle_; diff --git a/chromium/content/renderer/geolocation_dispatcher.cc b/chromium/content/renderer/geolocation_dispatcher.cc index 57eeeb6b724..a764b6107e2 100644 --- a/chromium/content/renderer/geolocation_dispatcher.cc +++ b/chromium/content/renderer/geolocation_dispatcher.cc @@ -13,11 +13,11 @@ #include "third_party/WebKit/public/web/WebGeolocationPosition.h" #include "third_party/WebKit/public/web/WebGeolocationError.h" -using WebKit::WebGeolocationController; -using WebKit::WebGeolocationError; -using WebKit::WebGeolocationPermissionRequest; -using WebKit::WebGeolocationPermissionRequestManager; -using WebKit::WebGeolocationPosition; +using blink::WebGeolocationController; +using blink::WebGeolocationError; +using blink::WebGeolocationPermissionRequest; +using blink::WebGeolocationPermissionRequestManager; +using blink::WebGeolocationPosition; namespace content { @@ -87,7 +87,7 @@ bool GeolocationDispatcher::lastPosition(WebGeolocationPosition&) { void GeolocationDispatcher::requestPermission( const WebGeolocationPermissionRequest& permissionRequest) { int bridge_id = pending_permissions_->add(permissionRequest); - string16 origin = permissionRequest.securityOrigin().toString(); + base::string16 origin = permissionRequest.securityOrigin().toString(); Send(new GeolocationHostMsg_RequestPermission( routing_id(), bridge_id, GURL(origin))); } @@ -99,7 +99,7 @@ void GeolocationDispatcher::cancelPermissionRequest( int bridge_id; if (!pending_permissions_->remove(permissionRequest, bridge_id)) return; - string16 origin = permissionRequest.securityOrigin().toString(); + base::string16 origin = permissionRequest.securityOrigin().toString(); Send(new GeolocationHostMsg_CancelPermissionRequest( routing_id(), bridge_id, GURL(origin))); } @@ -150,7 +150,7 @@ void GeolocationDispatcher::OnPositionUpdated( } controller_->errorOccurred( WebGeolocationError( - code, WebKit::WebString::fromUTF8(geoposition.error_message))); + code, blink::WebString::fromUTF8(geoposition.error_message))); } } diff --git a/chromium/content/renderer/geolocation_dispatcher.h b/chromium/content/renderer/geolocation_dispatcher.h index bda1ff73e66..5a96070373a 100644 --- a/chromium/content/renderer/geolocation_dispatcher.h +++ b/chromium/content/renderer/geolocation_dispatcher.h @@ -10,7 +10,7 @@ #include "third_party/WebKit/public/web/WebGeolocationClient.h" #include "third_party/WebKit/public/web/WebGeolocationController.h" -namespace WebKit { +namespace blink { class WebGeolocationController; class WebGeolocationPermissionRequest; class WebGeolocationPermissionRequestManager; @@ -25,7 +25,7 @@ struct Geoposition; // WebKit. // It's the complement of GeolocationDispatcherHost (owned by RenderViewHost). class GeolocationDispatcher : public RenderViewObserver, - public WebKit::WebGeolocationClient { + public blink::WebGeolocationClient { public: explicit GeolocationDispatcher(RenderViewImpl* render_view); virtual ~GeolocationDispatcher(); @@ -39,12 +39,12 @@ class GeolocationDispatcher : public RenderViewObserver, virtual void startUpdating(); virtual void stopUpdating(); virtual void setEnableHighAccuracy(bool enable_high_accuracy); - virtual void setController(WebKit::WebGeolocationController* controller); - virtual bool lastPosition(WebKit::WebGeolocationPosition& position); + virtual void setController(blink::WebGeolocationController* controller); + virtual bool lastPosition(blink::WebGeolocationPosition& position); virtual void requestPermission( - const WebKit::WebGeolocationPermissionRequest& permissionRequest); + const blink::WebGeolocationPermissionRequest& permissionRequest); virtual void cancelPermissionRequest( - const WebKit::WebGeolocationPermissionRequest& permissionRequest); + const blink::WebGeolocationPermissionRequest& permissionRequest); // Permission for using geolocation has been set. void OnPermissionSet(int bridge_id, bool is_allowed); @@ -55,9 +55,9 @@ class GeolocationDispatcher : public RenderViewObserver, // The controller_ is valid for the lifetime of the underlying // WebCore::GeolocationController. geolocationDestroyed() is // invoked when the underlying object is destroyed. - scoped_ptr< WebKit::WebGeolocationController> controller_; + scoped_ptr< blink::WebGeolocationController> controller_; - scoped_ptr<WebKit::WebGeolocationPermissionRequestManager> + scoped_ptr<blink::WebGeolocationPermissionRequestManager> pending_permissions_; bool enable_high_accuracy_; bool updating_; diff --git a/chromium/content/renderer/gin_browsertest.cc b/chromium/content/renderer/gin_browsertest.cc new file mode 100644 index 00000000000..3f69fbb8ab8 --- /dev/null +++ b/chromium/content/renderer/gin_browsertest.cc @@ -0,0 +1,95 @@ +// Copyright (c) 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/command_line.h" +#include "content/public/common/content_switches.h" +#include "content/public/test/render_view_test.h" +#include "content/renderer/render_view_impl.h" +#include "gin/handle.h" +#include "gin/per_isolate_data.h" +#include "gin/wrappable.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebKit.h" +#include "third_party/WebKit/public/web/WebView.h" + +namespace content { + +namespace { + +class TestGinObject : public gin::Wrappable<TestGinObject> { + public: + static gin::WrapperInfo kWrapperInfo; + + static gin::Handle<TestGinObject> Create(v8::Isolate* isolate, bool* alive) { + return gin::CreateHandle(isolate, new TestGinObject(alive)); + } + + private: + TestGinObject(bool* alive) : alive_(alive) { *alive_ = true; } + virtual ~TestGinObject() { *alive_ = false; } + + bool* alive_; + + DISALLOW_COPY_AND_ASSIGN(TestGinObject); +}; + +gin::WrapperInfo TestGinObject::kWrapperInfo = { gin::kEmbedderNativeGin }; + +void RegisterTemplates(v8::Isolate* isolate) { + gin::PerIsolateData* data = gin::PerIsolateData::From(isolate); + + v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate); + templ->SetInternalFieldCount(gin::kNumberOfInternalFields); + data->SetObjectTemplate(&TestGinObject::kWrapperInfo, templ); +} + +class GinBrowserTest : public RenderViewTest { + public: + GinBrowserTest() {} + virtual ~GinBrowserTest() {} + + virtual void SetUp() OVERRIDE { + CommandLine::ForCurrentProcess()->AppendSwitchASCII( + switches::kJavaScriptFlags, "--expose_gc"); + + RenderViewTest::SetUp(); + } + + private: + + DISALLOW_COPY_AND_ASSIGN(GinBrowserTest); +}; + +// Test that garbage collection doesn't crash if a gin-wrapped object is +// present. +TEST_F(GinBrowserTest, GinAndGarbageCollection) { + LoadHTML("<!doctype html>"); + + bool alive = false; + + { + v8::Isolate* isolate = blink::mainThreadIsolate(); + v8::HandleScope handle_scope(isolate); + v8::Context::Scope context_scope( + view_->GetWebView()->mainFrame()->mainWorldScriptContext()); + + RegisterTemplates(isolate); + + // We create the object inside a scope so it's not kept alive by a handle + // on the stack. + TestGinObject::Create(isolate, &alive); + } + + CHECK(alive); + + // Should not crash. + v8::V8::LowMemoryNotification(); + + CHECK(!alive); +} + +} // namespace + +} // namespace content diff --git a/chromium/content/renderer/gpu/OWNERS b/chromium/content/renderer/gpu/OWNERS index d73ca877b50..6f39d70c6bf 100644 --- a/chromium/content/renderer/gpu/OWNERS +++ b/chromium/content/renderer/gpu/OWNERS @@ -1,2 +1,2 @@ -apatrick@chromium.org
-kbr@chromium.org
+kbr@chromium.org +piman@chromium.org diff --git a/chromium/content/renderer/gpu/compositor_output_surface.cc b/chromium/content/renderer/gpu/compositor_output_surface.cc index a31bc92757f..3889f467f85 100644 --- a/chromium/content/renderer/gpu/compositor_output_surface.cc +++ b/chromium/content/renderer/gpu/compositor_output_surface.cc @@ -8,6 +8,7 @@ #include "base/message_loop/message_loop_proxy.h" #include "cc/output/compositor_frame.h" #include "cc/output/compositor_frame_ack.h" +#include "cc/output/managed_memory_policy.h" #include "cc/output/output_surface_client.h" #include "content/common/gpu/client/command_buffer_proxy_impl.h" #include "content/common/gpu/client/context_provider_command_buffer.h" @@ -76,7 +77,7 @@ CompositorOutputSurface::CompositorOutputSurface( CompositorOutputSurface::~CompositorOutputSurface() { DCHECK(CalledOnValidThread()); - SetNeedsBeginFrame(false); + SetNeedsBeginImplFrame(false); if (!HasClient()) return; UpdateSmoothnessTakesPriority(false); @@ -98,6 +99,14 @@ bool CompositorOutputSurface::BindToClient( base::Bind(&CompositorOutputSurfaceProxy::OnMessageReceived, output_surface_proxy_)); + if (!context_provider()) { + // Without a GPU context, the memory policy otherwise wouldn't be set. + client->SetMemoryPolicy(cc::ManagedMemoryPolicy( + 64 * 1024 * 1024, + gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE, + cc::ManagedMemoryPolicy::kDefaultNumResourcesLimit)); + } + return true; } @@ -133,7 +142,7 @@ void CompositorOutputSurface::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewMsg_SwapCompositorFrameAck, OnSwapAck); IPC_MESSAGE_HANDLER(ViewMsg_ReclaimCompositorResources, OnReclaimResources); #if defined(OS_ANDROID) - IPC_MESSAGE_HANDLER(ViewMsg_BeginFrame, OnBeginFrame); + IPC_MESSAGE_HANDLER(ViewMsg_BeginFrame, OnBeginImplFrame); #endif IPC_END_MESSAGE_MAP() } @@ -145,16 +154,16 @@ void CompositorOutputSurface::OnUpdateVSyncParameters( } #if defined(OS_ANDROID) -void CompositorOutputSurface::SetNeedsBeginFrame(bool enable) { +void CompositorOutputSurface::SetNeedsBeginImplFrame(bool enable) { DCHECK(CalledOnValidThread()); - if (needs_begin_frame_ != enable) + if (needs_begin_impl_frame_ != enable) Send(new ViewHostMsg_SetNeedsBeginFrame(routing_id_, enable)); - OutputSurface::SetNeedsBeginFrame(enable); + OutputSurface::SetNeedsBeginImplFrame(enable); } -void CompositorOutputSurface::OnBeginFrame(const cc::BeginFrameArgs& args) { +void CompositorOutputSurface::OnBeginImplFrame(const cc::BeginFrameArgs& args) { DCHECK(CalledOnValidThread()); - BeginFrame(args); + BeginImplFrame(args); } #endif // defined(OS_ANDROID) diff --git a/chromium/content/renderer/gpu/compositor_output_surface.h b/chromium/content/renderer/gpu/compositor_output_surface.h index f8c79558501..7afaa519bb8 100644 --- a/chromium/content/renderer/gpu/compositor_output_surface.h +++ b/chromium/content/renderer/gpu/compositor_output_surface.h @@ -54,7 +54,7 @@ class CompositorOutputSurface virtual bool BindToClient(cc::OutputSurfaceClient* client) OVERRIDE; virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE; #if defined(OS_ANDROID) - virtual void SetNeedsBeginFrame(bool enable) OVERRIDE; + virtual void SetNeedsBeginImplFrame(bool enable) OVERRIDE; #endif // TODO(epenner): This seems out of place here and would be a better fit @@ -93,7 +93,7 @@ class CompositorOutputSurface void OnUpdateVSyncParameters( base::TimeTicks timebase, base::TimeDelta interval); #if defined(OS_ANDROID) - void OnBeginFrame(const cc::BeginFrameArgs& args); + void OnBeginImplFrame(const cc::BeginFrameArgs& args); #endif bool Send(IPC::Message* message); diff --git a/chromium/content/renderer/gpu/compositor_software_output_device.cc b/chromium/content/renderer/gpu/compositor_software_output_device.cc index 6132590ecee..c37b958ad9e 100644 --- a/chromium/content/renderer/gpu/compositor_software_output_device.cc +++ b/chromium/content/renderer/gpu/compositor_software_output_device.cc @@ -201,6 +201,9 @@ void CompositorSoftwareOutputDevice::EndPaint( frame_data->size = viewport_size_; frame_data->damage_rect = damage_rect_; frame_data->handle = buffer->handle(); + + CHECK_LE(static_cast<size_t>(frame_data->size.GetArea()) * 4, + buffer->shared_memory()->mapped_size()); } void CompositorSoftwareOutputDevice::ReclaimSoftwareFrame(unsigned id) { diff --git a/chromium/content/renderer/gpu/compositor_software_output_device.h b/chromium/content/renderer/gpu/compositor_software_output_device.h index e658dfb386f..ce21b2b8d5b 100644 --- a/chromium/content/renderer/gpu/compositor_software_output_device.h +++ b/chromium/content/renderer/gpu/compositor_software_output_device.h @@ -49,6 +49,7 @@ private: void* memory() const { return mem_->memory(); } base::SharedMemoryHandle handle() const { return mem_->handle(); } + base::SharedMemory* shared_memory() const { return mem_.get(); } bool free() const { return free_; } void SetFree(bool free) { free_ = free; } diff --git a/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc b/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc index 9d745f9b018..602b6ec6cbf 100644 --- a/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc +++ b/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc @@ -14,8 +14,14 @@ #include "cc/layers/layer.h" #include "content/common/browser_rendering_stats.h" #include "content/common/gpu/gpu_rendering_stats.h" +#include "content/common/input/synthetic_gesture_params.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/renderer/render_thread.h" +#include "content/public/renderer/v8_value_converter.h" #include "content/renderer/gpu/render_widget_compositor.h" +#include "content/renderer/render_thread_impl.h" #include "content/renderer/render_view_impl.h" #include "content/renderer/skia_benchmarking_extension.h" #include "third_party/WebKit/public/web/WebFrame.h" @@ -30,13 +36,13 @@ #include "v8/include/v8.h" #include "webkit/renderer/compositor_bindings/web_rendering_stats_impl.h" -using WebKit::WebCanvas; -using WebKit::WebFrame; -using WebKit::WebImageCache; -using WebKit::WebPrivatePtr; -using WebKit::WebRenderingStatsImpl; -using WebKit::WebSize; -using WebKit::WebView; +using blink::WebCanvas; +using blink::WebFrame; +using blink::WebImageCache; +using blink::WebPrivatePtr; +using blink::WebRenderingStatsImpl; +using blink::WebSize; +using blink::WebView; const char kGpuBenchmarkingExtensionName[] = "v8/GpuBenchmarking"; @@ -100,28 +106,33 @@ class SkPictureSerializer { class RenderingStatsEnumerator : public cc::RenderingStats::Enumerator { public: - RenderingStatsEnumerator(v8::Handle<v8::Object> stats_object) - : stats_object(stats_object) { } + RenderingStatsEnumerator(v8::Isolate* isolate, + v8::Handle<v8::Object> stats_object) + : isolate(isolate), stats_object(stats_object) {} virtual void AddInt64(const char* name, int64 value) OVERRIDE { - stats_object->Set(v8::String::New(name), v8::Number::New(value)); + stats_object->Set(v8::String::NewFromUtf8(isolate, name), + v8::Number::New(isolate, value)); } virtual void AddDouble(const char* name, double value) OVERRIDE { - stats_object->Set(v8::String::New(name), v8::Number::New(value)); + stats_object->Set(v8::String::NewFromUtf8(isolate, name), + v8::Number::New(isolate, value)); } virtual void AddInt(const char* name, int value) OVERRIDE { - stats_object->Set(v8::String::New(name), v8::Integer::New(value)); + stats_object->Set(v8::String::NewFromUtf8(isolate, name), + v8::Integer::New(value)); } virtual void AddTimeDeltaInSecondsF(const char* name, const base::TimeDelta& value) OVERRIDE { - stats_object->Set(v8::String::New(name), - v8::Number::New(value.InSecondsF())); + stats_object->Set(v8::String::NewFromUtf8(isolate, name), + v8::Number::New(isolate, value.InSecondsF())); } private: + v8::Isolate* isolate; v8::Handle<v8::Object> stats_object; }; @@ -157,8 +168,8 @@ class CallbackAndContext : public base::RefCounted<CallbackAndContext> { friend class base::RefCounted<CallbackAndContext>; virtual ~CallbackAndContext() { - callback_.Dispose(); - context_.Dispose(); + callback_.Reset(); + context_.Reset(); } v8::Isolate* isolate_; @@ -167,6 +178,72 @@ class CallbackAndContext : public base::RefCounted<CallbackAndContext> { DISALLOW_COPY_AND_ASSIGN(CallbackAndContext); }; +class GpuBenchmarkingContext { + public: + GpuBenchmarkingContext() + : web_frame_(NULL), + web_view_(NULL), + render_view_impl_(NULL), + compositor_(NULL) {} + + bool Init(bool init_compositor) { + web_frame_ = WebFrame::frameForCurrentContext(); + if (!web_frame_) + return false; + + web_view_ = web_frame_->view(); + if (!web_view_) { + web_frame_ = NULL; + return false; + } + + render_view_impl_ = RenderViewImpl::FromWebView(web_view_); + if (!render_view_impl_) { + web_frame_ = NULL; + web_view_ = NULL; + return false; + } + + if (!init_compositor) + return true; + + compositor_ = render_view_impl_->compositor(); + if (!compositor_) { + web_frame_ = NULL; + web_view_ = NULL; + render_view_impl_ = NULL; + return false; + } + + return true; + } + + WebFrame* web_frame() const { + DCHECK(web_frame_ != NULL); + return web_frame_; + } + WebView* web_view() const { + DCHECK(web_view_ != NULL); + return web_view_; + } + RenderViewImpl* render_view_impl() const { + DCHECK(render_view_impl_ != NULL); + return render_view_impl_; + } + RenderWidgetCompositor* compositor() const { + DCHECK(compositor_ != NULL); + return compositor_; + } + + private: + WebFrame* web_frame_; + WebView* web_view_; + RenderViewImpl* render_view_impl_; + RenderWidgetCompositor* compositor_; + + DISALLOW_COPY_AND_ASSIGN(GpuBenchmarkingContext); +}; + } // namespace class GpuBenchmarkingWrapper : public v8::Extension { @@ -191,37 +268,72 @@ class GpuBenchmarkingWrapper : public v8::Extension { " native function GetRenderingStats();" " return GetRenderingStats();" "};" + "chrome.gpuBenchmarking.gpuRenderingStats = function() {" + " native function GetGpuRenderingStats();" + " return GetGpuRenderingStats();" + "};" "chrome.gpuBenchmarking.printToSkPicture = function(dirname) {" " native function PrintToSkPicture();" " return PrintToSkPicture(dirname);" "};" + "chrome.gpuBenchmarking.DEFAULT_INPUT = 0;" + "chrome.gpuBenchmarking.TOUCH_INPUT = 1;" + "chrome.gpuBenchmarking.MOUSE_INPUT = 2;" "chrome.gpuBenchmarking.smoothScrollBy = " - " function(pixels_to_scroll, opt_callback, opt_mouse_event_x," - " opt_mouse_event_y) {" + " function(pixels_to_scroll, opt_callback, opt_start_x," + " opt_start_y, opt_gesture_source_type," + " opt_direction, opt_speed_in_pixels_s) {" " pixels_to_scroll = pixels_to_scroll || 0;" " callback = opt_callback || function() { };" + " gesture_source_type = opt_gesture_source_type ||" + " chrome.gpuBenchmarking.DEFAULT_INPUT;" + " direction = opt_direction || 'down';" + " speed_in_pixels_s = opt_speed_in_pixels_s || 800;" " native function BeginSmoothScroll();" - " if (typeof opt_mouse_event_x !== 'undefined' &&" - " typeof opt_mouse_event_y !== 'undefined') {" - " return BeginSmoothScroll(pixels_to_scroll >= 0, callback," - " Math.abs(pixels_to_scroll)," - " opt_mouse_event_x, opt_mouse_event_y);" - " } else {" - " return BeginSmoothScroll(pixels_to_scroll >= 0, callback," - " Math.abs(pixels_to_scroll));" - " }" + " return BeginSmoothScroll(pixels_to_scroll, callback," + " gesture_source_type, direction," + " speed_in_pixels_s, true," + " opt_start_x, opt_start_y);" "};" "chrome.gpuBenchmarking.smoothScrollBySendsTouch = function() {" " native function SmoothScrollSendsTouch();" " return SmoothScrollSendsTouch();" "};" + "chrome.gpuBenchmarking.swipe = " + " function(direction, distance, opt_callback," + " opt_start_x, opt_start_y," + " opt_speed_in_pixels_s) {" + " direction = direction || 'up';" + " distance = distance || 0;" + " callback = opt_callback || function() { };" + " speed_in_pixels_s = opt_speed_in_pixels_s || 800;" + " native function BeginSmoothScroll();" + " return BeginSmoothScroll(-distance, callback," + " chrome.gpuBenchmarking.TOUCH_INPUT," + " direction, speed_in_pixels_s, false," + " opt_start_x, opt_start_y);" + "};" "chrome.gpuBenchmarking.pinchBy = " - " function(zoom_in, pixels_to_move, anchor_x, anchor_y," - " opt_callback) {" + " function(zoom_in, pixels_to_cover, anchor_x, anchor_y," + " opt_callback, opt_relative_pointer_speed_in_pixels_s) {" " callback = opt_callback || function() { };" + " relative_pointer_speed_in_pixels_s =" + " opt_relative_pointer_speed_in_pixels_s || 800;" " native function BeginPinch();" - " return BeginPinch(zoom_in, pixels_to_move," - " anchor_x, anchor_y, callback);" + " return BeginPinch(zoom_in, pixels_to_cover," + " anchor_x, anchor_y, callback," + " relative_pointer_speed_in_pixels_s);" + "};" + "chrome.gpuBenchmarking.tap = " + " function(position_x, position_y, opt_callback, opt_duration_ms," + " opt_gesture_source_type) {" + " callback = opt_callback || function() { };" + " duration_ms = opt_duration_ms || 0;" + " gesture_source_type = opt_gesture_source_type ||" + " chrome.gpuBenchmarking.DEFAULT_INPUT;" + " native function BeginTap();" + " return BeginTap(position_x, position_y, callback, duration_ms," + " gesture_source_type);" "};" "chrome.gpuBenchmarking.beginWindowSnapshotPNG = function(callback) {" " native function BeginWindowSnapshotPNG();" @@ -230,99 +342,90 @@ class GpuBenchmarkingWrapper : public v8::Extension { "chrome.gpuBenchmarking.clearImageCache = function() {" " native function ClearImageCache();" " ClearImageCache();" + "};" + "chrome.gpuBenchmarking.runMicroBenchmark =" + " function(name, callback, opt_arguments) {" + " arguments = opt_arguments || {};" + " native function RunMicroBenchmark();" + " return RunMicroBenchmark(name, callback, arguments);" + "};" + "chrome.gpuBenchmarking.hasGpuProcess = function() {" + " native function HasGpuProcess();" + " return HasGpuProcess();" "};") {} - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( + virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate( + v8::Isolate* isolate, v8::Handle<v8::String> name) OVERRIDE { - if (name->Equals(v8::String::New("SetNeedsDisplayOnAllLayers"))) - return v8::FunctionTemplate::New(SetNeedsDisplayOnAllLayers); - if (name->Equals(v8::String::New("SetRasterizeOnlyVisibleContent"))) - return v8::FunctionTemplate::New(SetRasterizeOnlyVisibleContent); - if (name->Equals(v8::String::New("GetRenderingStats"))) - return v8::FunctionTemplate::New(GetRenderingStats); - if (name->Equals(v8::String::New("PrintToSkPicture"))) - return v8::FunctionTemplate::New(PrintToSkPicture); - if (name->Equals(v8::String::New("BeginSmoothScroll"))) - return v8::FunctionTemplate::New(BeginSmoothScroll); - if (name->Equals(v8::String::New("SmoothScrollSendsTouch"))) - return v8::FunctionTemplate::New(SmoothScrollSendsTouch); - if (name->Equals(v8::String::New("BeginPinch"))) - return v8::FunctionTemplate::New(BeginPinch); - if (name->Equals(v8::String::New("BeginWindowSnapshotPNG"))) - return v8::FunctionTemplate::New(BeginWindowSnapshotPNG); - if (name->Equals(v8::String::New("ClearImageCache"))) - return v8::FunctionTemplate::New(ClearImageCache); + if (name->Equals( + v8::String::NewFromUtf8(isolate, "SetNeedsDisplayOnAllLayers"))) + return v8::FunctionTemplate::New(isolate, SetNeedsDisplayOnAllLayers); + if (name->Equals( + v8::String::NewFromUtf8(isolate, "SetRasterizeOnlyVisibleContent"))) + return v8::FunctionTemplate::New(isolate, SetRasterizeOnlyVisibleContent); + if (name->Equals(v8::String::NewFromUtf8(isolate, "GetRenderingStats"))) + return v8::FunctionTemplate::New(isolate, GetRenderingStats); + if (name->Equals(v8::String::NewFromUtf8(isolate, "GetGpuRenderingStats"))) + return v8::FunctionTemplate::New(isolate, GetGpuRenderingStats); + if (name->Equals(v8::String::NewFromUtf8(isolate, "PrintToSkPicture"))) + return v8::FunctionTemplate::New(isolate, PrintToSkPicture); + if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginSmoothScroll"))) + return v8::FunctionTemplate::New(isolate, BeginSmoothScroll); + if (name->Equals( + v8::String::NewFromUtf8(isolate, "SmoothScrollSendsTouch"))) + return v8::FunctionTemplate::New(isolate, SmoothScrollSendsTouch); + if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginPinch"))) + return v8::FunctionTemplate::New(isolate, BeginPinch); + if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginTap"))) + return v8::FunctionTemplate::New(isolate, BeginTap); + if (name->Equals( + v8::String::NewFromUtf8(isolate, "BeginWindowSnapshotPNG"))) + return v8::FunctionTemplate::New(isolate, BeginWindowSnapshotPNG); + if (name->Equals(v8::String::NewFromUtf8(isolate, "ClearImageCache"))) + return v8::FunctionTemplate::New(isolate, ClearImageCache); + if (name->Equals(v8::String::NewFromUtf8(isolate, "RunMicroBenchmark"))) + return v8::FunctionTemplate::New(isolate, RunMicroBenchmark); + if (name->Equals(v8::String::NewFromUtf8(isolate, "HasGpuProcess"))) + return v8::FunctionTemplate::New(isolate, HasGpuProcess); return v8::Handle<v8::FunctionTemplate>(); } static void SetNeedsDisplayOnAllLayers( const v8::FunctionCallbackInfo<v8::Value>& args) { - WebFrame* web_frame = WebFrame::frameForCurrentContext(); - if (!web_frame) - return; - - WebView* web_view = web_frame->view(); - if (!web_view) - return; - - RenderViewImpl* render_view_impl = RenderViewImpl::FromWebView(web_view); - if (!render_view_impl) - return; - - RenderWidgetCompositor* compositor = render_view_impl->compositor(); - if (!compositor) + GpuBenchmarkingContext context; + if (!context.Init(true)) return; - compositor->SetNeedsDisplayOnAllLayers(); + context.compositor()->SetNeedsDisplayOnAllLayers(); } static void SetRasterizeOnlyVisibleContent( const v8::FunctionCallbackInfo<v8::Value>& args) { - WebFrame* web_frame = WebFrame::frameForCurrentContext(); - if (!web_frame) - return; - - WebView* web_view = web_frame->view(); - if (!web_view) - return; - - RenderViewImpl* render_view_impl = RenderViewImpl::FromWebView(web_view); - if (!render_view_impl) + GpuBenchmarkingContext context; + if (!context.Init(true)) return; - RenderWidgetCompositor* compositor = render_view_impl->compositor(); - if (!compositor) - return; - - compositor->SetRasterizeOnlyVisibleContent(); + context.compositor()->SetRasterizeOnlyVisibleContent(); } static void GetRenderingStats( const v8::FunctionCallbackInfo<v8::Value>& args) { - WebFrame* web_frame = WebFrame::frameForCurrentContext(); - if (!web_frame) - return; - - WebView* web_view = web_frame->view(); - if (!web_view) - return; - - RenderViewImpl* render_view_impl = RenderViewImpl::FromWebView(web_view); - if (!render_view_impl) + GpuBenchmarkingContext context; + if (!context.Init(false)) return; WebRenderingStatsImpl stats; - render_view_impl->GetRenderingStats(stats); + context.render_view_impl()->GetRenderingStats(stats); content::GpuRenderingStats gpu_stats; - render_view_impl->GetGpuRenderingStats(&gpu_stats); + context.render_view_impl()->GetGpuRenderingStats(&gpu_stats); BrowserRenderingStats browser_stats; - render_view_impl->GetBrowserRenderingStats(&browser_stats); + context.render_view_impl()->GetBrowserRenderingStats(&browser_stats); v8::Handle<v8::Object> stats_object = v8::Object::New(); - RenderingStatsEnumerator enumerator(stats_object); + RenderingStatsEnumerator enumerator(args.GetIsolate(), stats_object); stats.rendering_stats.EnumerateFields(&enumerator); gpu_stats.EnumerateFields(&enumerator); browser_stats.EnumerateFields(&enumerator); @@ -330,43 +433,50 @@ class GpuBenchmarkingWrapper : public v8::Extension { args.GetReturnValue().Set(stats_object); } - static void PrintToSkPicture( + static void GetGpuRenderingStats( const v8::FunctionCallbackInfo<v8::Value>& args) { - if (args.Length() != 1) - return; - v8::String::AsciiValue dirname(args[0]); - if (dirname.length() == 0) + GpuBenchmarkingContext context; + if (!context.Init(false)) return; - WebFrame* web_frame = WebFrame::frameForCurrentContext(); - if (!web_frame) - return; + content::GpuRenderingStats gpu_stats; + context.render_view_impl()->GetGpuRenderingStats(&gpu_stats); - WebView* web_view = web_frame->view(); - if (!web_view) + v8::Isolate* isolate = args.GetIsolate(); + v8::Handle<v8::Object> stats_object = v8::Object::New(isolate); + RenderingStatsEnumerator enumerator(isolate, stats_object); + gpu_stats.EnumerateFields(&enumerator); + + args.GetReturnValue().Set(stats_object); + } + + static void PrintToSkPicture( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 1) return; - RenderViewImpl* render_view_impl = RenderViewImpl::FromWebView(web_view); - if (!render_view_impl) + v8::String::Utf8Value dirname(args[0]); + if (dirname.length() == 0) return; - RenderWidgetCompositor* compositor = render_view_impl->compositor(); - if (!compositor) + GpuBenchmarkingContext context; + if (!context.Init(true)) return; - const cc::Layer* root_layer = compositor->GetRootLayer(); + const cc::Layer* root_layer = context.compositor()->GetRootLayer(); if (!root_layer) return; base::FilePath dirpath( base::FilePath::StringType(*dirname, *dirname + dirname.length())); - if (!file_util::CreateDirectory(dirpath) || + if (!base::CreateDirectory(dirpath) || !base::PathIsWritable(dirpath)) { std::string msg("Path is not writable: "); msg.append(dirpath.MaybeAsASCII()); - v8::ThrowException(v8::Exception::Error( - v8::String::New(msg.c_str(), msg.length()))); + v8::Isolate* isolate = args.GetIsolate(); + isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8( + isolate, msg.c_str(), v8::String::kNormalString, msg.length()))); return; } @@ -374,7 +484,7 @@ class GpuBenchmarkingWrapper : public v8::Extension { serializer.Serialize(root_layer); } - static void OnSmoothScrollCompleted( + static void OnSyntheticGestureCompleted( CallbackAndContext* callback_and_context) { v8::HandleScope scope(callback_and_context->isolate()); v8::Handle<v8::Context> context = callback_and_context->GetContext(); @@ -398,120 +508,197 @@ class GpuBenchmarkingWrapper : public v8::Extension { static void BeginSmoothScroll( const v8::FunctionCallbackInfo<v8::Value>& args) { - WebFrame* web_frame = WebFrame::frameForCurrentContext(); - if (!web_frame) + GpuBenchmarkingContext context; + if (!context.Init(false)) return; - WebView* web_view = web_frame->view(); - if (!web_view) - return; - - RenderViewImpl* render_view_impl = RenderViewImpl::FromWebView(web_view); - if (!render_view_impl) - return; - - // Account for the 2 optional arguments, mouse_event_x and mouse_event_y. + // The last two arguments can be undefined. We check their validity later. int arglen = args.Length(); - if (arglen < 3 || - !args[0]->IsBoolean() || + if (arglen < 8 || + !args[0]->IsNumber() || !args[1]->IsFunction() || - !args[2]->IsNumber()) { + !args[2]->IsNumber() || + !args[3]->IsString() || + !args[4]->IsNumber() || + !args[5]->IsBoolean()) { args.GetReturnValue().Set(false); return; } - bool scroll_down = args[0]->BooleanValue(); v8::Local<v8::Function> callback_local = v8::Local<v8::Function>::Cast(args[1]); scoped_refptr<CallbackAndContext> callback_and_context = new CallbackAndContext(args.GetIsolate(), callback_local, - web_frame->mainWorldScriptContext()); + context.web_frame()->mainWorldScriptContext()); - int pixels_to_scroll = args[2]->IntegerValue(); + scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params( + new SyntheticSmoothScrollGestureParams); - int mouse_event_x = 0; - int mouse_event_y = 0; + // Convert coordinates from CSS pixels to density independent pixels (DIPs). + float page_scale_factor = context.web_view()->pageScaleFactor(); - if (arglen == 3) { - WebKit::WebRect rect = render_view_impl->windowRect(); - mouse_event_x = rect.x + rect.width / 2; - mouse_event_y = rect.y + rect.height / 2; - } else { - if (arglen != 5 || - !args[3]->IsNumber() || - !args[4]->IsNumber()) { - args.GetReturnValue().Set(false); - return; - } + int gesture_source_type = args[2]->IntegerValue(); + if (gesture_source_type < 0 || + gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) { + args.GetReturnValue().Set(false); + return; + } + gesture_params->gesture_source_type = + static_cast<SyntheticGestureParams::GestureSourceType>( + gesture_source_type); + + int distance = args[0]->IntegerValue() * page_scale_factor; + v8::String::Utf8Value direction(args[3]); + DCHECK(*direction); + std::string direction_str(*direction); + if (direction_str == "down") + gesture_params->distance.set_y(distance); + else if (direction_str == "up") + gesture_params->distance.set_y(-distance); + else if (direction_str == "right") + gesture_params->distance.set_x(distance); + else if (direction_str == "left") + gesture_params->distance.set_x(-distance); + else { + args.GetReturnValue().Set(false); + return; + } - mouse_event_x = args[3]->IntegerValue() * web_view->pageScaleFactor(); - mouse_event_y = args[4]->IntegerValue() * web_view->pageScaleFactor(); + gesture_params->speed_in_pixels_s = args[4]->IntegerValue(); + gesture_params->prevent_fling = args[5]->BooleanValue(); + + // Account for the 2 optional arguments, start_x and start_y. + if (args[6]->IsUndefined() || args[7]->IsUndefined()) { + blink::WebRect rect = context.render_view_impl()->windowRect(); + gesture_params->anchor.SetPoint(rect.width / 2, rect.height / 2); + } else if (args[6]->IsNumber() && args[7]->IsNumber()) { + gesture_params->anchor.SetPoint( + args[6]->IntegerValue() * page_scale_factor, + args[7]->IntegerValue() * page_scale_factor); + } else { + args.GetReturnValue().Set(false); + return; } // TODO(nduca): If the render_view_impl is destroyed while the gesture is in // progress, we will leak the callback and context. This needs to be fixed, // somehow. - render_view_impl->BeginSmoothScroll( - scroll_down, - base::Bind(&OnSmoothScrollCompleted, - callback_and_context), - pixels_to_scroll, - mouse_event_x, - mouse_event_y); + context.render_view_impl()->QueueSyntheticGesture( + gesture_params.PassAs<SyntheticGestureParams>(), + base::Bind(&OnSyntheticGestureCompleted, + callback_and_context)); args.GetReturnValue().Set(true); } static void BeginPinch( const v8::FunctionCallbackInfo<v8::Value>& args) { - WebFrame* web_frame = WebFrame::frameForCurrentContext(); - if (!web_frame) + GpuBenchmarkingContext context; + if (!context.Init(false)) return; - WebView* web_view = web_frame->view(); - if (!web_view) + int arglen = args.Length(); + if (arglen < 6 || + !args[0]->IsBoolean() || + !args[1]->IsNumber() || + !args[2]->IsNumber() || + !args[3]->IsNumber() || + !args[4]->IsFunction() || + !args[5]->IsNumber()) { + args.GetReturnValue().Set(false); return; + } + + scoped_ptr<SyntheticPinchGestureParams> gesture_params( + new SyntheticPinchGestureParams); + + // Convert coordinates from CSS pixels to density independent pixels (DIPs). + float page_scale_factor = context.web_view()->pageScaleFactor(); + + gesture_params->zoom_in = args[0]->BooleanValue(); + gesture_params->total_num_pixels_covered = + args[1]->IntegerValue() * page_scale_factor; + gesture_params->anchor.SetPoint( + args[2]->IntegerValue() * page_scale_factor, + args[3]->IntegerValue() * page_scale_factor); + gesture_params->relative_pointer_speed_in_pixels_s = + args[5]->IntegerValue(); + + v8::Local<v8::Function> callback_local = + v8::Local<v8::Function>::Cast(args[4]); + + scoped_refptr<CallbackAndContext> callback_and_context = + new CallbackAndContext(args.GetIsolate(), + callback_local, + context.web_frame()->mainWorldScriptContext()); - RenderViewImpl* render_view_impl = RenderViewImpl::FromWebView(web_view); - if (!render_view_impl) + + // TODO(nduca): If the render_view_impl is destroyed while the gesture is in + // progress, we will leak the callback and context. This needs to be fixed, + // somehow. + context.render_view_impl()->QueueSyntheticGesture( + gesture_params.PassAs<SyntheticGestureParams>(), + base::Bind(&OnSyntheticGestureCompleted, + callback_and_context)); + + args.GetReturnValue().Set(true); + } + + static void BeginTap( + const v8::FunctionCallbackInfo<v8::Value>& args) { + GpuBenchmarkingContext context; + if (!context.Init(false)) return; int arglen = args.Length(); if (arglen < 5 || - !args[0]->IsBoolean() || + !args[0]->IsNumber() || !args[1]->IsNumber() || - !args[2]->IsNumber() || + !args[2]->IsFunction() || !args[3]->IsNumber() || - !args[4]->IsFunction()) { + !args[4]->IsNumber()) { args.GetReturnValue().Set(false); return; } - bool zoom_in = args[0]->BooleanValue(); - int pixels_to_move = args[1]->IntegerValue(); - int anchor_x = args[2]->IntegerValue(); - int anchor_y = args[3]->IntegerValue(); + scoped_ptr<SyntheticTapGestureParams> gesture_params( + new SyntheticTapGestureParams); + + // Convert coordinates from CSS pixels to density independent pixels (DIPs). + float page_scale_factor = context.web_view()->pageScaleFactor(); + + gesture_params->position.SetPoint( + args[0]->IntegerValue() * page_scale_factor, + args[1]->IntegerValue() * page_scale_factor); + gesture_params->duration_ms = args[3]->IntegerValue(); + + int gesture_source_type = args[4]->IntegerValue(); + if (gesture_source_type < 0 || + gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) { + args.GetReturnValue().Set(false); + return; + } + gesture_params->gesture_source_type = + static_cast<SyntheticGestureParams::GestureSourceType>( + gesture_source_type); v8::Local<v8::Function> callback_local = - v8::Local<v8::Function>::Cast(args[4]); + v8::Local<v8::Function>::Cast(args[2]); scoped_refptr<CallbackAndContext> callback_and_context = new CallbackAndContext(args.GetIsolate(), callback_local, - web_frame->mainWorldScriptContext()); + context.web_frame()->mainWorldScriptContext()); // TODO(nduca): If the render_view_impl is destroyed while the gesture is in // progress, we will leak the callback and context. This needs to be fixed, // somehow. - render_view_impl->BeginPinch( - zoom_in, - pixels_to_move, - anchor_x, - anchor_y, - base::Bind(&OnSmoothScrollCompleted, + context.render_view_impl()->QueueSyntheticGesture( + gesture_params.PassAs<SyntheticGestureParams>(), + base::Bind(&OnSyntheticGestureCompleted, callback_and_context)); args.GetReturnValue().Set(true); @@ -520,7 +707,8 @@ class GpuBenchmarkingWrapper : public v8::Extension { static void OnSnapshotCompleted(CallbackAndContext* callback_and_context, const gfx::Size& size, const std::vector<unsigned char>& png) { - v8::HandleScope scope(callback_and_context->isolate()); + v8::Isolate* isolate = callback_and_context->isolate(); + v8::HandleScope scope(isolate); v8::Handle<v8::Context> context = callback_and_context->GetContext(); v8::Context::Scope context_scope(context); WebFrame* frame = WebFrame::frameForContext(context); @@ -530,24 +718,27 @@ class GpuBenchmarkingWrapper : public v8::Extension { if(!size.IsEmpty()) { v8::Handle<v8::Object> result_object; - result_object = v8::Object::New(); + result_object = v8::Object::New(isolate); - result_object->Set(v8::String::New("width"), - v8::Number::New(size.width())); - result_object->Set(v8::String::New("height"), - v8::Number::New(size.height())); + result_object->Set(v8::String::NewFromUtf8(isolate, "width"), + v8::Number::New(isolate, size.width())); + result_object->Set(v8::String::NewFromUtf8(isolate, "height"), + v8::Number::New(isolate, size.height())); std::string base64_png; base::Base64Encode(base::StringPiece( reinterpret_cast<const char*>(&*png.begin()), png.size()), &base64_png); - result_object->Set(v8::String::New("data"), - v8::String::New(base64_png.c_str(), base64_png.size())); + result_object->Set(v8::String::NewFromUtf8(isolate, "data"), + v8::String::NewFromUtf8(isolate, + base64_png.c_str(), + v8::String::kNormalString, + base64_png.size())); result = result_object; } else { - result = v8::Null(); + result = v8::Null(isolate); } v8::Handle<v8::Value> argv[] = { result }; @@ -559,16 +750,8 @@ class GpuBenchmarkingWrapper : public v8::Extension { static void BeginWindowSnapshotPNG( const v8::FunctionCallbackInfo<v8::Value>& args) { - WebFrame* web_frame = WebFrame::frameForCurrentContext(); - if (!web_frame) - return; - - WebView* web_view = web_frame->view(); - if (!web_view) - return; - - RenderViewImpl* render_view_impl = RenderViewImpl::FromWebView(web_view); - if (!render_view_impl) + GpuBenchmarkingContext context; + if (!context.Init(false)) return; if (!args[0]->IsFunction()) @@ -580,9 +763,9 @@ class GpuBenchmarkingWrapper : public v8::Extension { scoped_refptr<CallbackAndContext> callback_and_context = new CallbackAndContext(args.GetIsolate(), callback_local, - web_frame->mainWorldScriptContext()); + context.web_frame()->mainWorldScriptContext()); - render_view_impl->GetWindowSnapshot( + context.render_view_impl()->GetWindowSnapshot( base::Bind(&OnSnapshotCompleted, callback_and_context)); } @@ -590,6 +773,67 @@ class GpuBenchmarkingWrapper : public v8::Extension { const v8::FunctionCallbackInfo<v8::Value>& args) { WebImageCache::clear(); } + + static void OnMicroBenchmarkCompleted( + CallbackAndContext* callback_and_context, + scoped_ptr<base::Value> result) { + v8::HandleScope scope(callback_and_context->isolate()); + v8::Handle<v8::Context> context = callback_and_context->GetContext(); + v8::Context::Scope context_scope(context); + WebFrame* frame = WebFrame::frameForContext(context); + if (frame) { + scoped_ptr<V8ValueConverter> converter = + make_scoped_ptr(V8ValueConverter::create()); + v8::Handle<v8::Value> value = converter->ToV8Value(result.get(), context); + v8::Handle<v8::Value> argv[] = { value }; + + frame->callFunctionEvenIfScriptDisabled( + callback_and_context->GetCallback(), v8::Object::New(), 1, argv); + } + } + + static void RunMicroBenchmark( + const v8::FunctionCallbackInfo<v8::Value>& args) { + GpuBenchmarkingContext context; + if (!context.Init(true)) { + args.GetReturnValue().Set(false); + return; + } + + if (args.Length() != 3 || + !args[0]->IsString() || + !args[1]->IsFunction() || + !args[2]->IsObject()) { + args.GetReturnValue().Set(false); + return; + } + + v8::Local<v8::Function> callback_local = + v8::Local<v8::Function>::Cast(args[1]); + + scoped_refptr<CallbackAndContext> callback_and_context = + new CallbackAndContext(args.GetIsolate(), + callback_local, + context.web_frame()->mainWorldScriptContext()); + + scoped_ptr<V8ValueConverter> converter = + make_scoped_ptr(V8ValueConverter::create()); + v8::Handle<v8::Context> v8_context = callback_and_context->GetContext(); + scoped_ptr<base::Value> value = + make_scoped_ptr(converter->FromV8Value(args[2], v8_context)); + + v8::String::Utf8Value benchmark(args[0]); + DCHECK(*benchmark); + args.GetReturnValue().Set(context.compositor()->ScheduleMicroBenchmark( + std::string(*benchmark), + value.Pass(), + base::Bind(&OnMicroBenchmarkCompleted, callback_and_context))); + } + + static void HasGpuProcess(const v8::FunctionCallbackInfo<v8::Value>& args) { + GpuChannelHost* gpu_channel = RenderThreadImpl::current()->GetGpuChannel(); + args.GetReturnValue().Set(!!gpu_channel); + } }; v8::Extension* GpuBenchmarkingExtension::Get() { diff --git a/chromium/content/renderer/gpu/mailbox_output_surface.cc b/chromium/content/renderer/gpu/mailbox_output_surface.cc index ce635d3bce0..b23575da9ac 100644 --- a/chromium/content/renderer/gpu/mailbox_output_surface.cc +++ b/chromium/content/renderer/gpu/mailbox_output_surface.cc @@ -5,6 +5,7 @@ #include "content/renderer/gpu/mailbox_output_surface.h" #include "base/logging.h" +#include "cc/base/util.h" #include "cc/output/compositor_frame.h" #include "cc/output/compositor_frame_ack.h" #include "cc/output/gl_frame_data.h" @@ -53,7 +54,7 @@ MailboxOutputSurface::~MailboxOutputSurface() { void MailboxOutputSurface::EnsureBackbuffer() { is_backbuffer_discarded_ = false; - WebKit::WebGraphicsContext3D* context3d = context_provider_->Context3d(); + blink::WebGraphicsContext3D* context3d = context_provider_->Context3d(); if (!current_backing_.texture_id) { // Find a texture of matching size to recycle. @@ -86,12 +87,12 @@ void MailboxOutputSurface::EnsureBackbuffer() { context3d->texImage2D( GL_TEXTURE_2D, 0, - ResourceProvider::GetGLInternalFormat(format_), + GLInternalFormat(format_), surface_size_.width(), surface_size_.height(), 0, - ResourceProvider::GetGLDataFormat(format_), - ResourceProvider::GetGLDataType(format_), + GLDataFormat(format_), + GLDataType(format_), NULL); context3d->genMailboxCHROMIUM(current_backing_.mailbox.name); context3d->produceTextureCHROMIUM( @@ -103,7 +104,7 @@ void MailboxOutputSurface::EnsureBackbuffer() { void MailboxOutputSurface::DiscardBackbuffer() { is_backbuffer_discarded_ = true; - WebKit::WebGraphicsContext3D* context3d = context_provider_->Context3d(); + blink::WebGraphicsContext3D* context3d = context_provider_->Context3d(); if (current_backing_.texture_id) { context3d->deleteTexture(current_backing_.texture_id); @@ -137,7 +138,7 @@ void MailboxOutputSurface::BindFramebuffer() { EnsureBackbuffer(); DCHECK(current_backing_.texture_id); - WebKit::WebGraphicsContext3D* context3d = context_provider_->Context3d(); + blink::WebGraphicsContext3D* context3d = context_provider_->Context3d(); if (!fbo_) fbo_ = context3d->createFramebuffer(); diff --git a/chromium/content/renderer/gpu/render_widget_compositor.cc b/chromium/content/renderer/gpu/render_widget_compositor.cc index 2d5401e70b7..90ae2feaad7 100644 --- a/chromium/content/renderer/gpu/render_widget_compositor.cc +++ b/chromium/content/renderer/gpu/render_widget_compositor.cc @@ -16,26 +16,34 @@ #include "base/strings/string_number_conversions.h" #include "base/synchronization/lock.h" #include "base/time/time.h" +#include "base/values.h" +#include "cc/base/latency_info_swap_promise.h" +#include "cc/base/latency_info_swap_promise_monitor.h" #include "cc/base/switches.h" #include "cc/debug/layer_tree_debug_state.h" +#include "cc/debug/micro_benchmark.h" #include "cc/layers/layer.h" #include "cc/trees/layer_tree_host.h" #include "content/common/gpu/client/context_provider_command_buffer.h" #include "content/public/common/content_switches.h" -#include "content/renderer/gpu/input_handler_manager.h" +#include "content/renderer/input/input_handler_manager.h" #include "content/renderer/render_thread_impl.h" #include "third_party/WebKit/public/platform/WebSize.h" #include "third_party/WebKit/public/web/WebWidget.h" #include "ui/gl/gl_switches.h" #include "webkit/renderer/compositor_bindings/web_layer_impl.h" +namespace base { +class Value; +} + namespace cc { class Layer; } -using WebKit::WebFloatPoint; -using WebKit::WebSize; -using WebKit::WebRect; +using blink::WebFloatPoint; +using blink::WebSize; +using blink::WebRect; namespace content { namespace { @@ -59,26 +67,6 @@ bool GetSwitchValueAsInt( } } -bool GetSwitchValueAsFloat( - const CommandLine& command_line, - const std::string& switch_string, - float min_value, - float max_value, - float* result) { - std::string string_value = command_line.GetSwitchValueASCII(switch_string); - double double_value; - if (base::StringToDouble(string_value, &double_value) && - double_value >= min_value && double_value <= max_value) { - *result = static_cast<float>(double_value); - return true; - } else { - LOG(WARNING) << "Failed to parse switch " << switch_string << ": " << - string_value; - return false; - } -} - - } // namespace // static @@ -98,7 +86,7 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create( settings.throttle_frame_production = !cmd->HasSwitch(switches::kDisableGpuVsync); - settings.begin_frame_scheduling_enabled = + settings.begin_impl_frame_scheduling_enabled = cmd->HasSwitch(switches::kEnableBeginFrameScheduling); settings.deadline_scheduling_enabled = cmd->HasSwitch(switches::kEnableDeadlineScheduling) && @@ -109,8 +97,8 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create( cmd->HasSwitch(cc::switches::kEnablePerTilePainting); settings.accelerated_animation_enabled = !cmd->HasSwitch(cc::switches::kDisableThreadedAnimation); - settings.force_direct_layer_drawing = - cmd->HasSwitch(cc::switches::kForceDirectLayerDrawing); + settings.touch_hit_testing = + !cmd->HasSwitch(cc::switches::kDisableCompositorTouchHitTesting); int default_tile_width = settings.default_tile_size.width(); if (cmd->HasSwitch(switches::kDefaultTileWidth)) { @@ -142,6 +130,7 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create( max_untiled_layer_height); settings.impl_side_painting = cc::switches::IsImplSidePaintingEnabled(); + settings.gpu_rasterization = cc::switches::IsGPURasterizationEnabled(); settings.calculate_top_controls_position = cmd->HasSwitch(cc::switches::kEnableTopControlsPositionCalculation); @@ -196,6 +185,8 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create( cmd->HasSwitch(cc::switches::kShowCompositedLayerBorders); settings.initial_debug_state.show_fps_counter = cmd->HasSwitch(cc::switches::kShowFPSCounter); + settings.initial_debug_state.show_layer_animation_bounds_rects = + cmd->HasSwitch(cc::switches::kShowLayerAnimationBounds); settings.initial_debug_state.show_paint_rects = cmd->HasSwitch(switches::kShowPaintRects); settings.initial_debug_state.show_property_changed_rects = @@ -235,15 +226,6 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create( settings.num_raster_threads = num_raster_threads; } - if (cmd->HasSwitch(cc::switches::kLowResolutionContentsScaleFactor)) { - const int kMinScaleFactor = settings.minimum_contents_scale; - const int kMaxScaleFactor = 1; - GetSwitchValueAsFloat(*cmd, - cc::switches::kLowResolutionContentsScaleFactor, - kMinScaleFactor, kMaxScaleFactor, - &settings.low_res_contents_scale_factor); - } - if (cmd->HasSwitch(cc::switches::kMaxTilesForInterestArea)) { int max_tiles_for_interest_area; if (GetSwitchValueAsInt(*cmd, @@ -274,7 +256,6 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create( // TODO(danakj): Move these to the android code. settings.max_partial_texture_updates = 0; settings.scrollbar_animator = cc::LayerTreeSettings::LinearFade; - settings.solid_color_scrollbars = true; settings.solid_color_scrollbar_color = cmd->HasSwitch(switches::kHideScrollbars) ? SK_ColorTRANSPARENT @@ -283,6 +264,7 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create( // Android WebView handles root layer flings itself. settings.ignore_root_layer_flings = widget->UsingSynchronousRendererCompositor(); + settings.always_overscroll = widget->UsingSynchronousRendererCompositor(); // RGBA_4444 textures are only enabled for low end devices // and are disabled for Android WebView as it doesn't support the format. settings.use_rgba_4444_textures = @@ -292,7 +274,6 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create( #elif !defined(OS_MACOSX) if (cmd->HasSwitch(switches::kEnableOverlayScrollbars)) { settings.scrollbar_animator = cc::LayerTreeSettings::Thinning; - settings.solid_color_scrollbars = true; } if (cmd->HasSwitch(cc::switches::kEnablePinchVirtualViewport) || cmd->HasSwitch(switches::kEnableOverlayScrollbars)) { @@ -300,7 +281,7 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create( } #endif - if (!compositor->initialize(settings)) + if (!compositor->Initialize(settings)) return scoped_ptr<RenderWidgetCompositor>(); return compositor.Pass(); @@ -333,6 +314,10 @@ void RenderWidgetCompositor::SetSuppressScheduleComposite(bool suppress) { suppress_schedule_composite_ = suppress; } +bool RenderWidgetCompositor::BeginMainFrameRequested() const { + return layer_tree_host_->BeginMainFrameRequested(); +} + void RenderWidgetCompositor::Animate(base::TimeTicks time) { layer_tree_host_->UpdateClientAnimations(time); } @@ -373,9 +358,17 @@ void RenderWidgetCompositor::SetNeedsRedrawRect(gfx::Rect damage_rect) { layer_tree_host_->SetNeedsRedrawRect(damage_rect); } -void RenderWidgetCompositor::SetLatencyInfo( - const ui::LatencyInfo& latency_info) { - layer_tree_host_->SetLatencyInfo(latency_info); +void RenderWidgetCompositor::SetNeedsForcedRedraw() { + layer_tree_host_->SetNextCommitForcesRedraw(); + setNeedsAnimate(); +} + +scoped_ptr<cc::SwapPromiseMonitor> +RenderWidgetCompositor::CreateLatencyInfoSwapPromiseMonitor( + ui::LatencyInfo* latency) { + return scoped_ptr<cc::SwapPromiseMonitor>( + new cc::LatencyInfoSwapPromiseMonitor( + latency, layer_tree_host_.get(), NULL)); } int RenderWidgetCompositor::GetLayerTreeId() const { @@ -390,12 +383,23 @@ const cc::Layer* RenderWidgetCompositor::GetRootLayer() const { return layer_tree_host_->root_layer(); } -bool RenderWidgetCompositor::initialize(cc::LayerTreeSettings settings) { +bool RenderWidgetCompositor::ScheduleMicroBenchmark( + const std::string& name, + scoped_ptr<base::Value> value, + const base::Callback<void(scoped_ptr<base::Value>)>& callback) { + return layer_tree_host_->ScheduleMicroBenchmark(name, value.Pass(), callback); +} + +bool RenderWidgetCompositor::Initialize(cc::LayerTreeSettings settings) { scoped_refptr<base::MessageLoopProxy> compositor_message_loop_proxy = RenderThreadImpl::current()->compositor_message_loop_proxy(); - layer_tree_host_ = cc::LayerTreeHost::Create(this, - settings, - compositor_message_loop_proxy); + if (compositor_message_loop_proxy.get()) { + layer_tree_host_ = cc::LayerTreeHost::CreateThreaded( + this, NULL, settings, compositor_message_loop_proxy); + } else { + layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded( + this, this, NULL, settings); + } return layer_tree_host_; } @@ -403,7 +407,7 @@ void RenderWidgetCompositor::setSurfaceReady() { layer_tree_host_->SetLayerTreeHostClientReady(); } -void RenderWidgetCompositor::setRootLayer(const WebKit::WebLayer& layer) { +void RenderWidgetCompositor::setRootLayer(const blink::WebLayer& layer) { layer_tree_host_->SetRootLayer( static_cast<const webkit::WebLayerImpl*>(&layer)->layer()); } @@ -439,7 +443,7 @@ float RenderWidgetCompositor::deviceScaleFactor() const { return layer_tree_host_->device_scale_factor(); } -void RenderWidgetCompositor::setBackgroundColor(WebKit::WebColor color) { +void RenderWidgetCompositor::setBackgroundColor(blink::WebColor color) { layer_tree_host_->set_background_color(color); } @@ -462,7 +466,7 @@ void RenderWidgetCompositor::setPageScaleFactorAndLimits( } void RenderWidgetCompositor::startPageScaleAnimation( - const WebKit::WebPoint& destination, + const blink::WebPoint& destination, bool use_anchor, float new_page_scale, double duration_sec) { @@ -479,13 +483,6 @@ void RenderWidgetCompositor::setNeedsAnimate() { layer_tree_host_->SetNeedsAnimate(); } -void RenderWidgetCompositor::setNeedsRedraw() { - if (threaded_) - layer_tree_host_->SetNeedsAnimate(); - else - widget_->scheduleAnimation(); -} - bool RenderWidgetCompositor::commitRequested() const { return layer_tree_host_->CommitRequested(); } @@ -494,16 +491,16 @@ void RenderWidgetCompositor::didStopFlinging() { layer_tree_host_->DidStopFlinging(); } -void RenderWidgetCompositor::registerForAnimations(WebKit::WebLayer* layer) { +void RenderWidgetCompositor::registerForAnimations(blink::WebLayer* layer) { cc::Layer* cc_layer = static_cast<webkit::WebLayerImpl*>(layer)->layer(); cc_layer->layer_animation_controller()->SetAnimationRegistrar( layer_tree_host_->animation_registrar()); } void RenderWidgetCompositor::registerViewportLayers( - const WebKit::WebLayer* pageScaleLayer, - const WebKit::WebLayer* innerViewportScrollLayer, - const WebKit::WebLayer* outerViewportScrollLayer) { + const blink::WebLayer* pageScaleLayer, + const blink::WebLayer* innerViewportScrollLayer, + const blink::WebLayer* outerViewportScrollLayer) { layer_tree_host_->RegisterViewportLayers( static_cast<const webkit::WebLayerImpl*>(pageScaleLayer)->layer(), static_cast<const webkit::WebLayerImpl*>(innerViewportScrollLayer) @@ -567,12 +564,12 @@ void RenderWidgetCompositor::setShowScrollBottleneckRects(bool show) { layer_tree_host_->SetDebugState(debug_state); } -void RenderWidgetCompositor::WillBeginFrame() { - widget_->InstrumentWillBeginFrame(); +void RenderWidgetCompositor::WillBeginMainFrame(int frame_id) { + widget_->InstrumentWillBeginFrame(frame_id); widget_->willBeginCompositorFrame(); } -void RenderWidgetCompositor::DidBeginFrame() { +void RenderWidgetCompositor::DidBeginMainFrame() { widget_->InstrumentDidBeginFrame(); } @@ -614,6 +611,13 @@ void RenderWidgetCompositor::DidCommitAndDrawFrame() { void RenderWidgetCompositor::DidCompleteSwapBuffers() { widget_->didCompleteSwapBuffers(); + if (!threaded_) + widget_->OnSwapBuffersComplete(); +} + +scoped_refptr<cc::ContextProvider> +RenderWidgetCompositor::OffscreenContextProvider() { + return RenderThreadImpl::current()->OffscreenCompositorContextProvider(); } void RenderWidgetCompositor::ScheduleComposite() { @@ -621,15 +625,22 @@ void RenderWidgetCompositor::ScheduleComposite() { widget_->scheduleComposite(); } -scoped_refptr<cc::ContextProvider> -RenderWidgetCompositor::OffscreenContextProviderForMainThread() { - return RenderThreadImpl::current()->OffscreenContextProviderForMainThread(); +void RenderWidgetCompositor::ScheduleAnimation() { + widget_->scheduleAnimation(); } -scoped_refptr<cc::ContextProvider> -RenderWidgetCompositor::OffscreenContextProviderForCompositorThread() { - return RenderThreadImpl::current()-> - OffscreenContextProviderForCompositorThread(); +void RenderWidgetCompositor::DidPostSwapBuffers() { + widget_->OnSwapBuffersPosted(); +} + +void RenderWidgetCompositor::DidAbortSwapBuffers() { + widget_->OnSwapBuffersAborted(); +} + +void RenderWidgetCompositor::RateLimitSharedMainThreadContext() { + cc::ContextProvider* provider = + RenderThreadImpl::current()->SharedMainThreadContextProvider().get(); + provider->Context3d()->rateLimitOffscreenContextCHROMIUM(); } } // namespace content diff --git a/chromium/content/renderer/gpu/render_widget_compositor.h b/chromium/content/renderer/gpu/render_widget_compositor.h index 060d0b85e9e..941fe3173b8 100644 --- a/chromium/content/renderer/gpu/render_widget_compositor.h +++ b/chromium/content/renderer/gpu/render_widget_compositor.h @@ -5,11 +5,15 @@ #ifndef CONTENT_RENDERER_GPU_RENDER_WIDGET_COMPOSITOR_H_ #define CONTENT_RENDERER_GPU_RENDER_WIDGET_COMPOSITOR_H_ +#include "base/callback.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" +#include "base/values.h" +#include "cc/base/swap_promise_monitor.h" #include "cc/debug/rendering_stats.h" #include "cc/input/top_controls_state.h" #include "cc/trees/layer_tree_host_client.h" +#include "cc/trees/layer_tree_host_single_thread_client.h" #include "cc/trees/layer_tree_settings.h" #include "third_party/WebKit/public/platform/WebLayerTreeView.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -28,8 +32,9 @@ class LayerTreeHost; namespace content { class RenderWidget; -class RenderWidgetCompositor : public WebKit::WebLayerTreeView, - public cc::LayerTreeHostClient { +class RenderWidgetCompositor : public blink::WebLayerTreeView, + public cc::LayerTreeHostClient, + public cc::LayerTreeHostSingleThreadClient { public: // Attempt to construct and initialize a compositor instance for the widget // with the given settings. Returns NULL if initialization fails. @@ -40,6 +45,7 @@ class RenderWidgetCompositor : public WebKit::WebLayerTreeView, const base::WeakPtr<cc::InputHandler>& GetInputHandler(); void SetSuppressScheduleComposite(bool suppress); + bool BeginMainFrameRequested() const; void Animate(base::TimeTicks time); void Composite(base::TimeTicks frame_begin_time); void SetNeedsDisplayOnAllLayers(); @@ -50,49 +56,61 @@ class RenderWidgetCompositor : public WebKit::WebLayerTreeView, bool animate); void SetOverdrawBottomHeight(float overdraw_bottom_height); void SetNeedsRedrawRect(gfx::Rect damage_rect); - void SetLatencyInfo(const ui::LatencyInfo& latency_info); + // Like setNeedsRedraw but forces the frame to be drawn, without early-outs. + // Redraw will be forced after the next commit + void SetNeedsForcedRedraw(); + // Calling CreateLatencyInfoSwapPromiseMonitor() to get a scoped + // LatencyInfoSwapPromiseMonitor. During the life time of the + // LatencyInfoSwapPromiseMonitor, if SetNeedsCommit() or SetNeedsUpdateLayer() + // is called on LayerTreeHost, the original latency info will be turned + // into a LatencyInfoSwapPromise. + scoped_ptr<cc::SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor( + ui::LatencyInfo* latency); int GetLayerTreeId() const; void NotifyInputThrottledUntilCommit(); const cc::Layer* GetRootLayer() const; + bool ScheduleMicroBenchmark( + const std::string& name, + scoped_ptr<base::Value> value, + const base::Callback<void(scoped_ptr<base::Value>)>& callback); // WebLayerTreeView implementation. virtual void setSurfaceReady(); - virtual void setRootLayer(const WebKit::WebLayer& layer); + virtual void setRootLayer(const blink::WebLayer& layer); virtual void clearRootLayer(); virtual void setViewportSize( - const WebKit::WebSize& unused_deprecated, - const WebKit::WebSize& device_viewport_size); - virtual WebKit::WebSize layoutViewportSize() const; - virtual WebKit::WebSize deviceViewportSize() const; - virtual WebKit::WebFloatPoint adjustEventPointForPinchZoom( - const WebKit::WebFloatPoint& point) const; + const blink::WebSize& unused_deprecated, + const blink::WebSize& device_viewport_size); + virtual blink::WebSize layoutViewportSize() const; + virtual blink::WebSize deviceViewportSize() const; + virtual blink::WebFloatPoint adjustEventPointForPinchZoom( + const blink::WebFloatPoint& point) const; virtual void setDeviceScaleFactor(float device_scale); virtual float deviceScaleFactor() const; - virtual void setBackgroundColor(WebKit::WebColor color); + virtual void setBackgroundColor(blink::WebColor color); virtual void setHasTransparentBackground(bool transparent); virtual void setOverhangBitmap(const SkBitmap& bitmap); virtual void setVisible(bool visible); virtual void setPageScaleFactorAndLimits(float page_scale_factor, float minimum, float maximum); - virtual void startPageScaleAnimation(const WebKit::WebPoint& destination, + virtual void startPageScaleAnimation(const blink::WebPoint& destination, bool use_anchor, float new_page_scale, double duration_sec); virtual void setNeedsAnimate(); - virtual void setNeedsRedraw(); virtual bool commitRequested() const; virtual void didStopFlinging(); - virtual bool compositeAndReadback(void *pixels, const WebKit::WebRect& rect); + virtual bool compositeAndReadback(void *pixels, const blink::WebRect& rect); virtual void finishAllRendering(); virtual void setDeferCommits(bool defer_commits); - virtual void registerForAnimations(WebKit::WebLayer* layer); + virtual void registerForAnimations(blink::WebLayer* layer); virtual void registerViewportLayers( - const WebKit::WebLayer* pageScaleLayer, - const WebKit::WebLayer* innerViewportScrollLayer, - const WebKit::WebLayer* outerViewportScrollLayer) OVERRIDE; + const blink::WebLayer* pageScaleLayer, + const blink::WebLayer* innerViewportScrollLayer, + const blink::WebLayer* outerViewportScrollLayer) OVERRIDE; virtual void clearViewportLayers() OVERRIDE; - virtual void renderingStats(WebKit::WebRenderingStats& stats) const {} + virtual void renderingStats(blink::WebRenderingStats& stats) const {} virtual void setShowFPSCounter(bool show); virtual void setShowPaintRects(bool show); virtual void setShowDebugBorders(bool show); @@ -100,8 +118,8 @@ class RenderWidgetCompositor : public WebKit::WebLayerTreeView, virtual void setShowScrollBottleneckRects(bool show); // cc::LayerTreeHostClient implementation. - virtual void WillBeginFrame() OVERRIDE; - virtual void DidBeginFrame() OVERRIDE; + virtual void WillBeginMainFrame(int frame_id) OVERRIDE; + virtual void DidBeginMainFrame() OVERRIDE; virtual void Animate(double frame_begin_time) OVERRIDE; virtual void Layout() OVERRIDE; virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta, @@ -113,16 +131,20 @@ class RenderWidgetCompositor : public WebKit::WebLayerTreeView, virtual void DidCommit() OVERRIDE; virtual void DidCommitAndDrawFrame() OVERRIDE; virtual void DidCompleteSwapBuffers() OVERRIDE; - virtual void ScheduleComposite() OVERRIDE; - virtual scoped_refptr<cc::ContextProvider> - OffscreenContextProviderForMainThread() OVERRIDE; virtual scoped_refptr<cc::ContextProvider> - OffscreenContextProviderForCompositorThread() OVERRIDE; + OffscreenContextProvider() OVERRIDE; + virtual void RateLimitSharedMainThreadContext() OVERRIDE; + + // cc::LayerTreeHostSingleThreadClient implementation. + virtual void ScheduleComposite() OVERRIDE; + virtual void ScheduleAnimation() OVERRIDE; + virtual void DidPostSwapBuffers() OVERRIDE; + virtual void DidAbortSwapBuffers() OVERRIDE; private: RenderWidgetCompositor(RenderWidget* widget, bool threaded); - bool initialize(cc::LayerTreeSettings settings); + bool Initialize(cc::LayerTreeSettings settings); bool threaded_; bool suppress_schedule_composite_; diff --git a/chromium/content/renderer/ico_image_decoder_unittest.cc b/chromium/content/renderer/ico_image_decoder_unittest.cc index 83f5a3f161f..4beca93b05d 100644 --- a/chromium/content/renderer/ico_image_decoder_unittest.cc +++ b/chromium/content/renderer/ico_image_decoder_unittest.cc @@ -6,15 +6,15 @@ #include "content/test/image_decoder_test.h" #include "third_party/WebKit/public/web/WebImageDecoder.h" -using WebKit::WebImageDecoder; +using blink::WebImageDecoder; class ICOImageDecoderTest : public ImageDecoderTest { public: ICOImageDecoderTest() : ImageDecoderTest("ico") { } protected: - virtual WebKit::WebImageDecoder* CreateWebKitImageDecoder() const OVERRIDE { - return new WebKit::WebImageDecoder(WebKit::WebImageDecoder::TypeICO); + virtual blink::WebImageDecoder* CreateWebKitImageDecoder() const OVERRIDE { + return new blink::WebImageDecoder(blink::WebImageDecoder::TypeICO); } }; diff --git a/chromium/content/renderer/idle_user_detector.cc b/chromium/content/renderer/idle_user_detector.cc index 0f138a8d46f..dff78d1ab07 100644 --- a/chromium/content/renderer/idle_user_detector.cc +++ b/chromium/content/renderer/idle_user_detector.cc @@ -25,7 +25,7 @@ bool IdleUserDetector::OnMessageReceived(const IPC::Message& message) { return false; } -void IdleUserDetector::OnHandleInputEvent(const WebKit::WebInputEvent* event, +void IdleUserDetector::OnHandleInputEvent(const blink::WebInputEvent* event, const ui::LatencyInfo& latency_info, bool is_keyboard_shortcut) { if (GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden()) { diff --git a/chromium/content/renderer/idle_user_detector.h b/chromium/content/renderer/idle_user_detector.h index 500d8f752a0..a5ee80bdd29 100644 --- a/chromium/content/renderer/idle_user_detector.h +++ b/chromium/content/renderer/idle_user_detector.h @@ -8,7 +8,7 @@ #include "base/basictypes.h" #include "content/public/renderer/render_view_observer.h" -namespace WebKit { +namespace blink { class WebInputEvent; } @@ -29,7 +29,7 @@ class IdleUserDetector : public RenderViewObserver { // RenderViewObserver implementation: virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - void OnHandleInputEvent(const WebKit::WebInputEvent* event, + void OnHandleInputEvent(const blink::WebInputEvent* event, const ui::LatencyInfo& latency_info, bool is_keyboard_shortcut); diff --git a/chromium/content/renderer/image_loading_helper.cc b/chromium/content/renderer/image_loading_helper.cc index 22a36c8a48b..8f403bb9143 100644 --- a/chromium/content/renderer/image_loading_helper.cc +++ b/chromium/content/renderer/image_loading_helper.cc @@ -20,12 +20,11 @@ #include "ui/gfx/favicon_size.h" #include "ui/gfx/size.h" #include "ui/gfx/skbitmap_operations.h" -#include "webkit/glue/webkit_glue.h" -using WebKit::WebFrame; -using WebKit::WebVector; -using WebKit::WebURL; -using WebKit::WebURLRequest; +using blink::WebFrame; +using blink::WebVector; +using blink::WebURL; +using blink::WebURLRequest; namespace { diff --git a/chromium/content/renderer/input/OWNERS b/chromium/content/renderer/input/OWNERS new file mode 100644 index 00000000000..d012c830472 --- /dev/null +++ b/chromium/content/renderer/input/OWNERS @@ -0,0 +1,2 @@ +aelias@chromium.org +jdduke@chromium.org diff --git a/chromium/content/renderer/gpu/input_event_filter.cc b/chromium/content/renderer/input/input_event_filter.cc index 208c47180f9..a0399783988 100644 --- a/chromium/content/renderer/gpu/input_event_filter.cc +++ b/chromium/content/renderer/input/input_event_filter.cc @@ -1,20 +1,22 @@ -// 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. +#include "content/renderer/input/input_event_filter.h" + #include "base/bind.h" #include "base/command_line.h" #include "base/debug/trace_event.h" #include "base/location.h" #include "base/message_loop/message_loop_proxy.h" #include "cc/input/input_handler.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/renderer/gpu/input_event_filter.h" #include "ui/gfx/vector2d_f.h" -using WebKit::WebInputEvent; +using blink::WebInputEvent; namespace content { @@ -131,8 +133,7 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) { return; DCHECK(event); - InputEventAckState ack = - handler_.Run(routing_id, event, latency_info); + InputEventAckState ack = handler_.Run(routing_id, event, &latency_info); if (ack == INPUT_EVENT_ACK_STATE_NOT_CONSUMED) { TRACE_EVENT0("input", "InputEventFilter::ForwardToHandler"); @@ -145,10 +146,11 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) { return; } - SendACK(event->type, ack, latency_info, routing_id); + if (!WebInputEventTraits::IgnoresAckDisposition(event->type)) + SendACK(event->type, ack, latency_info, routing_id); } -void InputEventFilter::SendACK(WebKit::WebInputEvent::Type type, +void InputEventFilter::SendACK(blink::WebInputEvent::Type type, InputEventAckState ack_result, const ui::LatencyInfo& latency_info, int routing_id) { diff --git a/chromium/content/renderer/gpu/input_event_filter.h b/chromium/content/renderer/input/input_event_filter.h index b4526200c2f..240f939f721 100644 --- a/chromium/content/renderer/gpu/input_event_filter.h +++ b/chromium/content/renderer/input/input_event_filter.h @@ -1,9 +1,9 @@ -// Copyright (c) 2011 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. -#ifndef CONTENT_RENDERER_GPU_INPUT_EVENT_FILTER_H_ -#define CONTENT_RENDERER_GPU_INPUT_EVENT_FILTER_H_ +#ifndef CONTENT_RENDERER_INPUT_INPUT_EVENT_FILTER_H_ +#define CONTENT_RENDERER_INPUT_INPUT_EVENT_FILTER_H_ #include <queue> #include <set> @@ -12,7 +12,7 @@ #include "base/synchronization/lock.h" #include "content/common/content_export.h" #include "content/port/common/input_event_ack_state.h" -#include "content/renderer/gpu/input_handler_manager_client.h" +#include "content/renderer/input/input_handler_manager_client.h" #include "ipc/ipc_channel_proxy.h" #include "third_party/WebKit/public/web/WebInputEvent.h" @@ -62,7 +62,7 @@ class CONTENT_EXPORT InputEventFilter void ForwardToMainListener(const IPC::Message& message); void ForwardToHandler(const IPC::Message& message); - void SendACK(WebKit::WebInputEvent::Type type, + void SendACK(blink::WebInputEvent::Type type, InputEventAckState ack_result, const ui::LatencyInfo& latency_info, int routing_id); @@ -91,4 +91,4 @@ class CONTENT_EXPORT InputEventFilter } // namespace content -#endif // CONTENT_RENDERER_GPU_INPUT_EVENT_FILTER_H_ +#endif // CONTENT_RENDERER_INPUT_INPUT_EVENT_FILTER_H_ diff --git a/chromium/content/renderer/gpu/input_event_filter_unittest.cc b/chromium/content/renderer/input/input_event_filter_unittest.cc index d8e605268b0..a131ceb47dc 100644 --- a/chromium/content/renderer/gpu/input_event_filter_unittest.cc +++ b/chromium/content/renderer/input/input_event_filter_unittest.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. @@ -10,12 +10,12 @@ #include "base/message_loop/message_loop.h" #include "content/common/input_messages.h" #include "content/common/view_messages.h" -#include "content/renderer/gpu/input_event_filter.h" +#include "content/renderer/input/input_event_filter.h" #include "ipc/ipc_test_sink.h" #include "testing/gtest/include/gtest/gtest.h" -using WebKit::WebInputEvent; -using WebKit::WebMouseEvent; +using blink::WebInputEvent; +using blink::WebMouseEvent; namespace content { namespace { @@ -47,7 +47,7 @@ class InputEventRecorder { InputEventAckState HandleInputEvent(int routing_id, const WebInputEvent* event, - const ui::LatencyInfo& latency_info) { + ui::LatencyInfo* latency_info) { DCHECK_EQ(kTestRoutingID, routing_id); records_.push_back(Record(event)); @@ -285,9 +285,9 @@ TEST_F(InputEventFilterTest, PreserveRelativeOrder) { messages.push_back(InputMsg_Paste(kTestRoutingID)); messages.push_back(InputMsg_PasteAndMatchStyle(kTestRoutingID)); messages.push_back(InputMsg_Delete(kTestRoutingID)); - messages.push_back(InputMsg_Replace(kTestRoutingID, string16())); + messages.push_back(InputMsg_Replace(kTestRoutingID, base::string16())); messages.push_back(InputMsg_ReplaceMisspelling(kTestRoutingID, - string16())); + base::string16())); messages.push_back(InputMsg_Delete(kTestRoutingID)); messages.push_back(InputMsg_SelectAll(kTestRoutingID)); messages.push_back(InputMsg_Unselect(kTestRoutingID)); diff --git a/chromium/content/renderer/gpu/input_handler_manager.cc b/chromium/content/renderer/input/input_handler_manager.cc index 1db011baebb..6195f5195df 100644 --- a/chromium/content/renderer/gpu/input_handler_manager.cc +++ b/chromium/content/renderer/input/input_handler_manager.cc @@ -1,18 +1,18 @@ -// 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. -#include "content/renderer/gpu/input_handler_manager.h" +#include "content/renderer/input/input_handler_manager.h" #include "base/bind.h" #include "base/debug/trace_event.h" #include "base/message_loop/message_loop_proxy.h" #include "cc/input/input_handler.h" -#include "content/renderer/gpu/input_event_filter.h" -#include "content/renderer/gpu/input_handler_manager_client.h" -#include "content/renderer/gpu/input_handler_wrapper.h" +#include "content/renderer/input/input_event_filter.h" +#include "content/renderer/input/input_handler_manager_client.h" +#include "content/renderer/input/input_handler_wrapper.h" -using WebKit::WebInputEvent; +using blink::WebInputEvent; namespace content { @@ -88,13 +88,14 @@ void InputHandlerManager::AddInputHandlerOnCompositorThread( "InputHandlerManager::AddInputHandlerOnCompositorThread", "result", "AddingRoute"); client_->DidAddInputHandler(routing_id, input_handler.get()); - input_handlers_[routing_id] = - make_scoped_refptr(new InputHandlerWrapper(this, - routing_id, main_loop, input_handler, render_view_impl)); + input_handlers_.add(routing_id, + make_scoped_ptr(new InputHandlerWrapper(this, + routing_id, main_loop, input_handler, render_view_impl))); } void InputHandlerManager::RemoveInputHandler(int routing_id) { DCHECK(message_loop_proxy_->BelongsToCurrentThread()); + DCHECK(input_handlers_.contains(routing_id)); TRACE_EVENT0("input", "InputHandlerManager::RemoveInputHandler"); @@ -105,13 +106,13 @@ void InputHandlerManager::RemoveInputHandler(int routing_id) { InputEventAckState InputHandlerManager::HandleInputEvent( int routing_id, const WebInputEvent* input_event, - const ui::LatencyInfo& latency_info) { + ui::LatencyInfo* latency_info) { DCHECK(message_loop_proxy_->BelongsToCurrentThread()); InputHandlerMap::iterator it = input_handlers_.find(routing_id); if (it == input_handlers_.end()) { TRACE_EVENT1("input", "InputHandlerManager::HandleInputEvent", - "result", "NoInputHandlerFound"); + "result", "NoInputHandlerFound"); // Oops, we no longer have an interested input handler.. return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; } diff --git a/chromium/content/renderer/gpu/input_handler_manager.h b/chromium/content/renderer/input/input_handler_manager.h index 3811d63a8df..f2df0415f29 100644 --- a/chromium/content/renderer/gpu/input_handler_manager.h +++ b/chromium/content/renderer/input/input_handler_manager.h @@ -1,12 +1,11 @@ -// 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. -#ifndef CONTENT_RENDERER_GPU_INPUT_HANDLER_MANAGER_H_ -#define CONTENT_RENDERER_GPU_INPUT_HANDLER_MANAGER_H_ - -#include <map> +#ifndef CONTENT_RENDERER_INPUT_INPUT_HANDLER_MANAGER_H_ +#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_MANAGER_H_ +#include "base/containers/scoped_ptr_hash_map.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "content/port/common/input_event_ack_state.h" @@ -21,7 +20,7 @@ class InputHandler; struct DidOverscrollParams; } -namespace WebKit { +namespace blink { class WebInputEvent; } @@ -52,8 +51,8 @@ class InputHandlerManager { // Called from the compositor's thread. InputEventAckState HandleInputEvent(int routing_id, - const WebKit::WebInputEvent* input_event, - const ui::LatencyInfo& latency_info); + const blink::WebInputEvent* input_event, + ui::LatencyInfo* latency_info); // Called from the compositor's thread. void DidOverscroll(int routing_id, const cc::DidOverscrollParams& params); @@ -66,8 +65,8 @@ class InputHandlerManager { const base::WeakPtr<cc::InputHandler>& input_handler, const base::WeakPtr<RenderViewImpl>& render_view_impl); - typedef std::map<int, // routing_id - scoped_refptr<InputHandlerWrapper> > InputHandlerMap; + typedef base::ScopedPtrHashMap<int, // routing_id + InputHandlerWrapper> InputHandlerMap; InputHandlerMap input_handlers_; scoped_refptr<base::MessageLoopProxy> message_loop_proxy_; @@ -76,4 +75,4 @@ class InputHandlerManager { } // namespace content -#endif // CONTENT_RENDERER_GPU_INPUT_HANDLER_MANAGER_H_ +#endif // CONTENT_RENDERER_INPUT_INPUT_HANDLER_MANAGER_H_ diff --git a/chromium/content/renderer/gpu/input_handler_manager_client.h b/chromium/content/renderer/input/input_handler_manager_client.h index c147a8a6be0..0a36e50ba5d 100644 --- a/chromium/content/renderer/gpu/input_handler_manager_client.h +++ b/chromium/content/renderer/input/input_handler_manager_client.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_RENDERER_GPU_INPUT_HANDLER_MANAGER_CLIENT_H_ -#define CONTENT_RENDERER_GPU_INPUT_HANDLER_MANAGER_CLIENT_H_ +#ifndef CONTENT_RENDERER_INPUT_INPUT_HANDLER_MANAGER_CLIENT_H_ +#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_MANAGER_CLIENT_H_ #include "base/basictypes.h" #include "base/callback.h" @@ -20,7 +20,7 @@ class InputHandler; struct DidOverscrollParams; } -namespace WebKit { +namespace blink { class WebInputEvent; } @@ -35,8 +35,8 @@ class CONTENT_EXPORT InputHandlerManagerClient { // The client should only makes calls to |handler| on the compositor thread. typedef base::Callback< InputEventAckState(int /*routing_id*/, - const WebKit::WebInputEvent*, - const ui::LatencyInfo& latency_info)> Handler; + const blink::WebInputEvent*, + ui::LatencyInfo* latency_info)> Handler; // Called from the main thread. virtual void SetBoundHandler(const Handler& handler) = 0; diff --git a/chromium/content/renderer/gpu/input_handler_proxy.cc b/chromium/content/renderer/input/input_handler_proxy.cc index f1ca2a54711..ce9ce22a02d 100644 --- a/chromium/content/renderer/gpu/input_handler_proxy.cc +++ b/chromium/content/renderer/input/input_handler_proxy.cc @@ -1,27 +1,37 @@ -// 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. -#include "content/renderer/gpu/input_handler_proxy.h" +#include "content/renderer/input/input_handler_proxy.h" #include "base/debug/trace_event.h" #include "base/logging.h" #include "base/metrics/histogram.h" -#include "content/renderer/gpu/input_handler_proxy_client.h" +#include "content/renderer/input/input_handler_proxy_client.h" #include "third_party/WebKit/public/platform/Platform.h" #include "third_party/WebKit/public/web/WebInputEvent.h" #include "ui/events/latency_info.h" - -using WebKit::WebFloatPoint; -using WebKit::WebFloatSize; -using WebKit::WebGestureEvent; -using WebKit::WebInputEvent; -using WebKit::WebMouseWheelEvent; -using WebKit::WebPoint; -using WebKit::WebTouchEvent; +#include "ui/gfx/frame_time.h" + +using blink::WebFloatPoint; +using blink::WebFloatSize; +using blink::WebGestureEvent; +using blink::WebInputEvent; +using blink::WebMouseEvent; +using blink::WebMouseWheelEvent; +using blink::WebPoint; +using blink::WebTouchEvent; +using blink::WebTouchPoint; namespace { +// Validate provided event timestamps that interact with animation timestamps. +const double kBadTimestampDeltaFromNowInS = 60. * 60. * 24. * 7.; + +double InSecondsF(const base::TimeTicks& time) { + return (time - base::TimeTicks()).InSecondsF(); +} + void SendScrollLatencyUma(const WebInputEvent& event, const ui::LatencyInfo& latency_info) { if (!(event.type == WebInputEvent::GestureScrollBegin || @@ -39,10 +49,10 @@ void SendScrollLatencyUma(const WebInputEvent& event, base::TimeDelta delta = base::TimeTicks::HighResNow() - it->second.event_time; for (size_t i = 0; i < it->second.event_count; ++i) { UMA_HISTOGRAM_CUSTOM_COUNTS( - "Event.Latency.RendererImpl.GestureScroll", + "Event.Latency.RendererImpl.GestureScroll2", delta.InMicroseconds(), 0, - 200000, + 1000000, 100); } } // namespace @@ -82,14 +92,14 @@ void InputHandlerProxy::SetClient(InputHandlerProxyClient* client) { InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEventWithLatencyInfo( const WebInputEvent& event, - const ui::LatencyInfo& latency_info) { + ui::LatencyInfo* latency_info) { DCHECK(input_handler_); - SendScrollLatencyUma(event, latency_info); + SendScrollLatencyUma(event, *latency_info); + scoped_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor = + input_handler_->CreateLatencyInfoSwapPromiseMonitor(latency_info); InputHandlerProxy::EventDisposition disposition = HandleInputEvent(event); - if (disposition != DID_NOT_HANDLE) - input_handler_->SetLatencyInfoForInputEvent(latency_info); return disposition; } @@ -218,9 +228,14 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent( } else if (event.type == WebInputEvent::TouchStart) { const WebTouchEvent& touch_event = *static_cast<const WebTouchEvent*>(&event); - if (!input_handler_->HaveTouchEventHandlersAt(touch_event.touches[0] - .position)) - return DROP_EVENT; + for (size_t i = 0; i < touch_event.touchesLength; ++i) { + if (touch_event.touches[i].state != WebTouchPoint::StatePressed) + continue; + if (input_handler_->HaveTouchEventHandlersAt(touch_event.touches[i] + .position)) + return DID_NOT_HANDLE; + } + return DROP_EVENT; } else if (WebInputEvent::isKeyboardEventType(event.type)) { CancelCurrentFling(); } @@ -257,13 +272,19 @@ InputHandlerProxy::HandleGestureFling( gesture_event.sourceDevice, WebFloatPoint(gesture_event.data.flingStart.velocityX, gesture_event.data.flingStart.velocityY), - WebKit::WebSize())); + blink::WebSize())); fling_overscrolled_horizontally_ = false; fling_overscrolled_vertically_ = false; TRACE_EVENT_ASYNC_BEGIN0( "renderer", "InputHandlerProxy::HandleGestureFling::started", this); + if (gesture_event.timeStampSeconds) { + fling_parameters_.startTime = gesture_event.timeStampSeconds; + DCHECK_LT(fling_parameters_.startTime - + InSecondsF(gfx::FrameTime::Now()), + kBadTimestampDeltaFromNowInS); + } fling_parameters_.delta = WebFloatPoint(gesture_event.data.flingStart.velocityX, gesture_event.data.flingStart.velocityY); @@ -304,7 +325,7 @@ void InputHandlerProxy::Animate(base::TimeTicks time) { if (!fling_curve_) return; - double monotonic_time_sec = (time - base::TimeTicks()).InSecondsF(); + double monotonic_time_sec = InSecondsF(time); if (!fling_parameters_.startTime) { fling_parameters_.startTime = monotonic_time_sec; input_handler_->ScheduleAnimation(); @@ -359,7 +380,7 @@ bool InputHandlerProxy::CancelCurrentFling() { had_fling_animation); fling_curve_.reset(); gesture_scroll_on_impl_thread_ = false; - fling_parameters_ = WebKit::WebActiveWheelFlingParameters(); + fling_parameters_ = blink::WebActiveWheelFlingParameters(); return had_fling_animation; } diff --git a/chromium/content/renderer/gpu/input_handler_proxy.h b/chromium/content/renderer/input/input_handler_proxy.h index e307827bc00..46f88ab5ea4 100644 --- a/chromium/content/renderer/gpu/input_handler_proxy.h +++ b/chromium/content/renderer/input/input_handler_proxy.h @@ -1,19 +1,19 @@ -// 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. -#ifndef CONTENT_RENDERER_GPU_INPUT_HANDLER_PROXY_H_ -#define CONTENT_RENDERER_GPU_INPUT_HANDLER_PROXY_H_ +#ifndef CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_H_ +#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_H_ #include "base/basictypes.h" #include "base/containers/hash_tables.h" #include "base/memory/scoped_ptr.h" #include "cc/input/input_handler.h" #include "content/common/content_export.h" -#include "third_party/WebKit/public/web/WebActiveWheelFlingParameters.h" -#include "third_party/WebKit/public/web/WebInputEvent.h" #include "third_party/WebKit/public/platform/WebGestureCurve.h" #include "third_party/WebKit/public/platform/WebGestureCurveTarget.h" +#include "third_party/WebKit/public/web/WebActiveWheelFlingParameters.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" namespace content { @@ -25,7 +25,7 @@ class InputHandlerProxyClient; // intended for a specific WebWidget. class CONTENT_EXPORT InputHandlerProxy : public cc::InputHandlerClient, - public NON_EXPORTED_BASE(WebKit::WebGestureCurveTarget) { + public NON_EXPORTED_BASE(blink::WebGestureCurveTarget) { public: explicit InputHandlerProxy(cc::InputHandler* input_handler); virtual ~InputHandlerProxy(); @@ -38,9 +38,9 @@ class CONTENT_EXPORT InputHandlerProxy DROP_EVENT }; EventDisposition HandleInputEventWithLatencyInfo( - const WebKit::WebInputEvent& event, - const ui::LatencyInfo& latency_info); - EventDisposition HandleInputEvent(const WebKit::WebInputEvent& event); + const blink::WebInputEvent& event, + ui::LatencyInfo* latency_info); + EventDisposition HandleInputEvent(const blink::WebInputEvent& event); // cc::InputHandlerClient implementation. virtual void WillShutdown() OVERRIDE; @@ -48,27 +48,27 @@ class CONTENT_EXPORT InputHandlerProxy virtual void MainThreadHasStoppedFlinging() OVERRIDE; virtual void DidOverscroll(const cc::DidOverscrollParams& params) OVERRIDE; - // WebKit::WebGestureCurveTarget implementation. - virtual void scrollBy(const WebKit::WebFloatSize& offset); - virtual void notifyCurrentFlingVelocity(const WebKit::WebFloatSize& velocity); + // blink::WebGestureCurveTarget implementation. + virtual void scrollBy(const blink::WebFloatSize& offset); + virtual void notifyCurrentFlingVelocity(const blink::WebFloatSize& velocity); bool gesture_scroll_on_impl_thread_for_testing() const { return gesture_scroll_on_impl_thread_; } private: - EventDisposition HandleGestureFling(const WebKit::WebGestureEvent& event); + EventDisposition HandleGestureFling(const blink::WebGestureEvent& event); // Returns true if we scrolled by the increment. - bool TouchpadFlingScroll(const WebKit::WebFloatSize& increment); + bool TouchpadFlingScroll(const blink::WebFloatSize& increment); // Returns true if we actually had an active fling to cancel. bool CancelCurrentFling(); - scoped_ptr<WebKit::WebGestureCurve> fling_curve_; + scoped_ptr<blink::WebGestureCurve> fling_curve_; // Parameters for the active fling animation, stored in case we need to // transfer it out later. - WebKit::WebActiveWheelFlingParameters fling_parameters_; + blink::WebActiveWheelFlingParameters fling_parameters_; InputHandlerProxyClient* client_; cc::InputHandler* input_handler_; @@ -92,4 +92,4 @@ class CONTENT_EXPORT InputHandlerProxy } // namespace content -#endif // CONTENT_RENDERER_GPU_INPUT_HANDLER_PROXY_H_ +#endif // CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_H_ diff --git a/chromium/content/renderer/gpu/input_handler_proxy_client.h b/chromium/content/renderer/input/input_handler_proxy_client.h index 6ef000c098f..7ef1121bf7c 100644 --- a/chromium/content/renderer/gpu/input_handler_proxy_client.h +++ b/chromium/content/renderer/input/input_handler_proxy_client.h @@ -1,11 +1,11 @@ -// 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. -#ifndef CONTENT_RENDERER_GPU_INPUT_HANDLER_PROXY_CLIENT_H_ -#define CONTENT_RENDERER_GPU_INPUT_HANDLER_PROXY_CLIENT_H_ +#ifndef CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_CLIENT_H_ +#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_CLIENT_H_ -namespace WebKit { +namespace blink { class WebGestureCurve; struct WebActiveWheelFlingParameters; struct WebFloatPoint; @@ -23,14 +23,14 @@ class InputHandlerProxyClient { // Transfers an active wheel fling animation initiated by a previously // handled input event out to the client. virtual void TransferActiveWheelFlingAnimation( - const WebKit::WebActiveWheelFlingParameters& params) = 0; + const blink::WebActiveWheelFlingParameters& params) = 0; // Creates a new fling animation curve instance for device |device_source| // with |velocity| and already scrolled |cumulative_scroll| pixels. - virtual WebKit::WebGestureCurve* CreateFlingAnimationCurve( + virtual blink::WebGestureCurve* CreateFlingAnimationCurve( int device_source, - const WebKit::WebFloatPoint& velocity, - const WebKit::WebSize& cumulative_scroll) = 0; + const blink::WebFloatPoint& velocity, + const blink::WebSize& cumulative_scroll) = 0; virtual void DidOverscroll(const cc::DidOverscrollParams& params) = 0; @@ -40,4 +40,4 @@ class InputHandlerProxyClient { } // namespace content -#endif // CONTENT_RENDERER_GPU_INPUT_HANDLER_PROXY_CLIENT_H_ +#endif // CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_CLIENT_H_ diff --git a/chromium/content/renderer/gpu/input_handler_proxy_unittest.cc b/chromium/content/renderer/input/input_handler_proxy_unittest.cc index 5a3472cca47..c7cc9168c18 100644 --- a/chromium/content/renderer/gpu/input_handler_proxy_unittest.cc +++ b/chromium/content/renderer/input/input_handler_proxy_unittest.cc @@ -1,12 +1,13 @@ -// 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. -#include "content/renderer/gpu/input_handler_proxy.h" +#include "content/renderer/input/input_handler_proxy.h" #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" -#include "content/renderer/gpu/input_handler_proxy_client.h" +#include "cc/base/swap_promise_monitor.h" +#include "content/renderer/input/input_handler_proxy_client.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/platform/WebFloatPoint.h" @@ -16,14 +17,16 @@ #include "third_party/WebKit/public/web/WebInputEvent.h" #include "ui/events/latency_info.h" -using WebKit::WebActiveWheelFlingParameters; -using WebKit::WebFloatPoint; -using WebKit::WebFloatSize; -using WebKit::WebGestureEvent; -using WebKit::WebInputEvent; -using WebKit::WebMouseWheelEvent; -using WebKit::WebPoint; -using WebKit::WebSize; +using blink::WebActiveWheelFlingParameters; +using blink::WebFloatPoint; +using blink::WebFloatSize; +using blink::WebGestureEvent; +using blink::WebInputEvent; +using blink::WebMouseWheelEvent; +using blink::WebPoint; +using blink::WebSize; +using blink::WebTouchEvent; +using blink::WebTouchPoint; namespace content { namespace { @@ -51,8 +54,10 @@ class MockInputHandler : public cc::InputHandler { MOCK_METHOD0(ScrollEnd, void()); MOCK_METHOD0(FlingScrollBegin, cc::InputHandler::ScrollStatus()); - MOCK_METHOD1(SetLatencyInfoForInputEvent, - void(const ui::LatencyInfo& latency_info)); + virtual scoped_ptr<cc::SwapPromiseMonitor> + CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency) OVERRIDE { + return scoped_ptr<cc::SwapPromiseMonitor>(); + } virtual void BindToClient(cc::InputHandlerClient* client) OVERRIDE {} @@ -62,10 +67,10 @@ class MockInputHandler : public cc::InputHandler { base::TimeDelta duration) OVERRIDE {} virtual void NotifyCurrentFlingVelocity(gfx::Vector2dF velocity) OVERRIDE {} + virtual void MouseMoveAt(gfx::Point mouse_position) OVERRIDE {} - virtual bool HaveTouchEventHandlersAt(gfx::Point point) OVERRIDE { - return false; - } + MOCK_METHOD1(HaveTouchEventHandlersAt, + bool(gfx::Point point)); virtual void SetRootLayerScrollOffsetDelegate( cc::LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate) @@ -78,18 +83,18 @@ class MockInputHandler : public cc::InputHandler { // A simple WebGestureCurve implementation that flings at a constant velocity // indefinitely. -class FakeWebGestureCurve : public WebKit::WebGestureCurve { +class FakeWebGestureCurve : public blink::WebGestureCurve { public: - FakeWebGestureCurve(const WebKit::WebFloatPoint& velocity, - const WebKit::WebSize& cumulative_scroll) + FakeWebGestureCurve(const blink::WebFloatPoint& velocity, + const blink::WebSize& cumulative_scroll) : velocity_(velocity), cumulative_scroll_(cumulative_scroll) {} virtual ~FakeWebGestureCurve() {} // Returns false if curve has finished and can no longer be applied. - virtual bool apply(double time, WebKit::WebGestureCurveTarget* target) { - WebKit::WebSize displacement(velocity_.x * time, velocity_.y * time); - WebKit::WebFloatSize increment( + virtual bool apply(double time, blink::WebGestureCurveTarget* target) { + blink::WebSize displacement(velocity_.x * time, velocity_.y * time); + blink::WebFloatSize increment( displacement.width - cumulative_scroll_.width, displacement.height - cumulative_scroll_.height); cumulative_scroll_ = displacement; @@ -100,8 +105,8 @@ class FakeWebGestureCurve : public WebKit::WebGestureCurve { } private: - WebKit::WebFloatPoint velocity_; - WebKit::WebSize cumulative_scroll_; + blink::WebFloatPoint velocity_; + blink::WebSize cumulative_scroll_; DISALLOW_COPY_AND_ASSIGN(FakeWebGestureCurve); }; @@ -117,7 +122,7 @@ class MockInputHandlerProxyClient MOCK_METHOD1(TransferActiveWheelFlingAnimation, void(const WebActiveWheelFlingParameters&)); - virtual WebKit::WebGestureCurve* CreateFlingAnimationCurve( + virtual blink::WebGestureCurve* CreateFlingAnimationCurve( int deviceSource, const WebFloatPoint& velocity, const WebSize& cumulative_scroll) OVERRIDE { @@ -884,6 +889,63 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) { EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); } +TEST_F(InputHandlerProxyTest, GestureFlingWithValidTimestamp) { + // We shouldn't send any events to the widget for this gesture. + expected_disposition_ = InputHandlerProxy::DID_HANDLE; + VERIFY_AND_RESET_MOCKS(); + + EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) + .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); + + gesture_.type = WebInputEvent::GestureScrollBegin; + gesture_.sourceDevice = WebGestureEvent::Touchscreen; + EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); + + VERIFY_AND_RESET_MOCKS(); + + // On the fling start, we should schedule an animation but not actually start + // scrolling. + base::TimeDelta startTimeOffset = base::TimeDelta::FromMilliseconds(10); + gesture_.type = WebInputEvent::GestureFlingStart; + WebFloatPoint fling_delta = WebFloatPoint(1000, 0); + WebPoint fling_point = WebPoint(7, 13); + WebPoint fling_global_point = WebPoint(17, 23); + int modifiers = 7; + gesture_.timeStampSeconds = startTimeOffset.InSecondsF(); + gesture_.data.flingStart.velocityX = fling_delta.x; + gesture_.data.flingStart.velocityY = fling_delta.y; + gesture_.sourceDevice = WebGestureEvent::Touchscreen; + gesture_.x = fling_point.x; + gesture_.y = fling_point.y; + gesture_.globalX = fling_global_point.x; + gesture_.globalY = fling_global_point.y; + gesture_.modifiers = modifiers; + EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) + .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); + EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); + + testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + // With a valid time stamp, the first animate call should skip start time + // initialization and immediately begin scroll update production. This reduces + // the likelihood of a hitch between the scroll preceding the fling and + // the first scroll generated by the fling. + // Scrolling should start in the -X direction. + EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, + ScrollBy(testing::_, + testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) + .WillOnce(testing::Return(true)); + base::TimeTicks time = base::TimeTicks() + 2 * startTimeOffset; + input_handler_->Animate(time); + + testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + + EXPECT_CALL(mock_input_handler_, ScrollEnd()); + gesture_.type = WebInputEvent::GestureFlingCancel; + EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); +} + TEST_F(InputHandlerProxyTest, GestureScrollOnImplThreadFlagClearedAfterFling) { // We shouldn't send any events to the widget for this gesture. @@ -1016,5 +1078,75 @@ TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) { testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); } +TEST_F(InputHandlerProxyTest, MultiTouchPointHitTestNegative) { + // None of the three touch points fall in the touch region. So the event + // should be dropped. + expected_disposition_ = InputHandlerProxy::DROP_EVENT; + VERIFY_AND_RESET_MOCKS(); + + EXPECT_CALL(mock_input_handler_, + HaveTouchEventHandlersAt( + testing::Property(&gfx::Point::x, testing::Gt(0)))) + .WillOnce(testing::Return(false)); + EXPECT_CALL(mock_input_handler_, + HaveTouchEventHandlersAt( + testing::Property(&gfx::Point::x, testing::Lt(0)))) + .WillOnce(testing::Return(false)); + + WebTouchEvent touch; + touch.type = WebInputEvent::TouchStart; + + touch.touchesLength = 3; + touch.touches[0].state = WebTouchPoint::StateStationary; + touch.touches[0].screenPosition = WebPoint(); + touch.touches[0].position = WebPoint(); + + touch.touches[1].state = WebTouchPoint::StatePressed; + touch.touches[1].screenPosition = WebPoint(10, 10); + touch.touches[1].position = WebPoint(10, 10); + + touch.touches[2].state = WebTouchPoint::StatePressed; + touch.touches[2].screenPosition = WebPoint(-10, 10); + touch.touches[2].position = WebPoint(-10, 10); + + EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch)); +} + +TEST_F(InputHandlerProxyTest, MultiTouchPointHitTestPositive) { + // One of the touch points is on a touch-region. So the event should be sent + // to the main thread. + expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; + VERIFY_AND_RESET_MOCKS(); + + EXPECT_CALL(mock_input_handler_, + HaveTouchEventHandlersAt( + testing::Property(&gfx::Point::x, testing::Eq(0)))) + .WillOnce(testing::Return(false)); + EXPECT_CALL(mock_input_handler_, + HaveTouchEventHandlersAt( + testing::Property(&gfx::Point::x, testing::Gt(0)))) + .WillOnce(testing::Return(true)); + // Since the second touch point hits a touch-region, there should be no + // hit-testing for the third touch point. + + WebTouchEvent touch; + touch.type = WebInputEvent::TouchStart; + + touch.touchesLength = 3; + touch.touches[0].state = WebTouchPoint::StatePressed; + touch.touches[0].screenPosition = WebPoint(); + touch.touches[0].position = WebPoint(); + + touch.touches[1].state = WebTouchPoint::StatePressed; + touch.touches[1].screenPosition = WebPoint(10, 10); + touch.touches[1].position = WebPoint(10, 10); + + touch.touches[2].state = WebTouchPoint::StatePressed; + touch.touches[2].screenPosition = WebPoint(-10, 10); + touch.touches[2].position = WebPoint(-10, 10); + + EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch)); +} + } // namespace } // namespace content diff --git a/chromium/content/renderer/gpu/input_handler_wrapper.cc b/chromium/content/renderer/input/input_handler_wrapper.cc index 348ff6dc586..14e23ebf3ad 100644 --- a/chromium/content/renderer/gpu/input_handler_wrapper.cc +++ b/chromium/content/renderer/input/input_handler_wrapper.cc @@ -1,12 +1,12 @@ -// 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. -#include "content/renderer/gpu/input_handler_wrapper.h" +#include "content/renderer/input/input_handler_wrapper.h" #include "base/message_loop/message_loop_proxy.h" -#include "content/renderer/gpu/input_event_filter.h" -#include "content/renderer/gpu/input_handler_manager.h" +#include "content/renderer/input/input_event_filter.h" +#include "content/renderer/input/input_handler_manager.h" #include "third_party/WebKit/public/platform/Platform.h" namespace content { @@ -22,6 +22,7 @@ InputHandlerWrapper::InputHandlerWrapper( input_handler_proxy_(input_handler.get()), main_loop_(main_loop), render_view_impl_(render_view_impl) { + DCHECK(input_handler); input_handler_proxy_.SetClient(this); } @@ -30,7 +31,7 @@ InputHandlerWrapper::~InputHandlerWrapper() { } void InputHandlerWrapper::TransferActiveWheelFlingAnimation( - const WebKit::WebActiveWheelFlingParameters& params) { + const blink::WebActiveWheelFlingParameters& params) { main_loop_->PostTask( FROM_HERE, base::Bind(&RenderViewImpl::TransferActiveWheelFlingAnimation, @@ -42,11 +43,11 @@ void InputHandlerWrapper::WillShutdown() { input_handler_manager_->RemoveInputHandler(routing_id_); } -WebKit::WebGestureCurve* InputHandlerWrapper::CreateFlingAnimationCurve( +blink::WebGestureCurve* InputHandlerWrapper::CreateFlingAnimationCurve( int deviceSource, - const WebKit::WebFloatPoint& velocity, - const WebKit::WebSize& cumulative_scroll) { - return WebKit::Platform::current()->createFlingAnimationCurve( + const blink::WebFloatPoint& velocity, + const blink::WebSize& cumulative_scroll) { + return blink::Platform::current()->createFlingAnimationCurve( deviceSource, velocity, cumulative_scroll); } diff --git a/chromium/content/renderer/gpu/input_handler_wrapper.h b/chromium/content/renderer/input/input_handler_wrapper.h index f72bae5b12d..562012ace1d 100644 --- a/chromium/content/renderer/gpu/input_handler_wrapper.h +++ b/chromium/content/renderer/input/input_handler_wrapper.h @@ -1,28 +1,26 @@ -// 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. -#ifndef CONTENT_RENDERER_GPU_INPUT_HANDLER_WRAPPER_H_ -#define CONTENT_RENDERER_GPU_INPUT_HANDLER_WRAPPER_H_ +#ifndef CONTENT_RENDERER_INPUT_INPUT_HANDLER_WRAPPER_H_ +#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_WRAPPER_H_ -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" -#include "content/renderer/gpu/input_handler_manager.h" -#include "content/renderer/gpu/input_handler_proxy.h" -#include "content/renderer/gpu/input_handler_proxy_client.h" +#include "content/renderer/input/input_handler_manager.h" +#include "content/renderer/input/input_handler_proxy.h" +#include "content/renderer/input/input_handler_proxy_client.h" namespace content { // This class lives on the compositor thread. -class InputHandlerWrapper - : public InputHandlerProxyClient, - public base::RefCountedThreadSafe<InputHandlerWrapper> { +class InputHandlerWrapper : public InputHandlerProxyClient { public: InputHandlerWrapper(InputHandlerManager* input_handler_manager, int routing_id, const scoped_refptr<base::MessageLoopProxy>& main_loop, const base::WeakPtr<cc::InputHandler>& input_handler, const base::WeakPtr<RenderViewImpl>& render_view_impl); + virtual ~InputHandlerWrapper(); int routing_id() const { return routing_id_; } InputHandlerProxy* input_handler_proxy() { return &input_handler_proxy_; } @@ -30,18 +28,14 @@ class InputHandlerWrapper // InputHandlerProxyClient implementation. virtual void WillShutdown() OVERRIDE; virtual void TransferActiveWheelFlingAnimation( - const WebKit::WebActiveWheelFlingParameters& params) OVERRIDE; - virtual WebKit::WebGestureCurve* CreateFlingAnimationCurve( + const blink::WebActiveWheelFlingParameters& params) OVERRIDE; + virtual blink::WebGestureCurve* CreateFlingAnimationCurve( int deviceSource, - const WebKit::WebFloatPoint& velocity, - const WebKit::WebSize& cumulativeScroll) OVERRIDE; + const blink::WebFloatPoint& velocity, + const blink::WebSize& cumulativeScroll) OVERRIDE; virtual void DidOverscroll(const cc::DidOverscrollParams& params) OVERRIDE; private: - friend class base::RefCountedThreadSafe<InputHandlerWrapper>; - - virtual ~InputHandlerWrapper(); - InputHandlerManager* input_handler_manager_; int routing_id_; InputHandlerProxy input_handler_proxy_; @@ -55,4 +49,4 @@ class InputHandlerWrapper } // namespace content -#endif // CONTENT_RENDERER_GPU_INPUT_HANDLER_WRAPPER_H_ +#endif // CONTENT_RENDERER_INPUT_INPUT_HANDLER_WRAPPER_H_ diff --git a/chromium/content/renderer/input_tag_speech_dispatcher.cc b/chromium/content/renderer/input_tag_speech_dispatcher.cc index afce8c27cd8..b9490ce7639 100644 --- a/chromium/content/renderer/input_tag_speech_dispatcher.cc +++ b/chromium/content/renderer/input_tag_speech_dispatcher.cc @@ -18,18 +18,18 @@ #include "third_party/WebKit/public/web/WebSpeechInputListener.h" #include "third_party/WebKit/public/web/WebView.h" -using WebKit::WebDocument; -using WebKit::WebElement; -using WebKit::WebFrame; -using WebKit::WebInputElement; -using WebKit::WebNode; -using WebKit::WebView; +using blink::WebDocument; +using blink::WebElement; +using blink::WebFrame; +using blink::WebInputElement; +using blink::WebNode; +using blink::WebView; namespace content { InputTagSpeechDispatcher::InputTagSpeechDispatcher( RenderViewImpl* render_view, - WebKit::WebSpeechInputListener* listener) + blink::WebSpeechInputListener* listener) : RenderViewObserver(render_view), listener_(listener) { } @@ -53,10 +53,10 @@ bool InputTagSpeechDispatcher::OnMessageReceived( bool InputTagSpeechDispatcher::startRecognition( int request_id, - const WebKit::WebRect& element_rect, - const WebKit::WebString& language, - const WebKit::WebString& grammar, - const WebKit::WebSecurityOrigin& origin) { + const blink::WebRect& element_rect, + const blink::WebString& language, + const blink::WebString& grammar, + const blink::WebSecurityOrigin& origin) { DVLOG(1) << "InputTagSpeechDispatcher::startRecognition enter"; InputTagSpeechHostMsg_StartRecognition_Params params; @@ -92,7 +92,7 @@ void InputTagSpeechDispatcher::OnSpeechRecognitionResults( DCHECK_EQ(results.size(), 1U); const SpeechRecognitionResult& result = results[0]; - WebKit::WebSpeechInputResultArray webkit_result(result.hypotheses.size()); + blink::WebSpeechInputResultArray webkit_result(result.hypotheses.size()); for (size_t i = 0; i < result.hypotheses.size(); ++i) { webkit_result[i].assign(result.hypotheses[i].utterance, result.hypotheses[i].confidence); @@ -131,8 +131,8 @@ void InputTagSpeechDispatcher::OnSpeechRecognitionToggleSpeechInput() { if (focused_node.isNull() || !focused_node.isElementNode()) return; - WebKit::WebElement element = focused_node.to<WebKit::WebElement>(); - WebKit::WebInputElement* input_element = WebKit::toWebInputElement(&element); + blink::WebElement element = focused_node.to<blink::WebElement>(); + blink::WebInputElement* input_element = blink::toWebInputElement(&element); if (!input_element) return; if (!input_element->isSpeechInputEnabled()) diff --git a/chromium/content/renderer/input_tag_speech_dispatcher.h b/chromium/content/renderer/input_tag_speech_dispatcher.h index b51d7230347..ee9dda99e0e 100644 --- a/chromium/content/renderer/input_tag_speech_dispatcher.h +++ b/chromium/content/renderer/input_tag_speech_dispatcher.h @@ -10,7 +10,7 @@ #include "content/public/renderer/render_view_observer.h" #include "third_party/WebKit/public/web/WebSpeechInputController.h" -namespace WebKit { +namespace blink { class WebSpeechInputListener; } @@ -21,21 +21,21 @@ struct SpeechRecognitionResult; // InputTagSpeechDispatcher is a delegate for messages used by WebKit. It's // the complement of InputTagSpeechDispatcherHost (owned by RenderViewHost). class InputTagSpeechDispatcher : public RenderViewObserver, - public WebKit::WebSpeechInputController { + public blink::WebSpeechInputController { public: InputTagSpeechDispatcher(RenderViewImpl* render_view, - WebKit::WebSpeechInputListener* listener); + blink::WebSpeechInputListener* listener); private: // RenderView::Observer implementation. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - // WebKit::WebSpeechInputController. + // blink::WebSpeechInputController. virtual bool startRecognition(int request_id, - const WebKit::WebRect& element_rect, - const WebKit::WebString& language, - const WebKit::WebString& grammar, - const WebKit::WebSecurityOrigin& origin); + const blink::WebRect& element_rect, + const blink::WebString& language, + const blink::WebString& grammar, + const blink::WebSecurityOrigin& origin); virtual void cancelRecognition(int request_id); virtual void stopRecording(int request_id); @@ -46,7 +46,7 @@ class InputTagSpeechDispatcher : public RenderViewObserver, void OnSpeechRecognitionComplete(int request_id); void OnSpeechRecognitionToggleSpeechInput(); - WebKit::WebSpeechInputListener* listener_; + blink::WebSpeechInputListener* listener_; DISALLOW_COPY_AND_ASSIGN(InputTagSpeechDispatcher); }; diff --git a/chromium/content/renderer/internal_document_state_data.cc b/chromium/content/renderer/internal_document_state_data.cc index cd400f371eb..e3370dc5e56 100644 --- a/chromium/content/renderer/internal_document_state_data.cc +++ b/chromium/content/renderer/internal_document_state_data.cc @@ -25,14 +25,14 @@ InternalDocumentStateData::InternalDocumentStateData() is_overriding_user_agent_(false), must_reset_scroll_and_scale_state_(false), cache_policy_override_set_(false), - cache_policy_override_(WebKit::WebURLRequest::UseProtocolCachePolicy), + cache_policy_override_(blink::WebURLRequest::UseProtocolCachePolicy), referrer_policy_set_(false), - referrer_policy_(WebKit::WebReferrerPolicyDefault) { + referrer_policy_(blink::WebReferrerPolicyDefault) { } // static InternalDocumentStateData* InternalDocumentStateData::FromDataSource( - WebKit::WebDataSource* ds) { + blink::WebDataSource* ds) { return FromDocumentState(static_cast<DocumentState*>(ds->extraData())); } diff --git a/chromium/content/renderer/internal_document_state_data.h b/chromium/content/renderer/internal_document_state_data.h index 9fba893461d..6d2f2bc868d 100644 --- a/chromium/content/renderer/internal_document_state_data.h +++ b/chromium/content/renderer/internal_document_state_data.h @@ -13,7 +13,7 @@ #include "third_party/WebKit/public/platform/WebURLRequest.h" #include "url/gurl.h" -namespace WebKit { +namespace blink { class WebDataSource; } @@ -27,7 +27,7 @@ class InternalDocumentStateData : public base::SupportsUserData::Data { public: InternalDocumentStateData(); - static InternalDocumentStateData* FromDataSource(WebKit::WebDataSource* ds); + static InternalDocumentStateData* FromDataSource(blink::WebDataSource* ds); static InternalDocumentStateData* FromDocumentState(DocumentState* ds); // Set to true once RenderViewImpl::didFirstVisuallyNonEmptyLayout() is @@ -89,16 +89,16 @@ class InternalDocumentStateData : public base::SupportsUserData::Data { // by default is not set. You can mark a NavigationState as not having a cache // state by way of clear_cache_policy_override. void set_cache_policy_override( - WebKit::WebURLRequest::CachePolicy cache_policy) { + blink::WebURLRequest::CachePolicy cache_policy) { cache_policy_override_ = cache_policy; cache_policy_override_set_ = true; } - WebKit::WebURLRequest::CachePolicy cache_policy_override() const { + blink::WebURLRequest::CachePolicy cache_policy_override() const { return cache_policy_override_; } void clear_cache_policy_override() { cache_policy_override_set_ = false; - cache_policy_override_ = WebKit::WebURLRequest::UseProtocolCachePolicy; + cache_policy_override_ = blink::WebURLRequest::UseProtocolCachePolicy; } bool is_cache_policy_override_set() const { return cache_policy_override_set_; @@ -107,15 +107,15 @@ class InternalDocumentStateData : public base::SupportsUserData::Data { // Sets the referrer policy to use. This is only used for browser initiated // navigations, otherwise, the referrer policy is defined by the frame's // document. - WebKit::WebReferrerPolicy referrer_policy() const { + blink::WebReferrerPolicy referrer_policy() const { return referrer_policy_; } - void set_referrer_policy(WebKit::WebReferrerPolicy referrer_policy) { + void set_referrer_policy(blink::WebReferrerPolicy referrer_policy) { referrer_policy_ = referrer_policy; referrer_policy_set_ = true; } void clear_referrer_policy() { - referrer_policy_ = WebKit::WebReferrerPolicyDefault; + referrer_policy_ = blink::WebReferrerPolicyDefault; referrer_policy_set_ = false; } bool is_referrer_policy_set() const { return referrer_policy_set_; } @@ -138,9 +138,9 @@ class InternalDocumentStateData : public base::SupportsUserData::Data { bool is_overriding_user_agent_; bool must_reset_scroll_and_scale_state_; bool cache_policy_override_set_; - WebKit::WebURLRequest::CachePolicy cache_policy_override_; + blink::WebURLRequest::CachePolicy cache_policy_override_; bool referrer_policy_set_; - WebKit::WebReferrerPolicy referrer_policy_; + blink::WebReferrerPolicy referrer_policy_; scoped_ptr<AltErrorPageResourceFetcher> alt_error_page_fetcher_; DISALLOW_COPY_AND_ASSIGN(InternalDocumentStateData); diff --git a/chromium/content/renderer/java/OWNERS b/chromium/content/renderer/java/OWNERS index 4b297c43ee6..d378671071d 100644 --- a/chromium/content/renderer/java/OWNERS +++ b/chromium/content/renderer/java/OWNERS @@ -1,2 +1,2 @@ -joth@chromium.org steveblock@chromium.org +torne@chromium.org diff --git a/chromium/content/renderer/java/java_bridge_channel.cc b/chromium/content/renderer/java/java_bridge_channel.cc index 235425ab4ff..0d6d3f6c35f 100644 --- a/chromium/content/renderer/java/java_bridge_channel.cc +++ b/chromium/content/renderer/java/java_bridge_channel.cc @@ -27,12 +27,12 @@ JavaBridgeChannel::JavaBridgeChannel() : peer_owner_id_(new struct _NPP) { // Register the dummy owner Id for our peer (the Browser process) as an object // owner, and have all objects received from the peer owned by it. - WebKit::WebBindings::registerObjectOwner(peer_owner_id_.get()); + blink::WebBindings::registerObjectOwner(peer_owner_id_.get()); SetDefaultNPObjectOwner(peer_owner_id_.get()); } JavaBridgeChannel::~JavaBridgeChannel() { - WebKit::WebBindings::unregisterObjectOwner(peer_owner_id_.get()); + blink::WebBindings::unregisterObjectOwner(peer_owner_id_.get()); } int JavaBridgeChannel::GenerateRouteID() { diff --git a/chromium/content/renderer/java/java_bridge_dispatcher.cc b/chromium/content/renderer/java/java_bridge_dispatcher.cc index 376ecb1e481..f7e435cf2b1 100644 --- a/chromium/content/renderer/java/java_bridge_dispatcher.cc +++ b/chromium/content/renderer/java/java_bridge_dispatcher.cc @@ -36,7 +36,7 @@ void JavaBridgeDispatcher::EnsureChannelIsSetUp() { JavaBridgeDispatcher::~JavaBridgeDispatcher() { for (ObjectMap::const_iterator iter = objects_.begin(); iter != objects_.end(); ++iter) { - WebKit::WebBindings::releaseObject(NPVARIANT_TO_OBJECT(iter->second)); + blink::WebBindings::releaseObject(NPVARIANT_TO_OBJECT(iter->second)); } } @@ -51,7 +51,7 @@ bool JavaBridgeDispatcher::OnMessageReceived(const IPC::Message& msg) { return handled; } -void JavaBridgeDispatcher::DidClearWindowObject(WebKit::WebFrame* web_frame) { +void JavaBridgeDispatcher::DidClearWindowObject(blink::WebFrame* web_frame) { // Note that we have to (re)bind all objects, as they will have been unbound // when the window object was cleared. for (ObjectMap::const_iterator iter = objects_.begin(); @@ -65,7 +65,7 @@ void JavaBridgeDispatcher::DidClearWindowObject(WebKit::WebFrame* web_frame) { } void JavaBridgeDispatcher::OnAddNamedObject( - const string16& name, + const base::string16& name, const NPVariant_Param& variant_param) { DCHECK_EQ(variant_param.type, NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID); @@ -90,12 +90,12 @@ void JavaBridgeDispatcher::OnAddNamedObject( // OnRemoveNamedObject() is called for that object. ObjectMap::iterator iter = objects_.find(name); if (iter != objects_.end()) { - WebKit::WebBindings::releaseObject(NPVARIANT_TO_OBJECT(iter->second)); + blink::WebBindings::releaseObject(NPVARIANT_TO_OBJECT(iter->second)); } objects_[name] = variant; } -void JavaBridgeDispatcher::OnRemoveNamedObject(const string16& name) { +void JavaBridgeDispatcher::OnRemoveNamedObject(const base::string16& name) { if (!channel_.get()) { DCHECK(objects_.empty()); return; @@ -106,7 +106,7 @@ void JavaBridgeDispatcher::OnRemoveNamedObject(const string16& name) { // is present. ObjectMap::iterator iter = objects_.find(name); DCHECK(iter != objects_.end()); - WebKit::WebBindings::releaseObject(NPVARIANT_TO_OBJECT(iter->second)); + blink::WebBindings::releaseObject(NPVARIANT_TO_OBJECT(iter->second)); objects_.erase(iter); } diff --git a/chromium/content/renderer/java/java_bridge_dispatcher.h b/chromium/content/renderer/java/java_bridge_dispatcher.h index 29a10374590..325d5291851 100644 --- a/chromium/content/renderer/java/java_bridge_dispatcher.h +++ b/chromium/content/renderer/java/java_bridge_dispatcher.h @@ -30,18 +30,18 @@ class JavaBridgeDispatcher : public RenderViewObserver { private: // RenderViewObserver override: virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - virtual void DidClearWindowObject(WebKit::WebFrame* frame) OVERRIDE; + virtual void DidClearWindowObject(blink::WebFrame* frame) OVERRIDE; // Message handlers - void OnAddNamedObject(const string16& name, + void OnAddNamedObject(const base::string16& name, const NPVariant_Param& variant_param); - void OnRemoveNamedObject(const string16& name); + void OnRemoveNamedObject(const base::string16& name); void EnsureChannelIsSetUp(); // Objects that will be bound to the window when the window object is next // cleared. We hold a ref to these. - typedef std::map<string16, NPVariant> ObjectMap; + typedef std::map<base::string16, NPVariant> ObjectMap; ObjectMap objects_; scoped_refptr<JavaBridgeChannel> channel_; }; diff --git a/chromium/content/renderer/load_progress_tracker.cc b/chromium/content/renderer/load_progress_tracker.cc index 3a04b7232d1..0cc26fdcccf 100644 --- a/chromium/content/renderer/load_progress_tracker.cc +++ b/chromium/content/renderer/load_progress_tracker.cc @@ -38,7 +38,7 @@ void LoadProgressTracker::DidStopLoading() { ResetStates(); } -void LoadProgressTracker::DidChangeLoadProgress(WebKit::WebFrame* frame, +void LoadProgressTracker::DidChangeLoadProgress(blink::WebFrame* frame, double progress) { if (tracked_frame_ && frame != tracked_frame_) return; diff --git a/chromium/content/renderer/load_progress_tracker.h b/chromium/content/renderer/load_progress_tracker.h index a23935027d1..c4ed37eca9d 100644 --- a/chromium/content/renderer/load_progress_tracker.h +++ b/chromium/content/renderer/load_progress_tracker.h @@ -9,7 +9,7 @@ #include "base/memory/weak_ptr.h" #include "base/time/time.h" -namespace WebKit { +namespace blink { class WebFrame; } @@ -23,7 +23,7 @@ class LoadProgressTracker { void DidStopLoading(); - void DidChangeLoadProgress(WebKit::WebFrame* frame, double progress); + void DidChangeLoadProgress(blink::WebFrame* frame, double progress); private: void ResetStates(); @@ -32,7 +32,7 @@ class LoadProgressTracker { RenderViewImpl* render_view_; - WebKit::WebFrame* tracked_frame_; + blink::WebFrame* tracked_frame_; double progress_; diff --git a/chromium/content/renderer/media/active_loader.cc b/chromium/content/renderer/media/active_loader.cc index e7601ea6bca..6951514e5b1 100644 --- a/chromium/content/renderer/media/active_loader.cc +++ b/chromium/content/renderer/media/active_loader.cc @@ -9,7 +9,7 @@ namespace content { -ActiveLoader::ActiveLoader(scoped_ptr<WebKit::WebURLLoader> loader) +ActiveLoader::ActiveLoader(scoped_ptr<blink::WebURLLoader> loader) : loader_(loader.Pass()), deferred_(false) { } diff --git a/chromium/content/renderer/media/active_loader.h b/chromium/content/renderer/media/active_loader.h index 751e6a96c46..1c30214b92c 100644 --- a/chromium/content/renderer/media/active_loader.h +++ b/chromium/content/renderer/media/active_loader.h @@ -8,7 +8,7 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" -namespace WebKit { +namespace blink { class WebURLLoader; } @@ -21,7 +21,7 @@ class ActiveLoader { public: // Creates an ActiveLoader with the given loader. It is assumed that the // initial state of |loader| is loading and not deferred. - explicit ActiveLoader(scoped_ptr<WebKit::WebURLLoader> loader); + explicit ActiveLoader(scoped_ptr<blink::WebURLLoader> loader); ~ActiveLoader(); // Starts or stops deferring the resource load. @@ -31,7 +31,7 @@ class ActiveLoader { private: friend class BufferedDataSourceTest; - scoped_ptr<WebKit::WebURLLoader> loader_; + scoped_ptr<blink::WebURLLoader> loader_; bool deferred_; DISALLOW_IMPLICIT_CONSTRUCTORS(ActiveLoader); diff --git a/chromium/content/renderer/media/android/audio_decoder_android.cc b/chromium/content/renderer/media/android/audio_decoder_android.cc index afc6dec62e3..b589d67412c 100644 --- a/chromium/content/renderer/media/android/audio_decoder_android.cc +++ b/chromium/content/renderer/media/android/audio_decoder_android.cc @@ -113,7 +113,7 @@ class WAVEDecoder { // WAVE file, |destination_bus| is filled with the decoded data and // DecodeWAVEFile returns true. Otherwise, DecodeWAVEFile returns // false. - bool DecodeWAVEFile(WebKit::WebAudioBus* destination_bus); + bool DecodeWAVEFile(blink::WebAudioBus* destination_bus); private: // Minimum number of bytes in a WAVE file to hold all of the data we @@ -157,7 +157,7 @@ class WAVEDecoder { // Read data chunk and save it to |destination_bus|. Returns false // if the data chunk could not be read correctly. - bool CopyDataChunkToBus(WebKit::WebAudioBus* destination_bus); + bool CopyDataChunkToBus(blink::WebAudioBus* destination_bus); // The WAVE chunk ID that identifies the chunk. uint8_t chunk_id_[kChunkIDLength]; @@ -293,7 +293,7 @@ bool WAVEDecoder::ReadFMTChunk() { return false; } -bool WAVEDecoder::CopyDataChunkToBus(WebKit::WebAudioBus* destination_bus) { +bool WAVEDecoder::CopyDataChunkToBus(blink::WebAudioBus* destination_bus) { // The data chunk contains the audio data itself. if (!bytes_per_sample_ || bytes_per_sample_ > kMaximumBytesPerSample) { DVLOG(1) << "WARNING: data chunk without preceeding fmt chunk," @@ -326,7 +326,7 @@ bool WAVEDecoder::CopyDataChunkToBus(WebKit::WebAudioBus* destination_bus) { return true; } -bool WAVEDecoder::DecodeWAVEFile(WebKit::WebAudioBus* destination_bus) { +bool WAVEDecoder::DecodeWAVEFile(blink::WebAudioBus* destination_bus) { // Parse and decode WAVE file. If we can't parse it, return false. if (buffer_ + kMinimumWAVLength > buffer_end_) { @@ -395,7 +395,7 @@ bool WAVEDecoder::DecodeWAVEFile(WebKit::WebAudioBus* destination_bus) { // bus and copy the pcm data to the destination bus as it's being // received. static void CopyPcmDataToBus(int input_fd, - WebKit::WebAudioBus* destination_bus, + blink::WebAudioBus* destination_bus, size_t number_of_frames, unsigned number_of_channels, double file_sample_rate) { @@ -433,7 +433,7 @@ static void CopyPcmDataToBus(int input_fd, // until there's no more data and then copy the data to the // destination bus. static void BufferAndCopyPcmDataToBus(int input_fd, - WebKit::WebAudioBus* destination_bus, + blink::WebAudioBus* destination_bus, unsigned number_of_channels, double file_sample_rate) { int16_t pipe_data[PIPE_BUF / sizeof(int16_t)]; @@ -478,7 +478,7 @@ static void BufferAndCopyPcmDataToBus(int input_fd, destination_bus->resizeSmaller(decoded_frames); } -static bool TryWAVEFileDecoder(WebKit::WebAudioBus* destination_bus, +static bool TryWAVEFileDecoder(blink::WebAudioBus* destination_bus, const uint8_t* encoded_data, size_t data_size) { WAVEDecoder decoder(encoded_data, data_size); @@ -493,7 +493,7 @@ static bool TryWAVEFileDecoder(WebKit::WebAudioBus* destination_bus, // to the browser to start the decoder using this buffer and one end // of a pipe. The MediaCodec class will decode the data from the // shared memory and write the PCM samples back to us over a pipe. -bool DecodeAudioFileData(WebKit::WebAudioBus* destination_bus, const char* data, +bool DecodeAudioFileData(blink::WebAudioBus* destination_bus, const char* data, size_t data_size, double sample_rate, scoped_refptr<ThreadSafeSender> sender) { // Try to decode the data as a WAVE file first. If it can't be diff --git a/chromium/content/renderer/media/android/audio_decoder_android.h b/chromium/content/renderer/media/android/audio_decoder_android.h index c6c3b403b6a..d2cac1575df 100644 --- a/chromium/content/renderer/media/android/audio_decoder_android.h +++ b/chromium/content/renderer/media/android/audio_decoder_android.h @@ -7,13 +7,13 @@ #include "content/child/thread_safe_sender.h" -namespace WebKit { +namespace blink { class WebAudioBus; } namespace content { -bool DecodeAudioFileData(WebKit::WebAudioBus* destination_bus, +bool DecodeAudioFileData(blink::WebAudioBus* destination_bus, const char* data, size_t data_size, double sample_rate, diff --git a/chromium/content/renderer/media/android/media_info_loader.cc b/chromium/content/renderer/media/android/media_info_loader.cc index 1025550580b..875265c41c5 100644 --- a/chromium/content/renderer/media/android/media_info_loader.cc +++ b/chromium/content/renderer/media/android/media_info_loader.cc @@ -12,12 +12,12 @@ #include "third_party/WebKit/public/platform/WebURLResponse.h" #include "third_party/WebKit/public/web/WebFrame.h" -using WebKit::WebFrame; -using WebKit::WebURLError; -using WebKit::WebURLLoader; -using WebKit::WebURLLoaderOptions; -using WebKit::WebURLRequest; -using WebKit::WebURLResponse; +using blink::WebFrame; +using blink::WebURLError; +using blink::WebURLLoader; +using blink::WebURLLoaderOptions; +using blink::WebURLRequest; +using blink::WebURLResponse; namespace content { @@ -25,7 +25,7 @@ static const int kHttpOK = 200; MediaInfoLoader::MediaInfoLoader( const GURL& url, - WebKit::WebMediaPlayer::CORSMode cors_mode, + blink::WebMediaPlayer::CORSMode cors_mode, const ReadyCB& ready_cb) : loader_failed_(false), url_(url), @@ -35,7 +35,7 @@ MediaInfoLoader::MediaInfoLoader( MediaInfoLoader::~MediaInfoLoader() {} -void MediaInfoLoader::Start(WebKit::WebFrame* frame) { +void MediaInfoLoader::Start(blink::WebFrame* frame) { // Make sure we have not started. DCHECK(!ready_cb_.is_null()); CHECK(frame); @@ -45,22 +45,24 @@ void MediaInfoLoader::Start(WebKit::WebFrame* frame) { // Prepare the request. WebURLRequest request(url_); request.setTargetType(WebURLRequest::TargetIsMedia); - frame->setReferrerForRequest(request, WebKit::WebURL()); + frame->setReferrerForRequest(request, blink::WebURL()); scoped_ptr<WebURLLoader> loader; if (test_loader_) { loader = test_loader_.Pass(); } else { WebURLLoaderOptions options; - if (cors_mode_ == WebKit::WebMediaPlayer::CORSModeUnspecified) { + if (cors_mode_ == blink::WebMediaPlayer::CORSModeUnspecified) { options.allowCredentials = true; options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyAllow; } else { options.exposeAllResponseHeaders = true; + // The author header set is empty, no preflight should go ahead. + options.preflightPolicy = WebURLLoaderOptions::PreventPreflight; options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; - if (cors_mode_ == WebKit::WebMediaPlayer::CORSModeUseCredentials) + if (cors_mode_ == blink::WebMediaPlayer::CORSModeUseCredentials) options.allowCredentials = true; } loader.reset(frame->createAssociatedURLLoader(options)); @@ -72,7 +74,7 @@ void MediaInfoLoader::Start(WebKit::WebFrame* frame) { } ///////////////////////////////////////////////////////////////////////////// -// WebKit::WebURLLoaderClient implementation. +// blink::WebURLLoaderClient implementation. void MediaInfoLoader::willSendRequest( WebURLLoader* loader, WebURLRequest& newRequest, @@ -81,7 +83,7 @@ void MediaInfoLoader::willSendRequest( // In this case we shouldn't do anything. if (ready_cb_.is_null()) { // Set the url in the request to an invalid value (empty url). - newRequest.setURL(WebKit::WebURL()); + newRequest.setURL(blink::WebURL()); return; } @@ -109,7 +111,11 @@ void MediaInfoLoader::didReceiveResponse( "Unknown") << " " << response.httpStatusCode(); DCHECK(active_loader_.get()); - if (response.httpStatusCode() == kHttpOK || url_.SchemeIsFile()) { + if (!url_.SchemeIs("http") && !url_.SchemeIs("https")) { + DidBecomeReady(kOk); + return; + } + if (response.httpStatusCode() == kHttpOK) { DidBecomeReady(kOk); return; } @@ -126,7 +132,7 @@ void MediaInfoLoader::didReceiveData( } void MediaInfoLoader::didDownloadData( - WebKit::WebURLLoader* loader, + blink::WebURLLoader* loader, int dataLength, int encodedDataLength) { NOTIMPLEMENTED(); @@ -169,7 +175,7 @@ bool MediaInfoLoader::DidPassCORSAccessCheck() const { DCHECK(ready_cb_.is_null()) << "Must become ready before calling DidPassCORSAccessCheck()"; return !loader_failed_ && - cors_mode_ != WebKit::WebMediaPlayer::CORSModeUnspecified; + cors_mode_ != blink::WebMediaPlayer::CORSModeUnspecified; } ///////////////////////////////////////////////////////////////////////////// diff --git a/chromium/content/renderer/media/android/media_info_loader.h b/chromium/content/renderer/media/android/media_info_loader.h index 5a6fc054b22..8e67c80c0c9 100644 --- a/chromium/content/renderer/media/android/media_info_loader.h +++ b/chromium/content/renderer/media/android/media_info_loader.h @@ -12,11 +12,11 @@ #include "base/time/time.h" #include "content/common/content_export.h" #include "content/renderer/media/active_loader.h" +#include "third_party/WebKit/public/platform/WebMediaPlayer.h" #include "third_party/WebKit/public/platform/WebURLLoaderClient.h" -#include "third_party/WebKit/public/web/WebMediaPlayer.h" #include "url/gurl.h" -namespace WebKit { +namespace blink { class WebFrame; class WebURLLoader; class WebURLRequest; @@ -27,7 +27,7 @@ namespace content { // This class provides additional information about a media URL. Currently it // can be used to determine if a media URL has a single security origin and // whether the URL passes a CORS access check. -class CONTENT_EXPORT MediaInfoLoader : private WebKit::WebURLLoaderClient { +class CONTENT_EXPORT MediaInfoLoader : private blink::WebURLLoaderClient { public: // Status codes for start operations on MediaInfoLoader. enum Status { @@ -51,12 +51,12 @@ class CONTENT_EXPORT MediaInfoLoader : private WebKit::WebURLLoaderClient { typedef base::Callback<void(Status)> ReadyCB; MediaInfoLoader( const GURL& url, - WebKit::WebMediaPlayer::CORSMode cors_mode, + blink::WebMediaPlayer::CORSMode cors_mode, const ReadyCB& ready_cb); virtual ~MediaInfoLoader(); // Start loading media info. - void Start(WebKit::WebFrame* frame); + void Start(blink::WebFrame* frame); // Returns true if the media resource has a single origin, false otherwise. // Only valid to call after the loader becomes ready. @@ -69,48 +69,48 @@ class CONTENT_EXPORT MediaInfoLoader : private WebKit::WebURLLoaderClient { private: friend class MediaInfoLoaderTest; - // WebKit::WebURLLoaderClient implementation. + // blink::WebURLLoaderClient implementation. virtual void willSendRequest( - WebKit::WebURLLoader* loader, - WebKit::WebURLRequest& newRequest, - const WebKit::WebURLResponse& redirectResponse); + blink::WebURLLoader* loader, + blink::WebURLRequest& newRequest, + const blink::WebURLResponse& redirectResponse); virtual void didSendData( - WebKit::WebURLLoader* loader, + blink::WebURLLoader* loader, unsigned long long bytesSent, unsigned long long totalBytesToBeSent); virtual void didReceiveResponse( - WebKit::WebURLLoader* loader, - const WebKit::WebURLResponse& response); + blink::WebURLLoader* loader, + const blink::WebURLResponse& response); virtual void didDownloadData( - WebKit::WebURLLoader* loader, + blink::WebURLLoader* loader, int data_length, int encodedDataLength); virtual void didReceiveData( - WebKit::WebURLLoader* loader, + blink::WebURLLoader* loader, const char* data, int data_length, int encoded_data_length); virtual void didReceiveCachedMetadata( - WebKit::WebURLLoader* loader, + blink::WebURLLoader* loader, const char* data, int dataLength); virtual void didFinishLoading( - WebKit::WebURLLoader* loader, + blink::WebURLLoader* loader, double finishTime); virtual void didFail( - WebKit::WebURLLoader* loader, - const WebKit::WebURLError&); + blink::WebURLLoader* loader, + const blink::WebURLError&); void DidBecomeReady(Status status); // Injected WebURLLoader instance for testing purposes. - scoped_ptr<WebKit::WebURLLoader> test_loader_; + scoped_ptr<blink::WebURLLoader> test_loader_; // Keeps track of an active WebURLLoader and associated state. scoped_ptr<ActiveLoader> active_loader_; bool loader_failed_; GURL url_; - WebKit::WebMediaPlayer::CORSMode cors_mode_; + blink::WebMediaPlayer::CORSMode cors_mode_; bool single_origin_; ReadyCB ready_cb_; diff --git a/chromium/content/renderer/media/android/media_info_loader_unittest.cc b/chromium/content/renderer/media/android/media_info_loader_unittest.cc index 37e41b18a04..65bfba8e77c 100644 --- a/chromium/content/renderer/media/android/media_info_loader_unittest.cc +++ b/chromium/content/renderer/media/android/media_info_loader_unittest.cc @@ -5,25 +5,22 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" #include "content/renderer/media/android/media_info_loader.h" +#include "content/test/mock_webframeclient.h" +#include "content/test/mock_weburlloader.h" +#include "third_party/WebKit/public/platform/WebMediaPlayer.h" #include "third_party/WebKit/public/platform/WebURLError.h" #include "third_party/WebKit/public/platform/WebURLRequest.h" #include "third_party/WebKit/public/platform/WebURLResponse.h" -#include "third_party/WebKit/public/web/WebMediaPlayer.h" #include "third_party/WebKit/public/web/WebView.h" -#include "webkit/mocks/mock_webframeclient.h" -#include "webkit/mocks/mock_weburlloader.h" using ::testing::_; using ::testing::InSequence; using ::testing::NiceMock; -using WebKit::WebString; -using WebKit::WebURLError; -using WebKit::WebURLResponse; -using WebKit::WebView; - -using webkit_glue::MockWebFrameClient; -using webkit_glue::MockWebURLLoader; +using blink::WebString; +using blink::WebURLError; +using blink::WebURLResponse; +using blink::WebView; namespace content { @@ -48,7 +45,7 @@ class MediaInfoLoaderTest : public testing::Test { void Initialize( const char* url, - WebKit::WebMediaPlayer::CORSMode cors_mode) { + blink::WebMediaPlayer::CORSMode cors_mode) { gurl_ = GURL(url); loader_.reset(new MediaInfoLoader( @@ -58,7 +55,7 @@ class MediaInfoLoaderTest : public testing::Test { // |test_loader_| will be used when Start() is called. url_loader_ = new NiceMock<MockWebURLLoader>(); - loader_->test_loader_ = scoped_ptr<WebKit::WebURLLoader>(url_loader_); + loader_->test_loader_ = scoped_ptr<blink::WebURLLoader>(url_loader_); } void Start() { @@ -75,8 +72,8 @@ class MediaInfoLoaderTest : public testing::Test { void Redirect(const char* url) { GURL redirect_url(url); - WebKit::WebURLRequest new_request(redirect_url); - WebKit::WebURLResponse redirect_response(gurl_); + blink::WebURLRequest new_request(redirect_url); + blink::WebURLResponse redirect_response(gurl_); loader_->willSendRequest(url_loader_, new_request, redirect_response); @@ -119,20 +116,20 @@ class MediaInfoLoaderTest : public testing::Test { }; TEST_F(MediaInfoLoaderTest, StartStop) { - Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUnspecified); + Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUnspecified); Start(); Stop(); } TEST_F(MediaInfoLoaderTest, LoadFailure) { - Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUnspecified); + Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUnspecified); Start(); FailLoad(); } TEST_F(MediaInfoLoaderTest, HasSingleOriginNoRedirect) { // Make sure no redirect case works as expected. - Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUnspecified); + Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUnspecified); Start(); SendResponse(kHttpOK, MediaInfoLoader::kOk); EXPECT_TRUE(loader_->HasSingleOrigin()); @@ -140,7 +137,7 @@ TEST_F(MediaInfoLoaderTest, HasSingleOriginNoRedirect) { TEST_F(MediaInfoLoaderTest, HasSingleOriginSingleRedirect) { // Test redirect to the same domain. - Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUnspecified); + Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUnspecified); Start(); Redirect(kHttpRedirectToSameDomainUrl1); SendResponse(kHttpOK, MediaInfoLoader::kOk); @@ -149,7 +146,7 @@ TEST_F(MediaInfoLoaderTest, HasSingleOriginSingleRedirect) { TEST_F(MediaInfoLoaderTest, HasSingleOriginDoubleRedirect) { // Test redirect twice to the same domain. - Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUnspecified); + Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUnspecified); Start(); Redirect(kHttpRedirectToSameDomainUrl1); Redirect(kHttpRedirectToSameDomainUrl2); @@ -159,7 +156,7 @@ TEST_F(MediaInfoLoaderTest, HasSingleOriginDoubleRedirect) { TEST_F(MediaInfoLoaderTest, HasSingleOriginDifferentDomain) { // Test redirect to a different domain. - Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUnspecified); + Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUnspecified); Start(); Redirect(kHttpRedirectToDifferentDomainUrl1); SendResponse(kHttpOK, MediaInfoLoader::kOk); @@ -168,7 +165,7 @@ TEST_F(MediaInfoLoaderTest, HasSingleOriginDifferentDomain) { TEST_F(MediaInfoLoaderTest, HasSingleOriginMultipleDomains) { // Test redirect to the same domain and then to a different domain. - Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUnspecified); + Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUnspecified); Start(); Redirect(kHttpRedirectToSameDomainUrl1); Redirect(kHttpRedirectToDifferentDomainUrl1); @@ -177,14 +174,14 @@ TEST_F(MediaInfoLoaderTest, HasSingleOriginMultipleDomains) { } TEST_F(MediaInfoLoaderTest, CORSAccessCheckPassed) { - Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUseCredentials); + Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUseCredentials); Start(); SendResponse(kHttpOK, MediaInfoLoader::kOk); EXPECT_TRUE(loader_->DidPassCORSAccessCheck()); } TEST_F(MediaInfoLoaderTest, CORSAccessCheckFailed) { - Initialize(kHttpUrl, WebKit::WebMediaPlayer::CORSModeUseCredentials); + Initialize(kHttpUrl, blink::WebMediaPlayer::CORSModeUseCredentials); Start(); SendResponse(kHttpNotFound, MediaInfoLoader::kFailed); EXPECT_FALSE(loader_->DidPassCORSAccessCheck()); diff --git a/chromium/content/renderer/media/android/media_source_delegate.cc b/chromium/content/renderer/media/android/media_source_delegate.cc index eae0fe11301..57fc0157ca4 100644 --- a/chromium/content/renderer/media/android/media_source_delegate.cc +++ b/chromium/content/renderer/media/android/media_source_delegate.cc @@ -25,8 +25,8 @@ using media::DemuxerStream; using media::DemuxerConfigs; using media::DemuxerData; -using WebKit::WebMediaPlayer; -using WebKit::WebString; +using blink::WebMediaPlayer; +using blink::WebString; namespace { @@ -40,13 +40,6 @@ const uint8 kVorbisPadding[] = { 0xff, 0xff, 0xff, 0xff }; namespace content { -static scoped_ptr<media::TextTrack> ReturnNullTextTrack( - media::TextKind kind, - const std::string& label, - const std::string& language) { - return scoped_ptr<media::TextTrack>(); -} - static void LogMediaSourceError(const scoped_refptr<media::MediaLog>& media_log, const std::string& error) { media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error)); @@ -70,7 +63,9 @@ MediaSourceDelegate::MediaSourceDelegate( audio_stream_(NULL), video_stream_(NULL), seeking_(false), - last_seek_request_id_(0), + doing_browser_seek_(false), + browser_seek_time_(media::kNoTimestamp()), + expecting_regular_seek_(false), #if defined(GOOGLE_TV) key_added_(false), #endif @@ -101,7 +96,6 @@ void MediaSourceDelegate::Destroy() { } duration_change_cb_.Reset(); - time_update_seek_hack_cb_.Reset(); update_network_state_cb_.Reset(); media_source_opened_cb_.Reset(); @@ -145,11 +139,10 @@ void MediaSourceDelegate::StopDemuxer() { void MediaSourceDelegate::InitializeMediaSource( const MediaSourceOpenedCB& media_source_opened_cb, - const media::NeedKeyCB& need_key_cb, + const media::Demuxer::NeedKeyCB& need_key_cb, const media::SetDecryptorReadyCB& set_decryptor_ready_cb, const UpdateNetworkStateCB& update_network_state_cb, - const DurationChangeCB& duration_change_cb, - const TimeUpdateSeekHackCB& time_update_seek_hack_cb) { + const DurationChangeCB& duration_change_cb) { DCHECK(main_loop_->BelongsToCurrentThread()); DCHECK(!media_source_opened_cb.is_null()); media_source_opened_cb_ = media_source_opened_cb; @@ -157,7 +150,6 @@ void MediaSourceDelegate::InitializeMediaSource( set_decryptor_ready_cb_ = set_decryptor_ready_cb; update_network_state_cb_ = media::BindToCurrentLoop(update_network_state_cb); duration_change_cb_ = duration_change_cb; - time_update_seek_hack_cb_ = time_update_seek_hack_cb; access_unit_size_ = kAccessUnitSizeForMediaSource; chunk_demuxer_.reset(new media::ChunkDemuxer( @@ -165,7 +157,6 @@ void MediaSourceDelegate::InitializeMediaSource( &MediaSourceDelegate::OnDemuxerOpened, main_weak_this_)), media::BindToCurrentLoop(base::Bind( &MediaSourceDelegate::OnNeedKey, main_weak_this_)), - base::Bind(&ReturnNullTextTrack), base::Bind(&LogMediaSourceError, media_log_))); demuxer_ = chunk_demuxer_.get(); @@ -180,7 +171,8 @@ void MediaSourceDelegate::InitializeDemuxer() { DCHECK(media_loop_->BelongsToCurrentThread()); demuxer_client_->AddDelegate(demuxer_client_id_, this); demuxer_->Initialize(this, base::Bind(&MediaSourceDelegate::OnDemuxerInitDone, - media_weak_factory_.GetWeakPtr())); + media_weak_factory_.GetWeakPtr()), + false); } #if defined(GOOGLE_TV) @@ -203,7 +195,7 @@ void MediaSourceDelegate::InitializeMediaStream( } #endif -const WebKit::WebTimeRanges& MediaSourceDelegate::Buffered() { +const blink::WebTimeRanges& MediaSourceDelegate::Buffered() { buffered_web_time_ranges_ = ConvertToWebTimeRanges(buffered_time_ranges_); return buffered_web_time_ranges_; @@ -225,46 +217,106 @@ size_t MediaSourceDelegate::VideoDecodedByteCount() const { return statistics_.video_bytes_decoded; } -void MediaSourceDelegate::Seek(const base::TimeDelta& time, - unsigned seek_request_id) { - DCHECK(media_loop_->BelongsToCurrentThread()); - DVLOG(1) << __FUNCTION__ << "(" << time.InSecondsF() << ") : " +void MediaSourceDelegate::CancelPendingSeek(const base::TimeDelta& seek_time) { + DCHECK(main_loop_->BelongsToCurrentThread()); + DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ") : " << demuxer_client_id_; - last_seek_time_ = time; - last_seek_request_id_ = seek_request_id; + if (!chunk_demuxer_) + return; + + { + // Remember to trivially finish any newly arriving browser seek requests + // that may arrive prior to the next regular seek request. + base::AutoLock auto_lock(seeking_lock_); + expecting_regular_seek_ = true; + } + + // Cancel any previously expected or in-progress regular or browser seek. + // It is possible that we have just finished the seek, but caller does + // not know this yet. It is still safe to cancel in this case because the + // caller will always call StartWaitingForSeek() when it is notified of + // the finished seek. + chunk_demuxer_->CancelPendingSeek(seek_time); +} + +void MediaSourceDelegate::StartWaitingForSeek( + const base::TimeDelta& seek_time) { + DCHECK(main_loop_->BelongsToCurrentThread()); + DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ") : " + << demuxer_client_id_; - if (chunk_demuxer_) { - if (IsSeeking()) { - chunk_demuxer_->CancelPendingSeek(time); + if (!chunk_demuxer_) + return; + + bool cancel_browser_seek = false; + { + // Remember to trivially finish any newly arriving browser seek requests + // that may arrive prior to the next regular seek request. + base::AutoLock auto_lock(seeking_lock_); + expecting_regular_seek_ = true; + + // Remember to cancel any in-progress browser seek. + if (seeking_) { + DCHECK(doing_browser_seek_); + cancel_browser_seek = true; + } + } + + if (cancel_browser_seek) + chunk_demuxer_->CancelPendingSeek(seek_time); + chunk_demuxer_->StartWaitingForSeek(seek_time); +} + +void MediaSourceDelegate::Seek( + const base::TimeDelta& seek_time, bool is_browser_seek) { + DCHECK(media_loop_->BelongsToCurrentThread()); + DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ", " + << (is_browser_seek ? "browser seek" : "regular seek") << ") : " + << demuxer_client_id_; + + base::TimeDelta internal_seek_time = seek_time; + { + base::AutoLock auto_lock(seeking_lock_); + DCHECK(!seeking_); + seeking_ = true; + doing_browser_seek_ = is_browser_seek; + + if (doing_browser_seek_ && (!chunk_demuxer_ || expecting_regular_seek_)) { + // Trivially finish the browser seek without actually doing it. Reads will + // continue to be |kAborted| until the next regular seek is done. Browser + // seeking is not supported unless using a ChunkDemuxer; browser seeks are + // trivially finished if |chunk_demuxer_| is NULL. + seeking_ = false; + doing_browser_seek_ = false; + demuxer_client_->DemuxerSeekDone(demuxer_client_id_, seek_time); return; } - chunk_demuxer_->StartWaitingForSeek(time); + if (doing_browser_seek_) { + internal_seek_time = FindBufferedBrowserSeekTime_Locked(seek_time); + browser_seek_time_ = internal_seek_time; + } else { + expecting_regular_seek_ = false; + browser_seek_time_ = media::kNoTimestamp(); + } } - SetSeeking(true); - SeekInternal(time, seek_request_id); - - // During fullscreen media source playback Seek() can be called without - // WebMediaPlayerAndroid's knowledge. We need to inform it that a seek is - // in progress so the correct time can be returned to web applications while - // seeking. - // - // TODO(wolenetz): Remove after landing a uniform seeking codepath. - if (!time_update_seek_hack_cb_.is_null()) { - main_loop_->PostTask(FROM_HERE, - base::Bind(time_update_seek_hack_cb_, time)); + // Prepare |chunk_demuxer_| for browser seek. + if (is_browser_seek) { + chunk_demuxer_->CancelPendingSeek(internal_seek_time); + chunk_demuxer_->StartWaitingForSeek(internal_seek_time); } + + SeekInternal(internal_seek_time); } -void MediaSourceDelegate::SeekInternal(const base::TimeDelta& time, - unsigned request_id) { +void MediaSourceDelegate::SeekInternal(const base::TimeDelta& seek_time) { DCHECK(media_loop_->BelongsToCurrentThread()); DCHECK(IsSeeking()); - demuxer_->Seek(time, base::Bind( - &MediaSourceDelegate::OnDemuxerSeekDone, media_weak_factory_.GetWeakPtr(), - request_id)); + demuxer_->Seek(seek_time, base::Bind( + &MediaSourceDelegate::OnDemuxerSeekDone, + media_weak_factory_.GetWeakPtr())); } void MediaSourceDelegate::SetTotalBytes(int64 total_bytes) { @@ -447,6 +499,19 @@ void MediaSourceDelegate::OnDemuxerError(media::PipelineStatus status) { update_network_state_cb_.Run(PipelineErrorToNetworkState(status)); } +void MediaSourceDelegate::AddTextStream( + media::DemuxerStream* /* text_stream */ , + const media::TextTrackConfig& /* config */ ) { + // TODO(matthewjheaney): add text stream (http://crbug/322115). + NOTIMPLEMENTED(); +} + +void MediaSourceDelegate::RemoveTextStream( + media::DemuxerStream* /* text_stream */ ) { + // TODO(matthewjheaney): remove text stream (http://crbug/322115). + NOTIMPLEMENTED(); +} + void MediaSourceDelegate::OnDemuxerInitDone(media::PipelineStatus status) { DCHECK(media_loop_->BelongsToCurrentThread()); DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_; @@ -546,8 +611,7 @@ void MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone( NotifyDemuxerReady(); } -void MediaSourceDelegate::OnDemuxerSeekDone(unsigned seek_request_id, - media::PipelineStatus status) { +void MediaSourceDelegate::OnDemuxerSeekDone(media::PipelineStatus status) { DCHECK(media_loop_->BelongsToCurrentThread()); DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_; DCHECK(IsSeeking()); @@ -557,14 +621,6 @@ void MediaSourceDelegate::OnDemuxerSeekDone(unsigned seek_request_id, return; } - // Newer seek has been issued. Resume the last seek request. - if (seek_request_id != last_seek_request_id_) { - if (chunk_demuxer_) - chunk_demuxer_->StartWaitingForSeek(last_seek_time_); - SeekInternal(last_seek_time_, last_seek_request_id_); - return; - } - ResetAudioDecryptingDemuxerStream(); } @@ -597,9 +653,12 @@ void MediaSourceDelegate::ResetVideoDecryptingDemuxerStream() { void MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams() { DCHECK(media_loop_->BelongsToCurrentThread()); DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_; - SetSeeking(false); - demuxer_client_->SeekRequestAck(demuxer_client_id_, last_seek_request_id_); - last_seek_request_id_ = 0; + + base::AutoLock auto_lock(seeking_lock_); + DCHECK(seeking_); + seeking_ = false; + doing_browser_seek_ = false; + demuxer_client_->DemuxerSeekDone(demuxer_client_id_, browser_seek_time_); } void MediaSourceDelegate::OnDemuxerStopDone() { @@ -718,8 +777,7 @@ void MediaSourceDelegate::OnNeedKey(const std::string& type, if (need_key_cb_.is_null()) return; - // TODO(xhwang): Remove |session_id| from media::NeedKeyCB. - need_key_cb_.Run("", type, init_data); + need_key_cb_.Run(type, init_data); } bool MediaSourceDelegate::HasEncryptedStream() { @@ -730,14 +788,50 @@ bool MediaSourceDelegate::HasEncryptedStream() { video_stream_->video_decoder_config().is_encrypted()); } -void MediaSourceDelegate::SetSeeking(bool seeking) { - base::AutoLock auto_lock(seeking_lock_); - seeking_ = seeking; -} - bool MediaSourceDelegate::IsSeeking() const { base::AutoLock auto_lock(seeking_lock_); return seeking_; } +base::TimeDelta MediaSourceDelegate::FindBufferedBrowserSeekTime_Locked( + const base::TimeDelta& seek_time) const { + seeking_lock_.AssertAcquired(); + DCHECK(seeking_); + DCHECK(doing_browser_seek_); + DCHECK(chunk_demuxer_) << "Browser seek requested, but no chunk demuxer"; + + media::Ranges<base::TimeDelta> buffered = + chunk_demuxer_->GetBufferedRanges(); + + for (size_t i = 0; i < buffered.size(); ++i) { + base::TimeDelta range_start = buffered.start(i); + base::TimeDelta range_end = buffered.end(i); + if (range_start <= seek_time) { + if (range_end >= seek_time) + return seek_time; + continue; + } + + // If the start of the next buffered range after |seek_time| is too far + // into the future, do not jump forward. + if ((range_start - seek_time) > base::TimeDelta::FromMilliseconds(100)) + break; + + // TODO(wolenetz): Remove possibility that this browser seek jumps + // into future when the requested range is unbuffered but there is some + // other buffered range after it. See http://crbug.com/304234. + return range_start; + } + + // We found no range containing |seek_time| or beginning shortly after + // |seek_time|. While possible that such data at and beyond the player's + // current time have been garbage collected or removed by the web app, this is + // unlikely. This may cause unexpected playback stall due to seek pending an + // append for a GOP prior to the last GOP demuxed. + // TODO(wolenetz): Remove the possibility for this seek to cause unexpected + // player stall by replaying cached data since last keyframe in browser player + // rather than issuing browser seek. See http://crbug.com/304234. + return seek_time; +} + } // namespace content diff --git a/chromium/content/renderer/media/android/media_source_delegate.h b/chromium/content/renderer/media/android/media_source_delegate.h index d519c093836..317ef6544df 100644 --- a/chromium/content/renderer/media/android/media_source_delegate.h +++ b/chromium/content/renderer/media/android/media_source_delegate.h @@ -20,7 +20,7 @@ #include "media/base/pipeline_status.h" #include "media/base/ranges.h" #include "media/base/text_track.h" -#include "third_party/WebKit/public/web/WebMediaPlayer.h" +#include "third_party/WebKit/public/platform/WebMediaPlayer.h" namespace media { class ChunkDemuxer; @@ -38,12 +38,11 @@ class RendererDemuxerAndroid; class MediaSourceDelegate : public media::DemuxerHost { public: - typedef base::Callback<void(WebKit::WebMediaSource*)> + typedef base::Callback<void(blink::WebMediaSource*)> MediaSourceOpenedCB; - typedef base::Callback<void(WebKit::WebMediaPlayer::NetworkState)> + typedef base::Callback<void(blink::WebMediaPlayer::NetworkState)> UpdateNetworkStateCB; typedef base::Callback<void(const base::TimeDelta&)> DurationChangeCB; - typedef base::Callback<void(const base::TimeDelta&)> TimeUpdateSeekHackCB; // Helper class used by scoped_ptr to destroy an instance of // MediaSourceDelegate. @@ -63,11 +62,10 @@ class MediaSourceDelegate : public media::DemuxerHost { // this object after this call. void InitializeMediaSource( const MediaSourceOpenedCB& media_source_opened_cb, - const media::NeedKeyCB& need_key_cb, + const media::Demuxer::NeedKeyCB& need_key_cb, const media::SetDecryptorReadyCB& set_decryptor_ready_cb, const UpdateNetworkStateCB& update_network_state_cb, - const DurationChangeCB& duration_change_cb, - const TimeUpdateSeekHackCB& time_update_seek_hack_cb); + const DurationChangeCB& duration_change_cb); #if defined(GOOGLE_TV) void InitializeMediaStream( @@ -75,16 +73,32 @@ class MediaSourceDelegate : public media::DemuxerHost { const UpdateNetworkStateCB& update_network_state_cb); #endif - const WebKit::WebTimeRanges& Buffered(); + const blink::WebTimeRanges& Buffered(); size_t DecodedFrameCount() const; size_t DroppedFrameCount() const; size_t AudioDecodedByteCount() const; size_t VideoDecodedByteCount() const; - // Seeks the demuxer and acknowledges the seek request with |seek_request_id| - // after the seek has been completed. This method can be called during pending - // seeks, in which case only the last seek request will be acknowledged. - void Seek(const base::TimeDelta& time, unsigned seek_request_id); + // In MSE case, calls ChunkDemuxer::CancelPendingSeek(). Also sets the + // expectation that a regular seek will be arriving and to trivially finish + // any browser seeks that may be requested prior to the regular seek. + void CancelPendingSeek(const base::TimeDelta& seek_time); + + // In MSE case, calls ChunkDemuxer::StartWaitingForSeek(), first calling + // ChunkDemuxer::CancelPendingSeek() if a browser seek is in progress. + // Also sets the expectation that a regular seek will be arriving and to + // trivially finish any browser seeks that may be requested prior to the + // regular seek. + void StartWaitingForSeek(const base::TimeDelta& seek_time); + + // Seeks the demuxer and later calls OnDemuxerSeekDone() after the seek has + // been completed. There must be no other seek of the demuxer currently in + // process when this method is called. + // If |is_browser_seek| is true, then this is a short-term hack browser + // seek. + // TODO(wolenetz): Instead of doing browser seek, browser player should replay + // cached data since last keyframe. See http://crbug.com/304234. + void Seek(const base::TimeDelta& seek_time, bool is_browser_seek); void NotifyKeyAdded(const std::string& key_system); @@ -113,6 +127,9 @@ class MediaSourceDelegate : public media::DemuxerHost { base::TimeDelta end) OVERRIDE; virtual void SetDuration(base::TimeDelta duration) OVERRIDE; virtual void OnDemuxerError(media::PipelineStatus status) OVERRIDE; + virtual void AddTextStream(media::DemuxerStream* text_stream, + const media::TextTrackConfig& config) OVERRIDE; + virtual void RemoveTextStream(media::DemuxerStream* text_stream) OVERRIDE; // Notifies |demuxer_client_| and fires |duration_changed_cb_|. void OnDurationChanged(const base::TimeDelta& duration); @@ -132,8 +149,7 @@ class MediaSourceDelegate : public media::DemuxerHost { // decrypted audio/video streams if present. // // Runs on the media thread. - void OnDemuxerSeekDone(unsigned seek_request_id, - media::PipelineStatus status); + void OnDemuxerSeekDone(media::PipelineStatus status); void ResetAudioDecryptingDemuxerStream(); void ResetVideoDecryptingDemuxerStream(); void FinishResettingDecryptingDemuxerStreams(); @@ -147,7 +163,7 @@ class MediaSourceDelegate : public media::DemuxerHost { void StopDemuxer(); void InitializeDemuxer(); - void SeekInternal(const base::TimeDelta& time, unsigned seek_request_id); + void SeekInternal(const base::TimeDelta& seek_time); // Reads an access unit from the demuxer stream |stream| and stores it in // the |index|th access unit in |params|. void ReadFromDemuxerStream(media::DemuxerStream::Type type, @@ -164,9 +180,16 @@ class MediaSourceDelegate : public media::DemuxerHost { bool HasEncryptedStream(); - void SetSeeking(bool seeking); bool IsSeeking() const; + // Returns |seek_time| if it is still buffered or if there is no currently + // buffered range including or soon after |seek_time|. If |seek_time| is not + // buffered, but there is a later range buffered near to |seek_time|, returns + // next buffered range's start time instead. Only call this for browser seeks. + // |seeking_lock_| must be held by caller. + base::TimeDelta FindBufferedBrowserSeekTime_Locked( + const base::TimeDelta& seek_time) const; + // Message loop for main renderer thread and corresponding weak pointer. const scoped_refptr<base::MessageLoopProxy> main_loop_; base::WeakPtrFactory<MediaSourceDelegate> main_weak_factory_; @@ -182,7 +205,6 @@ class MediaSourceDelegate : public media::DemuxerHost { scoped_refptr<media::MediaLog> media_log_; UpdateNetworkStateCB update_network_state_cb_; DurationChangeCB duration_change_cb_; - TimeUpdateSeekHackCB time_update_seek_hack_cb_; scoped_ptr<media::ChunkDemuxer> chunk_demuxer_; media::Demuxer* demuxer_; @@ -199,14 +221,14 @@ class MediaSourceDelegate : public media::DemuxerHost { media::PipelineStatistics statistics_; media::Ranges<base::TimeDelta> buffered_time_ranges_; // Keep a list of buffered time ranges. - WebKit::WebTimeRanges buffered_web_time_ranges_; + blink::WebTimeRanges buffered_web_time_ranges_; MediaSourceOpenedCB media_source_opened_cb_; - media::NeedKeyCB need_key_cb_; + media::Demuxer::NeedKeyCB need_key_cb_; // The currently selected key system. Empty string means that no key system // has been selected. - WebKit::WebString current_key_system_; + blink::WebString current_key_system_; // Temporary for EME v0.1. In the future the init data type should be passed // through GenerateKeyRequest() directly from WebKit. @@ -216,8 +238,14 @@ class MediaSourceDelegate : public media::DemuxerHost { mutable base::Lock seeking_lock_; bool seeking_; - base::TimeDelta last_seek_time_; - unsigned last_seek_request_id_; + // Track if we are currently performing a browser seek, and track whether or + // not a regular seek is expected soon. If a regular seek is expected soon, + // then any in-progress browser seek will be canceled pending the + // regular seek, if using |chunk_demuxer_|, and any requested browser seek + // will be trivially finished. Access is serialized by |seeking_lock_|. + bool doing_browser_seek_; + base::TimeDelta browser_seek_time_; + bool expecting_regular_seek_; #if defined(GOOGLE_TV) bool key_added_; diff --git a/chromium/content/renderer/media/android/proxy_media_keys.cc b/chromium/content/renderer/media/android/proxy_media_keys.cc index 2beb66a478d..ef93a2552fb 100644 --- a/chromium/content/renderer/media/android/proxy_media_keys.cc +++ b/chromium/content/renderer/media/android/proxy_media_keys.cc @@ -8,15 +8,30 @@ #include "base/basictypes.h" #include "base/logging.h" -#include "content/renderer/media/android/webmediaplayer_proxy_android.h" +#include "content/renderer/media/android/renderer_media_player_manager.h" #include "content/renderer/media/crypto/key_systems.h" namespace content { -ProxyMediaKeys::ProxyMediaKeys(WebMediaPlayerProxyAndroid* proxy, - int media_keys_id) - : proxy_(proxy), media_keys_id_(media_keys_id) { - DCHECK(proxy_); +ProxyMediaKeys::ProxyMediaKeys( + RendererMediaPlayerManager* manager, + int media_keys_id, + const media::SessionCreatedCB& session_created_cb, + const media::SessionMessageCB& session_message_cb, + const media::SessionReadyCB& session_ready_cb, + const media::SessionClosedCB& session_closed_cb, + const media::SessionErrorCB& session_error_cb) + : manager_(manager), + media_keys_id_(media_keys_id), + session_created_cb_(session_created_cb), + session_message_cb_(session_message_cb), + session_ready_cb_(session_ready_cb), + session_closed_cb_(session_closed_cb), + session_error_cb_(session_error_cb) { + DCHECK(manager_); +} + +ProxyMediaKeys::~ProxyMediaKeys() { } void ProxyMediaKeys::InitializeCDM(const std::string& key_system, @@ -26,31 +41,58 @@ void ProxyMediaKeys::InitializeCDM(const std::string& key_system, #elif defined(OS_ANDROID) std::vector<uint8> uuid = GetUUID(key_system); DCHECK(!uuid.empty()); - proxy_->InitializeCDM(media_keys_id_, uuid, frame_url); + manager_->InitializeCDM(media_keys_id_, this, uuid, frame_url); #endif } -bool ProxyMediaKeys::GenerateKeyRequest(const std::string& type, - const uint8* init_data, - int init_data_length) { - proxy_->GenerateKeyRequest( +bool ProxyMediaKeys::CreateSession(uint32 session_id, + const std::string& type, + const uint8* init_data, + int init_data_length) { + manager_->CreateSession( media_keys_id_, + session_id, type, std::vector<uint8>(init_data, init_data + init_data_length)); return true; } -void ProxyMediaKeys::AddKey(const uint8* key, int key_length, - const uint8* init_data, int init_data_length, - const std::string& session_id) { - proxy_->AddKey(media_keys_id_, - std::vector<uint8>(key, key + key_length), - std::vector<uint8>(init_data, init_data + init_data_length), - session_id); +void ProxyMediaKeys::UpdateSession(uint32 session_id, + const uint8* response, + int response_length) { + manager_->UpdateSession( + media_keys_id_, + session_id, + std::vector<uint8>(response, response + response_length)); +} + +void ProxyMediaKeys::ReleaseSession(uint32 session_id) { + manager_->ReleaseSession(media_keys_id_, session_id); +} + +void ProxyMediaKeys::OnSessionCreated(uint32 session_id, + const std::string& web_session_id) { + session_created_cb_.Run(session_id, web_session_id); +} + +void ProxyMediaKeys::OnSessionMessage(uint32 session_id, + const std::vector<uint8>& message, + const std::string& destination_url) { + session_message_cb_.Run(session_id, message, destination_url); +} + +void ProxyMediaKeys::OnSessionReady(uint32 session_id) { + session_ready_cb_.Run(session_id); +} + +void ProxyMediaKeys::OnSessionClosed(uint32 session_id) { + session_closed_cb_.Run(session_id); } -void ProxyMediaKeys::CancelKeyRequest(const std::string& session_id) { - proxy_->CancelKeyRequest(media_keys_id_, session_id); +void ProxyMediaKeys::OnSessionError(uint32 session_id, + media::MediaKeys::KeyError error_code, + int system_code) { + session_error_cb_.Run(session_id, error_code, system_code); } } // namespace content diff --git a/chromium/content/renderer/media/android/proxy_media_keys.h b/chromium/content/renderer/media/android/proxy_media_keys.h index 847a78285f6..ca5c932d883 100644 --- a/chromium/content/renderer/media/android/proxy_media_keys.h +++ b/chromium/content/renderer/media/android/proxy_media_keys.h @@ -12,32 +12,56 @@ class GURL; namespace content { -class WebMediaPlayerProxyAndroid; +class RendererMediaPlayerManager; -// MediaKeys wrapper of the WebMediaPlayerProxyAndroid. -// TODO(xhwang): Remove |player_id| from WebMediaPlayerProxyAndroid, make -// WebMediaPlayerProxyAndroid a subclass of media::MediaKeys, then remove this -// class! +// A MediaKeys proxy that wraps the EME part of RendererMediaPlayerManager. +// TODO(xhwang): Instead of accessing RendererMediaPlayerManager directly, let +// RendererMediaPlayerManager return a MediaKeys object that can be used by +// ProxyDecryptor directly. Then we can remove this class! class ProxyMediaKeys : public media::MediaKeys { public: - ProxyMediaKeys(WebMediaPlayerProxyAndroid* proxy, int media_keys_id); + ProxyMediaKeys(RendererMediaPlayerManager* proxy, + int media_keys_id, + const media::SessionCreatedCB& session_created_cb, + const media::SessionMessageCB& session_message_cb, + const media::SessionReadyCB& session_ready_cb, + const media::SessionClosedCB& session_closed_cb, + const media::SessionErrorCB& session_error_cb); + virtual ~ProxyMediaKeys(); void InitializeCDM(const std::string& key_system, const GURL& frame_url); // MediaKeys implementation. - virtual bool GenerateKeyRequest(const std::string& type, - const uint8* init_data, - int init_data_length) OVERRIDE; - virtual void AddKey(const uint8* key, int key_length, - const uint8* init_data, int init_data_length, - const std::string& session_id) OVERRIDE; - virtual void CancelKeyRequest(const std::string& session_id) OVERRIDE; + virtual bool CreateSession(uint32 session_id, + const std::string& type, + const uint8* init_data, + int init_data_length) OVERRIDE; + virtual void UpdateSession(uint32 session_id, + const uint8* response, + int response_length) OVERRIDE; + virtual void ReleaseSession(uint32 session_id) OVERRIDE; + + // Callbacks. + void OnSessionCreated(uint32 session_id, const std::string& web_session_id); + void OnSessionMessage(uint32 session_id, + const std::vector<uint8>& message, + const std::string& destination_url); + void OnSessionReady(uint32 session_id); + void OnSessionClosed(uint32 session_id); + void OnSessionError(uint32 session_id, + media::MediaKeys::KeyError error_code, + int system_code); private: - WebMediaPlayerProxyAndroid* proxy_; + RendererMediaPlayerManager* manager_; int media_keys_id_; + media::SessionCreatedCB session_created_cb_; + media::SessionMessageCB session_message_cb_; + media::SessionReadyCB session_ready_cb_; + media::SessionClosedCB session_closed_cb_; + media::SessionErrorCB session_error_cb_; - DISALLOW_COPY_AND_ASSIGN (ProxyMediaKeys); + DISALLOW_COPY_AND_ASSIGN(ProxyMediaKeys); }; } // namespace content diff --git a/chromium/content/renderer/media/android/renderer_demuxer_android.cc b/chromium/content/renderer/media/android/renderer_demuxer_android.cc index 20d09570e29..ab139b5403e 100644 --- a/chromium/content/renderer/media/android/renderer_demuxer_android.cc +++ b/chromium/content/renderer/media/android/renderer_demuxer_android.cc @@ -40,7 +40,7 @@ void RendererDemuxerAndroid::RemoveDelegate(int demuxer_client_id) { bool RendererDemuxerAndroid::OnMessageReceived(const IPC::Message& message) { switch (message.type()) { - case MediaPlayerMsg_MediaSeekRequest::ID: + case MediaPlayerMsg_DemuxerSeekRequest::ID: case MediaPlayerMsg_ReadFromDemuxer::ID: case MediaPlayerMsg_MediaConfigRequest::ID: media_message_loop_->PostTask(FROM_HERE, base::Bind( @@ -64,10 +64,11 @@ void RendererDemuxerAndroid::ReadFromDemuxerAck( demuxer_client_id, data)); } -void RendererDemuxerAndroid::SeekRequestAck(int demuxer_client_id, - unsigned seek_request_id) { - thread_safe_sender_->Send(new MediaPlayerHostMsg_MediaSeekRequestAck( - demuxer_client_id, seek_request_id)); +void RendererDemuxerAndroid::DemuxerSeekDone( + int demuxer_client_id, + const base::TimeDelta& actual_browser_seek_time) { + thread_safe_sender_->Send(new MediaPlayerHostMsg_DemuxerSeekDone( + demuxer_client_id, actual_browser_seek_time)); } void RendererDemuxerAndroid::DurationChanged(int demuxer_client_id, @@ -78,7 +79,7 @@ void RendererDemuxerAndroid::DurationChanged(int demuxer_client_id, void RendererDemuxerAndroid::DispatchMessage(const IPC::Message& message) { IPC_BEGIN_MESSAGE_MAP(RendererDemuxerAndroid, message) - IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaSeekRequest, OnMediaSeekRequest) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_DemuxerSeekRequest, OnDemuxerSeekRequest) IPC_MESSAGE_HANDLER(MediaPlayerMsg_ReadFromDemuxer, OnReadFromDemuxer) IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaConfigRequest, OnMediaConfigRequest) IPC_END_MESSAGE_MAP() @@ -92,13 +93,13 @@ void RendererDemuxerAndroid::OnReadFromDemuxer( delegate->OnReadFromDemuxer(type); } -void RendererDemuxerAndroid::OnMediaSeekRequest( +void RendererDemuxerAndroid::OnDemuxerSeekRequest( int demuxer_client_id, const base::TimeDelta& time_to_seek, - unsigned seek_request_id) { + bool is_browser_seek) { MediaSourceDelegate* delegate = delegates_.Lookup(demuxer_client_id); if (delegate) - delegate->Seek(time_to_seek, seek_request_id); + delegate->Seek(time_to_seek, is_browser_seek); } void RendererDemuxerAndroid::OnMediaConfigRequest(int demuxer_client_id) { diff --git a/chromium/content/renderer/media/android/renderer_demuxer_android.h b/chromium/content/renderer/media/android/renderer_demuxer_android.h index 6888d6af8d4..c6538a1b2cb 100644 --- a/chromium/content/renderer/media/android/renderer_demuxer_android.h +++ b/chromium/content/renderer/media/android/renderer_demuxer_android.h @@ -51,7 +51,8 @@ class RendererDemuxerAndroid : public IPC::ChannelProxy::MessageFilter { const media::DemuxerConfigs& configs); void ReadFromDemuxerAck(int demuxer_client_id, const media::DemuxerData& data); - void SeekRequestAck(int demuxer_client_id, unsigned seek_request_id); + void DemuxerSeekDone(int demuxer_client_id, + const base::TimeDelta& actual_browser_seek_time); void DurationChanged(int demuxer_client_id, const base::TimeDelta& duration); protected: @@ -62,9 +63,9 @@ class RendererDemuxerAndroid : public IPC::ChannelProxy::MessageFilter { void DispatchMessage(const IPC::Message& message); void OnReadFromDemuxer(int demuxer_client_id, media::DemuxerStream::Type type); - void OnMediaSeekRequest(int demuxer_client_id, - const base::TimeDelta& time_to_seek, - unsigned seek_request_id); + void OnDemuxerSeekRequest(int demuxer_client_id, + const base::TimeDelta& time_to_seek, + bool is_browser_seek); void OnMediaConfigRequest(int demuxer_client_id); base::AtomicSequenceNumber next_demuxer_client_id_; diff --git a/chromium/content/renderer/media/android/renderer_media_player_manager.cc b/chromium/content/renderer/media/android/renderer_media_player_manager.cc index 62a99c0fa60..64e6fc5b112 100644 --- a/chromium/content/renderer/media/android/renderer_media_player_manager.cc +++ b/chromium/content/renderer/media/android/renderer_media_player_manager.cc @@ -4,15 +4,28 @@ #include "content/renderer/media/android/renderer_media_player_manager.h" +#include "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "content/common/media/media_player_messages_android.h" +#include "content/renderer/media/android/proxy_media_keys.h" +#include "content/renderer/media/android/renderer_media_player_manager.h" #include "content/renderer/media/android/webmediaplayer_android.h" #include "ui/gfx/rect_f.h" +// 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 kEmeWebSessionIdMaximum = 512; +static const size_t kEmeMessageMaximum = 10240; // 10 KB +static const size_t kEmeDestinationUrlMaximum = 2048; // 2 KB + namespace content { -RendererMediaPlayerManager::RendererMediaPlayerManager() - : next_media_player_id_(0), - fullscreen_frame_(NULL) { -} +RendererMediaPlayerManager::RendererMediaPlayerManager(RenderView* render_view) + : RenderViewObserver(render_view), + next_media_player_id_(0), + fullscreen_frame_(NULL), + pending_fullscreen_frame_(NULL) {} RendererMediaPlayerManager::~RendererMediaPlayerManager() { std::map<int, WebMediaPlayerAndroid*>::iterator player_it; @@ -21,6 +34,297 @@ RendererMediaPlayerManager::~RendererMediaPlayerManager() { WebMediaPlayerAndroid* player = player_it->second; player->Detach(); } + + Send(new MediaPlayerHostMsg_DestroyAllMediaPlayers(routing_id())); +} + +bool RendererMediaPlayerManager::OnMessageReceived(const IPC::Message& msg) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(RendererMediaPlayerManager, msg) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaMetadataChanged, + OnMediaMetadataChanged) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaPlaybackCompleted, + OnMediaPlaybackCompleted) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaBufferingUpdate, + OnMediaBufferingUpdate) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_SeekRequest, OnSeekRequest) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_SeekCompleted, OnSeekCompleted) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaError, OnMediaError) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaVideoSizeChanged, + OnVideoSizeChanged) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaTimeUpdate, OnTimeUpdate) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaPlayerReleased, + OnMediaPlayerReleased) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_ConnectedToRemoteDevice, + OnConnectedToRemoteDevice) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_DisconnectedFromRemoteDevice, + OnDisconnectedFromRemoteDevice) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_RequestFullscreen, + OnRequestFullscreen) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidEnterFullscreen, OnDidEnterFullscreen) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidExitFullscreen, OnDidExitFullscreen) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidMediaPlayerPlay, OnPlayerPlay) + IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidMediaPlayerPause, OnPlayerPause) + IPC_MESSAGE_HANDLER(MediaKeysMsg_SessionCreated, OnSessionCreated) + IPC_MESSAGE_HANDLER(MediaKeysMsg_SessionMessage, OnSessionMessage) + IPC_MESSAGE_HANDLER(MediaKeysMsg_SessionReady, OnSessionReady) + IPC_MESSAGE_HANDLER(MediaKeysMsg_SessionClosed, OnSessionClosed) + IPC_MESSAGE_HANDLER(MediaKeysMsg_SessionError, OnSessionError) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void RendererMediaPlayerManager::Initialize( + MediaPlayerHostMsg_Initialize_Type type, + int player_id, + const GURL& url, + const GURL& first_party_for_cookies, + int demuxer_client_id) { + Send(new MediaPlayerHostMsg_Initialize( + routing_id(), type, player_id, url, first_party_for_cookies, + demuxer_client_id)); +} + +void RendererMediaPlayerManager::Start(int player_id) { + Send(new MediaPlayerHostMsg_Start(routing_id(), player_id)); +} + +void RendererMediaPlayerManager::Pause( + int player_id, + bool is_media_related_action) { + Send(new MediaPlayerHostMsg_Pause( + routing_id(), player_id, is_media_related_action)); +} + +void RendererMediaPlayerManager::Seek( + int player_id, + const base::TimeDelta& time) { + Send(new MediaPlayerHostMsg_Seek(routing_id(), player_id, time)); +} + +void RendererMediaPlayerManager::SetVolume(int player_id, double volume) { + Send(new MediaPlayerHostMsg_SetVolume(routing_id(), player_id, volume)); +} + +void RendererMediaPlayerManager::ReleaseResources(int player_id) { + Send(new MediaPlayerHostMsg_Release(routing_id(), player_id)); +} + +void RendererMediaPlayerManager::DestroyPlayer(int player_id) { + Send(new MediaPlayerHostMsg_DestroyMediaPlayer(routing_id(), player_id)); +} + +void RendererMediaPlayerManager::OnMediaMetadataChanged( + int player_id, + base::TimeDelta duration, + int width, + int height, + bool success) { + WebMediaPlayerAndroid* player = GetMediaPlayer(player_id); + if (player) + player->OnMediaMetadataChanged(duration, width, height, success); +} + +void RendererMediaPlayerManager::OnMediaPlaybackCompleted(int player_id) { + WebMediaPlayerAndroid* player = GetMediaPlayer(player_id); + if (player) + player->OnPlaybackComplete(); +} + +void RendererMediaPlayerManager::OnMediaBufferingUpdate(int player_id, + int percent) { + WebMediaPlayerAndroid* player = GetMediaPlayer(player_id); + if (player) + player->OnBufferingUpdate(percent); +} + +void RendererMediaPlayerManager::OnSeekRequest( + int player_id, + const base::TimeDelta& time_to_seek) { + WebMediaPlayerAndroid* player = GetMediaPlayer(player_id); + if (player) + player->OnSeekRequest(time_to_seek); +} + +void RendererMediaPlayerManager::OnSeekCompleted( + int player_id, + const base::TimeDelta& current_time) { + WebMediaPlayerAndroid* player = GetMediaPlayer(player_id); + if (player) + player->OnSeekComplete(current_time); +} + +void RendererMediaPlayerManager::OnMediaError(int player_id, int error) { + WebMediaPlayerAndroid* player = GetMediaPlayer(player_id); + if (player) + player->OnMediaError(error); +} + +void RendererMediaPlayerManager::OnVideoSizeChanged(int player_id, + int width, + int height) { + WebMediaPlayerAndroid* player = GetMediaPlayer(player_id); + if (player) + player->OnVideoSizeChanged(width, height); +} + +void RendererMediaPlayerManager::OnTimeUpdate(int player_id, + base::TimeDelta current_time) { + WebMediaPlayerAndroid* player = GetMediaPlayer(player_id); + if (player) + player->OnTimeUpdate(current_time); +} + +void RendererMediaPlayerManager::OnMediaPlayerReleased(int player_id) { + WebMediaPlayerAndroid* player = GetMediaPlayer(player_id); + if (player) + player->OnPlayerReleased(); +} + +void RendererMediaPlayerManager::OnConnectedToRemoteDevice(int player_id) { + WebMediaPlayerAndroid* player = GetMediaPlayer(player_id); + if (player) + player->OnConnectedToRemoteDevice(); +} + +void RendererMediaPlayerManager::OnDisconnectedFromRemoteDevice(int player_id) { + WebMediaPlayerAndroid* player = GetMediaPlayer(player_id); + if (player) + player->OnDisconnectedFromRemoteDevice(); +} + +void RendererMediaPlayerManager::OnDidEnterFullscreen(int player_id) { + WebMediaPlayerAndroid* player = GetMediaPlayer(player_id); + if (player) + player->OnDidEnterFullscreen(); +} + +void RendererMediaPlayerManager::OnDidExitFullscreen(int player_id) { + WebMediaPlayerAndroid* player = GetMediaPlayer(player_id); + if (player) + player->OnDidExitFullscreen(); +} + +void RendererMediaPlayerManager::OnPlayerPlay(int player_id) { + WebMediaPlayerAndroid* player = GetMediaPlayer(player_id); + if (player) + player->OnMediaPlayerPlay(); +} + +void RendererMediaPlayerManager::OnPlayerPause(int player_id) { + WebMediaPlayerAndroid* player = GetMediaPlayer(player_id); + if (player) + player->OnMediaPlayerPause(); +} + +void RendererMediaPlayerManager::OnRequestFullscreen(int player_id) { + WebMediaPlayerAndroid* player = GetMediaPlayer(player_id); + if (player) + player->OnRequestFullscreen(); +} + +void RendererMediaPlayerManager::EnterFullscreen(int player_id, + blink::WebFrame* frame) { + pending_fullscreen_frame_ = frame; + Send(new MediaPlayerHostMsg_EnterFullscreen(routing_id(), player_id)); +} + +void RendererMediaPlayerManager::ExitFullscreen(int player_id) { + pending_fullscreen_frame_ = NULL; + Send(new MediaPlayerHostMsg_ExitFullscreen(routing_id(), player_id)); +} + +void RendererMediaPlayerManager::InitializeCDM(int media_keys_id, + ProxyMediaKeys* media_keys, + const std::vector<uint8>& uuid, + const GURL& frame_url) { + RegisterMediaKeys(media_keys_id, media_keys); + Send(new MediaKeysHostMsg_InitializeCDM( + routing_id(), media_keys_id, uuid, frame_url)); +} + +void RendererMediaPlayerManager::CreateSession( + int media_keys_id, + uint32 session_id, + const std::string& type, + const std::vector<uint8>& init_data) { + Send(new MediaKeysHostMsg_CreateSession( + routing_id(), media_keys_id, session_id, type, init_data)); +} + +void RendererMediaPlayerManager::UpdateSession( + int media_keys_id, + uint32 session_id, + const std::vector<uint8>& response) { + Send(new MediaKeysHostMsg_UpdateSession( + routing_id(), media_keys_id, session_id, response)); +} + +void RendererMediaPlayerManager::ReleaseSession(int media_keys_id, + uint32 session_id) { + Send(new MediaKeysHostMsg_ReleaseSession( + routing_id(), media_keys_id, session_id)); +} + +void RendererMediaPlayerManager::OnSessionCreated( + int media_keys_id, + uint32 session_id, + const std::string& web_session_id) { + if (web_session_id.length() > kEmeWebSessionIdMaximum) { + OnSessionError( + media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); + return; + } + + ProxyMediaKeys* media_keys = GetMediaKeys(media_keys_id); + if (media_keys) + media_keys->OnSessionCreated(session_id, web_session_id); +} + +void RendererMediaPlayerManager::OnSessionMessage( + int media_keys_id, + uint32 session_id, + const std::vector<uint8>& message, + const std::string& destination_url) { + if (message.size() > kEmeMessageMaximum) { + OnSessionError( + media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); + return; + } + if (destination_url.length() > kEmeDestinationUrlMaximum) { + OnSessionError( + media_keys_id, session_id, media::MediaKeys::kUnknownError, 0); + return; + } + + ProxyMediaKeys* media_keys = GetMediaKeys(media_keys_id); + if (media_keys) + media_keys->OnSessionMessage(session_id, message, destination_url); +} + +void RendererMediaPlayerManager::OnSessionReady(int media_keys_id, + uint32 session_id) { + ProxyMediaKeys* media_keys = GetMediaKeys(media_keys_id); + if (media_keys) + media_keys->OnSessionReady(session_id); +} + +void RendererMediaPlayerManager::OnSessionClosed(int media_keys_id, + uint32 session_id) { + ProxyMediaKeys* media_keys = GetMediaKeys(media_keys_id); + if (media_keys) + media_keys->OnSessionClosed(session_id); +} + +void RendererMediaPlayerManager::OnSessionError( + int media_keys_id, + uint32 session_id, + media::MediaKeys::KeyError error_code, + int system_code) { + ProxyMediaKeys* media_keys = GetMediaKeys(media_keys_id); + if (media_keys) + media_keys->OnSessionError(session_id, error_code, system_code); } int RendererMediaPlayerManager::RegisterMediaPlayer( @@ -31,6 +335,20 @@ int RendererMediaPlayerManager::RegisterMediaPlayer( void RendererMediaPlayerManager::UnregisterMediaPlayer(int player_id) { media_players_.erase(player_id); + media_keys_.erase(player_id); +} + +void RendererMediaPlayerManager::RegisterMediaKeys(int media_keys_id, + ProxyMediaKeys* media_keys) { + // WebMediaPlayerAndroid must have already been registered for + // |media_keys_id|. For now |media_keys_id| is the same as player_id + // used in other methods. + DCHECK(media_players_.find(media_keys_id) != media_players_.end()); + + // Only allowed to register once. + DCHECK(media_keys_.find(media_keys_id) == media_keys_.end()); + + media_keys_[media_keys_id] = media_keys; } void RendererMediaPlayerManager::ReleaseVideoResources() { @@ -54,11 +372,19 @@ WebMediaPlayerAndroid* RendererMediaPlayerManager::GetMediaPlayer( return NULL; } -bool RendererMediaPlayerManager::CanEnterFullscreen(WebKit::WebFrame* frame) { - return !fullscreen_frame_ || IsInFullscreen(frame); +ProxyMediaKeys* RendererMediaPlayerManager::GetMediaKeys(int media_keys_id) { + std::map<int, ProxyMediaKeys*>::iterator iter = + media_keys_.find(media_keys_id); + return (iter != media_keys_.end()) ? iter->second : NULL; +} + +bool RendererMediaPlayerManager::CanEnterFullscreen(blink::WebFrame* frame) { + return (!fullscreen_frame_ && !pending_fullscreen_frame_) + || ShouldEnterFullscreen(frame); } -void RendererMediaPlayerManager::DidEnterFullscreen(WebKit::WebFrame* frame) { +void RendererMediaPlayerManager::DidEnterFullscreen(blink::WebFrame* frame) { + pending_fullscreen_frame_ = NULL; fullscreen_frame_ = frame; } @@ -66,11 +392,33 @@ void RendererMediaPlayerManager::DidExitFullscreen() { fullscreen_frame_ = NULL; } -bool RendererMediaPlayerManager::IsInFullscreen(WebKit::WebFrame* frame) { +bool RendererMediaPlayerManager::IsInFullscreen(blink::WebFrame* frame) { return fullscreen_frame_ == frame; } -#if defined(GOOGLE_TV) +bool RendererMediaPlayerManager::ShouldEnterFullscreen(blink::WebFrame* frame) { + return fullscreen_frame_ == frame || pending_fullscreen_frame_ == frame; +} + +#if defined(VIDEO_HOLE) +void RendererMediaPlayerManager::RequestExternalSurface( + int player_id, + const gfx::RectF& geometry) { + Send(new MediaPlayerHostMsg_NotifyExternalSurface( + routing_id(), player_id, true, geometry)); +} + +void RendererMediaPlayerManager::DidCommitCompositorFrame() { + std::map<int, gfx::RectF> geometry_change; + RetrieveGeometryChanges(&geometry_change); + for (std::map<int, gfx::RectF>::iterator it = geometry_change.begin(); + it != geometry_change.end(); + ++it) { + Send(new MediaPlayerHostMsg_NotifyExternalSurface( + routing_id(), it->first, false, it->second)); + } +} + void RendererMediaPlayerManager::RetrieveGeometryChanges( std::map<int, gfx::RectF>* changes) { DCHECK(changes->empty()); @@ -88,6 +436,6 @@ void RendererMediaPlayerManager::RetrieveGeometryChanges( } } } -#endif +#endif // defined(VIDEO_HOLE) } // namespace content diff --git a/chromium/content/renderer/media/android/renderer_media_player_manager.h b/chromium/content/renderer/media/android/renderer_media_player_manager.h index e565602a279..188d5425132 100644 --- a/chromium/content/renderer/media/android/renderer_media_player_manager.h +++ b/chromium/content/renderer/media/android/renderer_media_player_manager.h @@ -6,10 +6,22 @@ #define CONTENT_RENDERER_MEDIA_ANDROID_RENDERER_MEDIA_PLAYER_MANAGER_H_ #include <map> +#include <string> +#include <vector> #include "base/basictypes.h" +#include "base/time/time.h" +#include "content/common/media/media_player_messages_enums_android.h" +#include "content/public/renderer/render_view_observer.h" +#include "media/base/android/media_player_android.h" +#include "media/base/media_keys.h" +#include "url/gurl.h" -namespace WebKit { +#if defined(GOOGLE_TV) +#include "ui/gfx/rect_f.h" +#endif + +namespace blink { class WebFrame; } @@ -19,50 +31,166 @@ class RectF; namespace content { +class ProxyMediaKeys; class WebMediaPlayerAndroid; // Class for managing all the WebMediaPlayerAndroid objects in the same // RenderView. -class RendererMediaPlayerManager { +class RendererMediaPlayerManager : public RenderViewObserver { public: - RendererMediaPlayerManager(); + // Constructs a RendererMediaPlayerManager object for the |render_view|. + RendererMediaPlayerManager(RenderView* render_view); virtual ~RendererMediaPlayerManager(); - // Register and unregister a WebMediaPlayerAndroid object. + // RenderViewObserver overrides. + virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; + + // Initializes a MediaPlayerAndroid object in browser process. + void Initialize(MediaPlayerHostMsg_Initialize_Type type, + int player_id, + const GURL& url, + const GURL& first_party_for_cookies, + int demuxer_client_id); + + // Starts the player. + void Start(int player_id); + + // Pauses the player. + // is_media_related_action should be true if this pause is coming from an + // an action that explicitly pauses the video (user pressing pause, JS, etc.) + // Otherwise it should be false if Pause is being called due to other reasons + // (cleanup, freeing resources, etc.) + void Pause(int player_id, bool is_media_related_action); + + // Performs seek on the player. + void Seek(int player_id, const base::TimeDelta& time); + + // Sets the player volume. + void SetVolume(int player_id, double volume); + + // Releases resources for the player. + void ReleaseResources(int player_id); + + // Destroys the player in the browser process + void DestroyPlayer(int player_id); + + // Requests the player to enter fullscreen. + void EnterFullscreen(int player_id, blink::WebFrame* frame); + + // Requests the player to exit fullscreen. + void ExitFullscreen(int player_id); + +#if defined(VIDEO_HOLE) + // Requests an external surface for out-of-band compositing. + void RequestExternalSurface(int player_id, const gfx::RectF& geometry); + + // RenderViewObserver overrides. + virtual void DidCommitCompositorFrame() OVERRIDE; +#endif // defined(VIDEO_HOLE) + + // Encrypted media related methods. + void InitializeCDM(int media_keys_id, + ProxyMediaKeys* media_keys, + const std::vector<uint8>& uuid, + const GURL& frame_url); + void CreateSession(int media_keys_id, + uint32 session_id, + const std::string& type, + const std::vector<uint8>& init_data); + void UpdateSession(int media_keys_id, + uint32 session_id, + const std::vector<uint8>& response); + void ReleaseSession(int media_keys_id, uint32 session_id); + + // Registers and unregisters a WebMediaPlayerAndroid object. int RegisterMediaPlayer(WebMediaPlayerAndroid* player); void UnregisterMediaPlayer(int player_id); - // Release the media resources managed by this object when a video + // Registers a ProxyMediaKeys object. There must be a WebMediaPlayerAndroid + // object already registered for this id, and it is unregistered when the + // player is unregistered. For now |media_keys_id| is the same as player_id + // used in other methods. + void RegisterMediaKeys(int media_keys_id, ProxyMediaKeys* media_keys); + + // Releases the media resources managed by this object when a video // is playing. void ReleaseVideoResources(); - // Check whether a player can enter fullscreen. - bool CanEnterFullscreen(WebKit::WebFrame* frame); + // Checks whether a player can enter fullscreen. + bool CanEnterFullscreen(blink::WebFrame* frame); // Called when a player entered or exited fullscreen. - void DidEnterFullscreen(WebKit::WebFrame* frame); + void DidEnterFullscreen(blink::WebFrame* frame); void DidExitFullscreen(); - // Check whether the Webframe is in fullscreen. - bool IsInFullscreen(WebKit::WebFrame* frame); + // Checks whether the Webframe is in fullscreen. + bool IsInFullscreen(blink::WebFrame* frame); + + // True if a newly created media player should enter fullscreen. + bool ShouldEnterFullscreen(blink::WebFrame* frame); - // Get the pointer to WebMediaPlayerAndroid given the |player_id|. + // Gets the pointer to WebMediaPlayerAndroid given the |player_id|. WebMediaPlayerAndroid* GetMediaPlayer(int player_id); -#if defined(GOOGLE_TV) - // Get the list of media players with video geometry changes. + // Gets the pointer to ProxyMediaKeys given the |media_keys_id|. + ProxyMediaKeys* GetMediaKeys(int media_keys_id); + +#if defined(VIDEO_HOLE) + // Gets the list of media players with video geometry changes. void RetrieveGeometryChanges(std::map<int, gfx::RectF>* changes); -#endif +#endif // defined(VIDEO_HOLE) private: + // Message handlers. + void OnMediaMetadataChanged(int player_id, + base::TimeDelta duration, + int width, + int height, + bool success); + void OnMediaPlaybackCompleted(int player_id); + void OnMediaBufferingUpdate(int player_id, int percent); + void OnSeekRequest(int player_id, const base::TimeDelta& time_to_seek); + void OnSeekCompleted(int player_id, const base::TimeDelta& current_time); + void OnMediaError(int player_id, int error); + void OnVideoSizeChanged(int player_id, int width, int height); + void OnTimeUpdate(int player_id, base::TimeDelta current_time); + void OnMediaPlayerReleased(int player_id); + void OnConnectedToRemoteDevice(int player_id); + void OnDisconnectedFromRemoteDevice(int player_id); + void OnDidExitFullscreen(int player_id); + void OnDidEnterFullscreen(int player_id); + void OnPlayerPlay(int player_id); + void OnPlayerPause(int player_id); + void OnRequestFullscreen(int player_id); + void OnSessionCreated(int media_keys_id, + uint32 session_id, + const std::string& web_session_id); + void OnSessionMessage(int media_keys_id, + uint32 session_id, + const std::vector<uint8>& message, + const std::string& destination_url); + void OnSessionReady(int media_keys_id, uint32 session_id); + void OnSessionClosed(int media_keys_id, uint32 session_id); + void OnSessionError(int media_keys_id, + uint32 session_id, + media::MediaKeys::KeyError error_code, + int system_code); + // Info for all available WebMediaPlayerAndroid on a page; kept so that - // we can enumerate them to send updates about tab focus and visibily. + // we can enumerate them to send updates about tab focus and visibility. std::map<int, WebMediaPlayerAndroid*> media_players_; + // Info for all available ProxyMediaKeys. There must be at most one + // ProxyMediaKeys for each available WebMediaPlayerAndroid. + std::map<int, ProxyMediaKeys*> media_keys_; + int next_media_player_id_; // WebFrame of the fullscreen video. - WebKit::WebFrame* fullscreen_frame_; + blink::WebFrame* fullscreen_frame_; + + // WebFrame of pending fullscreen request. + blink::WebFrame* pending_fullscreen_frame_; DISALLOW_COPY_AND_ASSIGN(RendererMediaPlayerManager); }; diff --git a/chromium/content/renderer/media/android/stream_texture_factory_android.h b/chromium/content/renderer/media/android/stream_texture_factory_android.h index d41d857cf62..849cc06eefa 100644 --- a/chromium/content/renderer/media/android/stream_texture_factory_android.h +++ b/chromium/content/renderer/media/android/stream_texture_factory_android.h @@ -10,6 +10,10 @@ #include "gpu/command_buffer/common/mailbox.h" #include "ui/gfx/size.h" +namespace blink { +class WebGraphicsContext3D; +} + namespace content { // The proxy class for the gpu thread to notify the compositor thread @@ -70,6 +74,8 @@ class StreamTextureFactory { // Set the streamTexture size for the given stream Id. virtual void SetStreamTextureSize(int32 texture_id, const gfx::Size& size) = 0; + + virtual blink::WebGraphicsContext3D* Context3d() = 0; }; } // namespace content diff --git a/chromium/content/renderer/media/android/stream_texture_factory_android_impl.cc b/chromium/content/renderer/media/android/stream_texture_factory_android_impl.cc index 721b680fb14..3b421ca04ef 100644 --- a/chromium/content/renderer/media/android/stream_texture_factory_android_impl.cc +++ b/chromium/content/renderer/media/android/stream_texture_factory_android_impl.cc @@ -80,7 +80,7 @@ void StreamTextureProxyImpl::OnMatrixChanged(const float matrix[16]) { } // namespace StreamTextureFactoryImpl::StreamTextureFactoryImpl( - WebKit::WebGraphicsContext3D* context, + blink::WebGraphicsContext3D* context, GpuChannelHost* channel, int view_id) : context_(context), channel_(channel), view_id_(view_id) { @@ -137,4 +137,8 @@ void StreamTextureFactoryImpl::SetStreamTextureSize( channel_->Send(new GpuChannelMsg_SetStreamTextureSize(stream_id, size)); } +blink::WebGraphicsContext3D* StreamTextureFactoryImpl::Context3d() { + return context_; +} + } // namespace content diff --git a/chromium/content/renderer/media/android/stream_texture_factory_android_impl.h b/chromium/content/renderer/media/android/stream_texture_factory_android_impl.h index 20aacdd9f98..0cd3d5866c9 100644 --- a/chromium/content/renderer/media/android/stream_texture_factory_android_impl.h +++ b/chromium/content/renderer/media/android/stream_texture_factory_android_impl.h @@ -7,7 +7,7 @@ #include "content/renderer/media/android/stream_texture_factory_android.h" -namespace WebKit { +namespace blink { class WebGraphicsContext3D; } @@ -17,7 +17,7 @@ class GpuChannelHost; class StreamTextureFactoryImpl : public StreamTextureFactory { public: - StreamTextureFactoryImpl(WebKit::WebGraphicsContext3D* context, + StreamTextureFactoryImpl(blink::WebGraphicsContext3D* context, GpuChannelHost* channel, int view_id); virtual ~StreamTextureFactoryImpl(); @@ -33,9 +33,10 @@ class StreamTextureFactoryImpl : public StreamTextureFactory { virtual void DestroyStreamTexture(unsigned texture_id) OVERRIDE; virtual void SetStreamTextureSize(int32 texture_id, const gfx::Size& size) OVERRIDE; + virtual blink::WebGraphicsContext3D* Context3d() OVERRIDE; private: - WebKit::WebGraphicsContext3D* context_; + blink::WebGraphicsContext3D* context_; scoped_refptr<GpuChannelHost> channel_; int view_id_; diff --git a/chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc b/chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc index 575bfa6557d..c284328a4b2 100644 --- a/chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc +++ b/chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc @@ -117,14 +117,19 @@ void StreamTextureProxyImpl::OnFrameAvailable() { } // namespace StreamTextureFactorySynchronousImpl::StreamTextureFactorySynchronousImpl( - ContextProvider* context_provider, + const CreateContextProviderCallback& try_create_callback, int view_id) - : context_provider_(context_provider), view_id_(view_id) {} + : create_context_provider_callback_(try_create_callback), + context_provider_(create_context_provider_callback_.Run()), + view_id_(view_id) {} StreamTextureFactorySynchronousImpl::~StreamTextureFactorySynchronousImpl() {} StreamTextureProxy* StreamTextureFactorySynchronousImpl::CreateProxy() { if (!context_provider_) + context_provider_ = create_context_provider_callback_.Run(); + + if (!context_provider_) return NULL; return new StreamTextureProxyImpl(context_provider_); } @@ -149,7 +154,7 @@ unsigned StreamTextureFactorySynchronousImpl::CreateStreamTexture( gpu::Mailbox* texture_mailbox, unsigned* texture_mailbox_sync_point) { DCHECK(context_provider_); - WebKit::WebGraphicsContext3D* context = context_provider_->Context3d(); + blink::WebGraphicsContext3D* context = context_provider_->Context3d(); unsigned stream_id = 0; if (context->makeContextCurrent()) { *texture_id = context->createTexture(); @@ -168,7 +173,7 @@ unsigned StreamTextureFactorySynchronousImpl::CreateStreamTexture( void StreamTextureFactorySynchronousImpl::DestroyStreamTexture( unsigned texture_id) { DCHECK(context_provider_); - WebKit::WebGraphicsContext3D* context = context_provider_->Context3d(); + blink::WebGraphicsContext3D* context = context_provider_->Context3d(); if (context->makeContextCurrent()) { context->destroyStreamTextureCHROMIUM(texture_id); context->deleteTexture(texture_id); @@ -180,4 +185,10 @@ void StreamTextureFactorySynchronousImpl::SetStreamTextureSize( int32 stream_id, const gfx::Size& size) {} +blink::WebGraphicsContext3D* +StreamTextureFactorySynchronousImpl::Context3d() { + DCHECK(context_provider_); + return context_provider_->Context3d(); +} + } // namespace content diff --git a/chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h b/chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h index 8b6ab6f106d..51c77e5666e 100644 --- a/chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h +++ b/chromium/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h @@ -5,6 +5,7 @@ #ifndef CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_SYNCHRONOUS_IMPL_H_ #define CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_SYNCHRONOUS_IMPL_H_ +#include "base/callback.h" #include "base/memory/ref_counted.h" #include "content/renderer/media/android/stream_texture_factory_android.h" @@ -12,7 +13,7 @@ namespace gfx { class SurfaceTexture; } -namespace WebKit { +namespace blink { class WebGraphicsContext3D; } @@ -26,15 +27,19 @@ class StreamTextureFactorySynchronousImpl : public StreamTextureFactory { virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture( uint32 stream_id) = 0; - virtual WebKit::WebGraphicsContext3D* Context3d() = 0; + virtual blink::WebGraphicsContext3D* Context3d() = 0; protected: friend class base::RefCountedThreadSafe<ContextProvider>; virtual ~ContextProvider() {} }; - StreamTextureFactorySynchronousImpl(ContextProvider* context_provider, - int view_id); + typedef base::Callback<scoped_refptr<ContextProvider>(void)> + CreateContextProviderCallback; + + StreamTextureFactorySynchronousImpl( + const CreateContextProviderCallback& try_create_callback, + int view_id); virtual ~StreamTextureFactorySynchronousImpl(); virtual StreamTextureProxy* CreateProxy() OVERRIDE; @@ -47,8 +52,10 @@ class StreamTextureFactorySynchronousImpl : public StreamTextureFactory { virtual void DestroyStreamTexture(unsigned texture_id) OVERRIDE; virtual void SetStreamTextureSize(int32 stream_id, const gfx::Size& size) OVERRIDE; + virtual blink::WebGraphicsContext3D* Context3d() OVERRIDE; private: + CreateContextProviderCallback create_context_provider_callback_; scoped_refptr<ContextProvider> context_provider_; int view_id_; diff --git a/chromium/content/renderer/media/android/webmediaplayer_android.cc b/chromium/content/renderer/media/android/webmediaplayer_android.cc index b2c0b37661d..a39ae56fead 100644 --- a/chromium/content/renderer/media/android/webmediaplayer_android.cc +++ b/chromium/content/renderer/media/android/webmediaplayer_android.cc @@ -13,26 +13,31 @@ #include "base/metrics/histogram.h" #include "base/strings/string_number_conversions.h" #include "cc/layers/video_layer.h" +#include "content/public/common/content_client.h" #include "content/renderer/media/android/proxy_media_keys.h" #include "content/renderer/media/android/renderer_demuxer_android.h" #include "content/renderer/media/android/renderer_media_player_manager.h" -#include "content/renderer/media/android/webmediaplayer_proxy_android.h" #include "content/renderer/media/crypto/key_systems.h" #include "content/renderer/media/webmediaplayer_delegate.h" #include "content/renderer/media/webmediaplayer_util.h" #include "content/renderer/render_thread_impl.h" #include "gpu/GLES2/gl2extchromium.h" +#include "grit/content_resources.h" #include "media/base/android/media_player_android.h" #include "media/base/bind_to_loop.h" #include "media/base/media_switches.h" #include "media/base/video_frame.h" #include "net/base/mime_util.h" +#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebFrame.h" -#include "third_party/WebKit/public/web/WebMediaPlayerClient.h" #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" #include "third_party/WebKit/public/web/WebView.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkPaint.h" +#include "ui/gfx/image/image.h" #include "webkit/renderer/compositor_bindings/web_layer_impl.h" #if defined(GOOGLE_TV) @@ -42,11 +47,11 @@ static const uint32 kGLTextureExternalOES = 0x8D65; -using WebKit::WebMediaPlayer; -using WebKit::WebSize; -using WebKit::WebString; -using WebKit::WebTimeRanges; -using WebKit::WebURL; +using blink::WebMediaPlayer; +using blink::WebSize; +using blink::WebString; +using blink::WebTimeRanges; +using blink::WebURL; using media::MediaPlayerAndroid; using media::VideoFrame; @@ -57,12 +62,23 @@ const char* kMediaEme = "Media.EME."; namespace content { +// static +void WebMediaPlayerAndroid::OnReleaseRemotePlaybackTexture( + const scoped_refptr<base::MessageLoopProxy>& main_loop, + const base::WeakPtr<WebMediaPlayerAndroid>& player, + uint32 sync_point) { + main_loop->PostTask( + FROM_HERE, + base::Bind(&WebMediaPlayerAndroid::DoReleaseRemotePlaybackTexture, + player, + sync_point)); +} + WebMediaPlayerAndroid::WebMediaPlayerAndroid( - WebKit::WebFrame* frame, - WebKit::WebMediaPlayerClient* client, + blink::WebFrame* frame, + blink::WebMediaPlayerClient* client, base::WeakPtr<WebMediaPlayerDelegate> delegate, RendererMediaPlayerManager* manager, - WebMediaPlayerProxyAndroid* proxy, StreamTextureFactory* factory, const scoped_refptr<base::MessageLoopProxy>& media_loop, media::MediaLog* media_log) @@ -73,12 +89,13 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid( main_loop_(base::MessageLoopProxy::current()), media_loop_(media_loop), ignore_metadata_duration_change_(false), - pending_seek_(0), + pending_seek_(false), seeking_(false), did_loading_progress_(false), manager_(manager), network_state_(WebMediaPlayer::NetworkStateEmpty), ready_state_(WebMediaPlayer::ReadyStateHaveNothing), + remote_playback_texture_id_(0), texture_id_(0), texture_mailbox_sync_point_(0), stream_id_(0), @@ -99,13 +116,14 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid( #endif // defined(GOOGLE_TV) pending_playback_(false), player_type_(MEDIA_PLAYER_TYPE_URL), - proxy_(proxy), current_time_(0), + is_remote_(false), media_log_(media_log), weak_factory_(this) { - DCHECK(proxy_); DCHECK(manager_); + DCHECK(main_thread_checker_.CalledOnValidThread()); + // We want to be notified of |main_loop_| destruction. base::MessageLoop::current()->AddDestructionObserver(this); @@ -121,25 +139,16 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid( external_surface_threshold_ = -1; } } +#endif // defined(GOOGLE_TV) +#if defined(VIDEO_HOLE) // Defer stream texture creation until we are sure it's necessary. - stream_id_ = 0; needs_establish_peer_ = false; current_frame_ = VideoFrame::CreateBlackFrame(gfx::Size(1, 1)); -#endif - if (stream_texture_factory_) { - stream_texture_proxy_.reset(stream_texture_factory_->CreateProxy()); - if (needs_establish_peer_ && stream_texture_proxy_) { - stream_id_ = stream_texture_factory_->CreateStreamTexture( - kGLTextureExternalOES, - &texture_id_, - &texture_mailbox_, - &texture_mailbox_sync_point_); - ReallocateVideoFrame(); - } - } +#endif // defined(VIDEO_HOLE) + TryCreateStreamTextureProxyIfNeeded(); - if (WebKit::WebRuntimeFeatures::isLegacyEncryptedMediaEnabled()) { + if (blink::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled()) { // TODO(xhwang): Report an error when there is encrypted stream but EME is // not enabled. Currently the player just doesn't start and waits for ever. decryptor_.reset(new ProxyDecryptor( @@ -147,7 +156,7 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid( client, frame, #else - proxy_, + manager_, player_id_, // TODO(xhwang): Use media_keys_id when MediaKeys are // separated from WebMediaPlayer. #endif // defined(ENABLE_PEPPER_CDMS) @@ -163,14 +172,20 @@ WebMediaPlayerAndroid::~WebMediaPlayerAndroid() { SetVideoFrameProviderClient(NULL); client_->setWebLayer(NULL); - if (proxy_) - proxy_->DestroyPlayer(player_id_); + if (manager_) { + manager_->DestroyPlayer(player_id_); + manager_->UnregisterMediaPlayer(player_id_); + } if (stream_id_) stream_texture_factory_->DestroyStreamTexture(texture_id_); - if (manager_) - manager_->UnregisterMediaPlayer(player_id_); + if (remote_playback_texture_id_) { + blink::WebGraphicsContext3D* context = + stream_texture_factory_->Context3d(); + if (context->makeContextCurrent()) + context->deleteTexture(remote_playback_texture_id_); + } if (base::MessageLoop::current()) base::MessageLoop::current()->RemoveDestructionObserver(this); @@ -198,7 +213,7 @@ WebMediaPlayerAndroid::~WebMediaPlayerAndroid() { } void WebMediaPlayerAndroid::load(LoadType load_type, - const WebKit::WebURL& url, + const blink::WebURL& url, CORSMode cors_mode) { switch (load_type) { case LoadTypeURL: @@ -250,8 +265,6 @@ void WebMediaPlayerAndroid::load(LoadType load_type, base::Bind(&WebMediaPlayerAndroid::UpdateNetworkState, weak_factory_.GetWeakPtr()), base::Bind(&WebMediaPlayerAndroid::OnDurationChanged, - weak_factory_.GetWeakPtr()), - base::Bind(&WebMediaPlayerAndroid::OnTimeUpdate, weak_factory_.GetWeakPtr())); } #if defined(GOOGLE_TV) @@ -279,11 +292,11 @@ void WebMediaPlayerAndroid::load(LoadType load_type, url_ = url; GURL first_party_url = frame_->document().firstPartyForCookies(); - proxy_->Initialize( + manager_->Initialize( player_type_, player_id_, url, first_party_url, demuxer_client_id); - if (manager_->IsInFullscreen(frame_)) - proxy_->EnterFullscreen(player_id_); + if (manager_->ShouldEnterFullscreen(frame_)) + manager_->EnterFullscreen(player_id_, frame_); UpdateNetworkState(WebMediaPlayer::NetworkStateLoading); UpdateReadyState(WebMediaPlayer::ReadyStateHaveNothing); @@ -312,20 +325,24 @@ void WebMediaPlayerAndroid::DidLoadMediaInfo( } void WebMediaPlayerAndroid::play() { -#if defined(GOOGLE_TV) +#if defined(VIDEO_HOLE) if (hasVideo() && needs_external_surface_ && !manager_->IsInFullscreen(frame_)) { DCHECK(!needs_establish_peer_); - proxy_->RequestExternalSurface(player_id_, last_computed_rect_); + manager_->RequestExternalSurface(player_id_, last_computed_rect_); } +#endif // defined(VIDEO_HOLE) +#if defined(GOOGLE_TV) if (audio_renderer_ && paused()) audio_renderer_->Play(); -#endif +#endif // defined(GOOGLE_TV) + + TryCreateStreamTextureProxyIfNeeded(); if (hasVideo() && needs_establish_peer_) EstablishSurfaceTexturePeer(); if (paused()) - proxy_->Start(player_id_); + manager_->Start(player_id_); UpdatePlayingState(true); UpdateNetworkState(WebMediaPlayer::NetworkStateLoading); playing_started_ = true; @@ -340,16 +357,52 @@ void WebMediaPlayerAndroid::pause(bool is_media_related_action) { if (audio_renderer_ && !paused()) audio_renderer_->Pause(); #endif - proxy_->Pause(player_id_, is_media_related_action); + manager_->Pause(player_id_, is_media_related_action); UpdatePlayingState(false); } void WebMediaPlayerAndroid::seek(double seconds) { - pending_seek_ = seconds; + DCHECK(main_loop_->BelongsToCurrentThread()); + DVLOG(1) << __FUNCTION__ << "(" << seconds << ")"; + + base::TimeDelta new_seek_time = ConvertSecondsToTimestamp(seconds); + + if (seeking_) { + if (new_seek_time == seek_time_) { + if (media_source_delegate_) { + if (!pending_seek_) { + // If using media source demuxer, only suppress redundant seeks if + // there is no pending seek. This enforces that any pending seek that + // results in a demuxer seek is preceded by matching + // CancelPendingSeek() and StartWaitingForSeek() calls. + return; + } + } else { + // Suppress all redundant seeks if unrestricted by media source + // demuxer API. + pending_seek_ = false; + return; + } + } + + pending_seek_ = true; + pending_seek_time_ = new_seek_time; + + if (media_source_delegate_) + media_source_delegate_->CancelPendingSeek(pending_seek_time_); + + // Later, OnSeekComplete will trigger the pending seek. + return; + } + seeking_ = true; + seek_time_ = new_seek_time; + + if (media_source_delegate_) + media_source_delegate_->StartWaitingForSeek(seek_time_); - base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds); - proxy_->Seek(player_id_, seek_time); + // Kick off the asynchronous seek! + manager_->Seek(player_id_, seek_time_); } bool WebMediaPlayerAndroid::supportsFullscreen() const { @@ -365,7 +418,7 @@ void WebMediaPlayerAndroid::setRate(double rate) { } void WebMediaPlayerAndroid::setVolume(double volume) { - proxy_->SetVolume(player_id_, volume); + manager_->SetVolume(player_id_, volume); } bool WebMediaPlayerAndroid::hasVideo() const { @@ -414,9 +467,13 @@ double WebMediaPlayerAndroid::duration() const { } double WebMediaPlayerAndroid::currentTime() const { - // If the player is pending for a seek, return the seek time. - if (seeking()) - return pending_seek_; + // If the player is processing a seek, return the seek time. + // Blink may still query us if updatePlaybackState() occurs while seeking. + if (seeking()) { + return pending_seek_ ? + pending_seek_time_.InSecondsF() : seek_time_.InSecondsF(); + } + return current_time_; } @@ -454,21 +511,21 @@ bool WebMediaPlayerAndroid::didLoadingProgress() const { return ret; } -void WebMediaPlayerAndroid::paint(WebKit::WebCanvas* canvas, - const WebKit::WebRect& rect, +void WebMediaPlayerAndroid::paint(blink::WebCanvas* canvas, + const blink::WebRect& rect, unsigned char alpha) { NOTIMPLEMENTED(); } bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture( - WebKit::WebGraphicsContext3D* web_graphics_context, + blink::WebGraphicsContext3D* web_graphics_context, unsigned int texture, unsigned int level, unsigned int internal_format, unsigned int type, bool premultiply_alpha, bool flip_y) { - if (!texture_id_) + if (is_remote_ || !texture_id_) return false; // For hidden video element (with style "display:none"), ensure the texture @@ -610,11 +667,11 @@ void WebMediaPlayerAndroid::OnPlaybackComplete() { // if the loop attribute is set, timeChanged() will update the current time // to 0. It will perform a seek to 0. As the requests to the renderer - // process are sequential, the OnSeekCompelete() will only occur + // process are sequential, the OnSeekComplete() will only occur // once OnPlaybackComplete() is done. As the playback can only be executed // upon completion of OnSeekComplete(), the request needs to be saved. is_playing_ = false; - if (seeking_ && pending_seek_ == 0) + if (seeking_ && seek_time_ == base::TimeDelta()) pending_playback_ = true; } @@ -623,9 +680,20 @@ void WebMediaPlayerAndroid::OnBufferingUpdate(int percentage) { did_loading_progress_ = true; } +void WebMediaPlayerAndroid::OnSeekRequest(const base::TimeDelta& time_to_seek) { + DCHECK(main_loop_->BelongsToCurrentThread()); + client_->requestSeek(time_to_seek.InSecondsF()); +} + void WebMediaPlayerAndroid::OnSeekComplete( const base::TimeDelta& current_time) { + DCHECK(main_loop_->BelongsToCurrentThread()); seeking_ = false; + if (pending_seek_) { + pending_seek_ = false; + seek(pending_seek_time_.InSecondsF()); + return; + } OnTimeUpdate(current_time); @@ -661,28 +729,36 @@ void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) { if (natural_size_.width == width && natural_size_.height == height) return; +#if defined(VIDEO_HOLE) + bool has_surface_size_restriction = false; #if defined(GOOGLE_TV) - if ((external_surface_threshold_ >= 0 && - external_surface_threshold_ <= width * height) || - // Use H/W surface for MSE as the content is protected. - media_source_delegate_) { + has_surface_size_restriction = external_surface_threshold_ >= 0 && + external_surface_threshold_ <= width * height; +#endif // defined(GOOGLE_TV) + // Use H/W surface for MSE as the content might be protected. + // TODO(qinmin): Change this so that only EME needs the H/W surface + if (media_source_delegate_ || has_surface_size_restriction) { needs_external_surface_ = true; if (!paused() && !manager_->IsInFullscreen(frame_)) - proxy_->RequestExternalSurface(player_id_, last_computed_rect_); + manager_->RequestExternalSurface(player_id_, last_computed_rect_); } else if (stream_texture_factory_ && !stream_id_) { // Do deferred stream texture creation finally. - stream_id_ = stream_texture_factory_->CreateStreamTexture( - kGLTextureExternalOES, - &texture_id_, - &texture_mailbox_, - &texture_mailbox_sync_point_); + DoCreateStreamTexture(); if (paused()) { SetNeedsEstablishPeer(true); } else { EstablishSurfaceTexturePeer(); } } -#endif +#else + // When play() gets called, |natural_size_| may still be empty and + // EstablishSurfaceTexturePeer() will not get called. As a result, the video + // may play without a surface texture. When we finally get the valid video + // size here, we should call EstablishSurfaceTexturePeer() if it has not been + // previously called. + if (!paused() && needs_establish_peer_) + EstablishSurfaceTexturePeer(); +#endif // defined(VIDEO_HOLE) natural_size_.width = width; natural_size_.height = height; @@ -694,6 +770,24 @@ void WebMediaPlayerAndroid::OnTimeUpdate(const base::TimeDelta& current_time) { current_time_ = current_time.InSecondsF(); } +void WebMediaPlayerAndroid::OnConnectedToRemoteDevice() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + DCHECK(!media_source_delegate_); + DrawRemotePlaybackIcon(); + is_remote_ = true; + SetNeedsEstablishPeer(false); +} + +void WebMediaPlayerAndroid::OnDisconnectedFromRemoteDevice() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + DCHECK(!media_source_delegate_); + SetNeedsEstablishPeer(true); + if (!paused()) + EstablishSurfaceTexturePeer(); + is_remote_ = false; + ReallocateVideoFrame(); +} + void WebMediaPlayerAndroid::OnDidEnterFullscreen() { if (!manager_->IsInFullscreen(frame_)) { frame_->view()->willEnterFullScreen(); @@ -711,10 +805,10 @@ void WebMediaPlayerAndroid::OnDidExitFullscreen() { if (!paused() && needs_establish_peer_) EstablishSurfaceTexturePeer(); -#if defined(GOOGLE_TV) +#if defined(VIDEO_HOLE) if (!paused() && needs_external_surface_) - proxy_->RequestExternalSurface(player_id_, last_computed_rect_); -#endif + manager_->RequestExternalSurface(player_id_, last_computed_rect_); +#endif // defined(VIDEO_HOLE) frame_->view()->willExitFullScreen(); frame_->view()->didExitFullScreen(); @@ -732,6 +826,10 @@ void WebMediaPlayerAndroid::OnMediaPlayerPause() { client_->playbackStateChanged(); } +void WebMediaPlayerAndroid::OnRequestFullscreen() { + client_->requestFullscreen(); +} + void WebMediaPlayerAndroid::OnDurationChanged(const base::TimeDelta& duration) { DCHECK(main_loop_->BelongsToCurrentThread()); // Only MSE |player_type_| registers this callback. @@ -776,9 +874,9 @@ void WebMediaPlayerAndroid::OnPlayerReleased() { if (!needs_external_surface_) needs_establish_peer_ = true; -#if defined(GOOGLE_TV) +#if defined(VIDEO_HOLE) last_computed_rect_ = gfx::RectF(); -#endif +#endif // defined(VIDEO_HOLE) } void WebMediaPlayerAndroid::ReleaseMediaResources() { @@ -800,7 +898,7 @@ void WebMediaPlayerAndroid::ReleaseMediaResources() { case WebMediaPlayer::NetworkStateDecodeError: break; } - proxy_->ReleaseResources(player_id_); + manager_->ReleaseResources(player_id_); OnPlayerReleased(); } @@ -817,33 +915,140 @@ void WebMediaPlayerAndroid::Detach() { } media_source_delegate_.reset(); - current_frame_ = NULL; + { + base::AutoLock auto_lock(current_frame_lock_); + current_frame_ = NULL; + } + is_remote_ = false; manager_ = NULL; - proxy_ = NULL; +} + +void WebMediaPlayerAndroid::DrawRemotePlaybackIcon() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + if (!video_weblayer_) + return; + blink::WebGraphicsContext3D* context = stream_texture_factory_->Context3d(); + if (!context->makeContextCurrent()) + return; + + // TODO(johnme): Should redraw this frame if the layer bounds change; but + // there seems no easy way to listen for the layer resizing (as opposed to + // OnVideoSizeChanged, which is when the frame sizes of the video file + // change). Perhaps have to poll (on main thread of course)? + gfx::Size video_size_css_px = video_weblayer_->bounds(); + float device_scale_factor = frame_->view()->deviceScaleFactor(); + // canvas_size will be the size in device pixels when pageScaleFactor == 1 + gfx::Size canvas_size( + static_cast<int>(video_size_css_px.width() * device_scale_factor), + static_cast<int>(video_size_css_px.height() * device_scale_factor)); + + SkBitmap bitmap; + bitmap.setConfig( + SkBitmap::kARGB_8888_Config, canvas_size.width(), canvas_size.height()); + bitmap.allocPixels(); + + SkCanvas canvas(bitmap); + canvas.drawColor(SK_ColorBLACK); + SkPaint paint; + paint.setAntiAlias(true); + paint.setFilterLevel(SkPaint::kHigh_FilterLevel); + const SkBitmap* icon_bitmap = + content::GetContentClient() + ->GetNativeImageNamed(IDR_MEDIAPLAYER_REMOTE_PLAYBACK_ICON) + .ToSkBitmap(); + // In order to get a reasonable margin around the icon: + // - the icon should be under half the frame width + // - the icon should be at most 3/5 of the frame height + // Additionally, on very large screens, the icon size should be capped. A max + // width of 320 was arbitrarily chosen; since this is half the resource's + // pixel width, it should look crisp even on 2x deviceScaleFactor displays. + int icon_width = 320; + icon_width = std::min(icon_width, canvas_size.width() / 2); + icon_width = std::min(icon_width, + canvas_size.height() * icon_bitmap->width() / + icon_bitmap->height() * 3 / 5); + int icon_height = icon_width * icon_bitmap->height() / icon_bitmap->width(); + // Center the icon within the frame + SkRect icon_rect = SkRect::MakeXYWH((canvas_size.width() - icon_width) / 2, + (canvas_size.height() - icon_height) / 2, + icon_width, + icon_height); + canvas.drawBitmapRectToRect( + *icon_bitmap, NULL /* src */, icon_rect /* dest */, &paint); + + if (!remote_playback_texture_id_) + remote_playback_texture_id_ = context->createTexture(); + unsigned texture_target = GL_TEXTURE_2D; + context->bindTexture(texture_target, remote_playback_texture_id_); + context->texParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + context->texParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + context->texParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + context->texParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + { + SkAutoLockPixels lock(bitmap); + context->texImage2D(texture_target, + 0 /* level */, + GL_RGBA /* internalformat */, + bitmap.width(), + bitmap.height(), + 0 /* border */, + GL_RGBA /* format */, + GL_UNSIGNED_BYTE /* type */, + bitmap.getPixels()); + } + + gpu::Mailbox texture_mailbox; + context->genMailboxCHROMIUM(texture_mailbox.name); + context->produceTextureCHROMIUM(texture_target, texture_mailbox.name); + context->flush(); + unsigned texture_mailbox_sync_point = context->insertSyncPoint(); + + scoped_refptr<VideoFrame> new_frame = VideoFrame::WrapNativeTexture( + make_scoped_ptr(new VideoFrame::MailboxHolder( + texture_mailbox, + texture_mailbox_sync_point, + base::Bind(&WebMediaPlayerAndroid::OnReleaseRemotePlaybackTexture, + main_loop_, + weak_factory_.GetWeakPtr()))), + texture_target, + canvas_size /* coded_size */, + gfx::Rect(canvas_size) /* visible_rect */, + canvas_size /* natural_size */, + base::TimeDelta() /* timestamp */, + VideoFrame::ReadPixelsCB(), + base::Closure() /* no_longer_needed_cb */); + SetCurrentFrameInternal(new_frame); } void WebMediaPlayerAndroid::ReallocateVideoFrame() { if (needs_external_surface_) { - // VideoFrame::CreateHoleFrame is only defined under GOOGLE_TV. -#if defined(GOOGLE_TV) + // VideoFrame::CreateHoleFrame is only defined under VIDEO_HOLE. +#if defined(VIDEO_HOLE) if (!natural_size_.isEmpty()) { - current_frame_ = VideoFrame::CreateHoleFrame(natural_size_); + scoped_refptr<VideoFrame> new_frame = + VideoFrame::CreateHoleFrame(natural_size_); + SetCurrentFrameInternal(new_frame); // Force the client to grab the hole frame. client_->repaint(); } #else - NOTIMPLEMENTED() << "Hole punching not supported outside of Google TV"; -#endif - } else if (texture_id_) { - current_frame_ = VideoFrame::WrapNativeTexture( - new VideoFrame::MailboxHolder( + NOTIMPLEMENTED() << "Hole punching not supported without VIDEO_HOLE flag"; +#endif // defined(VIDEO_HOLE) + } else if (!is_remote_ && texture_id_) { + scoped_refptr<VideoFrame> new_frame = VideoFrame::WrapNativeTexture( + make_scoped_ptr(new VideoFrame::MailboxHolder( texture_mailbox_, texture_mailbox_sync_point_, - VideoFrame::MailboxHolder::TextureNoLongerNeededCallback()), - kGLTextureExternalOES, natural_size_, - gfx::Rect(natural_size_), natural_size_, base::TimeDelta(), + VideoFrame::MailboxHolder::TextureNoLongerNeededCallback())), + kGLTextureExternalOES, + natural_size_, + gfx::Rect(natural_size_), + natural_size_, + base::TimeDelta(), VideoFrame::ReadPixelsCB(), base::Closure()); + SetCurrentFrameInternal(new_frame); } } @@ -860,22 +1065,55 @@ void WebMediaPlayerAndroid::SetVideoFrameProviderClient( stream_texture_proxy_->SetClient(client); } +void WebMediaPlayerAndroid::SetCurrentFrameInternal( + scoped_refptr<media::VideoFrame>& video_frame) { + base::AutoLock auto_lock(current_frame_lock_); + current_frame_ = video_frame; +} + scoped_refptr<media::VideoFrame> WebMediaPlayerAndroid::GetCurrentFrame() { + scoped_refptr<VideoFrame> video_frame; + { + base::AutoLock auto_lock(current_frame_lock_); + video_frame = current_frame_; + } + if (!stream_texture_proxy_initialized_ && stream_texture_proxy_ && - stream_id_ && !needs_external_surface_) { - gfx::Size natural_size = current_frame_->natural_size(); + stream_id_ && !needs_external_surface_ && !is_remote_) { + gfx::Size natural_size = video_frame->natural_size(); + // TODO(sievers): These variables are accessed on the wrong thread here. stream_texture_proxy_->BindToCurrentThread(stream_id_); stream_texture_factory_->SetStreamTextureSize(stream_id_, natural_size); stream_texture_proxy_initialized_ = true; cached_stream_texture_size_ = natural_size; } - return current_frame_; + + return video_frame; } void WebMediaPlayerAndroid::PutCurrentFrame( const scoped_refptr<media::VideoFrame>& frame) { } +void WebMediaPlayerAndroid::TryCreateStreamTextureProxyIfNeeded() { + // Already created. + if (stream_texture_proxy_) + return; + + // No factory to create proxy. + if (!stream_texture_factory_) + return; + + stream_texture_proxy_.reset(stream_texture_factory_->CreateProxy()); + if (needs_establish_peer_ && stream_texture_proxy_) { + DoCreateStreamTexture(); + ReallocateVideoFrame(); + } + + if (stream_texture_proxy_ && video_frame_provider_client_) + stream_texture_proxy_->SetClient(video_frame_provider_client_); +} + void WebMediaPlayerAndroid::EstablishSurfaceTexturePeer() { if (!stream_texture_proxy_) return; @@ -888,11 +1126,7 @@ void WebMediaPlayerAndroid::EstablishSurfaceTexturePeer() { texture_id_ = 0; texture_mailbox_ = gpu::Mailbox(); texture_mailbox_sync_point_ = 0; - stream_id_ = stream_texture_factory_->CreateStreamTexture( - kGLTextureExternalOES, - &texture_id_, - &texture_mailbox_, - &texture_mailbox_sync_point_); + DoCreateStreamTexture(); ReallocateVideoFrame(); stream_texture_proxy_initialized_ = false; } @@ -901,6 +1135,17 @@ void WebMediaPlayerAndroid::EstablishSurfaceTexturePeer() { needs_establish_peer_ = false; } +void WebMediaPlayerAndroid::DoCreateStreamTexture() { + DCHECK(!stream_id_); + DCHECK(!texture_id_); + DCHECK(!texture_mailbox_sync_point_); + stream_id_ = stream_texture_factory_->CreateStreamTexture( + kGLTextureExternalOES, + &texture_id_, + &texture_mailbox_, + &texture_mailbox_sync_point_); +} + void WebMediaPlayerAndroid::SetNeedsEstablishPeer(bool needs_establish_peer) { needs_establish_peer_ = needs_establish_peer; } @@ -915,7 +1160,7 @@ void WebMediaPlayerAndroid::UpdatePlayingState(bool is_playing) { delegate_->DidPause(this); } -#if defined(GOOGLE_TV) +#if defined(VIDEO_HOLE) bool WebMediaPlayerAndroid::RetrieveGeometryChange(gfx::RectF* rect) { if (!video_weblayer_) return false; @@ -948,7 +1193,7 @@ bool WebMediaPlayerAndroid::RetrieveGeometryChange(gfx::RectF* rect) { // UMA_HISTOGRAM_COUNTS. The reason that we cannot use those macros directly is // that UMA_* macros require the names to be constant throughout the process' // lifetime. -static void EmeUMAHistogramEnumeration(const WebKit::WebString& key_system, +static void EmeUMAHistogramEnumeration(const blink::WebString& key_system, const std::string& method, int sample, int boundary_value) { @@ -958,7 +1203,7 @@ static void EmeUMAHistogramEnumeration(const WebKit::WebString& key_system, base::Histogram::kUmaTargetedHistogramFlag)->Add(sample); } -static void EmeUMAHistogramCounts(const WebKit::WebString& key_system, +static void EmeUMAHistogramCounts(const blink::WebString& key_system, const std::string& method, int sample) { // Use the same parameters as UMA_HISTOGRAM_COUNTS. @@ -1012,6 +1257,12 @@ WebMediaPlayer::MediaKeyException WebMediaPlayerAndroid::generateKeyRequest( return e; } +bool WebMediaPlayerAndroid::IsKeySystemSupported(const WebString& key_system) { + // On Android, EME only works with MSE. + return player_type_ == MEDIA_PLAYER_TYPE_MEDIA_SOURCE && + IsConcreteSupportedKeySystem(key_system); +} + WebMediaPlayer::MediaKeyException WebMediaPlayerAndroid::GenerateKeyRequestInternal( const WebString& key_system, @@ -1021,7 +1272,7 @@ WebMediaPlayerAndroid::GenerateKeyRequestInternal( << std::string(reinterpret_cast<const char*>(init_data), static_cast<size_t>(init_data_length)); - if (!IsConcreteSupportedKeySystem(key_system)) + if (!IsKeySystemSupported(key_system)) return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; // We do not support run-time switching between key systems for now. @@ -1074,7 +1325,7 @@ WebMediaPlayer::MediaKeyException WebMediaPlayerAndroid::AddKeyInternal( static_cast<size_t>(init_data_length)) << " [" << session_id.utf8().data() << "]"; - if (!IsConcreteSupportedKeySystem(key_system)) + if (!IsKeySystemSupported(key_system)) return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; if (current_key_system_.isEmpty() || key_system != current_key_system_) @@ -1098,7 +1349,7 @@ WebMediaPlayer::MediaKeyException WebMediaPlayerAndroid::CancelKeyRequestInternal( const WebString& key_system, const WebString& session_id) { - if (!IsConcreteSupportedKeySystem(key_system)) + if (!IsKeySystemSupported(key_system)) return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported; if (current_key_system_.isEmpty() || key_system != current_key_system_) @@ -1128,7 +1379,7 @@ void WebMediaPlayerAndroid::OnKeyError(const std::string& session_id, client_->keyError( current_key_system_, WebString::fromUTF8(session_id), - static_cast<WebKit::WebMediaPlayerClient::MediaKeyErrorCode>(error_code), + static_cast<blink::WebMediaPlayerClient::MediaKeyErrorCode>(error_code), system_code); } @@ -1147,17 +1398,16 @@ void WebMediaPlayerAndroid::OnKeyMessage(const std::string& session_id, } void WebMediaPlayerAndroid::OnMediaSourceOpened( - WebKit::WebMediaSource* web_media_source) { + blink::WebMediaSource* web_media_source) { client_->mediaSourceOpened(web_media_source); } -void WebMediaPlayerAndroid::OnNeedKey(const std::string& session_id, - const std::string& type, +void WebMediaPlayerAndroid::OnNeedKey(const std::string& type, const std::vector<uint8>& init_data) { DCHECK(main_loop_->BelongsToCurrentThread()); // Do not fire NeedKey event if encrypted media is not enabled. - if (!WebKit::WebRuntimeFeatures::isEncryptedMediaEnabled() && - !WebKit::WebRuntimeFeatures::isLegacyEncryptedMediaEnabled()) { + if (!blink::WebRuntimeFeatures::isEncryptedMediaEnabled() && + !blink::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled()) { return; } @@ -1168,8 +1418,9 @@ void WebMediaPlayerAndroid::OnNeedKey(const std::string& session_id, init_data_type_ = type; const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0]; + // TODO(xhwang): Drop |keySystem| and |sessionId| in keyNeeded() call. client_->keyNeeded(WebString(), - WebString::fromUTF8(session_id), + WebString(), init_data_ptr, init_data.size()); } @@ -1187,15 +1438,28 @@ bool WebMediaPlayerAndroid::InjectMediaStream( } #endif +void WebMediaPlayerAndroid::DoReleaseRemotePlaybackTexture(uint32 sync_point) { + DCHECK(main_thread_checker_.CalledOnValidThread()); + DCHECK(remote_playback_texture_id_); + + blink::WebGraphicsContext3D* context = + stream_texture_factory_->Context3d(); + + if (sync_point) + context->waitSyncPoint(sync_point); + context->deleteTexture(remote_playback_texture_id_); + remote_playback_texture_id_ = 0; +} + void WebMediaPlayerAndroid::enterFullscreen() { if (manager_->CanEnterFullscreen(frame_)) { - proxy_->EnterFullscreen(player_id_); + manager_->EnterFullscreen(player_id_, frame_); SetNeedsEstablishPeer(false); } } void WebMediaPlayerAndroid::exitFullscreen() { - proxy_->ExitFullscreen(player_id_); + manager_->ExitFullscreen(player_id_); } bool WebMediaPlayerAndroid::canEnterFullscreen() const { diff --git a/chromium/content/renderer/media/android/webmediaplayer_android.h b/chromium/content/renderer/media/android/webmediaplayer_android.h index c25b0bd3975..40582ca1c8a 100644 --- a/chromium/content/renderer/media/android/webmediaplayer_android.h +++ b/chromium/content/renderer/media/android/webmediaplayer_android.h @@ -26,9 +26,9 @@ #include "media/base/demuxer_stream.h" #include "media/base/media_keys.h" #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" +#include "third_party/WebKit/public/platform/WebMediaPlayer.h" #include "third_party/WebKit/public/platform/WebSize.h" #include "third_party/WebKit/public/platform/WebURL.h" -#include "third_party/WebKit/public/web/WebMediaPlayer.h" #include "ui/gfx/rect_f.h" namespace media { @@ -36,7 +36,7 @@ class Demuxer; class MediaLog; } -namespace WebKit { +namespace blink { class WebFrame; } @@ -47,19 +47,18 @@ class WebLayerImpl; namespace content { class WebMediaPlayerDelegate; class RendererMediaPlayerManager; -class WebMediaPlayerProxyAndroid; #if defined(GOOGLE_TV) class MediaStreamAudioRenderer; class MediaStreamClient; #endif -// This class implements WebKit::WebMediaPlayer by keeping the android +// This class implements blink::WebMediaPlayer by keeping the android // media player in the browser process. It listens to all the status changes // sent from the browser process and sends playback controls to the media // player. class WebMediaPlayerAndroid - : public WebKit::WebMediaPlayer, + : public blink::WebMediaPlayer, public cc::VideoFrameProvider, public base::MessageLoop::DestructionObserver, public base::SupportsWeakPtr<WebMediaPlayerAndroid> { @@ -72,24 +71,23 @@ class WebMediaPlayerAndroid // blink, so that enterFullscreen() will not be called if another video is // already in fullscreen. WebMediaPlayerAndroid( - WebKit::WebFrame* frame, - WebKit::WebMediaPlayerClient* client, + blink::WebFrame* frame, + blink::WebMediaPlayerClient* client, base::WeakPtr<WebMediaPlayerDelegate> delegate, RendererMediaPlayerManager* manager, - WebMediaPlayerProxyAndroid* proxy, StreamTextureFactory* factory, const scoped_refptr<base::MessageLoopProxy>& media_loop, media::MediaLog* media_log); virtual ~WebMediaPlayerAndroid(); - // WebKit::WebMediaPlayer implementation. + // blink::WebMediaPlayer implementation. virtual void enterFullscreen(); virtual void exitFullscreen(); virtual bool canEnterFullscreen() const; // Resource loading. virtual void load(LoadType load_type, - const WebKit::WebURL& url, + const blink::WebURL& url, CORSMode cors_mode) OVERRIDE; // Playback controls. @@ -101,16 +99,16 @@ class WebMediaPlayerAndroid virtual bool supportsSave() const; virtual void setRate(double rate); virtual void setVolume(double volume); - virtual const WebKit::WebTimeRanges& buffered(); + virtual const blink::WebTimeRanges& buffered(); virtual double maxTimeSeekable() const; // Methods for painting. - virtual void paint(WebKit::WebCanvas* canvas, - const WebKit::WebRect& rect, + virtual void paint(blink::WebCanvas* canvas, + const blink::WebRect& rect, unsigned char alpha); virtual bool copyVideoTextureToPlatformTexture( - WebKit::WebGraphicsContext3D* web_graphics_context, + blink::WebGraphicsContext3D* web_graphics_context, unsigned int texture, unsigned int level, unsigned int internal_format, @@ -123,7 +121,7 @@ class WebMediaPlayerAndroid virtual bool hasAudio() const; // Dimensions of the video. - virtual WebKit::WebSize naturalSize() const; + virtual blink::WebSize naturalSize() const; // Getters of playback state. virtual bool paused() const; @@ -134,8 +132,8 @@ class WebMediaPlayerAndroid virtual bool didLoadingProgress() const; // Internal states of loading and network. - virtual WebKit::WebMediaPlayer::NetworkState networkState() const; - virtual WebKit::WebMediaPlayer::ReadyState readyState() const; + virtual blink::WebMediaPlayer::NetworkState networkState() const; + virtual blink::WebMediaPlayer::ReadyState readyState() const; virtual bool hasSingleSecurityOrigin() const; virtual bool didPassCORSAccessCheck() const; @@ -161,6 +159,7 @@ class WebMediaPlayerAndroid int height, bool success); void OnPlaybackComplete(); void OnBufferingUpdate(int percentage); + void OnSeekRequest(const base::TimeDelta& time_to_seek); void OnSeekComplete(const base::TimeDelta& current_time); void OnMediaError(int error_type); void OnVideoSizeChanged(int width, int height); @@ -170,10 +169,13 @@ class WebMediaPlayerAndroid void OnTimeUpdate(const base::TimeDelta& current_time); // Functions called when media player status changes. - void OnMediaPlayerPlay(); - void OnMediaPlayerPause(); + void OnConnectedToRemoteDevice(); + void OnDisconnectedFromRemoteDevice(); void OnDidEnterFullscreen(); void OnDidExitFullscreen(); + void OnMediaPlayerPlay(); + void OnMediaPlayerPause(); + void OnRequestFullscreen(); // Called when the player is released. virtual void OnPlayerReleased(); @@ -189,27 +191,27 @@ class WebMediaPlayerAndroid // Detach the player from its manager. void Detach(); -#if defined(GOOGLE_TV) +#if defined(VIDEO_HOLE) // Retrieve geometry of the media player (i.e. location and size of the video // frame) if changed. Returns true only if the geometry has been changed since // the last call. bool RetrieveGeometryChange(gfx::RectF* rect); -#endif +#endif // defined(VIDEO_HOLE) virtual MediaKeyException generateKeyRequest( - const WebKit::WebString& key_system, + const blink::WebString& key_system, const unsigned char* init_data, unsigned init_data_length) OVERRIDE; virtual MediaKeyException addKey( - const WebKit::WebString& key_system, + const blink::WebString& key_system, const unsigned char* key, unsigned key_length, const unsigned char* init_data, unsigned init_data_length, - const WebKit::WebString& session_id) OVERRIDE; + const blink::WebString& session_id) OVERRIDE; virtual MediaKeyException cancelKeyRequest( - const WebKit::WebString& key_system, - const WebKit::WebString& session_id) OVERRIDE; + const blink::WebString& key_system, + const blink::WebString& session_id) OVERRIDE; void OnKeyAdded(const std::string& session_id); void OnKeyError(const std::string& session_id, @@ -219,10 +221,9 @@ class WebMediaPlayerAndroid const std::vector<uint8>& message, const std::string& destination_url); - void OnMediaSourceOpened(WebKit::WebMediaSource* web_media_source); + void OnMediaSourceOpened(blink::WebMediaSource* web_media_source); void OnNeedKey(const std::string& type, - const std::string& session_id, const std::vector<uint8>& init_data); #if defined(GOOGLE_TV) @@ -231,13 +232,22 @@ class WebMediaPlayerAndroid const base::Closure& destroy_demuxer_cb); #endif + // Can be called on any thread. + static void OnReleaseRemotePlaybackTexture( + const scoped_refptr<base::MessageLoopProxy>& main_loop, + const base::WeakPtr<WebMediaPlayerAndroid>& player, + uint32 sync_point); + protected: // Helper method to update the playing state. void UpdatePlayingState(bool is_playing_); // Helper methods for posting task for setting states and update WebKit. - void UpdateNetworkState(WebKit::WebMediaPlayer::NetworkState state); - void UpdateReadyState(WebKit::WebMediaPlayer::ReadyState state); + void UpdateNetworkState(blink::WebMediaPlayer::NetworkState state); + void UpdateReadyState(blink::WebMediaPlayer::ReadyState state); + void TryCreateStreamTextureProxyIfNeeded(); + void DoCreateStreamTexture(); + // Helper method to reestablish the surface texture peer for android // media player. @@ -246,34 +256,34 @@ class WebMediaPlayerAndroid // Requesting whether the surface texture peer needs to be reestablished. void SetNeedsEstablishPeer(bool needs_establish_peer); -#if defined(GOOGLE_TV) - // Request external surface for out-of-band composition. - void RequestExternalSurface(); -#endif - private: + void DrawRemotePlaybackIcon(); void ReallocateVideoFrame(); + void SetCurrentFrameInternal(scoped_refptr<media::VideoFrame>& frame); void DidLoadMediaInfo(MediaInfoLoader::Status status); + void DoReleaseRemotePlaybackTexture(uint32 sync_point); + + bool IsKeySystemSupported(const blink::WebString& key_system); // Actually do the work for generateKeyRequest/addKey so they can easily // report results to UMA. MediaKeyException GenerateKeyRequestInternal( - const WebKit::WebString& key_system, + const blink::WebString& key_system, const unsigned char* init_data, unsigned init_data_length); - MediaKeyException AddKeyInternal(const WebKit::WebString& key_system, + MediaKeyException AddKeyInternal(const blink::WebString& key_system, const unsigned char* key, unsigned key_length, const unsigned char* init_data, unsigned init_data_length, - const WebKit::WebString& session_id); + const blink::WebString& session_id); MediaKeyException CancelKeyRequestInternal( - const WebKit::WebString& key_system, - const WebKit::WebString& session_id); + const blink::WebString& key_system, + const blink::WebString& session_id); - WebKit::WebFrame* const frame_; + blink::WebFrame* const frame_; - WebKit::WebMediaPlayerClient* const client_; + blink::WebMediaPlayerClient* const client_; // |delegate_| is used to notify the browser process of the player status, so // that the browser process can control screen locks. @@ -283,16 +293,19 @@ class WebMediaPlayerAndroid base::WeakPtr<WebMediaPlayerDelegate> delegate_; // Save the list of buffered time ranges. - WebKit::WebTimeRanges buffered_; + blink::WebTimeRanges buffered_; // Size of the video. - WebKit::WebSize natural_size_; + blink::WebSize natural_size_; // Size that has been sent to StreamTexture. - WebKit::WebSize cached_stream_texture_size_; + blink::WebSize cached_stream_texture_size_; // The video frame object used for rendering by the compositor. scoped_refptr<media::VideoFrame> current_frame_; + base::Lock current_frame_lock_; + + base::ThreadChecker main_thread_checker_; // Message loop for main renderer thread. const scoped_refptr<base::MessageLoopProxy> main_loop_; @@ -311,24 +324,31 @@ class WebMediaPlayerAndroid // any subsequent duration value passed to OnMediaMetadataChange(). bool ignore_metadata_duration_change_; - // The time android media player is trying to seek. - double pending_seek_; + // Seek gets pending if another seek is in progress. Only last pending seek + // will have effect. + bool pending_seek_; + base::TimeDelta pending_seek_time_; // Internal seek state. bool seeking_; + base::TimeDelta seek_time_; // Whether loading has progressed since the last call to didLoadingProgress. mutable bool did_loading_progress_; - // Manager for managing this object. + // Manager for managing this object and for delegating method calls on + // Render Thread. RendererMediaPlayerManager* manager_; // Player ID assigned by the |manager_|. int player_id_; // Current player states. - WebKit::WebMediaPlayer::NetworkState network_state_; - WebKit::WebMediaPlayer::ReadyState ready_state_; + blink::WebMediaPlayer::NetworkState network_state_; + blink::WebMediaPlayer::ReadyState ready_state_; + + // GL texture ID used to show the remote playback icon. + unsigned int remote_playback_texture_id_; // GL texture ID allocated to the video. unsigned int texture_id_; @@ -344,7 +364,7 @@ class WebMediaPlayerAndroid // Whether the mediaplayer is playing. bool is_playing_; - // Wether the mediaplayer has already started playing. + // Whether the mediaplayer has already started playing. bool playing_started_; // Whether media player needs to re-establish the surface texture peer. @@ -376,15 +396,17 @@ class WebMediaPlayerAndroid scoped_ptr<webkit::WebLayerImpl> video_weblayer_; +#if defined(VIDEO_HOLE) + // A rectangle represents the geometry of video frame, when computed last + // time. + gfx::RectF last_computed_rect_; +#endif // defined(VIDEO_HOLE) + #if defined(GOOGLE_TV) // Pixel threshold for external surface usage. Negative value means that the // threshold is not defined, so that external surface is never used. int external_surface_threshold_; - // A rectangle represents the geometry of video frame, when computed last - // time. - gfx::RectF last_computed_rect_; - // Media Stream related fields. media::Demuxer* demuxer_; base::Closure destroy_demuxer_cb_; @@ -401,23 +423,21 @@ class WebMediaPlayerAndroid MediaPlayerHostMsg_Initialize_Type player_type_; - // Proxy object that delegates method calls on Render Thread. - // This object is created on the Render Thread and is only called in the - // destructor. - WebMediaPlayerProxyAndroid* proxy_; - // The current playing time. Because the media player is in the browser // process, it will regularly update the |current_time_| by calling // OnTimeUpdate(). double current_time_; + // Whether the browser is currently connected to a remote media player. + bool is_remote_; + media::MediaLog* media_log_; scoped_ptr<MediaInfoLoader> info_loader_; // The currently selected key system. Empty string means that no key system // has been selected. - WebKit::WebString current_key_system_; + blink::WebString current_key_system_; // Temporary for EME v0.1. In the future the init data type should be passed // through GenerateKeyRequest() directly from WebKit. diff --git a/chromium/content/renderer/media/android/webmediaplayer_proxy_android.cc b/chromium/content/renderer/media/android/webmediaplayer_proxy_android.cc deleted file mode 100644 index 39e87a07dd7..00000000000 --- a/chromium/content/renderer/media/android/webmediaplayer_proxy_android.cc +++ /dev/null @@ -1,265 +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/renderer/media/android/webmediaplayer_proxy_android.h" - -#include "base/bind.h" -#include "base/message_loop/message_loop.h" -#include "content/common/media/media_player_messages_android.h" -#include "content/renderer/media/android/renderer_media_player_manager.h" -#include "content/renderer/media/android/webmediaplayer_android.h" - -namespace content { - -WebMediaPlayerProxyAndroid::WebMediaPlayerProxyAndroid( - RenderView* render_view, - RendererMediaPlayerManager* manager) - : RenderViewObserver(render_view), - manager_(manager) {} - -WebMediaPlayerProxyAndroid::~WebMediaPlayerProxyAndroid() { - Send(new MediaPlayerHostMsg_DestroyAllMediaPlayers(routing_id())); -} - -bool WebMediaPlayerProxyAndroid::OnMessageReceived(const IPC::Message& msg) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(WebMediaPlayerProxyAndroid, msg) - IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaMetadataChanged, - OnMediaMetadataChanged) - IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaPlaybackCompleted, - OnMediaPlaybackCompleted) - IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaBufferingUpdate, - OnMediaBufferingUpdate) - IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaSeekCompleted, OnMediaSeekCompleted) - IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaError, OnMediaError) - IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaVideoSizeChanged, - OnVideoSizeChanged) - IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaTimeUpdate, OnTimeUpdate) - IPC_MESSAGE_HANDLER(MediaPlayerMsg_MediaPlayerReleased, - OnMediaPlayerReleased) - IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidEnterFullscreen, OnDidEnterFullscreen) - IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidExitFullscreen, OnDidExitFullscreen) - IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidMediaPlayerPlay, OnPlayerPlay) - IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidMediaPlayerPause, OnPlayerPause) - IPC_MESSAGE_HANDLER(MediaKeysMsg_KeyAdded, OnKeyAdded) - IPC_MESSAGE_HANDLER(MediaKeysMsg_KeyError, OnKeyError) - IPC_MESSAGE_HANDLER(MediaKeysMsg_KeyMessage, OnKeyMessage) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - -void WebMediaPlayerProxyAndroid::Initialize( - MediaPlayerHostMsg_Initialize_Type type, - int player_id, - const GURL& url, - const GURL& first_party_for_cookies, - int demuxer_client_id) { - Send(new MediaPlayerHostMsg_Initialize( - routing_id(), type, player_id, url, first_party_for_cookies, - demuxer_client_id)); -} - -void WebMediaPlayerProxyAndroid::Start(int player_id) { - Send(new MediaPlayerHostMsg_Start(routing_id(), player_id)); -} - -void WebMediaPlayerProxyAndroid::Pause( - int player_id, - bool is_media_related_action) { - Send(new MediaPlayerHostMsg_Pause( - routing_id(), player_id, is_media_related_action)); -} - -void WebMediaPlayerProxyAndroid::Seek(int player_id, base::TimeDelta time) { - Send(new MediaPlayerHostMsg_Seek(routing_id(), player_id, time)); -} - -void WebMediaPlayerProxyAndroid::SetVolume(int player_id, double volume) { - Send(new MediaPlayerHostMsg_SetVolume(routing_id(), player_id, volume)); -} - -void WebMediaPlayerProxyAndroid::ReleaseResources(int player_id) { - Send(new MediaPlayerHostMsg_Release(routing_id(), player_id)); -} - -void WebMediaPlayerProxyAndroid::DestroyPlayer(int player_id) { - Send(new MediaPlayerHostMsg_DestroyMediaPlayer(routing_id(), player_id)); -} - -void WebMediaPlayerProxyAndroid::OnMediaMetadataChanged( - int player_id, - base::TimeDelta duration, - int width, - int height, - bool success) { - WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id); - if (player) - player->OnMediaMetadataChanged(duration, width, height, success); -} - -void WebMediaPlayerProxyAndroid::OnMediaPlaybackCompleted(int player_id) { - WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id); - if (player) - player->OnPlaybackComplete(); -} - -void WebMediaPlayerProxyAndroid::OnMediaBufferingUpdate(int player_id, - int percent) { - WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id); - if (player) - player->OnBufferingUpdate(percent); -} - -void WebMediaPlayerProxyAndroid::OnMediaSeekCompleted( - int player_id, - base::TimeDelta current_time) { - WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id); - if (player) - player->OnSeekComplete(current_time); -} - -void WebMediaPlayerProxyAndroid::OnMediaError(int player_id, int error) { - WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id); - if (player) - player->OnMediaError(error); -} - -void WebMediaPlayerProxyAndroid::OnVideoSizeChanged(int player_id, - int width, - int height) { - WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id); - if (player) - player->OnVideoSizeChanged(width, height); -} - -void WebMediaPlayerProxyAndroid::OnTimeUpdate(int player_id, - base::TimeDelta current_time) { - WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id); - if (player) - player->OnTimeUpdate(current_time); -} - -void WebMediaPlayerProxyAndroid::OnMediaPlayerReleased(int player_id) { - WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id); - if (player) - player->OnPlayerReleased(); -} - -void WebMediaPlayerProxyAndroid::OnDidEnterFullscreen(int player_id) { - WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id); - if (player) - player->OnDidEnterFullscreen(); -} - -void WebMediaPlayerProxyAndroid::OnDidExitFullscreen(int player_id) { - WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id); - if (player) - player->OnDidExitFullscreen(); -} - -void WebMediaPlayerProxyAndroid::OnPlayerPlay(int player_id) { - WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id); - if (player) - player->OnMediaPlayerPlay(); -} - -void WebMediaPlayerProxyAndroid::OnPlayerPause(int player_id) { - WebMediaPlayerAndroid* player = GetWebMediaPlayer(player_id); - if (player) - player->OnMediaPlayerPause(); -} - -void WebMediaPlayerProxyAndroid::EnterFullscreen(int player_id) { - Send(new MediaPlayerHostMsg_EnterFullscreen(routing_id(), player_id)); -} - -void WebMediaPlayerProxyAndroid::ExitFullscreen(int player_id) { - Send(new MediaPlayerHostMsg_ExitFullscreen(routing_id(), player_id)); -} - -#if defined(GOOGLE_TV) -void WebMediaPlayerProxyAndroid::RequestExternalSurface( - int player_id, - const gfx::RectF& geometry) { - Send(new MediaPlayerHostMsg_NotifyExternalSurface( - routing_id(), player_id, true, geometry)); -} - -void WebMediaPlayerProxyAndroid::DidCommitCompositorFrame() { - std::map<int, gfx::RectF> geometry_change; - manager_->RetrieveGeometryChanges(&geometry_change); - for (std::map<int, gfx::RectF>::iterator it = geometry_change.begin(); - it != geometry_change.end(); - ++it) { - Send(new MediaPlayerHostMsg_NotifyExternalSurface( - routing_id(), it->first, false, it->second)); - } -} -#endif - -void WebMediaPlayerProxyAndroid::InitializeCDM(int media_keys_id, - const std::vector<uint8>& uuid, - const GURL& frame_url) { - Send(new MediaKeysHostMsg_InitializeCDM( - routing_id(), media_keys_id, uuid, frame_url)); -} - -void WebMediaPlayerProxyAndroid::GenerateKeyRequest( - int media_keys_id, - const std::string& type, - const std::vector<uint8>& init_data) { - Send(new MediaKeysHostMsg_GenerateKeyRequest( - routing_id(), media_keys_id, type, init_data)); -} - -void WebMediaPlayerProxyAndroid::AddKey(int media_keys_id, - const std::vector<uint8>& key, - const std::vector<uint8>& init_data, - const std::string& session_id) { - Send(new MediaKeysHostMsg_AddKey( - routing_id(), media_keys_id, key, init_data, session_id)); -} - -void WebMediaPlayerProxyAndroid::CancelKeyRequest( - int media_keys_id, - const std::string& session_id) { - Send(new MediaKeysHostMsg_CancelKeyRequest( - routing_id(), media_keys_id, session_id)); -} - -WebMediaPlayerAndroid* WebMediaPlayerProxyAndroid::GetWebMediaPlayer( - int player_id) { - return static_cast<WebMediaPlayerAndroid*>( - manager_->GetMediaPlayer(player_id)); -} - -void WebMediaPlayerProxyAndroid::OnKeyAdded(int media_keys_id, - const std::string& session_id) { - WebMediaPlayerAndroid* player = GetWebMediaPlayer(media_keys_id); - if (player) - player->OnKeyAdded(session_id); -} - -void WebMediaPlayerProxyAndroid::OnKeyError( - int media_keys_id, - const std::string& session_id, - media::MediaKeys::KeyError error_code, - int system_code) { - WebMediaPlayerAndroid* player = GetWebMediaPlayer(media_keys_id); - if (player) - player->OnKeyError(session_id, error_code, system_code); -} - -void WebMediaPlayerProxyAndroid::OnKeyMessage( - int media_keys_id, - const std::string& session_id, - const std::vector<uint8>& message, - const std::string& destination_url) { - WebMediaPlayerAndroid* player = GetWebMediaPlayer(media_keys_id); - if (player) - player->OnKeyMessage(session_id, message, destination_url); -} - -} // namespace content diff --git a/chromium/content/renderer/media/android/webmediaplayer_proxy_android.h b/chromium/content/renderer/media/android/webmediaplayer_proxy_android.h deleted file mode 100644 index 76d2d43b1d5..00000000000 --- a/chromium/content/renderer/media/android/webmediaplayer_proxy_android.h +++ /dev/null @@ -1,136 +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_RENDERER_MEDIA_ANDROID_WEBMEDIAPLAYER_PROXY_ANDROID_H_ -#define CONTENT_RENDERER_MEDIA_ANDROID_WEBMEDIAPLAYER_PROXY_ANDROID_H_ - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/time/time.h" -#include "content/common/media/media_player_messages_enums_android.h" -#include "content/public/renderer/render_view_observer.h" -#include "media/base/android/media_player_android.h" -#include "media/base/media_keys.h" -#include "url/gurl.h" - -#if defined(GOOGLE_TV) -#include "ui/gfx/rect_f.h" -#endif - -namespace content { - -class RendererMediaPlayerManager; -class WebMediaPlayerAndroid; - -// This class manages IPC communication between WebMediaPlayerAndroid and the -// MediaPlayerManagerAndroid in the browser process. -class WebMediaPlayerProxyAndroid : public RenderViewObserver { - public: - // Construct a WebMediaPlayerProxyAndroid object for the |render_view|. - // |manager| is passed to this class so that it can find the right - // WebMediaPlayerAndroid using player IDs. - WebMediaPlayerProxyAndroid( - RenderView* render_view, - RendererMediaPlayerManager* manager); - virtual ~WebMediaPlayerProxyAndroid(); - - // RenderViewObserver overrides. - virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; - - // Initializes a MediaPlayerAndroid object in browser process. - void Initialize(MediaPlayerHostMsg_Initialize_Type type, - int player_id, - const GURL& url, - const GURL& first_party_for_cookies, - int demuxer_client_id); - - // Starts the player. - void Start(int player_id); - - // Pauses the player. - // is_media_related_action should be true if this pause is coming from an - // an action that explicitly pauses the video (user pressing pause, JS, etc.) - // Otherwise it should be false if Pause is being called due to other reasons - // (cleanup, freeing resources, etc.) - void Pause(int player_id, bool is_media_related_action); - - // Performs seek on the player. - void Seek(int player_id, base::TimeDelta time); - - // Set the player volume. - void SetVolume(int player_id, double volume); - - // Release resources for the player. - void ReleaseResources(int player_id); - - // Destroy the player in the browser process - void DestroyPlayer(int player_id); - - // Request the player to enter fullscreen. - void EnterFullscreen(int player_id); - - // Request the player to exit fullscreen. - void ExitFullscreen(int player_id); - -#if defined(GOOGLE_TV) - // Request an external surface for out-of-band compositing. - void RequestExternalSurface(int player_id, const gfx::RectF& geometry); - - // RenderViewObserver overrides. - virtual void DidCommitCompositorFrame() OVERRIDE; -#endif - - // Encrypted media related methods. - void InitializeCDM(int media_keys_id, - const std::vector<uint8>& uuid, - const GURL& frame_url); - void GenerateKeyRequest(int media_keys_id, - const std::string& type, - const std::vector<uint8>& init_data); - void AddKey(int media_keys_id, - const std::vector<uint8>& key, - const std::vector<uint8>& init_data, - const std::string& session_id); - void CancelKeyRequest(int media_keys_id, const std::string& session_id); - - private: - WebMediaPlayerAndroid* GetWebMediaPlayer(int player_id); - - // Message handlers. - void OnMediaMetadataChanged(int player_id, - base::TimeDelta duration, - int width, - int height, - bool success); - void OnMediaPlaybackCompleted(int player_id); - void OnMediaBufferingUpdate(int player_id, int percent); - void OnMediaSeekCompleted(int player_id, base::TimeDelta current_time); - void OnMediaError(int player_id, int error); - void OnVideoSizeChanged(int player_id, int width, int height); - void OnTimeUpdate(int player_id, base::TimeDelta current_time); - void OnMediaPlayerReleased(int player_id); - void OnDidExitFullscreen(int player_id); - void OnDidEnterFullscreen(int player_id); - void OnPlayerPlay(int player_id); - void OnPlayerPause(int player_id); - void OnKeyAdded(int media_keys_id, const std::string& session_id); - void OnKeyError(int media_keys_id, - const std::string& session_id, - media::MediaKeys::KeyError error_code, - int system_code); - void OnKeyMessage(int media_keys_id, - const std::string& session_id, - const std::vector<uint8>& message, - const std::string& destination_url); - - RendererMediaPlayerManager* manager_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(WebMediaPlayerProxyAndroid); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_ANDROID_WEBMEDIAPLAYER_PROXY_ANDROID_H_ diff --git a/chromium/content/renderer/media/audio_decoder.cc b/chromium/content/renderer/media/audio_decoder.cc index 64cf6ddde73..dd9f1fafa0d 100644 --- a/chromium/content/renderer/media/audio_decoder.cc +++ b/chromium/content/renderer/media/audio_decoder.cc @@ -19,13 +19,13 @@ using media::AudioBus; using media::AudioFileReader; using media::InMemoryUrlProtocol; using std::vector; -using WebKit::WebAudioBus; +using blink::WebAudioBus; namespace content { // Decode in-memory audio file data. bool DecodeAudioFileData( - WebKit::WebAudioBus* destination_bus, + blink::WebAudioBus* destination_bus, const char* data, size_t data_size, double sample_rate) { DCHECK(destination_bus); if (!destination_bus) diff --git a/chromium/content/renderer/media/audio_decoder.h b/chromium/content/renderer/media/audio_decoder.h index bef404b44bc..9c14ed9f5d5 100644 --- a/chromium/content/renderer/media/audio_decoder.h +++ b/chromium/content/renderer/media/audio_decoder.h @@ -7,12 +7,12 @@ #include "base/basictypes.h" -namespace WebKit { class WebAudioBus; } +namespace blink { class WebAudioBus; } namespace content { // Decode in-memory audio file data. -bool DecodeAudioFileData(WebKit::WebAudioBus* destination_bus, const char* data, +bool DecodeAudioFileData(blink::WebAudioBus* destination_bus, const char* data, size_t data_size, double sample_rate); } // namespace content diff --git a/chromium/content/renderer/media/audio_input_message_filter.cc b/chromium/content/renderer/media/audio_input_message_filter.cc index 84a86de2577..a2696f085e6 100644 --- a/chromium/content/renderer/media/audio_input_message_filter.cc +++ b/chromium/content/renderer/media/audio_input_message_filter.cc @@ -6,7 +6,9 @@ #include "base/bind.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/strings/stringprintf.h" #include "content/common/media/audio_messages.h" +#include "content/renderer/media/webrtc_logging.h" #include "ipc/ipc_logging.h" namespace content { @@ -123,6 +125,10 @@ void AudioInputMessageFilter::OnStreamCreated( uint32 total_segments) { DCHECK(io_message_loop_->BelongsToCurrentThread()); + WebRtcLogMessage(base::StringPrintf( + "AIMF::OnStreamCreated. stream_id=%d", + stream_id)); + #if !defined(OS_WIN) base::SyncSocket::Handle socket_handle = socket_descriptor.fd; #endif diff --git a/chromium/content/renderer/media/audio_message_filter.cc b/chromium/content/renderer/media/audio_message_filter.cc index e56d612d579..27d0821342f 100644 --- a/chromium/content/renderer/media/audio_message_filter.cc +++ b/chromium/content/renderer/media/audio_message_filter.cc @@ -6,7 +6,9 @@ #include "base/bind.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/strings/stringprintf.h" #include "content/common/media/audio_messages.h" +#include "content/renderer/media/webrtc_logging.h" #include "content/renderer/render_thread_impl.h" #include "ipc/ipc_logging.h" @@ -169,6 +171,10 @@ void AudioMessageFilter::OnStreamCreated( uint32 length) { DCHECK(io_message_loop_->BelongsToCurrentThread()); + WebRtcLogMessage(base::StringPrintf( + "AMF::OnStreamCreated. stream_id=%d", + stream_id)); + #if !defined(OS_WIN) base::SyncSocket::Handle socket_handle = socket_descriptor.fd; #endif @@ -202,6 +208,13 @@ void AudioMessageFilter::OnOutputDeviceChanged(int stream_id, DCHECK(io_message_loop_->BelongsToCurrentThread()); base::AutoLock auto_lock(lock_); + WebRtcLogMessage(base::StringPrintf( + "AMF::OnOutputDeviceChanged. stream_id=%d" + ", new_buffer_size=%d, new_sample_rate=%d", + stream_id, + new_buffer_size, + new_sample_rate)); + // Ignore the message if an audio hardware config hasn't been created; this // can occur if the renderer is using the high latency audio path. // TODO(dalecurtis): After http://crbug.com/173435 is fixed, convert to CHECK. diff --git a/chromium/content/renderer/media/buffered_data_source.cc b/chromium/content/renderer/media/buffered_data_source.cc index 65a2d49d8fe..1992b706ad4 100644 --- a/chromium/content/renderer/media/buffered_data_source.cc +++ b/chromium/content/renderer/media/buffered_data_source.cc @@ -10,7 +10,7 @@ #include "media/base/media_log.h" #include "net/base/net_errors.h" -using WebKit::WebFrame; +using blink::WebFrame; namespace { @@ -82,9 +82,7 @@ BufferedDataSource::BufferedDataSource( WebFrame* frame, media::MediaLog* media_log, const DownloadingCB& downloading_cb) - : weak_factory_(this), - weak_this_(weak_factory_.GetWeakPtr()), - cors_mode_(BufferedResourceLoader::kUnspecified), + : cors_mode_(BufferedResourceLoader::kUnspecified), total_bytes_(kPositionNotSpecified), assume_fully_buffered_(false), streaming_(false), @@ -98,8 +96,10 @@ BufferedDataSource::BufferedDataSource( bitrate_(0), playback_rate_(0.0), media_log_(media_log), - downloading_cb_(downloading_cb) { + downloading_cb_(downloading_cb), + weak_factory_(this) { DCHECK(!downloading_cb_.is_null()); + weak_this_ = weak_factory_.GetWeakPtr(); } BufferedDataSource::~BufferedDataSource() {} @@ -192,6 +192,28 @@ void BufferedDataSource::Abort() { frame_ = NULL; } +void BufferedDataSource::MediaPlaybackRateChanged(float playback_rate) { + DCHECK(render_loop_->BelongsToCurrentThread()); + DCHECK(loader_.get()); + + if (playback_rate < 0.0f) + return; + + playback_rate_ = playback_rate; + loader_->SetPlaybackRate(playback_rate); +} + +void BufferedDataSource::MediaIsPlaying() { + DCHECK(render_loop_->BelongsToCurrentThread()); + media_has_played_ = true; + UpdateDeferStrategy(false); +} + +void BufferedDataSource::MediaIsPaused() { + DCHECK(render_loop_->BelongsToCurrentThread()); + UpdateDeferStrategy(true); +} + ///////////////////////////////////////////////////////////////////////////// // media::DataSource implementation. void BufferedDataSource::Stop(const base::Closure& closure) { @@ -205,11 +227,6 @@ void BufferedDataSource::Stop(const base::Closure& closure) { base::Bind(&BufferedDataSource::StopLoader, weak_this_)); } -void BufferedDataSource::SetPlaybackRate(float playback_rate) { - render_loop_->PostTask(FROM_HERE, base::Bind( - &BufferedDataSource::SetPlaybackRateTask, weak_this_, playback_rate)); -} - void BufferedDataSource::SetBitrate(int bitrate) { render_loop_->PostTask(FROM_HERE, base::Bind( &BufferedDataSource::SetBitrateTask, weak_this_, bitrate)); @@ -279,35 +296,6 @@ void BufferedDataSource::StopLoader() { loader_->Stop(); } -void BufferedDataSource::SetPlaybackRateTask(float playback_rate) { - DCHECK(render_loop_->BelongsToCurrentThread()); - DCHECK(loader_.get()); - - if (playback_rate != 0) - media_has_played_ = true; - - playback_rate_ = playback_rate; - loader_->SetPlaybackRate(playback_rate); - - if (!loader_->range_supported()) { - // 200 responses end up not being reused to satisfy future range requests, - // and we don't want to get too far ahead of the read-head (and thus require - // a restart), so keep to the thresholds. - loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); - } else if (media_has_played_ && playback_rate == 0) { - // If the playback has started (at which point the preload value is ignored) - // and we're paused, then try to load as much as possible (the loader will - // fall back to kCapacityDefer if it knows the current response won't be - // useful from the cache in the future). - loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer); - } else { - // If media is currently playing or the page indicated preload=auto, - // use threshold strategy to enable/disable deferring when the buffer - // is full/depleted. - loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); - } -} - void BufferedDataSource::SetBitrateTask(int bitrate) { DCHECK(render_loop_->BelongsToCurrentThread()); DCHECK(loader_.get()); @@ -545,4 +533,28 @@ void BufferedDataSource::UpdateHostState_Locked() { host()->AddBufferedByteRange(0, total_bytes_); } +void BufferedDataSource::UpdateDeferStrategy(bool paused) { + // 200 responses end up not being reused to satisfy future range requests, + // and we don't want to get too far ahead of the read-head (and thus require + // a restart), so keep to the thresholds. + if (!loader_->range_supported()) { + loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); + return; + } + + // If the playback has started (at which point the preload value is ignored) + // and we're paused, then try to load as much as possible (the loader will + // fall back to kCapacityDefer if it knows the current response won't be + // useful from the cache in the future). + if (media_has_played_ && paused) { + loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer); + return; + } + + // If media is currently playing or the page indicated preload=auto, + // use threshold strategy to enable/disable deferring when the buffer + // is full/depleted. + loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); +} + } // namespace content diff --git a/chromium/content/renderer/media/buffered_data_source.h b/chromium/content/renderer/media/buffered_data_source.h index da451ba9a73..30991dd2796 100644 --- a/chromium/content/renderer/media/buffered_data_source.h +++ b/chromium/content/renderer/media/buffered_data_source.h @@ -39,7 +39,7 @@ class CONTENT_EXPORT BufferedDataSource : public media::DataSource { // |downloading_cb| will be called whenever the downloading/paused state of // the source changes. BufferedDataSource(const scoped_refptr<base::MessageLoopProxy>& render_loop, - WebKit::WebFrame* frame, + blink::WebFrame* frame, media::MediaLog* media_log, const DownloadingCB& downloading_cb); virtual ~BufferedDataSource(); @@ -73,11 +73,16 @@ class CONTENT_EXPORT BufferedDataSource : public media::DataSource { // Method called on the render thread. void Abort(); + // Notifies changes in playback state for controlling media buffering + // behavior. + void MediaPlaybackRateChanged(float playback_rate); + void MediaIsPlaying(); + void MediaIsPaused(); + // media::DataSource implementation. // Called from demuxer thread. virtual void set_host(media::DataSourceHost* host) OVERRIDE; virtual void Stop(const base::Closure& closure) OVERRIDE; - virtual void SetPlaybackRate(float playback_rate) OVERRIDE; virtual void Read(int64 position, int size, uint8* data, const media::DataSource::ReadCB& read_cb) OVERRIDE; @@ -105,11 +110,6 @@ class CONTENT_EXPORT BufferedDataSource : public media::DataSource { // Stops |loader_| if present. Used by Abort() and Stop(). void StopLoader(); - // This task uses the current playback rate with the previous playback rate - // to determine whether we are going from pause to play and play to pause, - // and signals the buffered resource loader accordingly. - void SetPlaybackRateTask(float playback_rate); - // Tells |loader_| the bitrate of the media. void SetBitrateTask(int bitrate); @@ -135,7 +135,10 @@ class CONTENT_EXPORT BufferedDataSource : public media::DataSource { void UpdateHostState_Locked(); - base::WeakPtrFactory<BufferedDataSource> weak_factory_; + // Update |loader_|'s deferring strategy in response to a play/pause, or + // change in playback rate. + void UpdateDeferStrategy(bool paused); + base::WeakPtr<BufferedDataSource> weak_this_; // URL of the resource requested. @@ -157,7 +160,7 @@ class CONTENT_EXPORT BufferedDataSource : public media::DataSource { bool streaming_; // A webframe for loading. - WebKit::WebFrame* frame_; + blink::WebFrame* frame_; // A resource loader for the media resource. scoped_ptr<BufferedResourceLoader> loader_; @@ -213,6 +216,8 @@ class CONTENT_EXPORT BufferedDataSource : public media::DataSource { DownloadingCB downloading_cb_; + base::WeakPtrFactory<BufferedDataSource> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(BufferedDataSource); }; diff --git a/chromium/content/renderer/media/buffered_data_source_unittest.cc b/chromium/content/renderer/media/buffered_data_source_unittest.cc index 11af9eb8349..b7808a88d53 100644 --- a/chromium/content/renderer/media/buffered_data_source_unittest.cc +++ b/chromium/content/renderer/media/buffered_data_source_unittest.cc @@ -6,14 +6,14 @@ #include "base/message_loop/message_loop.h" #include "content/renderer/media/buffered_data_source.h" #include "content/renderer/media/test_response_generator.h" +#include "content/test/mock_webframeclient.h" +#include "content/test/mock_weburlloader.h" #include "media/base/media_log.h" #include "media/base/mock_data_source_host.h" #include "media/base/mock_filters.h" #include "media/base/test_helpers.h" #include "third_party/WebKit/public/platform/WebURLResponse.h" #include "third_party/WebKit/public/web/WebView.h" -#include "webkit/mocks/mock_webframeclient.h" -#include "webkit/mocks/mock_weburlloader.h" using ::testing::_; using ::testing::Assign; @@ -22,14 +22,11 @@ using ::testing::InSequence; using ::testing::NiceMock; using ::testing::StrictMock; -using WebKit::WebFrame; -using WebKit::WebString; -using WebKit::WebURLLoader; -using WebKit::WebURLResponse; -using WebKit::WebView; - -using webkit_glue::MockWebFrameClient; -using webkit_glue::MockWebURLLoader; +using blink::WebFrame; +using blink::WebString; +using blink::WebURLLoader; +using blink::WebURLResponse; +using blink::WebView; namespace content { @@ -554,10 +551,10 @@ TEST_F(BufferedDataSourceTest, SetBitrate) { Stop(); } -TEST_F(BufferedDataSourceTest, SetPlaybackRate) { +TEST_F(BufferedDataSourceTest, MediaPlaybackRateChanged) { InitializeWith206Response(); - data_source_->SetPlaybackRate(2.0f); + data_source_->MediaPlaybackRateChanged(2.0f); message_loop_.RunUntilIdle(); EXPECT_EQ(2.0f, data_source_playback_rate()); EXPECT_EQ(2.0f, loader_playback_rate()); diff --git a/chromium/content/renderer/media/buffered_resource_loader.cc b/chromium/content/renderer/media/buffered_resource_loader.cc index a99f7ec77d0..b050febc25d 100644 --- a/chromium/content/renderer/media/buffered_resource_loader.cc +++ b/chromium/content/renderer/media/buffered_resource_loader.cc @@ -6,13 +6,12 @@ #include "base/bits.h" #include "base/callback_helpers.h" -#include "base/format_macros.h" #include "base/metrics/histogram.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" #include "content/renderer/media/cache_util.h" #include "media/base/media_log.h" +#include "net/http/http_byte_range.h" #include "net/http/http_request_headers.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURLError.h" @@ -20,13 +19,13 @@ #include "third_party/WebKit/public/web/WebKit.h" #include "third_party/WebKit/public/web/WebURLLoaderOptions.h" -using WebKit::WebFrame; -using WebKit::WebString; -using WebKit::WebURLError; -using WebKit::WebURLLoader; -using WebKit::WebURLLoaderOptions; -using WebKit::WebURLRequest; -using WebKit::WebURLResponse; +using blink::WebFrame; +using blink::WebString; +using blink::WebURLError; +using blink::WebURLLoader; +using blink::WebURLLoaderOptions; +using blink::WebURLRequest; +using blink::WebURLResponse; namespace content { @@ -165,11 +164,11 @@ void BufferedResourceLoader::Start( if (IsRangeRequest()) { request.setHTTPHeaderField( WebString::fromUTF8(net::HttpRequestHeaders::kRange), - WebString::fromUTF8(GenerateHeaders(first_byte_position_, - last_byte_position_))); + WebString::fromUTF8(net::HttpByteRange::Bounded( + first_byte_position_, last_byte_position_).GetHeaderValue())); } - frame->setReferrerForRequest(request, WebKit::WebURL()); + frame->setReferrerForRequest(request, blink::WebURL()); // Disable compression, compression for audio/video doesn't make sense... request.setHTTPHeaderField( @@ -188,6 +187,8 @@ void BufferedResourceLoader::Start( WebURLLoaderOptions::CrossOriginRequestPolicyAllow; } else { options.exposeAllResponseHeaders = true; + // The author header set is empty, no preflight should go ahead. + options.preflightPolicy = WebURLLoaderOptions::PreventPreflight; options.crossOriginRequestPolicy = WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; if (cors_mode_ == kUseCredentials) @@ -322,7 +323,7 @@ bool BufferedResourceLoader::range_supported() { } ///////////////////////////////////////////////////////////////////////////// -// WebKit::WebURLLoaderClient implementation. +// blink::WebURLLoaderClient implementation. void BufferedResourceLoader::willSendRequest( WebURLLoader* loader, WebURLRequest& newRequest, @@ -332,7 +333,7 @@ void BufferedResourceLoader::willSendRequest( // In this case we shouldn't do anything. if (start_cb_.is_null()) { // Set the url in the request to an invalid value (empty url). - newRequest.setURL(WebKit::WebURL()); + newRequest.setURL(blink::WebURL()); return; } @@ -467,7 +468,7 @@ void BufferedResourceLoader::didReceiveData( } void BufferedResourceLoader::didDownloadData( - WebKit::WebURLLoader* loader, + blink::WebURLLoader* loader, int dataLength, int encoded_data_length) { NOTIMPLEMENTED(); @@ -748,27 +749,6 @@ bool BufferedResourceLoader::VerifyPartialResponse( return true; } -std::string BufferedResourceLoader::GenerateHeaders( - int64 first_byte_position, - int64 last_byte_position) { - // Construct the value for the range header. - std::string header; - if (first_byte_position > kPositionNotSpecified && - last_byte_position > kPositionNotSpecified) { - if (first_byte_position <= last_byte_position) { - header = base::StringPrintf("bytes=%" PRId64 "-%" PRId64, - first_byte_position, - last_byte_position); - } - } else if (first_byte_position > kPositionNotSpecified) { - header = base::StringPrintf("bytes=%" PRId64 "-", - first_byte_position); - } else if (last_byte_position > kPositionNotSpecified) { - NOTIMPLEMENTED() << "Suffix range not implemented"; - } - return header; -} - void BufferedResourceLoader::DoneRead(Status status, int bytes_read) { if (saved_forward_capacity_) { buffer_.set_forward_capacity(saved_forward_capacity_); diff --git a/chromium/content/renderer/media/buffered_resource_loader.h b/chromium/content/renderer/media/buffered_resource_loader.h index 24b5ad8f96b..3331979d2c9 100644 --- a/chromium/content/renderer/media/buffered_resource_loader.h +++ b/chromium/content/renderer/media/buffered_resource_loader.h @@ -36,7 +36,7 @@ const char kHttpsScheme[] = "https"; // pausing resource loading when the in-memory buffer is full and resuming // resource loading when there is available capacity. class CONTENT_EXPORT BufferedResourceLoader - : NON_EXPORTED_BASE(public WebKit::WebURLLoaderClient) { + : NON_EXPORTED_BASE(public blink::WebURLLoaderClient) { public: // kNeverDefer - Aggresively buffer; never defer loading while paused. // kReadThenDefer - Request only enough data to fulfill read requests. @@ -106,7 +106,7 @@ class CONTENT_EXPORT BufferedResourceLoader void Start(const StartCB& start_cb, const LoadingStateChangedCB& loading_cb, const ProgressCB& progress_cb, - WebKit::WebFrame* frame); + blink::WebFrame* frame); // Stops everything associated with this loader, including active URL loads // and pending callbacks. @@ -138,36 +138,36 @@ class CONTENT_EXPORT BufferedResourceLoader // Returns true if the server supports byte range requests. bool range_supported(); - // WebKit::WebURLLoaderClient implementation. + // blink::WebURLLoaderClient implementation. virtual void willSendRequest( - WebKit::WebURLLoader* loader, - WebKit::WebURLRequest& newRequest, - const WebKit::WebURLResponse& redirectResponse); + blink::WebURLLoader* loader, + blink::WebURLRequest& newRequest, + const blink::WebURLResponse& redirectResponse); virtual void didSendData( - WebKit::WebURLLoader* loader, + blink::WebURLLoader* loader, unsigned long long bytesSent, unsigned long long totalBytesToBeSent); virtual void didReceiveResponse( - WebKit::WebURLLoader* loader, - const WebKit::WebURLResponse& response); + blink::WebURLLoader* loader, + const blink::WebURLResponse& response); virtual void didDownloadData( - WebKit::WebURLLoader* loader, + blink::WebURLLoader* loader, int data_length, int encoded_data_length); virtual void didReceiveData( - WebKit::WebURLLoader* loader, + blink::WebURLLoader* loader, const char* data, int data_length, int encoded_data_length); virtual void didReceiveCachedMetadata( - WebKit::WebURLLoader* loader, + blink::WebURLLoader* loader, const char* data, int dataLength); virtual void didFinishLoading( - WebKit::WebURLLoader* loader, + blink::WebURLLoader* loader, double finishTime); virtual void didFail( - WebKit::WebURLLoader* loader, - const WebKit::WebURLError&); + blink::WebURLLoader* loader, + const blink::WebURLError&); // Returns true if the media resource has a single origin, false otherwise. // Only valid to call after Start() has completed. @@ -235,16 +235,7 @@ class CONTENT_EXPORT BufferedResourceLoader void ReadInternal(); // If we have made a range request, verify the response from the server. - bool VerifyPartialResponse(const WebKit::WebURLResponse& response); - - // Returns the value for a range request header using parameters - // |first_byte_position| and |last_byte_position|. Negative numbers other - // than |kPositionNotSpecified| are not allowed for |first_byte_position| and - // |last_byte_position|. |first_byte_position| should always be less than or - // equal to |last_byte_position| if they are both not |kPositionNotSpecified|. - // Empty string is returned on invalid parameters. - std::string GenerateHeaders(int64 first_byte_position, - int64 last_byte_position); + bool VerifyPartialResponse(const blink::WebURLResponse& response); // Done with read. Invokes the read callback and reset parameters for the // read request. @@ -316,7 +307,7 @@ class CONTENT_EXPORT BufferedResourceLoader int last_offset_; // Injected WebURLLoader instance for testing purposes. - scoped_ptr<WebKit::WebURLLoader> test_loader_; + scoped_ptr<blink::WebURLLoader> test_loader_; // Bitrate of the media. Set to 0 if unknown. int bitrate_; diff --git a/chromium/content/renderer/media/buffered_resource_loader_unittest.cc b/chromium/content/renderer/media/buffered_resource_loader_unittest.cc index a0a63cf2aea..656f1e846e7 100644 --- a/chromium/content/renderer/media/buffered_resource_loader_unittest.cc +++ b/chromium/content/renderer/media/buffered_resource_loader_unittest.cc @@ -10,6 +10,8 @@ #include "base/message_loop/message_loop.h" #include "base/strings/stringprintf.h" #include "content/renderer/media/buffered_resource_loader.h" +#include "content/test/mock_webframeclient.h" +#include "content/test/mock_weburlloader.h" #include "media/base/media_log.h" #include "media/base/seekable_buffer.h" #include "net/base/net_errors.h" @@ -21,8 +23,6 @@ #include "third_party/WebKit/public/platform/WebURLResponse.h" #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebView.h" -#include "webkit/mocks/mock_webframeclient.h" -#include "webkit/mocks/mock_weburlloader.h" using ::testing::_; using ::testing::InSequence; @@ -30,13 +30,10 @@ using ::testing::Return; using ::testing::Truly; using ::testing::NiceMock; -using WebKit::WebString; -using WebKit::WebURLError; -using WebKit::WebURLResponse; -using WebKit::WebView; - -using webkit_glue::MockWebFrameClient; -using webkit_glue::MockWebURLLoader; +using blink::WebString; +using blink::WebURLError; +using blink::WebURLResponse; +using blink::WebView; namespace content { @@ -56,7 +53,7 @@ enum NetworkState { }; // Predicate that tests that request disallows compressed data. -static bool CorrectAcceptEncoding(const WebKit::WebURLRequest &request) { +static bool CorrectAcceptEncoding(const blink::WebURLRequest &request) { std::string value = request.httpHeaderField( WebString::fromUTF8(net::HttpRequestHeaders::kAcceptEncoding)).utf8(); return (value.find("identity;q=1") != std::string::npos) && @@ -91,7 +88,7 @@ class BufferedResourceLoaderTest : public testing::Test { // |test_loader_| will be used when Start() is called. url_loader_ = new NiceMock<MockWebURLLoader>(); - loader_->test_loader_ = scoped_ptr<WebKit::WebURLLoader>(url_loader_); + loader_->test_loader_ = scoped_ptr<blink::WebURLLoader>(url_loader_); } void SetLoaderBuffer(int forward_capacity, int backward_capacity) { @@ -190,8 +187,8 @@ class BufferedResourceLoaderTest : public testing::Test { void Redirect(const char* url) { GURL redirectUrl(url); - WebKit::WebURLRequest newRequest(redirectUrl); - WebKit::WebURLResponse redirectResponse(gurl_); + blink::WebURLRequest newRequest(redirectUrl); + blink::WebURLResponse redirectResponse(gurl_); loader_->willSendRequest(url_loader_, newRequest, redirectResponse); diff --git a/chromium/content/renderer/media/cache_util.cc b/chromium/content/renderer/media/cache_util.cc index f7326c12e09..2114ddd5189 100644 --- a/chromium/content/renderer/media/cache_util.cc +++ b/chromium/content/renderer/media/cache_util.cc @@ -18,7 +18,7 @@ using base::Time; using base::TimeDelta; using net::HttpVersion; -using WebKit::WebURLResponse; +using blink::WebURLResponse; namespace content { diff --git a/chromium/content/renderer/media/cache_util.h b/chromium/content/renderer/media/cache_util.h index 061e87a4e73..aca8d8a9081 100644 --- a/chromium/content/renderer/media/cache_util.h +++ b/chromium/content/renderer/media/cache_util.h @@ -10,7 +10,7 @@ #include "base/basictypes.h" #include "content/common/content_export.h" -namespace WebKit { +namespace blink { class WebURLResponse; } @@ -34,7 +34,7 @@ enum UncacheableReason { // Return the logical OR of the reasons "response" cannot be used for a future // request (using the disk cache), or 0 if it might be useful. uint32 CONTENT_EXPORT GetReasonsForUncacheability( - const WebKit::WebURLResponse& response); + const blink::WebURLResponse& response); } // namespace content diff --git a/chromium/content/renderer/media/cache_util_unittest.cc b/chromium/content/renderer/media/cache_util_unittest.cc index 806b201e1ef..2db66b94baa 100644 --- a/chromium/content/renderer/media/cache_util_unittest.cc +++ b/chromium/content/renderer/media/cache_util_unittest.cc @@ -14,8 +14,8 @@ #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURLResponse.h" -using WebKit::WebString; -using WebKit::WebURLResponse; +using blink::WebString; +using blink::WebURLResponse; namespace content { diff --git a/chromium/content/renderer/media/crypto/content_decryption_module_factory.cc b/chromium/content/renderer/media/crypto/content_decryption_module_factory.cc index e53fa17debc..feafca7c4bc 100644 --- a/chromium/content/renderer/media/crypto/content_decryption_module_factory.cc +++ b/chromium/content/renderer/media/crypto/content_decryption_module_factory.cc @@ -12,12 +12,12 @@ #include "content/renderer/media/crypto/ppapi_decryptor.h" #include "content/renderer/pepper/pepper_plugin_instance_impl.h" #include "content/renderer/pepper/pepper_webplugin_impl.h" +#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/web/WebFrame.h" -#include "third_party/WebKit/public/web/WebMediaPlayerClient.h" #elif defined(OS_ANDROID) #include "content/renderer/media/android/proxy_media_keys.h" -#include "content/renderer/media/android/webmediaplayer_proxy_android.h" +#include "content/renderer/media/android/renderer_media_player_manager.h" #endif // defined(ENABLE_PEPPER_CDMS) namespace content { @@ -28,13 +28,13 @@ namespace content { // closeHelperPluginSoon() when the Helper Plugin is no longer needed. static scoped_refptr<PepperPluginInstanceImpl> CreateHelperPlugin( const std::string& plugin_type, - WebKit::WebMediaPlayerClient* web_media_player_client, - WebKit::WebFrame* web_frame) { + blink::WebMediaPlayerClient* web_media_player_client, + blink::WebFrame* web_frame) { DCHECK(web_media_player_client); DCHECK(web_frame); - WebKit::WebPlugin* web_plugin = web_media_player_client->createHelperPlugin( - WebKit::WebString::fromUTF8(plugin_type), web_frame); + blink::WebPlugin* web_plugin = web_media_player_client->createHelperPlugin( + blink::WebString::fromUTF8(plugin_type), web_frame); if (!web_plugin) return NULL; @@ -47,12 +47,14 @@ static scoped_refptr<PepperPluginInstanceImpl> CreateHelperPlugin( static scoped_ptr<media::MediaKeys> CreatePpapiDecryptor( const std::string& key_system, - const media::KeyAddedCB& key_added_cb, - const media::KeyErrorCB& key_error_cb, - const media::KeyMessageCB& key_message_cb, + const media::SessionCreatedCB& session_created_cb, + const media::SessionMessageCB& session_message_cb, + const media::SessionReadyCB& session_ready_cb, + const media::SessionClosedCB& session_closed_cb, + const media::SessionErrorCB& session_error_cb, const base::Closure& destroy_plugin_cb, - WebKit::WebMediaPlayerClient* web_media_player_client, - WebKit::WebFrame* web_frame) { + blink::WebMediaPlayerClient* web_media_player_client, + blink::WebFrame* web_frame) { DCHECK(web_media_player_client); DCHECK(web_frame); @@ -61,16 +63,18 @@ static scoped_ptr<media::MediaKeys> CreatePpapiDecryptor( const scoped_refptr<PepperPluginInstanceImpl>& plugin_instance = CreateHelperPlugin(plugin_type, web_media_player_client, web_frame); if (!plugin_instance.get()) { - DLOG(ERROR) << "ProxyDecryptor: plugin instance creation failed."; + DLOG(ERROR) << "Plugin instance creation failed."; return scoped_ptr<media::MediaKeys>(); } scoped_ptr<PpapiDecryptor> decryptor = PpapiDecryptor::Create(key_system, plugin_instance, - key_added_cb, - key_error_cb, - key_message_cb, + session_created_cb, + session_message_cb, + session_ready_cb, + session_closed_cb, + session_error_cb, destroy_plugin_cb); if (!decryptor) @@ -81,8 +85,8 @@ static scoped_ptr<media::MediaKeys> CreatePpapiDecryptor( } void ContentDecryptionModuleFactory::DestroyHelperPlugin( - WebKit::WebMediaPlayerClient* web_media_player_client, - WebKit::WebFrame* web_frame) { + blink::WebMediaPlayerClient* web_media_player_client, + blink::WebFrame* web_frame) { web_media_player_client->closeHelperPluginSoon(web_frame); } #endif // defined(ENABLE_PEPPER_CDMS) @@ -90,20 +94,26 @@ void ContentDecryptionModuleFactory::DestroyHelperPlugin( scoped_ptr<media::MediaKeys> ContentDecryptionModuleFactory::Create( const std::string& key_system, #if defined(ENABLE_PEPPER_CDMS) - WebKit::WebMediaPlayerClient* web_media_player_client, - WebKit::WebFrame* web_frame, + blink::WebMediaPlayerClient* web_media_player_client, + blink::WebFrame* web_frame, const base::Closure& destroy_plugin_cb, #elif defined(OS_ANDROID) - WebMediaPlayerProxyAndroid* proxy, + RendererMediaPlayerManager* manager, int media_keys_id, const GURL& frame_url, #endif // defined(ENABLE_PEPPER_CDMS) - const media::KeyAddedCB& key_added_cb, - const media::KeyErrorCB& key_error_cb, - const media::KeyMessageCB& key_message_cb) { + const media::SessionCreatedCB& session_created_cb, + const media::SessionMessageCB& session_message_cb, + const media::SessionReadyCB& session_ready_cb, + const media::SessionClosedCB& session_closed_cb, + const media::SessionErrorCB& session_error_cb) { if (CanUseAesDecryptor(key_system)) { return scoped_ptr<media::MediaKeys>( - new media::AesDecryptor(key_added_cb, key_error_cb, key_message_cb)); + new media::AesDecryptor(session_created_cb, + session_message_cb, + session_ready_cb, + session_closed_cb, + session_error_cb)); } #if defined(ENABLE_PEPPER_CDMS) @@ -112,12 +122,24 @@ scoped_ptr<media::MediaKeys> ContentDecryptionModuleFactory::Create( if (!web_media_player_client) return scoped_ptr<media::MediaKeys>(); - return CreatePpapiDecryptor( - key_system, key_added_cb, key_error_cb, key_message_cb, - destroy_plugin_cb, web_media_player_client, web_frame); + return CreatePpapiDecryptor(key_system, + session_created_cb, + session_message_cb, + session_ready_cb, + session_closed_cb, + session_error_cb, + destroy_plugin_cb, + web_media_player_client, + web_frame); #elif defined(OS_ANDROID) scoped_ptr<ProxyMediaKeys> proxy_media_keys( - new ProxyMediaKeys(proxy, media_keys_id)); + new ProxyMediaKeys(manager, + media_keys_id, + session_created_cb, + session_message_cb, + session_ready_cb, + session_closed_cb, + session_error_cb)); proxy_media_keys->InitializeCDM(key_system, frame_url); return proxy_media_keys.PassAs<media::MediaKeys>(); #else diff --git a/chromium/content/renderer/media/crypto/content_decryption_module_factory.h b/chromium/content/renderer/media/crypto/content_decryption_module_factory.h index 01ab731e064..87623ca0785 100644 --- a/chromium/content/renderer/media/crypto/content_decryption_module_factory.h +++ b/chromium/content/renderer/media/crypto/content_decryption_module_factory.h @@ -13,7 +13,7 @@ class GURL; #if defined(ENABLE_PEPPER_CDMS) -namespace WebKit { +namespace blink { class WebFrame; class WebMediaPlayerClient; } @@ -21,7 +21,7 @@ class WebMediaPlayerClient; namespace content { -class WebMediaPlayerProxyAndroid; +class RendererMediaPlayerManager; class ContentDecryptionModuleFactory { public: @@ -29,22 +29,24 @@ class ContentDecryptionModuleFactory { const std::string& key_system, #if defined(ENABLE_PEPPER_CDMS) // TODO(ddorwin): We need different pointers for the WD API. - WebKit::WebMediaPlayerClient* web_media_player_client, - WebKit::WebFrame* web_frame, + blink::WebMediaPlayerClient* web_media_player_client, + blink::WebFrame* web_frame, const base::Closure& destroy_plugin_cb, #elif defined(OS_ANDROID) - WebMediaPlayerProxyAndroid* proxy, + RendererMediaPlayerManager* manager, int media_keys_id, const GURL& frame_url, #endif // defined(ENABLE_PEPPER_CDMS) - const media::KeyAddedCB& key_added_cb, - const media::KeyErrorCB& key_error_cb, - const media::KeyMessageCB& key_message_cb); + const media::SessionCreatedCB& session_created_cb, + const media::SessionMessageCB& session_message_cb, + const media::SessionReadyCB& session_ready_cb, + const media::SessionClosedCB& session_closed_cb, + const media::SessionErrorCB& session_error_cb); #if defined(ENABLE_PEPPER_CDMS) static void DestroyHelperPlugin( - WebKit::WebMediaPlayerClient* web_media_player_client, - WebKit::WebFrame* web_frame); + blink::WebMediaPlayerClient* web_media_player_client, + blink::WebFrame* web_frame); #endif // defined(ENABLE_PEPPER_CDMS) }; diff --git a/chromium/content/renderer/media/crypto/key_systems.cc b/chromium/content/renderer/media/crypto/key_systems.cc index 4ce61227050..41025337a03 100644 --- a/chromium/content/renderer/media/crypto/key_systems.cc +++ b/chromium/content/renderer/media/crypto/key_systems.cc @@ -5,6 +5,7 @@ #include "content/renderer/media/crypto/key_systems.h" #include <map> +#include <string> #include "base/lazy_instance.h" #include "base/logging.h" @@ -12,32 +13,51 @@ #include "content/public/common/content_client.h" #include "content/public/renderer/content_renderer_client.h" #include "content/public/renderer/key_system_info.h" -#include "content/renderer/media/crypto/key_systems_info.h" +#include "content/renderer/media/crypto/key_systems_support_uma.h" #include "net/base/mime_util.h" #include "third_party/WebKit/public/platform/WebCString.h" #include "third_party/WebKit/public/platform/WebString.h" +#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. + namespace content { +const char kClearKeyKeySystem[] = "webkit-org.w3.clearkey"; + +const char kAudioWebM[] = "audio/webm"; +const char kVideoWebM[] = "video/webm"; +const char kVorbis[] = "vorbis"; +const char kVorbisVP8[] = "vorbis,vp8,vp8.0"; + +#if defined(USE_PROPRIETARY_CODECS) +const char kAudioMp4[] = "audio/mp4"; +const char kVideoMp4[] = "video/mp4"; +const char kMp4a[] = "mp4a"; +const char kMp4aAvc1Avc3[] = "mp4a,avc1,avc3"; +#endif // defined(USE_PROPRIETARY_CODECS) + +#if !defined(GOOGLE_TV) +inline std::string KeySystemNameForUMAInternal( + const blink::WebString& key_system) { + if (key_system == kClearKeyKeySystem) + return "ClearKey"; +#if defined(WIDEVINE_CDM_AVAILABLE) + if (key_system == kWidevineKeySystem) + return "Widevine"; +#endif // WIDEVINE_CDM_AVAILABLE + return "Unknown"; +} +#else +// Declares the function, which is defined in another file. +std::string KeySystemNameForUMAInternal(const blink::WebString& key_system); +#endif // !defined(GOOGLE_TV) + // Convert a WebString to ASCII, falling back on an empty string in the case // of a non-ASCII string. -static std::string ToASCIIOrEmpty(const WebKit::WebString& string) { +static std::string ToASCIIOrEmpty(const blink::WebString& string) { return IsStringASCII(string) ? UTF16ToASCII(string) : std::string(); } -static const char kClearKeyKeySystem[] = "webkit-org.w3.clearkey"; - -static const char kAudioWebM[] = "audio/webm"; -static const char kVideoWebM[] = "video/webm"; -static const char kVorbis[] = "vorbis"; -static const char kVorbisVP8[] = "vorbis,vp8,vp8.0"; - -static const char kAudioMp4[] = "audio/mp4"; -static const char kVideoMp4[] = "video/mp4"; -static const char kMp4a[] = "mp4a"; -static const char kAvc1[] = "avc1"; -static const char kMp4aAvc1[] = "mp4a,avc1"; - static void AddClearKey(std::vector<KeySystemInfo>* concrete_key_systems) { KeySystemInfo info(kClearKeyKeySystem); @@ -45,7 +65,7 @@ static void AddClearKey(std::vector<KeySystemInfo>* concrete_key_systems) { info.supported_types.push_back(std::make_pair(kVideoWebM, kVorbisVP8)); #if defined(USE_PROPRIETARY_CODECS) info.supported_types.push_back(std::make_pair(kAudioMp4, kMp4a)); - info.supported_types.push_back(std::make_pair(kVideoMp4, kMp4aAvc1)); + info.supported_types.push_back(std::make_pair(kVideoMp4, kMp4aAvc1Avc3)); #endif // defined(USE_PROPRIETARY_CODECS) info.use_aes_decryptor = true; @@ -116,10 +136,9 @@ class KeySystems { const std::string& codecs_list, KeySystemProperties* properties); - bool IsSupportedKeySystemWithContainerAndCodec( - const std::string& mime_type, - const std::string& codec, - const std::string& key_system); + bool IsSupportedKeySystemWithContainerAndCodec(const std::string& mime_type, + const std::string& codec, + const std::string& key_system); // Map from key system string to capabilities. KeySystemPropertiesMap concrete_key_system_map_; @@ -128,6 +147,8 @@ class KeySystems { // to represent its capabilities. ParentKeySystemMap parent_key_system_map_; + KeySystemsSupportUMA key_systems_support_uma_; + DISALLOW_COPY_AND_ASSIGN(KeySystems); }; @@ -145,6 +166,9 @@ KeySystems::KeySystems() { // Clear Key is always supported. AddClearKey(&key_systems_info); AddConcreteSupportedKeySystems(key_systems_info); +#if defined(WIDEVINE_CDM_AVAILABLE) + key_systems_support_uma_.AddKeySystemToReport(kWidevineKeySystem); +#endif // defined(WIDEVINE_CDM_AVAILABLE) } void KeySystems::AddConcreteSupportedKeySystems( @@ -216,8 +240,6 @@ void KeySystems::AddSupportedType(const std::string& mime_type, net::ParseCodecString(codecs_list, &mime_type_codecs, false); CodecSet codecs(mime_type_codecs.begin(), mime_type_codecs.end()); - // Support the MIME type string alone, without codec(s) specified. - codecs.insert(std::string()); MimeTypeMap& mime_types_map = properties->types; // mime_types_map must not be repeated for a given key system. @@ -234,18 +256,37 @@ bool KeySystems::IsSupportedKeySystemWithContainerAndCodec( const std::string& mime_type, const std::string& codec, const std::string& key_system) { + bool has_type = !mime_type.empty(); + DCHECK(has_type || codec.empty()); + + key_systems_support_uma_.ReportKeySystemQuery(key_system, has_type); + KeySystemPropertiesMap::const_iterator key_system_iter = concrete_key_system_map_.find(key_system); if (key_system_iter == concrete_key_system_map_.end()) return false; + key_systems_support_uma_.ReportKeySystemSupport(key_system, false); + + if (mime_type.empty()) + return true; + const MimeTypeMap& mime_types_map = key_system_iter->second.types; MimeTypeMap::const_iterator mime_iter = mime_types_map.find(mime_type); if (mime_iter == mime_types_map.end()) return false; + if (codec.empty()) { + key_systems_support_uma_.ReportKeySystemSupport(key_system, true); + return true; + } + const CodecSet& codecs = mime_iter->second; - return (codecs.find(codec) != codecs.end()); + if (codecs.find(codec) == codecs.end()) + return false; + + key_systems_support_uma_.ReportKeySystemSupport(key_system, true); + return true; } bool KeySystems::IsSupportedKeySystemWithMediaMimeType( @@ -262,11 +303,6 @@ bool KeySystems::IsSupportedKeySystemWithMediaMimeType( else concrete_key_system = key_system; - // This method is only used by the canPlaytType() path (not the EME methods), - // so we check for suppressed key_systems here. - if(IsCanPlayTypeSuppressed(concrete_key_system)) - return false; - if (codecs.empty()) { return IsSupportedKeySystemWithContainerAndCodec( mime_type, std::string(), concrete_key_system); @@ -274,7 +310,7 @@ bool KeySystems::IsSupportedKeySystemWithMediaMimeType( for (size_t i = 0; i < codecs.size(); ++i) { if (!IsSupportedKeySystemWithContainerAndCodec( - mime_type, codecs[i], concrete_key_system)) { + mime_type, codecs[i], concrete_key_system)) { return false; } } @@ -321,7 +357,7 @@ std::vector<uint8> KeySystems::GetUUID(const std::string& concrete_key_system) { //------------------------------------------------------------------------------ -bool IsConcreteSupportedKeySystem(const WebKit::WebString& key_system) { +bool IsConcreteSupportedKeySystem(const blink::WebString& key_system) { return KeySystems::GetInstance().IsConcreteSupportedKeySystem( ToASCIIOrEmpty(key_system)); } @@ -334,10 +370,14 @@ bool IsSupportedKeySystemWithMediaMimeType( mime_type, codecs, key_system); } -std::string KeySystemNameForUMA(const WebKit::WebString& key_system) { +std::string KeySystemNameForUMA(const blink::WebString& key_system) { return KeySystemNameForUMAInternal(key_system); } +std::string KeySystemNameForUMA(const std::string& key_system) { + return KeySystemNameForUMAInternal(blink::WebString::fromUTF8(key_system)); +} + bool CanUseAesDecryptor(const std::string& concrete_key_system) { return KeySystems::GetInstance().UseAesDecryptor(concrete_key_system); } diff --git a/chromium/content/renderer/media/crypto/key_systems.h b/chromium/content/renderer/media/crypto/key_systems.h index 47dc06a93db..2f4cb101b09 100644 --- a/chromium/content/renderer/media/crypto/key_systems.h +++ b/chromium/content/renderer/media/crypto/key_systems.h @@ -11,7 +11,7 @@ #include "base/memory/scoped_ptr.h" #include "content/common/content_export.h" -namespace WebKit { +namespace blink { class WebString; } @@ -24,7 +24,7 @@ namespace content { // |key_system| supports a specific type of media or to check parent key // systems. CONTENT_EXPORT bool IsConcreteSupportedKeySystem( - const WebKit::WebString& key_system); + const blink::WebString& key_system); // Returns whether |key_sytem| supports the specified media type and codec(s). CONTENT_EXPORT bool IsSupportedKeySystemWithMediaMimeType( @@ -34,7 +34,8 @@ CONTENT_EXPORT bool IsSupportedKeySystemWithMediaMimeType( // Returns a name for |key_system| suitable to UMA logging. CONTENT_EXPORT std::string KeySystemNameForUMA( - const WebKit::WebString& key_system); + const blink::WebString& key_system); +CONTENT_EXPORT std::string KeySystemNameForUMA(const std::string& key_system); // Returns whether AesDecryptor can be used for the given |concrete_key_system|. CONTENT_EXPORT bool CanUseAesDecryptor(const std::string& concrete_key_system); diff --git a/chromium/content/renderer/media/crypto/key_systems_info.cc b/chromium/content/renderer/media/crypto/key_systems_info.cc deleted file mode 100644 index 22bc7181b24..00000000000 --- a/chromium/content/renderer/media/crypto/key_systems_info.cc +++ /dev/null @@ -1,43 +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/renderer/media/crypto/key_systems_info.h" - -#include "third_party/WebKit/public/platform/WebString.h" - -#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. - -// The following must be after widevine_cdm_version.h. - -#if defined(DISABLE_WIDEVINE_CDM_CANPLAYTYPE) -#include "base/command_line.h" -#include "media/base/media_switches.h" -#endif - -namespace content { - -static const char kClearKeyKeySystem[] = "webkit-org.w3.clearkey"; - -bool IsCanPlayTypeSuppressed(const std::string& key_system) { -#if defined(DISABLE_WIDEVINE_CDM_CANPLAYTYPE) - // See http://crbug.com/237627. - if (key_system == kWidevineKeySystem && - !CommandLine::ForCurrentProcess()->HasSwitch( - switches::kOverrideEncryptedMediaCanPlayType)) - return true; -#endif - return false; -} - -std::string KeySystemNameForUMAInternal(const WebKit::WebString& key_system) { - if (key_system == kClearKeyKeySystem) - return "ClearKey"; -#if defined(WIDEVINE_CDM_AVAILABLE) - if (key_system == kWidevineKeySystem) - return "Widevine"; -#endif // WIDEVINE_CDM_AVAILABLE - return "Unknown"; -} - -} // namespace content diff --git a/chromium/content/renderer/media/crypto/key_systems_info.h b/chromium/content/renderer/media/crypto/key_systems_info.h deleted file mode 100644 index e2fe128872c..00000000000 --- a/chromium/content/renderer/media/crypto/key_systems_info.h +++ /dev/null @@ -1,27 +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_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_INFO_H_ -#define CONTENT_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_INFO_H_ - -#include <string> - -namespace WebKit { -class WebString; -} - -namespace content { - -// Returns true if canPlayType should return an empty string for |key_system|. -bool IsCanPlayTypeSuppressed(const std::string& key_system); - -// Returns the name that UMA will use for the given |key_system|. -// This function can be called frequently. Hence this function should be -// implemented not to impact performance and does not rely on the main -// key system map. -std::string KeySystemNameForUMAInternal(const WebKit::WebString& key_system); - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_INFO_H_ diff --git a/chromium/content/renderer/media/crypto/key_systems_support_uma.cc b/chromium/content/renderer/media/crypto/key_systems_support_uma.cc new file mode 100644 index 00000000000..f1d77bd677b --- /dev/null +++ b/chromium/content/renderer/media/crypto/key_systems_support_uma.cc @@ -0,0 +1,125 @@ +// 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/renderer/media/crypto/key_systems_support_uma.h" + +#include <string> + +#include "content/public/renderer/render_thread.h" +#include "content/renderer/media/crypto/key_systems.h" + +namespace content { + +namespace { + +const char kKeySystemSupportActionPrefix[] = "KeySystemSupport."; + +// Reports an event only once. +class OneTimeReporter { + public: + OneTimeReporter(const std::string& key_system, + bool has_type, + const std::string& event); + ~OneTimeReporter(); + + void Report(); + + private: + bool is_reported_; + std::string action_; +}; + +OneTimeReporter::OneTimeReporter(const std::string& key_system, + bool has_type, + const std::string& event) + : is_reported_(false) { + action_ = kKeySystemSupportActionPrefix + KeySystemNameForUMA(key_system); + if (has_type) + action_ += "WithType"; + action_ += '.' + event; +} + +OneTimeReporter::~OneTimeReporter() {} + +void OneTimeReporter::Report() { + if (is_reported_) + return; + RenderThread::Get()->RecordComputedAction(action_); + is_reported_ = true; +} + +} // namespace + +class KeySystemsSupportUMA::Reporter { + public: + explicit Reporter(const std::string& key_system); + ~Reporter(); + + void Report(bool has_type, bool is_supported); + + private: + const std::string key_system_; + + OneTimeReporter call_reporter_; + OneTimeReporter call_with_type_reporter_; + OneTimeReporter support_reporter_; + OneTimeReporter support_with_type_reporter_; +}; + +KeySystemsSupportUMA::Reporter::Reporter(const std::string& key_system) + : key_system_(key_system), + call_reporter_(key_system, false, "Queried"), + call_with_type_reporter_(key_system, true, "Queried"), + support_reporter_(key_system, false, "Supported"), + support_with_type_reporter_(key_system, true, "Supported") {} + +KeySystemsSupportUMA::Reporter::~Reporter() {} + +void KeySystemsSupportUMA::Reporter::Report(bool has_type, bool is_supported) { + call_reporter_.Report(); + if (has_type) + call_with_type_reporter_.Report(); + + if (!is_supported) + return; + + support_reporter_.Report(); + if (has_type) + support_with_type_reporter_.Report(); +} + +KeySystemsSupportUMA::KeySystemsSupportUMA() {} + +KeySystemsSupportUMA::~KeySystemsSupportUMA() {} + +void KeySystemsSupportUMA::AddKeySystemToReport(const std::string& key_system) { + DCHECK(!GetReporter(key_system)); + reporters_.set(key_system, scoped_ptr<Reporter>(new Reporter(key_system))); +} + +void KeySystemsSupportUMA::ReportKeySystemQuery(const std::string& key_system, + bool has_type) { + Reporter* reporter = GetReporter(key_system); + if (!reporter) + return; + reporter->Report(has_type, false); +} + +void KeySystemsSupportUMA::ReportKeySystemSupport(const std::string& key_system, + bool has_type) { + Reporter* reporter = GetReporter(key_system); + if (!reporter) + return; + reporter->Report(has_type, true); +} + +KeySystemsSupportUMA::Reporter* KeySystemsSupportUMA::GetReporter( + const std::string& key_system) { + Reporters::iterator reporter = reporters_.find(key_system); + if (reporter == reporters_.end()) + return NULL; + return reporter->second; +} + +} // namespace content diff --git a/chromium/content/renderer/media/crypto/key_systems_support_uma.h b/chromium/content/renderer/media/crypto/key_systems_support_uma.h new file mode 100644 index 00000000000..95e1b02bcd4 --- /dev/null +++ b/chromium/content/renderer/media/crypto/key_systems_support_uma.h @@ -0,0 +1,57 @@ +// 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_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_SUPPORT_UMA_H_ +#define CONTENT_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_SUPPORT_UMA_H_ + +#include <string> + +#include "base/containers/scoped_ptr_hash_map.h" + +namespace content { + +// Key system support UMA statistics for queried key systems. +// 1. The key system is queried (with or without a MIME type). +// 2. The key system is queried with a MIME type. +// 3. The queried key system is supported (with or without a MIME type). This is +// reported when the key system is supported when queried, regardless of +// whether a MIME type is specified. +// 4. The queried key system is supported with a MIME type. This is reported +// when the key system is supported when queried without a MIME type +// specified. +// Note: All 4 stats are only reported once per renderer process per key system. +class KeySystemsSupportUMA { + public: + KeySystemsSupportUMA(); + ~KeySystemsSupportUMA(); + + // Adds a |key_system| for which query/support statistics are reported. + // If you use this function to add key system to report, make sure to update + // AddKeySystemSupportActions() in tools/metrics/actions/extract_actions.py. + void AddKeySystemToReport(const std::string& key_system); + + // Reports that the |key_system| is queried. When |has_type|, also reports + // that the |key_system| with a MIME type is queried. + void ReportKeySystemQuery(const std::string& key_system, bool has_type); + + // Reports that the queried |key_system| is supported. When |has_type| (a + // a MIME type is specified in the query), also reports that the queried + // |key_system| is supported with that MIME type. + void ReportKeySystemSupport(const std::string& key_system, bool has_type); + + private: + class Reporter; + + // Returns the Reporter for |key_system|. Returns NULL if |key_system| was not + // added for UMA reporting. + Reporter* GetReporter(const std::string& key_system); + + // Key system <-> Reporter map. + typedef base::ScopedPtrHashMap<std::string, Reporter> Reporters; + Reporters reporters_; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_CRYPTO_KEY_SYSTEMS_SUPPORT_UMA_H_ diff --git a/chromium/content/renderer/media/crypto/key_systems_unittest.cc b/chromium/content/renderer/media/crypto/key_systems_unittest.cc index 624b811519e..89fa51ab19a 100644 --- a/chromium/content/renderer/media/crypto/key_systems_unittest.cc +++ b/chromium/content/renderer/media/crypto/key_systems_unittest.cc @@ -33,7 +33,7 @@ #endif // defined(NDEBUG) #endif // defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID) -using WebKit::WebString; +using blink::WebString; // These are the (fake) key systems that are registered for these tests. // kUsesAes uses the AesDecryptor like Clear Key. @@ -355,8 +355,7 @@ TEST_F(KeySystemsTest, IsSupportedKeySystem_InvalidVariants) { } TEST_F(KeySystemsTest, IsSupportedKeySystemWithMediaMimeType_NoType) { - // These two should be true. See http://crbug.com/164303. - EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( + EXPECT_TRUE(IsSupportedKeySystemWithMediaMimeType( std::string(), no_codecs(), kUsesAes)); EXPECT_FALSE(IsSupportedKeySystemWithMediaMimeType( std::string(), no_codecs(), kUsesAesParent)); diff --git a/chromium/content/renderer/media/crypto/ppapi_decryptor.cc b/chromium/content/renderer/media/crypto/ppapi_decryptor.cc index 80f8149e315..aff94a240e5 100644 --- a/chromium/content/renderer/media/crypto/ppapi_decryptor.cc +++ b/chromium/content/renderer/media/crypto/ppapi_decryptor.cc @@ -25,9 +25,11 @@ namespace content { scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create( const std::string& key_system, const scoped_refptr<PepperPluginInstanceImpl>& plugin_instance, - const media::KeyAddedCB& key_added_cb, - const media::KeyErrorCB& key_error_cb, - const media::KeyMessageCB& key_message_cb, + const media::SessionCreatedCB& session_created_cb, + const media::SessionMessageCB& session_message_cb, + const media::SessionReadyCB& session_ready_cb, + const media::SessionClosedCB& session_closed_cb, + const media::SessionErrorCB& session_error_cb, const base::Closure& destroy_plugin_cb) { ContentDecryptorDelegate* plugin_cdm_delegate = plugin_instance->GetContentDecryptorDelegate(); @@ -36,41 +38,53 @@ scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create( return scoped_ptr<PpapiDecryptor>(); } - // TODO(jrummell): How do we get the can_challenge_platform value from - // the browser? - const bool can_challenge_platform = false; - plugin_cdm_delegate->Initialize(key_system, can_challenge_platform); + plugin_cdm_delegate->Initialize(key_system); return scoped_ptr<PpapiDecryptor>(new PpapiDecryptor(plugin_instance, plugin_cdm_delegate, - key_added_cb, - key_error_cb, - key_message_cb, + session_created_cb, + session_message_cb, + session_ready_cb, + session_closed_cb, + session_error_cb, destroy_plugin_cb)); } PpapiDecryptor::PpapiDecryptor( const scoped_refptr<PepperPluginInstanceImpl>& plugin_instance, ContentDecryptorDelegate* plugin_cdm_delegate, - const media::KeyAddedCB& key_added_cb, - const media::KeyErrorCB& key_error_cb, - const media::KeyMessageCB& key_message_cb, + const media::SessionCreatedCB& session_created_cb, + const media::SessionMessageCB& session_message_cb, + const media::SessionReadyCB& session_ready_cb, + const media::SessionClosedCB& session_closed_cb, + const media::SessionErrorCB& session_error_cb, const base::Closure& destroy_plugin_cb) : plugin_instance_(plugin_instance), plugin_cdm_delegate_(plugin_cdm_delegate), - key_added_cb_(key_added_cb), - key_error_cb_(key_error_cb), - key_message_cb_(key_message_cb), + session_created_cb_(session_created_cb), + session_message_cb_(session_message_cb), + session_ready_cb_(session_ready_cb), + session_closed_cb_(session_closed_cb), + session_error_cb_(session_error_cb), destroy_plugin_cb_(destroy_plugin_cb), render_loop_proxy_(base::MessageLoopProxy::current()), - weak_ptr_factory_(this), - weak_this_(weak_ptr_factory_.GetWeakPtr()) { + weak_ptr_factory_(this) { DCHECK(plugin_instance_.get()); - - plugin_cdm_delegate_->SetKeyEventCallbacks( - base::Bind(&PpapiDecryptor::KeyAdded, weak_this_), - base::Bind(&PpapiDecryptor::KeyError, weak_this_), - base::Bind(&PpapiDecryptor::KeyMessage, weak_this_)); + DCHECK(!session_created_cb_.is_null()); + DCHECK(!session_message_cb_.is_null()); + DCHECK(!session_ready_cb_.is_null()); + DCHECK(!session_closed_cb_.is_null()); + DCHECK(!session_error_cb_.is_null()); + DCHECK(!destroy_plugin_cb_.is_null()); + + weak_this_ = weak_ptr_factory_.GetWeakPtr(); + + plugin_cdm_delegate_->SetSessionEventCallbacks( + base::Bind(&PpapiDecryptor::OnSessionCreated, weak_this_), + base::Bind(&PpapiDecryptor::OnSessionMessage, weak_this_), + base::Bind(&PpapiDecryptor::OnSessionReady, weak_this_), + base::Bind(&PpapiDecryptor::OnSessionClosed, weak_this_), + base::Bind(&PpapiDecryptor::OnSessionError, weak_this_)); } PpapiDecryptor::~PpapiDecryptor() { @@ -79,34 +93,32 @@ PpapiDecryptor::~PpapiDecryptor() { destroy_plugin_cb_.Run(); } -bool PpapiDecryptor::GenerateKeyRequest(const std::string& type, - const uint8* init_data, - int init_data_length) { - DVLOG(2) << "GenerateKeyRequest()"; +bool PpapiDecryptor::CreateSession(uint32 session_id, + const std::string& type, + const uint8* init_data, + int init_data_length) { + DVLOG(2) << __FUNCTION__; DCHECK(render_loop_proxy_->BelongsToCurrentThread()); DCHECK(plugin_cdm_delegate_); - if (!plugin_cdm_delegate_->GenerateKeyRequest( - type, init_data, init_data_length)) { - ReportFailureToCallPlugin(std::string()); + if (!plugin_cdm_delegate_->CreateSession( + session_id, type, init_data, init_data_length)) { + ReportFailureToCallPlugin(session_id); return false; } return true; } -void PpapiDecryptor::AddKey(const uint8* key, - int key_length, - const uint8* init_data, - int init_data_length, - const std::string& session_id) { - DVLOG(2) << "AddKey()"; +void PpapiDecryptor::UpdateSession(uint32 session_id, + const uint8* response, + int response_length) { + DVLOG(2) << __FUNCTION__; DCHECK(render_loop_proxy_->BelongsToCurrentThread()); - if (!plugin_cdm_delegate_->AddKey( - session_id, key, key_length, init_data, init_data_length)) { + if (!plugin_cdm_delegate_->UpdateSession( + session_id, response, response_length)) ReportFailureToCallPlugin(session_id); - } if (!new_audio_key_cb_.is_null()) new_audio_key_cb_.Run(); @@ -115,11 +127,11 @@ void PpapiDecryptor::AddKey(const uint8* key, new_video_key_cb_.Run(); } -void PpapiDecryptor::CancelKeyRequest(const std::string& session_id) { - DVLOG(2) << "CancelKeyRequest()"; +void PpapiDecryptor::ReleaseSession(uint32 session_id) { + DVLOG(2) << __FUNCTION__; DCHECK(render_loop_proxy_->BelongsToCurrentThread()); - if (!plugin_cdm_delegate_->CancelKeyRequest(session_id)) + if (!plugin_cdm_delegate_->ReleaseSession(session_id)) ReportFailureToCallPlugin(session_id); } @@ -140,6 +152,14 @@ media::Decryptor* PpapiDecryptor::GetDecryptor() { void PpapiDecryptor::RegisterNewKeyCB(StreamType stream_type, const NewKeyCB& new_key_cb) { + if (!render_loop_proxy_->BelongsToCurrentThread()) { + render_loop_proxy_->PostTask(FROM_HERE, base::Bind( + &PpapiDecryptor::RegisterNewKeyCB, weak_this_, stream_type, + new_key_cb)); + return; + } + + DVLOG(3) << __FUNCTION__ << " - stream_type: " << stream_type; switch (stream_type) { case kAudio: new_audio_key_cb_ = new_key_cb; @@ -163,13 +183,19 @@ void PpapiDecryptor::Decrypt( return; } - DVLOG(3) << "Decrypt() - stream_type: " << stream_type; + DVLOG(3) << __FUNCTION__ << " - stream_type: " << stream_type; if (!plugin_cdm_delegate_->Decrypt(stream_type, encrypted, decrypt_cb)) decrypt_cb.Run(kError, NULL); } void PpapiDecryptor::CancelDecrypt(StreamType stream_type) { - DVLOG(1) << "CancelDecrypt() - stream_type: " << stream_type; + if (!render_loop_proxy_->BelongsToCurrentThread()) { + render_loop_proxy_->PostTask(FROM_HERE, base::Bind( + &PpapiDecryptor::CancelDecrypt, weak_this_, stream_type)); + return; + } + + DVLOG(1) << __FUNCTION__ << " - stream_type: " << stream_type; plugin_cdm_delegate_->CancelDecrypt(stream_type); } @@ -182,7 +208,7 @@ void PpapiDecryptor::InitializeAudioDecoder( return; } - DVLOG(2) << "InitializeAudioDecoder()"; + DVLOG(2) << __FUNCTION__; DCHECK(config.is_encrypted()); DCHECK(config.IsValidConfig()); @@ -203,7 +229,7 @@ void PpapiDecryptor::InitializeVideoDecoder( return; } - DVLOG(2) << "InitializeVideoDecoder()"; + DVLOG(2) << __FUNCTION__; DCHECK(config.is_encrypted()); DCHECK(config.IsValidConfig()); @@ -225,7 +251,7 @@ void PpapiDecryptor::DecryptAndDecodeAudio( return; } - DVLOG(3) << "DecryptAndDecodeAudio()"; + DVLOG(3) << __FUNCTION__; if (!plugin_cdm_delegate_->DecryptAndDecodeAudio(encrypted, audio_decode_cb)) audio_decode_cb.Run(kError, AudioBuffers()); } @@ -240,7 +266,7 @@ void PpapiDecryptor::DecryptAndDecodeVideo( return; } - DVLOG(3) << "DecryptAndDecodeVideo()"; + DVLOG(3) << __FUNCTION__; if (!plugin_cdm_delegate_->DecryptAndDecodeVideo(encrypted, video_decode_cb)) video_decode_cb.Run(kError, NULL); } @@ -252,7 +278,7 @@ void PpapiDecryptor::ResetDecoder(StreamType stream_type) { return; } - DVLOG(2) << "ResetDecoder() - stream_type: " << stream_type; + DVLOG(2) << __FUNCTION__ << " - stream_type: " << stream_type; plugin_cdm_delegate_->ResetDecoder(stream_type); } @@ -263,17 +289,19 @@ void PpapiDecryptor::DeinitializeDecoder(StreamType stream_type) { return; } - DVLOG(2) << "DeinitializeDecoder() - stream_type: " << stream_type; + DVLOG(2) << __FUNCTION__ << " - stream_type: " << stream_type; plugin_cdm_delegate_->DeinitializeDecoder(stream_type); } -void PpapiDecryptor::ReportFailureToCallPlugin(const std::string& session_id) { +void PpapiDecryptor::ReportFailureToCallPlugin(uint32 session_id) { + DCHECK(render_loop_proxy_->BelongsToCurrentThread()); DVLOG(1) << "Failed to call plugin."; - key_error_cb_.Run(session_id, kUnknownError, 0); + session_error_cb_.Run(session_id, kUnknownError, 0); } void PpapiDecryptor::OnDecoderInitialized(StreamType stream_type, bool success) { + DCHECK(render_loop_proxy_->BelongsToCurrentThread()); switch (stream_type) { case kAudio: DCHECK(!audio_decoder_init_cb_.is_null()); @@ -288,23 +316,34 @@ void PpapiDecryptor::OnDecoderInitialized(StreamType stream_type, } } -void PpapiDecryptor::KeyAdded(const std::string& session_id) { +void PpapiDecryptor::OnSessionCreated(uint32 session_id, + const std::string& web_session_id) { + DCHECK(render_loop_proxy_->BelongsToCurrentThread()); + session_created_cb_.Run(session_id, web_session_id); +} + +void PpapiDecryptor::OnSessionMessage(uint32 session_id, + const std::vector<uint8>& message, + const std::string& destination_url) { + DCHECK(render_loop_proxy_->BelongsToCurrentThread()); + session_message_cb_.Run(session_id, message, destination_url); +} + +void PpapiDecryptor::OnSessionReady(uint32 session_id) { DCHECK(render_loop_proxy_->BelongsToCurrentThread()); - key_added_cb_.Run(session_id); + session_ready_cb_.Run(session_id); } -void PpapiDecryptor::KeyError(const std::string& session_id, - media::MediaKeys::KeyError error_code, - int system_code) { +void PpapiDecryptor::OnSessionClosed(uint32 session_id) { DCHECK(render_loop_proxy_->BelongsToCurrentThread()); - key_error_cb_.Run(session_id, error_code, system_code); + session_closed_cb_.Run(session_id); } -void PpapiDecryptor::KeyMessage(const std::string& session_id, - const std::vector<uint8>& message, - const std::string& default_url) { +void PpapiDecryptor::OnSessionError(uint32 session_id, + media::MediaKeys::KeyError error_code, + int system_code) { DCHECK(render_loop_proxy_->BelongsToCurrentThread()); - key_message_cb_.Run(session_id, message, default_url); + session_error_cb_.Run(session_id, error_code, system_code); } } // namespace content diff --git a/chromium/content/renderer/media/crypto/ppapi_decryptor.h b/chromium/content/renderer/media/crypto/ppapi_decryptor.h index 327ecc6bc47..95c5f74a4c3 100644 --- a/chromium/content/renderer/media/crypto/ppapi_decryptor.h +++ b/chromium/content/renderer/media/crypto/ppapi_decryptor.h @@ -23,8 +23,8 @@ namespace content { class ContentDecryptorDelegate; class PepperPluginInstanceImpl; -// PpapiDecryptor implements media::Decryptor and forwards all calls to the -// PluginInstance. +// PpapiDecryptor implements media::MediaKeys and media::Decryptor and forwards +// all calls to the PluginInstance. // This class should always be created & destroyed on the main renderer thread. class PpapiDecryptor : public media::MediaKeys, public media::Decryptor { public: @@ -32,21 +32,24 @@ class PpapiDecryptor : public media::MediaKeys, public media::Decryptor { // TODO(ddorwin): Remove after updating the delegate. const std::string& key_system, const scoped_refptr<PepperPluginInstanceImpl>& plugin_instance, - const media::KeyAddedCB& key_added_cb, - const media::KeyErrorCB& key_error_cb, - const media::KeyMessageCB& key_message_cb, + const media::SessionCreatedCB& session_created_cb, + const media::SessionMessageCB& session_message_cb, + const media::SessionReadyCB& session_ready_cb, + const media::SessionClosedCB& session_closed_cb, + const media::SessionErrorCB& session_error_cb, const base::Closure& destroy_plugin_cb); virtual ~PpapiDecryptor(); // media::MediaKeys implementation. - virtual bool GenerateKeyRequest(const std::string& type, - const uint8* init_data, - int init_data_length) OVERRIDE; - virtual void AddKey(const uint8* key, int key_length, - const uint8* init_data, int init_data_length, - const std::string& session_id) OVERRIDE; - virtual void CancelKeyRequest(const std::string& session_id) OVERRIDE; + virtual bool CreateSession(uint32 session_id, + const std::string& type, + const uint8* init_data, + int init_data_length) OVERRIDE; + virtual void UpdateSession(uint32 session_id, + const uint8* response, + int response_length) OVERRIDE; + virtual void ReleaseSession(uint32 session_id) OVERRIDE; virtual Decryptor* GetDecryptor() OVERRIDE; // media::Decryptor implementation. @@ -70,26 +73,31 @@ class PpapiDecryptor : public media::MediaKeys, public media::Decryptor { virtual void DeinitializeDecoder(StreamType stream_type) OVERRIDE; private: - PpapiDecryptor( - const scoped_refptr<PepperPluginInstanceImpl>& plugin_instance, - ContentDecryptorDelegate* plugin_cdm_delegate, - const media::KeyAddedCB& key_added_cb, - const media::KeyErrorCB& key_error_cb, - const media::KeyMessageCB& key_message_cb, - const base::Closure& destroy_plugin_cb); + PpapiDecryptor(const scoped_refptr<PepperPluginInstanceImpl>& plugin_instance, + ContentDecryptorDelegate* plugin_cdm_delegate, + const media::SessionCreatedCB& session_created_cb, + const media::SessionMessageCB& session_message_cb, + const media::SessionReadyCB& session_ready_cb, + const media::SessionClosedCB& session_closed_cb, + const media::SessionErrorCB& session_error_cb, + const base::Closure& destroy_plugin_cb); - void ReportFailureToCallPlugin(const std::string& session_id); + void ReportFailureToCallPlugin(uint32 session_id); void OnDecoderInitialized(StreamType stream_type, bool success); - // Callbacks for |plugin_cdm_delegate_| to fire key events. - void KeyAdded(const std::string& session_id); - void KeyError(const std::string& session_id, - media::MediaKeys::KeyError error_code, - int system_code); - void KeyMessage(const std::string& session_id, - const std::vector<uint8>& message, - const std::string& default_url); + // Callbacks for |plugin_cdm_delegate_| to fire session events. + void OnSessionCreated(uint32 session_id, const std::string& web_session_id); + void OnSessionMessage(uint32 session_id, + const std::vector<uint8>& message, + const std::string& destination_url); + void OnSessionReady(uint32 session_id); + void OnSessionClosed(uint32 session_id); + void OnSessionError(uint32 session_id, + media::MediaKeys::KeyError error_code, + int system_code); + + base::WeakPtr<PpapiDecryptor> weak_this_; // Hold a reference of the plugin instance to make sure the plugin outlives // the |plugin_cdm_delegate_|. This is needed because |plugin_cdm_delegate_| @@ -98,10 +106,12 @@ class PpapiDecryptor : public media::MediaKeys, public media::Decryptor { ContentDecryptorDelegate* plugin_cdm_delegate_; - // Callbacks for firing key events. - media::KeyAddedCB key_added_cb_; - media::KeyErrorCB key_error_cb_; - media::KeyMessageCB key_message_cb_; + // Callbacks for firing session events. + media::SessionCreatedCB session_created_cb_; + media::SessionMessageCB session_message_cb_; + media::SessionReadyCB session_ready_cb_; + media::SessionClosedCB session_closed_cb_; + media::SessionErrorCB session_error_cb_; // Called to destroy the helper plugin when this class no longer needs it. base::Closure destroy_plugin_cb_; @@ -114,7 +124,6 @@ class PpapiDecryptor : public media::MediaKeys, public media::Decryptor { NewKeyCB new_video_key_cb_; base::WeakPtrFactory<PpapiDecryptor> weak_ptr_factory_; - base::WeakPtr<PpapiDecryptor> weak_this_; DISALLOW_COPY_AND_ASSIGN(PpapiDecryptor); }; diff --git a/chromium/content/renderer/media/crypto/proxy_decryptor.cc b/chromium/content/renderer/media/crypto/proxy_decryptor.cc index c50080f1c98..0016d19a7e8 100644 --- a/chromium/content/renderer/media/crypto/proxy_decryptor.cc +++ b/chromium/content/renderer/media/crypto/proxy_decryptor.cc @@ -7,10 +7,24 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/logging.h" +#include "base/strings/string_util.h" #include "content/renderer/media/crypto/content_decryption_module_factory.h" +#if defined(OS_ANDROID) +#include "content/renderer/media/android/renderer_media_player_manager.h" +#endif // defined(OS_ANDROID) +#include "media/cdm/json_web_key.h" +#include "media/cdm/key_system_names.h" namespace content { +// Since these reference IDs may conflict with the ones generated in +// WebContentDecryptionModuleSessionImpl for the short time both paths are +// active, start with 100000 and generate the IDs from there. +// TODO(jrummell): Only allow one path http://crbug.com/306680. +uint32 ProxyDecryptor::next_session_id_ = 100000; + +const uint32 kInvalidSessionId = 0; + #if defined(ENABLE_PEPPER_CDMS) void ProxyDecryptor::DestroyHelperPlugin() { ContentDecryptionModuleFactory::DestroyHelperPlugin( @@ -20,26 +34,30 @@ void ProxyDecryptor::DestroyHelperPlugin() { ProxyDecryptor::ProxyDecryptor( #if defined(ENABLE_PEPPER_CDMS) - WebKit::WebMediaPlayerClient* web_media_player_client, - WebKit::WebFrame* web_frame, + blink::WebMediaPlayerClient* web_media_player_client, + blink::WebFrame* web_frame, #elif defined(OS_ANDROID) - WebMediaPlayerProxyAndroid* proxy, + RendererMediaPlayerManager* manager, int media_keys_id, #endif // defined(ENABLE_PEPPER_CDMS) - const media::KeyAddedCB& key_added_cb, - const media::KeyErrorCB& key_error_cb, - const media::KeyMessageCB& key_message_cb) + const KeyAddedCB& key_added_cb, + const KeyErrorCB& key_error_cb, + const KeyMessageCB& key_message_cb) : weak_ptr_factory_(this), #if defined(ENABLE_PEPPER_CDMS) web_media_player_client_(web_media_player_client), web_frame_(web_frame), #elif defined(OS_ANDROID) - proxy_(proxy), + manager_(manager), media_keys_id_(media_keys_id), #endif // defined(ENABLE_PEPPER_CDMS) key_added_cb_(key_added_cb), key_error_cb_(key_error_cb), - key_message_cb_(key_message_cb) { + key_message_cb_(key_message_cb), + is_clear_key_(false) { + DCHECK(!key_added_cb_.is_null()); + DCHECK(!key_error_cb_.is_null()); + DCHECK(!key_message_cb_.is_null()); } ProxyDecryptor::~ProxyDecryptor() { @@ -83,21 +101,28 @@ bool ProxyDecryptor::InitializeCDM(const std::string& key_system, DCHECK(!media_keys_); media_keys_ = CreateMediaKeys(key_system, frame_url); + if (!media_keys_) + return false; - return media_keys_ != NULL; + if (!decryptor_ready_cb_.is_null()) + base::ResetAndReturn(&decryptor_ready_cb_).Run(media_keys_->GetDecryptor()); + + is_clear_key_ = + media::IsClearKey(key_system) || media::IsExternalClearKey(key_system); + return true; } bool ProxyDecryptor::GenerateKeyRequest(const std::string& type, const uint8* init_data, int init_data_length) { - if (!media_keys_->GenerateKeyRequest(type, init_data, init_data_length)) { + // Use a unique reference id for this request. + uint32 session_id = next_session_id_++; + if (!media_keys_->CreateSession( + session_id, type, init_data, init_data_length)) { media_keys_.reset(); return false; } - if (!decryptor_ready_cb_.is_null()) - base::ResetAndReturn(&decryptor_ready_cb_).Run(media_keys_->GetDecryptor()); - return true; } @@ -105,18 +130,58 @@ void ProxyDecryptor::AddKey(const uint8* key, int key_length, const uint8* init_data, int init_data_length, - const std::string& session_id) { + const std::string& web_session_id) { DVLOG(1) << "AddKey()"; // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called. - media_keys_->AddKey(key, key_length, init_data, init_data_length, session_id); + uint32 session_id = LookupSessionId(web_session_id); + if (session_id == kInvalidSessionId) { + // Session hasn't been referenced before, so it is an error. + // Note that the specification says "If sessionId is not null and is + // unrecognized, throw an INVALID_ACCESS_ERR." However, for backwards + // compatibility the error is not thrown, but rather reported as a + // KeyError. + key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0); + return; + } + + // EME WD spec only supports a single array passed to the CDM. For + // Clear Key using v0.1b, both arrays are used (|init_data| is key_id). + // Since the EME WD spec supports the key as a JSON Web Key, + // convert the 2 arrays to a JWK and pass it as the single array. + if (is_clear_key_) { + // Decryptor doesn't support empty key ID (see http://crbug.com/123265). + // So ensure a non-empty value is passed. + if (!init_data) { + static const uint8 kDummyInitData[1] = {0}; + init_data = kDummyInitData; + init_data_length = arraysize(kDummyInitData); + } + + std::string jwk = + media::GenerateJWKSet(key, key_length, init_data, init_data_length); + DCHECK(!jwk.empty()); + media_keys_->UpdateSession( + session_id, reinterpret_cast<const uint8*>(jwk.data()), jwk.size()); + return; + } + + media_keys_->UpdateSession(session_id, key, key_length); } void ProxyDecryptor::CancelKeyRequest(const std::string& session_id) { DVLOG(1) << "CancelKeyRequest()"; // WebMediaPlayerImpl ensures GenerateKeyRequest() has been called. - media_keys_->CancelKeyRequest(session_id); + uint32 session_reference_id = LookupSessionId(session_id); + if (session_reference_id == kInvalidSessionId) { + // Session hasn't been created, so it is an error. + key_error_cb_.Run( + std::string(), media::MediaKeys::kUnknownError, 0); + } + else { + media_keys_->ReleaseSession(session_reference_id); + } } scoped_ptr<media::MediaKeys> ProxyDecryptor::CreateMediaKeys( @@ -130,29 +195,76 @@ scoped_ptr<media::MediaKeys> ProxyDecryptor::CreateMediaKeys( base::Bind(&ProxyDecryptor::DestroyHelperPlugin, weak_ptr_factory_.GetWeakPtr()), #elif defined(OS_ANDROID) - proxy_, + manager_, media_keys_id_, frame_url, #endif // defined(ENABLE_PEPPER_CDMS) - base::Bind(&ProxyDecryptor::KeyAdded, weak_ptr_factory_.GetWeakPtr()), - base::Bind(&ProxyDecryptor::KeyError, weak_ptr_factory_.GetWeakPtr()), - base::Bind(&ProxyDecryptor::KeyMessage, weak_ptr_factory_.GetWeakPtr())); + base::Bind(&ProxyDecryptor::OnSessionCreated, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&ProxyDecryptor::OnSessionMessage, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&ProxyDecryptor::OnSessionReady, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&ProxyDecryptor::OnSessionClosed, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&ProxyDecryptor::OnSessionError, + weak_ptr_factory_.GetWeakPtr())); +} + +void ProxyDecryptor::OnSessionCreated(uint32 session_id, + const std::string& web_session_id) { + // Due to heartbeat messages, OnSessionCreated() can get called multiple + // times. + SessionIdMap::iterator it = sessions_.find(session_id); + DCHECK(it == sessions_.end() || it->second == web_session_id); + if (it == sessions_.end()) + sessions_[session_id] = web_session_id; +} + +void ProxyDecryptor::OnSessionMessage(uint32 session_id, + const std::vector<uint8>& message, + const std::string& destination_url) { + // Assumes that OnSessionCreated() has been called before this. + key_message_cb_.Run(LookupWebSessionId(session_id), message, destination_url); } -void ProxyDecryptor::KeyAdded(const std::string& session_id) { - key_added_cb_.Run(session_id); +void ProxyDecryptor::OnSessionReady(uint32 session_id) { + // Assumes that OnSessionCreated() has been called before this. + key_added_cb_.Run(LookupWebSessionId(session_id)); } -void ProxyDecryptor::KeyError(const std::string& session_id, - media::MediaKeys::KeyError error_code, - int system_code) { - key_error_cb_.Run(session_id, error_code, system_code); +void ProxyDecryptor::OnSessionClosed(uint32 session_id) { + // No closed event in EME v0.1b. } -void ProxyDecryptor::KeyMessage(const std::string& session_id, - const std::vector<uint8>& message, - const std::string& default_url) { - key_message_cb_.Run(session_id, message, default_url); +void ProxyDecryptor::OnSessionError(uint32 session_id, + media::MediaKeys::KeyError error_code, + int system_code) { + // Assumes that OnSessionCreated() has been called before this. + key_error_cb_.Run(LookupWebSessionId(session_id), error_code, system_code); +} + +uint32 ProxyDecryptor::LookupSessionId(const std::string& session_id) { + for (SessionIdMap::iterator it = sessions_.begin(); + it != sessions_.end(); + ++it) { + if (it->second == session_id) + return it->first; + } + + // If |session_id| is null, then use the single reference id. + if (session_id.empty() && sessions_.size() == 1) + return sessions_.begin()->first; + + return kInvalidSessionId; +} + +const std::string& ProxyDecryptor::LookupWebSessionId(uint32 session_id) { + DCHECK_NE(session_id, kInvalidSessionId); + + // Session may not exist if error happens during GenerateKeyRequest(). + SessionIdMap::iterator it = sessions_.find(session_id); + return (it != sessions_.end()) ? it->second : base::EmptyString(); } } // namespace content diff --git a/chromium/content/renderer/media/crypto/proxy_decryptor.h b/chromium/content/renderer/media/crypto/proxy_decryptor.h index 02027219794..026b56a2802 100644 --- a/chromium/content/renderer/media/crypto/proxy_decryptor.h +++ b/chromium/content/renderer/media/crypto/proxy_decryptor.h @@ -5,6 +5,7 @@ #ifndef CONTENT_RENDERER_MEDIA_CRYPTO_PROXY_DECRYPTOR_H_ #define CONTENT_RENDERER_MEDIA_CRYPTO_PROXY_DECRYPTOR_H_ +#include <map> #include <string> #include <vector> @@ -17,7 +18,7 @@ class GURL; -namespace WebKit { +namespace blink { #if defined(ENABLE_PEPPER_CDMS) class WebFrame; class WebMediaPlayerClient; @@ -26,27 +27,46 @@ class WebMediaPlayerClient; namespace content { -class WebMediaPlayerProxyAndroid; +#if defined(OS_ANDROID) +class RendererMediaPlayerManager; +#endif // defined(OS_ANDROID) // ProxyDecryptor is for EME v0.1b only. It should not be used for the WD API. // A decryptor proxy that creates a real decryptor object on demand and // forwards decryptor calls to it. +// +// Now that the Pepper API calls use session ID to match responses with +// requests, this class maintains a mapping between session ID and web session +// ID. Callers of this class expect web session IDs in the responses. +// Session IDs are internal unique references to the session. Web session IDs +// are the CDM generated ID for the session, and are what are visible to users. +// // TODO(xhwang): Currently we don't support run-time switching among decryptor // objects. Fix this when needed. // TODO(xhwang): The ProxyDecryptor is not a Decryptor. Find a better name! -class ProxyDecryptor : public media::MediaKeys { +class ProxyDecryptor { public: + // These are similar to the callbacks in media_keys.h, but pass back the + // web session ID rather than the internal session ID. + typedef base::Callback<void(const std::string& session_id)> KeyAddedCB; + typedef base::Callback<void(const std::string& session_id, + media::MediaKeys::KeyError error_code, + int system_code)> KeyErrorCB; + typedef base::Callback<void(const std::string& session_id, + const std::vector<uint8>& message, + const std::string& default_url)> KeyMessageCB; + ProxyDecryptor( #if defined(ENABLE_PEPPER_CDMS) - WebKit::WebMediaPlayerClient* web_media_player_client, - WebKit::WebFrame* web_frame, + blink::WebMediaPlayerClient* web_media_player_client, + blink::WebFrame* web_frame, #elif defined(OS_ANDROID) - WebMediaPlayerProxyAndroid* proxy, + RendererMediaPlayerManager* manager, int media_keys_id, #endif // defined(ENABLE_PEPPER_CDMS) - const media::KeyAddedCB& key_added_cb, - const media::KeyErrorCB& key_error_cb, - const media::KeyMessageCB& key_message_cb); + const KeyAddedCB& key_added_cb, + const KeyErrorCB& key_error_cb, + const KeyMessageCB& key_message_cb); virtual ~ProxyDecryptor(); // Only call this once. @@ -58,29 +78,41 @@ class ProxyDecryptor : public media::MediaKeys { // NULL immediately and reset. void SetDecryptorReadyCB(const media::DecryptorReadyCB& decryptor_ready_cb); - // MediaKeys implementation. // May only be called after InitializeCDM() succeeds. - virtual bool GenerateKeyRequest(const std::string& type, - const uint8* init_data, - int init_data_length) OVERRIDE; - virtual void AddKey(const uint8* key, int key_length, - const uint8* init_data, int init_data_length, - const std::string& session_id) OVERRIDE; - virtual void CancelKeyRequest(const std::string& session_id) OVERRIDE; + bool GenerateKeyRequest(const std::string& type, + const uint8* init_data, + int init_data_length); + void AddKey(const uint8* key, int key_length, + const uint8* init_data, int init_data_length, + const std::string& session_id); + void CancelKeyRequest(const std::string& session_id); private: + // Session_id <-> web_session_id map. + typedef std::map<uint32, std::string> SessionIdMap; + // Helper function to create MediaKeys to handle the given |key_system|. scoped_ptr<media::MediaKeys> CreateMediaKeys(const std::string& key_system, const GURL& frame_url); - // Callbacks for firing key events. - void KeyAdded(const std::string& session_id); - void KeyError(const std::string& session_id, - media::MediaKeys::KeyError error_code, - int system_code); - void KeyMessage(const std::string& session_id, - const std::vector<uint8>& message, - const std::string& default_url); + // Callbacks for firing session events. + void OnSessionCreated(uint32 session_id, const std::string& web_session_id); + void OnSessionMessage(uint32 session_id, + const std::vector<uint8>& message, + const std::string& default_url); + void OnSessionReady(uint32 session_id); + void OnSessionClosed(uint32 session_id); + void OnSessionError(uint32 session_id, + media::MediaKeys::KeyError error_code, + int system_code); + + // Helper function to determine session_id for the provided |web_session_id|. + uint32 LookupSessionId(const std::string& web_session_id); + + // Helper function to determine web_session_id for the provided |session_id|. + // The returned web_session_id is only valid on the main thread, and should be + // stored by copy. + const std::string& LookupWebSessionId(uint32 session_id); base::WeakPtrFactory<ProxyDecryptor> weak_ptr_factory_; @@ -89,10 +121,10 @@ class ProxyDecryptor : public media::MediaKeys { void DestroyHelperPlugin(); // Needed to create the PpapiDecryptor. - WebKit::WebMediaPlayerClient* web_media_player_client_; - WebKit::WebFrame* web_frame_; + blink::WebMediaPlayerClient* web_media_player_client_; + blink::WebFrame* web_frame_; #elif defined(OS_ANDROID) - WebMediaPlayerProxyAndroid* proxy_; + RendererMediaPlayerManager* manager_; int media_keys_id_; #endif // defined(ENABLE_PEPPER_CDMS) @@ -101,9 +133,9 @@ class ProxyDecryptor : public media::MediaKeys { scoped_ptr<media::MediaKeys> media_keys_; // Callbacks for firing key events. - media::KeyAddedCB key_added_cb_; - media::KeyErrorCB key_error_cb_; - media::KeyMessageCB key_message_cb_; + KeyAddedCB key_added_cb_; + KeyErrorCB key_error_cb_; + KeyMessageCB key_message_cb_; // Protects the |decryptor_|. Note that |decryptor_| itself should be thread // safe as per the Decryptor interface. @@ -111,6 +143,15 @@ class ProxyDecryptor : public media::MediaKeys { media::DecryptorReadyCB decryptor_ready_cb_; + // Session IDs are used to uniquely track sessions so that CDM callbacks + // can get mapped to the correct session ID. Session ID should be unique + // per renderer process for debugging purposes. + static uint32 next_session_id_; + + SessionIdMap sessions_; + + bool is_clear_key_; + DISALLOW_COPY_AND_ASSIGN(ProxyDecryptor); }; diff --git a/chromium/content/renderer/media/media_stream_audio_processor.cc b/chromium/content/renderer/media/media_stream_audio_processor.cc new file mode 100644 index 00000000000..98439c78aef --- /dev/null +++ b/chromium/content/renderer/media/media_stream_audio_processor.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/renderer/media/media_stream_audio_processor.h" + +#include "base/command_line.h" +#include "base/debug/trace_event.h" +#include "content/public/common/content_switches.h" +#include "content/renderer/media/media_stream_audio_processor_options.h" +#include "media/audio/audio_parameters.h" +#include "media/base/audio_converter.h" +#include "media/base/audio_fifo.h" +#include "media/base/channel_layout.h" + +namespace content { + +namespace { + +using webrtc::AudioProcessing; +using webrtc::MediaConstraintsInterface; + +#if defined(ANDROID) +const int kAudioProcessingSampleRate = 16000; +#else +const int kAudioProcessingSampleRate = 32000; +#endif +const int kAudioProcessingNumberOfChannel = 1; + +const int kMaxNumberOfBuffersInFifo = 2; + +} // namespace + +class MediaStreamAudioProcessor::MediaStreamAudioConverter + : public media::AudioConverter::InputCallback { + public: + MediaStreamAudioConverter(const media::AudioParameters& source_params, + const media::AudioParameters& sink_params) + : source_params_(source_params), + sink_params_(sink_params), + audio_converter_(source_params, sink_params_, false) { + audio_converter_.AddInput(this); + // Create and initialize audio fifo and audio bus wrapper. + // The size of the FIFO should be at least twice of the source buffer size + // or twice of the sink buffer size. + int buffer_size = std::max( + kMaxNumberOfBuffersInFifo * source_params_.frames_per_buffer(), + kMaxNumberOfBuffersInFifo * sink_params_.frames_per_buffer()); + fifo_.reset(new media::AudioFifo(source_params_.channels(), buffer_size)); + // TODO(xians): Use CreateWrapper to save one memcpy. + audio_wrapper_ = media::AudioBus::Create(sink_params_.channels(), + sink_params_.frames_per_buffer()); + } + + virtual ~MediaStreamAudioConverter() { + DCHECK(thread_checker_.CalledOnValidThread()); + audio_converter_.RemoveInput(this); + } + + void Push(media::AudioBus* audio_source) { + // Called on the audio thread, which is the capture audio thread for + // |MediaStreamAudioProcessor::capture_converter_|, and render audio thread + // for |MediaStreamAudioProcessor::render_converter_|. + // And it must be the same thread as calling Convert(). + DCHECK(thread_checker_.CalledOnValidThread()); + fifo_->Push(audio_source); + } + + bool Convert(webrtc::AudioFrame* out) { + // Called on the audio thread, which is the capture audio thread for + // |MediaStreamAudioProcessor::capture_converter_|, and render audio thread + // for |MediaStreamAudioProcessor::render_converter_|. + // Return false if there is no 10ms data in the FIFO. + DCHECK(thread_checker_.CalledOnValidThread()); + if (fifo_->frames() < (source_params_.sample_rate() / 100)) + return false; + + // Convert 10ms data to the output format, this will trigger ProvideInput(). + audio_converter_.Convert(audio_wrapper_.get()); + + // TODO(xians): Figure out a better way to handle the interleaved and + // deinterleaved format switching. + audio_wrapper_->ToInterleaved(audio_wrapper_->frames(), + sink_params_.bits_per_sample() / 8, + out->data_); + + out->samples_per_channel_ = sink_params_.frames_per_buffer(); + out->sample_rate_hz_ = sink_params_.sample_rate(); + out->speech_type_ = webrtc::AudioFrame::kNormalSpeech; + out->vad_activity_ = webrtc::AudioFrame::kVadUnknown; + out->num_channels_ = sink_params_.channels(); + + return true; + } + + const media::AudioParameters& source_parameters() const { + return source_params_; + } + const media::AudioParameters& sink_parameters() const { + return sink_params_; + } + + private: + // AudioConverter::InputCallback implementation. + virtual double ProvideInput(media::AudioBus* audio_bus, + base::TimeDelta buffer_delay) OVERRIDE { + // Called on realtime audio thread. + // TODO(xians): Figure out why the first Convert() triggers ProvideInput + // two times. + if (fifo_->frames() < audio_bus->frames()) + return 0; + + fifo_->Consume(audio_bus, 0, audio_bus->frames()); + + // Return 1.0 to indicate no volume scaling on the data. + return 1.0; + } + + base::ThreadChecker thread_checker_; + const media::AudioParameters source_params_; + const media::AudioParameters sink_params_; + + // TODO(xians): consider using SincResampler to save some memcpy. + // Handles mixing and resampling between input and output parameters. + media::AudioConverter audio_converter_; + scoped_ptr<media::AudioBus> audio_wrapper_; + scoped_ptr<media::AudioFifo> fifo_; +}; + +MediaStreamAudioProcessor::MediaStreamAudioProcessor( + const webrtc::MediaConstraintsInterface* constraints) + : render_delay_ms_(0) { + capture_thread_checker_.DetachFromThread(); + render_thread_checker_.DetachFromThread(); + InitializeAudioProcessingModule(constraints); +} + +MediaStreamAudioProcessor::~MediaStreamAudioProcessor() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + StopAudioProcessing(); +} + +void MediaStreamAudioProcessor::PushCaptureData(media::AudioBus* audio_source) { + DCHECK(capture_thread_checker_.CalledOnValidThread()); + capture_converter_->Push(audio_source); +} + +void MediaStreamAudioProcessor::PushRenderData( + const int16* render_audio, int sample_rate, int number_of_channels, + int number_of_frames, base::TimeDelta render_delay) { + DCHECK(render_thread_checker_.CalledOnValidThread()); + + // Return immediately if the echo cancellation is off. + if (!audio_processing_ || + !audio_processing_->echo_cancellation()->is_enabled()) { + return; + } + + TRACE_EVENT0("audio", + "MediaStreamAudioProcessor::FeedRenderDataToAudioProcessing"); + int64 new_render_delay_ms = render_delay.InMilliseconds(); + DCHECK_LT(new_render_delay_ms, + std::numeric_limits<base::subtle::Atomic32>::max()); + base::subtle::Release_Store(&render_delay_ms_, new_render_delay_ms); + + InitializeRenderConverterIfNeeded(sample_rate, number_of_channels, + number_of_frames); + + // TODO(xians): Avoid this extra interleave/deinterleave. + render_data_bus_->FromInterleaved(render_audio, + render_data_bus_->frames(), + sizeof(render_audio[0])); + render_converter_->Push(render_data_bus_.get()); + while (render_converter_->Convert(&render_frame_)) + audio_processing_->AnalyzeReverseStream(&render_frame_); +} + +bool MediaStreamAudioProcessor::ProcessAndConsumeData( + base::TimeDelta capture_delay, int volume, bool key_pressed, + int16** out) { + DCHECK(capture_thread_checker_.CalledOnValidThread()); + TRACE_EVENT0("audio", + "MediaStreamAudioProcessor::ProcessAndConsumeData"); + + if (!capture_converter_->Convert(&capture_frame_)) + return false; + + ProcessData(&capture_frame_, capture_delay, volume, key_pressed); + *out = capture_frame_.data_; + + return true; +} + +void MediaStreamAudioProcessor::SetCaptureFormat( + const media::AudioParameters& source_params) { + DCHECK(capture_thread_checker_.CalledOnValidThread()); + DCHECK(source_params.IsValid()); + + // Create and initialize audio converter for the source data. + // When the webrtc AudioProcessing is enabled, the sink format of the + // converter will be the same as the post-processed data format, which is + // 32k mono for desktops and 16k mono for Android. When the AudioProcessing + // is disabled, the sink format will be the same as the source format. + const int sink_sample_rate = audio_processing_ ? + kAudioProcessingSampleRate : source_params.sample_rate(); + const media::ChannelLayout sink_channel_layout = audio_processing_ ? + media::CHANNEL_LAYOUT_MONO : source_params.channel_layout(); + + // WebRtc is using 10ms data as its native packet size. + media::AudioParameters sink_params( + media::AudioParameters::AUDIO_PCM_LOW_LATENCY, sink_channel_layout, + sink_sample_rate, 16, sink_sample_rate / 100); + capture_converter_.reset( + new MediaStreamAudioConverter(source_params, sink_params)); +} + +const media::AudioParameters& MediaStreamAudioProcessor::OutputFormat() const { + return capture_converter_->sink_parameters(); +} + +void MediaStreamAudioProcessor::InitializeAudioProcessingModule( + const webrtc::MediaConstraintsInterface* constraints) { + DCHECK(!audio_processing_); + DCHECK(constraints); + if (!CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableAudioTrackProcessing)) { + return; + } + + const bool enable_aec = GetPropertyFromConstraints( + constraints, MediaConstraintsInterface::kEchoCancellation); + const bool enable_ns = GetPropertyFromConstraints( + constraints, MediaConstraintsInterface::kNoiseSuppression); + const bool enable_high_pass_filter = GetPropertyFromConstraints( + constraints, MediaConstraintsInterface::kHighpassFilter); +#if defined(IOS) || defined(ANDROID) + const bool enable_experimental_aec = false; + const bool enable_typing_detection = false; +#else + const bool enable_experimental_aec = GetPropertyFromConstraints( + constraints, MediaConstraintsInterface::kExperimentalEchoCancellation); + const bool enable_typing_detection = GetPropertyFromConstraints( + constraints, MediaConstraintsInterface::kTypingNoiseDetection); +#endif + + // Return immediately if no audio processing component is enabled. + if (!enable_aec && !enable_experimental_aec && !enable_ns && + !enable_high_pass_filter && !enable_typing_detection) { + return; + } + + // Create and configure the webrtc::AudioProcessing. + audio_processing_.reset(webrtc::AudioProcessing::Create(0)); + + // Enable the audio processing components. + if (enable_aec) { + EnableEchoCancellation(audio_processing_.get()); + if (enable_experimental_aec) + EnableExperimentalEchoCancellation(audio_processing_.get()); + } + + if (enable_ns) + EnableNoiseSuppression(audio_processing_.get()); + + if (enable_high_pass_filter) + EnableHighPassFilter(audio_processing_.get()); + + if (enable_typing_detection) + EnableTypingDetection(audio_processing_.get()); + + + // Configure the audio format the audio processing is running on. This + // has to be done after all the needed components are enabled. + CHECK_EQ(audio_processing_->set_sample_rate_hz(kAudioProcessingSampleRate), + 0); + CHECK_EQ(audio_processing_->set_num_channels(kAudioProcessingNumberOfChannel, + kAudioProcessingNumberOfChannel), + 0); +} + +void MediaStreamAudioProcessor::InitializeRenderConverterIfNeeded( + int sample_rate, int number_of_channels, int frames_per_buffer) { + DCHECK(render_thread_checker_.CalledOnValidThread()); + // TODO(xians): Figure out if we need to handle the buffer size change. + if (render_converter_.get() && + render_converter_->source_parameters().sample_rate() == sample_rate && + render_converter_->source_parameters().channels() == number_of_channels) { + // Do nothing if the |render_converter_| has been setup properly. + return; + } + + // Create and initialize audio converter for the render data. + // webrtc::AudioProcessing accepts the same format as what it uses to process + // capture data, which is 32k mono for desktops and 16k mono for Android. + media::AudioParameters source_params( + media::AudioParameters::AUDIO_PCM_LOW_LATENCY, + media::GuessChannelLayout(number_of_channels), sample_rate, 16, + frames_per_buffer); + media::AudioParameters sink_params( + media::AudioParameters::AUDIO_PCM_LOW_LATENCY, + media::CHANNEL_LAYOUT_MONO, kAudioProcessingSampleRate, 16, + kAudioProcessingSampleRate / 100); + render_converter_.reset( + new MediaStreamAudioConverter(source_params, sink_params)); + render_data_bus_ = media::AudioBus::Create(number_of_channels, + frames_per_buffer); +} + +void MediaStreamAudioProcessor::ProcessData(webrtc::AudioFrame* audio_frame, + base::TimeDelta capture_delay, + int volume, + bool key_pressed) { + DCHECK(capture_thread_checker_.CalledOnValidThread()); + if (!audio_processing_) + return; + + TRACE_EVENT0("audio", "MediaStreamAudioProcessor::Process10MsData"); + DCHECK_EQ(audio_processing_->sample_rate_hz(), + capture_converter_->sink_parameters().sample_rate()); + DCHECK_EQ(audio_processing_->num_input_channels(), + capture_converter_->sink_parameters().channels()); + DCHECK_EQ(audio_processing_->num_output_channels(), + capture_converter_->sink_parameters().channels()); + + base::subtle::Atomic32 render_delay_ms = + base::subtle::Acquire_Load(&render_delay_ms_); + int64 capture_delay_ms = capture_delay.InMilliseconds(); + DCHECK_LT(capture_delay_ms, + std::numeric_limits<base::subtle::Atomic32>::max()); + int total_delay_ms = capture_delay_ms + render_delay_ms; + if (total_delay_ms > 1000) { + LOG(WARNING) << "Large audio delay, capture delay: " << capture_delay_ms + << "ms; render delay: " << render_delay_ms << "ms"; + } + + audio_processing_->set_stream_delay_ms(total_delay_ms); + webrtc::GainControl* agc = audio_processing_->gain_control(); + int err = agc->set_stream_analog_level(volume); + DCHECK_EQ(err, 0) << "set_stream_analog_level() error: " << err; + err = audio_processing_->ProcessStream(audio_frame); + DCHECK_EQ(err, 0) << "ProcessStream() error: " << err; + + // TODO(xians): Add support for AGC, typing detection, audio level + // calculation, stereo swapping. +} + +void MediaStreamAudioProcessor::StopAudioProcessing() { + if (!audio_processing_.get()) + return; + + audio_processing_.reset(); +} + +} // namespace content diff --git a/chromium/content/renderer/media/media_stream_audio_processor.h b/chromium/content/renderer/media/media_stream_audio_processor.h new file mode 100644 index 00000000000..9c6db685db4 --- /dev/null +++ b/chromium/content/renderer/media/media_stream_audio_processor.h @@ -0,0 +1,138 @@ +// 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_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_PROCESSOR_H_ +#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_PROCESSOR_H_ + +#include "base/atomicops.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread_checker.h" +#include "base/time/time.h" +#include "content/common/content_export.h" +#include "media/base/audio_converter.h" +#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h" +#include "third_party/webrtc/modules/audio_processing/include/audio_processing.h" +#include "third_party/webrtc/modules/interface/module_common_types.h" + +namespace media { +class AudioBus; +class AudioFifo; +class AudioParameters; +} // namespace media + +namespace webrtc { +class AudioFrame; +} + +namespace content { + +// This class owns an object of webrtc::AudioProcessing which contains signal +// processing components like AGC, AEC and NS. It enables the components based +// on the getUserMedia constraints, processes the data and outputs it in a unit +// of 10 ms data chunk. +class CONTENT_EXPORT MediaStreamAudioProcessor { + public: + explicit MediaStreamAudioProcessor( + const webrtc::MediaConstraintsInterface* constraints); + ~MediaStreamAudioProcessor(); + + // Pushes capture data in |audio_source| to the internal FIFO. + // Called on the capture audio thread. + void PushCaptureData(media::AudioBus* audio_source); + + // Push the render audio to webrtc::AudioProcessing for analysis. This is + // needed iff echo processing is enabled. + // |render_audio| is the pointer to the render audio data, its format + // is specified by |sample_rate|, |number_of_channels| and |number_of_frames|. + // Called on the render audio thread. + void PushRenderData(const int16* render_audio, + int sample_rate, + int number_of_channels, + int number_of_frames, + base::TimeDelta render_delay); + + // Processes a block of 10 ms data from the internal FIFO and outputs it via + // |out|. |out| is the address of the pointer that will be pointed to + // the post-processed data if the method is returning a true. The lifetime + // of the data represeted by |out| is guaranteed to outlive the method call. + // That also says *|out| won't change until this method is called again. + // Returns true if the internal FIFO has at least 10 ms data for processing, + // otherwise false. + // |capture_delay|, |volume| and |key_pressed| will be passed to + // webrtc::AudioProcessing to help processing the data. + // Called on the capture audio thread. + bool ProcessAndConsumeData(base::TimeDelta capture_delay, + int volume, + bool key_pressed, + int16** out); + + // Called when the format of the capture data has changed. + // This has to be called before PushCaptureData() and ProcessAndConsumeData(). + // Called on the main render thread. + void SetCaptureFormat(const media::AudioParameters& source_params); + + // The audio format of the output from the processor. + const media::AudioParameters& OutputFormat() const; + + // Accessor to check if the audio processing is enabled or not. + bool has_audio_processing() const { return audio_processing_.get() != NULL; } + + private: + class MediaStreamAudioConverter; + + // Helper to initialize the WebRtc AudioProcessing. + void InitializeAudioProcessingModule( + const webrtc::MediaConstraintsInterface* constraints); + + // Helper to initialize the render converter. + void InitializeRenderConverterIfNeeded(int sample_rate, + int number_of_channels, + int frames_per_buffer); + + // Called by ProcessAndConsumeData(). + void ProcessData(webrtc::AudioFrame* audio_frame, + base::TimeDelta capture_delay, + int volume, + bool key_pressed); + + // Called when the processor is going away. + void StopAudioProcessing(); + + // Cached value for the render delay latency. This member is accessed by + // both the capture audio thread and the render audio thread. + base::subtle::Atomic32 render_delay_ms_; + + // webrtc::AudioProcessing module which does AEC, AGC, NS, HighPass filter, + // ..etc. + scoped_ptr<webrtc::AudioProcessing> audio_processing_; + + // Converter used for the down-mixing and resampling of the capture data. + scoped_ptr<MediaStreamAudioConverter> capture_converter_; + + // AudioFrame used to hold the output of |capture_converter_|. + webrtc::AudioFrame capture_frame_; + + // Converter used for the down-mixing and resampling of the render data when + // the AEC is enabled. + scoped_ptr<MediaStreamAudioConverter> render_converter_; + + // AudioFrame used to hold the output of |render_converter_|. + webrtc::AudioFrame render_frame_; + + // Data bus to help converting interleaved data to an AudioBus. + scoped_ptr<media::AudioBus> render_data_bus_; + + // Used to DCHECK that some methods are called on the main render thread. + base::ThreadChecker main_thread_checker_; + + // Used to DCHECK that some methods are called on the capture audio thread. + base::ThreadChecker capture_thread_checker_; + + // Used to DCHECK that PushRenderData() is called on the render audio thread. + base::ThreadChecker render_thread_checker_; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_PROCESSOR_H_ diff --git a/chromium/content/renderer/media/media_stream_audio_processor_options.cc b/chromium/content/renderer/media/media_stream_audio_processor_options.cc new file mode 100644 index 00000000000..add7f957c86 --- /dev/null +++ b/chromium/content/renderer/media/media_stream_audio_processor_options.cc @@ -0,0 +1,96 @@ +// 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/renderer/media/media_stream_audio_processor_options.h" + +#include "base/files/file_path.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/strings/utf_string_conversions.h" +#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h" +#include "third_party/webrtc/modules/audio_processing/include/audio_processing.h" + +namespace content { + +bool GetPropertyFromConstraints(const MediaConstraintsInterface* constraints, + const std::string& key) { + bool value = false; + return webrtc::FindConstraint(constraints, key, &value, NULL) && value; +} + +void EnableEchoCancellation(AudioProcessing* audio_processing) { +#if defined(OS_IOS) + // On iOS, VPIO provides built-in EC and AGC. + return; +#elif defined(OS_ANDROID) + // Mobile devices are using AECM. + int err = audio_processing->echo_control_mobile()->Enable(true); + err |= audio_processing->echo_control_mobile()->set_routing_mode( + webrtc::EchoControlMobile::kSpeakerphone); + CHECK_EQ(err, 0); +#else + int err = audio_processing->echo_cancellation()->Enable(true); + err |= audio_processing->echo_cancellation()->set_suppression_level( + webrtc::EchoCancellation::kHighSuppression); + + // Enable the metrics for AEC. + err |= audio_processing->echo_cancellation()->enable_metrics(true); + err |= audio_processing->echo_cancellation()->enable_delay_logging(true); + CHECK_EQ(err, 0); +#endif +} + +void EnableNoiseSuppression(AudioProcessing* audio_processing) { + int err = audio_processing->noise_suppression()->set_level( + webrtc::NoiseSuppression::kHigh); + err |= audio_processing->noise_suppression()->Enable(true); + CHECK_EQ(err, 0); +} + +void EnableHighPassFilter(AudioProcessing* audio_processing) { + CHECK_EQ(audio_processing->high_pass_filter()->Enable(true), 0); +} + +// TODO(xians): stereo swapping +void EnableTypingDetection(AudioProcessing* audio_processing) { + int err = audio_processing->voice_detection()->Enable(true); + err |= audio_processing->voice_detection()->set_likelihood( + webrtc::VoiceDetection::kVeryLowLikelihood); + CHECK_EQ(err, 0); +} + +void EnableExperimentalEchoCancellation(AudioProcessing* audio_processing) { + webrtc::Config config; + config.Set<webrtc::DelayCorrection>(new webrtc::DelayCorrection(true)); + audio_processing->SetExtraOptions(config); +} + +void StartAecDump(AudioProcessing* audio_processing) { + // TODO(grunell): Figure out a more suitable directory for the audio dump + // data. + base::FilePath path; +#if defined(CHROMEOS) + PathService::Get(base::DIR_TEMP, &path); +#elif defined(ANDROID) + path = base::FilePath(FILE_PATH_LITERAL("sdcard")); +#else + PathService::Get(base::DIR_EXE, &path); +#endif + base::FilePath file = path.Append(FILE_PATH_LITERAL("audio.aecdump")); + +#if defined(OS_WIN) + const std::string file_name = WideToUTF8(file.value()); +#else + const std::string file_name = file.value(); +#endif + if (audio_processing->StartDebugRecording(file_name.c_str())) + DLOG(ERROR) << "Fail to start AEC debug recording"; +} + +void StopAecDump(AudioProcessing* audio_processing) { + if (audio_processing->StopDebugRecording()) + DLOG(ERROR) << "Fail to stop AEC debug recording"; +} + +} // namespace content diff --git a/chromium/content/renderer/media/media_stream_audio_processor_options.h b/chromium/content/renderer/media/media_stream_audio_processor_options.h new file mode 100644 index 00000000000..dcdec4e61f4 --- /dev/null +++ b/chromium/content/renderer/media/media_stream_audio_processor_options.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_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_PROCESSOR_OPTIONS_H_ +#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_PROCESSOR_OPTIONS_H_ + +#include <string> + +namespace webrtc { + +class AudioFrame; +class AudioProcessing; +class MediaConstraintsInterface; + +} + +namespace content { + +using webrtc::AudioProcessing; +using webrtc::MediaConstraintsInterface; + +// Gets the property named by |key| from the |constraints|. +// Returns true if the key is found and has a valid boolean value; Otherwise +// false. +bool GetPropertyFromConstraints( + const MediaConstraintsInterface* constraints, + const std::string& key); + +// Enables the echo cancellation in |audio_processing|. +void EnableEchoCancellation(AudioProcessing* audio_processing); + +// Enables the noise suppression in |audio_processing|. +void EnableNoiseSuppression(AudioProcessing* audio_processing); + +// Enables the high pass filter in |audio_processing|. +void EnableHighPassFilter(AudioProcessing* audio_processing); + +// Enables the typing detection in |audio_processing|. +void EnableTypingDetection(AudioProcessing* audio_processing); + +// Enables the experimental echo cancellation in |audio_processing|. +void EnableExperimentalEchoCancellation(AudioProcessing* audio_processing); + +// Starts the echo cancellation dump in |audio_processing|. +void StartAecDump(AudioProcessing* audio_processing); + +// Stops the echo cancellation dump in |audio_processing|. +void StopAecDump(AudioProcessing* audio_processing); + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_PROCESSOR_OPTIONS_H_ diff --git a/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc b/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc new file mode 100644 index 00000000000..1a6409c2c1a --- /dev/null +++ b/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc @@ -0,0 +1,166 @@ +// 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/command_line.h" +#include "base/file_util.h" +#include "base/files/file_path.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/time/time.h" +#include "content/public/common/content_switches.h" +#include "content/renderer/media/media_stream_audio_processor.h" +#include "content/renderer/media/rtc_media_constraints.h" +#include "media/audio/audio_parameters.h" +#include "media/base/audio_bus.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" + +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::AtLeast; +using ::testing::Return; + +namespace content { + +namespace { + +#if defined(ANDROID) +const int kAudioProcessingSampleRate = 16000; +#else +const int kAudioProcessingSampleRate = 32000; +#endif +const int kAudioProcessingNumberOfChannel = 1; + +// The number of packers used for testing. +const int kNumberOfPacketsForTest = 100; + +void ReadDataFromSpeechFile(char* data, int length) { + base::FilePath file; + CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &file)); + file = file.Append(FILE_PATH_LITERAL("media")) + .Append(FILE_PATH_LITERAL("test")) + .Append(FILE_PATH_LITERAL("data")) + .Append(FILE_PATH_LITERAL("speech_16b_stereo_48kHz.raw")); + DCHECK(base::PathExists(file)); + int64 data_file_size64 = 0; + DCHECK(base::GetFileSize(file, &data_file_size64)); + EXPECT_EQ(length, base::ReadFile(file, data, length)); + DCHECK(data_file_size64 > length); +} + +void ApplyFixedAudioConstraints(RTCMediaConstraints* constraints) { + // Constant constraint keys which enables default audio constraints on + // mediastreams with audio. + struct { + const char* key; + const char* value; + } static const kDefaultAudioConstraints[] = { + { webrtc::MediaConstraintsInterface::kEchoCancellation, + webrtc::MediaConstraintsInterface::kValueTrue }, + #if defined(OS_CHROMEOS) || defined(OS_MACOSX) + // Enable the extended filter mode AEC on platforms with known echo issues. + { webrtc::MediaConstraintsInterface::kExperimentalEchoCancellation, + webrtc::MediaConstraintsInterface::kValueTrue }, + #endif + { webrtc::MediaConstraintsInterface::kAutoGainControl, + webrtc::MediaConstraintsInterface::kValueTrue }, + { webrtc::MediaConstraintsInterface::kExperimentalAutoGainControl, + webrtc::MediaConstraintsInterface::kValueTrue }, + { webrtc::MediaConstraintsInterface::kNoiseSuppression, + webrtc::MediaConstraintsInterface::kValueTrue }, + { webrtc::MediaConstraintsInterface::kHighpassFilter, + webrtc::MediaConstraintsInterface::kValueTrue }, + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { + constraints->AddMandatory(kDefaultAudioConstraints[i].key, + kDefaultAudioConstraints[i].value, false); + } +} + +} // namespace + +class MediaStreamAudioProcessorTest : public ::testing::Test { + public: + MediaStreamAudioProcessorTest() + : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, + media::CHANNEL_LAYOUT_STEREO, 48000, 16, 512) { + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableAudioTrackProcessing); + } + + protected: + // Helper method to save duplicated code. + void ProcessDataAndVerifyFormat(MediaStreamAudioProcessor* audio_processor, + int expected_output_sample_rate, + int expected_output_channels, + int expected_output_buffer_size) { + // Read the audio data from a file. + const int packet_size = + params_.frames_per_buffer() * 2 * params_.channels(); + const size_t length = packet_size * kNumberOfPacketsForTest; + scoped_ptr<char[]> capture_data(new char[length]); + ReadDataFromSpeechFile(capture_data.get(), length); + const int16* data_ptr = reinterpret_cast<const int16*>(capture_data.get()); + scoped_ptr<media::AudioBus> data_bus = media::AudioBus::Create( + params_.channels(), params_.frames_per_buffer()); + for (int i = 0; i < kNumberOfPacketsForTest; ++i) { + data_bus->FromInterleaved(data_ptr, data_bus->frames(), 2); + audio_processor->PushCaptureData(data_bus.get()); + + // |audio_processor| does nothing when the audio processing is off in + // the processor. + audio_processor->PushRenderData( + data_ptr, + params_.sample_rate(), params_.channels(), + params_.frames_per_buffer(), base::TimeDelta::FromMilliseconds(10)); + + int16* output = NULL; + while(audio_processor->ProcessAndConsumeData( + base::TimeDelta::FromMilliseconds(10), 255, false, &output)) { + EXPECT_TRUE(output != NULL); + EXPECT_EQ(audio_processor->OutputFormat().sample_rate(), + expected_output_sample_rate); + EXPECT_EQ(audio_processor->OutputFormat().channels(), + expected_output_channels); + EXPECT_EQ(audio_processor->OutputFormat().frames_per_buffer(), + expected_output_buffer_size); + } + + data_ptr += params_.frames_per_buffer() * params_.channels(); + } + } + + media::AudioParameters params_; +}; + +TEST_F(MediaStreamAudioProcessorTest, WithoutAudioProcessing) { + // Setup the audio processor with empty constraint. + RTCMediaConstraints constraints; + MediaStreamAudioProcessor audio_processor(&constraints); + audio_processor.SetCaptureFormat(params_); + EXPECT_FALSE(audio_processor.has_audio_processing()); + + ProcessDataAndVerifyFormat(&audio_processor, + params_.sample_rate(), + params_.channels(), + params_.sample_rate() / 100); +} + +TEST_F(MediaStreamAudioProcessorTest, WithAudioProcessing) { + // Setup the audio processor with default constraint. + RTCMediaConstraints constraints; + ApplyFixedAudioConstraints(&constraints); + MediaStreamAudioProcessor audio_processor(&constraints); + audio_processor.SetCaptureFormat(params_); + EXPECT_TRUE(audio_processor.has_audio_processing()); + + ProcessDataAndVerifyFormat(&audio_processor, + kAudioProcessingSampleRate, + kAudioProcessingNumberOfChannel, + kAudioProcessingSampleRate / 100); +} + +} // namespace content diff --git a/chromium/content/renderer/media/media_stream_audio_sink_owner.cc b/chromium/content/renderer/media/media_stream_audio_sink_owner.cc new file mode 100644 index 00000000000..664988d8213 --- /dev/null +++ b/chromium/content/renderer/media/media_stream_audio_sink_owner.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/renderer/media/media_stream_audio_sink_owner.h" + +#include "content/public/renderer/media_stream_audio_sink.h" +#include "media/audio/audio_parameters.h" + +namespace content { + +MediaStreamAudioSinkOwner::MediaStreamAudioSinkOwner(MediaStreamAudioSink* sink) + : delegate_(sink) { +} + +int MediaStreamAudioSinkOwner::OnData(const int16* audio_data, + int sample_rate, + int number_of_channels, + int number_of_frames, + const std::vector<int>& channels, + int audio_delay_milliseconds, + int current_volume, + bool need_audio_processing, + bool key_pressed) { + base::AutoLock lock(lock_); + // TODO(xians): Investigate on the possibility of not calling out with the + // lock. + if (delegate_) { + delegate_->OnData(audio_data, + sample_rate, + number_of_channels, + number_of_frames); + } + + return 0; +} + +void MediaStreamAudioSinkOwner::OnSetFormat( + const media::AudioParameters& params) { + base::AutoLock lock(lock_); + if (delegate_) + delegate_->OnSetFormat(params); +} + +void MediaStreamAudioSinkOwner::OnReadyStateChanged( + blink::WebMediaStreamSource::ReadyState state) { + base::AutoLock lock(lock_); + if (delegate_) + delegate_->OnReadyStateChanged(state); +} + +void MediaStreamAudioSinkOwner::Reset() { + base::AutoLock lock(lock_); + delegate_ = NULL; +} + +bool MediaStreamAudioSinkOwner::IsEqual( + const MediaStreamAudioSink* other) const { + DCHECK(other); + base::AutoLock lock(lock_); + return (other == delegate_); +} + +bool MediaStreamAudioSinkOwner::IsEqual( + const PeerConnectionAudioSink* other) const { + DCHECK(other); + return false; +} + +} // namespace content diff --git a/chromium/content/renderer/media/media_stream_audio_sink_owner.h b/chromium/content/renderer/media/media_stream_audio_sink_owner.h new file mode 100644 index 00000000000..6fcabbd3580 --- /dev/null +++ b/chromium/content/renderer/media/media_stream_audio_sink_owner.h @@ -0,0 +1,54 @@ +// 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_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_SINK_OWNER_H_ +#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_SINK_OWNER_H_ + +#include <vector> + +#include "base/synchronization/lock.h" +#include "content/renderer/media/media_stream_audio_track_sink.h" + +namespace content { + +class MediaStreamAudioSink; + +// Reference counted holder of MediaStreamAudioSink sinks. +class MediaStreamAudioSinkOwner : public MediaStreamAudioTrackSink { + public: + explicit MediaStreamAudioSinkOwner(MediaStreamAudioSink* sink); + + // MediaStreamAudioTrackSink implementation. + virtual int OnData(const int16* audio_data, + int sample_rate, + int number_of_channels, + int number_of_frames, + const std::vector<int>& channels, + int audio_delay_milliseconds, + int current_volume, + bool need_audio_processing, + bool key_pressed) OVERRIDE; + virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE; + virtual void OnReadyStateChanged( + blink::WebMediaStreamSource::ReadyState state) OVERRIDE; + virtual void Reset() OVERRIDE; + virtual bool IsEqual(const MediaStreamAudioSink* other) const OVERRIDE; + virtual bool IsEqual(const PeerConnectionAudioSink* other) const OVERRIDE; + + protected: + virtual ~MediaStreamAudioSinkOwner() {} + + private: + mutable base::Lock lock_; + + // Raw pointer to the delegate, the client need to call Reset() to set the + // pointer to NULL before the delegate goes away. + MediaStreamAudioSink* delegate_; + + DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioSinkOwner); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_SINK_OWNER_H_ diff --git a/chromium/content/renderer/media/media_stream_audio_track_sink.h b/chromium/content/renderer/media/media_stream_audio_track_sink.h new file mode 100644 index 00000000000..6e511bd6534 --- /dev/null +++ b/chromium/content/renderer/media/media_stream_audio_track_sink.h @@ -0,0 +1,72 @@ +// 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_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_TRACK_SINK_H_ +#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_TRACK_SINK_H_ + +#include <vector> + +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "media/audio/audio_parameters.h" +#include "third_party/WebKit/public/platform/WebMediaStreamSource.h" + +namespace content { + +class MediaStreamAudioSink; +class PeerConnectionAudioSink; + +// Interface for reference counted holder of audio stream audio track sink. +class MediaStreamAudioTrackSink + : public base::RefCountedThreadSafe<MediaStreamAudioTrackSink> { + public: + virtual int OnData(const int16* audio_data, + int sample_rate, + int number_of_channels, + int number_of_frames, + const std::vector<int>& channels, + int audio_delay_milliseconds, + int current_volume, + bool need_audio_processing, + bool key_pressed) = 0; + + virtual void OnSetFormat(const media::AudioParameters& params) = 0; + + virtual void OnReadyStateChanged( + blink::WebMediaStreamSource::ReadyState state) = 0; + + virtual void Reset() = 0; + + virtual bool IsEqual(const MediaStreamAudioSink* other) const = 0; + virtual bool IsEqual(const PeerConnectionAudioSink* other) const = 0; + + // Wrapper which allows to use std::find_if() when adding and removing + // sinks to/from the list. + struct WrapsMediaStreamSink { + WrapsMediaStreamSink(MediaStreamAudioSink* sink) : sink_(sink) {} + bool operator()( + const scoped_refptr<MediaStreamAudioTrackSink>& owner) const { + return owner->IsEqual(sink_); + } + MediaStreamAudioSink* sink_; + }; + struct WrapsPeerConnectionSink { + WrapsPeerConnectionSink(PeerConnectionAudioSink* sink) : sink_(sink) {} + bool operator()( + const scoped_refptr<MediaStreamAudioTrackSink>& owner) const { + return owner->IsEqual(sink_); + } + PeerConnectionAudioSink* sink_; + }; + + protected: + virtual ~MediaStreamAudioTrackSink() {} + + private: + friend class base::RefCountedThreadSafe<MediaStreamAudioTrackSink>; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_TRACK_SINK_H_ diff --git a/chromium/content/renderer/media/media_stream_center.cc b/chromium/content/renderer/media/media_stream_center.cc index 26f2303d04a..daf1a499507 100644 --- a/chromium/content/renderer/media/media_stream_center.cc +++ b/chromium/content/renderer/media/media_stream_center.cc @@ -16,7 +16,8 @@ #include "content/public/renderer/render_thread.h" #include "content/renderer/media/media_stream_dependency_factory.h" #include "content/renderer/media/media_stream_extra_data.h" -#include "content/renderer/media/media_stream_impl.h" +#include "content/renderer/media/media_stream_source_extra_data.h" +#include "content/renderer/media/media_stream_track_extra_data.h" #include "content/renderer/render_view_impl.h" #include "third_party/WebKit/public/platform/WebMediaStream.h" #include "third_party/WebKit/public/platform/WebMediaStreamCenterClient.h" @@ -28,43 +29,19 @@ #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/libjingle/source/talk/app/webrtc/jsep.h" -using WebKit::WebFrame; -using WebKit::WebView; +using blink::WebFrame; +using blink::WebView; namespace content { -static webrtc::MediaStreamInterface* GetNativeMediaStream( - const WebKit::WebMediaStream& stream) { - MediaStreamExtraData* extra_data = - static_cast<MediaStreamExtraData*>(stream.extraData()); - return extra_data->stream().get(); -} - -static webrtc::MediaStreamTrackInterface* GetNativeMediaStreamTrack( - const WebKit::WebMediaStream& stream, - const WebKit::WebMediaStreamTrack& component) { - std::string track_id = UTF16ToUTF8(component.id()); - webrtc::MediaStreamInterface* native_stream = GetNativeMediaStream(stream); - if (native_stream) { - if (component.source().type() == WebKit::WebMediaStreamSource::TypeAudio) { - return native_stream->FindAudioTrack(track_id); - } - if (component.source().type() == WebKit::WebMediaStreamSource::TypeVideo) { - return native_stream->FindVideoTrack(track_id); - } - } - NOTREACHED(); - return NULL; -} - -MediaStreamCenter::MediaStreamCenter(WebKit::WebMediaStreamCenterClient* client, +MediaStreamCenter::MediaStreamCenter(blink::WebMediaStreamCenterClient* client, MediaStreamDependencyFactory* factory) : rtc_factory_(factory), next_request_id_(0) {} MediaStreamCenter::~MediaStreamCenter() {} bool MediaStreamCenter::getMediaStreamTrackSources( - const WebKit::WebMediaStreamTrackSourcesRequest& request) { + const blink::WebMediaStreamTrackSourcesRequest& request) { if (!CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableDeviceEnumeration)) { int request_id = next_request_id_++; @@ -76,47 +53,83 @@ bool MediaStreamCenter::getMediaStreamTrackSources( return false; } +void MediaStreamCenter::didCreateMediaStreamTrack( + const blink::WebMediaStreamTrack& track) { + if (!rtc_factory_) + return; + rtc_factory_->CreateNativeMediaStreamTrack(track); +} + void MediaStreamCenter::didEnableMediaStreamTrack( - const WebKit::WebMediaStream& stream, - const WebKit::WebMediaStreamTrack& component) { - webrtc::MediaStreamTrackInterface* track = - GetNativeMediaStreamTrack(stream, component); - if (track) - track->set_enabled(true); + const blink::WebMediaStreamTrack& track) { + webrtc::MediaStreamTrackInterface* native_track = + MediaStreamDependencyFactory::GetNativeMediaStreamTrack(track); + if (native_track) + native_track->set_enabled(true); } void MediaStreamCenter::didDisableMediaStreamTrack( - const WebKit::WebMediaStream& stream, - const WebKit::WebMediaStreamTrack& component) { - webrtc::MediaStreamTrackInterface* track = - GetNativeMediaStreamTrack(stream, component); - if (track) - track->set_enabled(false); + const blink::WebMediaStreamTrack& track) { + webrtc::MediaStreamTrackInterface* native_track = + MediaStreamDependencyFactory::GetNativeMediaStreamTrack(track); + if (native_track) + native_track->set_enabled(false); +} + +bool MediaStreamCenter::didStopMediaStreamTrack( + const blink::WebMediaStreamTrack& track) { + DVLOG(1) << "MediaStreamCenter::didStopMediaStreamTrack"; + blink::WebMediaStreamSource source = track.source(); + MediaStreamSourceExtraData* extra_data = + static_cast<MediaStreamSourceExtraData*>(source.extraData()); + if (!extra_data) { + DVLOG(1) << "didStopMediaStreamTrack called on a remote track."; + return false; + } + + extra_data->OnLocalSourceStop(); + return true; } void MediaStreamCenter::didStopLocalMediaStream( - const WebKit::WebMediaStream& stream) { + const blink::WebMediaStream& stream) { DVLOG(1) << "MediaStreamCenter::didStopLocalMediaStream"; MediaStreamExtraData* extra_data = - static_cast<MediaStreamExtraData*>(stream.extraData()); + static_cast<MediaStreamExtraData*>(stream.extraData()); if (!extra_data) { NOTREACHED(); return; } + // TODO(perkj): MediaStream::Stop is being deprecated. But for the moment we + // need to support the old behavior and the new. Since we only create one + // source object per actual device- we need to fake stopping a + // MediaStreamTrack by disabling it if the same device is used as source by + // multiple tracks. Note that disabling a track here, don't affect the + // enabled property in JS. + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; + stream.audioTracks(audio_tracks); + for (size_t i = 0; i < audio_tracks.size(); ++i) + didDisableMediaStreamTrack(audio_tracks[i]); + + blink::WebVector<blink::WebMediaStreamTrack> video_tracks; + stream.videoTracks(video_tracks); + for (size_t i = 0; i < video_tracks.size(); ++i) + didDisableMediaStreamTrack(video_tracks[i]); + extra_data->OnLocalStreamStop(); } void MediaStreamCenter::didCreateMediaStream( - WebKit::WebMediaStream& stream) { + blink::WebMediaStream& stream) { if (!rtc_factory_) return; rtc_factory_->CreateNativeLocalMediaStream(&stream); } bool MediaStreamCenter::didAddMediaStreamTrack( - const WebKit::WebMediaStream& stream, - const WebKit::WebMediaStreamTrack& track) { + const blink::WebMediaStream& stream, + const blink::WebMediaStreamTrack& track) { if (!rtc_factory_) return false; @@ -124,8 +137,8 @@ bool MediaStreamCenter::didAddMediaStreamTrack( } bool MediaStreamCenter::didRemoveMediaStreamTrack( - const WebKit::WebMediaStream& stream, - const WebKit::WebMediaStreamTrack& track) { + const blink::WebMediaStream& stream, + const blink::WebMediaStreamTrack& track) { if (!rtc_factory_) return false; @@ -148,29 +161,29 @@ void MediaStreamCenter::OnGetSourcesComplete( RequestMap::iterator request_it = requests_.find(request_id); DCHECK(request_it != requests_.end()); - WebKit::WebVector<WebKit::WebSourceInfo> sourceInfos(devices.size()); + blink::WebVector<blink::WebSourceInfo> sourceInfos(devices.size()); for (size_t i = 0; i < devices.size(); ++i) { const MediaStreamDevice& device = devices[i].device; DCHECK(device.type == MEDIA_DEVICE_AUDIO_CAPTURE || device.type == MEDIA_DEVICE_VIDEO_CAPTURE); - WebKit::WebSourceInfo::VideoFacingMode video_facing; + blink::WebSourceInfo::VideoFacingMode video_facing; switch (device.video_facing) { case MEDIA_VIDEO_FACING_USER: - video_facing = WebKit::WebSourceInfo::VideoFacingModeUser; + video_facing = blink::WebSourceInfo::VideoFacingModeUser; break; case MEDIA_VIDEO_FACING_ENVIRONMENT: - video_facing = WebKit::WebSourceInfo::VideoFacingModeEnvironment; + video_facing = blink::WebSourceInfo::VideoFacingModeEnvironment; break; default: - video_facing = WebKit::WebSourceInfo::VideoFacingModeNone; + video_facing = blink::WebSourceInfo::VideoFacingModeNone; } sourceInfos[i] - .initialize(WebKit::WebString::fromUTF8(device.id), + .initialize(blink::WebString::fromUTF8(device.id), device.type == MEDIA_DEVICE_AUDIO_CAPTURE - ? WebKit::WebSourceInfo::SourceKindAudio - : WebKit::WebSourceInfo::SourceKindVideo, - WebKit::WebString::fromUTF8(device.name), + ? blink::WebSourceInfo::SourceKindAudio + : blink::WebSourceInfo::SourceKindVideo, + blink::WebString::fromUTF8(device.name), video_facing); } request_it->second.requestSucceeded(sourceInfos); diff --git a/chromium/content/renderer/media/media_stream_center.h b/chromium/content/renderer/media/media_stream_center.h index 83a55f621a2..fbf1be73b55 100644 --- a/chromium/content/renderer/media/media_stream_center.h +++ b/chromium/content/renderer/media/media_stream_center.h @@ -17,7 +17,7 @@ #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" #include "third_party/WebKit/public/platform/WebMediaStreamTrackSourcesRequest.h" -namespace WebKit { +namespace blink { class WebMediaStreamCenterClient; } @@ -25,39 +25,43 @@ namespace content { class MediaStreamDependencyFactory; class CONTENT_EXPORT MediaStreamCenter - : NON_EXPORTED_BASE(public WebKit::WebMediaStreamCenter), + : NON_EXPORTED_BASE(public blink::WebMediaStreamCenter), public RenderProcessObserver { public: - MediaStreamCenter(WebKit::WebMediaStreamCenterClient* client, + MediaStreamCenter(blink::WebMediaStreamCenterClient* client, MediaStreamDependencyFactory* factory); virtual ~MediaStreamCenter(); + private: virtual bool getMediaStreamTrackSources( - const WebKit::WebMediaStreamTrackSourcesRequest& request); + const blink::WebMediaStreamTrackSourcesRequest& request) OVERRIDE; + + virtual void didCreateMediaStreamTrack( + const blink::WebMediaStreamTrack& track) OVERRIDE; virtual void didEnableMediaStreamTrack( - const WebKit::WebMediaStream& stream, - const WebKit::WebMediaStreamTrack& component); + const blink::WebMediaStreamTrack& track) OVERRIDE; virtual void didDisableMediaStreamTrack( - const WebKit::WebMediaStream& stream, - const WebKit::WebMediaStreamTrack& component); + const blink::WebMediaStreamTrack& track) OVERRIDE; virtual void didStopLocalMediaStream( - const WebKit::WebMediaStream& stream); + const blink::WebMediaStream& stream) OVERRIDE; + + virtual bool didStopMediaStreamTrack( + const blink::WebMediaStreamTrack& track) OVERRIDE; virtual void didCreateMediaStream( - WebKit::WebMediaStream& stream); + blink::WebMediaStream& stream) OVERRIDE; virtual bool didAddMediaStreamTrack( - const WebKit::WebMediaStream& stream, - const WebKit::WebMediaStreamTrack& track); + const blink::WebMediaStream& stream, + const blink::WebMediaStreamTrack& track) OVERRIDE; virtual bool didRemoveMediaStreamTrack( - const WebKit::WebMediaStream& stream, - const WebKit::WebMediaStreamTrack& track); + const blink::WebMediaStream& stream, + const blink::WebMediaStreamTrack& track) OVERRIDE; - private: // RenderProcessObserver implementation. virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE; @@ -72,7 +76,7 @@ class CONTENT_EXPORT MediaStreamCenter // requests. int next_request_id_; - typedef std::map<int, WebKit::WebMediaStreamTrackSourcesRequest> RequestMap; + typedef std::map<int, blink::WebMediaStreamTrackSourcesRequest> RequestMap; // Maps request ids to request objects. RequestMap requests_; diff --git a/chromium/content/renderer/media/media_stream_dependency_factory.cc b/chromium/content/renderer/media/media_stream_dependency_factory.cc index 23f68e9fa5e..8da7b14cb71 100644 --- a/chromium/content/renderer/media/media_stream_dependency_factory.cc +++ b/chromium/content/renderer/media/media_stream_dependency_factory.cc @@ -11,6 +11,8 @@ #include "base/synchronization/waitable_event.h" #include "content/public/common/content_switches.h" #include "content/renderer/media/media_stream_source_extra_data.h" +#include "content/renderer/media/media_stream_track_extra_data.h" +#include "content/renderer/media/media_stream_video_track.h" #include "content/renderer/media/peer_connection_identity_service.h" #include "content/renderer/media/rtc_media_constraints.h" #include "content/renderer/media/rtc_peer_connection_handler.h" @@ -21,7 +23,6 @@ #include "content/renderer/media/webaudio_capturer_source.h" #include "content/renderer/media/webrtc_audio_device_impl.h" #include "content/renderer/media/webrtc_local_audio_track.h" -#include "content/renderer/media/webrtc_logging_initializer.h" #include "content/renderer/media/webrtc_uma_histograms.h" #include "content/renderer/p2p/ipc_network_manager.h" #include "content/renderer/p2p/ipc_socket_factory.h" @@ -48,11 +49,11 @@ #include "content/renderer/media/rtc_video_decoder_factory_tv.h" #endif -namespace content { +#if defined(OS_ANDROID) +#include "media/base/android/media_codec_bridge.h" +#endif -// The constraint key for the PeerConnection constructor for enabling diagnostic -// WebRTC logging. It's a Google specific key, hence the "goog" prefix. -const char kWebRtcLoggingConstraint[] = "googLog"; +namespace content { // Constant constraint keys which enables default audio constraints on // mediastreams with audio. @@ -62,6 +63,11 @@ struct { } const kDefaultAudioConstraints[] = { { webrtc::MediaConstraintsInterface::kEchoCancellation, webrtc::MediaConstraintsInterface::kValueTrue }, +#if defined(OS_CHROMEOS) || defined(OS_MACOSX) + // Enable the extended filter mode AEC on platforms with known echo issues. + { webrtc::MediaConstraintsInterface::kExperimentalEchoCancellation, + webrtc::MediaConstraintsInterface::kValueTrue }, +#endif { webrtc::MediaConstraintsInterface::kAutoGainControl, webrtc::MediaConstraintsInterface::kValueTrue }, { webrtc::MediaConstraintsInterface::kExperimentalAutoGainControl, @@ -72,6 +78,15 @@ struct { webrtc::MediaConstraintsInterface::kValueTrue }, }; +// Map of corresponding media constraints and platform effects. +struct { + const char* constraint; + const media::AudioParameters::PlatformEffectsMask effect; +} const kConstraintEffectMap[] = { + { webrtc::MediaConstraintsInterface::kEchoCancellation, + media::AudioParameters::ECHO_CANCELLER}, +}; + // Merge |constraints| with |kDefaultAudioConstraints|. For any key which exists // in both, the value from |constraints| is maintained, including its // mandatory/optional status. New values from |kDefaultAudioConstraints| will @@ -96,7 +111,7 @@ class P2PPortAllocatorFactory : public webrtc::PortAllocatorFactoryInterface { P2PSocketDispatcher* socket_dispatcher, talk_base::NetworkManager* network_manager, talk_base::PacketSocketFactory* socket_factory, - WebKit::WebFrame* web_frame) + blink::WebFrame* web_frame) : socket_dispatcher_(socket_dispatcher), network_manager_(network_manager), socket_factory_(socket_factory), @@ -145,14 +160,14 @@ class P2PPortAllocatorFactory : public webrtc::PortAllocatorFactoryInterface { talk_base::NetworkManager* network_manager_; talk_base::PacketSocketFactory* socket_factory_; // Raw ptr to the WebFrame that created the P2PPortAllocatorFactory. - WebKit::WebFrame* web_frame_; + blink::WebFrame* web_frame_; }; // SourceStateObserver is a help class used for observing the startup state // transition of webrtc media sources such as a camera or microphone. // An instance of the object deletes itself after use. // Usage: -// 1. Create an instance of the object with the WebKit::WebMediaStream +// 1. Create an instance of the object with the blink::WebMediaStream // the observed sources belongs to a callback. // 2. Add the sources to the observer using AddSource. // 3. Call StartObserving() @@ -162,7 +177,7 @@ class SourceStateObserver : public webrtc::ObserverInterface, public base::NonThreadSafe { public: SourceStateObserver( - WebKit::WebMediaStream* web_stream, + blink::WebMediaStream* web_stream, const MediaStreamDependencyFactory::MediaSourcesCreatedCallback& callback) : web_stream_(web_stream), ready_callback_(callback), @@ -216,7 +231,7 @@ class SourceStateObserver : public webrtc::ObserverInterface, } } - WebKit::WebMediaStream* web_stream_; + blink::WebMediaStream* web_stream_; MediaStreamDependencyFactory::MediaSourcesCreatedCallback ready_callback_; bool live_; typedef std::vector<scoped_refptr<webrtc::MediaSourceInterface> > @@ -242,9 +257,9 @@ MediaStreamDependencyFactory::~MediaStreamDependencyFactory() { CleanupPeerConnectionFactory(); } -WebKit::WebRTCPeerConnectionHandler* +blink::WebRTCPeerConnectionHandler* MediaStreamDependencyFactory::CreateRTCPeerConnectionHandler( - WebKit::WebRTCPeerConnectionHandlerClient* client) { + blink::WebRTCPeerConnectionHandlerClient* client) { // Save histogram data so we can see how much PeerConnetion is used. // The histogram counts the number of calls to the JS API // webKitRTCPeerConnection. @@ -258,9 +273,9 @@ MediaStreamDependencyFactory::CreateRTCPeerConnectionHandler( void MediaStreamDependencyFactory::CreateNativeMediaSources( int render_view_id, - const WebKit::WebMediaConstraints& audio_constraints, - const WebKit::WebMediaConstraints& video_constraints, - WebKit::WebMediaStream* web_stream, + const blink::WebMediaConstraints& audio_constraints, + const blink::WebMediaConstraints& video_constraints, + blink::WebMediaStream* web_stream, const MediaSourcesCreatedCallback& sources_created) { DVLOG(1) << "MediaStreamDependencyFactory::CreateNativeMediaSources()"; if (!EnsurePeerConnectionFactory()) { @@ -275,17 +290,19 @@ void MediaStreamDependencyFactory::CreateNativeMediaSources( // Create local video sources. RTCMediaConstraints native_video_constraints(video_constraints); - WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks; + blink::WebVector<blink::WebMediaStreamTrack> video_tracks; web_stream->videoTracks(video_tracks); for (size_t i = 0; i < video_tracks.size(); ++i) { - const WebKit::WebMediaStreamSource& source = video_tracks[i].source(); + const blink::WebMediaStreamSource& source = video_tracks[i].source(); MediaStreamSourceExtraData* source_data = static_cast<MediaStreamSourceExtraData*>(source.extraData()); - if (!source_data) { - // TODO(perkj): Implement support for sources from remote MediaStreams. - NOTIMPLEMENTED(); + + // Check if the source has already been created. This happens when the same + // source is used in multiple MediaStreams as a result of calling + // getUserMedia. + if (source_data->video_source()) continue; - } + const bool is_screencast = source_data->device_info().device.type == MEDIA_TAB_VIDEO_CAPTURE || source_data->device_info().device.type == MEDIA_DESKTOP_VIDEO_CAPTURE; @@ -300,26 +317,51 @@ void MediaStreamDependencyFactory::CreateNativeMediaSources( // microphone or tab audio. RTCMediaConstraints native_audio_constraints(audio_constraints); ApplyFixedAudioConstraints(&native_audio_constraints); - WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks; + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; web_stream->audioTracks(audio_tracks); - const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - if (command_line.HasSwitch(switches::kEnableWebRtcAecRecordings)) { - native_audio_constraints.AddOptional( - RTCMediaConstraints::kInternalAecDump, "true"); - } for (size_t i = 0; i < audio_tracks.size(); ++i) { - const WebKit::WebMediaStreamSource& source = audio_tracks[i].source(); + const blink::WebMediaStreamSource& source = audio_tracks[i].source(); MediaStreamSourceExtraData* source_data = static_cast<MediaStreamSourceExtraData*>(source.extraData()); - if (!source_data) { - // TODO(henrika): Implement support for sources from remote MediaStreams. - NOTIMPLEMENTED(); + + // Check if the source has already been created. This happens when the same + // source is used in multiple MediaStreams as a result of calling + // getUserMedia. + if (source_data->local_audio_source()) continue; - } // TODO(xians): Create a new capturer for difference microphones when we // support multiple microphones. See issue crbug/262117 . - const StreamDeviceInfo device_info = source_data->device_info(); + StreamDeviceInfo device_info = source_data->device_info(); + RTCMediaConstraints constraints = native_audio_constraints; + + // If any platform effects are available, check them against the + // constraints. Disable effects to match false constraints, but if a + // constraint is true, set the constraint to false to later disable the + // software effect. + int effects = device_info.device.input.effects; + if (effects != media::AudioParameters::NO_EFFECTS) { + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kConstraintEffectMap); ++i) { + bool value; + if (!webrtc::FindConstraint(&constraints, + kConstraintEffectMap[i].constraint, &value, NULL) || !value) { + // If the constraint is false, or does not exist, disable the platform + // effect. + effects &= ~kConstraintEffectMap[i].effect; + DVLOG(1) << "Disabling constraint: " + << kConstraintEffectMap[i].constraint; + } else if (effects & kConstraintEffectMap[i].effect) { + // If the constraint is true, leave the platform effect enabled, and + // set the constraint to false to later disable the software effect. + constraints.AddMandatory(kConstraintEffectMap[i].constraint, + webrtc::MediaConstraintsInterface::kValueFalse, true); + DVLOG(1) << "Disabling platform effect: " + << kConstraintEffectMap[i].constraint; + } + } + device_info.device.input.effects = effects; + } + scoped_refptr<WebRtcAudioCapturer> capturer( MaybeCreateAudioCapturer(render_view_id, device_info)); if (!capturer.get()) { @@ -332,11 +374,12 @@ void MediaStreamDependencyFactory::CreateNativeMediaSources( // be called multiple times which is likely also a bug. return; } + source_data->SetAudioCapturer(capturer); // Creates a LocalAudioSource object which holds audio options. // TODO(xians): The option should apply to the track instead of the source. source_data->SetLocalAudioSource( - CreateLocalAudioSource(&native_audio_constraints).get()); + CreateLocalAudioSource(&constraints).get()); source_observer->AddSource(source_data->local_audio_source()); } @@ -344,7 +387,7 @@ void MediaStreamDependencyFactory::CreateNativeMediaSources( } void MediaStreamDependencyFactory::CreateNativeLocalMediaStream( - WebKit::WebMediaStream* web_stream) { + blink::WebMediaStream* web_stream) { DVLOG(1) << "MediaStreamDependencyFactory::CreateNativeLocalMediaStream()"; if (!EnsurePeerConnectionFactory()) { DVLOG(1) << "EnsurePeerConnectionFactory() failed!"; @@ -359,14 +402,14 @@ void MediaStreamDependencyFactory::CreateNativeLocalMediaStream( web_stream->setExtraData(extra_data); // Add audio tracks. - WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks; + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; web_stream->audioTracks(audio_tracks); for (size_t i = 0; i < audio_tracks.size(); ++i) { AddNativeMediaStreamTrack(*web_stream, audio_tracks[i]); } // Add video tracks. - WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks; + blink::WebVector<blink::WebMediaStreamTrack> video_tracks; web_stream->videoTracks(video_tracks); for (size_t i = 0; i < video_tracks.size(); ++i) { AddNativeMediaStreamTrack(*web_stream, video_tracks[i]); @@ -374,7 +417,7 @@ void MediaStreamDependencyFactory::CreateNativeLocalMediaStream( } void MediaStreamDependencyFactory::CreateNativeLocalMediaStream( - WebKit::WebMediaStream* web_stream, + blink::WebMediaStream* web_stream, const MediaStreamExtraData::StreamStopCallback& stream_stop) { CreateNativeLocalMediaStream(web_stream); @@ -383,15 +426,11 @@ void MediaStreamDependencyFactory::CreateNativeLocalMediaStream( extra_data->SetLocalStreamStopCallback(stream_stop); } -bool MediaStreamDependencyFactory::AddNativeMediaStreamTrack( - const WebKit::WebMediaStream& stream, - const WebKit::WebMediaStreamTrack& track) { - MediaStreamExtraData* extra_data = - static_cast<MediaStreamExtraData*>(stream.extraData()); - webrtc::MediaStreamInterface* native_stream = extra_data->stream().get(); - DCHECK(native_stream); - - WebKit::WebMediaStreamSource source = track.source(); +scoped_refptr<webrtc::AudioTrackInterface> +MediaStreamDependencyFactory::CreateNativeAudioMediaStreamTrack( + const blink::WebMediaStreamTrack& track) { + blink::WebMediaStreamSource source = track.source(); + DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeAudio); MediaStreamSourceExtraData* source_data = static_cast<MediaStreamSourceExtraData*>(source.extraData()); @@ -399,15 +438,9 @@ bool MediaStreamDependencyFactory::AddNativeMediaStreamTrack( // right now they're on the source, so we fetch them from there. RTCMediaConstraints track_constraints(source.constraints()); - WebKit::WebMediaStreamSource::Type type = track.source().type(); - DCHECK(type == WebKit::WebMediaStreamSource::TypeAudio || - type == WebKit::WebMediaStreamSource::TypeVideo); - - if (type == WebKit::WebMediaStreamSource::TypeAudio) { - // Apply default audio constraints that enable echo cancellation, - // automatic gain control, noise suppression and high-pass filter. - ApplyFixedAudioConstraints(&track_constraints); - } + // Apply default audio constraints that enable echo cancellation, + // automatic gain control, noise suppression and high-pass filter. + ApplyFixedAudioConstraints(&track_constraints); scoped_refptr<WebAudioCapturerSource> webaudio_source; if (!source_data) { @@ -421,40 +454,111 @@ bool MediaStreamDependencyFactory::AddNativeMediaStreamTrack( // TODO(perkj): Implement support for sources from // remote MediaStreams. NOTIMPLEMENTED(); - return false; + return NULL; } } std::string track_id = UTF16ToUTF8(track.id()); - if (source.type() == WebKit::WebMediaStreamSource::TypeAudio) { - scoped_refptr<WebRtcAudioCapturer> capturer; - if (GetWebRtcAudioDevice()) - capturer = GetWebRtcAudioDevice()->GetDefaultCapturer(); - - scoped_refptr<webrtc::AudioTrackInterface> audio_track( - CreateLocalAudioTrack(track_id, - capturer, - webaudio_source.get(), - source_data->local_audio_source(), - &track_constraints)); - audio_track->set_enabled(track.isEnabled()); - if (capturer.get()) { - WebKit::WebMediaStreamTrack writable_track = track; - writable_track.setSourceProvider(capturer->audio_source_provider()); + scoped_refptr<WebRtcAudioCapturer> capturer; + if (GetWebRtcAudioDevice()) + capturer = GetWebRtcAudioDevice()->GetDefaultCapturer(); + + scoped_refptr<webrtc::AudioTrackInterface> audio_track( + CreateLocalAudioTrack(track_id, + capturer, + webaudio_source.get(), + source_data->local_audio_source(), + &track_constraints)); + AddNativeTrackToBlinkTrack(audio_track.get(), track, true); + + audio_track->set_enabled(track.isEnabled()); + + // Pass the pointer of the source provider to the blink audio track. + blink::WebMediaStreamTrack writable_track = track; + writable_track.setSourceProvider(static_cast<WebRtcLocalAudioTrack*>( + audio_track.get())->audio_source_provider()); + + return audio_track; +} + +scoped_refptr<webrtc::VideoTrackInterface> +MediaStreamDependencyFactory::CreateNativeVideoMediaStreamTrack( + const blink::WebMediaStreamTrack& track) { + blink::WebMediaStreamSource source = track.source(); + DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeVideo); + MediaStreamSourceExtraData* source_data = + static_cast<MediaStreamSourceExtraData*>(source.extraData()); + + if (!source_data) { + // TODO(perkj): Implement support for sources from + // remote MediaStreams. + NOTIMPLEMENTED(); + return NULL; + } + + std::string track_id = UTF16ToUTF8(track.id()); + scoped_refptr<webrtc::VideoTrackInterface> video_track( + CreateLocalVideoTrack(track_id, source_data->video_source())); + AddNativeTrackToBlinkTrack(video_track.get(), track, true); + + video_track->set_enabled(track.isEnabled()); + + return video_track; +} + +void MediaStreamDependencyFactory::CreateNativeMediaStreamTrack( + const blink::WebMediaStreamTrack& track) { + DCHECK(!track.isNull() && !track.extraData()); + DCHECK(!track.source().isNull()); + + switch (track.source().type()) { + case blink::WebMediaStreamSource::TypeAudio: + CreateNativeAudioMediaStreamTrack(track); + break; + case blink::WebMediaStreamSource::TypeVideo: + CreateNativeVideoMediaStreamTrack(track); + break; + } +} + +bool MediaStreamDependencyFactory::AddNativeMediaStreamTrack( + const blink::WebMediaStream& stream, + const blink::WebMediaStreamTrack& track) { + webrtc::MediaStreamInterface* native_stream = GetNativeMediaStream(stream); + DCHECK(native_stream); + + switch (track.source().type()) { + case blink::WebMediaStreamSource::TypeAudio: { + scoped_refptr<webrtc::AudioTrackInterface> native_audio_track; + if (!track.extraData()) { + native_audio_track = CreateNativeAudioMediaStreamTrack(track); + } else { + native_audio_track = static_cast<webrtc::AudioTrackInterface*>( + GetNativeMediaStreamTrack(track)); + } + + return native_audio_track.get() && + native_stream->AddTrack(native_audio_track); + } + case blink::WebMediaStreamSource::TypeVideo: { + scoped_refptr<webrtc::VideoTrackInterface> native_video_track; + if (!track.extraData()) { + native_video_track = CreateNativeVideoMediaStreamTrack(track); + } else { + native_video_track = static_cast<webrtc::VideoTrackInterface*>( + GetNativeMediaStreamTrack(track)); + } + + return native_video_track.get() && + native_stream->AddTrack(native_video_track); } - return native_stream->AddTrack(audio_track.get()); - } else { - DCHECK(source.type() == WebKit::WebMediaStreamSource::TypeVideo); - scoped_refptr<webrtc::VideoTrackInterface> video_track( - CreateLocalVideoTrack(track_id, source_data->video_source())); - video_track->set_enabled(track.isEnabled()); - return native_stream->AddTrack(video_track.get()); } + return false; } bool MediaStreamDependencyFactory::AddNativeVideoMediaTrack( const std::string& track_id, - WebKit::WebMediaStream* stream, + blink::WebMediaStream* stream, cricket::VideoCapturer* capturer) { if (!stream) { LOG(ERROR) << "AddNativeVideoMediaTrack called with null WebMediaStream."; @@ -466,20 +570,21 @@ bool MediaStreamDependencyFactory::AddNativeVideoMediaTrack( CreateLocalVideoTrack(track_id, capturer); // Add the native track to native stream - MediaStreamExtraData* extra_data = - static_cast<MediaStreamExtraData*>(stream->extraData()); - DCHECK(extra_data); - webrtc::MediaStreamInterface* native_stream = extra_data->stream().get(); + webrtc::MediaStreamInterface* native_stream = + GetNativeMediaStream(*stream); + DCHECK(native_stream); native_stream->AddTrack(native_track.get()); // Create a new webkit video track. - WebKit::WebMediaStreamTrack webkit_track; - WebKit::WebMediaStreamSource webkit_source; - WebKit::WebString webkit_track_id(UTF8ToUTF16(track_id)); - WebKit::WebMediaStreamSource::Type type = - WebKit::WebMediaStreamSource::TypeVideo; + blink::WebMediaStreamTrack webkit_track; + blink::WebMediaStreamSource webkit_source; + blink::WebString webkit_track_id(UTF8ToUTF16(track_id)); + blink::WebMediaStreamSource::Type type = + blink::WebMediaStreamSource::TypeVideo; webkit_source.initialize(webkit_track_id, type, webkit_track_id); + webkit_track.initialize(webkit_track_id, webkit_source); + AddNativeTrackToBlinkTrack(native_track.get(), webkit_track, true); // Add the track to WebMediaStream. stream->addTrack(webkit_track); @@ -487,71 +592,82 @@ bool MediaStreamDependencyFactory::AddNativeVideoMediaTrack( } bool MediaStreamDependencyFactory::RemoveNativeMediaStreamTrack( - const WebKit::WebMediaStream& stream, - const WebKit::WebMediaStreamTrack& track) { + const blink::WebMediaStream& stream, + const blink::WebMediaStreamTrack& track) { MediaStreamExtraData* extra_data = static_cast<MediaStreamExtraData*>(stream.extraData()); webrtc::MediaStreamInterface* native_stream = extra_data->stream().get(); DCHECK(native_stream); - - WebKit::WebMediaStreamSource::Type type = track.source().type(); - DCHECK(type == WebKit::WebMediaStreamSource::TypeAudio || - type == WebKit::WebMediaStreamSource::TypeVideo); - std::string track_id = UTF16ToUTF8(track.id()); - if (type == WebKit::WebMediaStreamSource::TypeAudio) { - // Remove the source provider as the track is going away. - WebKit::WebMediaStreamTrack writable_track = track; - writable_track.setSourceProvider(NULL); - return native_stream->RemoveTrack(native_stream->FindAudioTrack(track_id)); - } - - CHECK_EQ(type, WebKit::WebMediaStreamSource::TypeVideo); - return native_stream->RemoveTrack(native_stream->FindVideoTrack(track_id)); + switch (track.source().type()) { + case blink::WebMediaStreamSource::TypeAudio: + return native_stream->RemoveTrack( + native_stream->FindAudioTrack(track_id)); + case blink::WebMediaStreamSource::TypeVideo: + return native_stream->RemoveTrack( + native_stream->FindVideoTrack(track_id)); + } + return false; } bool MediaStreamDependencyFactory::CreatePeerConnectionFactory() { + DCHECK(!pc_factory_.get()); + DCHECK(!audio_device_.get()); DVLOG(1) << "MediaStreamDependencyFactory::CreatePeerConnectionFactory()"; - if (!pc_factory_.get()) { - DCHECK(!audio_device_.get()); - audio_device_ = new WebRtcAudioDeviceImpl(); - - scoped_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory; - scoped_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory; - - const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); - scoped_refptr<base::MessageLoopProxy> media_loop_proxy = - RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy(); - scoped_refptr<RendererGpuVideoAcceleratorFactories> gpu_factories = - RenderThreadImpl::current()->GetGpuFactories(media_loop_proxy); + + scoped_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory; + scoped_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory; + + const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); + scoped_refptr<RendererGpuVideoAcceleratorFactories> gpu_factories = + RenderThreadImpl::current()->GetGpuFactories(); #if !defined(GOOGLE_TV) - if (!cmd_line->HasSwitch(switches::kDisableWebRtcHWDecoding)) { - if (gpu_factories) - decoder_factory.reset(new RTCVideoDecoderFactory(gpu_factories)); - } + if (!cmd_line->HasSwitch(switches::kDisableWebRtcHWDecoding)) { + if (gpu_factories) + decoder_factory.reset(new RTCVideoDecoderFactory(gpu_factories)); + } #else - // PeerConnectionFactory will hold the ownership of this - // VideoDecoderFactory. - decoder_factory.reset(decoder_factory_tv_ = new RTCVideoDecoderFactoryTv()); + // PeerConnectionFactory will hold the ownership of this + // VideoDecoderFactory. + decoder_factory.reset(decoder_factory_tv_ = new RTCVideoDecoderFactoryTv()); #endif - if (!cmd_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) { - if (gpu_factories) - encoder_factory.reset(new RTCVideoEncoderFactory(gpu_factories)); - } + if (!cmd_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) { + if (gpu_factories) + encoder_factory.reset(new RTCVideoEncoderFactory(gpu_factories)); + } - scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory( - webrtc::CreatePeerConnectionFactory(worker_thread_, - signaling_thread_, - audio_device_.get(), - encoder_factory.release(), - decoder_factory.release())); - if (factory.get()) - pc_factory_ = factory; - else - audio_device_ = NULL; +#if defined(OS_ANDROID) + if (!media::MediaCodecBridge::IsAvailable() || + !media::MediaCodecBridge::SupportsSetParameters()) { + encoder_factory.reset(); } - return pc_factory_.get() != NULL; +#endif + + scoped_refptr<WebRtcAudioDeviceImpl> audio_device( + new WebRtcAudioDeviceImpl()); + + scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory( + webrtc::CreatePeerConnectionFactory(worker_thread_, + signaling_thread_, + audio_device.get(), + encoder_factory.release(), + decoder_factory.release())); + if (!factory.get()) { + return false; + } + + audio_device_ = audio_device; + pc_factory_ = factory; + webrtc::PeerConnectionFactoryInterface::Options factory_options; + factory_options.enable_aec_dump = + cmd_line->HasSwitch(switches::kEnableWebRtcAecRecordings); + factory_options.disable_sctp_data_channels = + cmd_line->HasSwitch(switches::kDisableSCTPDataChannels); + factory_options.disable_encryption = + cmd_line->HasSwitch(switches::kDisableWebRtcEncryption); + pc_factory_->SetOptions(factory_options); + return true; } bool MediaStreamDependencyFactory::PeerConnectionFactoryCreated() { @@ -562,24 +678,11 @@ scoped_refptr<webrtc::PeerConnectionInterface> MediaStreamDependencyFactory::CreatePeerConnection( const webrtc::PeerConnectionInterface::IceServers& ice_servers, const webrtc::MediaConstraintsInterface* constraints, - WebKit::WebFrame* web_frame, + blink::WebFrame* web_frame, webrtc::PeerConnectionObserver* observer) { CHECK(web_frame); CHECK(observer); - webrtc::MediaConstraintsInterface::Constraints optional_constraints = - constraints->GetOptional(); - std::string constraint_value; - if (optional_constraints.FindFirst(kWebRtcLoggingConstraint, - &constraint_value)) { - std::string url = web_frame->document().url().spec(); - RenderThreadImpl::current()->GetIOMessageLoopProxy()->PostTask( - FROM_HERE, base::Bind( - &InitWebRtcLogging, - constraint_value, - url)); - } - scoped_refptr<P2PPortAllocatorFactory> pa_factory = new talk_base::RefCountedObject<P2PPortAllocatorFactory>( p2p_socket_dispatcher_.get(), @@ -588,7 +691,7 @@ MediaStreamDependencyFactory::CreatePeerConnection( web_frame); PeerConnectionIdentityService* identity_service = - PeerConnectionIdentityService::Create( + new PeerConnectionIdentityService( GURL(web_frame->document().url().spec()).GetOrigin()); return pc_factory_->CreatePeerConnection(ice_servers, @@ -628,7 +731,7 @@ MediaStreamDependencyFactory::CreateLocalVideoSource( scoped_refptr<WebAudioCapturerSource> MediaStreamDependencyFactory::CreateWebAudioSource( - WebKit::WebMediaStreamSource* source, + blink::WebMediaStreamSource* source, RTCMediaConstraints* constraints) { DVLOG(1) << "MediaStreamDependencyFactory::CreateWebAudioSource()"; DCHECK(GetWebRtcAudioDevice()); @@ -843,7 +946,10 @@ MediaStreamDependencyFactory::MaybeCreateAudioCapturer( device_info.device.input.sample_rate, device_info.device.input.frames_per_buffer, device_info.session_id, - device_info.device.id)) { + device_info.device.id, + device_info.device.matched_output.sample_rate, + device_info.device.matched_output.frames_per_buffer, + device_info.device.input.effects)) { return NULL; } @@ -854,4 +960,41 @@ MediaStreamDependencyFactory::MaybeCreateAudioCapturer( return capturer; } +void MediaStreamDependencyFactory::AddNativeTrackToBlinkTrack( + webrtc::MediaStreamTrackInterface* native_track, + const blink::WebMediaStreamTrack& webkit_track, + bool is_local_track) { + DCHECK(!webkit_track.isNull() && !webkit_track.extraData()); + blink::WebMediaStreamTrack track = webkit_track; + + if (track.source().type() == blink::WebMediaStreamSource::TypeVideo) { + track.setExtraData(new MediaStreamVideoTrack( + static_cast<webrtc::VideoTrackInterface*>(native_track), + is_local_track)); + } else { + track.setExtraData(new MediaStreamTrackExtraData(native_track, + is_local_track)); + } +} + +webrtc::MediaStreamInterface* +MediaStreamDependencyFactory::GetNativeMediaStream( + const blink::WebMediaStream& stream) { + if (stream.isNull()) + return NULL; + MediaStreamExtraData* extra_data = + static_cast<MediaStreamExtraData*>(stream.extraData()); + return extra_data ? extra_data->stream().get() : NULL; +} + +webrtc::MediaStreamTrackInterface* +MediaStreamDependencyFactory::GetNativeMediaStreamTrack( + const blink::WebMediaStreamTrack& track) { + if (track.isNull()) + return NULL; + MediaStreamTrackExtraData* extra_data = + static_cast<MediaStreamTrackExtraData*>(track.extraData()); + return extra_data ? extra_data->track().get() : NULL; +} + } // namespace content diff --git a/chromium/content/renderer/media/media_stream_dependency_factory.h b/chromium/content/renderer/media/media_stream_dependency_factory.h index a728d885041..d0759708b8f 100644 --- a/chromium/content/renderer/media/media_stream_dependency_factory.h +++ b/chromium/content/renderer/media/media_stream_dependency_factory.h @@ -30,7 +30,7 @@ namespace webrtc { class PeerConnection; } -namespace WebKit { +namespace blink { class WebFrame; class WebMediaConstraints; class WebMediaStream; @@ -60,7 +60,7 @@ class CONTENT_EXPORT MediaStreamDependencyFactory : NON_EXPORTED_BASE(public base::NonThreadSafe) { public: // MediaSourcesCreatedCallback is used in CreateNativeMediaSources. - typedef base::Callback<void(WebKit::WebMediaStream* web_stream, + typedef base::Callback<void(blink::WebMediaStream* web_stream, bool live)> MediaSourcesCreatedCallback; MediaStreamDependencyFactory( VideoCaptureImplManager* vc_manager, @@ -69,8 +69,8 @@ class CONTENT_EXPORT MediaStreamDependencyFactory // Create a RTCPeerConnectionHandler object that implements the // WebKit WebRTCPeerConnectionHandler interface. - WebKit::WebRTCPeerConnectionHandler* CreateRTCPeerConnectionHandler( - WebKit::WebRTCPeerConnectionHandlerClient* client); + blink::WebRTCPeerConnectionHandler* CreateRTCPeerConnectionHandler( + blink::WebRTCPeerConnectionHandlerClient* client); // CreateNativeMediaSources creates libjingle representations of // the underlying sources to the tracks in |web_stream|. @@ -81,37 +81,41 @@ class CONTENT_EXPORT MediaStreamDependencyFactory // |audio_constraints| and |video_constraints| set parameters for the sources. void CreateNativeMediaSources( int render_view_id, - const WebKit::WebMediaConstraints& audio_constraints, - const WebKit::WebMediaConstraints& video_constraints, - WebKit::WebMediaStream* web_stream, + const blink::WebMediaConstraints& audio_constraints, + const blink::WebMediaConstraints& video_constraints, + blink::WebMediaStream* web_stream, const MediaSourcesCreatedCallback& sources_created); // Creates a libjingle representation of a MediaStream and stores // it in the extra data field of |web_stream|. void CreateNativeLocalMediaStream( - WebKit::WebMediaStream* web_stream); + blink::WebMediaStream* web_stream); // Creates a libjingle representation of a MediaStream and stores // it in the extra data field of |web_stream|. // |stream_stopped| is a callback that is run when a MediaStream have been // stopped. void CreateNativeLocalMediaStream( - WebKit::WebMediaStream* web_stream, + blink::WebMediaStream* web_stream, const MediaStreamExtraData::StreamStopCallback& stream_stop); + // Creates a libjingle representation of a MediaStreamTrack and stores + // it in the extra data field of |track|. + void CreateNativeMediaStreamTrack(const blink::WebMediaStreamTrack& track); + // Adds a libjingle representation of a MediaStreamTrack to |stream| based // on the source of |track|. - bool AddNativeMediaStreamTrack(const WebKit::WebMediaStream& stream, - const WebKit::WebMediaStreamTrack& track); + bool AddNativeMediaStreamTrack(const blink::WebMediaStream& stream, + const blink::WebMediaStreamTrack& track); // Creates and adds libjingle representation of a MediaStreamTrack to |stream| // based on the desired |track_id| and |capturer|. bool AddNativeVideoMediaTrack(const std::string& track_id, - WebKit::WebMediaStream* stream, + blink::WebMediaStream* stream, cricket::VideoCapturer* capturer); - bool RemoveNativeMediaStreamTrack(const WebKit::WebMediaStream& stream, - const WebKit::WebMediaStreamTrack& track); + bool RemoveNativeMediaStreamTrack(const blink::WebMediaStream& stream, + const blink::WebMediaStreamTrack& track); // Asks the libjingle PeerConnection factory to create a libjingle // PeerConnection object. @@ -120,7 +124,7 @@ class CONTENT_EXPORT MediaStreamDependencyFactory CreatePeerConnection( const webrtc::PeerConnectionInterface::IceServers& ice_servers, const webrtc::MediaConstraintsInterface* constraints, - WebKit::WebFrame* web_frame, + blink::WebFrame* web_frame, webrtc::PeerConnectionObserver* observer); // Creates a libjingle representation of a Session description. Used by a @@ -142,6 +146,17 @@ class CONTENT_EXPORT MediaStreamDependencyFactory RTCVideoDecoderFactoryTv* decoder_factory_tv() { return decoder_factory_tv_; } #endif + static void AddNativeTrackToBlinkTrack( + webrtc::MediaStreamTrackInterface* native_track, + const blink::WebMediaStreamTrack& webkit_track, + bool is_local_track); + + static webrtc::MediaStreamInterface* GetNativeMediaStream( + const blink::WebMediaStream& stream); + + static webrtc::MediaStreamTrackInterface* GetNativeMediaStreamTrack( + const blink::WebMediaStreamTrack& track); + protected: // Asks the PeerConnection factory to create a Local MediaStream object. virtual scoped_refptr<webrtc::MediaStreamInterface> @@ -166,7 +181,7 @@ class CONTENT_EXPORT MediaStreamDependencyFactory // The |constraints| will be modified to include the default, mandatory // WebAudio constraints. virtual scoped_refptr<WebAudioCapturerSource> CreateWebAudioSource( - WebKit::WebMediaStreamSource* source, RTCMediaConstraints* constraints); + blink::WebMediaStreamSource* source, RTCMediaConstraints* constraints); // Asks the PeerConnection factory to create a Local AudioTrack object. virtual scoped_refptr<webrtc::AudioTrackInterface> @@ -209,9 +224,11 @@ class CONTENT_EXPORT MediaStreamDependencyFactory void DeleteIpcNetworkManager(); void CleanupPeerConnectionFactory(); - void CreateWebRtcLoggingHandler(WebRtcLoggingMessageFilter* filter, - const std::string& app_session_id, - const std::string& app_url); + scoped_refptr<webrtc::AudioTrackInterface> + CreateNativeAudioMediaStreamTrack(const blink::WebMediaStreamTrack& track); + + scoped_refptr<webrtc::VideoTrackInterface> + CreateNativeVideoMediaStreamTrack(const blink::WebMediaStreamTrack& track); // We own network_manager_, must be deleted on the worker thread. // The network manager uses |p2p_socket_dispatcher_|. diff --git a/chromium/content/renderer/media/media_stream_dependency_factory_unittest.cc b/chromium/content/renderer/media/media_stream_dependency_factory_unittest.cc index 8cc562c07e0..352fa6ea0ee 100644 --- a/chromium/content/renderer/media/media_stream_dependency_factory_unittest.cc +++ b/chromium/content/renderer/media/media_stream_dependency_factory_unittest.cc @@ -27,20 +27,20 @@ class MediaSourceCreatedObserver { } void OnCreateNativeSourcesComplete( - WebKit::WebMediaStream* description, + blink::WebMediaStream* description, bool request_succeeded) { result_ = request_succeeded; description_ = description; } - WebKit::WebMediaStream* description() const { + blink::WebMediaStream* description() const { return description_; } bool result() const { return result_; } private: bool result_; - WebKit::WebMediaStream* description_; + blink::WebMediaStream* description_; }; class MediaStreamDependencyFactoryTest : public ::testing::Test { @@ -49,21 +49,12 @@ class MediaStreamDependencyFactoryTest : public ::testing::Test { dependency_factory_.reset(new MockMediaStreamDependencyFactory()); } - virtual void TearDown() OVERRIDE { - // TODO(tommyw): Remove this once WebKit::MediaStreamSource::Owner has been - // implemented to fully avoid a circular dependency. - for (size_t i = 0; i < audio_sources_.size(); ++i) - audio_sources_[i].setExtraData(NULL); - - for (size_t i = 0; i < video_sources_.size(); ++i) - video_sources_[i].setExtraData(NULL); - } - - WebKit::WebMediaStream CreateWebKitMediaStream(bool audio, bool video) { - WebKit::WebVector<WebKit::WebMediaStreamSource> audio_sources( + blink::WebMediaStream CreateWebKitMediaStream(bool audio, bool video) { + blink::WebVector<blink::WebMediaStreamSource> audio_sources( audio ? static_cast<size_t>(1) : 0); - WebKit::WebVector<WebKit::WebMediaStreamSource> video_sources( + blink::WebVector<blink::WebMediaStreamSource> video_sources( video ? static_cast<size_t>(1) : 0); + MediaStreamSourceExtraData::SourceStopCallback dummy_callback; if (audio) { StreamDeviceInfo info; @@ -71,10 +62,10 @@ class MediaStreamDependencyFactoryTest : public ::testing::Test { info.device.name = "audio"; info.session_id = 99; audio_sources[0].initialize("audio", - WebKit::WebMediaStreamSource::TypeAudio, + blink::WebMediaStreamSource::TypeAudio, "audio"); audio_sources[0].setExtraData( - new MediaStreamSourceExtraData(info, audio_sources[0])); + new MediaStreamSourceExtraData(info, dummy_callback)); audio_sources_.assign(audio_sources); } if (video) { @@ -83,21 +74,21 @@ class MediaStreamDependencyFactoryTest : public ::testing::Test { info.device.name = "video"; info.session_id = 98; video_sources[0].initialize("video", - WebKit::WebMediaStreamSource::TypeVideo, + blink::WebMediaStreamSource::TypeVideo, "video"); video_sources[0].setExtraData( - new MediaStreamSourceExtraData(info, video_sources[0])); + new MediaStreamSourceExtraData(info, dummy_callback)); video_sources_.assign(video_sources); } - WebKit::WebMediaStream stream_desc; - WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_track_vector( + blink::WebMediaStream stream_desc; + blink::WebVector<blink::WebMediaStreamTrack> audio_track_vector( audio_sources.size()); for (size_t i = 0; i < audio_track_vector.size(); ++i) { audio_track_vector[i].initialize(audio_sources[i].id(), audio_sources[i]); } - WebKit::WebVector<WebKit::WebMediaStreamTrack> video_track_vector( + blink::WebVector<blink::WebMediaStreamTrack> video_track_vector( video_sources.size()); for (size_t i = 0; i < video_track_vector.size(); ++i) { video_track_vector[i].initialize(video_sources[i].id(), @@ -109,15 +100,15 @@ class MediaStreamDependencyFactoryTest : public ::testing::Test { return stream_desc; } - void CreateNativeSources(WebKit::WebMediaStream* descriptor) { + void CreateNativeSources(blink::WebMediaStream* descriptor) { static const int kRenderViewId = 1; MediaSourceCreatedObserver observer; - WebKit::WebMediaConstraints audio_constraints; + blink::WebMediaConstraints audio_constraints; dependency_factory_->CreateNativeMediaSources( kRenderViewId, - WebKit::WebMediaConstraints(), - WebKit::WebMediaConstraints(), + blink::WebMediaConstraints(), + blink::WebMediaConstraints(), descriptor, base::Bind( &MediaSourceCreatedObserver::OnCreateNativeSourcesComplete, @@ -134,7 +125,7 @@ class MediaStreamDependencyFactoryTest : public ::testing::Test { EXPECT_TRUE(observer.description() == descriptor); } - void VerifyMediaStream(const WebKit::WebMediaStream& stream_desc, + void VerifyMediaStream(const blink::WebMediaStream& stream_desc, size_t num_audio_tracks, size_t num_video_tracks) { content::MediaStreamExtraData* extra_data = @@ -147,19 +138,19 @@ class MediaStreamDependencyFactoryTest : public ::testing::Test { protected: scoped_ptr<MockMediaStreamDependencyFactory> dependency_factory_; - WebKit::WebVector<WebKit::WebMediaStreamSource> audio_sources_; - WebKit::WebVector<WebKit::WebMediaStreamSource> video_sources_; + blink::WebVector<blink::WebMediaStreamSource> audio_sources_; + blink::WebVector<blink::WebMediaStreamSource> video_sources_; }; TEST_F(MediaStreamDependencyFactoryTest, CreateRTCPeerConnectionHandler) { MockWebRTCPeerConnectionHandlerClient client_jsep; - scoped_ptr<WebKit::WebRTCPeerConnectionHandler> pc_handler( + scoped_ptr<blink::WebRTCPeerConnectionHandler> pc_handler( dependency_factory_->CreateRTCPeerConnectionHandler(&client_jsep)); EXPECT_TRUE(pc_handler.get() != NULL); } TEST_F(MediaStreamDependencyFactoryTest, CreateNativeMediaStream) { - WebKit::WebMediaStream stream_desc = CreateWebKitMediaStream(true, true); + blink::WebMediaStream stream_desc = CreateWebKitMediaStream(true, true); CreateNativeSources(&stream_desc); dependency_factory_->CreateNativeLocalMediaStream(&stream_desc); @@ -171,23 +162,23 @@ TEST_F(MediaStreamDependencyFactoryTest, CreateNativeMediaStream) { // remote tracks. TEST_F(MediaStreamDependencyFactoryTest, CreateNativeMediaStreamWithoutSource) { // Create a WebKit MediaStream description. - WebKit::WebMediaStreamSource audio_source; + blink::WebMediaStreamSource audio_source; audio_source.initialize("audio source", - WebKit::WebMediaStreamSource::TypeAudio, + blink::WebMediaStreamSource::TypeAudio, "something"); - WebKit::WebMediaStreamSource video_source; + blink::WebMediaStreamSource video_source; video_source.initialize("video source", - WebKit::WebMediaStreamSource::TypeVideo, + blink::WebMediaStreamSource::TypeVideo, "something"); - WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks( + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks( static_cast<size_t>(1)); audio_tracks[0].initialize(audio_source.id(), audio_source); - WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks( + blink::WebVector<blink::WebMediaStreamTrack> video_tracks( static_cast<size_t>(1)); video_tracks[0].initialize(video_source.id(), video_source); - WebKit::WebMediaStream stream_desc; + blink::WebMediaStream stream_desc; stream_desc.initialize("new stream", audio_tracks, video_tracks); EXPECT_TRUE(dependency_factory_->EnsurePeerConnectionFactory()); @@ -196,13 +187,13 @@ TEST_F(MediaStreamDependencyFactoryTest, CreateNativeMediaStreamWithoutSource) { } TEST_F(MediaStreamDependencyFactoryTest, AddAndRemoveNativeTrack) { - WebKit::WebMediaStream stream_desc = CreateWebKitMediaStream(true, true); + blink::WebMediaStream stream_desc = CreateWebKitMediaStream(true, true); CreateNativeSources(&stream_desc); dependency_factory_->CreateNativeLocalMediaStream(&stream_desc); VerifyMediaStream(stream_desc, 1, 1); - WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks; + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; stream_desc.audioTracks(audio_tracks); EXPECT_TRUE(dependency_factory_->RemoveNativeMediaStreamTrack( stream_desc, audio_tracks[0])); @@ -212,7 +203,7 @@ TEST_F(MediaStreamDependencyFactoryTest, AddAndRemoveNativeTrack) { stream_desc, audio_tracks[0])); VerifyMediaStream(stream_desc, 1, 1); - WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks; + blink::WebVector<blink::WebMediaStreamTrack> video_tracks; stream_desc.videoTracks(video_tracks); EXPECT_TRUE(dependency_factory_->RemoveNativeMediaStreamTrack( stream_desc, video_tracks[0])); diff --git a/chromium/content/renderer/media/media_stream_dispatcher.cc b/chromium/content/renderer/media/media_stream_dispatcher.cc index 57d65b6b8ef..96f92fbfa9c 100644 --- a/chromium/content/renderer/media/media_stream_dispatcher.cc +++ b/chromium/content/renderer/media/media_stream_dispatcher.cc @@ -14,38 +14,21 @@ namespace content { -MediaStreamDispatcher::EnumerationRequest::EnumerationRequest( - const base::WeakPtr<MediaStreamDispatcherEventHandler>& handler, - int request_id) - : handler(handler), - request_id(request_id) { -} - -MediaStreamDispatcher::EnumerationRequest::~EnumerationRequest() {} - -bool MediaStreamDispatcher::EnumerationRequest::IsThisRequest( - int request_id1, - const base::WeakPtr<MediaStreamDispatcherEventHandler>& handler1) { - return (request_id1 == request_id && handler1.get() == handler.get()); -} - -MediaStreamDispatcher::EnumerationState::EnumerationState() - : ipc_id(-1) { -} - -MediaStreamDispatcher::EnumerationState::~EnumerationState() {} - -struct MediaStreamDispatcher::EnumerationState::CachedDevices { - CachedDevices(const std::string& label, - const StreamDeviceInfoArray& device_array) - : label(label), - devices(device_array) { +namespace { + +bool RemoveStreamDeviceFromArray(const StreamDeviceInfo device_info, + StreamDeviceInfoArray* array) { + for (StreamDeviceInfoArray::iterator device_it = array->begin(); + device_it != array->end(); ++device_it) { + if (StreamDeviceInfo::IsEqual(*device_it, device_info)) { + array->erase(device_it); + return true; + } } - ~CachedDevices() {} + return false; +} - std::string label; - StreamDeviceInfoArray devices; -}; +} // namespace MediaStreamDispatcher::MediaStreamDispatcher(RenderViewImpl* render_view) : RenderViewObserver(render_view), @@ -89,17 +72,31 @@ void MediaStreamDispatcher::CancelGenerateStream( } } -void MediaStreamDispatcher::StopStream(const std::string& label) { - DCHECK(main_loop_->BelongsToCurrentThread()); - DVLOG(1) << "MediaStreamDispatcher::StopStream" - << ", {label = " << label << "}"; - - LabelStreamMap::iterator it = label_stream_map_.find(label); - if (it == label_stream_map_.end()) - return; +void MediaStreamDispatcher::StopStreamDevice( + const StreamDeviceInfo& device_info) { + DVLOG(1) << "MediaStreamDispatcher::StopStreamDevice" + << ", {device_id = " << device_info.device.id << "}"; + // Remove |device_info| from all streams in |label_stream_map_|. + bool device_found = false; + LabelStreamMap::iterator stream_it = label_stream_map_.begin(); + while (stream_it != label_stream_map_.end()) { + StreamDeviceInfoArray& audio_array = stream_it->second.audio_array; + StreamDeviceInfoArray& video_array = stream_it->second.video_array; + + if (RemoveStreamDeviceFromArray(device_info, &audio_array) || + RemoveStreamDeviceFromArray(device_info, &video_array)) { + device_found = true; + if (audio_array.empty() && video_array.empty()) { + label_stream_map_.erase(stream_it++); + continue; + } + } + ++stream_it; + } + DCHECK(device_found); - Send(new MediaStreamHostMsg_StopGeneratedStream(routing_id(), label)); - label_stream_map_.erase(it); + Send(new MediaStreamHostMsg_StopStreamDevice(routing_id(), + device_info.device.id)); } void MediaStreamDispatcher::EnumerateDevices( @@ -113,21 +110,16 @@ void MediaStreamDispatcher::EnumerateDevices( DVLOG(1) << "MediaStreamDispatcher::EnumerateDevices(" << request_id << ")"; - EnumerationState* state = - (type == MEDIA_DEVICE_AUDIO_CAPTURE ? - &audio_enumeration_state_ : &video_enumeration_state_); - state->requests.push_back(EnumerationRequest(event_handler, request_id)); - - if (state->cached_devices) { - event_handler->OnDevicesEnumerated( - request_id, state->cached_devices->devices); - } else if (state->ipc_id < 0) { - Send(new MediaStreamHostMsg_EnumerateDevices(routing_id(), - next_ipc_id_, - type, - security_origin)); - state->ipc_id = next_ipc_id_++; + for (RequestList::iterator it = requests_.begin(); it != requests_.end(); + ++it) { + DCHECK(!it->IsThisRequest(request_id, event_handler)); } + + requests_.push_back(Request(event_handler, request_id, next_ipc_id_)); + Send(new MediaStreamHostMsg_EnumerateDevices(routing_id(), + next_ipc_id_++, + type, + security_origin)); } void MediaStreamDispatcher::StopEnumerateDevices( @@ -136,32 +128,13 @@ void MediaStreamDispatcher::StopEnumerateDevices( DCHECK(main_loop_->BelongsToCurrentThread()); DVLOG(1) << "MediaStreamDispatcher::StopEnumerateDevices(" << request_id << ")"; - - // Remove the request. - RemoveEnumerationRequest( - request_id, event_handler, &audio_enumeration_state_); - RemoveEnumerationRequest( - request_id, event_handler, &video_enumeration_state_); -} - -void MediaStreamDispatcher::RemoveEnumerationRequest( - int request_id, - const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler, - EnumerationState* state) { - EnumerationRequestList* requests = &state->requests; - for (EnumerationRequestList::iterator it = requests->begin(); - it != requests->end(); ++it) { + for (RequestList::iterator it = requests_.begin(); it != requests_.end(); + ++it) { if (it->IsThisRequest(request_id, event_handler)) { - requests->erase(it); - if (requests->empty() && state->cached_devices) { - // No more request and has a label, try to stop the label - // and invalidate the state. - Send(new MediaStreamHostMsg_StopGeneratedStream( - routing_id(), state->cached_devices->label)); - state->ipc_id = -1; - state->cached_devices.reset(); - } - return; + Send(new MediaStreamHostMsg_CancelEnumerateDevices(routing_id(), + it->ipc_request)); + requests_.erase(it); + break; } } } @@ -191,10 +164,16 @@ void MediaStreamDispatcher::CancelOpenDevice( void MediaStreamDispatcher::CloseDevice(const std::string& label) { DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(!label.empty()); DVLOG(1) << "MediaStreamDispatcher::CloseDevice" << ", {label = " << label << "}"; - StopStream(label); + LabelStreamMap::iterator it = label_stream_map_.find(label); + if (it == label_stream_map_.end()) + return; + label_stream_map_.erase(it); + + Send(new MediaStreamHostMsg_CloseDevice(routing_id(), label)); } bool MediaStreamDispatcher::Send(IPC::Message* message) { @@ -213,12 +192,10 @@ bool MediaStreamDispatcher::OnMessageReceived(const IPC::Message& message) { OnStreamGenerated) IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed, OnStreamGenerationFailed) - IPC_MESSAGE_HANDLER(MediaStreamMsg_StopGeneratedStream, - OnStopGeneratedStream) + IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceStopped, + OnDeviceStopped) IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerated, OnDevicesEnumerated) - IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerationFailed, - OnDevicesEnumerationFailed) IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened, OnDeviceOpened) IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpenFailed, @@ -273,67 +250,43 @@ void MediaStreamDispatcher::OnStreamGenerationFailed(int request_id) { } } -void MediaStreamDispatcher::OnStopGeneratedStream(const std::string& label) { +void MediaStreamDispatcher::OnDeviceStopped( + const std::string& label, + const StreamDeviceInfo& device_info) { DCHECK(main_loop_->BelongsToCurrentThread()); + DVLOG(1) << "MediaStreamDispatcher::OnDeviceStopped(" + << "{label = " << label << "})" + << ", {device_id = " << device_info.device.id << "})"; + LabelStreamMap::iterator it = label_stream_map_.find(label); - if (it == label_stream_map_.end()) + if (it == label_stream_map_.end()) { + // This can happen if a user happen stop a the device from JS at the same + // time as the underlying media device is unplugged from the system. return; - - if (it->second.handler.get()) { - it->second.handler->OnStopGeneratedStream(label); - DVLOG(1) << "MediaStreamDispatcher::OnStopGeneratedStream(" - << label << ")\n"; } - label_stream_map_.erase(it); + Stream* stream = &it->second; + if (IsAudioMediaType(device_info.device.type)) + RemoveStreamDeviceFromArray(device_info, &stream->audio_array); + else + RemoveStreamDeviceFromArray(device_info, &stream->video_array); + + if (stream->handler.get()) + stream->handler->OnDeviceStopped(label, device_info); + + if (stream->audio_array.empty() && stream->video_array.empty()) + label_stream_map_.erase(it); } void MediaStreamDispatcher::OnDevicesEnumerated( int request_id, - const std::string& label, const StreamDeviceInfoArray& device_array) { DCHECK(main_loop_->BelongsToCurrentThread()); DCHECK_GE(request_id, 0); - EnumerationState* state; - if (request_id == audio_enumeration_state_.ipc_id) { - state = &audio_enumeration_state_; - } else if (request_id == video_enumeration_state_.ipc_id) { - state = &video_enumeration_state_; - } else { - // This could happen when requester has stopped enumeration while some - // enumerated response is on the way. Have to stop the |label| because - // this might be the first enumerated device list is received. This also - // lead to same label being stopped multiple times. - Send(new MediaStreamHostMsg_StopGeneratedStream(routing_id(), label)); - return; - } - - DCHECK(!label.empty()); - state->cached_devices.reset(new EnumerationState::CachedDevices( - label, device_array)); - - for (EnumerationRequestList::iterator it = state->requests.begin(); - it != state->requests.end(); ++it) { - if (it->handler.get()) { + for (RequestList::iterator it = requests_.begin(); it != requests_.end(); + ++it) { + if (it->ipc_request == request_id && it->handler.get()) { it->handler->OnDevicesEnumerated(it->request_id, device_array); - DVLOG(1) << "MediaStreamDispatcher::OnDevicesEnumerated(" - << it->request_id << ")"; - } - } -} - -void MediaStreamDispatcher::OnDevicesEnumerationFailed(int request_id) { - DCHECK(main_loop_->BelongsToCurrentThread()); - for (RequestList::iterator it = requests_.begin(); - it != requests_.end(); ++it) { - Request& request = *it; - if (request.ipc_request == request_id) { - if (request.handler.get()) { - request.handler->OnDevicesEnumerationFailed(request.request_id); - DVLOG(1) << "MediaStreamDispatcher::OnDevicesEnumerationFailed(" - << request.request_id << ")\n"; - } - requests_.erase(it); break; } } @@ -389,10 +342,10 @@ void MediaStreamDispatcher::OnDeviceOpenFailed(int request_id) { int MediaStreamDispatcher::audio_session_id(const std::string& label, int index) { LabelStreamMap::iterator it = label_stream_map_.find(label); - if (it == label_stream_map_.end()) + if (it == label_stream_map_.end() || + it->second.audio_array.size() <= static_cast<size_t>(index)) { return StreamDeviceInfo::kNoId; - - DCHECK_GT(it->second.audio_array.size(), static_cast<size_t>(index)); + } return it->second.audio_array[index].session_id; } @@ -403,10 +356,10 @@ bool MediaStreamDispatcher::IsStream(const std::string& label) { int MediaStreamDispatcher::video_session_id(const std::string& label, int index) { LabelStreamMap::iterator it = label_stream_map_.find(label); - if (it == label_stream_map_.end()) + if (it == label_stream_map_.end() || + it->second.video_array.size() <= static_cast<size_t>(index)) { return StreamDeviceInfo::kNoId; - - DCHECK_GT(it->second.video_array.size(), static_cast<size_t>(index)); + } return it->second.video_array[index].session_id; } diff --git a/chromium/content/renderer/media/media_stream_dispatcher.h b/chromium/content/renderer/media/media_stream_dispatcher.h index af25963940e..4c08958488a 100644 --- a/chromium/content/renderer/media/media_stream_dispatcher.h +++ b/chromium/content/renderer/media/media_stream_dispatcher.h @@ -52,8 +52,8 @@ class CONTENT_EXPORT MediaStreamDispatcher int request_id, const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler); - // Stop a started stream. Label is the label provided in OnStreamGenerated. - virtual void StopStream(const std::string& label); + // Stop a started device that has been requested by calling GenerateStream. + virtual void StopStreamDevice(const StreamDeviceInfo& device_info); // Request to enumerate devices. void EnumerateDevices( @@ -91,9 +91,10 @@ class CONTENT_EXPORT MediaStreamDispatcher // Returns an audio session_id given a label and an index. virtual int audio_session_id(const std::string& label, int index); + protected: + int GetNextIpcIdForTest() { return next_ipc_id_; } + private: - FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, BasicStream); - FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, BasicStreamForDevice); FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, BasicVideoDevice); FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, TestFailure); FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, CancelGenerateStream); @@ -131,37 +132,6 @@ class CONTENT_EXPORT MediaStreamDispatcher StreamDeviceInfoArray video_array; }; - // An enumeration request is identified by pair (request_id, handler). - // It allows multiple clients to make requests and each client could have - // its own request_id sequence. - struct EnumerationRequest { - EnumerationRequest( - const base::WeakPtr<MediaStreamDispatcherEventHandler>& handler, - int request_id); - ~EnumerationRequest(); - bool IsThisRequest( - int request_id, - const base::WeakPtr<MediaStreamDispatcherEventHandler>& handler); - - base::WeakPtr<MediaStreamDispatcherEventHandler> handler; - int request_id; - }; - - // List of requests made to EnumerateDevices. - typedef std::list<EnumerationRequest> EnumerationRequestList; - - struct EnumerationState { - EnumerationState(); - ~EnumerationState(); - - struct CachedDevices; - - // If |ipc_id| >= 0, then we've started. - int ipc_id; - scoped_ptr<CachedDevices> cached_devices; - EnumerationRequestList requests; - }; - // RenderViewObserver OVERRIDE. virtual bool Send(IPC::Message* message) OVERRIDE; @@ -173,10 +143,10 @@ class CONTENT_EXPORT MediaStreamDispatcher const StreamDeviceInfoArray& audio_array, const StreamDeviceInfoArray& video_array); void OnStreamGenerationFailed(int request_id); - void OnStopGeneratedStream(const std::string& label); + void OnDeviceStopped(const std::string& label, + const StreamDeviceInfo& device_info); void OnDevicesEnumerated( int request_id, - const std::string& label, const StreamDeviceInfoArray& device_array); void OnDevicesEnumerationFailed(int request_id); void OnDeviceOpened( @@ -185,11 +155,6 @@ class CONTENT_EXPORT MediaStreamDispatcher const StreamDeviceInfo& device_info); void OnDeviceOpenFailed(int request_id); - void RemoveEnumerationRequest( - int request_id, - const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler, - EnumerationState* state); - // Used for DCHECKs so methods calls won't execute in the wrong thread. scoped_refptr<base::MessageLoopProxy> main_loop_; @@ -197,10 +162,8 @@ class CONTENT_EXPORT MediaStreamDispatcher typedef std::map<std::string, Stream> LabelStreamMap; LabelStreamMap label_stream_map_; - EnumerationState audio_enumeration_state_; - EnumerationState video_enumeration_state_; - - // List of calls made to GenerateStream that have not yet completed. + // List of calls made to the browser process that have not yet completed or + // been canceled. typedef std::list<Request> RequestList; RequestList requests_; diff --git a/chromium/content/renderer/media/media_stream_dispatcher_eventhandler.h b/chromium/content/renderer/media/media_stream_dispatcher_eventhandler.h index 7a0803a096c..e83f2952560 100644 --- a/chromium/content/renderer/media/media_stream_dispatcher_eventhandler.h +++ b/chromium/content/renderer/media/media_stream_dispatcher_eventhandler.h @@ -25,17 +25,16 @@ class CONTENT_EXPORT MediaStreamDispatcherEventHandler { // to the requested devices or no device is available. virtual void OnStreamGenerationFailed(int request_id) = 0; - // The user has requested to stop a media stream. - virtual void OnStopGeneratedStream(const std::string& label) = 0; + // A device has been stopped in the browser processes. + virtual void OnDeviceStopped( + const std::string& label, + const StreamDeviceInfo& device_info) = 0; // A new list of devices have been enumerated. virtual void OnDevicesEnumerated( int request_id, const StreamDeviceInfoArray& device_array) = 0; - // Failed to enumerate devices. - virtual void OnDevicesEnumerationFailed(int request_id) = 0; - // A device has been opened. virtual void OnDeviceOpened( int request_id, diff --git a/chromium/content/renderer/media/media_stream_dispatcher_unittest.cc b/chromium/content/renderer/media/media_stream_dispatcher_unittest.cc index 300bfe39690..635d22fa04c 100644 --- a/chromium/content/renderer/media/media_stream_dispatcher_unittest.cc +++ b/chromium/content/renderer/media/media_stream_dispatcher_unittest.cc @@ -7,6 +7,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" +#include "base/strings/string_number_conversions.h" #include "content/common/media/media_stream_messages.h" #include "content/public/common/media_stream_request.h" #include "content/renderer/media/media_stream_dispatcher.h" @@ -24,11 +25,9 @@ const int kRequestId1 = 10; const int kRequestId2 = 20; const int kRequestId3 = 30; const int kRequestId4 = 40; -static const char kLabel[] = "test"; const MediaStreamType kAudioType = MEDIA_DEVICE_AUDIO_CAPTURE; const MediaStreamType kVideoType = MEDIA_DEVICE_VIDEO_CAPTURE; -const MediaStreamType kNoAudioType = MEDIA_NO_SERVICE; class MockMediaStreamDispatcherEventHandler : public MediaStreamDispatcherEventHandler, @@ -44,14 +43,29 @@ class MockMediaStreamDispatcherEventHandler const StreamDeviceInfoArray& video_device_array) OVERRIDE { request_id_ = request_id; label_ = label; + if (audio_device_array.size()) { + DCHECK(audio_device_array.size() == 1); + audio_device_ = audio_device_array[0]; + } + if (video_device_array.size()) { + DCHECK(video_device_array.size() == 1); + video_device_ = video_device_array[0]; + } } virtual void OnStreamGenerationFailed(int request_id) OVERRIDE { request_id_ = request_id; } - virtual void OnStopGeneratedStream(const std::string& label) OVERRIDE { - label_ = label; + virtual void OnDeviceStopped(const std::string& label, + const StreamDeviceInfo& device_info) OVERRIDE { + device_stopped_label_ = label; + if (IsVideoMediaType(device_info.device.type)) { + EXPECT_TRUE(StreamDeviceInfo::IsEqual(video_device_, device_info)); + } + if (IsAudioMediaType(device_info.device.type)) { + EXPECT_TRUE(StreamDeviceInfo::IsEqual(audio_device_, device_info)); + } } virtual void OnDevicesEnumerated( @@ -60,10 +74,6 @@ class MockMediaStreamDispatcherEventHandler request_id_ = request_id; } - virtual void OnDevicesEnumerationFailed(int request_id) OVERRIDE { - request_id_ = request_id; - } - virtual void OnDeviceOpened( int request_id, const std::string& label, @@ -76,163 +86,133 @@ class MockMediaStreamDispatcherEventHandler request_id_ = request_id; } + void ResetStoredParameters() { + request_id_ = -1; + label_ = ""; + device_stopped_label_ = ""; + audio_device_ = StreamDeviceInfo(); + video_device_ = StreamDeviceInfo(); + } + int request_id_; std::string label_; - - DISALLOW_COPY_AND_ASSIGN(MockMediaStreamDispatcherEventHandler); + std::string device_stopped_label_; + StreamDeviceInfo audio_device_; + StreamDeviceInfo video_device_; }; -} // namespace - -TEST(MediaStreamDispatcherTest, BasicStream) { - scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); - scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL)); - scoped_ptr<MockMediaStreamDispatcherEventHandler> - handler(new MockMediaStreamDispatcherEventHandler); - StreamOptions components(kAudioType, kVideoType); - GURL security_origin; - - int ipc_request_id1 = dispatcher->next_ipc_id_; - dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(), - components, security_origin); - int ipc_request_id2 = dispatcher->next_ipc_id_; - EXPECT_NE(ipc_request_id1, ipc_request_id2); - dispatcher->GenerateStream(kRequestId2, handler.get()->AsWeakPtr(), - components, security_origin); - EXPECT_EQ(dispatcher->requests_.size(), size_t(2)); +class MediaStreamDispatcherUnderTest : public MediaStreamDispatcher { + public: + MediaStreamDispatcherUnderTest() : MediaStreamDispatcher(NULL) {} - StreamDeviceInfoArray audio_device_array(1); - StreamDeviceInfo audio_device_info; - audio_device_info.device.name = "Microphone"; - audio_device_info.device.type = kAudioType; - audio_device_info.session_id = kAudioSessionId; - audio_device_array[0] = audio_device_info; + using MediaStreamDispatcher::GetNextIpcIdForTest; + using RenderViewObserver::OnMessageReceived; +}; - StreamDeviceInfoArray video_device_array(1); - StreamDeviceInfo video_device_info; - video_device_info.device.name = "Camera"; - video_device_info.device.type = kVideoType; - video_device_info.session_id = kVideoSessionId; - video_device_array[0] = video_device_info; +class MediaStreamDispatcherTest : public ::testing::Test { + public: + MediaStreamDispatcherTest() + : dispatcher_(new MediaStreamDispatcherUnderTest()), + handler_(new MockMediaStreamDispatcherEventHandler), + security_origin_("http://test.com"), + request_id_(10) { + } - // Complete the creation of stream1. - std::string stream_label1 = std::string("stream1"); - dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated( - kRouteId, ipc_request_id1, stream_label1, - audio_device_array, video_device_array)); - EXPECT_EQ(handler->request_id_, kRequestId1); - EXPECT_EQ(handler->label_, stream_label1); + // Generates a request for a MediaStream and returns the request id that is + // used in IPC. Use this returned id in CompleteGenerateStream to identify + // the request. + int GenerateStream(const StreamOptions& options, int request_id) { + int next_ipc_id = dispatcher_->GetNextIpcIdForTest(); + dispatcher_->GenerateStream(request_id, handler_.get()->AsWeakPtr(), + options, security_origin_); + return next_ipc_id; + } - // Complete the creation of stream2. - std::string stream_label2 = std::string("stream2"); - dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated( - kRouteId, ipc_request_id2, stream_label2, + // CompleteGenerateStream create a MediaStreamMsg_StreamGenerated instance + // and call the MediaStreamDispathcer::OnMessageReceived. |ipc_id| must be the + // the id returned by GenerateStream. + std::string CompleteGenerateStream(int ipc_id, const StreamOptions& options, + int request_id) { + StreamDeviceInfoArray audio_device_array(options.audio_requested ? 1 : 0); + if (options.audio_requested) { + StreamDeviceInfo audio_device_info; + audio_device_info.device.name = "Microphone"; + audio_device_info.device.type = kAudioType; + audio_device_info.session_id = kAudioSessionId; + audio_device_array[0] = audio_device_info; + } + + StreamDeviceInfoArray video_device_array(options.video_requested ? 1 : 0); + if (options.video_requested) { + StreamDeviceInfo video_device_info; + video_device_info.device.name = "Camera"; + video_device_info.device.type = kVideoType; + video_device_info.session_id = kVideoSessionId; + video_device_array[0] = video_device_info; + } + + std::string label = "stream" + base::IntToString(ipc_id); + + handler_->ResetStoredParameters(); + dispatcher_->OnMessageReceived(MediaStreamMsg_StreamGenerated( + kRouteId, ipc_id, label, audio_device_array, video_device_array)); - EXPECT_EQ(handler->request_id_, kRequestId2); - EXPECT_EQ(handler->label_, stream_label2); - EXPECT_EQ(dispatcher->requests_.size(), size_t(0)); - EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(2)); + EXPECT_EQ(handler_->request_id_, request_id); + EXPECT_EQ(handler_->label_, label); - // Check the session_id of stream2. - EXPECT_EQ(dispatcher->audio_session_id(stream_label2, 0), kAudioSessionId); - EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0), kVideoSessionId); + if (options.audio_requested) + EXPECT_EQ(dispatcher_->audio_session_id(label, 0), kAudioSessionId); - // Stop stream2. - dispatcher->StopStream(stream_label2); - EXPECT_EQ(dispatcher->audio_session_id(stream_label2, 0), - StreamDeviceInfo::kNoId); - EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0), - StreamDeviceInfo::kNoId); + if (options.video_requested) + EXPECT_EQ(dispatcher_->video_session_id(label, 0), kVideoSessionId); - // Stop stream1. - dispatcher->StopStream(stream_label1); - EXPECT_EQ(dispatcher->audio_session_id(stream_label1, 0), - StreamDeviceInfo::kNoId); - EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0), - StreamDeviceInfo::kNoId); - EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0)); + return label; + } - // Verify that the request has been completed. - EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0)); - EXPECT_EQ(dispatcher->requests_.size(), size_t(0)); -} + protected: + base::MessageLoop message_loop_; + scoped_ptr<MediaStreamDispatcherUnderTest> dispatcher_; + scoped_ptr<MockMediaStreamDispatcherEventHandler> handler_; + GURL security_origin_; + int request_id_; +}; -TEST(MediaStreamDispatcherTest, BasicStreamForDevice) { - static const char kDeviceId[] = "/dev/video0"; +} // namespace - scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); - scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL)); - scoped_ptr<MockMediaStreamDispatcherEventHandler> - handler(new MockMediaStreamDispatcherEventHandler); - StreamOptions components(kNoAudioType, kVideoType); - components.audio_device_id = kDeviceId; - components.video_device_id = kDeviceId; - GURL security_origin; +TEST_F(MediaStreamDispatcherTest, GenerateStreamAndStopDevices) { + StreamOptions options(true, true); - int ipc_request_id1 = dispatcher->next_ipc_id_; - dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(), - components, security_origin); - int ipc_request_id2 = dispatcher->next_ipc_id_; + int ipc_request_id1 = GenerateStream(options, kRequestId1); + int ipc_request_id2 = GenerateStream(options, kRequestId2); EXPECT_NE(ipc_request_id1, ipc_request_id2); - dispatcher->GenerateStream(kRequestId2, handler.get()->AsWeakPtr(), - components, security_origin); - EXPECT_EQ(dispatcher->requests_.size(), size_t(2)); - - // No audio requested. - StreamDeviceInfoArray audio_device_array; - - StreamDeviceInfoArray video_device_array(1); - StreamDeviceInfo video_device_info; - video_device_info.device.name = "Fake Video Capture Device"; - video_device_info.device.type = kVideoType; - video_device_info.session_id = kVideoSessionId; - video_device_array[0] = video_device_info; // Complete the creation of stream1. - std::string stream_label1 = std::string("stream1"); - dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated( - kRouteId, ipc_request_id1, stream_label1, - audio_device_array, video_device_array)); - EXPECT_EQ(handler->request_id_, kRequestId1); - EXPECT_EQ(handler->label_, stream_label1); + const std::string& label1 = CompleteGenerateStream(ipc_request_id1, options, + kRequestId1); // Complete the creation of stream2. - std::string stream_label2 = std::string("stream2"); - dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated( - kRouteId, ipc_request_id2, stream_label2, - audio_device_array, video_device_array)); - EXPECT_EQ(handler->request_id_, kRequestId2); - EXPECT_EQ(handler->label_, stream_label2); + const std::string& label2 = CompleteGenerateStream(ipc_request_id2, options, + kRequestId2); - EXPECT_EQ(dispatcher->requests_.size(), size_t(0)); - EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(2)); - - // Check the session_id of stream2. - EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0), kVideoSessionId); - - // Stop stream2. - dispatcher->StopStream(stream_label2); - EXPECT_EQ(dispatcher->audio_session_id(stream_label2, 0), + // Stop the actual audio device and verify that there is no valid + // |session_id|. + dispatcher_->StopStreamDevice(handler_->audio_device_); + EXPECT_EQ(dispatcher_->audio_session_id(label1, 0), StreamDeviceInfo::kNoId); - EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0), + EXPECT_EQ(dispatcher_->audio_session_id(label2, 0), StreamDeviceInfo::kNoId); - // Stop stream1. - dispatcher->StopStream(stream_label1); - EXPECT_EQ(dispatcher->audio_session_id(stream_label1, 0), + // Stop the actual video device and verify that there is no valid + // |session_id|. + dispatcher_->StopStreamDevice(handler_->video_device_); + EXPECT_EQ(dispatcher_->video_session_id(label1, 0), StreamDeviceInfo::kNoId); - EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0), + EXPECT_EQ(dispatcher_->video_session_id(label2, 0), StreamDeviceInfo::kNoId); - EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0)); - - // Verify that the request has been completed. - EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0)); - EXPECT_EQ(dispatcher->requests_.size(), size_t(0)); } -TEST(MediaStreamDispatcherTest, BasicVideoDevice) { - scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); +TEST_F(MediaStreamDispatcherTest, BasicVideoDevice) { scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL)); scoped_ptr<MockMediaStreamDispatcherEventHandler> handler1(new MockMediaStreamDispatcherEventHandler); @@ -251,7 +231,7 @@ TEST(MediaStreamDispatcherTest, BasicVideoDevice) { kRequestId2, handler2.get()->AsWeakPtr(), kVideoType, security_origin); - EXPECT_EQ(dispatcher->video_enumeration_state_.requests.size(), size_t(2)); + EXPECT_EQ(dispatcher->requests_.size(), size_t(2)); StreamDeviceInfoArray video_device_array(1); StreamDeviceInfo video_device_info; @@ -261,13 +241,16 @@ TEST(MediaStreamDispatcherTest, BasicVideoDevice) { video_device_info.session_id = kVideoSessionId; video_device_array[0] = video_device_info; - // Complete the enumeration request and all requesters should receive reply. + // Complete the first enumeration request. dispatcher->OnMessageReceived(MediaStreamMsg_DevicesEnumerated( - kRouteId, ipc_request_id1, kLabel, video_device_array)); + kRouteId, ipc_request_id1, video_device_array)); EXPECT_EQ(handler1->request_id_, kRequestId1); + + dispatcher->OnMessageReceived(MediaStreamMsg_DevicesEnumerated( + kRouteId, ipc_request_id2, video_device_array)); EXPECT_EQ(handler2->request_id_, kRequestId2); - EXPECT_EQ(dispatcher->video_enumeration_state_.requests.size(), size_t(2)); + EXPECT_EQ(dispatcher->requests_.size(), size_t(2)); EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0)); int ipc_request_id3 = dispatcher->next_ipc_id_; @@ -281,7 +264,7 @@ TEST(MediaStreamDispatcherTest, BasicVideoDevice) { video_device_info.device.id, kVideoType, security_origin); - EXPECT_EQ(dispatcher->requests_.size(), size_t(2)); + EXPECT_EQ(dispatcher->requests_.size(), size_t(4)); // Complete the OpenDevice of request 1. std::string stream_label1 = std::string("stream1"); @@ -295,35 +278,34 @@ TEST(MediaStreamDispatcherTest, BasicVideoDevice) { kRouteId, ipc_request_id4, stream_label2, video_device_info)); EXPECT_EQ(handler1->request_id_, kRequestId4); - EXPECT_EQ(dispatcher->requests_.size(), size_t(0)); + EXPECT_EQ(dispatcher->requests_.size(), size_t(2)); EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(2)); // Check the video_session_id. EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0), kVideoSessionId); EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0), kVideoSessionId); - // Stop stream2. - dispatcher->StopStream(stream_label2); + // Close the device from request 2. + dispatcher->CloseDevice(stream_label2); EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0), StreamDeviceInfo::kNoId); - // Stop stream1. - dispatcher->StopStream(stream_label1); + // Close the device from request 1. + dispatcher->CloseDevice(stream_label1); EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0), StreamDeviceInfo::kNoId); EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0)); // Verify that the request have been completed. EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0)); - EXPECT_EQ(dispatcher->requests_.size(), size_t(0)); + EXPECT_EQ(dispatcher->requests_.size(), size_t(2)); } -TEST(MediaStreamDispatcherTest, TestFailure) { - scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); +TEST_F(MediaStreamDispatcherTest, TestFailure) { scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL)); scoped_ptr<MockMediaStreamDispatcherEventHandler> handler(new MockMediaStreamDispatcherEventHandler); - StreamOptions components(kAudioType, kVideoType); + StreamOptions components(true, true); GURL security_origin; // Test failure when creating a stream. @@ -364,18 +346,13 @@ TEST(MediaStreamDispatcherTest, TestFailure) { EXPECT_EQ(handler->request_id_, kRequestId1); EXPECT_EQ(handler->label_, stream_label1); EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0), kVideoSessionId); - - // Stop stream1. - dispatcher->StopStream(stream_label1); - EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0)); } -TEST(MediaStreamDispatcherTest, CancelGenerateStream) { - scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); +TEST_F(MediaStreamDispatcherTest, CancelGenerateStream) { scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL)); scoped_ptr<MockMediaStreamDispatcherEventHandler> handler(new MockMediaStreamDispatcherEventHandler); - StreamOptions components(kAudioType, kVideoType); + StreamOptions components(true, true); int ipc_request_id1 = dispatcher->next_ipc_id_; dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(), @@ -411,4 +388,22 @@ TEST(MediaStreamDispatcherTest, CancelGenerateStream) { EXPECT_EQ(0u, dispatcher->requests_.size()); } +// Test that the MediaStreamDispatcherEventHandler is notified when the message +// MediaStreamMsg_DeviceStopped is received. +TEST_F(MediaStreamDispatcherTest, DeviceClosed) { + StreamOptions options(true, true); + + int ipc_request_id = GenerateStream(options, kRequestId1); + const std::string& label = CompleteGenerateStream(ipc_request_id, options, + kRequestId1); + + dispatcher_->OnMessageReceived( + MediaStreamMsg_DeviceStopped(kRouteId, label, handler_->video_device_)); + // Verify that MediaStreamDispatcherEventHandler::OnDeviceStopped has been + // called. + EXPECT_EQ(label, handler_->device_stopped_label_); + EXPECT_EQ(dispatcher_->video_session_id(label, 0), + StreamDeviceInfo::kNoId); +} + } // namespace content diff --git a/chromium/content/renderer/media/media_stream_extra_data.h b/chromium/content/renderer/media/media_stream_extra_data.h index afac9c350a2..63bfca4a139 100644 --- a/chromium/content/renderer/media/media_stream_extra_data.h +++ b/chromium/content/renderer/media/media_stream_extra_data.h @@ -18,7 +18,7 @@ class MediaStreamInterface; namespace content { class CONTENT_EXPORT MediaStreamExtraData - : NON_EXPORTED_BASE(public WebKit::WebMediaStream::ExtraData) { + : NON_EXPORTED_BASE(public blink::WebMediaStream::ExtraData) { public: typedef base::Callback<void(const std::string& label)> StreamStopCallback; diff --git a/chromium/content/renderer/media/media_stream_impl.cc b/chromium/content/renderer/media/media_stream_impl.cc index 96dffde9fcd..bc720205d8e 100644 --- a/chromium/content/renderer/media/media_stream_impl.cc +++ b/chromium/content/renderer/media/media_stream_impl.cc @@ -7,11 +7,9 @@ #include <utility> #include "base/logging.h" -#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "content/public/common/desktop_media_id.h" #include "content/renderer/media/media_stream_audio_renderer.h" #include "content/renderer/media/media_stream_dependency_factory.h" #include "content/renderer/media/media_stream_dispatcher.h" @@ -21,13 +19,12 @@ #include "content/renderer/media/webrtc_audio_capturer.h" #include "content/renderer/media/webrtc_audio_renderer.h" #include "content/renderer/media/webrtc_local_audio_renderer.h" +#include "content/renderer/media/webrtc_logging.h" #include "content/renderer/media/webrtc_uma_histograms.h" #include "content/renderer/render_thread_impl.h" #include "media/base/audio_hardware_config.h" #include "third_party/WebKit/public/platform/WebMediaConstraints.h" -#include "third_party/WebKit/public/platform/WebMediaStreamSource.h" #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" -#include "third_party/WebKit/public/platform/WebVector.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h" @@ -35,87 +32,30 @@ namespace content { namespace { -std::string GetStreamConstraint( - const WebKit::WebMediaConstraints& constraints, const std::string& key, - bool is_mandatory) { - if (constraints.isNull()) - return std::string(); - - WebKit::WebString value; - if (is_mandatory) { - constraints.getMandatoryConstraintValue(UTF8ToUTF16(key), value); - } else { - constraints.getOptionalConstraintValue(UTF8ToUTF16(key), value); - } - return UTF16ToUTF8(value); -} - -void UpdateRequestOptions( - const WebKit::WebUserMediaRequest& user_media_request, - StreamOptions* options) { - if (options->audio_type != content::MEDIA_NO_SERVICE) { - std::string audio_stream_source = GetStreamConstraint( - user_media_request.audioConstraints(), kMediaStreamSource, true); - if (audio_stream_source == kMediaStreamSourceTab) { - options->audio_type = content::MEDIA_TAB_AUDIO_CAPTURE; - options->audio_device_id = GetStreamConstraint( - user_media_request.audioConstraints(), - kMediaStreamSourceId, true); - } else if (audio_stream_source == kMediaStreamSourceSystem) { - options->audio_type = content::MEDIA_SYSTEM_AUDIO_CAPTURE; - } +void CopyStreamConstraints(const blink::WebMediaConstraints& constraints, + StreamOptions::Constraints* mandatory, + StreamOptions::Constraints* optional) { + blink::WebVector<blink::WebMediaConstraint> mandatory_constraints; + constraints.getMandatoryConstraints(mandatory_constraints); + for (size_t i = 0; i < mandatory_constraints.size(); i++) { + mandatory->push_back(StreamOptions::Constraint( + mandatory_constraints[i].m_name.utf8(), + mandatory_constraints[i].m_value.utf8())); } - if (options->video_type != content::MEDIA_NO_SERVICE) { - std::string video_stream_source = GetStreamConstraint( - user_media_request.videoConstraints(), kMediaStreamSource, true); - if (video_stream_source == kMediaStreamSourceTab) { - options->video_type = content::MEDIA_TAB_VIDEO_CAPTURE; - options->video_device_id = GetStreamConstraint( - user_media_request.videoConstraints(), - kMediaStreamSourceId, true); - } else if (video_stream_source == kMediaStreamSourceScreen) { - options->video_type = content::MEDIA_DESKTOP_VIDEO_CAPTURE; - options->video_device_id = - DesktopMediaID(DesktopMediaID::TYPE_SCREEN, 0).ToString(); - } else if (video_stream_source == kMediaStreamSourceDesktop) { - options->video_type = content::MEDIA_DESKTOP_VIDEO_CAPTURE; - options->video_device_id = GetStreamConstraint( - user_media_request.videoConstraints(), - kMediaStreamSourceId, true); - } + blink::WebVector<blink::WebMediaConstraint> optional_constraints; + constraints.getOptionalConstraints(optional_constraints); + for (size_t i = 0; i < optional_constraints.size(); i++) { + optional->push_back(StreamOptions::Constraint( + optional_constraints[i].m_name.utf8(), + optional_constraints[i].m_value.utf8())); } } static int g_next_request_id = 0; -// Creates a WebKit representation of a stream sources based on -// |devices| from the MediaStreamDispatcher. -void CreateWebKitSourceVector( - const std::string& label, - const StreamDeviceInfoArray& devices, - WebKit::WebMediaStreamSource::Type type, - WebKit::WebVector<WebKit::WebMediaStreamSource>& webkit_sources) { - CHECK_EQ(devices.size(), webkit_sources.size()); - for (size_t i = 0; i < devices.size(); ++i) { - const char* track_type = - (type == WebKit::WebMediaStreamSource::TypeAudio) ? "a" : "v"; - std::string source_id = base::StringPrintf("%s%s%u", label.c_str(), - track_type, - static_cast<unsigned int>(i)); - webkit_sources[i].initialize( - UTF8ToUTF16(source_id), - type, - UTF8ToUTF16(devices[i].device.name)); - webkit_sources[i].setExtraData( - new content::MediaStreamSourceExtraData(devices[i], webkit_sources[i])); - webkit_sources[i].setDeviceId(UTF8ToUTF16( - base::IntToString(devices[i].session_id))); - } -} - webrtc::MediaStreamInterface* GetNativeMediaStream( - const WebKit::WebMediaStream& web_stream) { + const blink::WebMediaStream& web_stream) { content::MediaStreamExtraData* extra_data = static_cast<content::MediaStreamExtraData*>(web_stream.extraData()); if (!extra_data) @@ -132,6 +72,18 @@ void GetDefaultOutputDeviceParams( *output_buffer_size = hardware_config->GetOutputBufferSize(); } +void RemoveSource(const blink::WebMediaStreamSource& source, + std::vector<blink::WebMediaStreamSource>* sources) { + for (std::vector<blink::WebMediaStreamSource>::iterator it = + sources->begin(); + it != sources->end(); ++it) { + if (source.id() == it->id()) { + sources->erase(it); + return; + } + } +} + } // namespace MediaStreamImpl::MediaStreamImpl( @@ -146,31 +98,16 @@ MediaStreamImpl::MediaStreamImpl( MediaStreamImpl::~MediaStreamImpl() { } -void MediaStreamImpl::OnLocalMediaStreamStop( - const std::string& label) { - DVLOG(1) << "MediaStreamImpl::OnLocalMediaStreamStop(" << label << ")"; - - UserMediaRequestInfo* user_media_request = FindUserMediaRequestInfo(label); - if (user_media_request) { - StopLocalAudioTrack(user_media_request->web_stream); - media_stream_dispatcher_->StopStream(label); - DeleteUserMediaRequestInfo(user_media_request); - } else { - DVLOG(1) << "MediaStreamImpl::OnLocalMediaStreamStop: the stream has " - << "already been stopped."; - } -} - void MediaStreamImpl::requestUserMedia( - const WebKit::WebUserMediaRequest& user_media_request) { + const blink::WebUserMediaRequest& user_media_request) { // Save histogram data so we can see how much GetUserMedia is used. // The histogram counts the number of calls to the JS API // webGetUserMedia. UpdateWebRTCMethodCount(WEBKIT_GET_USER_MEDIA); DCHECK(CalledOnValidThread()); int request_id = g_next_request_id++; - StreamOptions options(MEDIA_NO_SERVICE, MEDIA_NO_SERVICE); - WebKit::WebFrame* frame = NULL; + StreamOptions options; + blink::WebFrame* frame = NULL; GURL security_origin; bool enable_automatic_output_device_selection = false; @@ -178,27 +115,29 @@ void MediaStreamImpl::requestUserMedia( // if it isNull. if (user_media_request.isNull()) { // We are in a test. - options.audio_type = MEDIA_DEVICE_AUDIO_CAPTURE; - options.video_type = MEDIA_DEVICE_VIDEO_CAPTURE; + options.audio_requested = true; + options.video_requested = true; } else { if (user_media_request.audio()) { - options.audio_type = MEDIA_DEVICE_AUDIO_CAPTURE; - options.audio_device_id = GetStreamConstraint( - user_media_request.audioConstraints(), - kMediaStreamSourceInfoId, false); + options.audio_requested = true; + CopyStreamConstraints(user_media_request.audioConstraints(), + &options.mandatory_audio, + &options.optional_audio); + // Check if this input device should be used to select a matching output // device for audio rendering. - std::string enable = GetStreamConstraint( - user_media_request.audioConstraints(), - kMediaStreamRenderToAssociatedSink, false); - if (LowerCaseEqualsASCII(enable, "true")) + std::string enable; + if (options.GetFirstAudioConstraintByName( + kMediaStreamRenderToAssociatedSink, &enable, NULL) && + LowerCaseEqualsASCII(enable, "true")) { enable_automatic_output_device_selection = true; + } } if (user_media_request.video()) { - options.video_type = MEDIA_DEVICE_VIDEO_CAPTURE; - options.video_device_id = GetStreamConstraint( - user_media_request.videoConstraints(), - kMediaStreamSourceInfoId, false); + options.video_requested = true; + CopyStreamConstraints(user_media_request.videoConstraints(), + &options.mandatory_video, + &options.optional_video); } security_origin = GURL(user_media_request.securityOrigin().toString()); @@ -207,17 +146,34 @@ void MediaStreamImpl::requestUserMedia( // out of scope. frame = user_media_request.ownerDocument().frame(); DCHECK(frame); - - UpdateRequestOptions(user_media_request, &options); } DVLOG(1) << "MediaStreamImpl::requestUserMedia(" << request_id << ", [ " - << "audio=" << (options.audio_type) + << "audio=" << (options.audio_requested) << " select associated sink: " << enable_automatic_output_device_selection - << ", video=" << (options.video_type) << " ], " + << ", video=" << (options.video_requested) << " ], " << security_origin.spec() << ")"; + std::string audio_device_id; + bool mandatory_audio; + options.GetFirstAudioConstraintByName(kMediaStreamSourceInfoId, + &audio_device_id, &mandatory_audio); + std::string video_device_id; + bool mandatory_video; + options.GetFirstVideoConstraintByName(kMediaStreamSourceInfoId, + &video_device_id, &mandatory_video); + + WebRtcLogMessage(base::StringPrintf( + "MSI::requestUserMedia. request_id=%d" + ", audio source id=%s mandatory= %s " + ", video source id=%s mandatory= %s", + request_id, + audio_device_id.c_str(), + mandatory_audio ? "true":"false", + video_device_id.c_str(), + mandatory_video ? "true":"false")); + user_media_requests_.push_back( new UserMediaRequestInfo(request_id, frame, user_media_request, enable_automatic_output_device_selection)); @@ -230,7 +186,7 @@ void MediaStreamImpl::requestUserMedia( } void MediaStreamImpl::cancelUserMediaRequest( - const WebKit::WebUserMediaRequest& user_media_request) { + const blink::WebUserMediaRequest& user_media_request) { DCHECK(CalledOnValidThread()); UserMediaRequestInfo* request = FindUserMediaRequestInfo(user_media_request); if (request) { @@ -241,14 +197,14 @@ void MediaStreamImpl::cancelUserMediaRequest( } } -WebKit::WebMediaStream MediaStreamImpl::GetMediaStream( +blink::WebMediaStream MediaStreamImpl::GetMediaStream( const GURL& url) { - return WebKit::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url); + return blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url); } bool MediaStreamImpl::IsMediaStream(const GURL& url) { - WebKit::WebMediaStream web_stream( - WebKit::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url)); + blink::WebMediaStream web_stream( + blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url)); if (web_stream.isNull() || !web_stream.extraData()) return false; // This is not a valid stream. @@ -264,7 +220,7 @@ MediaStreamImpl::GetVideoFrameProvider( const base::Closure& error_cb, const VideoFrameProvider::RepaintCB& repaint_cb) { DCHECK(CalledOnValidThread()); - WebKit::WebMediaStream web_stream(GetMediaStream(url)); + blink::WebMediaStream web_stream(GetMediaStream(url)); if (web_stream.isNull() || !web_stream.extraData()) return NULL; // This is not a valid stream. @@ -272,17 +228,18 @@ MediaStreamImpl::GetVideoFrameProvider( DVLOG(1) << "MediaStreamImpl::GetVideoFrameProvider stream:" << UTF16ToUTF8(web_stream.id()); - webrtc::MediaStreamInterface* stream = GetNativeMediaStream(web_stream); - if (stream) - return CreateVideoFrameProvider(stream, error_cb, repaint_cb); - NOTREACHED(); - return NULL; + blink::WebVector<blink::WebMediaStreamTrack> video_tracks; + web_stream.videoTracks(video_tracks); + if (video_tracks.isEmpty()) + return NULL; + + return new RTCVideoRenderer(video_tracks[0], error_cb, repaint_cb); } scoped_refptr<MediaStreamAudioRenderer> MediaStreamImpl::GetAudioRenderer(const GURL& url) { DCHECK(CalledOnValidThread()); - WebKit::WebMediaStream web_stream(GetMediaStream(url)); + blink::WebMediaStream web_stream(GetMediaStream(url)); if (web_stream.isNull() || !web_stream.extraData()) return NULL; // This is not a valid stream. @@ -295,7 +252,14 @@ MediaStreamImpl::GetAudioRenderer(const GURL& url) { if (extra_data->is_local()) { // Create the local audio renderer if the stream contains audio tracks. - return CreateLocalAudioRenderer(extra_data->stream().get()); + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; + web_stream.audioTracks(audio_tracks); + if (audio_tracks.isEmpty()) + return NULL; + + // TODO(xians): Add support for the case that the media stream contains + // multiple audio tracks. + return CreateLocalAudioRenderer(audio_tracks[0]); } webrtc::MediaStreamInterface* stream = extra_data->stream().get(); @@ -332,42 +296,75 @@ void MediaStreamImpl::OnStreamGenerated( if (!request_info) { // This can happen if the request is canceled or the frame reloads while // MediaStreamDispatcher is processing the request. - // We need to tell the dispatcher to stop the stream. - media_stream_dispatcher_->StopStream(label); + // Only stop the device if the device is not used in another MediaStream. + for (StreamDeviceInfoArray::const_iterator device_it = audio_array.begin(); + device_it != audio_array.end(); ++device_it) { + if (!FindLocalSource(*device_it)) + media_stream_dispatcher_->StopStreamDevice(*device_it); + } + + for (StreamDeviceInfoArray::const_iterator device_it = video_array.begin(); + device_it != video_array.end(); ++device_it) { + if (!FindLocalSource(*device_it)) + media_stream_dispatcher_->StopStreamDevice(*device_it); + } + DVLOG(1) << "Request ID not found"; return; } request_info->generated = true; - WebKit::WebVector<WebKit::WebMediaStreamSource> audio_source_vector( - audio_array.size()); - CreateWebKitSourceVector(label, audio_array, - WebKit::WebMediaStreamSource::TypeAudio, + blink::WebVector<blink::WebMediaStreamSource> audio_source_vector( + audio_array.size()); + + // Log the device names for this request. + for (StreamDeviceInfoArray::const_iterator it = audio_array.begin(); + it != audio_array.end(); ++it) { + WebRtcLogMessage(base::StringPrintf( + "Generated media stream for request id %d contains audio device name" + " \"%s\"", + request_id, + it->device.name.c_str())); + } + + StreamDeviceInfoArray overridden_audio_array = audio_array; + if (!request_info->enable_automatic_output_device_selection) { + // If the GetUserMedia request did not explicitly set the constraint + // kMediaStreamRenderToAssociatedSink, the output device parameters must + // be removed. + for (StreamDeviceInfoArray::iterator it = overridden_audio_array.begin(); + it != overridden_audio_array.end(); ++it) { + it->device.matched_output_device_id = ""; + it->device.matched_output = MediaStreamDevice::AudioDeviceParameters(); + } + } + CreateWebKitSourceVector(label, overridden_audio_array, + blink::WebMediaStreamSource::TypeAudio, + request_info->frame, audio_source_vector); - request_info->audio_sources.assign(audio_source_vector); - WebKit::WebVector<WebKit::WebMediaStreamSource> video_source_vector( + + blink::WebVector<blink::WebMediaStreamSource> video_source_vector( video_array.size()); CreateWebKitSourceVector(label, video_array, - WebKit::WebMediaStreamSource::TypeVideo, + blink::WebMediaStreamSource::TypeVideo, + request_info->frame, video_source_vector); - request_info->video_sources.assign(video_source_vector); + blink::WebUserMediaRequest* request = &(request_info->request); + blink::WebString webkit_id = UTF8ToUTF16(label); + blink::WebMediaStream* web_stream = &(request_info->web_stream); - WebKit::WebUserMediaRequest* request = &(request_info->request); - WebKit::WebString webkit_id = UTF8ToUTF16(label); - WebKit::WebMediaStream* web_stream = &(request_info->web_stream); - - WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_track_vector( + blink::WebVector<blink::WebMediaStreamTrack> audio_track_vector( audio_array.size()); for (size_t i = 0; i < audio_track_vector.size(); ++i) { - audio_track_vector[i].initialize(audio_source_vector[i].id(), - audio_source_vector[i]); + audio_track_vector[i].initialize(audio_source_vector[i]); + request_info->sources.push_back(audio_source_vector[i]); } - WebKit::WebVector<WebKit::WebMediaStreamTrack> video_track_vector( + blink::WebVector<blink::WebMediaStreamTrack> video_track_vector( video_array.size()); for (size_t i = 0; i < video_track_vector.size(); ++i) { - video_track_vector[i].initialize(video_source_vector[i].id(), - video_source_vector[i]); + video_track_vector[i].initialize(video_source_vector[i]); + request_info->sources.push_back(video_source_vector[i]); } web_stream->initialize(webkit_id, audio_track_vector, @@ -375,10 +372,10 @@ void MediaStreamImpl::OnStreamGenerated( // WebUserMediaRequest don't have an implementation in unit tests. // Therefore we need to check for isNull here. - WebKit::WebMediaConstraints audio_constraints = request->isNull() ? - WebKit::WebMediaConstraints() : request->audioConstraints(); - WebKit::WebMediaConstraints video_constraints = request->isNull() ? - WebKit::WebMediaConstraints() : request->videoConstraints(); + blink::WebMediaConstraints audio_constraints = request->isNull() ? + blink::WebMediaConstraints() : request->audioConstraints(); + blink::WebMediaConstraints video_constraints = request->isNull() ? + blink::WebMediaConstraints() : request->videoConstraints(); dependency_factory_->CreateNativeMediaSources( RenderViewObserver::routing_id(), @@ -406,27 +403,82 @@ void MediaStreamImpl::OnStreamGenerationFailed(int request_id) { } // Callback from MediaStreamDispatcher. -// The user has requested to stop the media stream. -void MediaStreamImpl::OnStopGeneratedStream(const std::string& label) { +// The browser process has stopped a device used by a MediaStream. +void MediaStreamImpl::OnDeviceStopped( + const std::string& label, + const StreamDeviceInfo& device_info) { DCHECK(CalledOnValidThread()); - DVLOG(1) << "MediaStreamImpl::OnStopGeneratedStream(" << label << ")"; + DVLOG(1) << "MediaStreamImpl::OnDeviceStopped(" + << "{device_id = " << device_info.device.id << "})"; + + const blink::WebMediaStreamSource* source_ptr = FindLocalSource(device_info); + if (!source_ptr) { + // This happens if the same device is used in several guM requests or + // if a user happen stop a track from JS at the same time + // as the underlying media device is unplugged from the system. + return; + } + // By creating |source| it is guaranteed that the blink::WebMediaStreamSource + // object is valid during the cleanup. + blink::WebMediaStreamSource source(*source_ptr); + StopLocalSource(source, false); + + for (LocalStreamSources::iterator device_it = local_sources_.begin(); + device_it != local_sources_.end(); ++device_it) { + if (device_it->source.id() == source.id()) { + local_sources_.erase(device_it); + break; + } + } - UserMediaRequestInfo* user_media_request = FindUserMediaRequestInfo(label); - if (user_media_request) { - // No need to call media_stream_dispatcher_->StopStream() because the - // request has come from the browser process. - StopLocalAudioTrack(user_media_request->web_stream); - DeleteUserMediaRequestInfo(user_media_request); - } else { - DVLOG(1) << "MediaStreamImpl::OnStopGeneratedStream: the stream has " - << "already been stopped."; + // Remove the reference to this source from all |user_media_requests_|. + // TODO(perkj): The below is not necessary once we don't need to support + // MediaStream::Stop(). + UserMediaRequests::iterator it = user_media_requests_.begin(); + while (it != user_media_requests_.end()) { + RemoveSource(source, &(*it)->sources); + if ((*it)->sources.empty()) { + it = user_media_requests_.erase(it); + } else { + ++it; + } + } +} + +void MediaStreamImpl::CreateWebKitSourceVector( + const std::string& label, + const StreamDeviceInfoArray& devices, + blink::WebMediaStreamSource::Type type, + blink::WebFrame* frame, + blink::WebVector<blink::WebMediaStreamSource>& webkit_sources) { + CHECK_EQ(devices.size(), webkit_sources.size()); + for (size_t i = 0; i < devices.size(); ++i) { + const blink::WebMediaStreamSource* existing_source = + FindLocalSource(devices[i]); + if (existing_source) { + webkit_sources[i] = *existing_source; + DVLOG(1) << "Source already exist. Reusing source with id " + << webkit_sources[i]. id().utf8(); + continue; + } + webkit_sources[i].initialize( + UTF8ToUTF16(devices[i].device.id), + type, + UTF8ToUTF16(devices[i].device.name)); + MediaStreamSourceExtraData* source_extra_data( + new content::MediaStreamSourceExtraData( + devices[i], + base::Bind(&MediaStreamImpl::OnLocalSourceStop, AsWeakPtr()))); + // |source_extra_data| is owned by webkit_sources[i]. + webkit_sources[i].setExtraData(source_extra_data); + local_sources_.push_back(LocalStreamSource(frame, webkit_sources[i])); } } // Callback from MediaStreamDependencyFactory when the sources in |web_stream| // have been generated. void MediaStreamImpl::OnCreateNativeSourcesComplete( - WebKit::WebMediaStream* web_stream, + blink::WebMediaStream* web_stream, bool request_succeeded) { UserMediaRequestInfo* request_info = FindUserMediaRequestInfo(web_stream); if (!request_info) { @@ -442,10 +494,16 @@ void MediaStreamImpl::OnCreateNativeSourcesComplete( web_stream, base::Bind(&MediaStreamImpl::OnLocalMediaStreamStop, AsWeakPtr())); } + DVLOG(1) << "MediaStreamImpl::OnCreateNativeSourcesComplete(" + << "{request_id = " << request_info->request_id << "} " + << "{request_succeeded = " << request_succeeded << "})"; CompleteGetUserMediaRequest(request_info->web_stream, &request_info->request, request_succeeded); if (!request_succeeded) { - OnLocalMediaStreamStop(UTF16ToUTF8(web_stream->id())); + // TODO(perkj): Once we don't support MediaStream::Stop the |request_info| + // can be deleted even if the request succeeds. + DeleteUserMediaRequestInfo(request_info); + StopUnreferencedSources(true); } } @@ -457,12 +515,6 @@ void MediaStreamImpl::OnDevicesEnumerated( NOTIMPLEMENTED(); } -void MediaStreamImpl::OnDevicesEnumerationFailed(int request_id) { - DVLOG(1) << "MediaStreamImpl::OnDevicesEnumerationFailed(" - << request_id << ")"; - NOTIMPLEMENTED(); -} - void MediaStreamImpl::OnDeviceOpened( int request_id, const std::string& label, @@ -479,8 +531,8 @@ void MediaStreamImpl::OnDeviceOpenFailed(int request_id) { } void MediaStreamImpl::CompleteGetUserMediaRequest( - const WebKit::WebMediaStream& stream, - WebKit::WebUserMediaRequest* request_info, + const blink::WebMediaStream& stream, + blink::WebUserMediaRequest* request_info, bool request_succeeded) { if (request_succeeded) { request_info->requestSucceeded(stream); @@ -489,6 +541,40 @@ void MediaStreamImpl::CompleteGetUserMediaRequest( } } +const blink::WebMediaStreamSource* MediaStreamImpl::FindLocalSource( + const StreamDeviceInfo& device) const { + for (LocalStreamSources::const_iterator it = local_sources_.begin(); + it != local_sources_.end(); ++it) { + MediaStreamSourceExtraData* extra_data = + static_cast<MediaStreamSourceExtraData*>( + it->source.extraData()); + const StreamDeviceInfo& active_device = extra_data->device_info(); + if (active_device.device.id == device.device.id && + active_device.device.type == device.device.type && + active_device.session_id == device.session_id) { + return &it->source; + } + } + return NULL; +} + +bool MediaStreamImpl::FindSourceInRequests( + const blink::WebMediaStreamSource& source) const { + for (UserMediaRequests::const_iterator req_it = user_media_requests_.begin(); + req_it != user_media_requests_.end(); ++req_it) { + const std::vector<blink::WebMediaStreamSource>& sources = + (*req_it)->sources; + for (std::vector<blink::WebMediaStreamSource>::const_iterator source_it = + sources.begin(); + source_it != sources.end(); ++source_it) { + if (source_it->id() == source.id()) { + return true; + } + } + } + return false; +} + MediaStreamImpl::UserMediaRequestInfo* MediaStreamImpl::FindUserMediaRequestInfo(int request_id) { UserMediaRequests::iterator it = user_media_requests_.begin(); @@ -501,7 +587,7 @@ MediaStreamImpl::FindUserMediaRequestInfo(int request_id) { MediaStreamImpl::UserMediaRequestInfo* MediaStreamImpl::FindUserMediaRequestInfo( - const WebKit::WebUserMediaRequest& request) { + const blink::WebUserMediaRequest& request) { UserMediaRequests::iterator it = user_media_requests_.begin(); for (; it != user_media_requests_.end(); ++it) { if ((*it)->request == request) @@ -522,7 +608,7 @@ MediaStreamImpl::FindUserMediaRequestInfo(const std::string& label) { MediaStreamImpl::UserMediaRequestInfo* MediaStreamImpl::FindUserMediaRequestInfo( - WebKit::WebMediaStream* web_stream) { + blink::WebMediaStream* web_stream) { UserMediaRequests::iterator it = user_media_requests_.begin(); for (; it != user_media_requests_.end(); ++it) { if (&((*it)->web_stream) == web_stream) @@ -543,31 +629,24 @@ void MediaStreamImpl::DeleteUserMediaRequestInfo( NOTREACHED(); } -void MediaStreamImpl::FrameDetached(WebKit::WebFrame* frame) { +void MediaStreamImpl::FrameDetached(blink::WebFrame* frame) { // Do same thing as FrameWillClose. FrameWillClose(frame); } -void MediaStreamImpl::FrameWillClose(WebKit::WebFrame* frame) { +void MediaStreamImpl::FrameWillClose(blink::WebFrame* frame) { // Loop through all UserMediaRequests and find the requests that belong to the // frame that is being closed. UserMediaRequests::iterator request_it = user_media_requests_.begin(); - while (request_it != user_media_requests_.end()) { if ((*request_it)->frame == frame) { DVLOG(1) << "MediaStreamImpl::FrameWillClose: " << "Cancel user media request " << (*request_it)->request_id; - // If the request is generated, it means that the MediaStreamDispatcher - // has generated a stream for us and we need to let the - // MediaStreamDispatcher know that the stream is no longer wanted. - // If not, we cancel the request and delete the request object. - if ((*request_it)->generated) { - // Stop the local audio track before closing the device in the browser. - StopLocalAudioTrack((*request_it)->web_stream); - - media_stream_dispatcher_->StopStream( - UTF16ToUTF8((*request_it)->web_stream.id())); - } else { + // If the request is not generated, it means that a request + // has been sent to the MediaStreamDispatcher to generate a stream + // but MediaStreamDispatcher has not yet responded and we need to cancel + // the request. + if (!(*request_it)->generated) { media_stream_dispatcher_->CancelGenerateStream( (*request_it)->request_id, AsWeakPtr()); } @@ -576,23 +655,96 @@ void MediaStreamImpl::FrameWillClose(WebKit::WebFrame* frame) { ++request_it; } } + + // Loop through all current local sources and stop the sources that were + // created by the frame that will be closed. + LocalStreamSources::iterator sources_it = local_sources_.begin(); + while (sources_it != local_sources_.end()) { + if (sources_it->frame == frame) { + StopLocalSource(sources_it->source, true); + sources_it = local_sources_.erase(sources_it); + } else { + ++sources_it; + } + } } -scoped_refptr<VideoFrameProvider> -MediaStreamImpl::CreateVideoFrameProvider( - webrtc::MediaStreamInterface* stream, - const base::Closure& error_cb, - const VideoFrameProvider::RepaintCB& repaint_cb) { - if (stream->GetVideoTracks().empty()) - return NULL; +void MediaStreamImpl::OnLocalMediaStreamStop( + const std::string& label) { + DVLOG(1) << "MediaStreamImpl::OnLocalMediaStreamStop(" << label << ")"; - DVLOG(1) << "MediaStreamImpl::CreateRemoteVideoFrameProvider label:" - << stream->label(); + UserMediaRequestInfo* user_media_request = FindUserMediaRequestInfo(label); + if (user_media_request) { + DeleteUserMediaRequestInfo(user_media_request); + } + StopUnreferencedSources(true); +} + +void MediaStreamImpl::OnLocalSourceStop( + const blink::WebMediaStreamSource& source) { + DCHECK(CalledOnValidThread()); + + StopLocalSource(source, true); + + bool device_found = false; + for (LocalStreamSources::iterator device_it = local_sources_.begin(); + device_it != local_sources_.end(); ++device_it) { + if (device_it->source.id() == source.id()) { + device_found = true; + local_sources_.erase(device_it); + break; + } + } + CHECK(device_found); + + // Remove the reference to this source from all |user_media_requests_|. + // TODO(perkj): The below is not necessary once we don't need to support + // MediaStream::Stop(). + UserMediaRequests::iterator it = user_media_requests_.begin(); + while (it != user_media_requests_.end()) { + RemoveSource(source, &(*it)->sources); + if ((*it)->sources.empty()) { + it = user_media_requests_.erase(it); + } else { + ++it; + } + } +} + +void MediaStreamImpl::StopLocalSource( + const blink::WebMediaStreamSource& source, + bool notify_dispatcher) { + MediaStreamSourceExtraData* extra_data = + static_cast<MediaStreamSourceExtraData*> (source.extraData()); + CHECK(extra_data); + DVLOG(1) << "MediaStreamImpl::StopLocalSource(" + << "{device_id = " << extra_data->device_info().device.id << "})"; + + if (source.type() == blink::WebMediaStreamSource::TypeAudio) { + if (extra_data->GetAudioCapturer()) { + extra_data->GetAudioCapturer()->Stop(); + } + } + + if (notify_dispatcher) + media_stream_dispatcher_->StopStreamDevice(extra_data->device_info()); - return new RTCVideoRenderer( - stream->GetVideoTracks()[0], - error_cb, - repaint_cb); + blink::WebMediaStreamSource writable_source(source); + writable_source.setReadyState( + blink::WebMediaStreamSource::ReadyStateEnded); + writable_source.setExtraData(NULL); +} + +void MediaStreamImpl::StopUnreferencedSources(bool notify_dispatcher) { + LocalStreamSources::iterator source_it = local_sources_.begin(); + while (source_it != local_sources_.end()) { + if (!FindSourceInRequests(source_it->source)) { + StopLocalSource(source_it->source, notify_dispatcher); + source_it = local_sources_.erase(source_it); + } else { + ++source_it; + } + } } scoped_refptr<WebRtcAudioRenderer> MediaStreamImpl::CreateRemoteAudioRenderer( @@ -618,19 +770,8 @@ scoped_refptr<WebRtcAudioRenderer> MediaStreamImpl::CreateRemoteAudioRenderer( scoped_refptr<WebRtcLocalAudioRenderer> MediaStreamImpl::CreateLocalAudioRenderer( - webrtc::MediaStreamInterface* stream) { - if (stream->GetAudioTracks().empty()) - return NULL; - - DVLOG(1) << "MediaStreamImpl::CreateLocalAudioRenderer label:" - << stream->label(); - - webrtc::AudioTrackVector audio_tracks = stream->GetAudioTracks(); - DCHECK_EQ(audio_tracks.size(), 1u); - webrtc::AudioTrackInterface* audio_track = audio_tracks[0]; - DVLOG(1) << "audio_track.kind : " << audio_track->kind() - << "audio_track.id : " << audio_track->id() - << "audio_track.enabled: " << audio_track->enabled(); + const blink::WebMediaStreamTrack& audio_track) { + DVLOG(1) << "MediaStreamImpl::CreateLocalAudioRenderer"; int session_id = 0, sample_rate = 0, buffer_size = 0; if (!GetAuthorizedDeviceInfoForAudioRenderer(&session_id, @@ -642,89 +783,37 @@ MediaStreamImpl::CreateLocalAudioRenderer( // Create a new WebRtcLocalAudioRenderer instance and connect it to the // existing WebRtcAudioCapturer so that the renderer can use it as source. return new WebRtcLocalAudioRenderer( - static_cast<WebRtcLocalAudioTrack*>(audio_track), + audio_track, RenderViewObserver::routing_id(), session_id, - sample_rate, buffer_size); } -void MediaStreamImpl::StopLocalAudioTrack( - const WebKit::WebMediaStream& web_stream) { - MediaStreamExtraData* extra_data = static_cast<MediaStreamExtraData*>( - web_stream.extraData()); - if (extra_data && extra_data->is_local() && extra_data->stream().get() && - !extra_data->stream()->GetAudioTracks().empty()) { - webrtc::AudioTrackVector audio_tracks = - extra_data->stream()->GetAudioTracks(); - for (size_t i = 0; i < audio_tracks.size(); ++i) { - WebRtcLocalAudioTrack* audio_track = static_cast<WebRtcLocalAudioTrack*>( - audio_tracks[i].get()); - // Remove the WebRtcAudioDevice as the sink to the local audio track. - audio_track->RemoveSink(dependency_factory_->GetWebRtcAudioDevice()); - // Stop the audio track. This will unhook the audio track from the - // capturer and will shutdown the source of the capturer if it is the - // last audio track connecting to the capturer. - audio_track->Stop(); - } - } -} - bool MediaStreamImpl::GetAuthorizedDeviceInfoForAudioRenderer( int* session_id, int* output_sample_rate, int* output_frames_per_buffer) { DCHECK(CalledOnValidThread()); - const StreamDeviceInfo* device_info = NULL; - WebKit::WebString session_id_str; - UserMediaRequests::iterator it = user_media_requests_.begin(); - for (; it != user_media_requests_.end(); ++it) { - UserMediaRequestInfo* request = (*it); - for (size_t i = 0; i < request->audio_sources.size(); ++i) { - const WebKit::WebMediaStreamSource& source = request->audio_sources[i]; - if (source.readyState() == WebKit::WebMediaStreamSource::ReadyStateEnded) - continue; - - // Check if this request explicitly turned on the automatic output - // device selection constraint. - if (!request->enable_automatic_output_device_selection) - continue; - - if (!session_id_str.isEmpty() && - !session_id_str.equals(source.deviceId())) { - DVLOG(1) << "Multiple capture devices are open so we can't pick a " - "session for a matching output device."; - return false; - } - - // TODO(tommi): Storing the session id in the deviceId field doesn't - // feel right. Move it over to MediaStreamSourceExtraData? - session_id_str = source.deviceId(); - content::MediaStreamSourceExtraData* extra_data = - static_cast<content::MediaStreamSourceExtraData*>(source.extraData()); - device_info = &extra_data->device_info(); - } - } - - if (session_id_str.isEmpty() || !device_info || - !device_info->device.matched_output.sample_rate) { + WebRtcAudioDeviceImpl* audio_device = + dependency_factory_->GetWebRtcAudioDevice(); + if (!audio_device) return false; - } - base::StringToInt(UTF16ToUTF8(session_id_str), session_id); - *output_sample_rate = device_info->device.matched_output.sample_rate; - *output_frames_per_buffer = - device_info->device.matched_output.frames_per_buffer; + if (!audio_device->GetDefaultCapturer()) + return false; - return true; + return audio_device->GetDefaultCapturer()->GetPairedOutputParameters( + session_id, + output_sample_rate, + output_frames_per_buffer); } MediaStreamSourceExtraData::MediaStreamSourceExtraData( const StreamDeviceInfo& device_info, - const WebKit::WebMediaStreamSource& webkit_source) + const SourceStopCallback& stop_callback) : device_info_(device_info), - webkit_source_(webkit_source) { + stop_callback_(stop_callback) { } MediaStreamSourceExtraData::MediaStreamSourceExtraData() { @@ -732,6 +821,11 @@ MediaStreamSourceExtraData::MediaStreamSourceExtraData() { MediaStreamSourceExtraData::~MediaStreamSourceExtraData() {} +void MediaStreamSourceExtraData::OnLocalSourceStop() { + if (!stop_callback_.is_null()) + stop_callback_.Run(owner()); +} + MediaStreamExtraData::MediaStreamExtraData( webrtc::MediaStreamInterface* stream, bool is_local) : stream_(stream), @@ -753,8 +847,8 @@ void MediaStreamExtraData::OnLocalStreamStop() { MediaStreamImpl::UserMediaRequestInfo::UserMediaRequestInfo( int request_id, - WebKit::WebFrame* frame, - const WebKit::WebUserMediaRequest& request, + blink::WebFrame* frame, + const blink::WebUserMediaRequest& request, bool enable_automatic_output_device_selection) : request_id(request_id), generated(false), @@ -765,22 +859,6 @@ MediaStreamImpl::UserMediaRequestInfo::UserMediaRequestInfo( } MediaStreamImpl::UserMediaRequestInfo::~UserMediaRequestInfo() { - // Release the extra data field of all sources created by - // MediaStreamImpl for this request. This breaks the circular reference to - // WebKit::MediaStreamSource. - // TODO(tommyw): Remove this once WebKit::MediaStreamSource::Owner has been - // implemented to fully avoid a circular dependency. - for (size_t i = 0; i < audio_sources.size(); ++i) { - audio_sources[i].setReadyState( - WebKit::WebMediaStreamSource::ReadyStateEnded); - audio_sources[i].setExtraData(NULL); - } - - for (size_t i = 0; i < video_sources.size(); ++i) { - video_sources[i].setReadyState( - WebKit::WebMediaStreamSource::ReadyStateEnded); - video_sources[i].setExtraData(NULL); - } } } // namespace content diff --git a/chromium/content/renderer/media/media_stream_impl.h b/chromium/content/renderer/media/media_stream_impl.h index 8329d5f0b8d..8f72d2ba287 100644 --- a/chromium/content/renderer/media/media_stream_impl.h +++ b/chromium/content/renderer/media/media_stream_impl.h @@ -20,6 +20,8 @@ #include "content/renderer/media/media_stream_client.h" #include "content/renderer/media/media_stream_dispatcher_eventhandler.h" #include "third_party/WebKit/public/platform/WebMediaStream.h" +#include "third_party/WebKit/public/platform/WebMediaStreamSource.h" +#include "third_party/WebKit/public/platform/WebVector.h" #include "third_party/WebKit/public/web/WebUserMediaClient.h" #include "third_party/WebKit/public/web/WebUserMediaRequest.h" #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" @@ -28,6 +30,7 @@ namespace content { class MediaStreamAudioRenderer; class MediaStreamDependencyFactory; class MediaStreamDispatcher; +class MediaStreamSourceExtraData; class WebRtcAudioRenderer; class WebRtcLocalAudioRenderer; @@ -39,7 +42,7 @@ class WebRtcLocalAudioRenderer; // MediaStreamImpl have weak pointers to a MediaStreamDispatcher. class CONTENT_EXPORT MediaStreamImpl : public RenderViewObserver, - NON_EXPORTED_BASE(public WebKit::WebUserMediaClient), + NON_EXPORTED_BASE(public blink::WebUserMediaClient), NON_EXPORTED_BASE(public MediaStreamClient), public MediaStreamDispatcherEventHandler, public base::SupportsWeakPtr<MediaStreamImpl>, @@ -51,11 +54,11 @@ class CONTENT_EXPORT MediaStreamImpl MediaStreamDependencyFactory* dependency_factory); virtual ~MediaStreamImpl(); - // WebKit::WebUserMediaClient implementation + // blink::WebUserMediaClient implementation virtual void requestUserMedia( - const WebKit::WebUserMediaRequest& user_media_request) OVERRIDE; + const blink::WebUserMediaRequest& user_media_request) OVERRIDE; virtual void cancelUserMediaRequest( - const WebKit::WebUserMediaRequest& user_media_request) OVERRIDE; + const blink::WebUserMediaRequest& user_media_request) OVERRIDE; // MediaStreamClient implementation. virtual bool IsMediaStream(const GURL& url) OVERRIDE; @@ -73,11 +76,11 @@ class CONTENT_EXPORT MediaStreamImpl const StreamDeviceInfoArray& audio_array, const StreamDeviceInfoArray& video_array) OVERRIDE; virtual void OnStreamGenerationFailed(int request_id) OVERRIDE; - virtual void OnStopGeneratedStream(const std::string& label) OVERRIDE; + virtual void OnDeviceStopped(const std::string& label, + const StreamDeviceInfo& device_info) OVERRIDE; virtual void OnDevicesEnumerated( int request_id, const StreamDeviceInfoArray& device_array) OVERRIDE; - virtual void OnDevicesEnumerationFailed(int request_id) OVERRIDE; virtual void OnDeviceOpened( int request_id, const std::string& label, @@ -85,12 +88,12 @@ class CONTENT_EXPORT MediaStreamImpl virtual void OnDeviceOpenFailed(int request_id) OVERRIDE; // RenderViewObserver OVERRIDE - virtual void FrameDetached(WebKit::WebFrame* frame) OVERRIDE; - virtual void FrameWillClose(WebKit::WebFrame* frame) OVERRIDE; + virtual void FrameDetached(blink::WebFrame* frame) OVERRIDE; + virtual void FrameWillClose(blink::WebFrame* frame) OVERRIDE; protected: - // Stops a local MediaStream by notifying the MediaStreamDispatcher that the - // stream no longer may be used. + void OnLocalSourceStop(const blink::WebMediaStreamSource& source); + void OnLocalMediaStreamStop(const std::string& label); // Callback function triggered when all native (libjingle) versions of the @@ -99,28 +102,28 @@ class CONTENT_EXPORT MediaStreamImpl // UserMediaRequests::web_stream for which the underlying sources have been // created. void OnCreateNativeSourcesComplete( - WebKit::WebMediaStream* web_stream, + blink::WebMediaStream* web_stream, bool request_succeeded); // This function is virtual for test purposes. A test can override this to // test requesting local media streams. The function notifies WebKit that the // |request| have completed and generated the MediaStream |stream|. virtual void CompleteGetUserMediaRequest( - const WebKit::WebMediaStream& stream, - WebKit::WebUserMediaRequest* request_info, + const blink::WebMediaStream& stream, + blink::WebUserMediaRequest* request_info, bool request_succeeded); // Returns the WebKit representation of a MediaStream given an URL. // This is virtual for test purposes. - virtual WebKit::WebMediaStream GetMediaStream(const GURL& url); + virtual blink::WebMediaStream GetMediaStream(const GURL& url); private: // Structure for storing information about a WebKit request to create a // MediaStream. struct UserMediaRequestInfo { UserMediaRequestInfo(int request_id, - WebKit::WebFrame* frame, - const WebKit::WebUserMediaRequest& request, + blink::WebFrame* frame, + const blink::WebUserMediaRequest& request, bool enable_automatic_output_device_selection); ~UserMediaRequestInfo(); int request_id; @@ -128,33 +131,60 @@ class CONTENT_EXPORT MediaStreamImpl // OnStreamGenerated. bool generated; const bool enable_automatic_output_device_selection; - WebKit::WebFrame* frame; // WebFrame that requested the MediaStream. - WebKit::WebMediaStream web_stream; - WebKit::WebUserMediaRequest request; - WebKit::WebVector<WebKit::WebMediaStreamSource> audio_sources; - WebKit::WebVector<WebKit::WebMediaStreamSource> video_sources; + blink::WebFrame* frame; // WebFrame that requested the MediaStream. + blink::WebMediaStream web_stream; + blink::WebUserMediaRequest request; + std::vector<blink::WebMediaStreamSource> sources; }; typedef ScopedVector<UserMediaRequestInfo> UserMediaRequests; + struct LocalStreamSource { + LocalStreamSource(blink::WebFrame* frame, + const blink::WebMediaStreamSource& source) + : frame(frame), source(source) { + } + // |frame| is the WebFrame that requested |source|. NULL in unit tests. + // TODO(perkj): Change so that |frame| is not NULL in unit tests. + blink::WebFrame* frame; + blink::WebMediaStreamSource source; + }; + typedef std::vector<LocalStreamSource> LocalStreamSources; + + // Creates a WebKit representation of stream sources based on + // |devices| from the MediaStreamDispatcher. + void CreateWebKitSourceVector( + const std::string& label, + const StreamDeviceInfoArray& devices, + blink::WebMediaStreamSource::Type type, + blink::WebFrame* frame, + blink::WebVector<blink::WebMediaStreamSource>& webkit_sources); + UserMediaRequestInfo* FindUserMediaRequestInfo(int request_id); UserMediaRequestInfo* FindUserMediaRequestInfo( - WebKit::WebMediaStream* web_stream); + blink::WebMediaStream* web_stream); UserMediaRequestInfo* FindUserMediaRequestInfo( - const WebKit::WebUserMediaRequest& request); + const blink::WebUserMediaRequest& request); UserMediaRequestInfo* FindUserMediaRequestInfo(const std::string& label); void DeleteUserMediaRequestInfo(UserMediaRequestInfo* request); - scoped_refptr<VideoFrameProvider> - CreateVideoFrameProvider( - webrtc::MediaStreamInterface* stream, - const base::Closure& error_cb, - const VideoFrameProvider::RepaintCB& repaint_cb); + // Returns the source that use a device with |device.session_id| + // and |device.device.id|. NULL if such source doesn't exist. + const blink::WebMediaStreamSource* FindLocalSource( + const StreamDeviceInfo& device) const; + + // Returns true if |source| exists in |user_media_requests_| + bool FindSourceInRequests(const blink::WebMediaStreamSource& source) const; + + void StopLocalSource(const blink::WebMediaStreamSource& source, + bool notify_dispatcher); + // Stops all local sources that don't exist in exist in + // |user_media_requests_|. + void StopUnreferencedSources(bool notify_dispatcher); + scoped_refptr<WebRtcAudioRenderer> CreateRemoteAudioRenderer( webrtc::MediaStreamInterface* stream); scoped_refptr<WebRtcLocalAudioRenderer> CreateLocalAudioRenderer( - webrtc::MediaStreamInterface* stream); - - void StopLocalAudioTrack(const WebKit::WebMediaStream& web_stream); + const blink::WebMediaStreamTrack& audio_track); // Returns a valid session id if a single capture device is currently open // (and then the matching session_id), otherwise -1. @@ -176,6 +206,8 @@ class CONTENT_EXPORT MediaStreamImpl UserMediaRequests user_media_requests_; + LocalStreamSources local_sources_; + DISALLOW_COPY_AND_ASSIGN(MediaStreamImpl); }; diff --git a/chromium/content/renderer/media/media_stream_impl_unittest.cc b/chromium/content/renderer/media/media_stream_impl_unittest.cc index ea0b834039e..644f2cd483d 100644 --- a/chromium/content/renderer/media/media_stream_impl_unittest.cc +++ b/chromium/content/renderer/media/media_stream_impl_unittest.cc @@ -34,34 +34,35 @@ class MediaStreamImplUnderTest : public MediaStreamImpl { } void RequestUserMedia() { - WebKit::WebUserMediaRequest user_media_request; + blink::WebUserMediaRequest user_media_request; state_ = REQUEST_NOT_COMPLETE; requestUserMedia(user_media_request); } virtual void CompleteGetUserMediaRequest( - const WebKit::WebMediaStream& stream, - WebKit::WebUserMediaRequest* request_info, + const blink::WebMediaStream& stream, + blink::WebUserMediaRequest* request_info, bool request_succeeded) OVERRIDE { last_generated_stream_ = stream; state_ = request_succeeded ? REQUEST_SUCCEEDED : REQUEST_FAILED; } - virtual WebKit::WebMediaStream GetMediaStream( + virtual blink::WebMediaStream GetMediaStream( const GURL& url) OVERRIDE { return last_generated_stream_; } using MediaStreamImpl::OnLocalMediaStreamStop; + using MediaStreamImpl::OnLocalSourceStop; - const WebKit::WebMediaStream& last_generated_stream() { + const blink::WebMediaStream& last_generated_stream() { return last_generated_stream_; } RequestState request_state() const { return state_; } private: - WebKit::WebMediaStream last_generated_stream_; + blink::WebMediaStream last_generated_stream_; RequestState state_; }; @@ -75,7 +76,7 @@ class MediaStreamImplTest : public ::testing::Test { dependency_factory_.get())); } - WebKit::WebMediaStream RequestLocalMediaStream() { + blink::WebMediaStream RequestLocalMediaStream() { ms_impl_->RequestUserMedia(); FakeMediaStreamDispatcherComplete(); ChangeVideoSourceStateToLive(); @@ -84,7 +85,7 @@ class MediaStreamImplTest : public ::testing::Test { EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_SUCCEEDED, ms_impl_->request_state()); - WebKit::WebMediaStream desc = ms_impl_->last_generated_stream(); + blink::WebMediaStream desc = ms_impl_->last_generated_stream(); content::MediaStreamExtraData* extra_data = static_cast<content::MediaStreamExtraData*>(desc.extraData()); if (!extra_data || !extra_data->stream().get()) { @@ -136,26 +137,128 @@ class MediaStreamImplTest : public ::testing::Test { scoped_ptr<MockMediaStreamDependencyFactory> dependency_factory_; }; -TEST_F(MediaStreamImplTest, LocalMediaStream) { - // Test a stream with both audio and video. - WebKit::WebMediaStream mixed_desc = RequestLocalMediaStream(); +TEST_F(MediaStreamImplTest, GenerateMediaStream) { + // Generate a stream with both audio and video. + blink::WebMediaStream mixed_desc = RequestLocalMediaStream(); +} + +// Test that the same source object is used if two MediaStreams are generated +// using the same source. +TEST_F(MediaStreamImplTest, GenerateTwoMediaStreamsWithSameSource) { + blink::WebMediaStream desc1 = RequestLocalMediaStream(); + blink::WebMediaStream desc2 = RequestLocalMediaStream(); + + blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks; + desc1.videoTracks(desc1_video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks; + desc2.videoTracks(desc2_video_tracks); + EXPECT_EQ(desc1_video_tracks[0].source().id(), + desc2_video_tracks[0].source().id()); + + EXPECT_EQ(desc1_video_tracks[0].source().extraData(), + desc2_video_tracks[0].source().extraData()); + + blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks; + desc1.audioTracks(desc1_audio_tracks); + blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks; + desc2.audioTracks(desc2_audio_tracks); + EXPECT_EQ(desc1_audio_tracks[0].source().id(), + desc2_audio_tracks[0].source().id()); + + EXPECT_EQ(desc1_audio_tracks[0].source().extraData(), + desc2_audio_tracks[0].source().extraData()); +} - // Test a stream with audio only. - WebKit::WebMediaStream audio_desc = RequestLocalMediaStream(); +// Test that the same source object is not used if two MediaStreams are +// generated using different sources. +TEST_F(MediaStreamImplTest, GenerateTwoMediaStreamsWithDifferentSources) { + blink::WebMediaStream desc1 = RequestLocalMediaStream(); + // Make sure another device is selected (another |session_id|) in the next + // gUM request. + ms_dispatcher_->IncrementSessionId(); + blink::WebMediaStream desc2 = RequestLocalMediaStream(); + + blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks; + desc1.videoTracks(desc1_video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks; + desc2.videoTracks(desc2_video_tracks); + EXPECT_NE(desc1_video_tracks[0].source().id(), + desc2_video_tracks[0].source().id()); + + EXPECT_NE(desc1_video_tracks[0].source().extraData(), + desc2_video_tracks[0].source().extraData()); + + blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks; + desc1.audioTracks(desc1_audio_tracks); + blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks; + desc2.audioTracks(desc2_audio_tracks); + EXPECT_NE(desc1_audio_tracks[0].source().id(), + desc2_audio_tracks[0].source().id()); + + EXPECT_NE(desc1_audio_tracks[0].source().extraData(), + desc2_audio_tracks[0].source().extraData()); +} - // Test a stream with video only. - WebKit::WebMediaStream video_desc = RequestLocalMediaStream(); +TEST_F(MediaStreamImplTest, StopLocalMediaStream) { + // Generate a stream with both audio and video. + blink::WebMediaStream mixed_desc = RequestLocalMediaStream(); // Stop generated local streams. ms_impl_->OnLocalMediaStreamStop(mixed_desc.id().utf8()); - EXPECT_EQ(1, ms_dispatcher_->stop_stream_counter()); - ms_impl_->OnLocalMediaStreamStop(audio_desc.id().utf8()); - EXPECT_EQ(2, ms_dispatcher_->stop_stream_counter()); + EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); + EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); +} + +// This test that a source is not stopped even if the MediaStream is stopped if +// there are two MediaStreams using the same device. The source is stopped +// if there are no more MediaStreams using the device. +TEST_F(MediaStreamImplTest, StopLocalMediaStreamWhenTwoStreamUseSameDevices) { + // Generate a stream with both audio and video. + blink::WebMediaStream desc1 = RequestLocalMediaStream(); + blink::WebMediaStream desc2 = RequestLocalMediaStream(); + + ms_impl_->OnLocalMediaStreamStop(desc2.id().utf8()); + EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter()); + EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter()); + + ms_impl_->OnLocalMediaStreamStop(desc1.id().utf8()); + EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); + EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); +} + +// Test that the source is stopped even if there are two MediaStreams using +// the same source. +TEST_F(MediaStreamImplTest, StopSource) { + // Generate a stream with both audio and video. + blink::WebMediaStream desc1 = RequestLocalMediaStream(); + blink::WebMediaStream desc2 = RequestLocalMediaStream(); + + // Stop the video source. + blink::WebVector<blink::WebMediaStreamTrack> video_tracks; + desc1.videoTracks(video_tracks); + ms_impl_->OnLocalSourceStop(video_tracks[0].source()); + EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter()); + EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); + + // Stop the audio source. + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; + desc1.audioTracks(audio_tracks); + ms_impl_->OnLocalSourceStop(audio_tracks[0].source()); + EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); + EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); +} + +// Test that the MediaStreams are deleted if the owning WebFrame is deleted. +// In the unit test the owning frame is NULL. +TEST_F(MediaStreamImplTest, FrameWillClose) { + // Test a stream with both audio and video. + blink::WebMediaStream mixed_desc = RequestLocalMediaStream(); // Test that the MediaStreams are deleted if the owning WebFrame is deleted. // In the unit test the owning frame is NULL. ms_impl_->FrameWillClose(NULL); - EXPECT_EQ(3, ms_dispatcher_->stop_stream_counter()); + EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); + EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); } // This test what happens if a source to a MediaSteam fails to start. @@ -167,7 +270,8 @@ TEST_F(MediaStreamImplTest, MediaSourceFailToStart) { EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_FAILED, ms_impl_->request_state()); EXPECT_EQ(1, ms_dispatcher_->request_stream_counter()); - EXPECT_EQ(1, ms_dispatcher_->stop_stream_counter()); + EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); + EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); } // This test what happens if MediaStreamImpl is deleted while the sources of a @@ -189,7 +293,8 @@ TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingStream) { ms_impl_->RequestUserMedia(); ms_impl_->FrameWillClose(NULL); EXPECT_EQ(1, ms_dispatcher_->request_stream_counter()); - EXPECT_EQ(0, ms_dispatcher_->stop_stream_counter()); + EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter()); + EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter()); ChangeAudioSourceStateToLive(); ChangeVideoSourceStateToLive(); EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE, @@ -201,10 +306,10 @@ TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingStream) { TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingSources) { ms_impl_->RequestUserMedia(); FakeMediaStreamDispatcherComplete(); - EXPECT_EQ(0, ms_dispatcher_->stop_stream_counter()); EXPECT_EQ(1, ms_dispatcher_->request_stream_counter()); ms_impl_->FrameWillClose(NULL); - EXPECT_EQ(1, ms_dispatcher_->stop_stream_counter()); + EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); + EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); ChangeAudioSourceStateToLive(); ChangeVideoSourceStateToLive(); EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE, @@ -214,13 +319,14 @@ TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingSources) { // This test what happens if stop is called on a stream after the frame has // been reloaded. TEST_F(MediaStreamImplTest, StopStreamAfterReload) { - WebKit::WebMediaStream mixed_desc = RequestLocalMediaStream(); - EXPECT_EQ(0, ms_dispatcher_->stop_stream_counter()); + blink::WebMediaStream mixed_desc = RequestLocalMediaStream(); EXPECT_EQ(1, ms_dispatcher_->request_stream_counter()); ms_impl_->FrameWillClose(NULL); - EXPECT_EQ(1, ms_dispatcher_->stop_stream_counter()); + EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); + EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); ms_impl_->OnLocalMediaStreamStop(mixed_desc.id().utf8()); - EXPECT_EQ(1, ms_dispatcher_->stop_stream_counter()); + EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter()); + EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter()); } } // namespace content diff --git a/chromium/content/renderer/media/media_stream_registry_interface.h b/chromium/content/renderer/media/media_stream_registry_interface.h index af4c26a4e78..ace11c5e396 100644 --- a/chromium/content/renderer/media/media_stream_registry_interface.h +++ b/chromium/content/renderer/media/media_stream_registry_interface.h @@ -14,7 +14,7 @@ namespace content { // Interface to get WebMediaStream from its url. class MediaStreamRegistryInterface { public: - virtual WebKit::WebMediaStream GetMediaStream(const std::string& url) = 0; + virtual blink::WebMediaStream GetMediaStream(const std::string& url) = 0; protected: virtual ~MediaStreamRegistryInterface() {} diff --git a/chromium/content/renderer/media/media_stream_source_extra_data.h b/chromium/content/renderer/media/media_stream_source_extra_data.h index bb06435c158..4b88c147f8b 100644 --- a/chromium/content/renderer/media/media_stream_source_extra_data.h +++ b/chromium/content/renderer/media/media_stream_source_extra_data.h @@ -5,29 +5,28 @@ #ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_SOURCE_EXTRA_DATA_H_ #define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_SOURCE_EXTRA_DATA_H_ +#include "base/callback.h" #include "base/compiler_specific.h" #include "content/common/content_export.h" #include "content/common/media/media_stream_options.h" #include "content/renderer/media/media_stream_source_observer.h" +#include "content/renderer/media/webrtc_audio_capturer.h" #include "third_party/libjingle/source/talk/app/webrtc/videosourceinterface.h" #include "third_party/WebKit/public/platform/WebMediaStreamSource.h" namespace content { class CONTENT_EXPORT MediaStreamSourceExtraData - : NON_EXPORTED_BASE(public WebKit::WebMediaStreamSource::ExtraData) { + : NON_EXPORTED_BASE(public blink::WebMediaStreamSource::ExtraData) { public: - MediaStreamSourceExtraData( - const StreamDeviceInfo& device_info, - const WebKit::WebMediaStreamSource& webkit_source); + typedef base::Callback<void(const blink::WebMediaStreamSource& source)> + SourceStopCallback; + + MediaStreamSourceExtraData(const StreamDeviceInfo& device_info, + const SourceStopCallback& stop_callback); MediaStreamSourceExtraData(); virtual ~MediaStreamSourceExtraData(); - // Returns the WebMediaStreamSource object that owns this object. - const WebKit::WebMediaStreamSource& webkit_source() const { - return webkit_source_; - } - // Return device information about the camera or microphone. const StreamDeviceInfo& device_info() const { return device_info_; @@ -44,23 +43,34 @@ class CONTENT_EXPORT MediaStreamSourceExtraData // See |source_observer_|. } + void SetAudioCapturer(WebRtcAudioCapturer* capturer) { + DCHECK(!audio_capturer_); + audio_capturer_ = capturer; + } + + WebRtcAudioCapturer* GetAudioCapturer() const { + // TODO(perkj): |audio_capturer_| can currently be reconfigured to use + // another microphone even after it has been created since only one + // capturer is supported. See issue crbug/262117. + // It would make more sense if a WebRtcAudioCapturer represent one and only + // one audio source. + if (audio_capturer_ && + device_info_.session_id == audio_capturer_->session_id()) { + return audio_capturer_; + } + return NULL; + } + webrtc::VideoSourceInterface* video_source() { return video_source_.get(); } webrtc::AudioSourceInterface* local_audio_source() { return local_audio_source_.get(); } + void OnLocalSourceStop(); + private: StreamDeviceInfo device_info_; - // TODO(tommyw): Remove |webkit_source_| after WebMediaStreamSource::Owner() - // is implemented, which let us fetch the - // WebMediaStreamSource without increasing the reference count. - // |webkit_source_| will create a circular reference to WebMediaStreamSource. - // WebMediaStreamSource -> MediaStreamSourceExtraData -> WebMediaStreamSource - // Currently, we rely on manually releasing the MediaStreamSourceExtraData - // from WebMediaStreamSource like what - // MediaStreamImpl::~UserMediaRequestInfo() does. - WebKit::WebMediaStreamSource webkit_source_; scoped_refptr<webrtc::VideoSourceInterface> video_source_; // This member holds an instance of webrtc::LocalAudioSource. This is used @@ -70,6 +80,10 @@ class CONTENT_EXPORT MediaStreamSourceExtraData scoped_refptr<webrtc::AudioSourceInterface> local_audio_source_; scoped_ptr<MediaStreamSourceObserver> source_observer_; + scoped_refptr<WebRtcAudioCapturer> audio_capturer_; + + SourceStopCallback stop_callback_; + DISALLOW_COPY_AND_ASSIGN(MediaStreamSourceExtraData); }; diff --git a/chromium/content/renderer/media/media_stream_source_observer.cc b/chromium/content/renderer/media/media_stream_source_observer.cc index 1f165bbfa37..319327fa72d 100644 --- a/chromium/content/renderer/media/media_stream_source_observer.cc +++ b/chromium/content/renderer/media/media_stream_source_observer.cc @@ -33,7 +33,7 @@ void MediaStreamSourceObserver::OnChanged() { if (state == state_) return; state_ = state; - WebKit::WebMediaStreamSource webkit_source(extra_data_->webkit_source()); + blink::WebMediaStreamSource webkit_source(extra_data_->owner()); switch (state) { case webrtc::MediaSourceInterface::kInitializing: @@ -42,15 +42,15 @@ void MediaStreamSourceObserver::OnChanged() { break; case webrtc::MediaSourceInterface::kLive: webkit_source.setReadyState( - WebKit::WebMediaStreamSource::ReadyStateLive); + blink::WebMediaStreamSource::ReadyStateLive); break; case webrtc::MediaSourceInterface::kMuted: webkit_source.setReadyState( - WebKit::WebMediaStreamSource::ReadyStateMuted); + blink::WebMediaStreamSource::ReadyStateMuted); break; case webrtc::MediaSourceInterface::kEnded: webkit_source.setReadyState( - WebKit::WebMediaStreamSource::ReadyStateEnded); + blink::WebMediaStreamSource::ReadyStateEnded); webrtc_source_->UnregisterObserver(this); webrtc_source_ = NULL; break; diff --git a/chromium/content/renderer/media/media_stream_track_extra_data.cc b/chromium/content/renderer/media/media_stream_track_extra_data.cc new file mode 100644 index 00000000000..0fbb29496b3 --- /dev/null +++ b/chromium/content/renderer/media/media_stream_track_extra_data.cc @@ -0,0 +1,20 @@ +// 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/renderer/media/media_stream_track_extra_data.h" + +#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" + +namespace content { + +MediaStreamTrackExtraData::MediaStreamTrackExtraData( + webrtc::MediaStreamTrackInterface* track, bool is_local_track) + : track_(track), + is_local_track_(is_local_track) { +} + +MediaStreamTrackExtraData::~MediaStreamTrackExtraData() { +} + +} // namespace content diff --git a/chromium/content/renderer/media/media_stream_track_extra_data.h b/chromium/content/renderer/media/media_stream_track_extra_data.h new file mode 100644 index 00000000000..dbc25b46dec --- /dev/null +++ b/chromium/content/renderer/media/media_stream_track_extra_data.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. + +#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_TRACK_EXTRA_DATA_H_ +#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_TRACK_EXTRA_DATA_H_ + +#include "base/callback.h" +#include "base/compiler_specific.h" +#include "base/memory/ref_counted.h" +#include "content/common/content_export.h" +#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" + +namespace webrtc { +class MediaStreamTrackInterface; +} // namespace webrtc + +namespace content { + +class CONTENT_EXPORT MediaStreamTrackExtraData + : NON_EXPORTED_BASE(public blink::WebMediaStreamTrack::ExtraData) { + public: + MediaStreamTrackExtraData(webrtc::MediaStreamTrackInterface* track, + bool is_local_track); + virtual ~MediaStreamTrackExtraData(); + + const scoped_refptr<webrtc::MediaStreamTrackInterface>& track() const { + return track_; + } + bool is_local_track () const { return is_local_track_; } + + private: + scoped_refptr<webrtc::MediaStreamTrackInterface> track_; + const bool is_local_track_; + + DISALLOW_COPY_AND_ASSIGN(MediaStreamTrackExtraData); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_TRACK_EXTRA_DATA_H_ diff --git a/chromium/content/renderer/media/media_stream_video_track.cc b/chromium/content/renderer/media/media_stream_video_track.cc new file mode 100644 index 00000000000..44962445161 --- /dev/null +++ b/chromium/content/renderer/media/media_stream_video_track.cc @@ -0,0 +1,47 @@ +// 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/renderer/media/media_stream_video_track.h" + +#include "content/renderer/media/webrtc/webrtc_video_sink_adapter.h" + +namespace content { + +// Wrapper which allows to use std::find_if() when adding and removing +// sinks to/from |sinks_|. +struct SinkWrapper { + explicit SinkWrapper(MediaStreamVideoSink* sink) : sink_(sink) {} + bool operator()( + const WebRtcVideoSinkAdapter* owner) { + return owner->sink() == sink_; + } + MediaStreamVideoSink* sink_; +}; + +MediaStreamVideoTrack::MediaStreamVideoTrack(webrtc::VideoTrackInterface* track, + bool is_local_track) + : MediaStreamTrackExtraData(track, is_local_track), + video_track_(track) { +} + +MediaStreamVideoTrack::~MediaStreamVideoTrack() { + DCHECK(sinks_.empty()); +} + +void MediaStreamVideoTrack::AddSink(MediaStreamVideoSink* sink) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(std::find_if(sinks_.begin(), sinks_.end(), + SinkWrapper(sink)) == sinks_.end()); + sinks_.push_back(new WebRtcVideoSinkAdapter(video_track_, sink)); +} + +void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) { + DCHECK(thread_checker_.CalledOnValidThread()); + ScopedVector<WebRtcVideoSinkAdapter>::iterator it = + std::find_if(sinks_.begin(), sinks_.end(), SinkWrapper(sink)); + DCHECK(it != sinks_.end()); + sinks_.erase(it); +} + +} // namespace content diff --git a/chromium/content/renderer/media/media_stream_video_track.h b/chromium/content/renderer/media/media_stream_video_track.h new file mode 100644 index 00000000000..410a8f9a40b --- /dev/null +++ b/chromium/content/renderer/media/media_stream_video_track.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_RENDERER_MEDIA_MEDIA_STREAM_VIDEO_TRACK_H_ +#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_VIDEO_TRACK_H_ + +#include "base/compiler_specific.h" +#include "base/memory/scoped_vector.h" +#include "base/threading/thread_checker.h" +#include "content/common/content_export.h" +#include "content/public/renderer/media_stream_video_sink.h" +#include "content/renderer/media/media_stream_track_extra_data.h" + +namespace webrtc { +class VideoTrackInterface; +} + +namespace content { + +class WebRtcVideoSinkAdapter; + +// MediaStreamVideoTrack is a video specific representation of a +// blink::WebMediaStreamTrack in content. It is owned by the blink object +// and can be retrieved from a blink object using +// WebMediaStreamTrack::extraData() +class CONTENT_EXPORT MediaStreamVideoTrack : public MediaStreamTrackExtraData { + public: + MediaStreamVideoTrack(webrtc::VideoTrackInterface* track, + bool is_local_track); + virtual ~MediaStreamVideoTrack(); + void AddSink(MediaStreamVideoSink* sink); + void RemoveSink(MediaStreamVideoSink* sink); + + private: + // Used to DCHECK that we are called on the correct thread. + base::ThreadChecker thread_checker_; + // The webrtc video track. + // TODO(perkj): Make this class independent of webrtc as part of project + // Piranha Plant. + webrtc::VideoTrackInterface* video_track_; + ScopedVector<WebRtcVideoSinkAdapter> sinks_; + + DISALLOW_COPY_AND_ASSIGN(MediaStreamVideoTrack); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_VIDEO_TRACK_H_ diff --git a/chromium/content/renderer/media/midi_dispatcher.cc b/chromium/content/renderer/media/midi_dispatcher.cc index edd57c23ee1..1f04e3e22f8 100644 --- a/chromium/content/renderer/media/midi_dispatcher.cc +++ b/chromium/content/renderer/media/midi_dispatcher.cc @@ -11,8 +11,8 @@ #include "third_party/WebKit/public/web/WebMIDIPermissionRequest.h" #include "third_party/WebKit/public/web/WebSecurityOrigin.h" -using WebKit::WebMIDIPermissionRequest; -using WebKit::WebSecurityOrigin; +using blink::WebMIDIPermissionRequest; +using blink::WebSecurityOrigin; namespace content { @@ -34,11 +34,11 @@ bool MIDIDispatcher::OnMessageReceived(const IPC::Message& message) { void MIDIDispatcher::requestSysExPermission( const WebMIDIPermissionRequest& request) { - int client_id = requests_.Add(new WebMIDIPermissionRequest(request)); + int bridge_id = requests_.Add(new WebMIDIPermissionRequest(request)); WebSecurityOrigin security_origin = request.securityOrigin(); std::string origin = security_origin.toString().utf8(); GURL url(origin); - Send(new MIDIHostMsg_RequestSysExPermission(routing_id(), client_id, url)); + Send(new MIDIHostMsg_RequestSysExPermission(routing_id(), bridge_id, url)); } void MIDIDispatcher::cancelSysExPermissionRequest( @@ -47,19 +47,23 @@ void MIDIDispatcher::cancelSysExPermissionRequest( !it.IsAtEnd(); it.Advance()) { WebMIDIPermissionRequest* value = it.GetCurrentValue(); - if (!value->equals(request)) - continue; - requests_.Remove(it.GetCurrentKey()); + if (value->equals(request)) { + base::string16 origin = request.securityOrigin().toString(); + Send(new MIDIHostMsg_CancelSysExPermissionRequest( + routing_id(), it.GetCurrentKey(), GURL(origin))); + requests_.Remove(it.GetCurrentKey()); + break; + } } } -void MIDIDispatcher::OnSysExPermissionApproved(int client_id, bool is_allowed) { +void MIDIDispatcher::OnSysExPermissionApproved(int bridge_id, bool is_allowed) { // |request| can be NULL when the request is canceled. - WebMIDIPermissionRequest* request = requests_.Lookup(client_id); + WebMIDIPermissionRequest* request = requests_.Lookup(bridge_id); if (!request) return; request->setIsAllowed(is_allowed); - requests_.Remove(client_id); + requests_.Remove(bridge_id); } } // namespace content diff --git a/chromium/content/renderer/media/midi_dispatcher.h b/chromium/content/renderer/media/midi_dispatcher.h index 143d706987e..70f8125bdd2 100644 --- a/chromium/content/renderer/media/midi_dispatcher.h +++ b/chromium/content/renderer/media/midi_dispatcher.h @@ -9,7 +9,7 @@ #include "content/public/renderer/render_view_observer.h" #include "third_party/WebKit/public/web/WebMIDIClient.h" -namespace WebKit { +namespace blink { class WebMIDIPermissionRequest; } @@ -23,7 +23,7 @@ class RenderViewImpl; // MIDIDispatcherHost owned by RenderViewHost since permissions are managed in // the browser process. class MIDIDispatcher : public RenderViewObserver, - public WebKit::WebMIDIClient { + public blink::WebMIDIClient { public: explicit MIDIDispatcher(RenderViewImpl* render_view); virtual ~MIDIDispatcher(); @@ -32,11 +32,11 @@ class MIDIDispatcher : public RenderViewObserver, // RenderView::Observer implementation. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - // WebKit::WebMIDIClient implementation. + // blink::WebMIDIClient implementation. virtual void requestSysExPermission( - const WebKit::WebMIDIPermissionRequest& request) OVERRIDE; + const blink::WebMIDIPermissionRequest& request) OVERRIDE; virtual void cancelSysExPermissionRequest( - const WebKit::WebMIDIPermissionRequest& request) OVERRIDE; + const blink::WebMIDIPermissionRequest& request) OVERRIDE; // Permission for using system exclusive messages has been set. void OnSysExPermissionApproved(int client_id, bool is_allowed); @@ -44,7 +44,7 @@ class MIDIDispatcher : public RenderViewObserver, // Each WebMIDIPermissionRequest object is valid until // cancelSysExPermissionRequest() is called with the object, or used to call // WebMIDIPermissionRequest::setIsAllowed(). - IDMap<WebKit::WebMIDIPermissionRequest> requests_; + IDMap<blink::WebMIDIPermissionRequest> requests_; DISALLOW_COPY_AND_ASSIGN(MIDIDispatcher); }; diff --git a/chromium/content/renderer/media/midi_message_filter.cc b/chromium/content/renderer/media/midi_message_filter.cc index 32e8bdd2477..d114618ec60 100644 --- a/chromium/content/renderer/media/midi_message_filter.cc +++ b/chromium/content/renderer/media/midi_message_filter.cc @@ -72,7 +72,7 @@ void MIDIMessageFilter::OnChannelClosing() { channel_ = NULL; } -void MIDIMessageFilter::StartSession(WebKit::WebMIDIAccessorClient* client) { +void MIDIMessageFilter::StartSession(blink::WebMIDIAccessorClient* client) { // Generate and keep track of a "client id" which is sent to the browser // to ask permission to talk to MIDI hardware. // This id is handed back when we receive the answer in OnAccessApproved(). @@ -90,7 +90,7 @@ void MIDIMessageFilter::StartSessionOnIOThread(int client_id) { Send(new MIDIHostMsg_StartSession(client_id)); } -void MIDIMessageFilter::RemoveClient(WebKit::WebMIDIAccessorClient* client) { +void MIDIMessageFilter::RemoveClient(blink::WebMIDIAccessorClient* client) { ClientsMap::iterator i = clients_.find(client); if (i != clients_.end()) clients_.erase(i); @@ -115,7 +115,7 @@ void MIDIMessageFilter::HandleSessionStarted( bool success, MIDIPortInfoList inputs, MIDIPortInfoList outputs) { - WebKit::WebMIDIAccessorClient* client = GetClientFromId(client_id); + blink::WebMIDIAccessorClient* client = GetClientFromId(client_id); if (!client) return; @@ -140,7 +140,7 @@ void MIDIMessageFilter::HandleSessionStarted( client->didStartSession(success); } -WebKit::WebMIDIAccessorClient* +blink::WebMIDIAccessorClient* MIDIMessageFilter::GetClientFromId(int client_id) { // Iterating like this seems inefficient, but in practice there generally // will be very few clients (usually one). Additionally, this lookup diff --git a/chromium/content/renderer/media/midi_message_filter.h b/chromium/content/renderer/media/midi_message_filter.h index 4b8481fbc57..c2e66ae4d0c 100644 --- a/chromium/content/renderer/media/midi_message_filter.h +++ b/chromium/content/renderer/media/midi_message_filter.h @@ -31,8 +31,8 @@ class CONTENT_EXPORT MIDIMessageFilter // If permission is granted, then the client's // addInputPort() and addOutputPort() methods will be called, // giving the client access to receive and send data. - void StartSession(WebKit::WebMIDIAccessorClient* client); - void RemoveClient(WebKit::WebMIDIAccessorClient* client); + void StartSession(blink::WebMIDIAccessorClient* client); + void RemoveClient(blink::WebMIDIAccessorClient* client); // A client will only be able to call this method if it has a suitable // output port (from addOutputPort()). @@ -92,7 +92,7 @@ class CONTENT_EXPORT MIDIMessageFilter const std::vector<uint8>& data, double timestamp); - WebKit::WebMIDIAccessorClient* GetClientFromId(int client_id); + blink::WebMIDIAccessorClient* GetClientFromId(int client_id); // IPC channel for Send(); must only be accessed on |io_message_loop_|. IPC::Channel* channel_; @@ -107,7 +107,7 @@ class CONTENT_EXPORT MIDIMessageFilter // We map client to "client id" used to track permission. // When access has been approved, we add the input and output ports to // the client, allowing it to actually receive and send MIDI data. - typedef std::map<WebKit::WebMIDIAccessorClient*, int> ClientsMap; + typedef std::map<blink::WebMIDIAccessorClient*, int> ClientsMap; ClientsMap clients_; // Dishes out client ids. diff --git a/chromium/content/renderer/media/mock_media_stream_dependency_factory.cc b/chromium/content/renderer/media/mock_media_stream_dependency_factory.cc index 6067c1117bb..8de0e2b43dd 100644 --- a/chromium/content/renderer/media/mock_media_stream_dependency_factory.cc +++ b/chromium/content/renderer/media/mock_media_stream_dependency_factory.cc @@ -135,7 +135,8 @@ void MockAudioSource::UnregisterObserver(webrtc::ObserverInterface* observer) { } void MockAudioSource::SetLive() { - DCHECK_EQ(MediaSourceInterface::kInitializing, state_); + DCHECK(state_ == MediaSourceInterface::kInitializing || + state_ == MediaSourceInterface::kLive); state_ = MediaSourceInterface::kLive; if (observer_) observer_->OnChanged(); @@ -202,7 +203,8 @@ void MockVideoSource::FireOnChanged() { } void MockVideoSource::SetLive() { - DCHECK_EQ(MediaSourceInterface::kInitializing, state_); + DCHECK(state_ == MediaSourceInterface::kInitializing || + state_ == MediaSourceInterface::kLive); state_ = MediaSourceInterface::kLive; FireOnChanged(); } @@ -384,7 +386,7 @@ scoped_refptr<webrtc::PeerConnectionInterface> MockMediaStreamDependencyFactory::CreatePeerConnection( const webrtc::PeerConnectionInterface::IceServers& ice_servers, const webrtc::MediaConstraintsInterface* constraints, - WebKit::WebFrame* frame, + blink::WebFrame* frame, webrtc::PeerConnectionObserver* observer) { DCHECK(mock_pc_factory_created_); return new talk_base::RefCountedObject<MockPeerConnectionImpl>(this); @@ -409,7 +411,7 @@ MockMediaStreamDependencyFactory::CreateLocalVideoSource( scoped_refptr<WebAudioCapturerSource> MockMediaStreamDependencyFactory::CreateWebAudioSource( - WebKit::WebMediaStreamSource* source, + blink::WebMediaStreamSource* source, RTCMediaConstraints* constraints) { return NULL; } diff --git a/chromium/content/renderer/media/mock_media_stream_dependency_factory.h b/chromium/content/renderer/media/mock_media_stream_dependency_factory.h index 7152d119608..bd73ec7bd9b 100644 --- a/chromium/content/renderer/media/mock_media_stream_dependency_factory.h +++ b/chromium/content/renderer/media/mock_media_stream_dependency_factory.h @@ -118,7 +118,7 @@ class MockMediaStreamDependencyFactory : public MediaStreamDependencyFactory { virtual scoped_refptr<webrtc::PeerConnectionInterface> CreatePeerConnection( const webrtc::PeerConnectionInterface::IceServers& ice_servers, const webrtc::MediaConstraintsInterface* constraints, - WebKit::WebFrame* frame, + blink::WebFrame* frame, webrtc::PeerConnectionObserver* observer) OVERRIDE; virtual scoped_refptr<webrtc::AudioSourceInterface> CreateLocalAudioSource( @@ -129,7 +129,7 @@ class MockMediaStreamDependencyFactory : public MediaStreamDependencyFactory { bool is_screencast, const webrtc::MediaConstraintsInterface* constraints) OVERRIDE; virtual scoped_refptr<WebAudioCapturerSource> CreateWebAudioSource( - WebKit::WebMediaStreamSource* source, + blink::WebMediaStreamSource* source, RTCMediaConstraints* constraints) OVERRIDE; virtual scoped_refptr<webrtc::MediaStreamInterface> CreateLocalMediaStream(const std::string& label) OVERRIDE; diff --git a/chromium/content/renderer/media/mock_media_stream_dispatcher.cc b/chromium/content/renderer/media/mock_media_stream_dispatcher.cc index b6a163a9c5f..ed5c91c91ee 100644 --- a/chromium/content/renderer/media/mock_media_stream_dispatcher.cc +++ b/chromium/content/renderer/media/mock_media_stream_dispatcher.cc @@ -4,7 +4,7 @@ #include "content/renderer/media/mock_media_stream_dispatcher.h" -#include "base/strings/stringprintf.h" +#include "base/strings/string_number_conversions.h" #include "content/public/common/media_stream_request.h" #include "testing/gtest/include/gtest/gtest.h" @@ -14,7 +14,9 @@ MockMediaStreamDispatcher::MockMediaStreamDispatcher() : MediaStreamDispatcher(NULL), request_id_(-1), request_stream_counter_(0), - stop_stream_counter_(0) { + stop_audio_device_counter_(0), + stop_video_device_counter_(0), + session_id_(0) { } MockMediaStreamDispatcher::~MockMediaStreamDispatcher() {} @@ -26,24 +28,24 @@ void MockMediaStreamDispatcher::GenerateStream( const GURL& url) { request_id_ = request_id; - stream_label_ = base::StringPrintf("%s%d","local_stream",request_id); + stream_label_ = "local_stream" + base::IntToString(request_id); audio_array_.clear(); video_array_.clear(); - if (IsAudioMediaType(components.audio_type)) { + if (components.audio_requested) { StreamDeviceInfo audio; - audio.device.id = "audio_device_id"; + audio.device.id = "audio_device_id" + base::IntToString(session_id_); audio.device.name = "microphone"; - audio.device.type = components.audio_type; - audio.session_id = request_id; + audio.device.type = MEDIA_DEVICE_AUDIO_CAPTURE; + audio.session_id = session_id_; audio_array_.push_back(audio); } - if (IsVideoMediaType(components.video_type)) { + if (components.video_requested) { StreamDeviceInfo video; - video.device.id = "video_device_id"; + video.device.id = "video_device_id" + base::IntToString(session_id_); video.device.name = "usb video camera"; - video.device.type = components.video_type; - video.session_id = request_id; + video.device.type = MEDIA_DEVICE_VIDEO_CAPTURE; + video.session_id = session_id_; video_array_.push_back(video); } ++request_stream_counter_; @@ -55,8 +57,17 @@ void MockMediaStreamDispatcher::CancelGenerateStream( EXPECT_EQ(request_id, request_id_); } -void MockMediaStreamDispatcher::StopStream(const std::string& label) { - ++stop_stream_counter_; +void MockMediaStreamDispatcher::StopStreamDevice( + const StreamDeviceInfo& device_info) { + if (IsAudioMediaType(device_info.device.type)) { + ++stop_audio_device_counter_; + return; + } + if (IsVideoMediaType(device_info.device.type)) { + ++stop_video_device_counter_; + return; + } + NOTREACHED(); } bool MockMediaStreamDispatcher::IsStream(const std::string& label) { diff --git a/chromium/content/renderer/media/mock_media_stream_dispatcher.h b/chromium/content/renderer/media/mock_media_stream_dispatcher.h index 23ecec0bfe5..d16f32d6f3f 100644 --- a/chromium/content/renderer/media/mock_media_stream_dispatcher.h +++ b/chromium/content/renderer/media/mock_media_stream_dispatcher.h @@ -27,14 +27,18 @@ class MockMediaStreamDispatcher : public MediaStreamDispatcher { int request_id, const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler) OVERRIDE; - virtual void StopStream(const std::string& label) OVERRIDE; + virtual void StopStreamDevice(const StreamDeviceInfo& device_info) OVERRIDE; virtual bool IsStream(const std::string& label) OVERRIDE; virtual int video_session_id(const std::string& label, int index) OVERRIDE; virtual int audio_session_id(const std::string& label, int index) OVERRIDE; int request_id() const { return request_id_; } int request_stream_counter() const { return request_stream_counter_; } - int stop_stream_counter() const { return stop_stream_counter_; } + void IncrementSessionId() { ++session_id_; } + + int stop_audio_device_counter() const { return stop_audio_device_counter_; } + int stop_video_device_counter() const { return stop_video_device_counter_; } + const std::string& stream_label() const { return stream_label_;} StreamDeviceInfoArray audio_array() const { return audio_array_; } StreamDeviceInfoArray video_array() const { return video_array_; } @@ -43,9 +47,11 @@ class MockMediaStreamDispatcher : public MediaStreamDispatcher { int request_id_; base::WeakPtr<MediaStreamDispatcherEventHandler> event_handler_; int request_stream_counter_; - int stop_stream_counter_; + int stop_audio_device_counter_; + int stop_video_device_counter_; std::string stream_label_; + int session_id_; StreamDeviceInfoArray audio_array_; StreamDeviceInfoArray video_array_; diff --git a/chromium/content/renderer/media/mock_media_stream_registry.cc b/chromium/content/renderer/media/mock_media_stream_registry.cc index 04621238f50..cc29c058e66 100644 --- a/chromium/content/renderer/media/mock_media_stream_registry.cc +++ b/chromium/content/renderer/media/mock_media_stream_registry.cc @@ -26,9 +26,9 @@ void MockMediaStreamRegistry::Init(const std::string& stream_url) { stream_url_ = stream_url; scoped_refptr<webrtc::MediaStreamInterface> stream( factory_->CreateLocalMediaStream(kTestStreamLabel)); - WebKit::WebVector<WebKit::WebMediaStreamTrack> webkit_audio_tracks; - WebKit::WebVector<WebKit::WebMediaStreamTrack> webkit_video_tracks; - WebKit::WebString webkit_stream_label(UTF8ToUTF16(stream->label())); + blink::WebVector<blink::WebMediaStreamTrack> webkit_audio_tracks; + blink::WebVector<blink::WebMediaStreamTrack> webkit_video_tracks; + blink::WebString webkit_stream_label(UTF8ToUTF16(stream->label())); test_stream_.initialize(webkit_stream_label, webkit_audio_tracks, webkit_video_tracks); test_stream_.setExtraData(new MediaStreamExtraData(stream.get(), false)); @@ -39,15 +39,15 @@ bool MockMediaStreamRegistry::AddVideoTrack(const std::string& track_id) { return factory_->AddNativeVideoMediaTrack(track_id, &test_stream_, capturer); } -WebKit::WebMediaStream MockMediaStreamRegistry::GetMediaStream( +blink::WebMediaStream MockMediaStreamRegistry::GetMediaStream( const std::string& url) { if (url != stream_url_) { - return WebKit::WebMediaStream(); + return blink::WebMediaStream(); } return test_stream_; } -const WebKit::WebMediaStream MockMediaStreamRegistry::test_stream() const { +const blink::WebMediaStream MockMediaStreamRegistry::test_stream() const { return test_stream_; } diff --git a/chromium/content/renderer/media/mock_media_stream_registry.h b/chromium/content/renderer/media/mock_media_stream_registry.h index 4d77395cced..c0dba849fb4 100644 --- a/chromium/content/renderer/media/mock_media_stream_registry.h +++ b/chromium/content/renderer/media/mock_media_stream_registry.h @@ -18,13 +18,13 @@ class MockMediaStreamRegistry : public MediaStreamRegistryInterface { void Init(const std::string& stream_label); bool AddVideoTrack(const std::string& track_id); - virtual WebKit::WebMediaStream GetMediaStream(const std::string& url) + virtual blink::WebMediaStream GetMediaStream(const std::string& url) OVERRIDE; - const WebKit::WebMediaStream test_stream() const; + const blink::WebMediaStream test_stream() const; private: MockMediaStreamDependencyFactory* factory_; - WebKit::WebMediaStream test_stream_; + blink::WebMediaStream test_stream_; std::string stream_url_; }; diff --git a/chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.cc b/chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.cc index 2eb8b08e328..a50525e1c39 100644 --- a/chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.cc +++ b/chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.cc @@ -30,7 +30,7 @@ MockWebRTCPeerConnectionHandlerClient:: ~MockWebRTCPeerConnectionHandlerClient() {} void MockWebRTCPeerConnectionHandlerClient::didGenerateICECandidateWorker( - const WebKit::WebRTCICECandidate& candidate) { + const blink::WebRTCICECandidate& candidate) { if (!candidate.isNull()) { candidate_sdp_ = UTF16ToUTF8(candidate.candidate()); candidate_mline_index_ = candidate.sdpMLineIndex(); @@ -43,12 +43,12 @@ void MockWebRTCPeerConnectionHandlerClient::didGenerateICECandidateWorker( } void MockWebRTCPeerConnectionHandlerClient::didAddRemoteStreamWorker( - const WebKit::WebMediaStream& stream_descriptor) { + const blink::WebMediaStream& stream_descriptor) { remote_steam_ = stream_descriptor; } void MockWebRTCPeerConnectionHandlerClient::didRemoveRemoteStreamWorker( - const WebKit::WebMediaStream& stream_descriptor) { + const blink::WebMediaStream& stream_descriptor) { remote_steam_.reset(); } diff --git a/chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.h b/chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.h index 1bc5b2ac15a..720a7cb65ea 100644 --- a/chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.h +++ b/chromium/content/renderer/media/mock_web_rtc_peer_connection_handler_client.h @@ -17,7 +17,7 @@ namespace content { class MockWebRTCPeerConnectionHandlerClient - : public WebKit::WebRTCPeerConnectionHandlerClient { + : public blink::WebRTCPeerConnectionHandlerClient { public: MockWebRTCPeerConnectionHandlerClient(); virtual ~MockWebRTCPeerConnectionHandlerClient(); @@ -25,33 +25,33 @@ class MockWebRTCPeerConnectionHandlerClient // WebRTCPeerConnectionHandlerClient implementation. MOCK_METHOD0(negotiationNeeded, void()); MOCK_METHOD1(didGenerateICECandidate, - void(const WebKit::WebRTCICECandidate& candidate)); + void(const blink::WebRTCICECandidate& candidate)); MOCK_METHOD1(didChangeSignalingState, void(SignalingState state)); MOCK_METHOD1(didChangeICEGatheringState, void(ICEGatheringState state)); MOCK_METHOD1(didChangeICEConnectionState, void(ICEConnectionState state)); MOCK_METHOD1(didAddRemoteStream, - void(const WebKit::WebMediaStream& stream_descriptor)); + void(const blink::WebMediaStream& stream_descriptor)); MOCK_METHOD1(didRemoveRemoteStream, - void(const WebKit::WebMediaStream& stream_descriptor)); + void(const blink::WebMediaStream& stream_descriptor)); MOCK_METHOD1(didAddRemoteDataChannel, - void(WebKit::WebRTCDataChannelHandler*)); + void(blink::WebRTCDataChannelHandler*)); void didGenerateICECandidateWorker( - const WebKit::WebRTCICECandidate& candidate); + const blink::WebRTCICECandidate& candidate); void didAddRemoteStreamWorker( - const WebKit::WebMediaStream& stream_descriptor); + const blink::WebMediaStream& stream_descriptor); void didRemoveRemoteStreamWorker( - const WebKit::WebMediaStream& stream_descriptor); + const blink::WebMediaStream& stream_descriptor); const std::string& candidate_sdp() const { return candidate_sdp_; } int candidate_mlineindex() const { return candidate_mline_index_; } const std::string& candidate_mid() const { return candidate_mid_ ; } - const WebKit::WebMediaStream& remote_stream() const { return remote_steam_;} + const blink::WebMediaStream& remote_stream() const { return remote_steam_;} private: - WebKit::WebMediaStream remote_steam_; + blink::WebMediaStream remote_steam_; std::string candidate_sdp_; int candidate_mline_index_; std::string candidate_mid_; diff --git a/chromium/content/renderer/media/peer_connection_audio_sink_owner.cc b/chromium/content/renderer/media/peer_connection_audio_sink_owner.cc new file mode 100644 index 00000000000..4073ac61425 --- /dev/null +++ b/chromium/content/renderer/media/peer_connection_audio_sink_owner.cc @@ -0,0 +1,71 @@ +// 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/renderer/media/peer_connection_audio_sink_owner.h" + +#include "content/renderer/media/webrtc_audio_device_impl.h" + +namespace content { + +PeerConnectionAudioSinkOwner::PeerConnectionAudioSinkOwner( + PeerConnectionAudioSink* sink) + : delegate_(sink) { +} + +int PeerConnectionAudioSinkOwner::OnData(const int16* audio_data, + int sample_rate, + int number_of_channels, + int number_of_frames, + const std::vector<int>& channels, + int audio_delay_milliseconds, + int current_volume, + bool need_audio_processing, + bool key_pressed) { + base::AutoLock lock(lock_); + if (delegate_) { + return delegate_->OnData(audio_data, + sample_rate, + number_of_channels, + number_of_frames, + channels, + audio_delay_milliseconds, + current_volume, + need_audio_processing, + key_pressed); + } + + return 0; +} + +void PeerConnectionAudioSinkOwner::OnSetFormat( + const media::AudioParameters& params) { + base::AutoLock lock(lock_); + if (delegate_) + delegate_->OnSetFormat(params); +} + +void PeerConnectionAudioSinkOwner::OnReadyStateChanged( + blink::WebMediaStreamSource::ReadyState state) { + // Not forwarded at the moment. +} + +void PeerConnectionAudioSinkOwner::Reset() { + base::AutoLock lock(lock_); + delegate_ = NULL; +} + +bool PeerConnectionAudioSinkOwner::IsEqual( + const MediaStreamAudioSink* other) const { + DCHECK(other); + return false; +} + +bool PeerConnectionAudioSinkOwner::IsEqual( + const PeerConnectionAudioSink* other) const { + DCHECK(other); + base::AutoLock lock(lock_); + return (other == delegate_); +} + +} // namespace content diff --git a/chromium/content/renderer/media/peer_connection_audio_sink_owner.h b/chromium/content/renderer/media/peer_connection_audio_sink_owner.h new file mode 100644 index 00000000000..289a3f477a7 --- /dev/null +++ b/chromium/content/renderer/media/peer_connection_audio_sink_owner.h @@ -0,0 +1,54 @@ +// 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_RENDERER_MEDIA_PEER_CONNECTION_AUDIO_SINK_OWNER_H_ +#define CONTENT_RENDERER_MEDIA_PEER_CONNECTION_AUDIO_SINK_OWNER_H_ + +#include <vector> + +#include "base/synchronization/lock.h" +#include "content/renderer/media/media_stream_audio_track_sink.h" + +namespace content { + +class PeerConnectionAudioSink; + +// Reference counted holder of PeerConnectionAudioSink. +class PeerConnectionAudioSinkOwner : public MediaStreamAudioTrackSink { + public: + explicit PeerConnectionAudioSinkOwner(PeerConnectionAudioSink* sink); + + // MediaStreamAudioTrackSink implementation. + virtual int OnData(const int16* audio_data, + int sample_rate, + int number_of_channels, + int number_of_frames, + const std::vector<int>& channels, + int audio_delay_milliseconds, + int current_volume, + bool need_audio_processing, + bool key_pressed) OVERRIDE; + virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE; + virtual void OnReadyStateChanged( + blink::WebMediaStreamSource::ReadyState state) OVERRIDE; + virtual void Reset() OVERRIDE; + virtual bool IsEqual(const MediaStreamAudioSink* other) const OVERRIDE; + virtual bool IsEqual(const PeerConnectionAudioSink* other) const OVERRIDE; + + protected: + virtual ~PeerConnectionAudioSinkOwner() {} + + private: + mutable base::Lock lock_; + + // Raw pointer to the delegate, the client need to call Reset() to set the + // pointer to NULL before the delegate goes away. + PeerConnectionAudioSink* delegate_; + + DISALLOW_COPY_AND_ASSIGN(PeerConnectionAudioSinkOwner); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_PEER_CONNECTION_AUDIO_SINK_OWNER_H_ diff --git a/chromium/content/renderer/media/peer_connection_handler_base.cc b/chromium/content/renderer/media/peer_connection_handler_base.cc index 792e61b0968..05e71a6226a 100644 --- a/chromium/content/renderer/media/peer_connection_handler_base.cc +++ b/chromium/content/renderer/media/peer_connection_handler_base.cc @@ -15,16 +15,6 @@ namespace content { -// TODO(hta): Unify implementations of these functions from MediaStreamCenter -static webrtc::MediaStreamInterface* GetNativeMediaStream( - const WebKit::WebMediaStream& stream) { - MediaStreamExtraData* extra_data = - static_cast<MediaStreamExtraData*>(stream.extraData()); - if (extra_data) - return extra_data->stream().get(); - return NULL; -} - PeerConnectionHandlerBase::PeerConnectionHandlerBase( MediaStreamDependencyFactory* dependency_factory) : dependency_factory_(dependency_factory), @@ -35,39 +25,22 @@ PeerConnectionHandlerBase::~PeerConnectionHandlerBase() { } bool PeerConnectionHandlerBase::AddStream( - const WebKit::WebMediaStream& stream, + const blink::WebMediaStream& stream, const webrtc::MediaConstraintsInterface* constraints) { - webrtc::MediaStreamInterface* native_stream = GetNativeMediaStream(stream); + webrtc::MediaStreamInterface* native_stream = + MediaStreamDependencyFactory::GetNativeMediaStream(stream); if (!native_stream) return false; return native_peer_connection_->AddStream(native_stream, constraints); } void PeerConnectionHandlerBase::RemoveStream( - const WebKit::WebMediaStream& stream) { - webrtc::MediaStreamInterface* native_stream = GetNativeMediaStream(stream); + const blink::WebMediaStream& stream) { + webrtc::MediaStreamInterface* native_stream = + MediaStreamDependencyFactory::GetNativeMediaStream(stream); if (native_stream) native_peer_connection_->RemoveStream(native_stream); DCHECK(native_stream); } -webrtc::MediaStreamTrackInterface* -PeerConnectionHandlerBase::GetNativeMediaStreamTrack( - const WebKit::WebMediaStream& stream, - const WebKit::WebMediaStreamTrack& track) { - std::string track_id = UTF16ToUTF8(track.id()); - webrtc::MediaStreamInterface* native_stream = GetNativeMediaStream(stream); - if (!native_stream) { - return NULL; - } - if (track.source().type() == WebKit::WebMediaStreamSource::TypeAudio) { - return native_stream->FindAudioTrack(track_id); - } - if (track.source().type() == WebKit::WebMediaStreamSource::TypeVideo) { - return native_stream->FindVideoTrack(track_id); - } - NOTIMPLEMENTED(); // We have an unknown type of media stream track. - return NULL; -} - } // namespace content diff --git a/chromium/content/renderer/media/peer_connection_handler_base.h b/chromium/content/renderer/media/peer_connection_handler_base.h index 54f16734f5c..db6c0407e31 100644 --- a/chromium/content/renderer/media/peer_connection_handler_base.h +++ b/chromium/content/renderer/media/peer_connection_handler_base.h @@ -32,13 +32,10 @@ class CONTENT_EXPORT PeerConnectionHandlerBase protected: virtual ~PeerConnectionHandlerBase(); - void AddStream(const WebKit::WebMediaStream& stream); - bool AddStream(const WebKit::WebMediaStream& stream, + void AddStream(const blink::WebMediaStream& stream); + bool AddStream(const blink::WebMediaStream& stream, const webrtc::MediaConstraintsInterface* constraints); - void RemoveStream(const WebKit::WebMediaStream& stream); - webrtc::MediaStreamTrackInterface* GetNativeMediaStreamTrack( - const WebKit::WebMediaStream& stream, - const WebKit::WebMediaStreamTrack& component); + void RemoveStream(const blink::WebMediaStream& stream); // dependency_factory_ is a raw pointer, and is valid for the lifetime of // MediaStreamImpl. diff --git a/chromium/content/renderer/media/peer_connection_identity_service.cc b/chromium/content/renderer/media/peer_connection_identity_service.cc index 904eb4128c3..f7bc8568102 100644 --- a/chromium/content/renderer/media/peer_connection_identity_service.cc +++ b/chromium/content/renderer/media/peer_connection_identity_service.cc @@ -9,17 +9,8 @@ namespace content { -PeerConnectionIdentityService* PeerConnectionIdentityService::Create( - const GURL& origin) { -// The crypto APIs needed for generating identities are not implenented for -// OPENSSL yet (crbug/91512). So returning NULL in that case. -// TODO(jiayl): remove the #if once the crypto APIs are implemented for OPENSSL. -#if defined(USE_OPENSSL) - return NULL; -#else - return new PeerConnectionIdentityService(origin); -#endif // defined(USE_OPENSSL) -} +PeerConnectionIdentityService::PeerConnectionIdentityService(const GURL& origin) + : origin_(origin), pending_observer_(NULL), pending_request_id_(0) {} PeerConnectionIdentityService::~PeerConnectionIdentityService() { if (pending_observer_) @@ -48,9 +39,6 @@ bool PeerConnectionIdentityService::RequestIdentity( return true; } -PeerConnectionIdentityService::PeerConnectionIdentityService(const GURL& origin) - : origin_(origin), pending_observer_(NULL), pending_request_id_(0) {} - void PeerConnectionIdentityService::OnIdentityReady( const std::string& certificate, const std::string& private_key) { diff --git a/chromium/content/renderer/media/peer_connection_identity_service.h b/chromium/content/renderer/media/peer_connection_identity_service.h index fa0b16a096c..b68cafa135d 100644 --- a/chromium/content/renderer/media/peer_connection_identity_service.h +++ b/chromium/content/renderer/media/peer_connection_identity_service.h @@ -19,7 +19,7 @@ namespace content { class PeerConnectionIdentityService : public webrtc::DTLSIdentityServiceInterface { public: - static PeerConnectionIdentityService* Create(const GURL& origin); + explicit PeerConnectionIdentityService(const GURL& origin); virtual ~PeerConnectionIdentityService(); @@ -30,8 +30,6 @@ class PeerConnectionIdentityService webrtc::DTLSIdentityRequestObserver* observer) OVERRIDE; private: - explicit PeerConnectionIdentityService(const GURL& origin); - void OnIdentityReady(const std::string& certificate, const std::string& private_key); void OnRequestFailed(int error); diff --git a/chromium/content/renderer/media/peer_connection_tracker.cc b/chromium/content/renderer/media/peer_connection_tracker.cc index 597c6455704..b594ff8f0b3 100644 --- a/chromium/content/renderer/media/peer_connection_tracker.cc +++ b/chromium/content/renderer/media/peer_connection_tracker.cc @@ -18,7 +18,7 @@ using std::string; using webrtc::MediaConstraintsInterface; -using WebKit::WebRTCPeerConnectionHandlerClient; +using blink::WebRTCPeerConnectionHandlerClient; namespace content { @@ -63,16 +63,16 @@ static string SerializeMediaConstraints( } static string SerializeMediaStreamComponent( - const WebKit::WebMediaStreamTrack component) { + const blink::WebMediaStreamTrack component) { string id = UTF16ToUTF8(component.source().id()); return id; } static string SerializeMediaDescriptor( - const WebKit::WebMediaStream& stream) { + const blink::WebMediaStream& stream) { string label = UTF16ToUTF8(stream.id()); string result = "label: " + label; - WebKit::WebVector<WebKit::WebMediaStreamTrack> tracks; + blink::WebVector<blink::WebMediaStreamTrack> tracks; stream.audioTracks(tracks); if (!tracks.isEmpty()) { result += ", audio: ["; @@ -251,7 +251,7 @@ void PeerConnectionTracker::RegisterPeerConnection( RTCPeerConnectionHandler* pc_handler, const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers, const RTCMediaConstraints& constraints, - const WebKit::WebFrame* frame) { + const blink::WebFrame* frame) { DVLOG(1) << "PeerConnectionTracker::RegisterPeerConnection()"; PeerConnectionInfo info; @@ -304,7 +304,7 @@ void PeerConnectionTracker::TrackCreateAnswer( void PeerConnectionTracker::TrackSetSessionDescription( RTCPeerConnectionHandler* pc_handler, - const WebKit::WebRTCSessionDescription& desc, + const blink::WebRTCSessionDescription& desc, Source source) { string sdp = UTF16ToUTF8(desc.sdp()); string type = UTF16ToUTF8(desc.type()); @@ -330,7 +330,7 @@ void PeerConnectionTracker::TrackUpdateIce( void PeerConnectionTracker::TrackAddIceCandidate( RTCPeerConnectionHandler* pc_handler, - const WebKit::WebRTCICECandidate& candidate, + const blink::WebRTCICECandidate& candidate, Source source) { string value = "mid: " + UTF16ToUTF8(candidate.sdpMid()) + ", " + "candidate: " + UTF16ToUTF8(candidate.candidate()); @@ -341,7 +341,7 @@ void PeerConnectionTracker::TrackAddIceCandidate( void PeerConnectionTracker::TrackAddStream( RTCPeerConnectionHandler* pc_handler, - const WebKit::WebMediaStream& stream, + const blink::WebMediaStream& stream, Source source){ SendPeerConnectionUpdate( pc_handler, source == SOURCE_LOCAL ? "addStream" : "onAddStream", @@ -350,7 +350,7 @@ void PeerConnectionTracker::TrackAddStream( void PeerConnectionTracker::TrackRemoveStream( RTCPeerConnectionHandler* pc_handler, - const WebKit::WebMediaStream& stream, + const blink::WebMediaStream& stream, Source source){ SendPeerConnectionUpdate( pc_handler, source == SOURCE_LOCAL ? "removeStream" : "onRemoveStream", @@ -429,7 +429,7 @@ void PeerConnectionTracker::TrackOnRenegotiationNeeded( void PeerConnectionTracker::TrackCreateDTMFSender( RTCPeerConnectionHandler* pc_handler, - const WebKit::WebMediaStreamTrack& track) { + const blink::WebMediaStreamTrack& track) { SendPeerConnectionUpdate(pc_handler, "createDTMFSender", UTF16ToUTF8(track.id())); } diff --git a/chromium/content/renderer/media/peer_connection_tracker.h b/chromium/content/renderer/media/peer_connection_tracker.h index 41c78d87852..3bcda3996f7 100644 --- a/chromium/content/renderer/media/peer_connection_tracker.h +++ b/chromium/content/renderer/media/peer_connection_tracker.h @@ -14,12 +14,12 @@ #include "third_party/WebKit/public/platform/WebRTCSessionDescription.h" #include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h" -namespace WebKit { +namespace blink { class WebFrame; class WebRTCICECandidate; class WebString; class WebRTCSessionDescription; -} // namespace WebKit +} // namespace blink namespace webrtc { class DataChannelInterface; @@ -70,7 +70,7 @@ class CONTENT_EXPORT PeerConnectionTracker : public RenderProcessObserver { RTCPeerConnectionHandler* pc_handler, const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers, const RTCMediaConstraints& constraints, - const WebKit::WebFrame* frame); + const blink::WebFrame* frame); // Sends an update when a PeerConnection has been destroyed. virtual void UnregisterPeerConnection(RTCPeerConnectionHandler* pc_handler); @@ -86,7 +86,7 @@ class CONTENT_EXPORT PeerConnectionTracker : public RenderProcessObserver { // Sends an update when setLocalDescription or setRemoteDescription is called. virtual void TrackSetSessionDescription( RTCPeerConnectionHandler* pc_handler, - const WebKit::WebRTCSessionDescription& desc, Source source); + const blink::WebRTCSessionDescription& desc, Source source); // Sends an update when Ice candidates are updated. virtual void TrackUpdateIce( @@ -97,17 +97,17 @@ class CONTENT_EXPORT PeerConnectionTracker : public RenderProcessObserver { // Sends an update when an Ice candidate is added. virtual void TrackAddIceCandidate( RTCPeerConnectionHandler* pc_handler, - const WebKit::WebRTCICECandidate& candidate, Source source); + const blink::WebRTCICECandidate& candidate, Source source); // Sends an update when a media stream is added. virtual void TrackAddStream( RTCPeerConnectionHandler* pc_handler, - const WebKit::WebMediaStream& stream, Source source); + const blink::WebMediaStream& stream, Source source); // Sends an update when a media stream is removed. virtual void TrackRemoveStream( RTCPeerConnectionHandler* pc_handler, - const WebKit::WebMediaStream& stream, Source source); + const blink::WebMediaStream& stream, Source source); // Sends an update when a DataChannel is created. virtual void TrackCreateDataChannel( @@ -120,19 +120,19 @@ class CONTENT_EXPORT PeerConnectionTracker : public RenderProcessObserver { // Sends an update when the signaling state of a PeerConnection has changed. virtual void TrackSignalingStateChange( RTCPeerConnectionHandler* pc_handler, - WebKit::WebRTCPeerConnectionHandlerClient::SignalingState state); + blink::WebRTCPeerConnectionHandlerClient::SignalingState state); // Sends an update when the Ice connection state // of a PeerConnection has changed. virtual void TrackIceConnectionStateChange( RTCPeerConnectionHandler* pc_handler, - WebKit::WebRTCPeerConnectionHandlerClient::ICEConnectionState state); + blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state); // Sends an update when the Ice gathering state // of a PeerConnection has changed. virtual void TrackIceGatheringStateChange( RTCPeerConnectionHandler* pc_handler, - WebKit::WebRTCPeerConnectionHandlerClient::ICEGatheringState state); + blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state); // Sends an update when the SetSessionDescription or CreateOffer or // CreateAnswer callbacks are called. @@ -146,7 +146,7 @@ class CONTENT_EXPORT PeerConnectionTracker : public RenderProcessObserver { // Sends an update when a DTMFSender is created. virtual void TrackCreateDTMFSender( RTCPeerConnectionHandler* pc_handler, - const WebKit::WebMediaStreamTrack& track); + const blink::WebMediaStreamTrack& track); private: // Assign a local ID to a peer connection so that the browser process can diff --git a/chromium/content/renderer/media/remote_media_stream_impl.cc b/chromium/content/renderer/media/remote_media_stream_impl.cc index 7e481a6d042..af430e242f7 100644 --- a/chromium/content/renderer/media/remote_media_stream_impl.cc +++ b/chromium/content/renderer/media/remote_media_stream_impl.cc @@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/strings/utf_string_conversions.h" +#include "content/renderer/media/media_stream_dependency_factory.h" #include "content/renderer/media/media_stream_extra_data.h" #include "third_party/WebKit/public/platform/WebString.h" @@ -21,13 +22,13 @@ class RemoteMediaStreamTrackObserver public: RemoteMediaStreamTrackObserver( webrtc::MediaStreamTrackInterface* webrtc_track, - const WebKit::WebMediaStreamTrack& webkit_track); + const blink::WebMediaStreamTrack& webkit_track); virtual ~RemoteMediaStreamTrackObserver(); webrtc::MediaStreamTrackInterface* observered_track() { return webrtc_track_.get(); } - const WebKit::WebMediaStreamTrack& webkit_track() { return webkit_track_; } + const blink::WebMediaStreamTrack& webkit_track() { return webkit_track_; } private: // webrtc::ObserverInterface implementation. @@ -35,7 +36,7 @@ class RemoteMediaStreamTrackObserver webrtc::MediaStreamTrackInterface::TrackState state_; scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track_; - WebKit::WebMediaStreamTrack webkit_track_; + blink::WebMediaStreamTrack webkit_track_; DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamTrackObserver); }; @@ -45,13 +46,15 @@ class RemoteMediaStreamTrackObserver namespace { void InitializeWebkitTrack(webrtc::MediaStreamTrackInterface* track, - WebKit::WebMediaStreamTrack* webkit_track, - WebKit::WebMediaStreamSource::Type type) { - WebKit::WebMediaStreamSource webkit_source; - WebKit::WebString webkit_track_id(UTF8ToUTF16(track->id())); + blink::WebMediaStreamTrack* webkit_track, + blink::WebMediaStreamSource::Type type) { + blink::WebMediaStreamSource webkit_source; + blink::WebString webkit_track_id(UTF8ToUTF16(track->id())); webkit_source.initialize(webkit_track_id, type, webkit_track_id); webkit_track->initialize(webkit_track_id, webkit_source); + content::MediaStreamDependencyFactory::AddNativeTrackToBlinkTrack( + track, *webkit_track, false); } content::RemoteMediaStreamTrackObserver* FindTrackObserver( @@ -72,7 +75,7 @@ namespace content { RemoteMediaStreamTrackObserver::RemoteMediaStreamTrackObserver( webrtc::MediaStreamTrackInterface* webrtc_track, - const WebKit::WebMediaStreamTrack& webkit_track) + const blink::WebMediaStreamTrack& webkit_track) : state_(webrtc_track->state()), webrtc_track_(webrtc_track), webkit_track_(webkit_track) { @@ -98,11 +101,11 @@ void RemoteMediaStreamTrackObserver::OnChanged() { break; case webrtc::MediaStreamTrackInterface::kLive: webkit_track_.source().setReadyState( - WebKit::WebMediaStreamSource::ReadyStateLive); + blink::WebMediaStreamSource::ReadyStateLive); break; case webrtc::MediaStreamTrackInterface::kEnded: webkit_track_.source().setReadyState( - WebKit::WebMediaStreamSource::ReadyStateEnded); + blink::WebMediaStreamSource::ReadyStateEnded); break; default: NOTREACHED(); @@ -117,7 +120,7 @@ RemoteMediaStreamImpl::RemoteMediaStreamImpl( webrtc::AudioTrackVector webrtc_audio_tracks = webrtc_stream_->GetAudioTracks(); - WebKit::WebVector<WebKit::WebMediaStreamTrack> webkit_audio_tracks( + blink::WebVector<blink::WebMediaStreamTrack> webkit_audio_tracks( webrtc_audio_tracks.size()); // Initialize WebKit audio tracks. @@ -126,7 +129,7 @@ RemoteMediaStreamImpl::RemoteMediaStreamImpl( webrtc::AudioTrackInterface* audio_track = webrtc_audio_tracks[i]; DCHECK(audio_track); InitializeWebkitTrack(audio_track, &webkit_audio_tracks[i], - WebKit::WebMediaStreamSource::TypeAudio); + blink::WebMediaStreamSource::TypeAudio); audio_track_observers_.push_back( new RemoteMediaStreamTrackObserver(audio_track, webkit_audio_tracks[i])); @@ -135,13 +138,13 @@ RemoteMediaStreamImpl::RemoteMediaStreamImpl( // Initialize WebKit video tracks. webrtc::VideoTrackVector webrtc_video_tracks = webrtc_stream_->GetVideoTracks(); - WebKit::WebVector<WebKit::WebMediaStreamTrack> webkit_video_tracks( + blink::WebVector<blink::WebMediaStreamTrack> webkit_video_tracks( webrtc_video_tracks.size()); for (i = 0; i < webrtc_video_tracks.size(); ++i) { webrtc::VideoTrackInterface* video_track = webrtc_video_tracks[i]; DCHECK(video_track); InitializeWebkitTrack(video_track, &webkit_video_tracks[i], - WebKit::WebMediaStreamSource::TypeVideo); + blink::WebMediaStreamSource::TypeVideo); video_track_observers_.push_back( new RemoteMediaStreamTrackObserver(video_track, webkit_video_tracks[i])); @@ -189,9 +192,9 @@ void RemoteMediaStreamImpl::OnChanged() { for (webrtc::AudioTrackVector::iterator it = webrtc_audio_tracks.begin(); it != webrtc_audio_tracks.end(); ++it) { if (!FindTrackObserver(*it, audio_track_observers_)) { - WebKit::WebMediaStreamTrack new_track; + blink::WebMediaStreamTrack new_track; InitializeWebkitTrack(*it, &new_track, - WebKit::WebMediaStreamSource::TypeAudio); + blink::WebMediaStreamSource::TypeAudio); audio_track_observers_.push_back( new RemoteMediaStreamTrackObserver(*it, new_track)); webkit_stream_.addTrack(new_track); @@ -204,9 +207,9 @@ void RemoteMediaStreamImpl::OnChanged() { for (webrtc::VideoTrackVector::iterator it = webrtc_video_tracks.begin(); it != webrtc_video_tracks.end(); ++it) { if (!FindTrackObserver(*it, video_track_observers_)) { - WebKit::WebMediaStreamTrack new_track; + blink::WebMediaStreamTrack new_track; InitializeWebkitTrack(*it, &new_track, - WebKit::WebMediaStreamSource::TypeVideo); + blink::WebMediaStreamSource::TypeVideo); video_track_observers_.push_back( new RemoteMediaStreamTrackObserver(*it, new_track)); webkit_stream_.addTrack(new_track); diff --git a/chromium/content/renderer/media/remote_media_stream_impl.h b/chromium/content/renderer/media/remote_media_stream_impl.h index cc711e41358..3263ed458e9 100644 --- a/chromium/content/renderer/media/remote_media_stream_impl.h +++ b/chromium/content/renderer/media/remote_media_stream_impl.h @@ -32,7 +32,7 @@ class CONTENT_EXPORT RemoteMediaStreamImpl webrtc::MediaStreamInterface* webrtc_stream); virtual ~RemoteMediaStreamImpl(); - const WebKit::WebMediaStream& webkit_stream() { return webkit_stream_; } + const blink::WebMediaStream& webkit_stream() { return webkit_stream_; } private: // webrtc::ObserverInterface implementation. @@ -41,7 +41,7 @@ class CONTENT_EXPORT RemoteMediaStreamImpl scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream_; ScopedVector<RemoteMediaStreamTrackObserver> audio_track_observers_; ScopedVector<RemoteMediaStreamTrackObserver> video_track_observers_; - WebKit::WebMediaStream webkit_stream_; + blink::WebMediaStream webkit_stream_; DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamImpl); }; diff --git a/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc b/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc index 7fcb79cb25c..7d4db85513f 100644 --- a/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc +++ b/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc @@ -12,8 +12,8 @@ #include "content/common/gpu/client/context_provider_command_buffer.h" #include "content/common/gpu/client/gpu_channel_host.h" #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" +#include "content/renderer/render_thread_impl.h" #include "gpu/command_buffer/client/gles2_implementation.h" -#include "gpu/ipc/command_buffer_proxy.h" #include "third_party/skia/include/core/SkPixelRef.h" namespace content { @@ -21,9 +21,9 @@ namespace content { RendererGpuVideoAcceleratorFactories::~RendererGpuVideoAcceleratorFactories() {} RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories( GpuChannelHost* gpu_channel_host, - const scoped_refptr<base::MessageLoopProxy>& message_loop, const scoped_refptr<ContextProviderCommandBuffer>& context_provider) - : message_loop_(message_loop), + : message_loop_( + RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy()), gpu_channel_host_(gpu_channel_host), context_provider_(context_provider), thread_safe_sender_(ChildThread::current()->thread_safe_sender()), @@ -111,32 +111,9 @@ RendererGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator( scoped_ptr<media::VideoEncodeAccelerator> RendererGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator( media::VideoEncodeAccelerator::Client* client) { - if (message_loop_->BelongsToCurrentThread()) { - AsyncCreateVideoEncodeAccelerator(client); - message_loop_async_waiter_.Reset(); - return vea_.Pass(); - } - // The VEA is returned in the vea_ member variable by the - // AsyncCreateVideoEncodeAccelerator() function. - message_loop_->PostTask(FROM_HERE, - base::Bind(&RendererGpuVideoAcceleratorFactories:: - AsyncCreateVideoEncodeAccelerator, - this, - client)); + DCHECK(message_loop_->BelongsToCurrentThread()); - base::WaitableEvent* objects[] = {&aborted_waiter_, - &message_loop_async_waiter_}; - if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) { - // If we are aborting and the VDA is created by the - // AsyncCreateVideoEncodeAccelerator() function later we need to ensure - // that it is destroyed on the same thread. - message_loop_->PostTask(FROM_HERE, - base::Bind(&RendererGpuVideoAcceleratorFactories:: - AsyncDestroyVideoEncodeAccelerator, - this)); - return scoped_ptr<media::VideoEncodeAccelerator>(); - } - return vea_.Pass(); + return gpu_channel_host_->CreateVideoEncoder(client); } void RendererGpuVideoAcceleratorFactories::AsyncCreateVideoDecodeAccelerator( @@ -152,67 +129,26 @@ void RendererGpuVideoAcceleratorFactories::AsyncCreateVideoDecodeAccelerator( message_loop_async_waiter_.Signal(); } -void RendererGpuVideoAcceleratorFactories::AsyncCreateVideoEncodeAccelerator( - media::VideoEncodeAccelerator::Client* client) { - DCHECK(message_loop_->BelongsToCurrentThread()); - - vea_ = gpu_channel_host_->CreateVideoEncoder(client).Pass(); - message_loop_async_waiter_.Signal(); -} - uint32 RendererGpuVideoAcceleratorFactories::CreateTextures( int32 count, const gfx::Size& size, std::vector<uint32>* texture_ids, std::vector<gpu::Mailbox>* texture_mailboxes, uint32 texture_target) { - uint32 sync_point = 0; - - if (message_loop_->BelongsToCurrentThread()) { - AsyncCreateTextures(count, size, texture_target, &sync_point); - texture_ids->swap(created_textures_); - texture_mailboxes->swap(created_texture_mailboxes_); - message_loop_async_waiter_.Reset(); - return sync_point; - } - message_loop_->PostTask( - FROM_HERE, - base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncCreateTextures, - this, - count, - size, - texture_target, - &sync_point)); - - base::WaitableEvent* objects[] = {&aborted_waiter_, - &message_loop_async_waiter_}; - if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) - return 0; - texture_ids->swap(created_textures_); - texture_mailboxes->swap(created_texture_mailboxes_); - return sync_point; -} - -void RendererGpuVideoAcceleratorFactories::AsyncCreateTextures( - int32 count, - const gfx::Size& size, - uint32 texture_target, - uint32* sync_point) { DCHECK(message_loop_->BelongsToCurrentThread()); DCHECK(texture_target); WebGraphicsContext3DCommandBufferImpl* context = GetContext3d(); - if (!context) { - message_loop_async_waiter_.Signal(); - return; - } + if (!context) + return 0; + gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation(); - created_textures_.resize(count); - created_texture_mailboxes_.resize(count); - gles2->GenTextures(count, &created_textures_[0]); + texture_ids->resize(count); + texture_mailboxes->resize(count); + gles2->GenTextures(count, &texture_ids->at(0)); for (int i = 0; i < count; ++i) { gles2->ActiveTexture(GL_TEXTURE0); - uint32 texture_id = created_textures_[i]; + uint32 texture_id = texture_ids->at(i); gles2->BindTexture(texture_target, texture_id); gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -229,11 +165,9 @@ void RendererGpuVideoAcceleratorFactories::AsyncCreateTextures( GL_UNSIGNED_BYTE, NULL); } - // GLES2Implementation doesn't currently have the fast path of mailbox - // generation, but WebGraphicsContext3DCommandBufferImpl does. - context->genMailboxCHROMIUM(created_texture_mailboxes_[i].name); + gles2->GenMailboxCHROMIUM(texture_mailboxes->at(i).name); gles2->ProduceTextureCHROMIUM(texture_target, - created_texture_mailboxes_[i].name); + texture_mailboxes->at(i).name); } // We need a glFlush here to guarantee the decoder (in the GPU process) can @@ -242,25 +176,12 @@ void RendererGpuVideoAcceleratorFactories::AsyncCreateTextures( gles2->Flush(); DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR)); - *sync_point = gles2->InsertSyncPointCHROMIUM(); - message_loop_async_waiter_.Signal(); + return gles2->InsertSyncPointCHROMIUM(); } void RendererGpuVideoAcceleratorFactories::DeleteTexture(uint32 texture_id) { - if (message_loop_->BelongsToCurrentThread()) { - AsyncDeleteTexture(texture_id); - return; - } - message_loop_->PostTask( - FROM_HERE, - base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncDeleteTexture, - this, - texture_id)); -} - -void RendererGpuVideoAcceleratorFactories::AsyncDeleteTexture( - uint32 texture_id) { DCHECK(message_loop_->BelongsToCurrentThread()); + WebGraphicsContext3DCommandBufferImpl* context = GetContext3d(); if (!context) return; @@ -271,38 +192,21 @@ void RendererGpuVideoAcceleratorFactories::AsyncDeleteTexture( } void RendererGpuVideoAcceleratorFactories::WaitSyncPoint(uint32 sync_point) { - if (message_loop_->BelongsToCurrentThread()) { - AsyncWaitSyncPoint(sync_point); - message_loop_async_waiter_.Reset(); - return; - } - - message_loop_->PostTask( - FROM_HERE, - base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncWaitSyncPoint, - this, - sync_point)); - base::WaitableEvent* objects[] = {&aborted_waiter_, - &message_loop_async_waiter_}; - base::WaitableEvent::WaitMany(objects, arraysize(objects)); -} - -void RendererGpuVideoAcceleratorFactories::AsyncWaitSyncPoint( - uint32 sync_point) { DCHECK(message_loop_->BelongsToCurrentThread()); + WebGraphicsContext3DCommandBufferImpl* context = GetContext3d(); - if (!context) { - message_loop_async_waiter_.Signal(); + if (!context) return; - } gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation(); gles2->WaitSyncPointCHROMIUM(sync_point); - message_loop_async_waiter_.Signal(); + + // Callers expect the WaitSyncPoint to affect the next IPCs. Make sure to + // flush the command buffers to ensure that. + gles2->ShallowFlushCHROMIUM(); } void RendererGpuVideoAcceleratorFactories::ReadPixels(uint32 texture_id, - uint32 texture_target, const gfx::Size& size, const SkBitmap& pixels) { // SkBitmaps use the SkPixelRef object to refcount the underlying pixels. @@ -317,14 +221,13 @@ void RendererGpuVideoAcceleratorFactories::ReadPixels(uint32 texture_id, base::Bind(&RendererGpuVideoAcceleratorFactories::AsyncReadPixels, this, texture_id, - texture_target, size)); base::WaitableEvent* objects[] = {&aborted_waiter_, &message_loop_async_waiter_}; if (base::WaitableEvent::WaitMany(objects, arraysize(objects)) == 0) return; } else { - AsyncReadPixels(texture_id, texture_target, size); + AsyncReadPixels(texture_id, size); message_loop_async_waiter_.Reset(); } read_pixels_bitmap_.setPixelRef(NULL); @@ -332,7 +235,6 @@ void RendererGpuVideoAcceleratorFactories::ReadPixels(uint32 texture_id, void RendererGpuVideoAcceleratorFactories::AsyncReadPixels( uint32 texture_id, - uint32 texture_target, const gfx::Size& size) { DCHECK(message_loop_->BelongsToCurrentThread()); WebGraphicsContext3DCommandBufferImpl* context = GetContext3d(); @@ -345,25 +247,34 @@ void RendererGpuVideoAcceleratorFactories::AsyncReadPixels( GLuint tmp_texture; gles2->GenTextures(1, &tmp_texture); - gles2->BindTexture(texture_target, tmp_texture); - gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + gles2->BindTexture(GL_TEXTURE_2D, tmp_texture); + gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); context->copyTextureCHROMIUM( - texture_target, texture_id, tmp_texture, 0, GL_RGBA, GL_UNSIGNED_BYTE); + GL_TEXTURE_2D, texture_id, tmp_texture, 0, GL_RGBA, GL_UNSIGNED_BYTE); GLuint fb; gles2->GenFramebuffers(1, &fb); gles2->BindFramebuffer(GL_FRAMEBUFFER, fb); gles2->FramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target, tmp_texture, 0); + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_texture, 0); gles2->PixelStorei(GL_PACK_ALIGNMENT, 4); +#if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \ + SK_A32_SHIFT == 24 + GLenum skia_format = GL_BGRA_EXT; +#elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \ + SK_A32_SHIFT == 24 + GLenum skia_format = GL_RGBA; +#else +#error Unexpected Skia ARGB_8888 layout! +#endif gles2->ReadPixels(0, 0, size.width(), size.height(), - GL_BGRA_EXT, + skia_format, GL_UNSIGNED_BYTE, read_pixels_bitmap_.pixelRef()->pixels()); gles2->DeleteFramebuffers(1, &fb); @@ -374,6 +285,7 @@ void RendererGpuVideoAcceleratorFactories::AsyncReadPixels( base::SharedMemory* RendererGpuVideoAcceleratorFactories::CreateSharedMemory( size_t size) { + DCHECK(message_loop_->BelongsToCurrentThread()); return ChildThread::AllocateSharedMemory(size, thread_safe_sender_.get()); } @@ -406,11 +318,4 @@ RendererGpuVideoAcceleratorFactories::AsyncDestroyVideoDecodeAccelerator() { vda_.release()->Destroy(); } -void -RendererGpuVideoAcceleratorFactories::AsyncDestroyVideoEncodeAccelerator() { - // OK to release because Destroy() will delete the VDA instance. - if (vea_) - vea_.release()->Destroy(); -} - } // namespace content diff --git a/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h b/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h index e1736d12a3b..eb9d650b5d0 100644 --- a/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h +++ b/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h @@ -32,20 +32,23 @@ class WebGraphicsContext3DCommandBufferImpl; // RenderViewImpl and only has its own header to allow extraction of its // implementation from render_view_impl.cc which is already far too large. // -// The public methods of the class can be called from any thread, and are -// internally trampolined to the appropriate thread. GPU/GL-related calls go to -// the constructor-argument loop (the media thread). +// The RendererGpuVideoAcceleratorFactories can be constructed on any thread. +// Most public methods of the class must be called from the media thread. The +// exceptions (which can be called from any thread, as they are internally +// trampolined) are: +// * CreateVideoDecodeAccelerator() +// * ReadPixels() class CONTENT_EXPORT RendererGpuVideoAcceleratorFactories : public media::GpuVideoAcceleratorFactories { public: // Takes a ref on |gpu_channel_host| and tests |context| for loss before each - // use. + // use. Safe to call from any thread. RendererGpuVideoAcceleratorFactories( GpuChannelHost* gpu_channel_host, - const scoped_refptr<base::MessageLoopProxy>& message_loop, const scoped_refptr<ContextProviderCommandBuffer>& context_provider); // media::GpuVideoAcceleratorFactories implementation. + // CreateVideoDecodeAccelerator() is safe to call from any thread. virtual scoped_ptr<media::VideoDecodeAccelerator> CreateVideoDecodeAccelerator( media::VideoCodecProfile profile, @@ -62,8 +65,8 @@ class CONTENT_EXPORT RendererGpuVideoAcceleratorFactories uint32 texture_target) OVERRIDE; virtual void DeleteTexture(uint32 texture_id) OVERRIDE; virtual void WaitSyncPoint(uint32 sync_point) OVERRIDE; + // ReadPixels() is safe to call from any thread. virtual void ReadPixels(uint32 texture_id, - uint32 texture_target, const gfx::Size& size, const SkBitmap& pixels) OVERRIDE; virtual base::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE; @@ -92,23 +95,11 @@ class CONTENT_EXPORT RendererGpuVideoAcceleratorFactories // a WaitableEvent* param to signal completion (except for DeleteTexture, // which is fire-and-forget). // AsyncCreateVideoDecodeAccelerator returns its output in the |vda_| member. - // AsyncCreateVideoEncodeAccelerator returns its output in the |vea_| member. void AsyncCreateVideoDecodeAccelerator( media::VideoCodecProfile profile, media::VideoDecodeAccelerator::Client* client); - void AsyncCreateVideoEncodeAccelerator( - media::VideoEncodeAccelerator::Client* client); - void AsyncCreateTextures(int32 count, - const gfx::Size& size, - uint32 texture_target, - uint32* sync_point); - void AsyncDeleteTexture(uint32 texture_id); - void AsyncWaitSyncPoint(uint32 sync_point); - void AsyncReadPixels(uint32 texture_id, - uint32 texture_target, - const gfx::Size& size); + void AsyncReadPixels(uint32 texture_id, const gfx::Size& size); void AsyncDestroyVideoDecodeAccelerator(); - void AsyncDestroyVideoEncodeAccelerator(); scoped_refptr<base::MessageLoopProxy> message_loop_; scoped_refptr<GpuChannelHost> gpu_channel_host_; @@ -128,16 +119,9 @@ class CONTENT_EXPORT RendererGpuVideoAcceleratorFactories // The vda returned by the CreateVideoDecodeAccelerator function. scoped_ptr<media::VideoDecodeAccelerator> vda_; - // The vea returned by the CreateVideoEncodeAccelerator function. - scoped_ptr<media::VideoEncodeAccelerator> vea_; - // Bitmap returned by ReadPixels(). SkBitmap read_pixels_bitmap_; - // Textures returned by the CreateTexture() function. - std::vector<uint32> created_textures_; - std::vector<gpu::Mailbox> created_texture_mailboxes_; - DISALLOW_COPY_AND_ASSIGN(RendererGpuVideoAcceleratorFactories); }; diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc b/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc index 3d23a9ce3c4..ec38769573f 100644 --- a/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc +++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc @@ -13,10 +13,10 @@ #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebView.h" -using WebKit::WebAudioDevice; -using WebKit::WebFrame; -using WebKit::WebVector; -using WebKit::WebView; +using blink::WebAudioDevice; +using blink::WebFrame; +using blink::WebVector; +using blink::WebView; namespace content { diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl.h b/chromium/content/renderer/media/renderer_webaudiodevice_impl.h index 5a8161fde83..962ec0851c3 100644 --- a/chromium/content/renderer/media/renderer_webaudiodevice_impl.h +++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl.h @@ -19,15 +19,15 @@ class AudioOutputDevice; namespace content { class RendererWebAudioDeviceImpl - : public WebKit::WebAudioDevice, + : public blink::WebAudioDevice, public media::AudioRendererSink::RenderCallback { public: RendererWebAudioDeviceImpl(const media::AudioParameters& params, - WebKit::WebAudioDevice::RenderCallback* callback, + blink::WebAudioDevice::RenderCallback* callback, int session_id); virtual ~RendererWebAudioDeviceImpl(); - // WebKit::WebAudioDevice implementation. + // blink::WebAudioDevice implementation. virtual void start(); virtual void stop(); virtual double sampleRate(); @@ -46,10 +46,10 @@ class RendererWebAudioDeviceImpl const media::AudioParameters params_; // Weak reference to the callback into WebKit code. - WebKit::WebAudioDevice::RenderCallback* const client_callback_; + blink::WebAudioDevice::RenderCallback* const client_callback_; // To avoid the need for locking, ensure the control methods of the - // WebKit::WebAudioDevice implementation are called on the same thread. + // blink::WebAudioDevice implementation are called on the same thread. base::ThreadChecker thread_checker_; // When non-NULL, we are started. When NULL, we are stopped. diff --git a/chromium/content/renderer/media/renderer_webmidiaccessor_impl.cc b/chromium/content/renderer/media/renderer_webmidiaccessor_impl.cc index de9db931c13..b12174636e8 100644 --- a/chromium/content/renderer/media/renderer_webmidiaccessor_impl.cc +++ b/chromium/content/renderer/media/renderer_webmidiaccessor_impl.cc @@ -11,7 +11,7 @@ namespace content { RendererWebMIDIAccessorImpl::RendererWebMIDIAccessorImpl( - WebKit::WebMIDIAccessorClient* client) + blink::WebMIDIAccessorClient* client) : client_(client) { DCHECK(client_); } diff --git a/chromium/content/renderer/media/renderer_webmidiaccessor_impl.h b/chromium/content/renderer/media/renderer_webmidiaccessor_impl.h index 7032943c441..4ebaffd408b 100644 --- a/chromium/content/renderer/media/renderer_webmidiaccessor_impl.h +++ b/chromium/content/renderer/media/renderer_webmidiaccessor_impl.h @@ -15,13 +15,13 @@ namespace content { class MIDIMessageFilter; class RendererWebMIDIAccessorImpl - : public WebKit::WebMIDIAccessor { + : public blink::WebMIDIAccessor { public: explicit RendererWebMIDIAccessorImpl( - WebKit::WebMIDIAccessorClient* client); + blink::WebMIDIAccessorClient* client); virtual ~RendererWebMIDIAccessorImpl(); - // WebKit::WebMIDIAccessor implementation. + // blink::WebMIDIAccessor implementation. virtual void startSession(); virtual void sendMIDIData(unsigned port_index, const unsigned char* data, @@ -29,7 +29,7 @@ class RendererWebMIDIAccessorImpl double timestamp); private: - WebKit::WebMIDIAccessorClient* client_; + blink::WebMIDIAccessorClient* client_; MIDIMessageFilter* midi_message_filter(); diff --git a/chromium/content/renderer/media/rtc_data_channel_handler.cc b/chromium/content/renderer/media/rtc_data_channel_handler.cc index 713dc4cf8b8..065048a5556 100644 --- a/chromium/content/renderer/media/rtc_data_channel_handler.cc +++ b/chromium/content/renderer/media/rtc_data_channel_handler.cc @@ -25,11 +25,11 @@ RtcDataChannelHandler::~RtcDataChannelHandler() { } void RtcDataChannelHandler::setClient( - WebKit::WebRTCDataChannelHandlerClient* client) { + blink::WebRTCDataChannelHandlerClient* client) { webkit_client_ = client; } -WebKit::WebString RtcDataChannelHandler::label() { +blink::WebString RtcDataChannelHandler::label() { return UTF8ToUTF16(channel_->label()); } @@ -49,7 +49,7 @@ unsigned short RtcDataChannelHandler::maxRetransmits() const { return channel_->maxRetransmits(); } -WebKit::WebString RtcDataChannelHandler::protocol() const { +blink::WebString RtcDataChannelHandler::protocol() const { return UTF8ToUTF16(channel_->protocol()); } @@ -65,7 +65,7 @@ unsigned long RtcDataChannelHandler::bufferedAmount() { return channel_->buffered_amount(); } -bool RtcDataChannelHandler::sendStringData(const WebKit::WebString& data) { +bool RtcDataChannelHandler::sendStringData(const blink::WebString& data) { std::string utf8_buffer = UTF16ToUTF8(data); talk_base::Buffer buffer(utf8_buffer.c_str(), utf8_buffer.length()); webrtc::DataBuffer data_buffer(buffer, false); @@ -91,19 +91,19 @@ void RtcDataChannelHandler::OnStateChange() { switch (channel_->state()) { case webrtc::DataChannelInterface::kConnecting: webkit_client_->didChangeReadyState( - WebKit::WebRTCDataChannelHandlerClient::ReadyStateConnecting); + blink::WebRTCDataChannelHandlerClient::ReadyStateConnecting); break; case webrtc::DataChannelInterface::kOpen: webkit_client_->didChangeReadyState( - WebKit::WebRTCDataChannelHandlerClient::ReadyStateOpen); + blink::WebRTCDataChannelHandlerClient::ReadyStateOpen); break; case webrtc::DataChannelInterface::kClosing: webkit_client_->didChangeReadyState( - WebKit::WebRTCDataChannelHandlerClient::ReadyStateClosing); + blink::WebRTCDataChannelHandlerClient::ReadyStateClosing); break; case webrtc::DataChannelInterface::kClosed: webkit_client_->didChangeReadyState( - WebKit::WebRTCDataChannelHandlerClient::ReadyStateClosed); + blink::WebRTCDataChannelHandlerClient::ReadyStateClosed); break; default: NOTREACHED(); @@ -120,7 +120,7 @@ void RtcDataChannelHandler::OnMessage(const webrtc::DataBuffer& buffer) { if (buffer.binary) { webkit_client_->didReceiveRawData(buffer.data.data(), buffer.data.length()); } else { - string16 utf16; + base::string16 utf16; if (!UTF8ToUTF16(buffer.data.data(), buffer.data.length(), &utf16)) { LOG(ERROR) << "Failed convert received data to UTF16"; return; diff --git a/chromium/content/renderer/media/rtc_data_channel_handler.h b/chromium/content/renderer/media/rtc_data_channel_handler.h index 8ec07e03691..a5521344f08 100644 --- a/chromium/content/renderer/media/rtc_data_channel_handler.h +++ b/chromium/content/renderer/media/rtc_data_channel_handler.h @@ -21,26 +21,26 @@ namespace content { // Callbacks to the webrtc::DataChannelObserver implementation also occur on // the main render thread. class CONTENT_EXPORT RtcDataChannelHandler - : NON_EXPORTED_BASE(public WebKit::WebRTCDataChannelHandler), + : NON_EXPORTED_BASE(public blink::WebRTCDataChannelHandler), NON_EXPORTED_BASE(public webrtc::DataChannelObserver), NON_EXPORTED_BASE(public base::NonThreadSafe) { public: explicit RtcDataChannelHandler(webrtc::DataChannelInterface* channel); virtual ~RtcDataChannelHandler(); - // WebKit::WebRTCDataChannelHandler implementation. + // blink::WebRTCDataChannelHandler implementation. virtual void setClient( - WebKit::WebRTCDataChannelHandlerClient* client) OVERRIDE; - virtual WebKit::WebString label() OVERRIDE; + blink::WebRTCDataChannelHandlerClient* client) OVERRIDE; + virtual blink::WebString label() OVERRIDE; virtual bool isReliable() OVERRIDE; virtual bool ordered() const OVERRIDE; virtual unsigned short maxRetransmitTime() const OVERRIDE; virtual unsigned short maxRetransmits() const OVERRIDE; - virtual WebKit::WebString protocol() const OVERRIDE; + virtual blink::WebString protocol() const OVERRIDE; virtual bool negotiated() const OVERRIDE; virtual unsigned short id() const OVERRIDE; virtual unsigned long bufferedAmount() OVERRIDE; - virtual bool sendStringData(const WebKit::WebString& data) OVERRIDE; + virtual bool sendStringData(const blink::WebString& data) OVERRIDE; virtual bool sendRawData(const char* data, size_t length) OVERRIDE; virtual void close() OVERRIDE; @@ -50,7 +50,7 @@ class CONTENT_EXPORT RtcDataChannelHandler private: scoped_refptr<webrtc::DataChannelInterface> channel_; - WebKit::WebRTCDataChannelHandlerClient* webkit_client_; + blink::WebRTCDataChannelHandlerClient* webkit_client_; }; } // namespace content diff --git a/chromium/content/renderer/media/rtc_dtmf_sender_handler.cc b/chromium/content/renderer/media/rtc_dtmf_sender_handler.cc index 72e75aa4c62..3df592c8a6b 100644 --- a/chromium/content/renderer/media/rtc_dtmf_sender_handler.cc +++ b/chromium/content/renderer/media/rtc_dtmf_sender_handler.cc @@ -26,11 +26,11 @@ RtcDtmfSenderHandler::~RtcDtmfSenderHandler() { } void RtcDtmfSenderHandler::setClient( - WebKit::WebRTCDTMFSenderHandlerClient* client) { + blink::WebRTCDTMFSenderHandlerClient* client) { webkit_client_ = client; } -WebKit::WebString RtcDtmfSenderHandler::currentToneBuffer() { +blink::WebString RtcDtmfSenderHandler::currentToneBuffer() { return UTF8ToUTF16(dtmf_sender_->tones()); } @@ -38,7 +38,7 @@ bool RtcDtmfSenderHandler::canInsertDTMF() { return dtmf_sender_->CanInsertDtmf(); } -bool RtcDtmfSenderHandler::insertDTMF(const WebKit::WebString& tones, +bool RtcDtmfSenderHandler::insertDTMF(const blink::WebString& tones, long duration, long interToneGap) { std::string utf8_tones = UTF16ToUTF8(tones); diff --git a/chromium/content/renderer/media/rtc_dtmf_sender_handler.h b/chromium/content/renderer/media/rtc_dtmf_sender_handler.h index eeff5eb4860..3f77525fb5e 100644 --- a/chromium/content/renderer/media/rtc_dtmf_sender_handler.h +++ b/chromium/content/renderer/media/rtc_dtmf_sender_handler.h @@ -23,19 +23,19 @@ namespace content { // Callbacks to the webrtc::DtmfSenderObserverInterface implementation also // occur on the main render thread. class CONTENT_EXPORT RtcDtmfSenderHandler - : NON_EXPORTED_BASE(public WebKit::WebRTCDTMFSenderHandler), + : NON_EXPORTED_BASE(public blink::WebRTCDTMFSenderHandler), NON_EXPORTED_BASE(public webrtc::DtmfSenderObserverInterface), NON_EXPORTED_BASE(public base::NonThreadSafe) { public: explicit RtcDtmfSenderHandler(webrtc::DtmfSenderInterface* dtmf_sender); virtual ~RtcDtmfSenderHandler(); - // WebKit::WebRTCDTMFSenderHandler implementation. + // blink::WebRTCDTMFSenderHandler implementation. virtual void setClient( - WebKit::WebRTCDTMFSenderHandlerClient* client) OVERRIDE; - virtual WebKit::WebString currentToneBuffer() OVERRIDE; + blink::WebRTCDTMFSenderHandlerClient* client) OVERRIDE; + virtual blink::WebString currentToneBuffer() OVERRIDE; virtual bool canInsertDTMF() OVERRIDE; - virtual bool insertDTMF(const WebKit::WebString& tones, long duration, + virtual bool insertDTMF(const blink::WebString& tones, long duration, long interToneGap) OVERRIDE; // webrtc::DtmfSenderObserverInterface implementation. @@ -43,7 +43,7 @@ class CONTENT_EXPORT RtcDtmfSenderHandler private: scoped_refptr<webrtc::DtmfSenderInterface> dtmf_sender_; - WebKit::WebRTCDTMFSenderHandlerClient* webkit_client_; + blink::WebRTCDTMFSenderHandlerClient* webkit_client_; }; } // namespace content diff --git a/chromium/content/renderer/media/rtc_media_constraints.cc b/chromium/content/renderer/media/rtc_media_constraints.cc index 7fa9791f2eb..4bdfd9079b3 100644 --- a/chromium/content/renderer/media/rtc_media_constraints.cc +++ b/chromium/content/renderer/media/rtc_media_constraints.cc @@ -3,6 +3,8 @@ // found in the LICENSE file. #include "content/renderer/media/rtc_media_constraints.h" +#include <string> + #include "base/logging.h" #include "base/strings/string_util.h" #include "content/common/media/media_stream_options.h" @@ -14,7 +16,7 @@ namespace content { namespace { void GetNativeMediaConstraints( - const WebKit::WebVector<WebKit::WebMediaConstraint>& constraints, + const blink::WebVector<blink::WebMediaConstraint>& constraints, webrtc::MediaConstraintsInterface::Constraints* native_constraints) { DCHECK(native_constraints); for (size_t i = 0; i < constraints.size(); ++i) { @@ -27,12 +29,17 @@ void GetNativeMediaConstraints( new_constraint.key == kMediaStreamSourceId) continue; + // Ignore sourceId constraint since that has nothing to do with webrtc. + if (new_constraint.key == kMediaStreamSourceInfoId) + continue; + // Ignore internal constraints set by JS. - // TODO(jiayl): replace the hard coded string with - // webrtc::MediaConstraintsInterface::kInternalConstraintPrefix when - // the Libjingle change is rolled. - if (StartsWithASCII(new_constraint.key, "internal", true)) + if (StartsWithASCII( + new_constraint.key, + webrtc::MediaConstraintsInterface::kInternalConstraintPrefix, + true)) { continue; + } DVLOG(3) << "MediaStreamConstraints:" << new_constraint.key << " : " << new_constraint.value; @@ -45,13 +52,13 @@ void GetNativeMediaConstraints( RTCMediaConstraints::RTCMediaConstraints() {} RTCMediaConstraints::RTCMediaConstraints( - const WebKit::WebMediaConstraints& constraints) { + const blink::WebMediaConstraints& constraints) { if (constraints.isNull()) return; // Will happen in unit tests. - WebKit::WebVector<WebKit::WebMediaConstraint> mandatory; + blink::WebVector<blink::WebMediaConstraint> mandatory; constraints.getMandatoryConstraints(mandatory); GetNativeMediaConstraints(mandatory, &mandatory_); - WebKit::WebVector<WebKit::WebMediaConstraint> optional; + blink::WebVector<blink::WebMediaConstraint> optional; constraints.getOptionalConstraints(optional); GetNativeMediaConstraints(optional, &optional_); } diff --git a/chromium/content/renderer/media/rtc_media_constraints.h b/chromium/content/renderer/media/rtc_media_constraints.h index 58f84864f22..fd55e346b06 100644 --- a/chromium/content/renderer/media/rtc_media_constraints.h +++ b/chromium/content/renderer/media/rtc_media_constraints.h @@ -9,7 +9,7 @@ #include "content/common/content_export.h" #include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h" -namespace WebKit { +namespace blink { class WebMediaConstraints; } @@ -23,7 +23,7 @@ class CONTENT_EXPORT RTCMediaConstraints public: RTCMediaConstraints(); explicit RTCMediaConstraints( - const WebKit::WebMediaConstraints& constraints); + const blink::WebMediaConstraints& constraints); virtual ~RTCMediaConstraints(); virtual const Constraints& GetMandatory() const OVERRIDE; virtual const Constraints& GetOptional() const OVERRIDE; diff --git a/chromium/content/renderer/media/rtc_peer_connection_handler.cc b/chromium/content/renderer/media/rtc_peer_connection_handler.cc index 127a7e23fcd..1536ec30188 100644 --- a/chromium/content/renderer/media/rtc_peer_connection_handler.cc +++ b/chromium/content/renderer/media/rtc_peer_connection_handler.cc @@ -41,10 +41,10 @@ namespace content { // Converter functions from libjingle types to WebKit types. -WebKit::WebRTCPeerConnectionHandlerClient::ICEGatheringState +blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState GetWebKitIceGatheringState( webrtc::PeerConnectionInterface::IceGatheringState state) { - using WebKit::WebRTCPeerConnectionHandlerClient; + using blink::WebRTCPeerConnectionHandlerClient; switch (state) { case webrtc::PeerConnectionInterface::kIceGatheringNew: return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew; @@ -58,10 +58,10 @@ GetWebKitIceGatheringState( } } -static WebKit::WebRTCPeerConnectionHandlerClient::ICEConnectionState +static blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState GetWebKitIceConnectionState( webrtc::PeerConnectionInterface::IceConnectionState ice_state) { - using WebKit::WebRTCPeerConnectionHandlerClient; + using blink::WebRTCPeerConnectionHandlerClient; switch (ice_state) { case webrtc::PeerConnectionInterface::kIceConnectionNew: return WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting; @@ -83,9 +83,9 @@ GetWebKitIceConnectionState( } } -static WebKit::WebRTCPeerConnectionHandlerClient::SignalingState +static blink::WebRTCPeerConnectionHandlerClient::SignalingState GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) { - using WebKit::WebRTCPeerConnectionHandlerClient; + using blink::WebRTCPeerConnectionHandlerClient; switch (state) { case webrtc::PeerConnectionInterface::kStable: return WebRTCPeerConnectionHandlerClient::SignalingStateStable; @@ -106,10 +106,10 @@ GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) { } } -static WebKit::WebRTCSessionDescription +static blink::WebRTCSessionDescription CreateWebKitSessionDescription( const webrtc::SessionDescriptionInterface* native_desc) { - WebKit::WebRTCSessionDescription description; + blink::WebRTCSessionDescription description; if (!native_desc) { LOG(ERROR) << "Native session description is null."; return description; @@ -128,13 +128,13 @@ CreateWebKitSessionDescription( // Converter functions from WebKit types to libjingle types. static void GetNativeIceServers( - const WebKit::WebRTCConfiguration& server_configuration, + const blink::WebRTCConfiguration& server_configuration, webrtc::PeerConnectionInterface::IceServers* servers) { if (server_configuration.isNull() || !servers) return; for (size_t i = 0; i < server_configuration.numberOfServers(); ++i) { webrtc::PeerConnectionInterface::IceServer server; - const WebKit::WebRTCICEServer& webkit_server = + const blink::WebRTCICEServer& webkit_server = server_configuration.server(i); server.username = UTF16ToUTF8(webkit_server.username()); server.password = UTF16ToUTF8(webkit_server.credential()); @@ -172,12 +172,12 @@ class SessionDescriptionRequestTracker { }; // Class mapping responses from calls to libjingle CreateOffer/Answer and -// the WebKit::WebRTCSessionDescriptionRequest. +// the blink::WebRTCSessionDescriptionRequest. class CreateSessionDescriptionRequest : public webrtc::CreateSessionDescriptionObserver { public: explicit CreateSessionDescriptionRequest( - const WebKit::WebRTCSessionDescriptionRequest& request, + const blink::WebRTCSessionDescriptionRequest& request, RTCPeerConnectionHandler* handler, PeerConnectionTracker::Action action) : webkit_request_(request), tracker_(handler, action) {} @@ -195,17 +195,17 @@ class CreateSessionDescriptionRequest virtual ~CreateSessionDescriptionRequest() {} private: - WebKit::WebRTCSessionDescriptionRequest webkit_request_; + blink::WebRTCSessionDescriptionRequest webkit_request_; SessionDescriptionRequestTracker tracker_; }; // Class mapping responses from calls to libjingle -// SetLocalDescription/SetRemoteDescription and a WebKit::WebRTCVoidRequest. +// SetLocalDescription/SetRemoteDescription and a blink::WebRTCVoidRequest. class SetSessionDescriptionRequest : public webrtc::SetSessionDescriptionObserver { public: explicit SetSessionDescriptionRequest( - const WebKit::WebRTCVoidRequest& request, + const blink::WebRTCVoidRequest& request, RTCPeerConnectionHandler* handler, PeerConnectionTracker::Action action) : webkit_request_(request), tracker_(handler, action) {} @@ -223,12 +223,12 @@ class SetSessionDescriptionRequest virtual ~SetSessionDescriptionRequest() {} private: - WebKit::WebRTCVoidRequest webkit_request_; + blink::WebRTCVoidRequest webkit_request_; SessionDescriptionRequestTracker tracker_; }; // Class mapping responses from calls to libjingle -// GetStats into a WebKit::WebRTCStatsCallback. +// GetStats into a blink::WebRTCStatsCallback. class StatsResponse : public webrtc::StatsObserver { public: explicit StatsResponse(const scoped_refptr<LocalRTCStatsRequest>& request) @@ -247,8 +247,8 @@ class StatsResponse : public webrtc::StatsObserver { private: void AddReport(const webrtc::StatsReport& report) { - int idx = response_->addReport(WebKit::WebString::fromUTF8(report.id), - WebKit::WebString::fromUTF8(report.type), + int idx = response_->addReport(blink::WebString::fromUTF8(report.id), + blink::WebString::fromUTF8(report.type), report.timestamp); for (webrtc::StatsReport::Values::const_iterator value_it = report.values.begin(); @@ -260,8 +260,8 @@ class StatsResponse : public webrtc::StatsObserver { void AddStatistic(int idx, const std::string& name, const std::string& value) { response_->addStatistic(idx, - WebKit::WebString::fromUTF8(name), - WebKit::WebString::fromUTF8(value)); + blink::WebString::fromUTF8(name), + blink::WebString::fromUTF8(value)); } talk_base::scoped_refptr<LocalRTCStatsRequest> request_; @@ -269,7 +269,7 @@ class StatsResponse : public webrtc::StatsObserver { }; // Implementation of LocalRTCStatsRequest. -LocalRTCStatsRequest::LocalRTCStatsRequest(WebKit::WebRTCStatsRequest impl) +LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl) : impl_(impl), response_(NULL) { } @@ -281,11 +281,7 @@ bool LocalRTCStatsRequest::hasSelector() const { return impl_.hasSelector(); } -WebKit::WebMediaStream LocalRTCStatsRequest::stream() const { - return impl_.stream(); -} - -WebKit::WebMediaStreamTrack LocalRTCStatsRequest::component() const { +blink::WebMediaStreamTrack LocalRTCStatsRequest::component() const { return impl_.component(); } @@ -302,24 +298,24 @@ void LocalRTCStatsRequest::requestSucceeded( } // Implementation of LocalRTCStatsResponse. -WebKit::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const { +blink::WebRTCStatsResponse LocalRTCStatsResponse::webKitStatsResponse() const { return impl_; } -size_t LocalRTCStatsResponse::addReport(WebKit::WebString type, - WebKit::WebString id, +size_t LocalRTCStatsResponse::addReport(blink::WebString type, + blink::WebString id, double timestamp) { return impl_.addReport(type, id, timestamp); } void LocalRTCStatsResponse::addStatistic(size_t report, - WebKit::WebString name, - WebKit::WebString value) { + blink::WebString name, + blink::WebString value) { impl_.addStatistic(report, name, value); } RTCPeerConnectionHandler::RTCPeerConnectionHandler( - WebKit::WebRTCPeerConnectionHandlerClient* client, + blink::WebRTCPeerConnectionHandlerClient* client, MediaStreamDependencyFactory* dependency_factory) : PeerConnectionHandlerBase(dependency_factory), client_(client), @@ -333,14 +329,14 @@ RTCPeerConnectionHandler::~RTCPeerConnectionHandler() { STLDeleteValues(&remote_streams_); } -void RTCPeerConnectionHandler::associateWithFrame(WebKit::WebFrame* frame) { +void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame* frame) { DCHECK(frame); frame_ = frame; } bool RTCPeerConnectionHandler::initialize( - const WebKit::WebRTCConfiguration& server_configuration, - const WebKit::WebMediaConstraints& options) { + const blink::WebRTCConfiguration& server_configuration, + const blink::WebMediaConstraints& options) { DCHECK(frame_); peer_connection_tracker_ = @@ -351,12 +347,6 @@ bool RTCPeerConnectionHandler::initialize( RTCMediaConstraints constraints(options); - if (!CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableSCTPDataChannels)) { - constraints.AddOptional( - webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, "true"); - } - native_peer_connection_ = dependency_factory_->CreatePeerConnection( servers, &constraints, frame_, this); @@ -372,8 +362,8 @@ bool RTCPeerConnectionHandler::initialize( } bool RTCPeerConnectionHandler::InitializeForTest( - const WebKit::WebRTCConfiguration& server_configuration, - const WebKit::WebMediaConstraints& options, + const blink::WebRTCConfiguration& server_configuration, + const blink::WebMediaConstraints& options, PeerConnectionTracker* peer_connection_tracker) { webrtc::PeerConnectionInterface::IceServers servers; GetNativeIceServers(server_configuration, &servers); @@ -391,8 +381,8 @@ bool RTCPeerConnectionHandler::InitializeForTest( } void RTCPeerConnectionHandler::createOffer( - const WebKit::WebRTCSessionDescriptionRequest& request, - const WebKit::WebMediaConstraints& options) { + const blink::WebRTCSessionDescriptionRequest& request, + const blink::WebMediaConstraints& options) { scoped_refptr<CreateSessionDescriptionRequest> description_request( new talk_base::RefCountedObject<CreateSessionDescriptionRequest>( request, this, PeerConnectionTracker::ACTION_CREATE_OFFER)); @@ -404,8 +394,8 @@ void RTCPeerConnectionHandler::createOffer( } void RTCPeerConnectionHandler::createAnswer( - const WebKit::WebRTCSessionDescriptionRequest& request, - const WebKit::WebMediaConstraints& options) { + const blink::WebRTCSessionDescriptionRequest& request, + const blink::WebMediaConstraints& options) { scoped_refptr<CreateSessionDescriptionRequest> description_request( new talk_base::RefCountedObject<CreateSessionDescriptionRequest>( request, this, PeerConnectionTracker::ACTION_CREATE_ANSWER)); @@ -418,8 +408,8 @@ void RTCPeerConnectionHandler::createAnswer( } void RTCPeerConnectionHandler::setLocalDescription( - const WebKit::WebRTCVoidRequest& request, - const WebKit::WebRTCSessionDescription& description) { + const blink::WebRTCVoidRequest& request, + const blink::WebRTCSessionDescription& description) { webrtc::SdpParseError error; webrtc::SessionDescriptionInterface* native_desc = CreateNativeSessionDescription(description, &error); @@ -429,7 +419,7 @@ void RTCPeerConnectionHandler::setLocalDescription( reason_str.append(" "); reason_str.append(error.description); LOG(ERROR) << reason_str; - request.requestFailed(WebKit::WebString::fromUTF8(reason_str)); + request.requestFailed(blink::WebString::fromUTF8(reason_str)); return; } if (peer_connection_tracker_) @@ -443,8 +433,8 @@ void RTCPeerConnectionHandler::setLocalDescription( } void RTCPeerConnectionHandler::setRemoteDescription( - const WebKit::WebRTCVoidRequest& request, - const WebKit::WebRTCSessionDescription& description) { + const blink::WebRTCVoidRequest& request, + const blink::WebRTCSessionDescription& description) { webrtc::SdpParseError error; webrtc::SessionDescriptionInterface* native_desc = CreateNativeSessionDescription(description, &error); @@ -454,7 +444,7 @@ void RTCPeerConnectionHandler::setRemoteDescription( reason_str.append(" "); reason_str.append(error.description); LOG(ERROR) << reason_str; - request.requestFailed(WebKit::WebString::fromUTF8(reason_str)); + request.requestFailed(blink::WebString::fromUTF8(reason_str)); return; } if (peer_connection_tracker_) @@ -467,27 +457,27 @@ void RTCPeerConnectionHandler::setRemoteDescription( native_peer_connection_->SetRemoteDescription(set_request.get(), native_desc); } -WebKit::WebRTCSessionDescription +blink::WebRTCSessionDescription RTCPeerConnectionHandler::localDescription() { const webrtc::SessionDescriptionInterface* native_desc = native_peer_connection_->local_description(); - WebKit::WebRTCSessionDescription description = + blink::WebRTCSessionDescription description = CreateWebKitSessionDescription(native_desc); return description; } -WebKit::WebRTCSessionDescription +blink::WebRTCSessionDescription RTCPeerConnectionHandler::remoteDescription() { const webrtc::SessionDescriptionInterface* native_desc = native_peer_connection_->remote_description(); - WebKit::WebRTCSessionDescription description = + blink::WebRTCSessionDescription description = CreateWebKitSessionDescription(native_desc); return description; } bool RTCPeerConnectionHandler::updateICE( - const WebKit::WebRTCConfiguration& server_configuration, - const WebKit::WebMediaConstraints& options) { + const blink::WebRTCConfiguration& server_configuration, + const blink::WebMediaConstraints& options) { webrtc::PeerConnectionInterface::IceServers servers; GetNativeIceServers(server_configuration, &servers); RTCMediaConstraints constraints(options); @@ -500,7 +490,21 @@ bool RTCPeerConnectionHandler::updateICE( } bool RTCPeerConnectionHandler::addICECandidate( - const WebKit::WebRTCICECandidate& candidate) { + const blink::WebRTCVoidRequest& request, + const blink::WebRTCICECandidate& candidate) { + // Libjingle currently does not accept callbacks for addICECandidate. + // For that reason we are going to call callbacks from here. + bool result = addICECandidate(candidate); + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&RTCPeerConnectionHandler::OnaddICECandidateResult, + base::Unretained(this), request, result)); + // On failure callback will be triggered. + return true; +} + +bool RTCPeerConnectionHandler::addICECandidate( + const blink::WebRTCICECandidate& candidate) { scoped_ptr<webrtc::IceCandidateInterface> native_candidate( dependency_factory_->CreateIceCandidate( UTF16ToUTF8(candidate.sdpMid()), @@ -522,9 +526,21 @@ bool RTCPeerConnectionHandler::addICECandidate( return return_value; } +void RTCPeerConnectionHandler::OnaddICECandidateResult( + const blink::WebRTCVoidRequest& webkit_request, bool result) { + if (!result) { + // We don't have the actual error code from the libjingle, so for now + // using a generic error string. + return webkit_request.requestFailed( + UTF8ToUTF16("Error processing ICE candidate")); + } + + return webkit_request.requestSucceeded(); +} + bool RTCPeerConnectionHandler::addStream( - const WebKit::WebMediaStream& stream, - const WebKit::WebMediaConstraints& options) { + const blink::WebMediaStream& stream, + const blink::WebMediaConstraints& options) { RTCMediaConstraints constraints(options); if (peer_connection_tracker_) @@ -545,7 +561,7 @@ bool RTCPeerConnectionHandler::addStream( } void RTCPeerConnectionHandler::removeStream( - const WebKit::WebMediaStream& stream) { + const blink::WebMediaStream& stream) { RemoveStream(stream); if (peer_connection_tracker_) peer_connection_tracker_->TrackRemoveStream( @@ -553,7 +569,7 @@ void RTCPeerConnectionHandler::removeStream( } void RTCPeerConnectionHandler::getStats( - const WebKit::WebRTCStatsRequest& request) { + const blink::WebRTCStatsRequest& request) { scoped_refptr<LocalRTCStatsRequest> inner_request( new talk_base::RefCountedObject<LocalRTCStatsRequest>(request)); getStats(inner_request.get()); @@ -564,8 +580,8 @@ void RTCPeerConnectionHandler::getStats(LocalRTCStatsRequest* request) { new talk_base::RefCountedObject<StatsResponse>(request)); webrtc::MediaStreamTrackInterface* track = NULL; if (request->hasSelector()) { - track = GetNativeMediaStreamTrack(request->stream(), - request->component()); + track = MediaStreamDependencyFactory::GetNativeMediaStreamTrack( + request->component()); if (!track) { DVLOG(1) << "GetStats: Track not found."; // TODO(hta): Consider how to get an error back. @@ -589,8 +605,8 @@ void RTCPeerConnectionHandler::GetStats( } } -WebKit::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel( - const WebKit::WebString& label, const WebKit::WebRTCDataChannelInit& init) { +blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel( + const blink::WebString& label, const blink::WebRTCDataChannelInit& init) { DVLOG(1) << "createDataChannel label " << UTF16ToUTF8(label); webrtc::DataChannelInit config; @@ -617,18 +633,18 @@ WebKit::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel( return new RtcDataChannelHandler(webrtc_channel); } -WebKit::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender( - const WebKit::WebMediaStreamTrack& track) { +blink::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender( + const blink::WebMediaStreamTrack& track) { DVLOG(1) << "createDTMFSender."; - if (track.source().type() != WebKit::WebMediaStreamSource::TypeAudio) { + if (track.source().type() != blink::WebMediaStreamSource::TypeAudio) { DLOG(ERROR) << "Could not create DTMF sender from a non-audio track."; return NULL; } webrtc::AudioTrackInterface* audio_track = static_cast<webrtc::AudioTrackInterface*>( - GetNativeMediaStreamTrack(track.stream(), track)); + MediaStreamDependencyFactory::GetNativeMediaStreamTrack(track)); talk_base::scoped_refptr<webrtc::DtmfSenderInterface> sender( native_peer_connection_->CreateDtmfSender(audio_track)); @@ -657,7 +673,7 @@ void RTCPeerConnectionHandler::OnError() { void RTCPeerConnectionHandler::OnSignalingChange( webrtc::PeerConnectionInterface::SignalingState new_state) { - WebKit::WebRTCPeerConnectionHandlerClient::SignalingState state = + blink::WebRTCPeerConnectionHandlerClient::SignalingState state = GetWebKitSignalingState(new_state); if (peer_connection_tracker_) peer_connection_tracker_->TrackSignalingStateChange(this, state); @@ -667,7 +683,7 @@ void RTCPeerConnectionHandler::OnSignalingChange( // Called any time the IceConnectionState changes void RTCPeerConnectionHandler::OnIceConnectionChange( webrtc::PeerConnectionInterface::IceConnectionState new_state) { - WebKit::WebRTCPeerConnectionHandlerClient::ICEConnectionState state = + blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state = GetWebKitIceConnectionState(new_state); if (peer_connection_tracker_) peer_connection_tracker_->TrackIceConnectionStateChange(this, state); @@ -680,11 +696,11 @@ void RTCPeerConnectionHandler::OnIceGatheringChange( if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) { // If ICE gathering is completed, generate a NULL ICE candidate, // to signal end of candidates. - WebKit::WebRTCICECandidate null_candidate; + blink::WebRTCICECandidate null_candidate; client_->didGenerateICECandidate(null_candidate); } - WebKit::WebRTCPeerConnectionHandlerClient::ICEGatheringState state = + blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state = GetWebKitIceGatheringState(new_state); if (peer_connection_tracker_) peer_connection_tracker_->TrackIceGatheringStateChange(this, state); @@ -720,7 +736,7 @@ void RTCPeerConnectionHandler::OnRemoveStream( } scoped_ptr<RemoteMediaStreamImpl> remote_stream(it->second); - const WebKit::WebMediaStream& webkit_stream = remote_stream->webkit_stream(); + const blink::WebMediaStream& webkit_stream = remote_stream->webkit_stream(); DCHECK(!webkit_stream.isNull()); remote_streams_.erase(it); @@ -739,7 +755,7 @@ void RTCPeerConnectionHandler::OnIceCandidate( NOTREACHED() << "OnIceCandidate: Could not get SDP string."; return; } - WebKit::WebRTCICECandidate web_candidate; + blink::WebRTCICECandidate web_candidate; web_candidate.initialize(UTF8ToUTF16(sdp), UTF8ToUTF16(candidate->sdp_mid()), candidate->sdp_mline_index()); @@ -773,7 +789,7 @@ PeerConnectionTracker* RTCPeerConnectionHandler::peer_connection_tracker() { webrtc::SessionDescriptionInterface* RTCPeerConnectionHandler::CreateNativeSessionDescription( - const WebKit::WebRTCSessionDescription& description, + const blink::WebRTCSessionDescription& description, webrtc::SdpParseError* error) { std::string sdp = UTF16ToUTF8(description.sdp()); std::string type = UTF16ToUTF8(description.type()); diff --git a/chromium/content/renderer/media/rtc_peer_connection_handler.h b/chromium/content/renderer/media/rtc_peer_connection_handler.h index bb650102143..f3de4b9e8f7 100644 --- a/chromium/content/renderer/media/rtc_peer_connection_handler.h +++ b/chromium/content/renderer/media/rtc_peer_connection_handler.h @@ -13,7 +13,7 @@ #include "third_party/WebKit/public/platform/WebRTCStatsRequest.h" #include "third_party/WebKit/public/platform/WebRTCStatsResponse.h" -namespace WebKit { +namespace blink { class WebFrame; class WebRTCDataChannelHandler; } @@ -22,19 +22,19 @@ namespace content { class PeerConnectionTracker; -// Mockable wrapper for WebKit::WebRTCStatsResponse +// Mockable wrapper for blink::WebRTCStatsResponse class CONTENT_EXPORT LocalRTCStatsResponse : public NON_EXPORTED_BASE(talk_base::RefCountInterface) { public: - explicit LocalRTCStatsResponse(const WebKit::WebRTCStatsResponse& impl) + explicit LocalRTCStatsResponse(const blink::WebRTCStatsResponse& impl) : impl_(impl) { } - virtual WebKit::WebRTCStatsResponse webKitStatsResponse() const; - virtual size_t addReport(WebKit::WebString type, WebKit::WebString id, + virtual blink::WebRTCStatsResponse webKitStatsResponse() const; + virtual size_t addReport(blink::WebString type, blink::WebString id, double timestamp); virtual void addStatistic(size_t report, - WebKit::WebString name, WebKit::WebString value); + blink::WebString name, blink::WebString value); protected: virtual ~LocalRTCStatsResponse() {} @@ -42,20 +42,19 @@ class CONTENT_EXPORT LocalRTCStatsResponse LocalRTCStatsResponse() {} private: - WebKit::WebRTCStatsResponse impl_; + blink::WebRTCStatsResponse impl_; }; -// Mockable wrapper for WebKit::WebRTCStatsRequest +// Mockable wrapper for blink::WebRTCStatsRequest class CONTENT_EXPORT LocalRTCStatsRequest : public NON_EXPORTED_BASE(talk_base::RefCountInterface) { public: - explicit LocalRTCStatsRequest(WebKit::WebRTCStatsRequest impl); + explicit LocalRTCStatsRequest(blink::WebRTCStatsRequest impl); // Constructor for testing. LocalRTCStatsRequest(); virtual bool hasSelector() const; - virtual WebKit::WebMediaStream stream() const; - virtual WebKit::WebMediaStreamTrack component() const; + virtual blink::WebMediaStreamTrack component() const; virtual void requestSucceeded(const LocalRTCStatsResponse* response); virtual scoped_refptr<LocalRTCStatsResponse> createResponse(); @@ -63,7 +62,7 @@ class CONTENT_EXPORT LocalRTCStatsRequest virtual ~LocalRTCStatsRequest(); private: - WebKit::WebRTCStatsRequest impl_; + blink::WebRTCStatsRequest impl_; talk_base::scoped_refptr<LocalRTCStatsResponse> response_; }; @@ -75,62 +74,68 @@ class CONTENT_EXPORT LocalRTCStatsRequest // the main render thread. class CONTENT_EXPORT RTCPeerConnectionHandler : public PeerConnectionHandlerBase, - NON_EXPORTED_BASE(public WebKit::WebRTCPeerConnectionHandler) { + NON_EXPORTED_BASE(public blink::WebRTCPeerConnectionHandler) { public: RTCPeerConnectionHandler( - WebKit::WebRTCPeerConnectionHandlerClient* client, + blink::WebRTCPeerConnectionHandlerClient* client, MediaStreamDependencyFactory* dependency_factory); virtual ~RTCPeerConnectionHandler(); - void associateWithFrame(WebKit::WebFrame* frame); + void associateWithFrame(blink::WebFrame* frame); // Initialize method only used for unit test. bool InitializeForTest( - const WebKit::WebRTCConfiguration& server_configuration, - const WebKit::WebMediaConstraints& options, + const blink::WebRTCConfiguration& server_configuration, + const blink::WebMediaConstraints& options, PeerConnectionTracker* peer_connection_tracker); - // WebKit::WebRTCPeerConnectionHandler implementation + // blink::WebRTCPeerConnectionHandler implementation virtual bool initialize( - const WebKit::WebRTCConfiguration& server_configuration, - const WebKit::WebMediaConstraints& options) OVERRIDE; + const blink::WebRTCConfiguration& server_configuration, + const blink::WebMediaConstraints& options) OVERRIDE; virtual void createOffer( - const WebKit::WebRTCSessionDescriptionRequest& request, - const WebKit::WebMediaConstraints& options) OVERRIDE; + const blink::WebRTCSessionDescriptionRequest& request, + const blink::WebMediaConstraints& options) OVERRIDE; virtual void createAnswer( - const WebKit::WebRTCSessionDescriptionRequest& request, - const WebKit::WebMediaConstraints& options) OVERRIDE; + const blink::WebRTCSessionDescriptionRequest& request, + const blink::WebMediaConstraints& options) OVERRIDE; virtual void setLocalDescription( - const WebKit::WebRTCVoidRequest& request, - const WebKit::WebRTCSessionDescription& description) OVERRIDE; + const blink::WebRTCVoidRequest& request, + const blink::WebRTCSessionDescription& description) OVERRIDE; virtual void setRemoteDescription( - const WebKit::WebRTCVoidRequest& request, - const WebKit::WebRTCSessionDescription& description) OVERRIDE; + const blink::WebRTCVoidRequest& request, + const blink::WebRTCSessionDescription& description) OVERRIDE; - virtual WebKit::WebRTCSessionDescription localDescription() + virtual blink::WebRTCSessionDescription localDescription() OVERRIDE; - virtual WebKit::WebRTCSessionDescription remoteDescription() + virtual blink::WebRTCSessionDescription remoteDescription() OVERRIDE; + virtual bool updateICE( - const WebKit::WebRTCConfiguration& server_configuration, - const WebKit::WebMediaConstraints& options) OVERRIDE; + const blink::WebRTCConfiguration& server_configuration, + const blink::WebMediaConstraints& options) OVERRIDE; + virtual bool addICECandidate( + const blink::WebRTCICECandidate& candidate) OVERRIDE; virtual bool addICECandidate( - const WebKit::WebRTCICECandidate& candidate) OVERRIDE; + const blink::WebRTCVoidRequest& request, + const blink::WebRTCICECandidate& candidate) OVERRIDE; + virtual void OnaddICECandidateResult(const blink::WebRTCVoidRequest& request, + bool result); virtual bool addStream( - const WebKit::WebMediaStream& stream, - const WebKit::WebMediaConstraints& options) OVERRIDE; + const blink::WebMediaStream& stream, + const blink::WebMediaConstraints& options) OVERRIDE; virtual void removeStream( - const WebKit::WebMediaStream& stream) OVERRIDE; + const blink::WebMediaStream& stream) OVERRIDE; virtual void getStats( - const WebKit::WebRTCStatsRequest& request) OVERRIDE; - virtual WebKit::WebRTCDataChannelHandler* createDataChannel( - const WebKit::WebString& label, - const WebKit::WebRTCDataChannelInit& init) OVERRIDE; - virtual WebKit::WebRTCDTMFSenderHandler* createDTMFSender( - const WebKit::WebMediaStreamTrack& track) OVERRIDE; + const blink::WebRTCStatsRequest& request) OVERRIDE; + virtual blink::WebRTCDataChannelHandler* createDataChannel( + const blink::WebString& label, + const blink::WebRTCDataChannelInit& init) OVERRIDE; + virtual blink::WebRTCDTMFSenderHandler* createDTMFSender( + const blink::WebMediaStreamTrack& track) OVERRIDE; virtual void stop() OVERRIDE; // webrtc::PeerConnectionObserver implementation @@ -163,13 +168,13 @@ class CONTENT_EXPORT RTCPeerConnectionHandler private: webrtc::SessionDescriptionInterface* CreateNativeSessionDescription( - const WebKit::WebRTCSessionDescription& description, + const blink::WebRTCSessionDescription& description, webrtc::SdpParseError* error); // |client_| is a weak pointer, and is valid until stop() has returned. - WebKit::WebRTCPeerConnectionHandlerClient* client_; + blink::WebRTCPeerConnectionHandlerClient* client_; - WebKit::WebFrame* frame_; + blink::WebFrame* frame_; PeerConnectionTracker* peer_connection_tracker_; diff --git a/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc b/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc index 9528cbe6714..18901ea7a7e 100644 --- a/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc +++ b/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc @@ -38,7 +38,7 @@ static const char kDummySdp[] = "dummy sdp"; static const char kDummySdpType[] = "dummy type"; -using WebKit::WebRTCPeerConnectionHandlerClient; +using blink::WebRTCPeerConnectionHandlerClient; using testing::NiceMock; using testing::_; using testing::Ref; @@ -52,15 +52,15 @@ class MockRTCStatsResponse : public LocalRTCStatsResponse { statistic_count_(0) { } - virtual size_t addReport(WebKit::WebString type, - WebKit::WebString id, + virtual size_t addReport(blink::WebString type, + blink::WebString id, double timestamp) OVERRIDE { ++report_count_; return report_count_; } virtual void addStatistic(size_t report, - WebKit::WebString name, WebKit::WebString value) + blink::WebString name, blink::WebString value) OVERRIDE { ++statistic_count_; } @@ -71,21 +71,17 @@ class MockRTCStatsResponse : public LocalRTCStatsResponse { int statistic_count_; }; -// Mocked wrapper for WebKit::WebRTCStatsRequest +// Mocked wrapper for blink::WebRTCStatsRequest class MockRTCStatsRequest : public LocalRTCStatsRequest { public: MockRTCStatsRequest() : has_selector_(false), - stream_(), request_succeeded_called_(false) {} virtual bool hasSelector() const OVERRIDE { return has_selector_; } - virtual WebKit::WebMediaStream stream() const OVERRIDE { - return stream_; - } - virtual WebKit::WebMediaStreamTrack component() const OVERRIDE { + virtual blink::WebMediaStreamTrack component() const OVERRIDE { return component_; } virtual scoped_refptr<LocalRTCStatsResponse> createResponse() OVERRIDE { @@ -101,10 +97,8 @@ class MockRTCStatsRequest : public LocalRTCStatsRequest { } // Function for setting whether or not a selector is available. - void setSelector(const WebKit::WebMediaStream& stream, - const WebKit::WebMediaStreamTrack& component) { + void setSelector(const blink::WebMediaStreamTrack& component) { has_selector_ = true; - stream_ = stream; component_ = component; } @@ -119,8 +113,7 @@ class MockRTCStatsRequest : public LocalRTCStatsRequest { private: bool has_selector_; - WebKit::WebMediaStream stream_; - WebKit::WebMediaStreamTrack component_; + blink::WebMediaStreamTrack component_; scoped_refptr<MockRTCStatsResponse> response_; bool request_succeeded_called_; }; @@ -138,7 +131,7 @@ class MockPeerConnectionTracker : public PeerConnectionTracker { const RTCMediaConstraints& constraints)); MOCK_METHOD3(TrackSetSessionDescription, void(RTCPeerConnectionHandler* pc_handler, - const WebKit::WebRTCSessionDescription& desc, + const blink::WebRTCSessionDescription& desc, Source source)); MOCK_METHOD3( TrackUpdateIce, @@ -148,15 +141,15 @@ class MockPeerConnectionTracker : public PeerConnectionTracker { const RTCMediaConstraints& options)); MOCK_METHOD3(TrackAddIceCandidate, void(RTCPeerConnectionHandler* pc_handler, - const WebKit::WebRTCICECandidate& candidate, + const blink::WebRTCICECandidate& candidate, Source source)); MOCK_METHOD3(TrackAddStream, void(RTCPeerConnectionHandler* pc_handler, - const WebKit::WebMediaStream& stream, + const blink::WebMediaStream& stream, Source source)); MOCK_METHOD3(TrackRemoveStream, void(RTCPeerConnectionHandler* pc_handler, - const WebKit::WebMediaStream& stream, + const blink::WebMediaStream& stream, Source source)); MOCK_METHOD1(TrackOnIceComplete, void(RTCPeerConnectionHandler* pc_handler)); @@ -180,7 +173,7 @@ class MockPeerConnectionTracker : public PeerConnectionTracker { void(RTCPeerConnectionHandler* pc_handler)); MOCK_METHOD2(TrackCreateDTMFSender, void(RTCPeerConnectionHandler* pc_handler, - const WebKit::WebMediaStreamTrack& track)); + const blink::WebMediaStreamTrack& track)); }; class RTCPeerConnectionHandlerUnderTest : public RTCPeerConnectionHandler { @@ -209,8 +202,8 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test { new RTCPeerConnectionHandlerUnderTest(mock_client_.get(), mock_dependency_factory_.get())); mock_tracker_.reset(new NiceMock<MockPeerConnectionTracker>()); - WebKit::WebRTCConfiguration config; - WebKit::WebMediaConstraints constraints; + blink::WebRTCConfiguration config; + blink::WebMediaConstraints constraints; EXPECT_TRUE(pc_handler_->InitializeForTest(config, constraints, mock_tracker_.get())); @@ -219,28 +212,28 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test { } // Creates a WebKit local MediaStream. - WebKit::WebMediaStream CreateLocalMediaStream( + blink::WebMediaStream CreateLocalMediaStream( const std::string& stream_label) { std::string video_track_label("video-label"); std::string audio_track_label("audio-label"); - WebKit::WebMediaStreamSource audio_source; - audio_source.initialize(WebKit::WebString::fromUTF8(audio_track_label), - WebKit::WebMediaStreamSource::TypeAudio, - WebKit::WebString::fromUTF8("audio_track")); - WebKit::WebMediaStreamSource video_source; - video_source.initialize(WebKit::WebString::fromUTF8(video_track_label), - WebKit::WebMediaStreamSource::TypeVideo, - WebKit::WebString::fromUTF8("video_track")); + blink::WebMediaStreamSource audio_source; + audio_source.initialize(blink::WebString::fromUTF8(audio_track_label), + blink::WebMediaStreamSource::TypeAudio, + blink::WebString::fromUTF8("audio_track")); + blink::WebMediaStreamSource video_source; + video_source.initialize(blink::WebString::fromUTF8(video_track_label), + blink::WebMediaStreamSource::TypeVideo, + blink::WebString::fromUTF8("video_track")); - WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks( + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks( static_cast<size_t>(1)); audio_tracks[0].initialize(audio_source.id(), audio_source); - WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks( + blink::WebVector<blink::WebMediaStreamTrack> video_tracks( static_cast<size_t>(1)); video_tracks[0].initialize(video_source.id(), video_source); - WebKit::WebMediaStream local_stream; + blink::WebMediaStream local_stream; local_stream.initialize(UTF8ToUTF16(stream_label), audio_tracks, video_tracks); @@ -255,6 +248,8 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test { mock_dependency_factory_->CreateLocalAudioTrack( audio_track_id, capturer, NULL, NULL, &audio_constraints)); + MediaStreamDependencyFactory::AddNativeTrackToBlinkTrack( + audio_track.get(), audio_tracks[0], true); native_stream->AddTrack(audio_track.get()); local_stream.videoTracks(video_tracks); @@ -263,6 +258,8 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test { scoped_refptr<webrtc::VideoTrackInterface> video_track( mock_dependency_factory_->CreateLocalVideoTrack( video_track_id, source)); + MediaStreamDependencyFactory::AddNativeTrackToBlinkTrack( + video_track.get(), video_tracks[0], true); native_stream->AddTrack(video_track.get()); local_stream.setExtraData( @@ -315,11 +312,11 @@ TEST_F(RTCPeerConnectionHandlerTest, Destruct) { } TEST_F(RTCPeerConnectionHandlerTest, CreateOffer) { - WebKit::WebRTCSessionDescriptionRequest request; - WebKit::WebMediaConstraints options; + blink::WebRTCSessionDescriptionRequest request; + blink::WebMediaConstraints options; EXPECT_CALL(*mock_tracker_.get(), TrackCreateOffer(pc_handler_.get(), _)); - // TODO(perkj): Can WebKit::WebRTCSessionDescriptionRequest be changed so + // TODO(perkj): Can blink::WebRTCSessionDescriptionRequest be changed so // the |reqest| requestSucceeded can be tested? Currently the |request| object // can not be initialized from a unit test. EXPECT_FALSE(mock_peer_connection_->created_session_description() != NULL); @@ -328,10 +325,10 @@ TEST_F(RTCPeerConnectionHandlerTest, CreateOffer) { } TEST_F(RTCPeerConnectionHandlerTest, CreateAnswer) { - WebKit::WebRTCSessionDescriptionRequest request; - WebKit::WebMediaConstraints options; + blink::WebRTCSessionDescriptionRequest request; + blink::WebMediaConstraints options; EXPECT_CALL(*mock_tracker_.get(), TrackCreateAnswer(pc_handler_.get(), _)); - // TODO(perkj): Can WebKit::WebRTCSessionDescriptionRequest be changed so + // TODO(perkj): Can blink::WebRTCSessionDescriptionRequest be changed so // the |reqest| requestSucceeded can be tested? Currently the |request| object // can not be initialized from a unit test. EXPECT_FALSE(mock_peer_connection_->created_session_description() != NULL); @@ -340,8 +337,8 @@ TEST_F(RTCPeerConnectionHandlerTest, CreateAnswer) { } TEST_F(RTCPeerConnectionHandlerTest, setLocalDescription) { - WebKit::WebRTCVoidRequest request; - WebKit::WebRTCSessionDescription description; + blink::WebRTCVoidRequest request; + blink::WebRTCSessionDescription description; description.initialize(kDummySdpType, kDummySdp); // PeerConnectionTracker::TrackSetSessionDescription is expected to be called // before |mock_peer_connection| is called. @@ -363,8 +360,8 @@ TEST_F(RTCPeerConnectionHandlerTest, setLocalDescription) { } TEST_F(RTCPeerConnectionHandlerTest, setRemoteDescription) { - WebKit::WebRTCVoidRequest request; - WebKit::WebRTCSessionDescription description; + blink::WebRTCVoidRequest request; + blink::WebRTCSessionDescription description; description.initialize(kDummySdpType, kDummySdp); // PeerConnectionTracker::TrackSetSessionDescription is expected to be called @@ -387,8 +384,8 @@ TEST_F(RTCPeerConnectionHandlerTest, setRemoteDescription) { } TEST_F(RTCPeerConnectionHandlerTest, updateICE) { - WebKit::WebRTCConfiguration config; - WebKit::WebMediaConstraints constraints; + blink::WebRTCConfiguration config; + blink::WebMediaConstraints constraints; EXPECT_CALL(*mock_tracker_.get(), TrackUpdateIce(pc_handler_.get(), _, _)); // TODO(perkj): Test that the parameters in |config| can be translated when a @@ -398,7 +395,7 @@ TEST_F(RTCPeerConnectionHandlerTest, updateICE) { } TEST_F(RTCPeerConnectionHandlerTest, addICECandidate) { - WebKit::WebRTCICECandidate candidate; + blink::WebRTCICECandidate candidate; candidate.initialize(kDummySdp, "mid", 1); EXPECT_CALL(*mock_tracker_.get(), @@ -413,9 +410,9 @@ TEST_F(RTCPeerConnectionHandlerTest, addICECandidate) { TEST_F(RTCPeerConnectionHandlerTest, addAndRemoveStream) { std::string stream_label = "local_stream"; - WebKit::WebMediaStream local_stream( + blink::WebMediaStream local_stream( CreateLocalMediaStream(stream_label)); - WebKit::WebMediaConstraints constraints; + blink::WebMediaConstraints constraints; EXPECT_CALL(*mock_tracker_.get(), TrackAddStream(pc_handler_.get(), @@ -456,17 +453,17 @@ TEST_F(RTCPeerConnectionHandlerTest, GetStatsAfterClose) { } TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithLocalSelector) { - WebKit::WebMediaStream local_stream( + blink::WebMediaStream local_stream( CreateLocalMediaStream("local_stream")); - WebKit::WebMediaConstraints constraints; + blink::WebMediaConstraints constraints; pc_handler_->addStream(local_stream, constraints); - WebKit::WebVector<WebKit::WebMediaStreamTrack> tracks; + blink::WebVector<blink::WebMediaStreamTrack> tracks; local_stream.audioTracks(tracks); ASSERT_LE(1ul, tracks.size()); scoped_refptr<MockRTCStatsRequest> request( new talk_base::RefCountedObject<MockRTCStatsRequest>()); - request->setSelector(local_stream, tracks[0]); + request->setSelector(tracks[0]); pc_handler_->getStats(request.get()); EXPECT_EQ(1, request->result()->report_count()); } @@ -475,15 +472,15 @@ TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithRemoteSelector) { scoped_refptr<webrtc::MediaStreamInterface> stream( AddRemoteMockMediaStream("remote_stream", "video", "audio")); pc_handler_->OnAddStream(stream.get()); - const WebKit::WebMediaStream& remote_stream = mock_client_->remote_stream(); + const blink::WebMediaStream& remote_stream = mock_client_->remote_stream(); - WebKit::WebVector<WebKit::WebMediaStreamTrack> tracks; + blink::WebVector<blink::WebMediaStreamTrack> tracks; remote_stream.audioTracks(tracks); ASSERT_LE(1ul, tracks.size()); scoped_refptr<MockRTCStatsRequest> request( new talk_base::RefCountedObject<MockRTCStatsRequest>()); - request->setSelector(remote_stream, tracks[0]); + request->setSelector(tracks[0]); pc_handler_->getStats(request.get()); EXPECT_EQ(1, request->result()->report_count()); } @@ -491,18 +488,18 @@ TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithRemoteSelector) { TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithBadSelector) { // The setup is the same as GetStatsWithLocalSelector, but the stream is not // added to the PeerConnection. - WebKit::WebMediaStream local_stream( + blink::WebMediaStream local_stream( CreateLocalMediaStream("local_stream_2")); - WebKit::WebMediaConstraints constraints; - WebKit::WebVector<WebKit::WebMediaStreamTrack> tracks; + blink::WebMediaConstraints constraints; + blink::WebVector<blink::WebMediaStreamTrack> tracks; local_stream.audioTracks(tracks); - WebKit::WebMediaStreamTrack component = tracks[0]; + blink::WebMediaStreamTrack component = tracks[0]; mock_peer_connection_->SetGetStatsResult(false); scoped_refptr<MockRTCStatsRequest> request( new talk_base::RefCountedObject<MockRTCStatsRequest>()); - request->setSelector(local_stream, component); + request->setSelector(component); pc_handler_->getStats(request.get()); EXPECT_EQ(0, request->result()->report_count()); } @@ -655,20 +652,20 @@ TEST_F(RTCPeerConnectionHandlerTest, OnAddAndOnRemoveStream) { testing::InSequence sequence; EXPECT_CALL(*mock_tracker_.get(), TrackAddStream( pc_handler_.get(), - testing::Property(&WebKit::WebMediaStream::id, + testing::Property(&blink::WebMediaStream::id, UTF8ToUTF16(remote_stream_label)), PeerConnectionTracker::SOURCE_REMOTE)); EXPECT_CALL(*mock_client_.get(), didAddRemoteStream( - testing::Property(&WebKit::WebMediaStream::id, + testing::Property(&blink::WebMediaStream::id, UTF8ToUTF16(remote_stream_label)))); EXPECT_CALL(*mock_tracker_.get(), TrackRemoveStream( pc_handler_.get(), - testing::Property(&WebKit::WebMediaStream::id, + testing::Property(&blink::WebMediaStream::id, UTF8ToUTF16(remote_stream_label)), PeerConnectionTracker::SOURCE_REMOTE)); EXPECT_CALL(*mock_client_.get(), didRemoveRemoteStream( - testing::Property(&WebKit::WebMediaStream::id, + testing::Property(&blink::WebMediaStream::id, UTF8ToUTF16(remote_stream_label)))); pc_handler_->OnAddStream(remote_stream.get()); @@ -683,29 +680,29 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoteTrackState) { testing::InSequence sequence; EXPECT_CALL(*mock_client_.get(), didAddRemoteStream( - testing::Property(&WebKit::WebMediaStream::id, + testing::Property(&blink::WebMediaStream::id, UTF8ToUTF16(remote_stream_label)))); pc_handler_->OnAddStream(remote_stream.get()); - const WebKit::WebMediaStream& webkit_stream = mock_client_->remote_stream(); + const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream(); - WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks; + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; webkit_stream.audioTracks(audio_tracks); - EXPECT_EQ(WebKit::WebMediaStreamSource::ReadyStateLive, + EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive, audio_tracks[0].source().readyState()); - WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks; + blink::WebVector<blink::WebMediaStreamTrack> video_tracks; webkit_stream.videoTracks(video_tracks); - EXPECT_EQ(WebKit::WebMediaStreamSource::ReadyStateLive, + EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive, video_tracks[0].source().readyState()); remote_stream->GetAudioTracks()[0]->set_state( webrtc::MediaStreamTrackInterface::kEnded); - EXPECT_EQ(WebKit::WebMediaStreamSource::ReadyStateEnded, + EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded, audio_tracks[0].source().readyState()); remote_stream->GetVideoTracks()[0]->set_state( webrtc::MediaStreamTrackInterface::kEnded); - EXPECT_EQ(WebKit::WebMediaStreamSource::ReadyStateEnded, + EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded, video_tracks[0].source().readyState()); } @@ -715,12 +712,12 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddAudioTrackFromRemoteStream) { AddRemoteMockMediaStream(remote_stream_label, "video", "audio")); EXPECT_CALL(*mock_client_.get(), didAddRemoteStream( - testing::Property(&WebKit::WebMediaStream::id, + testing::Property(&blink::WebMediaStream::id, UTF8ToUTF16(remote_stream_label)))); pc_handler_->OnAddStream(remote_stream.get()); - const WebKit::WebMediaStream& webkit_stream = mock_client_->remote_stream(); + const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream(); - WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks; + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; webkit_stream.audioTracks(audio_tracks); EXPECT_EQ(1u, audio_tracks.size()); @@ -728,13 +725,13 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddAudioTrackFromRemoteStream) { scoped_refptr<webrtc::AudioTrackInterface> webrtc_track = remote_stream->GetAudioTracks()[0].get(); remote_stream->RemoveTrack(webrtc_track.get()); - WebKit::WebVector<WebKit::WebMediaStreamTrack> modified_audio_tracks1; + blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks1; webkit_stream.audioTracks(modified_audio_tracks1); EXPECT_EQ(0u, modified_audio_tracks1.size()); // Add the WebRtc audio track again. remote_stream->AddTrack(webrtc_track.get()); - WebKit::WebVector<WebKit::WebMediaStreamTrack> modified_audio_tracks2; + blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks2; webkit_stream.audioTracks(modified_audio_tracks2); EXPECT_EQ(1u, modified_audio_tracks2.size()); } @@ -745,12 +742,12 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddVideoTrackFromRemoteStream) { AddRemoteMockMediaStream(remote_stream_label, "video", "video")); EXPECT_CALL(*mock_client_.get(), didAddRemoteStream( - testing::Property(&WebKit::WebMediaStream::id, + testing::Property(&blink::WebMediaStream::id, UTF8ToUTF16(remote_stream_label)))); pc_handler_->OnAddStream(remote_stream.get()); - const WebKit::WebMediaStream& webkit_stream = mock_client_->remote_stream(); + const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream(); - WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks; + blink::WebVector<blink::WebMediaStreamTrack> video_tracks; webkit_stream.videoTracks(video_tracks); EXPECT_EQ(1u, video_tracks.size()); @@ -758,13 +755,13 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddVideoTrackFromRemoteStream) { scoped_refptr<webrtc::VideoTrackInterface> webrtc_track = remote_stream->GetVideoTracks()[0].get(); remote_stream->RemoveTrack(webrtc_track.get()); - WebKit::WebVector<WebKit::WebMediaStreamTrack> modified_video_tracks1; + blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks1; webkit_stream.videoTracks(modified_video_tracks1); EXPECT_EQ(0u, modified_video_tracks1.size()); // Add the WebRtc video track again. remote_stream->AddTrack(webrtc_track.get()); - WebKit::WebVector<WebKit::WebMediaStreamTrack> modified_video_tracks2; + blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks2; webkit_stream.videoTracks(modified_video_tracks2); EXPECT_EQ(1u, modified_video_tracks2.size()); } @@ -793,24 +790,24 @@ TEST_F(RTCPeerConnectionHandlerTest, OnRenegotiationNeeded) { } TEST_F(RTCPeerConnectionHandlerTest, CreateDataChannel) { - WebKit::WebString label = "d1"; + blink::WebString label = "d1"; EXPECT_CALL(*mock_tracker_.get(), TrackCreateDataChannel(pc_handler_.get(), testing::NotNull(), PeerConnectionTracker::SOURCE_LOCAL)); - scoped_ptr<WebKit::WebRTCDataChannelHandler> channel( - pc_handler_->createDataChannel("d1", WebKit::WebRTCDataChannelInit())); + scoped_ptr<blink::WebRTCDataChannelHandler> channel( + pc_handler_->createDataChannel("d1", blink::WebRTCDataChannelInit())); EXPECT_TRUE(channel.get() != NULL); EXPECT_EQ(label, channel->label()); } TEST_F(RTCPeerConnectionHandlerTest, CreateDtmfSender) { std::string stream_label = "local_stream"; - WebKit::WebMediaStream local_stream(CreateLocalMediaStream(stream_label)); - WebKit::WebMediaConstraints constraints; + blink::WebMediaStream local_stream(CreateLocalMediaStream(stream_label)); + blink::WebMediaConstraints constraints; pc_handler_->addStream(local_stream, constraints); - WebKit::WebVector<WebKit::WebMediaStreamTrack> tracks; + blink::WebVector<blink::WebMediaStreamTrack> tracks; local_stream.videoTracks(tracks); ASSERT_LE(1ul, tracks.size()); @@ -823,7 +820,7 @@ TEST_F(RTCPeerConnectionHandlerTest, CreateDtmfSender) { TrackCreateDTMFSender(pc_handler_.get(), testing::Ref(tracks[0]))); - scoped_ptr<WebKit::WebRTCDTMFSenderHandler> sender( + scoped_ptr<blink::WebRTCDTMFSenderHandler> sender( pc_handler_->createDTMFSender(tracks[0])); EXPECT_TRUE(sender.get()); } diff --git a/chromium/content/renderer/media/rtc_video_capture_delegate.cc b/chromium/content/renderer/media/rtc_video_capture_delegate.cc index 8b038d5c75c..4cc2b59193a 100644 --- a/chromium/content/renderer/media/rtc_video_capture_delegate.cc +++ b/chromium/content/renderer/media/rtc_video_capture_delegate.cc @@ -5,6 +5,7 @@ #include "content/renderer/media/rtc_video_capture_delegate.h" #include "base/bind.h" +#include "media/base/video_frame.h" namespace content { @@ -26,7 +27,7 @@ RtcVideoCaptureDelegate::~RtcVideoCaptureDelegate() { } void RtcVideoCaptureDelegate::StartCapture( - const media::VideoCaptureCapability& capability, + const media::VideoCaptureParams& params, const FrameCapturedCallback& captured_callback, const StateChangeCallback& state_callback) { DVLOG(3) << " RtcVideoCaptureDelegate::StartCapture "; @@ -39,7 +40,7 @@ void RtcVideoCaptureDelegate::StartCapture( // Increase the reference count to ensure we are not deleted until // The we are unregistered in RtcVideoCaptureDelegate::OnRemoved. AddRef(); - capture_engine_->StartCapture(this, capability); + capture_engine_->StartCapture(this, params); } void RtcVideoCaptureDelegate::StopCapture() { @@ -92,16 +93,6 @@ void RtcVideoCaptureDelegate::OnFrameReady( frame)); } -void RtcVideoCaptureDelegate::OnDeviceInfoReceived( - media::VideoCapture* capture, - const media::VideoCaptureParams& device_info) { -} - -void RtcVideoCaptureDelegate::OnDeviceInfoChanged( - media::VideoCapture* capture, - const media::VideoCaptureParams& device_info) { -} - void RtcVideoCaptureDelegate::OnFrameReadyOnCaptureThread( media::VideoCapture* capture, const scoped_refptr<media::VideoFrame>& frame) { diff --git a/chromium/content/renderer/media/rtc_video_capture_delegate.h b/chromium/content/renderer/media/rtc_video_capture_delegate.h index 415b346c838..f081c3731b0 100644 --- a/chromium/content/renderer/media/rtc_video_capture_delegate.h +++ b/chromium/content/renderer/media/rtc_video_capture_delegate.h @@ -36,7 +36,7 @@ class RtcVideoCaptureDelegate RtcVideoCaptureDelegate(const media::VideoCaptureSessionId id, VideoCaptureImplManager* vc_manager); - void StartCapture(const media::VideoCaptureCapability& capability, + void StartCapture(const media::VideoCaptureParams& params, const FrameCapturedCallback& captured_callback, const StateChangeCallback& state_callback); void StopCapture(); @@ -51,12 +51,6 @@ class RtcVideoCaptureDelegate virtual void OnFrameReady( media::VideoCapture* capture, const scoped_refptr<media::VideoFrame>& frame) OVERRIDE; - virtual void OnDeviceInfoReceived( - media::VideoCapture* capture, - const media::VideoCaptureParams& device_info) OVERRIDE; - virtual void OnDeviceInfoChanged( - media::VideoCapture* capture, - const media::VideoCaptureParams& device_info) OVERRIDE; private: friend class base::RefCountedThreadSafe<RtcVideoCaptureDelegate>; diff --git a/chromium/content/renderer/media/rtc_video_capturer.cc b/chromium/content/renderer/media/rtc_video_capturer.cc index fec4d091e87..0a7a82cf588 100644 --- a/chromium/content/renderer/media/rtc_video_capturer.cc +++ b/chromium/content/renderer/media/rtc_video_capturer.cc @@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/debug/trace_event.h" +#include "media/base/video_frame.h" namespace content { @@ -29,24 +30,24 @@ cricket::CaptureState RtcVideoCapturer::Start( return cricket::CS_FAILED; } - media::VideoCaptureCapability cap; - cap.width = capture_format.width; - cap.height = capture_format.height; - cap.frame_rate = capture_format.framerate(); - cap.color = media::PIXEL_FORMAT_I420; + media::VideoCaptureParams request; + request.requested_format = media::VideoCaptureFormat( + gfx::Size(capture_format.width, capture_format.height), + capture_format.framerate(), + media::PIXEL_FORMAT_I420); SetCaptureFormat(&capture_format); state_ = VIDEO_CAPTURE_STATE_STARTED; first_frame_timestamp_ = media::kNoTimestamp(); delegate_->StartCapture( - cap, + request, base::Bind(&RtcVideoCapturer::OnFrameCaptured, base::Unretained(this)), base::Bind(&RtcVideoCapturer::OnStateChange, base::Unretained(this))); // Update the desired aspect ratio so that later the video frame can be // cropped to meet the requirement if the camera returns a different - // resolution than the |cap|. - UpdateAspectRatio(cap.width, cap.height); + // resolution than the |request|. + UpdateAspectRatio(capture_format.width, capture_format.height); return cricket::CS_STARTING; } diff --git a/chromium/content/renderer/media/rtc_video_decoder.cc b/chromium/content/renderer/media/rtc_video_decoder.cc index 70f8add2d00..1c8d6008bca 100644 --- a/chromium/content/renderer/media/rtc_video_decoder.cc +++ b/chromium/content/renderer/media/rtc_video_decoder.cc @@ -73,9 +73,7 @@ RTCVideoDecoder::BufferData::~BufferData() {} RTCVideoDecoder::RTCVideoDecoder( const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories) - : weak_factory_(this), - weak_this_(weak_factory_.GetWeakPtr()), - factories_(factories), + : factories_(factories), vda_loop_proxy_(factories->GetMessageLoop()), decoder_texture_target_(0), next_picture_buffer_id_(0), @@ -83,8 +81,12 @@ RTCVideoDecoder::RTCVideoDecoder( decode_complete_callback_(NULL), num_shm_buffers_(0), next_bitstream_buffer_id_(0), - reset_bitstream_buffer_id_(ID_INVALID) { + reset_bitstream_buffer_id_(ID_INVALID), + weak_factory_(this) { DCHECK(!vda_loop_proxy_->BelongsToCurrentThread()); + + weak_this_ = weak_factory_.GetWeakPtr(); + base::WaitableEvent message_loop_async_waiter(false, false); // Waiting here is safe. The media thread is stopped in the child thread and // the child thread is blocked when VideoDecoderFactory::CreateVideoDecoder @@ -184,24 +186,44 @@ int32_t RTCVideoDecoder::Decode( DVLOG(3) << "Decode"; base::AutoLock auto_lock(lock_); + if (state_ == UNINITIALIZED || decode_complete_callback_ == NULL) { LOG(ERROR) << "The decoder has not initialized."; return WEBRTC_VIDEO_CODEC_UNINITIALIZED; } + if (state_ == DECODE_ERROR) { LOG(ERROR) << "Decoding error occurred."; return WEBRTC_VIDEO_CODEC_ERROR; } + if (missingFrames || !inputImage._completeFrame) { DLOG(ERROR) << "Missing or incomplete frames."; // Unlike the SW decoder in libvpx, hw decoder cannot handle broken frames. // Return an error to request a key frame. return WEBRTC_VIDEO_CODEC_ERROR; } + + // Most platforms' VDA implementations support mid-stream resolution change + // internally. Platforms whose VDAs fail to support mid-stream resolution + // change gracefully need to have their clients cover for them, and we do that + // here. +#ifdef ANDROID + const bool kVDACanHandleMidstreamResize = false; +#else + const bool kVDACanHandleMidstreamResize = true; +#endif + + bool need_to_reset_for_midstream_resize = false; if (inputImage._frameType == webrtc::kKeyFrame) { DVLOG(2) << "Got key frame. size=" << inputImage._encodedWidth << "x" << inputImage._encodedHeight; + gfx::Size prev_frame_size = frame_size_; frame_size_.SetSize(inputImage._encodedWidth, inputImage._encodedHeight); + if (!kVDACanHandleMidstreamResize && !prev_frame_size.IsEmpty() && + prev_frame_size != frame_size_) { + need_to_reset_for_midstream_resize = true; + } } else if (IsFirstBufferAfterReset(next_bitstream_buffer_id_, reset_bitstream_buffer_id_)) { // TODO(wuchengli): VDA should handle it. Remove this when @@ -219,15 +241,20 @@ int32_t RTCVideoDecoder::Decode( // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & ID_LAST; - // If the shared memory is available and there are no pending buffers, send - // the buffer for decode. If not, save the buffer in the queue for decode - // later. + // If a shared memory segment is available, there are no pending buffers, and + // this isn't a mid-stream resolution change, then send the buffer for decode + // immediately. Otherwise, save the buffer in the queue for later decode. scoped_ptr<SHMBuffer> shm_buffer; - if (pending_buffers_.size() == 0) + if (!need_to_reset_for_midstream_resize && pending_buffers_.size() == 0) shm_buffer = GetSHM_Locked(inputImage._length); if (!shm_buffer) { - int32_t result = SaveToPendingBuffers_Locked(inputImage, buffer_data); - return result ? WEBRTC_VIDEO_CODEC_OK : WEBRTC_VIDEO_CODEC_ERROR; + if (!SaveToPendingBuffers_Locked(inputImage, buffer_data)) + return WEBRTC_VIDEO_CODEC_ERROR; + if (need_to_reset_for_midstream_resize) { + base::AutoUnlock auto_unlock(lock_); + Reset(); + } + return WEBRTC_VIDEO_CODEC_OK; } SaveToDecodeBuffers_Locked(inputImage, shm_buffer.Pass(), buffer_data); @@ -394,13 +421,13 @@ scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame( base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue( base::checked_numeric_cast<uint64_t>(timestamp) * 1000 / 90); return media::VideoFrame::WrapNativeTexture( - new media::VideoFrame::MailboxHolder( + make_scoped_ptr(new media::VideoFrame::MailboxHolder( pb.texture_mailbox(), 0, // sync_point media::BindToCurrentLoop( base::Bind(&RTCVideoDecoder::ReusePictureBuffer, weak_this_, - picture.picture_buffer_id()))), + picture.picture_buffer_id())))), decoder_texture_target_, pb.size(), visible_rect, @@ -409,7 +436,6 @@ scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame( base::Bind(&media::GpuVideoAcceleratorFactories::ReadPixels, factories_, pb.texture_id(), - decoder_texture_target_, natural_size), base::Closure()); } @@ -755,7 +781,7 @@ int32_t RTCVideoDecoder::RecordInitDecodeUMA(int32_t status) { // Logging boolean is enough to know if HW decoding has been used. Also, // InitDecode is less likely to return an error so enum is not used here. bool sample = (status == WEBRTC_VIDEO_CODEC_OK) ? true : false; - UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeStatus", sample); + UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoDecoderInitDecodeSuccess", sample); return status; } diff --git a/chromium/content/renderer/media/rtc_video_decoder.h b/chromium/content/renderer/media/rtc_video_decoder.h index d73fc143d1b..b0f967ab546 100644 --- a/chromium/content/renderer/media/rtc_video_decoder.h +++ b/chromium/content/renderer/media/rtc_video_decoder.h @@ -201,8 +201,7 @@ class CONTENT_EXPORT RTCVideoDecoder // The size of the incoming video frames. gfx::Size frame_size_; - // The weak pointer should live and die on the |vda_loop_proxy_|; - base::WeakPtrFactory<RTCVideoDecoder> weak_factory_; + // Weak pointer to this, which can be dereferenced only on |vda_loop_proxy_|. base::WeakPtr<RTCVideoDecoder> weak_this_; scoped_refptr<media::GpuVideoAcceleratorFactories> factories_; @@ -269,6 +268,10 @@ class CONTENT_EXPORT RTCVideoDecoder // Release has been called. Guarded by |lock_|. int32 reset_bitstream_buffer_id_; + // Factory used to populate |weak_this_|. Must be destroyed, or invalidated, + // on |vda_loop_proxy_|. + base::WeakPtrFactory<RTCVideoDecoder> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoder); }; diff --git a/chromium/content/renderer/media/rtc_video_decoder_factory_tv.cc b/chromium/content/renderer/media/rtc_video_decoder_factory_tv.cc index 58db5c383fe..64c14adf313 100644 --- a/chromium/content/renderer/media/rtc_video_decoder_factory_tv.cc +++ b/chromium/content/renderer/media/rtc_video_decoder_factory_tv.cc @@ -193,14 +193,29 @@ void RTCVideoDecoderFactoryTv::ReleaseDemuxer() { } } -void RTCVideoDecoderFactoryTv::Initialize(media::DemuxerHost*, - const media::PipelineStatusCB& cb) { +void RTCVideoDecoderFactoryTv::Initialize(media::DemuxerHost* /*host*/, + const media::PipelineStatusCB& cb, + bool /*enable_text_tracks*/) { base::AutoLock lock(lock_); init_cb_ = media::BindToLoop(base::MessageLoopProxy::current(), cb); if (stream_) base::ResetAndReturn(&init_cb_).Run(media::PIPELINE_OK); } +void RTCVideoDecoderFactoryTv::Seek(base::TimeDelta time, + const media::PipelineStatusCB& status_cb) { + DCHECK(!status_cb.is_null()); + status_cb.Run(media::PIPELINE_OK); +} + +void RTCVideoDecoderFactoryTv::Stop(const base::Closure& callback) { + DCHECK(!callback.is_null()); + callback.Run(); +} + +void RTCVideoDecoderFactoryTv::OnAudioRendererDisabled() { +} + DemuxerStream* RTCVideoDecoderFactoryTv::GetStream(DemuxerStream::Type type) { base::AutoLock lock(lock_); if (type == DemuxerStream::VIDEO) diff --git a/chromium/content/renderer/media/rtc_video_decoder_factory_tv.h b/chromium/content/renderer/media/rtc_video_decoder_factory_tv.h index 0d5380bc65a..cd51cdcf862 100644 --- a/chromium/content/renderer/media/rtc_video_decoder_factory_tv.h +++ b/chromium/content/renderer/media/rtc_video_decoder_factory_tv.h @@ -47,7 +47,12 @@ class CONTENT_EXPORT RTCVideoDecoderFactoryTv // media::Demuxer implementation. virtual void Initialize(media::DemuxerHost* host, - const media::PipelineStatusCB& cb) OVERRIDE; + const media::PipelineStatusCB& cb, + bool enable_text_tracks) OVERRIDE; + virtual void Seek(base::TimeDelta time, + const media::PipelineStatusCB& status_cb) OVERRIDE; + virtual void Stop(const base::Closure& callback) OVERRIDE; + virtual void OnAudioRendererDisabled() OVERRIDE; virtual media::DemuxerStream* GetStream( media::DemuxerStream::Type type) OVERRIDE; virtual base::TimeDelta GetStartTime() const OVERRIDE; diff --git a/chromium/content/renderer/media/rtc_video_encoder.cc b/chromium/content/renderer/media/rtc_video_encoder.cc index 1ab56c930be..4b54db2342d 100644 --- a/chromium/content/renderer/media/rtc_video_encoder.cc +++ b/chromium/content/renderer/media/rtc_video_encoder.cc @@ -9,6 +9,7 @@ #include "base/logging.h" #include "base/memory/scoped_vector.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/metrics/histogram.h" #include "base/synchronization/waitable_event.h" #include "content/renderer/media/renderer_gpu_video_accelerator_factories.h" #include "media/base/bitstream_buffer.h" @@ -395,7 +396,7 @@ void RTCVideoEncoder::Impl::EncodeOneFrame() { const int index = input_buffers_free_.back(); base::SharedMemory* input_buffer = input_buffers_[index]; scoped_refptr<media::VideoFrame> frame = - media::VideoFrame::WrapExternalSharedMemory( + media::VideoFrame::WrapExternalPackedMemory( media::VideoFrame::I420, input_frame_coded_size_, gfx::Rect(input_visible_size_), @@ -474,9 +475,9 @@ RTCVideoEncoder::RTCVideoEncoder( : video_codec_type_(type), video_codec_profile_(profile), gpu_factories_(gpu_factories), - weak_this_factory_(this), encoded_image_callback_(NULL), - impl_status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED) { + impl_status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED), + weak_this_factory_(this) { DVLOG(1) << "RTCVideoEncoder(): profile=" << profile; } @@ -512,6 +513,7 @@ int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings, // webrtc::VideoEncoder expects this call to be synchronous. initialization_waiter.Wait(); + RecordInitEncodeUMA(initialization_retval); return initialization_retval; } @@ -612,6 +614,11 @@ void RTCVideoEncoder::ReturnEncodedImage(scoped_ptr<webrtc::EncodedImage> image, webrtc::CodecSpecificInfo info; memset(&info, 0, sizeof(info)); info.codecType = video_codec_type_; + if (video_codec_type_ == webrtc::kVideoCodecVP8) { + info.codecSpecific.VP8.pictureId = -1; + info.codecSpecific.VP8.tl0PicIdx = -1; + info.codecSpecific.VP8.keyIdx = -1; + } // Generate a header describing a single fragment. webrtc::RTPFragmentationHeader header; @@ -647,4 +654,14 @@ void RTCVideoEncoder::NotifyError(int32_t error) { impl_ = NULL; } +void RTCVideoEncoder::RecordInitEncodeUMA(int32_t init_retval) { + UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess", + init_retval == WEBRTC_VIDEO_CODEC_OK); + if (init_retval == WEBRTC_VIDEO_CODEC_OK) { + UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile", + video_codec_profile_, + media::VIDEO_CODEC_PROFILE_MAX); + } +} + } // namespace content diff --git a/chromium/content/renderer/media/rtc_video_encoder.h b/chromium/content/renderer/media/rtc_video_encoder.h index 3c15a55ce73..4e36ece1c1d 100644 --- a/chromium/content/renderer/media/rtc_video_encoder.h +++ b/chromium/content/renderer/media/rtc_video_encoder.h @@ -69,6 +69,8 @@ class CONTENT_EXPORT RTCVideoEncoder void NotifyError(int32_t error); + void RecordInitEncodeUMA(int32_t init_retval); + base::ThreadChecker thread_checker_; // The video codec type, as reported to WebRTC. @@ -80,10 +82,6 @@ class CONTENT_EXPORT RTCVideoEncoder // Factory for creating VEAs, shared memory buffers, etc. scoped_refptr<RendererGpuVideoAcceleratorFactories> gpu_factories_; - // Weak pointer factory for posting back VEA::Client notifications to - // RTCVideoEncoder. - base::WeakPtrFactory<RTCVideoEncoder> weak_this_factory_; - // webrtc::VideoEncoder encode complete callback. webrtc::EncodedImageCallback* encoded_image_callback_; @@ -96,6 +94,10 @@ class CONTENT_EXPORT RTCVideoEncoder // interface entry point is called. int32_t impl_status_; + // Weak pointer factory for posting back VEA::Client notifications to + // RTCVideoEncoder. + base::WeakPtrFactory<RTCVideoEncoder> weak_this_factory_; + DISALLOW_COPY_AND_ASSIGN(RTCVideoEncoder); }; diff --git a/chromium/content/renderer/media/rtc_video_renderer.cc b/chromium/content/renderer/media/rtc_video_renderer.cc index f64ed02fed2..013fcad8dfb 100644 --- a/chromium/content/renderer/media/rtc_video_renderer.cc +++ b/chromium/content/renderer/media/rtc_video_renderer.cc @@ -4,30 +4,22 @@ #include "content/renderer/media/rtc_video_renderer.h" -#include "base/bind.h" #include "base/debug/trace_event.h" -#include "base/location.h" -#include "base/logging.h" #include "base/message_loop/message_loop_proxy.h" -#include "content/renderer/media/native_handle_impl.h" #include "media/base/video_frame.h" #include "media/base/video_util.h" -#include "third_party/libjingle/source/talk/media/base/videoframe.h" - -using media::CopyYPlane; -using media::CopyUPlane; -using media::CopyVPlane; namespace content { RTCVideoRenderer::RTCVideoRenderer( - webrtc::VideoTrackInterface* video_track, + const blink::WebMediaStreamTrack& video_track, const base::Closure& error_cb, const RepaintCB& repaint_cb) : error_cb_(error_cb), repaint_cb_(repaint_cb), message_loop_proxy_(base::MessageLoopProxy::current()), - state_(kStopped), + state_(STOPPED), + first_frame_rendered_(false), video_track_(video_track) { } @@ -36,113 +28,82 @@ RTCVideoRenderer::~RTCVideoRenderer() { void RTCVideoRenderer::Start() { DCHECK(message_loop_proxy_->BelongsToCurrentThread()); - DCHECK_EQ(state_, kStopped); + DCHECK_EQ(state_, STOPPED); + DCHECK(!first_frame_rendered_); + + AddToVideoTrack(this, video_track_); + state_ = STARTED; - if (video_track_.get()) { - video_track_->AddRenderer(this); - video_track_->RegisterObserver(this); + if (video_track_.source().readyState() == + blink::WebMediaStreamSource::ReadyStateEnded || + !video_track_.isEnabled()) { + MaybeRenderSignalingFrame(); } - state_ = kStarted; - MaybeRenderSignalingFrame(); } void RTCVideoRenderer::Stop() { DCHECK(message_loop_proxy_->BelongsToCurrentThread()); - if (video_track_.get()) { - state_ = kStopped; - video_track_->RemoveRenderer(this); - video_track_->UnregisterObserver(this); - video_track_ = NULL; - } + DCHECK(state_ == STARTED || state_ == PAUSED); + RemoveFromVideoTrack(this, video_track_); + state_ = STOPPED; + first_frame_rendered_ = false; } void RTCVideoRenderer::Play() { DCHECK(message_loop_proxy_->BelongsToCurrentThread()); - if (video_track_.get() && state_ == kPaused) { - state_ = kStarted; + if (state_ == PAUSED) { + state_ = STARTED; } } void RTCVideoRenderer::Pause() { DCHECK(message_loop_proxy_->BelongsToCurrentThread()); - if (video_track_.get() && state_ == kStarted) { - state_ = kPaused; + if (state_ == STARTED) { + state_ = PAUSED; } } -void RTCVideoRenderer::SetSize(int width, int height) { +void RTCVideoRenderer::OnReadyStateChanged( + blink::WebMediaStreamSource::ReadyState state) { + DCHECK(message_loop_proxy_->BelongsToCurrentThread()); + if (state == blink::WebMediaStreamSource::ReadyStateEnded) + MaybeRenderSignalingFrame(); } -void RTCVideoRenderer::RenderFrame(const cricket::VideoFrame* frame) { - base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds( - frame->GetTimeStamp() / talk_base::kNumNanosecsPerMillisec); - - TRACE_EVENT_INSTANT2("rtc_video_renderer", - "RenderFrame", - TRACE_EVENT_SCOPE_THREAD, - "elapsed time", - frame->GetElapsedTime(), - "timestamp_ms", - timestamp.InMilliseconds()); - - scoped_refptr<media::VideoFrame> video_frame; - if (frame->GetNativeHandle() != NULL) { - NativeHandleImpl* handle = - static_cast<NativeHandleImpl*>(frame->GetNativeHandle()); - video_frame = static_cast<media::VideoFrame*>(handle->GetHandle()); - video_frame->SetTimestamp(timestamp); - } else { - gfx::Size size(frame->GetWidth(), frame->GetHeight()); - video_frame = media::VideoFrame::CreateFrame( - media::VideoFrame::YV12, size, gfx::Rect(size), size, timestamp); - - // Aspect ratio unsupported; DCHECK when there are non-square pixels. - DCHECK_EQ(frame->GetPixelWidth(), 1u); - DCHECK_EQ(frame->GetPixelHeight(), 1u); - - int y_rows = frame->GetHeight(); - int uv_rows = frame->GetHeight() / 2; // YV12 format. - CopyYPlane( - frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame.get()); - CopyUPlane( - frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame.get()); - CopyVPlane( - frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame.get()); - } - - message_loop_proxy_->PostTask( - FROM_HERE, base::Bind(&RTCVideoRenderer::DoRenderFrameOnMainThread, - this, video_frame)); +void RTCVideoRenderer::OnEnabledChanged(bool enabled) { + DCHECK(message_loop_proxy_->BelongsToCurrentThread()); + if (!enabled) + MaybeRenderSignalingFrame(); } -void RTCVideoRenderer::OnChanged() { +void RTCVideoRenderer::OnVideoFrame( + const scoped_refptr<media::VideoFrame>& frame) { DCHECK(message_loop_proxy_->BelongsToCurrentThread()); - MaybeRenderSignalingFrame(); + if (state_ != STARTED) { + return; + } + + TRACE_EVENT_INSTANT1("rtc_video_renderer", + "OnVideoFrame", + TRACE_EVENT_SCOPE_THREAD, + "timestamp", + frame->GetTimestamp().InMilliseconds()); + repaint_cb_.Run(frame); + first_frame_rendered_ = true; } void RTCVideoRenderer::MaybeRenderSignalingFrame() { - // Render a small black frame if the track transition to ended. + // Render a small black frame if no frame has been rendered. // This is necessary to make sure audio can play if the video tag src is - // a MediaStream video track that has been rejected or ended. - if (video_track_->state() == webrtc::MediaStreamTrackInterface::kEnded) { - const int kMinFrameSize = 2; - const gfx::Size size(kMinFrameSize, kMinFrameSize); - scoped_refptr<media::VideoFrame> video_frame = - media::VideoFrame::CreateBlackFrame(size); - DoRenderFrameOnMainThread(video_frame); - } -} - -void RTCVideoRenderer::DoRenderFrameOnMainThread( - scoped_refptr<media::VideoFrame> video_frame) { - DCHECK(message_loop_proxy_->BelongsToCurrentThread()); - - if (state_ != kStarted) { + // a MediaStream video track that has been rejected, ended or disabled. + if (first_frame_rendered_) return; - } - TRACE_EVENT0("video", "DoRenderFrameOnMainThread"); - repaint_cb_.Run(video_frame); + const int kMinFrameSize = 2; + const gfx::Size size(kMinFrameSize, kMinFrameSize); + scoped_refptr<media::VideoFrame> video_frame = + media::VideoFrame::CreateBlackFrame(size); + OnVideoFrame(video_frame); } } // namespace content diff --git a/chromium/content/renderer/media/rtc_video_renderer.h b/chromium/content/renderer/media/rtc_video_renderer.h index d7bb9869dab..b72a5860ee8 100644 --- a/chromium/content/renderer/media/rtc_video_renderer.h +++ b/chromium/content/renderer/media/rtc_video_renderer.h @@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_MEDIA_LOCAL_VIDEO_RENDERER_H_ -#define CONTENT_RENDERER_MEDIA_LOCAL_VIDEO_RENDERER_H_ +#ifndef CONTENT_RENDERER_MEDIA_RTC_VIDEO_RENDERER_H_ +#define CONTENT_RENDERER_MEDIA_RTC_VIDEO_RENDERER_H_ #include "base/callback.h" #include "content/common/content_export.h" +#include "content/public/renderer/media_stream_video_sink.h" #include "content/renderer/media/video_frame_provider.h" -#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" +#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" #include "ui/gfx/size.h" namespace base { @@ -20,23 +21,20 @@ namespace content { // RTCVideoRenderer is a VideoFrameProvider designed for rendering // Video MediaStreamTracks, // http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediastreamtrack -// RTCVideoRenderer implements webrtc::VideoRendererInterface in order to render -// video frames provided from a webrtc::VideoTrackInteface. -// RTCVideoRenderer register itself to the Video Track when the +// RTCVideoRenderer implements VideoTrackSink in order to render +// video frames provided from a VideoTrack. +// RTCVideoRenderer register itself as a sink to the VideoTrack when the // VideoFrameProvider is started and deregisters itself when it is stopped. -// Calls to webrtc::VideoTrackInterface must occur on the main thread. // TODO(wuchengli): Add unit test. See the link below for reference. // http://src.chromium.org/viewvc/chrome/trunk/src/content/renderer/media/rtc_vi // deo_decoder_unittest.cc?revision=180591&view=markup class CONTENT_EXPORT RTCVideoRenderer : NON_EXPORTED_BASE(public VideoFrameProvider), - NON_EXPORTED_BASE(public webrtc::VideoRendererInterface), - NON_EXPORTED_BASE(public webrtc::ObserverInterface) { + NON_EXPORTED_BASE(public MediaStreamVideoSink) { public: - RTCVideoRenderer( - webrtc::VideoTrackInterface* video_track, - const base::Closure& error_cb, - const RepaintCB& repaint_cb); + RTCVideoRenderer(const blink::WebMediaStreamTrack& video_track, + const base::Closure& error_cb, + const RepaintCB& repaint_cb); // VideoFrameProvider implementation. Called on the main thread. virtual void Start() OVERRIDE; @@ -44,38 +42,35 @@ class CONTENT_EXPORT RTCVideoRenderer virtual void Play() OVERRIDE; virtual void Pause() OVERRIDE; - // webrtc::VideoRendererInterface implementation. May be called on - // a different thread. - virtual void SetSize(int width, int height) OVERRIDE; - virtual void RenderFrame(const cricket::VideoFrame* frame) OVERRIDE; - - // webrtc::ObserverInterface implementation. - virtual void OnChanged() OVERRIDE; - protected: virtual ~RTCVideoRenderer(); private: enum State { - kStarted, - kPaused, - kStopped, + STARTED, + PAUSED, + STOPPED, }; + // VideoTrackSink implementation. Called on the main thread. + virtual void OnVideoFrame( + const scoped_refptr<media::VideoFrame>& frame) OVERRIDE; + virtual void OnReadyStateChanged( + blink::WebMediaStreamSource::ReadyState state) OVERRIDE; + virtual void OnEnabledChanged(bool enabled) OVERRIDE; + void MaybeRenderSignalingFrame(); - void DoRenderFrameOnMainThread(scoped_refptr<media::VideoFrame> video_frame); base::Closure error_cb_; RepaintCB repaint_cb_; scoped_refptr<base::MessageLoopProxy> message_loop_proxy_; State state_; - - // The video track the renderer is connected to. - scoped_refptr<webrtc::VideoTrackInterface> video_track_; + bool first_frame_rendered_; + blink::WebMediaStreamTrack video_track_; DISALLOW_COPY_AND_ASSIGN(RTCVideoRenderer); }; } // namespace content -#endif // CONTENT_RENDERER_MEDIA_LOCAL_VIDEO_RENDERER_H_ +#endif // CONTENT_RENDERER_MEDIA_RTC_VIDEO_RENDERER_H_ diff --git a/chromium/content/renderer/media/tagged_list.h b/chromium/content/renderer/media/tagged_list.h new file mode 100644 index 00000000000..450f9f69e98 --- /dev/null +++ b/chromium/content/renderer/media/tagged_list.h @@ -0,0 +1,94 @@ +// 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_RENDERER_MEDIA_TAGGED_LIST_H_ +#define CONTENT_RENDERER_MEDIA_TAGGED_LIST_H_ + +#include <algorithm> +#include <list> + +#include "base/logging.h" +#include "base/memory/ref_counted.h" + +namespace content { + +// Implements the pattern of a list of items, where added items are +// tagged, you can tag all items, and you can retrieve the list of +// items that are tagged, which removes the tag. +// +// For thread safety, operations on this object should be under an +// external lock. An internally-locked version could be created, but +// is not needed at the moment as users already lock. +template <class ItemType> +class TaggedList { + public: + typedef std::list<scoped_refptr<ItemType> > ItemList; + + TaggedList() {} + + void AddAndTag(ItemType* item) { + items_.push_back(item); + tagged_items_.push_back(item); + } + + void TagAll() { + tagged_items_ = items_; + } + + const ItemList& Items() const { + return items_; + } + + // Retrieves the list of items with tags, and removes their tags. + // + // |dest| should be empty. + void RetrieveAndClearTags(ItemList* dest) { + DCHECK(dest->empty()); + dest->swap(tagged_items_); + } + + // Remove an item that matches a predicate. Will return a reference + // to it if it is found. + template <class UnaryPredicate> + scoped_refptr<ItemType> Remove(UnaryPredicate predicate) { + tagged_items_.remove_if(predicate); + + typename ItemList::iterator it = std::find_if( + items_.begin(), items_.end(), predicate); + if (it != items_.end()) { + scoped_refptr<ItemType> removed_item = *it; + items_.erase(it); + return removed_item; + } + + return NULL; + } + + template <class UnaryPredicate> + bool Contains(UnaryPredicate predicate) const { + return std::find_if(items_.begin(), items_.end(), predicate) != + items_.end(); + } + + void Clear() { + items_.clear(); + tagged_items_.clear(); + } + + bool IsEmpty() const { + bool is_empty = items_.empty(); + DCHECK(!is_empty || tagged_items_.empty()); + return is_empty; + } + + private: + ItemList items_; + ItemList tagged_items_; + + DISALLOW_COPY_AND_ASSIGN(TaggedList); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_TAGGED_LIST_H_ diff --git a/chromium/content/renderer/media/test_response_generator.cc b/chromium/content/renderer/media/test_response_generator.cc index 1ced1313db6..64f82e78f50 100644 --- a/chromium/content/renderer/media/test_response_generator.cc +++ b/chromium/content/renderer/media/test_response_generator.cc @@ -11,9 +11,9 @@ #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURLResponse.h" -using WebKit::WebString; -using WebKit::WebURLError; -using WebKit::WebURLResponse; +using blink::WebString; +using blink::WebURLError; +using blink::WebURLResponse; namespace content { diff --git a/chromium/content/renderer/media/test_response_generator.h b/chromium/content/renderer/media/test_response_generator.h index d8f1d5e1322..dcbcc0544e4 100644 --- a/chromium/content/renderer/media/test_response_generator.h +++ b/chromium/content/renderer/media/test_response_generator.h @@ -28,29 +28,29 @@ class TestResponseGenerator { TestResponseGenerator(const GURL& gurl, int64 content_length); // Generates a WebURLError object. - WebKit::WebURLError GenerateError(); + blink::WebURLError GenerateError(); // Generates a regular HTTP 200 response. - WebKit::WebURLResponse Generate200(); + blink::WebURLResponse Generate200(); // Generates a regular HTTP 206 response starting from |first_byte_offset| // until the end of the resource. - WebKit::WebURLResponse Generate206(int64 first_byte_offset); + blink::WebURLResponse Generate206(int64 first_byte_offset); // Generates a custom HTTP 206 response starting from |first_byte_offset| // until the end of the resource. You can tweak what gets included in the // headers via |flags|. - WebKit::WebURLResponse Generate206(int64 first_byte_offset, Flags flags); + blink::WebURLResponse Generate206(int64 first_byte_offset, Flags flags); // Generates a regular HTTP 404 response. - WebKit::WebURLResponse Generate404(); + blink::WebURLResponse Generate404(); // Generates a file:// response starting from |first_byte_offset| until the // end of the resource. // // If |first_byte_offset| is negative a response containing no content length // will be returned. - WebKit::WebURLResponse GenerateFileResponse(int64 first_byte_offset); + blink::WebURLResponse GenerateFileResponse(int64 first_byte_offset); int64 content_length() { return content_length_; } diff --git a/chromium/content/renderer/media/texttrack_impl.cc b/chromium/content/renderer/media/texttrack_impl.cc index 7acf39a1a48..3df473b593a 100644 --- a/chromium/content/renderer/media/texttrack_impl.cc +++ b/chromium/content/renderer/media/texttrack_impl.cc @@ -4,21 +4,32 @@ #include "content/renderer/media/texttrack_impl.h" +#include "base/bind.h" +#include "base/location.h" +#include "base/message_loop/message_loop_proxy.h" #include "content/renderer/media/webinbandtexttrack_impl.h" -#include "third_party/WebKit/public/web/WebInbandTextTrackClient.h" -#include "third_party/WebKit/public/web/WebMediaPlayerClient.h" +#include "media/base/bind_to_loop.h" +#include "third_party/WebKit/public/platform/WebInbandTextTrackClient.h" +#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" namespace content { -TextTrackImpl::TextTrackImpl(WebKit::WebMediaPlayerClient* client, - WebInbandTextTrackImpl* text_track) - : client_(client), text_track_(text_track) { +TextTrackImpl::TextTrackImpl( + const scoped_refptr<base::MessageLoopProxy>& message_loop, + blink::WebMediaPlayerClient* client, + scoped_ptr<WebInbandTextTrackImpl> text_track) + : message_loop_(message_loop), + client_(client), + text_track_(text_track.Pass()) { client_->addTextTrack(text_track_.get()); } TextTrackImpl::~TextTrackImpl() { - if (text_track_->client()) - client_->removeTextTrack(text_track_.get()); + message_loop_->PostTask( + FROM_HERE, + base::Bind(&TextTrackImpl::OnRemoveTrack, + client_, + base::Passed(&text_track_))); } void TextTrackImpl::addWebVTTCue(const base::TimeDelta& start, @@ -26,12 +37,34 @@ void TextTrackImpl::addWebVTTCue(const base::TimeDelta& start, const std::string& id, const std::string& content, const std::string& settings) { - if (WebKit::WebInbandTextTrackClient* client = text_track_->client()) + message_loop_->PostTask( + FROM_HERE, + base::Bind(&TextTrackImpl::OnAddCue, + text_track_.get(), + start, end, + id, content, settings)); +} + +void TextTrackImpl::OnAddCue(WebInbandTextTrackImpl* text_track, + const base::TimeDelta& start, + const base::TimeDelta& end, + const std::string& id, + const std::string& content, + const std::string& settings) { + if (blink::WebInbandTextTrackClient* client = text_track->client()) { client->addWebVTTCue(start.InSecondsF(), end.InSecondsF(), - WebKit::WebString::fromUTF8(id), - WebKit::WebString::fromUTF8(content), - WebKit::WebString::fromUTF8(settings)); + blink::WebString::fromUTF8(id), + blink::WebString::fromUTF8(content), + blink::WebString::fromUTF8(settings)); + } +} + +void TextTrackImpl::OnRemoveTrack( + blink::WebMediaPlayerClient* client, + scoped_ptr<WebInbandTextTrackImpl> text_track) { + if (text_track->client()) + client->removeTextTrack(text_track.get()); } } // namespace content diff --git a/chromium/content/renderer/media/texttrack_impl.h b/chromium/content/renderer/media/texttrack_impl.h index 09007c6b17a..3285b60ed10 100644 --- a/chromium/content/renderer/media/texttrack_impl.h +++ b/chromium/content/renderer/media/texttrack_impl.h @@ -11,7 +11,12 @@ #include "base/memory/scoped_ptr.h" #include "media/base/text_track.h" -namespace WebKit { +namespace base { +class MessageLoopProxy; +} + +namespace blink { +class WebInbandTextTrackClient; class WebMediaPlayerClient; } @@ -22,8 +27,9 @@ class WebInbandTextTrackImpl; class TextTrackImpl : public media::TextTrack { public: // Constructor assumes ownership of the |text_track| object. - TextTrackImpl(WebKit::WebMediaPlayerClient* client, - WebInbandTextTrackImpl* text_track); + TextTrackImpl(const scoped_refptr<base::MessageLoopProxy>& message_loop, + blink::WebMediaPlayerClient* client, + scoped_ptr<WebInbandTextTrackImpl> text_track); virtual ~TextTrackImpl(); @@ -34,7 +40,18 @@ class TextTrackImpl : public media::TextTrack { const std::string& settings) OVERRIDE; private: - WebKit::WebMediaPlayerClient* client_; + static void OnAddCue(WebInbandTextTrackImpl* text_track, + const base::TimeDelta& start, + const base::TimeDelta& end, + const std::string& id, + const std::string& content, + const std::string& settings); + + static void OnRemoveTrack(blink::WebMediaPlayerClient* client, + scoped_ptr<WebInbandTextTrackImpl> text_track); + + scoped_refptr<base::MessageLoopProxy> message_loop_; + blink::WebMediaPlayerClient* client_; scoped_ptr<WebInbandTextTrackImpl> text_track_; DISALLOW_COPY_AND_ASSIGN(TextTrackImpl); }; diff --git a/chromium/content/renderer/media/video_capture_impl.cc b/chromium/content/renderer/media/video_capture_impl.cc index 0fe2789b17f..30b43ddfcf4 100644 --- a/chromium/content/renderer/media/video_capture_impl.cc +++ b/chromium/content/renderer/media/video_capture_impl.cc @@ -10,6 +10,7 @@ #include "content/common/media/video_capture_messages.h" #include "media/base/bind_to_loop.h" #include "media/base/limits.h" +#include "media/base/video_frame.h" namespace content { @@ -17,20 +18,11 @@ class VideoCaptureImpl::ClientBuffer : public base::RefCountedThreadSafe<ClientBuffer> { public: ClientBuffer(scoped_ptr<base::SharedMemory> buffer, - size_t buffer_size, - int frame_width, - int frame_height, - int frame_stride) + size_t buffer_size) : buffer(buffer.Pass()), - buffer_size(buffer_size), - frame_width(frame_width), - frame_height(frame_height), - frame_stride(frame_stride) {} + buffer_size(buffer_size) {} const scoped_ptr<base::SharedMemory> buffer; const size_t buffer_size; - const int frame_width; // In pixels. - const int frame_height; // In pixels. - const int frame_stride; // In pixels. private: friend class base::RefCountedThreadSafe<ClientBuffer>; @@ -44,20 +36,12 @@ bool VideoCaptureImpl::CaptureStarted() { return state_ == VIDEO_CAPTURE_STATE_STARTED; } -int VideoCaptureImpl::CaptureWidth() { - return capture_format_.width; -} - -int VideoCaptureImpl::CaptureHeight() { - return capture_format_.height; -} - int VideoCaptureImpl::CaptureFrameRate() { - return capture_format_.frame_rate; + return last_frame_format_.frame_rate; } VideoCaptureImpl::VideoCaptureImpl( - const media::VideoCaptureSessionId id, + const media::VideoCaptureSessionId session_id, base::MessageLoopProxy* capture_message_loop_proxy, VideoCaptureMessageFilter* filter) : VideoCapture(), @@ -65,13 +49,11 @@ VideoCaptureImpl::VideoCaptureImpl( capture_message_loop_proxy_(capture_message_loop_proxy), io_message_loop_proxy_(ChildProcess::current()->io_message_loop_proxy()), device_id_(0), - client_buffer_weak_this_factory_(this), - video_type_(media::PIXEL_FORMAT_I420), - device_info_available_(false), + session_id_(session_id), suspended_(false), - state_(VIDEO_CAPTURE_STATE_STOPPED) { + state_(VIDEO_CAPTURE_STATE_STOPPED), + weak_this_factory_(this) { DCHECK(filter); - capture_format_.session_id = id; } VideoCaptureImpl::~VideoCaptureImpl() {} @@ -94,12 +76,10 @@ void VideoCaptureImpl::DeInit(base::Closure task) { void VideoCaptureImpl::StartCapture( media::VideoCapture::EventHandler* handler, - const media::VideoCaptureCapability& capability) { - DCHECK_EQ(capability.color, media::PIXEL_FORMAT_I420); - + const media::VideoCaptureParams& params) { capture_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(&VideoCaptureImpl::DoStartCaptureOnCaptureThread, - base::Unretained(this), handler, capability)); + base::Unretained(this), handler, params)); } void VideoCaptureImpl::StopCapture(media::VideoCapture::EventHandler* handler) { @@ -116,10 +96,19 @@ void VideoCaptureImpl::OnBufferCreated( base::Unretained(this), handle, length, buffer_id)); } -void VideoCaptureImpl::OnBufferReceived(int buffer_id, base::Time timestamp) { +void VideoCaptureImpl::OnBufferDestroyed(int buffer_id) { + capture_message_loop_proxy_->PostTask(FROM_HERE, + base::Bind(&VideoCaptureImpl::DoBufferDestroyedOnCaptureThread, + base::Unretained(this), buffer_id)); +} + +void VideoCaptureImpl::OnBufferReceived( + int buffer_id, + base::Time timestamp, + const media::VideoCaptureFormat& format) { capture_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(&VideoCaptureImpl::DoBufferReceivedOnCaptureThread, - base::Unretained(this), buffer_id, timestamp)); + base::Unretained(this), buffer_id, timestamp, format)); } void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) { @@ -128,20 +117,6 @@ void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) { base::Unretained(this), state)); } -void VideoCaptureImpl::OnDeviceInfoReceived( - const media::VideoCaptureParams& device_info) { - capture_message_loop_proxy_->PostTask(FROM_HERE, - base::Bind(&VideoCaptureImpl::DoDeviceInfoReceivedOnCaptureThread, - base::Unretained(this), device_info)); -} - -void VideoCaptureImpl::OnDeviceInfoChanged( - const media::VideoCaptureParams& device_info) { - capture_message_loop_proxy_->PostTask(FROM_HERE, - base::Bind(&VideoCaptureImpl::DoDeviceInfoChangedOnCaptureThread, - base::Unretained(this), device_info)); -} - void VideoCaptureImpl::OnDelegateAdded(int32 device_id) { capture_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(&VideoCaptureImpl::DoDelegateAddedOnCaptureThread, @@ -165,7 +140,7 @@ void VideoCaptureImpl::DoDeInitOnCaptureThread(base::Closure task) { void VideoCaptureImpl::DoStartCaptureOnCaptureThread( media::VideoCapture::EventHandler* handler, - const media::VideoCaptureCapability& capability) { + const media::VideoCaptureParams& params) { DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); if (state_ == VIDEO_CAPTURE_STATE_ERROR) { @@ -178,46 +153,30 @@ void VideoCaptureImpl::DoStartCaptureOnCaptureThread( clients_.find(handler) != clients_.end() ) { // This client has started. } else if (!device_id_) { - clients_pending_on_filter_[handler] = capability; + clients_pending_on_filter_[handler] = params; } else { handler->OnStarted(this); if (state_ == VIDEO_CAPTURE_STATE_STARTED) { - // TODO(wjia): Temporarily disable restarting till client supports - // resampling. -#if 0 - if (capability.width > capture_format_.width || - capability.height > capture_format_.height) { - StopDevice(); - DVLOG(1) << "StartCapture: Got client with higher resolution (" - << capability.width << ", " << capability.height << ") " - << "after started, try to restart."; - clients_pending_on_restart_[handler] = capability; - } else { -#endif - { - if (device_info_available_) { - handler->OnDeviceInfoReceived(this, device_info_); - } - - clients_[handler] = capability; - } + clients_[handler] = params; } else if (state_ == VIDEO_CAPTURE_STATE_STOPPING) { - clients_pending_on_restart_[handler] = capability; - DVLOG(1) << "StartCapture: Got new resolution (" - << capability.width << ", " << capability.height << ") " - << ", during stopping."; + clients_pending_on_restart_[handler] = params; + DVLOG(1) << "StartCapture: Got new resolution " + << params.requested_format.frame_size.ToString() + << " during stopping."; } else { - clients_[handler] = capability; + // TODO(sheu): Allowing resolution change will require that all + // outstanding clients of a capture session support resolution change. + DCHECK(!params.allow_resolution_change); + clients_[handler] = params; DCHECK_EQ(1ul, clients_.size()); - video_type_ = capability.color; - int session_id = capture_format_.session_id; - DCHECK_EQ(capability.session_id, 0); - capture_format_ = capability; - capture_format_.session_id = session_id; - if (capture_format_.frame_rate > media::limits::kMaxFramesPerSecond) - capture_format_.frame_rate = media::limits::kMaxFramesPerSecond; - DVLOG(1) << "StartCapture: starting with first resolution (" - << capture_format_.width << "," << capture_format_.height << ")"; + params_ = params; + if (params_.requested_format.frame_rate > + media::limits::kMaxFramesPerSecond) { + params_.requested_format.frame_rate = + media::limits::kMaxFramesPerSecond; + } + DVLOG(1) << "StartCapture: starting with first resolution " + << params_.requested_format.frame_size.ToString(); StartCaptureInternal(); } @@ -239,7 +198,7 @@ void VideoCaptureImpl::DoStopCaptureOnCaptureThread( DVLOG(1) << "StopCapture: No more client, stopping ..."; StopDevice(); client_buffers_.clear(); - client_buffer_weak_this_factory_.InvalidateWeakPtrs(); + weak_this_factory_.InvalidateWeakPtrs(); } } @@ -255,8 +214,6 @@ void VideoCaptureImpl::DoBufferCreatedOnCaptureThread( return; } - DCHECK(device_info_available_); - scoped_ptr<base::SharedMemory> shm(new base::SharedMemory(handle, false)); if (!shm->Map(length)) { DLOG(ERROR) << "DoBufferCreatedOnCaptureThread: Map() failed."; @@ -267,15 +224,26 @@ void VideoCaptureImpl::DoBufferCreatedOnCaptureThread( client_buffers_.insert(std::make_pair( buffer_id, new ClientBuffer(shm.Pass(), - length, - device_info_.width, - device_info_.height, - device_info_.width))).second; + length))).second; DCHECK(inserted); } +void VideoCaptureImpl::DoBufferDestroyedOnCaptureThread(int buffer_id) { + DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); + + ClientBufferMap::iterator iter = client_buffers_.find(buffer_id); + if (iter == client_buffers_.end()) + return; + + DCHECK(!iter->second || iter->second->HasOneRef()) + << "Instructed to delete buffer we are still using."; + client_buffers_.erase(iter); +} + void VideoCaptureImpl::DoBufferReceivedOnCaptureThread( - int buffer_id, base::Time timestamp) { + int buffer_id, + base::Time timestamp, + const media::VideoCaptureFormat& format) { DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) { @@ -283,15 +251,17 @@ void VideoCaptureImpl::DoBufferReceivedOnCaptureThread( return; } + last_frame_format_ = format; + ClientBufferMap::iterator iter = client_buffers_.find(buffer_id); DCHECK(iter != client_buffers_.end()); scoped_refptr<ClientBuffer> buffer = iter->second; scoped_refptr<media::VideoFrame> frame = - media::VideoFrame::WrapExternalSharedMemory( + media::VideoFrame::WrapExternalPackedMemory( media::VideoFrame::I420, - gfx::Size(buffer->frame_stride, buffer->frame_height), - gfx::Rect(0, 0, buffer->frame_width, buffer->frame_height), - gfx::Size(buffer->frame_width, buffer->frame_height), + last_frame_format_.frame_size, + gfx::Rect(last_frame_format_.frame_size), + last_frame_format_.frame_size, reinterpret_cast<uint8*>(buffer->buffer->memory()), buffer->buffer_size, buffer->buffer->handle(), @@ -302,7 +272,7 @@ void VideoCaptureImpl::DoBufferReceivedOnCaptureThread( capture_message_loop_proxy_, base::Bind( &VideoCaptureImpl::DoClientBufferFinishedOnCaptureThread, - client_buffer_weak_this_factory_.GetWeakPtr(), + weak_this_factory_.GetWeakPtr(), buffer_id, buffer))); @@ -327,7 +297,7 @@ void VideoCaptureImpl::DoStateChangedOnCaptureThread(VideoCaptureState state) { state_ = VIDEO_CAPTURE_STATE_STOPPED; DVLOG(1) << "OnStateChanged: stopped!, device_id = " << device_id_; client_buffers_.clear(); - client_buffer_weak_this_factory_.InvalidateWeakPtrs(); + weak_this_factory_.InvalidateWeakPtrs(); if (!clients_.empty() || !clients_pending_on_restart_.empty()) RestartCapture(); break; @@ -362,27 +332,6 @@ void VideoCaptureImpl::DoStateChangedOnCaptureThread(VideoCaptureState state) { } } -void VideoCaptureImpl::DoDeviceInfoReceivedOnCaptureThread( - const media::VideoCaptureParams& device_info) { - DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); - DCHECK(client_buffers_.empty()); - - device_info_ = device_info; - device_info_available_ = true; - for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) { - it->first->OnDeviceInfoReceived(this, device_info); - } -} - -void VideoCaptureImpl::DoDeviceInfoChangedOnCaptureThread( - const media::VideoCaptureParams& device_info) { - DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); - - for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) { - it->first->OnDeviceInfoChanged(this, device_info); - } -} - void VideoCaptureImpl::DoDelegateAddedOnCaptureThread(int32 device_id) { DVLOG(1) << "DoDelegateAdded: device_id " << device_id; DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); @@ -391,9 +340,9 @@ void VideoCaptureImpl::DoDelegateAddedOnCaptureThread(int32 device_id) { for (ClientInfo::iterator it = clients_pending_on_filter_.begin(); it != clients_pending_on_filter_.end(); ) { media::VideoCapture::EventHandler* handler = it->first; - const media::VideoCaptureCapability capability = it->second; + const media::VideoCaptureParams params = it->second; clients_pending_on_filter_.erase(it++); - StartCapture(handler, capability); + StartCapture(handler, params); } } @@ -407,11 +356,10 @@ void VideoCaptureImpl::DoSuspendCaptureOnCaptureThread(bool suspend) { void VideoCaptureImpl::StopDevice() { DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); - device_info_available_ = false; if (state_ == VIDEO_CAPTURE_STATE_STARTED) { state_ = VIDEO_CAPTURE_STATE_STOPPING; Send(new VideoCaptureHostMsg_Stop(device_id_)); - capture_format_.width = capture_format_.height = 0; + params_.requested_format.frame_size.SetSize(0, 0); } } @@ -423,20 +371,19 @@ void VideoCaptureImpl::RestartCapture() { int height = 0; for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); ++it) { - width = std::max(width, it->second.width); - height = std::max(height, it->second.height); + width = std::max(width, it->second.requested_format.frame_size.width()); + height = std::max(height, it->second.requested_format.frame_size.height()); } for (ClientInfo::iterator it = clients_pending_on_restart_.begin(); it != clients_pending_on_restart_.end(); ) { - width = std::max(width, it->second.width); - height = std::max(height, it->second.height); + width = std::max(width, it->second.requested_format.frame_size.width()); + height = std::max(height, it->second.requested_format.frame_size.height()); clients_[it->first] = it->second; clients_pending_on_restart_.erase(it++); } - capture_format_.width = width; - capture_format_.height = height; - DVLOG(1) << "RestartCapture, " << capture_format_.width << ", " - << capture_format_.height; + params_.requested_format.frame_size.SetSize(width, height); + DVLOG(1) << "RestartCapture, " + << params_.requested_format.frame_size.ToString(); StartCaptureInternal(); } @@ -444,13 +391,7 @@ void VideoCaptureImpl::StartCaptureInternal() { DCHECK(capture_message_loop_proxy_->BelongsToCurrentThread()); DCHECK(device_id_); - media::VideoCaptureParams capability_as_params_copy; - capability_as_params_copy.width = capture_format_.width; - capability_as_params_copy.height = capture_format_.height; - capability_as_params_copy.frame_rate = capture_format_.frame_rate; - capability_as_params_copy.session_id = capture_format_.session_id; - capability_as_params_copy.frame_size_type = capture_format_.frame_size_type; - Send(new VideoCaptureHostMsg_Start(device_id_, capability_as_params_copy)); + Send(new VideoCaptureHostMsg_Start(device_id_, session_id_, params_)); state_ = VIDEO_CAPTURE_STATE_STARTED; } diff --git a/chromium/content/renderer/media/video_capture_impl.h b/chromium/content/renderer/media/video_capture_impl.h index 03696a7c9ec..2215cef4336 100644 --- a/chromium/content/renderer/media/video_capture_impl.h +++ b/chromium/content/renderer/media/video_capture_impl.h @@ -6,8 +6,8 @@ // interfaces for clients to Start/Stop capture. It also communicates to clients // when buffer is ready, state of capture device is changed. -// VideoCaptureImpl is also a delegate of VideoCaptureMessageFilter which -// relays operation of capture device to browser process and receives response +// VideoCaptureImpl is also a delegate of VideoCaptureMessageFilter which relays +// operation of a capture device to the browser process and receives responses // from browser process. // The media::VideoCapture and VideoCaptureMessageFilter::Delegate are @@ -52,22 +52,21 @@ class CONTENT_EXPORT VideoCaptureImpl // media::VideoCapture interface. virtual void StartCapture( media::VideoCapture::EventHandler* handler, - const media::VideoCaptureCapability& capability) OVERRIDE; + const media::VideoCaptureParams& params) OVERRIDE; virtual void StopCapture(media::VideoCapture::EventHandler* handler) OVERRIDE; virtual bool CaptureStarted() OVERRIDE; - virtual int CaptureWidth() OVERRIDE; - virtual int CaptureHeight() OVERRIDE; virtual int CaptureFrameRate() OVERRIDE; // VideoCaptureMessageFilter::Delegate interface. virtual void OnBufferCreated(base::SharedMemoryHandle handle, - int length, int buffer_id) OVERRIDE; - virtual void OnBufferReceived(int buffer_id, base::Time timestamp) OVERRIDE; + int length, + int buffer_id) OVERRIDE; + virtual void OnBufferDestroyed(int buffer_id) OVERRIDE; + virtual void OnBufferReceived( + int buffer_id, + base::Time timestamp, + const media::VideoCaptureFormat& format) OVERRIDE; virtual void OnStateChanged(VideoCaptureState state) OVERRIDE; - virtual void OnDeviceInfoReceived( - const media::VideoCaptureParams& device_info) OVERRIDE; - virtual void OnDeviceInfoChanged( - const media::VideoCaptureParams& device_info) OVERRIDE; virtual void OnDelegateAdded(int32 device_id) OVERRIDE; // Stop/resume delivering video frames to clients, based on flag |suspend|. @@ -80,28 +79,29 @@ class CONTENT_EXPORT VideoCaptureImpl class ClientBuffer; typedef std::map<media::VideoCapture::EventHandler*, - media::VideoCaptureCapability> ClientInfo; + media::VideoCaptureParams> ClientInfo; - VideoCaptureImpl(media::VideoCaptureSessionId id, + VideoCaptureImpl(media::VideoCaptureSessionId session_id, base::MessageLoopProxy* capture_message_loop_proxy, VideoCaptureMessageFilter* filter); virtual ~VideoCaptureImpl(); void DoStartCaptureOnCaptureThread( media::VideoCapture::EventHandler* handler, - const media::VideoCaptureCapability& capability); + const media::VideoCaptureParams& params); void DoStopCaptureOnCaptureThread(media::VideoCapture::EventHandler* handler); void DoBufferCreatedOnCaptureThread(base::SharedMemoryHandle handle, - int length, int buffer_id); - void DoBufferReceivedOnCaptureThread(int buffer_id, base::Time timestamp); + int length, + int buffer_id); + void DoBufferDestroyedOnCaptureThread(int buffer_id); + void DoBufferReceivedOnCaptureThread( + int buffer_id, + base::Time timestamp, + const media::VideoCaptureFormat& format); void DoClientBufferFinishedOnCaptureThread( int buffer_id, const scoped_refptr<ClientBuffer>& buffer); void DoStateChangedOnCaptureThread(VideoCaptureState state); - void DoDeviceInfoReceivedOnCaptureThread( - const media::VideoCaptureParams& device_info); - void DoDeviceInfoChangedOnCaptureThread( - const media::VideoCaptureParams& device_info); void DoDelegateAddedOnCaptureThread(int32 device_id); void DoSuspendCaptureOnCaptureThread(bool suspend); @@ -124,33 +124,31 @@ class CONTENT_EXPORT VideoCaptureImpl const scoped_refptr<base::MessageLoopProxy> capture_message_loop_proxy_; const scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; int device_id_; + const int session_id_; // Buffers available for sending to the client. typedef std::map<int32, scoped_refptr<ClientBuffer> > ClientBufferMap; ClientBufferMap client_buffers_; - // WeakPtrFactory pointing back to |this| object, for use with - // media::VideoFrames constructed in OnBufferReceived() from buffers cached - // in |client_buffers_|. - base::WeakPtrFactory<VideoCaptureImpl> client_buffer_weak_this_factory_; ClientInfo clients_; - ClientInfo clients_pending_on_filter_; ClientInfo clients_pending_on_restart_; - media::VideoPixelFormat video_type_; - - // Member capture_format_ represents the video format requested by the client - // to this class via DoStartCaptureOnCaptureThread. - media::VideoCaptureCapability capture_format_; + // Member params_ represents the video format requested by the + // client to this class via DoStartCaptureOnCaptureThread. + media::VideoCaptureParams params_; // The device's video capture format sent from browser process side. - media::VideoCaptureParams device_info_; - bool device_info_available_; + media::VideoCaptureFormat last_frame_format_; bool suspended_; VideoCaptureState state_; + // WeakPtrFactory pointing back to |this| object, for use with + // media::VideoFrames constructed in OnBufferReceived() from buffers cached + // in |client_buffers_|. + base::WeakPtrFactory<VideoCaptureImpl> weak_this_factory_; + DISALLOW_COPY_AND_ASSIGN(VideoCaptureImpl); }; diff --git a/chromium/content/renderer/media/video_capture_impl_unittest.cc b/chromium/content/renderer/media/video_capture_impl_unittest.cc index 986106bf1bd..713b3a06d4f 100644 --- a/chromium/content/renderer/media/video_capture_impl_unittest.cc +++ b/chromium/content/renderer/media/video_capture_impl_unittest.cc @@ -45,7 +45,7 @@ class MockVideoCaptureClient : public media::VideoCapture::EventHandler { const scoped_refptr<media::VideoFrame>& frame)); MOCK_METHOD2(OnDeviceInfoReceived, void(media::VideoCapture* capture, - const media::VideoCaptureParams& device_info)); + const media::VideoCaptureFormat& device_info)); private: DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureClient); @@ -81,9 +81,8 @@ class VideoCaptureImplTest : public ::testing::Test { } void DeviceStartCapture(int device_id, + media::VideoCaptureSessionId session_id, const media::VideoCaptureParams& params) { - media::VideoCaptureParams device_info = params; - OnDeviceInfoReceived(device_info); OnStateChanged(VIDEO_CAPTURE_STATE_STARTED); } @@ -96,21 +95,13 @@ class VideoCaptureImplTest : public ::testing::Test { void DeviceReceiveEmptyBuffer(int device_id, int buffer_id) {} }; - VideoCaptureImplTest() - : capability_small_(176, - 144, - 30, - media::PIXEL_FORMAT_I420, - 0, - false, - media::ConstantResolutionVideoCaptureDevice), - capability_large_(320, - 240, - 30, - media::PIXEL_FORMAT_I420, - 0, - false, - media::ConstantResolutionVideoCaptureDevice) { + VideoCaptureImplTest() { + params_small_.requested_format = media::VideoCaptureFormat( + gfx::Size(176, 144), 30, media::PIXEL_FORMAT_I420); + + params_large_.requested_format = media::VideoCaptureFormat( + gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420); + message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO)); message_loop_proxy_ = base::MessageLoopProxy::current().get(); child_process_.reset(new ChildProcess()); @@ -135,8 +126,8 @@ class VideoCaptureImplTest : public ::testing::Test { scoped_refptr<MockVideoCaptureMessageFilter> message_filter_; media::VideoCaptureSessionId session_id_; MockVideoCaptureImpl* video_capture_impl_; - const media::VideoCaptureCapability capability_small_; - const media::VideoCaptureCapability capability_large_; + media::VideoCaptureParams params_small_; + media::VideoCaptureParams params_large_; private: DISALLOW_COPY_AND_ASSIGN(VideoCaptureImplTest); @@ -148,10 +139,8 @@ TEST_F(VideoCaptureImplTest, Simple) { EXPECT_CALL(*client, OnStarted(_)) .WillOnce(Return()); - EXPECT_CALL(*client, OnDeviceInfoReceived(_,_)) - .WillOnce(Return()); - video_capture_impl_->StartCapture(client.get(), capability_small_); + video_capture_impl_->StartCapture(client.get(), params_small_); message_loop_->RunUntilIdle(); EXPECT_CALL(*client, OnStopped(_)) @@ -169,10 +158,8 @@ TEST_F(VideoCaptureImplTest, TwoClientsInSequence) { EXPECT_CALL(*client, OnStarted(_)) .WillOnce(Return()); - EXPECT_CALL(*client, OnDeviceInfoReceived(_,_)) - .WillOnce(Return()); - video_capture_impl_->StartCapture(client.get(), capability_small_); + video_capture_impl_->StartCapture(client.get(), params_small_); message_loop_->RunUntilIdle(); EXPECT_CALL(*client, OnStopped(_)) @@ -185,10 +172,8 @@ TEST_F(VideoCaptureImplTest, TwoClientsInSequence) { EXPECT_CALL(*client, OnStarted(_)) .WillOnce(Return()); - EXPECT_CALL(*client, OnDeviceInfoReceived(_,_)) - .WillOnce(Return()); - video_capture_impl_->StartCapture(client.get(), capability_small_); + video_capture_impl_->StartCapture(client.get(), params_small_); message_loop_->RunUntilIdle(); EXPECT_CALL(*client, OnStopped(_)) @@ -208,15 +193,11 @@ TEST_F(VideoCaptureImplTest, LargeAndSmall) { EXPECT_CALL(*client_large, OnStarted(_)) .WillOnce(Return()); - EXPECT_CALL(*client_large, OnDeviceInfoReceived(_,_)) - .WillOnce(Return()); EXPECT_CALL(*client_small, OnStarted(_)) .WillOnce(Return()); - EXPECT_CALL(*client_small, OnDeviceInfoReceived(_,_)) - .WillOnce(Return()); - video_capture_impl_->StartCapture(client_large.get(), capability_large_); - video_capture_impl_->StartCapture(client_small.get(), capability_small_); + video_capture_impl_->StartCapture(client_large.get(), params_large_); + video_capture_impl_->StartCapture(client_small.get(), params_small_); message_loop_->RunUntilIdle(); EXPECT_CALL(*client_large, OnStopped(_)) @@ -241,16 +222,11 @@ TEST_F(VideoCaptureImplTest, SmallAndLarge) { EXPECT_CALL(*client_large, OnStarted(_)) .WillOnce(Return()); - EXPECT_CALL(*client_large, OnDeviceInfoReceived(_,_)) - .WillOnce(Return()); EXPECT_CALL(*client_small, OnStarted(_)) .WillOnce(Return()); - EXPECT_CALL(*client_small, OnDeviceInfoReceived(_,_)) - .Times(AtLeast(1)) - .WillRepeatedly(Return()); - video_capture_impl_->StartCapture(client_small.get(), capability_small_); - video_capture_impl_->StartCapture(client_large.get(), capability_large_); + video_capture_impl_->StartCapture(client_small.get(), params_small_); + video_capture_impl_->StartCapture(client_large.get(), params_large_); message_loop_->RunUntilIdle(); EXPECT_CALL(*client_large, OnStopped(_)) @@ -275,15 +251,11 @@ TEST_F(VideoCaptureImplTest, TwoClientsWithSameSize) { EXPECT_CALL(*client1, OnStarted(_)) .WillOnce(Return()); - EXPECT_CALL(*client1, OnDeviceInfoReceived(_,_)) - .WillOnce(Return()); EXPECT_CALL(*client2, OnStarted(_)) .WillOnce(Return()); - EXPECT_CALL(*client2, OnDeviceInfoReceived(_,_)) - .WillOnce(Return()); - video_capture_impl_->StartCapture(client1.get(), capability_small_); - video_capture_impl_->StartCapture(client2.get(), capability_small_); + video_capture_impl_->StartCapture(client1.get(), params_small_); + video_capture_impl_->StartCapture(client2.get(), params_small_); message_loop_->RunUntilIdle(); EXPECT_CALL(*client1, OnStopped(_)) diff --git a/chromium/content/renderer/media/video_capture_message_filter.cc b/chromium/content/renderer/media/video_capture_message_filter.cc index 0ef77fa1888..52847d91744 100644 --- a/chromium/content/renderer/media/video_capture_message_filter.cc +++ b/chromium/content/renderer/media/video_capture_message_filter.cc @@ -60,7 +60,7 @@ bool VideoCaptureMessageFilter::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(VideoCaptureMsg_BufferReady, OnBufferReceived) IPC_MESSAGE_HANDLER(VideoCaptureMsg_StateChanged, OnDeviceStateChanged) IPC_MESSAGE_HANDLER(VideoCaptureMsg_NewBuffer, OnBufferCreated) - IPC_MESSAGE_HANDLER(VideoCaptureMsg_DeviceInfo, OnDeviceInfoReceived) + IPC_MESSAGE_HANDLER(VideoCaptureMsg_FreeBuffer, OnBufferDestroyed) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -68,8 +68,6 @@ bool VideoCaptureMessageFilter::OnMessageReceived(const IPC::Message& message) { void VideoCaptureMessageFilter::OnFilterAdded(IPC::Channel* channel) { DVLOG(1) << "VideoCaptureMessageFilter::OnFilterAdded()"; - // Captures the message loop proxy for IPC. - message_loop_proxy_ = base::MessageLoopProxy::current(); channel_ = channel; for (Delegates::iterator it = pending_delegates_.begin(); @@ -119,7 +117,8 @@ void VideoCaptureMessageFilter::OnBufferCreated( void VideoCaptureMessageFilter::OnBufferReceived( int device_id, int buffer_id, - base::Time timestamp) { + base::Time timestamp, + const media::VideoCaptureFormat& format) { Delegate* delegate = find_delegate(device_id); if (!delegate) { DLOG(WARNING) << "OnBufferReceived: Got video frame buffer for a " @@ -131,31 +130,32 @@ void VideoCaptureMessageFilter::OnBufferReceived( return; } - delegate->OnBufferReceived(buffer_id, timestamp); + delegate->OnBufferReceived(buffer_id, timestamp, format); } -void VideoCaptureMessageFilter::OnDeviceStateChanged( +void VideoCaptureMessageFilter::OnBufferDestroyed( int device_id, - VideoCaptureState state) { + int buffer_id) { Delegate* delegate = find_delegate(device_id); if (!delegate) { - DLOG(WARNING) << "OnDeviceStateChanged: Got video capture event for a " + DLOG(WARNING) << "OnBufferDestroyed: Instructed to free buffer for a " "non-existent or removed video capture."; return; } - delegate->OnStateChanged(state); + + delegate->OnBufferDestroyed(buffer_id); } -void VideoCaptureMessageFilter::OnDeviceInfoReceived( +void VideoCaptureMessageFilter::OnDeviceStateChanged( int device_id, - const media::VideoCaptureParams& params) { + VideoCaptureState state) { Delegate* delegate = find_delegate(device_id); if (!delegate) { - DLOG(WARNING) << "OnDeviceInfoReceived: Got video capture event for a " + DLOG(WARNING) << "OnDeviceStateChanged: Got video capture event for a " "non-existent or removed video capture."; return; } - delegate->OnDeviceInfoReceived(params); + delegate->OnStateChanged(state); } } // namespace content diff --git a/chromium/content/renderer/media/video_capture_message_filter.h b/chromium/content/renderer/media/video_capture_message_filter.h index abbe23edb0c..024c1bd91b3 100644 --- a/chromium/content/renderer/media/video_capture_message_filter.h +++ b/chromium/content/renderer/media/video_capture_message_filter.h @@ -13,7 +13,6 @@ #include <map> #include "base/memory/shared_memory.h" -#include "base/message_loop/message_loop_proxy.h" #include "content/common/content_export.h" #include "content/common/media/video_capture.h" #include "ipc/ipc_channel_proxy.h" @@ -28,25 +27,20 @@ class CONTENT_EXPORT VideoCaptureMessageFilter public: // Called when a video frame buffer is created in the browser process. virtual void OnBufferCreated(base::SharedMemoryHandle handle, - int length, int buffer_id) = 0; + int length, + int buffer_id) = 0; + + virtual void OnBufferDestroyed(int buffer_id) = 0; // Called when a video frame buffer is received from the browser process. - virtual void OnBufferReceived(int buffer_id, base::Time timestamp) = 0; + virtual void OnBufferReceived(int buffer_id, + base::Time timestamp, + const media::VideoCaptureFormat& format) = 0; // Called when state of a video capture device has changed in the browser // process. virtual void OnStateChanged(VideoCaptureState state) = 0; - // Called when device info is received from video capture device in the - // browser process. - virtual void OnDeviceInfoReceived( - const media::VideoCaptureParams& device_info) = 0; - - // Called when newly changed device info is received from video capture - // device in the browser process. - virtual void OnDeviceInfoChanged( - const media::VideoCaptureParams& device_info) {}; - // Called when the delegate has been added to filter's delegate list. // |device_id| is the device id for the delegate. virtual void OnDelegateAdded(int32 device_id) = 0; @@ -76,26 +70,27 @@ class CONTENT_EXPORT VideoCaptureMessageFilter virtual ~VideoCaptureMessageFilter(); private: - FRIEND_TEST_ALL_PREFIXES(VideoCaptureMessageFilterTest, Basic); - FRIEND_TEST_ALL_PREFIXES(VideoCaptureMessageFilterTest, Delegates); - typedef std::map<int32, Delegate*> Delegates; // Receive a newly created buffer from browser process. void OnBufferCreated(int device_id, base::SharedMemoryHandle handle, - int length, int buffer_id); + int length, + int buffer_id); - // Receive a buffer from browser process. - void OnBufferReceived(int device_id, int buffer_id, base::Time timestamp); + // Release a buffer received by OnBufferCreated. + void OnBufferDestroyed(int device_id, + int buffer_id); + + // Receive a filled buffer from browser process. + void OnBufferReceived(int device_id, + int buffer_id, + base::Time timestamp, + const media::VideoCaptureFormat& format); // State of browser process' video capture device has changed. void OnDeviceStateChanged(int device_id, VideoCaptureState state); - // Receive device info from browser process. - void OnDeviceInfoReceived(int device_id, - const media::VideoCaptureParams& params); - // Finds the delegate associated with |device_id|, NULL if not found. Delegate* find_delegate(int device_id) const; @@ -106,8 +101,6 @@ class CONTENT_EXPORT VideoCaptureMessageFilter IPC::Channel* channel_; - scoped_refptr<base::MessageLoopProxy> message_loop_proxy_; - DISALLOW_COPY_AND_ASSIGN(VideoCaptureMessageFilter); }; diff --git a/chromium/content/renderer/media/video_capture_message_filter_unittest.cc b/chromium/content/renderer/media/video_capture_message_filter_unittest.cc index 3dec39d5de3..366bcb03041 100644 --- a/chromium/content/renderer/media/video_capture_message_filter_unittest.cc +++ b/chromium/content/renderer/media/video_capture_message_filter_unittest.cc @@ -3,125 +3,67 @@ // found in the LICENSE file. #include "base/memory/shared_memory.h" -#include "base/message_loop/message_loop.h" #include "content/common/media/video_capture_messages.h" #include "content/renderer/media/video_capture_message_filter.h" +#include "ipc/ipc_test_sink.h" +#include "media/video/capture/video_capture_types.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::Mock; +using ::testing::Return; +using ::testing::SaveArg; +using ::testing::StrictMock; + namespace content { namespace { class MockVideoCaptureDelegate : public VideoCaptureMessageFilter::Delegate { public: - MockVideoCaptureDelegate() { - Reset(); - device_id_received_ = false; - device_id_ = 0; - } - - virtual void OnBufferCreated(base::SharedMemoryHandle handle, - int length, int buffer_id) OVERRIDE { - buffer_created_ = true; - handle_ = handle; - } - - // Called when a video frame buffer is received from the browser process. - virtual void OnBufferReceived(int buffer_id, base::Time timestamp) OVERRIDE { - buffer_received_ = true; - buffer_id_ = buffer_id; - timestamp_ = timestamp; - } - - virtual void OnStateChanged(VideoCaptureState state) OVERRIDE { - state_changed_received_ = true; - state_ = state; - } - - virtual void OnDeviceInfoReceived( - const media::VideoCaptureParams& params) OVERRIDE { - device_info_received_ = true; - params_.width = params.width; - params_.height = params.height; - params_.frame_rate = params.frame_rate; - } + MockVideoCaptureDelegate() : device_id_(0) {} + + // VideoCaptureMessageFilter::Delegate implementation. + MOCK_METHOD3(OnBufferCreated, void(base::SharedMemoryHandle handle, + int length, + int buffer_id)); + MOCK_METHOD1(OnBufferDestroyed, void(int buffer_id)); + MOCK_METHOD3(OnBufferReceived, void(int buffer_id, + base::Time timestamp, + const media::VideoCaptureFormat& format)); + MOCK_METHOD1(OnStateChanged, void(VideoCaptureState state)); virtual void OnDelegateAdded(int32 device_id) OVERRIDE { - device_id_received_ = true; + ASSERT_TRUE(device_id != 0); + ASSERT_TRUE(device_id_ == 0); device_id_ = device_id; } - void Reset() { - buffer_created_ = false; - handle_ = base::SharedMemory::NULLHandle(); - - buffer_received_ = false; - buffer_id_ = -1; - timestamp_ = base::Time(); - - state_changed_received_ = false; - state_ = VIDEO_CAPTURE_STATE_ERROR; - - device_info_received_ = false; - params_.width = 0; - params_.height = 0; - params_.frame_rate = 0; - } - - bool buffer_created() { return buffer_created_; } - base::SharedMemoryHandle received_buffer_handle() { return handle_; } - - bool buffer_received() { return buffer_received_; } - int received_buffer_id() { return buffer_id_; } - base::Time received_buffer_ts() { return timestamp_; } - - bool state_changed_received() { return state_changed_received_; } - VideoCaptureState state() { return state_; } - - bool device_info_receive() { return device_info_received_; } - const media::VideoCaptureParams& received_device_info() { return params_; } - - int32 device_id() { return device_id_; } + int device_id() { return device_id_; } private: - bool buffer_created_; - base::SharedMemoryHandle handle_; - - bool buffer_received_; - int buffer_id_; - base::Time timestamp_; - - bool state_changed_received_; - VideoCaptureState state_; - - bool device_info_received_; - media::VideoCaptureParams params_; - - bool device_id_received_; - int32 device_id_; - - DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureDelegate); + int device_id_; }; } // namespace TEST(VideoCaptureMessageFilterTest, Basic) { - base::MessageLoop message_loop(base::MessageLoop::TYPE_IO); - scoped_refptr<VideoCaptureMessageFilter> filter( new VideoCaptureMessageFilter()); - filter->channel_ = reinterpret_cast<IPC::Channel*>(1); + IPC::TestSink channel; + filter->OnFilterAdded(&channel); MockVideoCaptureDelegate delegate; filter->AddDelegate(&delegate); + ASSERT_EQ(1, delegate.device_id()); // VideoCaptureMsg_StateChanged - EXPECT_FALSE(delegate.state_changed_received()); + EXPECT_CALL(delegate, OnStateChanged(VIDEO_CAPTURE_STATE_STARTED)); filter->OnMessageReceived( VideoCaptureMsg_StateChanged(delegate.device_id(), VIDEO_CAPTURE_STATE_STARTED)); - EXPECT_TRUE(delegate.state_changed_received()); - EXPECT_TRUE(VIDEO_CAPTURE_STATE_STARTED == delegate.state()); - delegate.Reset(); + Mock::VerifyAndClearExpectations(&delegate); // VideoCaptureMsg_NewBuffer const base::SharedMemoryHandle handle = @@ -130,92 +72,72 @@ TEST(VideoCaptureMessageFilterTest, Basic) { #else base::SharedMemoryHandle(10, true); #endif - EXPECT_FALSE(delegate.buffer_created()); + EXPECT_CALL(delegate, OnBufferCreated(handle, 100, 1)); filter->OnMessageReceived(VideoCaptureMsg_NewBuffer( - delegate.device_id(), handle, 1, 1)); - EXPECT_TRUE(delegate.buffer_created()); - EXPECT_EQ(handle, delegate.received_buffer_handle()); - delegate.Reset(); + delegate.device_id(), handle, 100, 1)); + Mock::VerifyAndClearExpectations(&delegate); // VideoCaptureMsg_BufferReady - int buffer_id = 1; + int buffer_id = 22; base::Time timestamp = base::Time::FromInternalValue(1); - EXPECT_FALSE(delegate.buffer_received()); + media::VideoCaptureFormat format( + gfx::Size(234, 512), 30, media::PIXEL_FORMAT_I420); + media::VideoCaptureFormat saved_format; + EXPECT_CALL(delegate, OnBufferReceived(buffer_id, timestamp, _)) + .WillRepeatedly(SaveArg<2>(&saved_format)); filter->OnMessageReceived(VideoCaptureMsg_BufferReady( - delegate.device_id(), buffer_id, timestamp)); - EXPECT_TRUE(delegate.buffer_received()); - EXPECT_EQ(buffer_id, delegate.received_buffer_id()); - EXPECT_TRUE(timestamp == delegate.received_buffer_ts()); - delegate.Reset(); - - // VideoCaptureMsg_DeviceInfo - media::VideoCaptureParams params; - params.width = 320; - params.height = 240; - params.frame_rate = 30; - - EXPECT_FALSE(delegate.device_info_receive()); - filter->OnMessageReceived(VideoCaptureMsg_DeviceInfo( - delegate.device_id(), params)); - EXPECT_TRUE(delegate.device_info_receive()); - EXPECT_EQ(params.width, delegate.received_device_info().width); - EXPECT_EQ(params.height, delegate.received_device_info().height); - EXPECT_EQ(params.frame_rate, - delegate.received_device_info().frame_rate); - delegate.Reset(); - - message_loop.RunUntilIdle(); + delegate.device_id(), buffer_id, timestamp, format)); + Mock::VerifyAndClearExpectations(&delegate); + EXPECT_EQ(234, saved_format.frame_size.width()); + EXPECT_EQ(512, saved_format.frame_size.height()); + EXPECT_EQ(30, saved_format.frame_rate); + + // VideoCaptureMsg_FreeBuffer + EXPECT_CALL(delegate, OnBufferDestroyed(buffer_id)); + filter->OnMessageReceived(VideoCaptureMsg_FreeBuffer( + delegate.device_id(), buffer_id)); + Mock::VerifyAndClearExpectations(&delegate); } TEST(VideoCaptureMessageFilterTest, Delegates) { - base::MessageLoop message_loop(base::MessageLoop::TYPE_IO); - scoped_refptr<VideoCaptureMessageFilter> filter( new VideoCaptureMessageFilter()); - filter->channel_ = reinterpret_cast<IPC::Channel*>(1); - MockVideoCaptureDelegate delegate1; - MockVideoCaptureDelegate delegate2; + IPC::TestSink channel; + filter->OnFilterAdded(&channel); + + StrictMock<MockVideoCaptureDelegate> delegate1; + StrictMock<MockVideoCaptureDelegate> delegate2; filter->AddDelegate(&delegate1); filter->AddDelegate(&delegate2); + ASSERT_EQ(1, delegate1.device_id()); + ASSERT_EQ(2, delegate2.device_id()); // Send an IPC message. Make sure the correct delegate gets called. - EXPECT_FALSE(delegate1.state_changed_received()); - EXPECT_FALSE(delegate2.state_changed_received()); + EXPECT_CALL(delegate1, OnStateChanged(VIDEO_CAPTURE_STATE_STARTED)); filter->OnMessageReceived( VideoCaptureMsg_StateChanged(delegate1.device_id(), VIDEO_CAPTURE_STATE_STARTED)); - EXPECT_TRUE(delegate1.state_changed_received()); - EXPECT_FALSE(delegate2.state_changed_received()); - delegate1.Reset(); + Mock::VerifyAndClearExpectations(&delegate1); - EXPECT_FALSE(delegate1.state_changed_received()); - EXPECT_FALSE(delegate2.state_changed_received()); + EXPECT_CALL(delegate2, OnStateChanged(VIDEO_CAPTURE_STATE_STARTED)); filter->OnMessageReceived( VideoCaptureMsg_StateChanged(delegate2.device_id(), VIDEO_CAPTURE_STATE_STARTED)); - EXPECT_FALSE(delegate1.state_changed_received()); - EXPECT_TRUE(delegate2.state_changed_received()); - delegate2.Reset(); + Mock::VerifyAndClearExpectations(&delegate2); // Remove the delegates. Make sure they won't get called. filter->RemoveDelegate(&delegate1); - EXPECT_FALSE(delegate1.state_changed_received()); filter->OnMessageReceived( VideoCaptureMsg_StateChanged(delegate1.device_id(), - VIDEO_CAPTURE_STATE_STARTED)); - EXPECT_FALSE(delegate1.state_changed_received()); + VIDEO_CAPTURE_STATE_ENDED)); filter->RemoveDelegate(&delegate2); - EXPECT_FALSE(delegate2.state_changed_received()); filter->OnMessageReceived( VideoCaptureMsg_StateChanged(delegate2.device_id(), - VIDEO_CAPTURE_STATE_STARTED)); - EXPECT_FALSE(delegate2.state_changed_received()); - - message_loop.RunUntilIdle(); + VIDEO_CAPTURE_STATE_ENDED)); } } // namespace content diff --git a/chromium/content/renderer/media/video_destination_handler.cc b/chromium/content/renderer/media/video_destination_handler.cc index 7438c495f3a..692efeff86f 100644 --- a/chromium/content/renderer/media/video_destination_handler.cc +++ b/chromium/content/renderer/media/video_destination_handler.cc @@ -168,12 +168,12 @@ bool VideoDestinationHandler::Open( factory = RenderThreadImpl::current()->GetMediaStreamDependencyFactory(); DCHECK(factory != NULL); } - WebKit::WebMediaStream stream; + blink::WebMediaStream stream; if (registry) { stream = registry->GetMediaStream(url); } else { stream = - WebKit::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url)); + blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url)); } if (stream.isNull() || !stream.extraData()) { LOG(ERROR) << "VideoDestinationHandler::Open - invalid url: " << url; diff --git a/chromium/content/renderer/media/video_destination_handler.h b/chromium/content/renderer/media/video_destination_handler.h index 087d3ac6437..578fe223202 100644 --- a/chromium/content/renderer/media/video_destination_handler.h +++ b/chromium/content/renderer/media/video_destination_handler.h @@ -75,7 +75,7 @@ class CONTENT_EXPORT VideoDestinationHandler { // |frame_writer|. // If |factory| is NULL the MediaStreamDependencyFactory owned by // RenderThreadImpl::current() will be used. - // If |registry| is NULL the global WebKit::WebMediaStreamRegistry will be + // If |registry| is NULL the global blink::WebMediaStreamRegistry will be // used to look up the media stream. // The caller of the function takes the ownership of |frame_writer|. // Returns true on success and false on failure. diff --git a/chromium/content/renderer/media/video_destination_handler_unittest.cc b/chromium/content/renderer/media/video_destination_handler_unittest.cc index 110e115b84b..a89ad614386 100644 --- a/chromium/content/renderer/media/video_destination_handler_unittest.cc +++ b/chromium/content/renderer/media/video_destination_handler_unittest.cc @@ -106,8 +106,8 @@ TEST_F(VideoDestinationHandlerTest, Open) { EXPECT_TRUE(frame_writer); // Verify the video track has been added. - const WebKit::WebMediaStream test_stream = registry_.test_stream(); - WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks; + const blink::WebMediaStream test_stream = registry_.test_stream(); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks; test_stream.videoTracks(video_tracks); EXPECT_EQ(1u, video_tracks.size()); diff --git a/chromium/content/renderer/media/video_source_handler.cc b/chromium/content/renderer/media/video_source_handler.cc index c0577fc3a32..69b83557939 100644 --- a/chromium/content/renderer/media/video_source_handler.cc +++ b/chromium/content/renderer/media/video_source_handler.cc @@ -103,12 +103,12 @@ bool VideoSourceHandler::Close(const std::string& url, scoped_refptr<VideoSourceInterface> VideoSourceHandler::GetFirstVideoSource( const std::string& url) { scoped_refptr<webrtc::VideoSourceInterface> source; - WebKit::WebMediaStream stream; + blink::WebMediaStream stream; if (registry_) { stream = registry_->GetMediaStream(url); } else { stream = - WebKit::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url)); + blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url)); } if (stream.isNull() || !stream.extraData()) { LOG(ERROR) << "GetFirstVideoSource - invalid url: " << url; diff --git a/chromium/content/renderer/media/video_source_handler.h b/chromium/content/renderer/media/video_source_handler.h index 3d3b4df560b..7025d922ccc 100644 --- a/chromium/content/renderer/media/video_source_handler.h +++ b/chromium/content/renderer/media/video_source_handler.h @@ -40,7 +40,7 @@ class CONTENT_EXPORT FrameReaderInterface { class CONTENT_EXPORT VideoSourceHandler { public: // |registry| is used to look up the media stream by url. If a NULL |registry| - // is given, the global WebKit::WebMediaStreamRegistry will be used. + // is given, the global blink::WebMediaStreamRegistry will be used. explicit VideoSourceHandler(MediaStreamRegistryInterface* registry); virtual ~VideoSourceHandler(); // Connects to the first video track in the MediaStream specified by |url| and diff --git a/chromium/content/renderer/media/webaudio_capturer_source.cc b/chromium/content/renderer/media/webaudio_capturer_source.cc index f9bf084cccd..1f1192a9791 100644 --- a/chromium/content/renderer/media/webaudio_capturer_source.cc +++ b/chromium/content/renderer/media/webaudio_capturer_source.cc @@ -5,7 +5,8 @@ #include "content/renderer/media/webaudio_capturer_source.h" #include "base/logging.h" -#include "content/renderer/media/webrtc_local_audio_source_provider.h" +#include "base/time/time.h" +#include "content/renderer/media/webrtc_audio_capturer.h" #include "content/renderer/media/webrtc_local_audio_track.h" using media::AudioBus; @@ -21,7 +22,8 @@ namespace content { WebAudioCapturerSource::WebAudioCapturerSource() : track_(NULL), - source_provider_(NULL) { + capturer_(NULL), + audio_format_changed_(false) { } WebAudioCapturerSource::~WebAudioCapturerSource() { @@ -48,11 +50,7 @@ void WebAudioCapturerSource::setFormat( params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, number_of_channels, 0, sample_rate, 16, sample_rate / 100); - - // Update the downstream client to use the same format as what WebKit - // is using. - if (track_) - track_->SetCaptureFormat(params_); + audio_format_changed_ = true; wrapper_bus_ = AudioBus::CreateWrapper(params_.channels()); capture_bus_ = AudioBus::Create(params_); @@ -62,35 +60,34 @@ void WebAudioCapturerSource::setFormat( } void WebAudioCapturerSource::Start( - WebRtcLocalAudioTrack* track, - WebRtcLocalAudioSourceProvider* source_provider) { + WebRtcLocalAudioTrack* track, WebRtcAudioCapturer* capturer) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(track); - // |source_provider| may be NULL if no getUserMedia has been called before - // calling CreateMediaStreamDestination. - // The downstream client should be configured the same as what WebKit - // is feeding it. - track->SetCaptureFormat(params_); - base::AutoLock auto_lock(lock_); track_ = track; - source_provider_ = source_provider; + capturer_ = capturer; } void WebAudioCapturerSource::Stop() { DCHECK(thread_checker_.CalledOnValidThread()); base::AutoLock auto_lock(lock_); track_ = NULL; - source_provider_ = NULL; + capturer_ = NULL; } void WebAudioCapturerSource::consumeAudio( - const WebKit::WebVector<const float*>& audio_data, + const blink::WebVector<const float*>& audio_data, size_t number_of_frames) { base::AutoLock auto_lock(lock_); if (!track_) return; + // Update the downstream client if the audio format has been changed. + if (audio_format_changed_) { + track_->OnSetFormat(params_); + audio_format_changed_ = false; + } + wrapper_bus_->set_frames(number_of_frames); // Make sure WebKit is honoring what it told us up front @@ -109,16 +106,16 @@ void WebAudioCapturerSource::consumeAudio( fifo_->Push(wrapper_bus_.get()); int capture_frames = params_.frames_per_buffer(); - int delay_ms = 0; + base::TimeDelta delay; int volume = 0; bool key_pressed = false; + if (capturer_) { + capturer_->GetAudioProcessingParams(&delay, &volume, &key_pressed); + } while (fifo_->frames() >= capture_frames) { - if (source_provider_) { - source_provider_->GetAudioProcessingParams( - &delay_ms, &volume, &key_pressed); - } fifo_->Consume(capture_bus_.get(), 0, capture_frames); - track_->Capture(capture_bus_.get(), delay_ms, volume, key_pressed); + track_->Capture(capture_bus_.get(), delay.InMilliseconds(), + volume, key_pressed); } } diff --git a/chromium/content/renderer/media/webaudio_capturer_source.h b/chromium/content/renderer/media/webaudio_capturer_source.h index b438a4083ee..2993531db18 100644 --- a/chromium/content/renderer/media/webaudio_capturer_source.h +++ b/chromium/content/renderer/media/webaudio_capturer_source.h @@ -16,8 +16,8 @@ namespace content { +class WebRtcAudioCapturer; class WebRtcLocalAudioTrack; -class WebRtcLocalAudioSourceProvider; // WebAudioCapturerSource is the missing link between // WebAudio's MediaStreamAudioDestinationNode and WebRtcLocalAudioTrack. @@ -28,7 +28,7 @@ class WebRtcLocalAudioSourceProvider; // audio stream to the WebRtcLocalAudioTrack::Capture() method. class WebAudioCapturerSource : public base::RefCountedThreadSafe<WebAudioCapturerSource>, - public WebKit::WebAudioDestinationConsumer { + public blink::WebAudioDestinationConsumer { public: WebAudioCapturerSource(); @@ -37,15 +37,14 @@ class WebAudioCapturerSource virtual void setFormat(size_t number_of_channels, float sample_rate) OVERRIDE; // MediaStreamAudioDestinationNode periodically calls consumeAudio(). // Called on the WebAudio audio thread. - virtual void consumeAudio(const WebKit::WebVector<const float*>& audio_data, + virtual void consumeAudio(const blink::WebVector<const float*>& audio_data, size_t number_of_frames) OVERRIDE; // Called when the WebAudioCapturerSource is hooking to a media audio track. // |track| is the sink of the data flow. |source_provider| is the source of // the data flow where stream information like delay, volume, key_pressed, // is stored. - void Start(WebRtcLocalAudioTrack* track, - WebRtcLocalAudioSourceProvider* source_provider); + void Start(WebRtcLocalAudioTrack* track, WebRtcAudioCapturer* capturer); // Called when the media audio track is stopping. void Stop(); @@ -63,13 +62,16 @@ class WebAudioCapturerSource // To avoid circular reference, a raw pointer is kept here. WebRtcLocalAudioTrack* track_; - // A raw pointer to the source provider to get audio processing params like + // A raw pointer to the capturer to get audio processing params like // delay, volume, key_pressed information. - // This |source_provider_| is guaranteed to outlive this object. - WebRtcLocalAudioSourceProvider* source_provider_; + // This |capturer_| is guaranteed to outlive this object. + WebRtcAudioCapturer* capturer_; media::AudioParameters params_; + // Flag to help notify the |track_| when the audio format has changed. + bool audio_format_changed_; + // Wraps data coming from HandleCapture(). scoped_ptr<media::AudioBus> wrapper_bus_; diff --git a/chromium/content/renderer/media/webaudiosourceprovider_impl.cc b/chromium/content/renderer/media/webaudiosourceprovider_impl.cc index b722a33af4c..ec1683daae4 100644 --- a/chromium/content/renderer/media/webaudiosourceprovider_impl.cc +++ b/chromium/content/renderer/media/webaudiosourceprovider_impl.cc @@ -6,10 +6,13 @@ #include <vector> +#include "base/bind.h" +#include "base/callback_helpers.h" #include "base/logging.h" -#include "third_party/WebKit/public/web/WebAudioSourceProviderClient.h" +#include "media/base/bind_to_loop.h" +#include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h" -using WebKit::WebVector; +using blink::WebVector; namespace content { @@ -45,7 +48,8 @@ class AutoTryLock { WebAudioSourceProviderImpl::WebAudioSourceProviderImpl( const scoped_refptr<media::AudioRendererSink>& sink) - : channels_(0), + : weak_this_(this), + channels_(0), sample_rate_(0), volume_(1.0), state_(kStopped), @@ -54,10 +58,11 @@ WebAudioSourceProviderImpl::WebAudioSourceProviderImpl( sink_(sink) { } -WebAudioSourceProviderImpl::~WebAudioSourceProviderImpl() {} +WebAudioSourceProviderImpl::~WebAudioSourceProviderImpl() { +} void WebAudioSourceProviderImpl::setClient( - WebKit::WebAudioSourceProviderClient* client) { + blink::WebAudioSourceProviderClient* client) { base::AutoLock auto_lock(sink_lock_); if (client && client != client_) { // Detach the audio renderer from normal playback. @@ -66,14 +71,17 @@ void WebAudioSourceProviderImpl::setClient( // The client will now take control by calling provideInput() periodically. client_ = client; - if (renderer_) { - // The client needs to be notified of the audio format, if available. - // If the format is not yet available, we'll be notified later - // when Initialize() is called. - - // Inform WebKit about the audio stream format. - client->setFormat(channels_, sample_rate_); - } + set_format_cb_ = media::BindToCurrentLoop( + base::Bind(&WebAudioSourceProviderImpl::OnSetFormat, + weak_this_.GetWeakPtr())); + + // If |renderer_| is set, then run |set_format_cb_| to send |client_| + // the current format info. If |renderer_| is not set, then |set_format_cb_| + // will get called when Initialize() is called. + // Note: Always using |set_format_cb_| ensures we have the same + // locking order when calling into |client_|. + if (renderer_) + base::ResetAndReturn(&set_format_cb_).Run(); } else if (!client && client_) { // Restore normal playback. client_ = NULL; @@ -165,10 +173,17 @@ void WebAudioSourceProviderImpl::Initialize( channels_ = params.channels(); sample_rate_ = params.sample_rate(); - if (client_) { - // Inform WebKit about the audio stream format. - client_->setFormat(channels_, sample_rate_); - } + if (!set_format_cb_.is_null()) + base::ResetAndReturn(&set_format_cb_).Run(); +} + +void WebAudioSourceProviderImpl::OnSetFormat() { + base::AutoLock auto_lock(sink_lock_); + if (!client_) + return; + + // Inform Blink about the audio stream format. + client_->setFormat(channels_, sample_rate_); } } // namespace content diff --git a/chromium/content/renderer/media/webaudiosourceprovider_impl.h b/chromium/content/renderer/media/webaudiosourceprovider_impl.h index fd27697f49b..d1a6fe72322 100644 --- a/chromium/content/renderer/media/webaudiosourceprovider_impl.h +++ b/chromium/content/renderer/media/webaudiosourceprovider_impl.h @@ -5,20 +5,22 @@ #ifndef CONTENT_RENDERER_MEDIA_WEBAUDIOSOURCEPROVIDER_IMPL_H_ #define CONTENT_RENDERER_MEDIA_WEBAUDIOSOURCEPROVIDER_IMPL_H_ +#include "base/callback.h" +#include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" #include "content/common/content_export.h" #include "media/base/audio_renderer_sink.h" +#include "third_party/WebKit/public/platform/WebAudioSourceProvider.h" #include "third_party/WebKit/public/platform/WebVector.h" -#include "third_party/WebKit/public/web/WebAudioSourceProvider.h" -namespace WebKit { +namespace blink { class WebAudioSourceProviderClient; } namespace content { // WebAudioSourceProviderImpl provides a bridge between classes: -// WebKit::WebAudioSourceProvider <---> media::AudioRendererSink +// blink::WebAudioSourceProvider <---> media::AudioRendererSink // // WebAudioSourceProviderImpl wraps an existing audio sink that is used unless // WebKit has set a client via setClient(). While a client is set WebKit will @@ -27,15 +29,15 @@ namespace content { // // All calls are protected by a lock. class CONTENT_EXPORT WebAudioSourceProviderImpl - : NON_EXPORTED_BASE(public WebKit::WebAudioSourceProvider), + : NON_EXPORTED_BASE(public blink::WebAudioSourceProvider), NON_EXPORTED_BASE(public media::AudioRendererSink) { public: explicit WebAudioSourceProviderImpl( const scoped_refptr<media::AudioRendererSink>& sink); - // WebKit::WebAudioSourceProvider implementation. - virtual void setClient(WebKit::WebAudioSourceProviderClient* client); - virtual void provideInput(const WebKit::WebVector<float*>& audio_data, + // blink::WebAudioSourceProvider implementation. + virtual void setClient(blink::WebAudioSourceProviderClient* client); + virtual void provideInput(const blink::WebVector<float*>& audio_data, size_t number_of_frames); // media::AudioRendererSink implementation. @@ -51,6 +53,14 @@ class CONTENT_EXPORT WebAudioSourceProviderImpl virtual ~WebAudioSourceProviderImpl(); private: + // Calls setFormat() on |client_| from the Blink renderer thread. + void OnSetFormat(); + + base::WeakPtrFactory<WebAudioSourceProviderImpl> weak_this_; + + // Closure that posts a task to call OnSetFormat() on the renderer thread. + base::Closure set_format_cb_; + // Set to true when Initialize() is called. int channels_; int sample_rate_; @@ -64,7 +74,7 @@ class CONTENT_EXPORT WebAudioSourceProviderImpl media::AudioRendererSink::RenderCallback* renderer_; // When set via setClient() it overrides |sink_| for consuming audio. - WebKit::WebAudioSourceProviderClient* client_; + blink::WebAudioSourceProviderClient* client_; // Where audio ends up unless overridden by |client_|. base::Lock sink_lock_; diff --git a/chromium/content/renderer/media/webaudiosourceprovider_impl_unittest.cc b/chromium/content/renderer/media/webaudiosourceprovider_impl_unittest.cc index 9b893c74b25..e4786a5a07a 100644 --- a/chromium/content/renderer/media/webaudiosourceprovider_impl_unittest.cc +++ b/chromium/content/renderer/media/webaudiosourceprovider_impl_unittest.cc @@ -2,13 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" #include "content/renderer/media/webaudiosourceprovider_impl.h" #include "media/audio/audio_parameters.h" #include "media/base/fake_audio_render_callback.h" #include "media/base/mock_audio_renderer_sink.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/WebKit/public/web/WebAudioSourceProviderClient.h" +#include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h" namespace content { @@ -18,7 +20,7 @@ const float kTestVolume = 0.25; class WebAudioSourceProviderImplTest : public testing::Test, - public WebKit::WebAudioSourceProviderClient { + public blink::WebAudioSourceProviderClient { public: WebAudioSourceProviderImplTest() : params_(media::AudioParameters::AUDIO_PCM_LINEAR, @@ -51,7 +53,7 @@ class WebAudioSourceProviderImplTest testing::Mock::VerifyAndClear(mock_sink_.get()); } - void SetClient(WebKit::WebAudioSourceProviderClient* client) { + void SetClient(blink::WebAudioSourceProviderClient* client) { testing::InSequence s; if (client) { @@ -59,6 +61,7 @@ class WebAudioSourceProviderImplTest EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate())); } wasp_impl_->setClient(client); + base::RunLoop().RunUntilIdle(); testing::Mock::VerifyAndClear(mock_sink_.get()); testing::Mock::VerifyAndClear(this); @@ -76,7 +79,7 @@ class WebAudioSourceProviderImplTest return true; } - // WebKit::WebAudioSourceProviderClient implementation. + // blink::WebAudioSourceProviderClient implementation. MOCK_METHOD2(setFormat, void(size_t numberOfChannels, float sampleRate)); protected: @@ -84,6 +87,7 @@ class WebAudioSourceProviderImplTest media::FakeAudioRenderCallback fake_callback_; scoped_refptr<media::MockAudioRendererSink> mock_sink_; scoped_refptr<WebAudioSourceProviderImpl> wasp_impl_; + base::MessageLoop message_loop_; DISALLOW_COPY_AND_ASSIGN(WebAudioSourceProviderImplTest); }; @@ -94,14 +98,17 @@ TEST_F(WebAudioSourceProviderImplTest, SetClientBeforeInitialize) { EXPECT_CALL(*mock_sink_.get(), Stop()); wasp_impl_->setClient(this); + base::RunLoop().RunUntilIdle(); // When Initialize() is called after setClient(), the params should propagate // to the client via setFormat() during the call. EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate())); wasp_impl_->Initialize(params_, &fake_callback_); + base::RunLoop().RunUntilIdle(); // setClient() with the same client should do nothing. wasp_impl_->setClient(this); + base::RunLoop().RunUntilIdle(); } // Verify AudioRendererSink functionality w/ and w/o a client. @@ -153,7 +160,7 @@ TEST_F(WebAudioSourceProviderImplTest, ProvideInput) { scoped_ptr<media::AudioBus> bus2 = media::AudioBus::Create(params_); // Point the WebVector into memory owned by |bus1|. - WebKit::WebVector<float*> audio_data(static_cast<size_t>(bus1->channels())); + blink::WebVector<float*> audio_data(static_cast<size_t>(bus1->channels())); for (size_t i = 0; i < audio_data.size(); ++i) audio_data[i] = bus1->channel(i); diff --git a/chromium/content/renderer/media/webcontentdecryptionmodule_impl.cc b/chromium/content/renderer/media/webcontentdecryptionmodule_impl.cc index a70ad2adbb8..14bbc8d5fe9 100644 --- a/chromium/content/renderer/media/webcontentdecryptionmodule_impl.cc +++ b/chromium/content/renderer/media/webcontentdecryptionmodule_impl.cc @@ -31,37 +31,48 @@ class SessionIdAdapter { bool Initialize(const std::string& key_system, scoped_ptr<media::MediaKeys>* media_keys); + // Generates a unique internal session id. + uint32 GenerateSessionId(); + // Adds a session to the internal map. Does not take ownership of the session. - void AddSession(const std::string& session_id, + void AddSession(uint32 session_id, WebContentDecryptionModuleSessionImpl* session); // Removes a session from the internal map. - void RemoveSession(const std::string& session_id); + void RemoveSession(uint32 session_id); private: - typedef std::map<std::string, WebContentDecryptionModuleSessionImpl*> - SessionMap; - - // Callbacks for firing key events. - void KeyAdded(const std::string& session_id); - void KeyError(const std::string& session_id, - media::MediaKeys::KeyError error_code, - int system_code); - void KeyMessage(const std::string& session_id, - const std::vector<uint8>& message, - const std::string& destination_url); + typedef std::map<uint32, WebContentDecryptionModuleSessionImpl*> SessionMap; + + // Callbacks for firing session events. + void OnSessionCreated(uint32 session_id, const std::string& web_session_id); + void OnSessionMessage(uint32 session_id, + const std::vector<uint8>& message, + const std::string& destination_url); + void OnSessionReady(uint32 session_id); + void OnSessionClosed(uint32 session_id); + void OnSessionError(uint32 session_id, + media::MediaKeys::KeyError error_code, + int system_code); // Helper function of the callbacks. - WebContentDecryptionModuleSessionImpl* GetSession( - const std::string& session_id); + WebContentDecryptionModuleSessionImpl* GetSession(uint32 session_id); base::WeakPtrFactory<SessionIdAdapter> weak_ptr_factory_; SessionMap sessions_; + // Session ID should be unique per renderer process for debugging purposes. + static uint32 next_session_id_; + DISALLOW_COPY_AND_ASSIGN(SessionIdAdapter); }; +const uint32 kStartingSessionId = 1; +uint32 SessionIdAdapter::next_session_id_ = kStartingSessionId; +COMPILE_ASSERT(kStartingSessionId > media::MediaKeys::kInvalidSessionId, + invalid_starting_value); + SessionIdAdapter::SessionIdAdapter() : weak_ptr_factory_(this) { } @@ -91,9 +102,11 @@ bool SessionIdAdapter::Initialize(const std::string& key_system, // TODO(ddorwin): Get the URL for the frame containing the MediaKeys. GURL(), #endif // defined(ENABLE_PEPPER_CDMS) - base::Bind(&SessionIdAdapter::KeyAdded, weak_this), - base::Bind(&SessionIdAdapter::KeyError, weak_this), - base::Bind(&SessionIdAdapter::KeyMessage, weak_this)); + base::Bind(&SessionIdAdapter::OnSessionCreated, weak_this), + base::Bind(&SessionIdAdapter::OnSessionMessage, weak_this), + base::Bind(&SessionIdAdapter::OnSessionReady, weak_this), + base::Bind(&SessionIdAdapter::OnSessionClosed, weak_this), + base::Bind(&SessionIdAdapter::OnSessionError, weak_this)); if (!created_media_keys) return false; @@ -101,47 +114,57 @@ bool SessionIdAdapter::Initialize(const std::string& key_system, return true; } +uint32 SessionIdAdapter::GenerateSessionId() { + return next_session_id_++; +} + void SessionIdAdapter::AddSession( - const std::string& session_id, + uint32 session_id, WebContentDecryptionModuleSessionImpl* session) { DCHECK(sessions_.find(session_id) == sessions_.end()); sessions_[session_id] = session; } -void SessionIdAdapter::RemoveSession(const std::string& session_id) { +void SessionIdAdapter::RemoveSession(uint32 session_id) { DCHECK(sessions_.find(session_id) != sessions_.end()); sessions_.erase(session_id); } -void SessionIdAdapter::KeyAdded(const std::string& session_id) { - GetSession(session_id)->KeyAdded(); +void SessionIdAdapter::OnSessionCreated(uint32 session_id, + const std::string& web_session_id) { + GetSession(session_id)->OnSessionCreated(web_session_id); } -void SessionIdAdapter::KeyError(const std::string& session_id, - media::MediaKeys::KeyError error_code, - int system_code) { - GetSession(session_id)->KeyError(error_code, system_code); +void SessionIdAdapter::OnSessionMessage(uint32 session_id, + const std::vector<uint8>& message, + const std::string& destination_url) { + GetSession(session_id)->OnSessionMessage(message, destination_url); } -void SessionIdAdapter::KeyMessage(const std::string& session_id, - const std::vector<uint8>& message, - const std::string& destination_url) { - GetSession(session_id)->KeyMessage(message, destination_url); +void SessionIdAdapter::OnSessionReady(uint32 session_id) { + GetSession(session_id)->OnSessionReady(); +} + +void SessionIdAdapter::OnSessionClosed(uint32 session_id) { + GetSession(session_id)->OnSessionClosed(); +} + +void SessionIdAdapter::OnSessionError(uint32 session_id, + media::MediaKeys::KeyError error_code, + int system_code) { + GetSession(session_id)->OnSessionError(error_code, system_code); } WebContentDecryptionModuleSessionImpl* SessionIdAdapter::GetSession( - const std::string& session_id) { - // TODO(ddorwin): Map session IDs correctly. For now, we only support one. - std::string session_object_id = ""; - WebContentDecryptionModuleSessionImpl* session = sessions_[session_object_id]; - DCHECK(session); // It must have been present. - return session; + uint32 session_id) { + DCHECK(sessions_.find(session_id) != sessions_.end()); + return sessions_[session_id]; } //------------------------------------------------------------------------------ WebContentDecryptionModuleImpl* -WebContentDecryptionModuleImpl::Create(const string16& key_system) { +WebContentDecryptionModuleImpl::Create(const base::string16& key_system) { // TODO(ddorwin): Guard against this in supported types check and remove this. // Chromium only supports ASCII key systems. if (!IsStringASCII(key_system)) { @@ -170,24 +193,24 @@ WebContentDecryptionModuleImpl::~WebContentDecryptionModuleImpl() { } // The caller owns the created session. -WebKit::WebContentDecryptionModuleSession* +blink::WebContentDecryptionModuleSession* WebContentDecryptionModuleImpl::createSession( - WebKit::WebContentDecryptionModuleSession::Client* client) { + blink::WebContentDecryptionModuleSession::Client* client) { DCHECK(media_keys_); + uint32 session_id = adapter_->GenerateSessionId(); WebContentDecryptionModuleSessionImpl* session = new WebContentDecryptionModuleSessionImpl( + session_id, media_keys_.get(), client, base::Bind(&WebContentDecryptionModuleImpl::OnSessionClosed, base::Unretained(this))); - // TODO(ddorwin): session_id is not populated yet! - adapter_->AddSession(session->session_id(), session); + adapter_->AddSession(session_id, session); return session; } -void WebContentDecryptionModuleImpl::OnSessionClosed( - const std::string& session_id) { +void WebContentDecryptionModuleImpl::OnSessionClosed(uint32 session_id) { adapter_->RemoveSession(session_id); } diff --git a/chromium/content/renderer/media/webcontentdecryptionmodule_impl.h b/chromium/content/renderer/media/webcontentdecryptionmodule_impl.h index d2aa01fa1bf..ecd5198efda 100644 --- a/chromium/content/renderer/media/webcontentdecryptionmodule_impl.h +++ b/chromium/content/renderer/media/webcontentdecryptionmodule_impl.h @@ -21,15 +21,16 @@ class WebContentDecryptionModuleSessionImpl; class SessionIdAdapter; class WebContentDecryptionModuleImpl - : public WebKit::WebContentDecryptionModule { + : public blink::WebContentDecryptionModule { public: - static WebContentDecryptionModuleImpl* Create(const string16& key_system); + static WebContentDecryptionModuleImpl* Create( + const base::string16& key_system); virtual ~WebContentDecryptionModuleImpl(); - // WebKit::WebContentDecryptionModule implementation. - virtual WebKit::WebContentDecryptionModuleSession* createSession( - WebKit::WebContentDecryptionModuleSession::Client* client); + // blink::WebContentDecryptionModule implementation. + virtual blink::WebContentDecryptionModuleSession* createSession( + blink::WebContentDecryptionModuleSession::Client* client); private: // Takes ownership of |media_keys| and |adapter|. @@ -37,7 +38,7 @@ class WebContentDecryptionModuleImpl scoped_ptr<SessionIdAdapter> adapter); // Called when a WebContentDecryptionModuleSessionImpl is closed. - void OnSessionClosed(const std::string& session_id); + void OnSessionClosed(uint32 session_id); scoped_ptr<media::MediaKeys> media_keys_; scoped_ptr<SessionIdAdapter> adapter_; diff --git a/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.cc b/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.cc index b1dea741d5a..bc74d35dc6a 100644 --- a/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.cc +++ b/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.cc @@ -12,70 +12,87 @@ namespace content { WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl( + uint32 session_id, media::MediaKeys* media_keys, Client* client, const SessionClosedCB& session_closed_cb) : media_keys_(media_keys), client_(client), - session_closed_cb_(session_closed_cb) { + session_closed_cb_(session_closed_cb), + session_id_(session_id) { DCHECK(media_keys_); - // TODO(ddorwin): Populate session_id_ from the real implementation. } WebContentDecryptionModuleSessionImpl:: ~WebContentDecryptionModuleSessionImpl() { } -WebKit::WebString WebContentDecryptionModuleSessionImpl::sessionId() const { - return WebKit::WebString::fromUTF8(session_id_); +blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const { + return web_session_id_; } void WebContentDecryptionModuleSessionImpl::generateKeyRequest( - const WebKit::WebString& mime_type, + const blink::WebString& mime_type, const uint8* init_data, size_t init_data_length) { // TODO(ddorwin): Guard against this in supported types check and remove this. // Chromium only supports ASCII MIME types. if (!IsStringASCII(mime_type)) { NOTREACHED(); - KeyError(media::MediaKeys::kUnknownError, 0); + OnSessionError(media::MediaKeys::kUnknownError, 0); return; } - media_keys_->GenerateKeyRequest(UTF16ToASCII(mime_type), - init_data, init_data_length); + media_keys_->CreateSession( + session_id_, UTF16ToASCII(mime_type), init_data, init_data_length); } -void WebContentDecryptionModuleSessionImpl::update(const uint8* key, - size_t key_length) { - DCHECK(key); - media_keys_->AddKey(key, key_length, NULL, 0, session_id_); +void WebContentDecryptionModuleSessionImpl::update(const uint8* response, + size_t response_length) { + DCHECK(response); + media_keys_->UpdateSession(session_id_, response, response_length); } void WebContentDecryptionModuleSessionImpl::close() { - media_keys_->CancelKeyRequest(session_id_); + media_keys_->ReleaseSession(session_id_); +} - // Detach from the CDM. - if (!session_closed_cb_.is_null()) - base::ResetAndReturn(&session_closed_cb_).Run(session_id_); +void WebContentDecryptionModuleSessionImpl::OnSessionCreated( + const std::string& web_session_id) { + // Due to heartbeat messages, OnSessionCreated() can get called multiple + // times. + // TODO(jrummell): Once all CDMs are updated to support reference ids, + // OnSessionCreated() should only be called once, and the second check can be + // removed. + blink::WebString id = blink::WebString::fromUTF8(web_session_id); + DCHECK(web_session_id_.isEmpty() || web_session_id_ == id) + << "Session ID may not be changed once set."; + web_session_id_ = id; } -void WebContentDecryptionModuleSessionImpl::KeyAdded() { +void WebContentDecryptionModuleSessionImpl::OnSessionMessage( + const std::vector<uint8>& message, + const std::string& destination_url) { + client_->keyMessage(message.empty() ? NULL : &message[0], + message.size(), + GURL(destination_url)); +} + +void WebContentDecryptionModuleSessionImpl::OnSessionReady() { + // TODO(jrummell): Blink APIs need to be updated to the new EME API. For now, + // convert the response to the old v0.1b API. client_->keyAdded(); } -void WebContentDecryptionModuleSessionImpl::KeyError( +void WebContentDecryptionModuleSessionImpl::OnSessionClosed() { + if (!session_closed_cb_.is_null()) + base::ResetAndReturn(&session_closed_cb_).Run(session_id_); +} + +void WebContentDecryptionModuleSessionImpl::OnSessionError( media::MediaKeys::KeyError error_code, int system_code) { client_->keyError(static_cast<Client::MediaKeyErrorCode>(error_code), system_code); } -void WebContentDecryptionModuleSessionImpl::KeyMessage( - const std::vector<uint8>& message, - const std::string& destination_url) { - client_->keyMessage(message.empty() ? NULL : &message[0], - message.size(), - GURL(destination_url)); -} - } // namespace content diff --git a/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.h b/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.h index df76f08de5f..6ff091c876a 100644 --- a/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.h +++ b/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.h @@ -21,31 +21,32 @@ class MediaKeys; namespace content { class WebContentDecryptionModuleSessionImpl - : public WebKit::WebContentDecryptionModuleSession { + : public blink::WebContentDecryptionModuleSession { public: - typedef base::Callback<void(const std::string& session_id)> SessionClosedCB; + typedef base::Callback<void(uint32 session_id)> SessionClosedCB; WebContentDecryptionModuleSessionImpl( + uint32 session_id, media::MediaKeys* media_keys, Client* client, const SessionClosedCB& session_closed_cb); virtual ~WebContentDecryptionModuleSessionImpl(); - // WebKit::WebContentDecryptionModuleSession implementation. - virtual WebKit::WebString sessionId() const OVERRIDE; - virtual void generateKeyRequest(const WebKit::WebString& mime_type, + // blink::WebContentDecryptionModuleSession implementation. + virtual blink::WebString sessionId() const OVERRIDE; + virtual void generateKeyRequest(const blink::WebString& mime_type, const uint8* init_data, size_t init_data_length) OVERRIDE; - virtual void update(const uint8* key, size_t key_length) OVERRIDE; + virtual void update(const uint8* response, size_t response_length) OVERRIDE; virtual void close() OVERRIDE; - const std::string& session_id() const { return session_id_; } - // Callbacks. - void KeyAdded(); - void KeyError(media::MediaKeys::KeyError error_code, int system_code); - void KeyMessage(const std::vector<uint8>& message, - const std::string& destination_url); + void OnSessionCreated(const std::string& web_session_id); + void OnSessionMessage(const std::vector<uint8>& message, + const std::string& destination_url); + void OnSessionReady(); + void OnSessionClosed(); + void OnSessionError(media::MediaKeys::KeyError error_code, int system_code); private: // Non-owned pointers. @@ -54,7 +55,13 @@ class WebContentDecryptionModuleSessionImpl SessionClosedCB session_closed_cb_; - std::string session_id_; + // Web session ID is the app visible ID for this session generated by the CDM. + // This value is not set until the CDM calls OnSessionCreated(). + blink::WebString web_session_id_; + + // Session ID is used to uniquely track this object so that CDM callbacks + // can get routed to the correct object. + const uint32 session_id_; DISALLOW_COPY_AND_ASSIGN(WebContentDecryptionModuleSessionImpl); }; diff --git a/chromium/content/renderer/media/webinbandtexttrack_impl.cc b/chromium/content/renderer/media/webinbandtexttrack_impl.cc index 6d1de2610c8..e83af8f3451 100644 --- a/chromium/content/renderer/media/webinbandtexttrack_impl.cc +++ b/chromium/content/renderer/media/webinbandtexttrack_impl.cc @@ -10,14 +10,15 @@ namespace content { WebInbandTextTrackImpl::WebInbandTextTrackImpl( Kind kind, - const WebKit::WebString& label, - const WebKit::WebString& language, + const blink::WebString& label, + const blink::WebString& language, + const blink::WebString& id, int index) : client_(NULL), - mode_(ModeDisabled), kind_(kind), label_(label), language_(language), + id_(id), index_(index) { } @@ -26,47 +27,28 @@ WebInbandTextTrackImpl::~WebInbandTextTrackImpl() { } void WebInbandTextTrackImpl::setClient( - WebKit::WebInbandTextTrackClient* client) { + blink::WebInbandTextTrackClient* client) { client_ = client; } -WebKit::WebInbandTextTrackClient* WebInbandTextTrackImpl::client() { +blink::WebInbandTextTrackClient* WebInbandTextTrackImpl::client() { return client_; } -void WebInbandTextTrackImpl::setMode(Mode mode) { - mode_ = mode; -} - -WebInbandTextTrackImpl::Mode WebInbandTextTrackImpl::mode() const { - return mode_; -} - WebInbandTextTrackImpl::Kind WebInbandTextTrackImpl::kind() const { return kind_; } -bool WebInbandTextTrackImpl::isClosedCaptions() const { - switch (kind_) { - case KindCaptions: - case KindSubtitles: - return true; - - default: - return false; - } -} - -WebKit::WebString WebInbandTextTrackImpl::label() const { +blink::WebString WebInbandTextTrackImpl::label() const { return label_; } -WebKit::WebString WebInbandTextTrackImpl::language() const { +blink::WebString WebInbandTextTrackImpl::language() const { return language_; } -bool WebInbandTextTrackImpl::isDefault() const { - return false; +blink::WebString WebInbandTextTrackImpl::id() const { + return id_; } int WebInbandTextTrackImpl::textTrackIndex() const { diff --git a/chromium/content/renderer/media/webinbandtexttrack_impl.h b/chromium/content/renderer/media/webinbandtexttrack_impl.h index 82b94adbdbc..293fbd3fac9 100644 --- a/chromium/content/renderer/media/webinbandtexttrack_impl.h +++ b/chromium/content/renderer/media/webinbandtexttrack_impl.h @@ -5,40 +5,37 @@ #ifndef CONTENT_RENDERER_MEDIA_WEBINBANDTEXTTRACK_IMPL_H_ #define CONTENT_RENDERER_MEDIA_WEBINBANDTEXTTRACK_IMPL_H_ +#include "third_party/WebKit/public/platform/WebInbandTextTrack.h" #include "third_party/WebKit/public/platform/WebString.h" -#include "third_party/WebKit/public/web/WebInbandTextTrack.h" namespace content { -class WebInbandTextTrackImpl : public WebKit::WebInbandTextTrack { +class WebInbandTextTrackImpl : public blink::WebInbandTextTrack { public: WebInbandTextTrackImpl(Kind kind, - const WebKit::WebString& label, - const WebKit::WebString& language, + const blink::WebString& label, + const blink::WebString& language, + const blink::WebString& id, int index); virtual ~WebInbandTextTrackImpl(); - virtual void setClient(WebKit::WebInbandTextTrackClient* client); - virtual WebKit::WebInbandTextTrackClient* client(); - - virtual void setMode(Mode mode); - virtual Mode mode() const; + virtual void setClient(blink::WebInbandTextTrackClient* client); + virtual blink::WebInbandTextTrackClient* client(); virtual Kind kind() const; - virtual bool isClosedCaptions() const; - virtual WebKit::WebString label() const; - virtual WebKit::WebString language() const; - virtual bool isDefault() const; + virtual blink::WebString label() const; + virtual blink::WebString language() const; + virtual blink::WebString id() const; virtual int textTrackIndex() const; private: - WebKit::WebInbandTextTrackClient* client_; - Mode mode_; + blink::WebInbandTextTrackClient* client_; Kind kind_; - WebKit::WebString label_; - WebKit::WebString language_; + blink::WebString label_; + blink::WebString language_; + blink::WebString id_; int index_; DISALLOW_COPY_AND_ASSIGN(WebInbandTextTrackImpl); }; diff --git a/chromium/content/renderer/media/webmediaplayer_delegate.h b/chromium/content/renderer/media/webmediaplayer_delegate.h index 63492f8c5f3..868abce6407 100644 --- a/chromium/content/renderer/media/webmediaplayer_delegate.h +++ b/chromium/content/renderer/media/webmediaplayer_delegate.h @@ -5,7 +5,7 @@ #ifndef CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_DELEGATE_H_ #define CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_DELEGATE_H_ -namespace WebKit { +namespace blink { class WebMediaPlayer; } namespace content { @@ -17,13 +17,13 @@ class WebMediaPlayerDelegate { WebMediaPlayerDelegate() {} // The specified player started playing media. - virtual void DidPlay(WebKit::WebMediaPlayer* player) = 0; + virtual void DidPlay(blink::WebMediaPlayer* player) = 0; // The specified player stopped playing media. - virtual void DidPause(WebKit::WebMediaPlayer* player) = 0; + virtual void DidPause(blink::WebMediaPlayer* player) = 0; // The specified player was destroyed. Do not call any methods on it. - virtual void PlayerGone(WebKit::WebMediaPlayer* player) = 0; + virtual void PlayerGone(blink::WebMediaPlayer* player) = 0; protected: virtual ~WebMediaPlayerDelegate() {} diff --git a/chromium/content/renderer/media/webmediaplayer_impl.cc b/chromium/content/renderer/media/webmediaplayer_impl.cc index 7bb1937af4e..ee637a6879a 100644 --- a/chromium/content/renderer/media/webmediaplayer_impl.cc +++ b/chromium/content/renderer/media/webmediaplayer_impl.cc @@ -13,6 +13,7 @@ #include "base/callback.h" #include "base/command_line.h" #include "base/debug/crash_logging.h" +#include "base/debug/trace_event.h" #include "base/message_loop/message_loop_proxy.h" #include "base/metrics/histogram.h" #include "base/strings/string_number_conversions.h" @@ -37,6 +38,7 @@ #include "media/base/media_log.h" #include "media/base/media_switches.h" #include "media/base/pipeline.h" +#include "media/base/text_renderer.h" #include "media/base/video_frame.h" #include "media/filters/audio_renderer_impl.h" #include "media/filters/chunk_demuxer.h" @@ -46,7 +48,7 @@ #include "media/filters/gpu_video_accelerator_factories.h" #include "media/filters/gpu_video_decoder.h" #include "media/filters/opus_audio_decoder.h" -#include "media/filters/video_renderer_base.h" +#include "media/filters/video_renderer_impl.h" #include "media/filters/vpx_video_decoder.h" #include "third_party/WebKit/public/platform/WebMediaSource.h" #include "third_party/WebKit/public/platform/WebRect.h" @@ -59,11 +61,11 @@ #include "v8/include/v8.h" #include "webkit/renderer/compositor_bindings/web_layer_impl.h" -using WebKit::WebCanvas; -using WebKit::WebMediaPlayer; -using WebKit::WebRect; -using WebKit::WebSize; -using WebKit::WebString; +using blink::WebCanvas; +using blink::WebMediaPlayer; +using blink::WebRect; +using blink::WebSize; +using blink::WebString; using media::PipelineStatus; namespace { @@ -128,11 +130,13 @@ static void LogMediaSourceError(const scoped_refptr<media::MediaLog>& media_log, } WebMediaPlayerImpl::WebMediaPlayerImpl( - WebKit::WebFrame* frame, - WebKit::WebMediaPlayerClient* client, + content::RenderView* render_view, + blink::WebFrame* frame, + blink::WebMediaPlayerClient* client, base::WeakPtr<WebMediaPlayerDelegate> delegate, const WebMediaPlayerParams& params) - : frame_(frame), + : content::RenderViewObserver(render_view), + frame_(frame), network_state_(WebMediaPlayer::NetworkStateEmpty), ready_state_(WebMediaPlayer::ReadyStateHaveNothing), main_loop_(base::MessageLoopProxy::current()), @@ -153,6 +157,8 @@ WebMediaPlayerImpl::WebMediaPlayerImpl( supports_save_(true), starting_(false), chunk_demuxer_(NULL), + current_frame_painted_(false), + frames_dropped_before_paint_(0), pending_repaint_(false), pending_size_change_(false), video_frame_provider_client_(NULL), @@ -162,6 +168,11 @@ WebMediaPlayerImpl::WebMediaPlayerImpl( pipeline_.reset(new media::Pipeline(media_loop_, media_log_.get())); + // |gpu_factories_| requires that its entry points be called on its + // |GetMessageLoop()|. Since |pipeline_| will own decoders created from the + // factories, require that their message loops are identical. + DCHECK(!gpu_factories_ || (gpu_factories_->GetMessageLoop() == media_loop_)); + // Let V8 know we started new thread if we did not do it yet. // Made separate task to avoid deletion of player currently being created. // Also, delaying GC until after player starts gets rid of starting lag -- @@ -173,10 +184,7 @@ WebMediaPlayerImpl::WebMediaPlayerImpl( base::Bind(&WebMediaPlayerImpl::IncrementExternallyAllocatedMemory, AsWeakPtr())); - // Also we want to be notified of |main_loop_| destruction. - base::MessageLoop::current()->AddDestructionObserver(this); - - if (WebKit::WebRuntimeFeatures::isLegacyEncryptedMediaEnabled()) { + if (blink::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled()) { decryptor_.reset(new ProxyDecryptor( #if defined(ENABLE_PEPPER_CDMS) client, @@ -206,11 +214,6 @@ WebMediaPlayerImpl::~WebMediaPlayerImpl() { delegate_->PlayerGone(this); Destroy(); - - // Remove destruction observer if we're being destroyed but the main thread is - // still running. - if (base::MessageLoop::current()) - base::MessageLoop::current()->RemoveDestructionObserver(this); } namespace { @@ -247,7 +250,7 @@ URLSchemeForHistogram URLScheme(const GURL& url) { } // anonymous namespace -void WebMediaPlayerImpl::load(LoadType load_type, const WebKit::WebURL& url, +void WebMediaPlayerImpl::load(LoadType load_type, const blink::WebURL& url, CORSMode cors_mode) { if (!defer_load_cb_.is_null()) { defer_load_cb_.Run(base::Bind( @@ -258,7 +261,7 @@ void WebMediaPlayerImpl::load(LoadType load_type, const WebKit::WebURL& url, } void WebMediaPlayerImpl::DoLoad(LoadType load_type, - const WebKit::WebURL& url, + const blink::WebURL& url, CORSMode cors_mode) { DCHECK(main_loop_->BelongsToCurrentThread()); @@ -305,6 +308,8 @@ void WebMediaPlayerImpl::play() { paused_ = false; pipeline_->SetPlaybackRate(playback_rate_); + if (data_source_) + data_source_->MediaIsPlaying(); media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY)); @@ -317,6 +322,8 @@ void WebMediaPlayerImpl::pause() { paused_ = true; pipeline_->SetPlaybackRate(0.0f); + if (data_source_) + data_source_->MediaIsPaused(); paused_time_ = pipeline_->GetMediaTime(); media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE)); @@ -338,6 +345,9 @@ bool WebMediaPlayerImpl::supportsSave() const { void WebMediaPlayerImpl::seek(double seconds) { DCHECK(main_loop_->BelongsToCurrentThread()); + if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata) + SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); + base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds); if (starting_ || seeking_) { @@ -384,6 +394,8 @@ void WebMediaPlayerImpl::setRate(double rate) { playback_rate_ = rate; if (!paused_) { pipeline_->SetPlaybackRate(rate); + if (data_source_) + data_source_->MediaPlaybackRateChanged(rate); } } @@ -421,12 +433,12 @@ bool WebMediaPlayerImpl::hasAudio() const { return pipeline_->HasAudio(); } -WebKit::WebSize WebMediaPlayerImpl::naturalSize() const { +blink::WebSize WebMediaPlayerImpl::naturalSize() const { DCHECK(main_loop_->BelongsToCurrentThread()); gfx::Size size; pipeline_->GetNaturalVideoSize(&size); - return WebKit::WebSize(size); + return blink::WebSize(size); } bool WebMediaPlayerImpl::paused() const { @@ -468,9 +480,9 @@ WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const { return ready_state_; } -const WebKit::WebTimeRanges& WebMediaPlayerImpl::buffered() { +const blink::WebTimeRanges& WebMediaPlayerImpl::buffered() { DCHECK(main_loop_->BelongsToCurrentThread()); - WebKit::WebTimeRanges web_ranges( + blink::WebTimeRanges web_ranges( ConvertToWebTimeRanges(pipeline_->GetBufferedTimeRanges())); buffered_.swap(web_ranges); return buffered_; @@ -515,8 +527,10 @@ void WebMediaPlayerImpl::paint(WebCanvas* canvas, scoped_refptr<media::VideoFrame> video_frame; { base::AutoLock auto_lock(lock_); + DoneWaitingForPaint(true); video_frame = current_frame_; } + TRACE_EVENT0("media", "WebMediaPlayerImpl:paint"); gfx::Rect gfx_rect(rect); skcanvas_video_renderer_.Paint(video_frame.get(), canvas, gfx_rect, alpha); } @@ -548,7 +562,12 @@ unsigned WebMediaPlayerImpl::droppedFrameCount() const { DCHECK(main_loop_->BelongsToCurrentThread()); media::PipelineStatistics stats = pipeline_->GetStatistics(); - return stats.video_frames_dropped; + + base::AutoLock auto_lock(lock_); + unsigned frames_dropped = + stats.video_frames_dropped + frames_dropped_before_paint_; + DCHECK_LE(frames_dropped, stats.video_frames_decoded); + return frames_dropped; } unsigned WebMediaPlayerImpl::audioDecodedByteCount() const { @@ -576,6 +595,9 @@ void WebMediaPlayerImpl::SetVideoFrameProviderClient( scoped_refptr<media::VideoFrame> WebMediaPlayerImpl::GetCurrentFrame() { base::AutoLock auto_lock(lock_); + DoneWaitingForPaint(true); + TRACE_EVENT_ASYNC_BEGIN0( + "media", "WebMediaPlayerImpl:compositing", this); return current_frame_; } @@ -586,10 +608,11 @@ void WebMediaPlayerImpl::PutCurrentFrame( DCHECK(frame_->view()->isAcceleratedCompositingActive()); UMA_HISTOGRAM_BOOLEAN("Media.AcceleratedCompositingActive", true); } + TRACE_EVENT_ASYNC_END0("media", "WebMediaPlayerImpl:compositing", this); } bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture( - WebKit::WebGraphicsContext3D* web_graphics_context, + blink::WebGraphicsContext3D* web_graphics_context, unsigned int texture, unsigned int level, unsigned int internal_format, @@ -602,7 +625,9 @@ bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture( video_frame = current_frame_; } - if (!video_frame.get()) + TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture"); + + if (!video_frame) return false; if (video_frame->format() != media::VideoFrame::NATIVE_TEXTURE) return false; @@ -621,7 +646,7 @@ bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture( DCHECK_EQ(static_cast<GLuint>(bound_texture), texture); } - scoped_refptr<media::VideoFrame::MailboxHolder> mailbox_holder = + media::VideoFrame::MailboxHolder* mailbox_holder = video_frame->texture_mailbox(); uint32 source_texture = web_graphics_context->createTexture(); @@ -666,7 +691,7 @@ bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture( // UMA_HISTOGRAM_COUNTS. The reason that we cannot use those macros directly is // that UMA_* macros require the names to be constant throughout the process' // lifetime. -static void EmeUMAHistogramEnumeration(const WebKit::WebString& key_system, +static void EmeUMAHistogramEnumeration(const blink::WebString& key_system, const std::string& method, int sample, int boundary_value) { @@ -676,7 +701,7 @@ static void EmeUMAHistogramEnumeration(const WebKit::WebString& key_system, base::Histogram::kUmaTargetedHistogramFlag)->Add(sample); } -static void EmeUMAHistogramCounts(const WebKit::WebString& key_system, +static void EmeUMAHistogramCounts(const blink::WebString& key_system, const std::string& method, int sample) { // Use the same parameters as UMA_HISTOGRAM_COUNTS. @@ -828,23 +853,31 @@ WebMediaPlayerImpl::CancelKeyRequestInternal( return WebMediaPlayer::MediaKeyExceptionNoError; } -void WebMediaPlayerImpl::WillDestroyCurrentMessageLoop() { +void WebMediaPlayerImpl::OnDestruct() { Destroy(); } void WebMediaPlayerImpl::Repaint() { DCHECK(main_loop_->BelongsToCurrentThread()); + TRACE_EVENT0("media", "WebMediaPlayerImpl:repaint"); bool size_changed = false; { base::AutoLock auto_lock(lock_); std::swap(pending_size_change_, size_changed); - pending_repaint_ = false; + if (pending_repaint_) { + TRACE_EVENT_ASYNC_END0( + "media", "WebMediaPlayerImpl:repaintPending", this); + pending_repaint_ = false; + } } - if (size_changed) + if (size_changed) { + TRACE_EVENT0("media", "WebMediaPlayerImpl:clientSizeChanged"); GetClient()->sizeChanged(); + } + TRACE_EVENT0("media", "WebMediaPlayerImpl:clientRepaint"); GetClient()->repaint(); } @@ -937,8 +970,7 @@ void WebMediaPlayerImpl::OnKeyAdded(const std::string& session_id) { WebString::fromUTF8(session_id)); } -void WebMediaPlayerImpl::OnNeedKey(const std::string& session_id, - const std::string& type, +void WebMediaPlayerImpl::OnNeedKey(const std::string& type, const std::vector<uint8>& init_data) { DCHECK(main_loop_->BelongsToCurrentThread()); @@ -954,26 +986,33 @@ void WebMediaPlayerImpl::OnNeedKey(const std::string& session_id, const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0]; GetClient()->keyNeeded(WebString(), - WebString::fromUTF8(session_id), + WebString(), init_data_ptr, init_data.size()); } -scoped_ptr<media::TextTrack> -WebMediaPlayerImpl::OnTextTrack(media::TextKind kind, - const std::string& label, - const std::string& language) { - typedef WebInbandTextTrackImpl::Kind webkind_t; - const webkind_t webkind = static_cast<webkind_t>(kind); - const WebKit::WebString weblabel = WebKit::WebString::fromUTF8(label); - const WebKit::WebString weblanguage = WebKit::WebString::fromUTF8(language); +void WebMediaPlayerImpl::OnAddTextTrack( + const media::TextTrackConfig& config, + const media::AddTextTrackDoneCB& done_cb) { + DCHECK(main_loop_->BelongsToCurrentThread()); + + const WebInbandTextTrackImpl::Kind web_kind = + static_cast<WebInbandTextTrackImpl::Kind>(config.kind()); + const blink::WebString web_label = + blink::WebString::fromUTF8(config.label()); + const blink::WebString web_language = + blink::WebString::fromUTF8(config.language()); + const blink::WebString web_id = + blink::WebString::fromUTF8(config.id()); + + scoped_ptr<WebInbandTextTrackImpl> web_inband_text_track( + new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id, + text_track_index_++)); - WebInbandTextTrackImpl* const text_track = - new WebInbandTextTrackImpl(webkind, weblabel, weblanguage, - text_track_index_++); + scoped_ptr<media::TextTrack> text_track( + new TextTrackImpl(main_loop_, GetClient(), web_inband_text_track.Pass())); - return scoped_ptr<media::TextTrack>(new TextTrackImpl(GetClient(), - text_track)); + done_cb.Run(text_track.Pass()); } void WebMediaPlayerImpl::OnKeyError(const std::string& session_id, @@ -987,7 +1026,7 @@ void WebMediaPlayerImpl::OnKeyError(const std::string& session_id, GetClient()->keyError( current_key_system_, WebString::fromUTF8(session_id), - static_cast<WebKit::WebMediaPlayerClient::MediaKeyErrorCode>(error_code), + static_cast<blink::WebMediaPlayerClient::MediaKeyErrorCode>(error_code), system_code); } @@ -1038,7 +1077,6 @@ void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) { void WebMediaPlayerImpl::StartPipeline() { const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); - bool increase_preroll_on_underflow = true; // Keep track if this is a MSE or non-MSE playback. UMA_HISTOGRAM_BOOLEAN("Media.MSE.Playback", @@ -1051,38 +1089,17 @@ void WebMediaPlayerImpl::StartPipeline() { demuxer_.reset(new media::FFmpegDemuxer( media_loop_, data_source_.get(), - BIND_TO_RENDER_LOOP_1(&WebMediaPlayerImpl::OnNeedKey, ""), + BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNeedKey), media_log_)); } else { DCHECK(!chunk_demuxer_); DCHECK(!data_source_); - media::AddTextTrackCB add_text_track_cb; - - if (cmd_line->HasSwitch(switches::kEnableInbandTextTracks)) { - add_text_track_cb = - base::Bind(&WebMediaPlayerImpl::OnTextTrack, base::Unretained(this)); - } - chunk_demuxer_ = new media::ChunkDemuxer( BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened), - BIND_TO_RENDER_LOOP_1(&WebMediaPlayerImpl::OnNeedKey, ""), - add_text_track_cb, + BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNeedKey), base::Bind(&LogMediaSourceError, media_log_)); demuxer_.reset(chunk_demuxer_); - -#if !defined(OS_CHROMEOS) - // Disable GpuVideoDecoder creation on platforms other than CrOS until - // they support codec config changes. - // TODO(acolwell): Remove this once http://crbug.com/151045 is fixed. - gpu_factories_ = NULL; -#endif - - // Disable preroll increases on underflow since the web application has no - // way to detect that this is happening and runs the risk of triggering - // unwanted garbage collection if it is to aggressive about appending data. - // TODO(acolwell): Remove this once http://crbug.com/144683 is fixed. - increase_preroll_on_underflow = false; } scoped_ptr<media::FilterCollection> filter_collection( @@ -1099,7 +1116,7 @@ void WebMediaPlayerImpl::StartPipeline() { // Create our audio decoders and renderer. ScopedVector<media::AudioDecoder> audio_decoders; audio_decoders.push_back(new media::FFmpegAudioDecoder(media_loop_)); - if (cmd_line->HasSwitch(switches::kEnableOpusPlayback)) { + if (!cmd_line->HasSwitch(switches::kDisableOpusPlayback)) { audio_decoders.push_back(new media::OpusAudioDecoder(media_loop_)); } @@ -1107,8 +1124,7 @@ void WebMediaPlayerImpl::StartPipeline() { new media::AudioRendererImpl(media_loop_, audio_source_provider_.get(), audio_decoders.Pass(), - set_decryptor_ready_cb, - increase_preroll_on_underflow)); + set_decryptor_ready_cb)); filter_collection->SetAudioRenderer(audio_renderer.Pass()); // Create our video decoders and renderer. @@ -1119,8 +1135,6 @@ void WebMediaPlayerImpl::StartPipeline() { new media::GpuVideoDecoder(gpu_factories_, media_log_)); } - // TODO(phajdan.jr): Remove ifdefs when libvpx with vp9 support is released - // (http://crbug.com/174287) . #if !defined(MEDIA_DISABLE_LIBVPX) video_decoders.push_back(new media::VpxVideoDecoder(media_loop_)); #endif // !defined(MEDIA_DISABLE_LIBVPX) @@ -1128,7 +1142,7 @@ void WebMediaPlayerImpl::StartPipeline() { video_decoders.push_back(new media::FFmpegVideoDecoder(media_loop_)); scoped_ptr<media::VideoRenderer> video_renderer( - new media::VideoRendererBase( + new media::VideoRendererImpl( media_loop_, video_decoders.Pass(), set_decryptor_ready_cb, @@ -1137,6 +1151,15 @@ void WebMediaPlayerImpl::StartPipeline() { true)); filter_collection->SetVideoRenderer(video_renderer.Pass()); + if (cmd_line->HasSwitch(switches::kEnableInbandTextTracks)) { + scoped_ptr<media::TextRenderer> text_renderer( + new media::TextRenderer( + media_loop_, + BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack))); + + filter_collection->SetTextRenderer(text_renderer.Pass()); + } + // ... and we're ready to go! starting_ = true; pipeline_->Start( @@ -1195,7 +1218,8 @@ void WebMediaPlayerImpl::Destroy() { // Let V8 know we are not using extra resources anymore. if (incremented_externally_allocated_memory_) { - v8::V8::AdjustAmountOfExternalAllocatedMemory(-kPlayerExtraMemory); + v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory( + -kPlayerExtraMemory); incremented_externally_allocated_memory_ = false; } @@ -1205,20 +1229,21 @@ void WebMediaPlayerImpl::Destroy() { data_source_.reset(); } -WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() { +blink::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() { DCHECK(main_loop_->BelongsToCurrentThread()); DCHECK(client_); return client_; } -WebKit::WebAudioSourceProvider* WebMediaPlayerImpl::audioSourceProvider() { +blink::WebAudioSourceProvider* WebMediaPlayerImpl::audioSourceProvider() { return audio_source_provider_.get(); } void WebMediaPlayerImpl::IncrementExternallyAllocatedMemory() { DCHECK(main_loop_->BelongsToCurrentThread()); incremented_externally_allocated_memory_ = true; - v8::V8::AdjustAmountOfExternalAllocatedMemory(kPlayerExtraMemory); + v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory( + kPlayerExtraMemory); } double WebMediaPlayerImpl::GetPipelineDuration() const { @@ -1243,20 +1268,51 @@ void WebMediaPlayerImpl::FrameReady( const scoped_refptr<media::VideoFrame>& frame) { base::AutoLock auto_lock(lock_); - if (current_frame_.get() && + if (current_frame_ && current_frame_->natural_size() != frame->natural_size() && !pending_size_change_) { pending_size_change_ = true; } + DoneWaitingForPaint(false); + current_frame_ = frame; + current_frame_painted_ = false; + TRACE_EVENT_FLOW_BEGIN0("media", "WebMediaPlayerImpl:waitingForPaint", this); if (pending_repaint_) return; + TRACE_EVENT_ASYNC_BEGIN0("media", "WebMediaPlayerImpl:repaintPending", this); pending_repaint_ = true; main_loop_->PostTask(FROM_HERE, base::Bind( &WebMediaPlayerImpl::Repaint, AsWeakPtr())); } +void WebMediaPlayerImpl::DoneWaitingForPaint(bool painting_frame) { + lock_.AssertAcquired(); + if (!current_frame_ || current_frame_painted_) + return; + + TRACE_EVENT_FLOW_END0("media", "WebMediaPlayerImpl:waitingForPaint", this); + + if (painting_frame) { + current_frame_painted_ = true; + return; + } + + // The frame wasn't painted, but we aren't waiting for a Repaint() call so + // assume that the frame wasn't painted because the video wasn't visible. + if (!pending_repaint_) + return; + + // The |current_frame_| wasn't painted, it is being replaced, and we haven't + // even gotten the chance to request a repaint for it yet. Mark it as dropped. + TRACE_EVENT0("media", "WebMediaPlayerImpl:frameDropped"); + DVLOG(1) << "Frame dropped before being painted: " + << current_frame_->GetTimestamp().InSecondsF(); + if (frames_dropped_before_paint_ < kuint32max) + frames_dropped_before_paint_++; +} + } // namespace content diff --git a/chromium/content/renderer/media/webmediaplayer_impl.h b/chromium/content/renderer/media/webmediaplayer_impl.h index 270186bbbe5..50ee39b1429 100644 --- a/chromium/content/renderer/media/webmediaplayer_impl.h +++ b/chromium/content/renderer/media/webmediaplayer_impl.h @@ -29,6 +29,7 @@ #include "base/memory/weak_ptr.h" #include "base/threading/thread.h" #include "cc/layers/video_frame_provider.h" +#include "content/public/renderer/render_view_observer.h" #include "content/renderer/media/crypto/proxy_decryptor.h" #include "media/base/audio_renderer_sink.h" #include "media/base/decryptor.h" @@ -37,15 +38,15 @@ #include "media/base/text_track.h" #include "media/filters/skcanvas_video_renderer.h" #include "skia/ext/platform_canvas.h" +#include "third_party/WebKit/public/platform/WebAudioSourceProvider.h" #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" -#include "third_party/WebKit/public/web/WebAudioSourceProvider.h" -#include "third_party/WebKit/public/web/WebMediaPlayer.h" -#include "third_party/WebKit/public/web/WebMediaPlayerClient.h" +#include "third_party/WebKit/public/platform/WebMediaPlayer.h" +#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" #include "url/gurl.h" class RenderAudioSourceProvider; -namespace WebKit { +namespace blink { class WebFrame; } @@ -55,7 +56,6 @@ class MessageLoopProxy; namespace media { class ChunkDemuxer; -class FFmpegDemuxer; class GpuVideoAcceleratorFactories; class MediaLog; } @@ -72,23 +72,25 @@ class WebMediaPlayerParams; class WebTextTrackImpl; class WebMediaPlayerImpl - : public WebKit::WebMediaPlayer, + : public blink::WebMediaPlayer, public cc::VideoFrameProvider, - public base::MessageLoop::DestructionObserver, + public content::RenderViewObserver, public base::SupportsWeakPtr<WebMediaPlayerImpl> { public: // Constructs a WebMediaPlayer implementation using Chromium's media stack. - // + // |render_view| is passed only for the purpose of registering |this| as an + // observer of it. // |delegate| may be null. WebMediaPlayerImpl( - WebKit::WebFrame* frame, - WebKit::WebMediaPlayerClient* client, + content::RenderView* render_view, + blink::WebFrame* frame, + blink::WebMediaPlayerClient* client, base::WeakPtr<WebMediaPlayerDelegate> delegate, const WebMediaPlayerParams& params); virtual ~WebMediaPlayerImpl(); virtual void load(LoadType load_type, - const WebKit::WebURL& url, + const blink::WebURL& url, CORSMode cors_mode) OVERRIDE; // Playback controls. @@ -99,13 +101,13 @@ class WebMediaPlayerImpl virtual void seek(double seconds); virtual void setRate(double rate); virtual void setVolume(double volume); - virtual void setPreload(WebKit::WebMediaPlayer::Preload preload); - virtual const WebKit::WebTimeRanges& buffered(); + virtual void setPreload(blink::WebMediaPlayer::Preload preload); + virtual const blink::WebTimeRanges& buffered(); virtual double maxTimeSeekable() const; // Methods for painting. - virtual void paint(WebKit::WebCanvas* canvas, - const WebKit::WebRect& rect, + virtual void paint(blink::WebCanvas* canvas, + const blink::WebRect& rect, unsigned char alpha); // True if the loaded media has a playable video/audio track. @@ -113,7 +115,7 @@ class WebMediaPlayerImpl virtual bool hasAudio() const; // Dimensions of the video. - virtual WebKit::WebSize naturalSize() const; + virtual blink::WebSize naturalSize() const; // Getters of playback state. virtual bool paused() const; @@ -124,8 +126,8 @@ class WebMediaPlayerImpl // Internal states of loading and network. // TODO(hclam): Ask the pipeline about the state rather than having reading // them from members which would cause race conditions. - virtual WebKit::WebMediaPlayer::NetworkState networkState() const; - virtual WebKit::WebMediaPlayer::ReadyState readyState() const; + virtual blink::WebMediaPlayer::NetworkState networkState() const; + virtual blink::WebMediaPlayer::ReadyState readyState() const; virtual bool didLoadingProgress() const; @@ -147,7 +149,7 @@ class WebMediaPlayerImpl OVERRIDE; virtual bool copyVideoTextureToPlatformTexture( - WebKit::WebGraphicsContext3D* web_graphics_context, + blink::WebGraphicsContext3D* web_graphics_context, unsigned int texture, unsigned int level, unsigned int internal_format, @@ -155,29 +157,26 @@ class WebMediaPlayerImpl bool premultiply_alpha, bool flip_y); - virtual WebKit::WebAudioSourceProvider* audioSourceProvider(); + virtual blink::WebAudioSourceProvider* audioSourceProvider(); virtual MediaKeyException generateKeyRequest( - const WebKit::WebString& key_system, + const blink::WebString& key_system, const unsigned char* init_data, unsigned init_data_length); - virtual MediaKeyException addKey(const WebKit::WebString& key_system, + virtual MediaKeyException addKey(const blink::WebString& key_system, const unsigned char* key, unsigned key_length, const unsigned char* init_data, unsigned init_data_length, - const WebKit::WebString& session_id); + const blink::WebString& session_id); virtual MediaKeyException cancelKeyRequest( - const WebKit::WebString& key_system, - const WebKit::WebString& session_id); + const blink::WebString& key_system, + const blink::WebString& session_id); - // As we are closing the tab or even the browser, |main_loop_| is destroyed - // even before this object gets destructed, so we need to know when - // |main_loop_| is being destroyed and we can stop posting repaint task - // to it. - virtual void WillDestroyCurrentMessageLoop() OVERRIDE; + // content::RenderViewObserver implementation. + virtual void OnDestruct() OVERRIDE; void Repaint(); @@ -195,18 +194,16 @@ class WebMediaPlayerImpl const std::vector<uint8>& message, const std::string& default_url); void OnNeedKey(const std::string& type, - const std::string& session_id, const std::vector<uint8>& init_data); - scoped_ptr<media::TextTrack> OnTextTrack(media::TextKind kind, - const std::string& label, - const std::string& language); + void OnAddTextTrack(const media::TextTrackConfig& config, + const media::AddTextTrackDoneCB& done_cb); void SetOpaque(bool); private: // Called after |defer_load_cb_| has decided to allow the load. If // |defer_load_cb_| is null this is called immediately. void DoLoad(LoadType load_type, - const WebKit::WebURL& url, + const blink::WebURL& url, CORSMode cors_mode); // Called after asynchronous initialization of a data source completed. @@ -220,14 +217,14 @@ class WebMediaPlayerImpl // Helpers that set the network/ready state and notifies the client if // they've changed. - void SetNetworkState(WebKit::WebMediaPlayer::NetworkState state); - void SetReadyState(WebKit::WebMediaPlayer::ReadyState state); + void SetNetworkState(blink::WebMediaPlayer::NetworkState state); + void SetReadyState(blink::WebMediaPlayer::ReadyState state); // Destroy resources held. void Destroy(); // Getter method to |client_|. - WebKit::WebMediaPlayerClient* GetClient(); + blink::WebMediaPlayerClient* GetClient(); // Lets V8 know that player uses extra resources not managed by V8. void IncrementExternallyAllocatedMemory(); @@ -235,18 +232,18 @@ class WebMediaPlayerImpl // Actually do the work for generateKeyRequest/addKey so they can easily // report results to UMA. MediaKeyException GenerateKeyRequestInternal( - const WebKit::WebString& key_system, + const blink::WebString& key_system, const unsigned char* init_data, unsigned init_data_length); - MediaKeyException AddKeyInternal(const WebKit::WebString& key_system, + MediaKeyException AddKeyInternal(const blink::WebString& key_system, const unsigned char* key, unsigned key_length, const unsigned char* init_data, unsigned init_data_length, - const WebKit::WebString& session_id); + const blink::WebString& session_id); MediaKeyException CancelKeyRequestInternal( - const WebKit::WebString& key_system, - const WebKit::WebString& session_id); + const blink::WebString& key_system, + const blink::WebString& session_id); // Gets the duration value reported by the pipeline. double GetPipelineDuration() const; @@ -254,18 +251,24 @@ class WebMediaPlayerImpl // Notifies WebKit of the duration change. void OnDurationChange(); - // Called by VideoRendererBase on its internal thread with the new frame to be + // Called by VideoRendererImpl on its internal thread with the new frame to be // painted. void FrameReady(const scoped_refptr<media::VideoFrame>& frame); - WebKit::WebFrame* frame_; + // Called when a paint or a new frame arrives to indicate that we are + // no longer waiting for |current_frame_| to be painted. + // |painting_frame| is set to true if |current_frame_| is being painted. + // False indicates |current_frame_| is being replaced with a new frame. + void DoneWaitingForPaint(bool painting_frame); + + blink::WebFrame* frame_; // TODO(hclam): get rid of these members and read from the pipeline directly. - WebKit::WebMediaPlayer::NetworkState network_state_; - WebKit::WebMediaPlayer::ReadyState ready_state_; + blink::WebMediaPlayer::NetworkState network_state_; + blink::WebMediaPlayer::ReadyState ready_state_; // Keep a list of buffered time ranges. - WebKit::WebTimeRanges buffered_; + blink::WebTimeRanges buffered_; // Message loops for posting tasks on Chrome's main thread. Also used // for DCHECKs so methods calls won't execute in the wrong thread. @@ -276,7 +279,7 @@ class WebMediaPlayerImpl // The currently selected key system. Empty string means that no key system // has been selected. - WebKit::WebString current_key_system_; + blink::WebString current_key_system_; // The LoadType passed in the |load_type| parameter of the load() call. LoadType load_type_; @@ -303,7 +306,7 @@ class WebMediaPlayerImpl bool pending_seek_; double pending_seek_seconds_; - WebKit::WebMediaPlayerClient* client_; + blink::WebMediaPlayerClient* client_; base::WeakPtr<WebMediaPlayerDelegate> delegate_; @@ -347,12 +350,15 @@ class WebMediaPlayerImpl // Video frame rendering members. // - // |lock_| protects |current_frame_| since new frames arrive on the video + // |lock_| protects |current_frame_|, |current_frame_painted_|, and + // |frames_dropped_before_paint_| since new frames arrive on the video // rendering thread, yet are accessed for rendering on either the main thread // or compositing thread depending on whether accelerated compositing is used. - base::Lock lock_; + mutable base::Lock lock_; media::SkCanvasVideoRenderer skcanvas_video_renderer_; scoped_refptr<media::VideoFrame> current_frame_; + bool current_frame_painted_; + uint32 frames_dropped_before_paint_; bool pending_repaint_; bool pending_size_change_; diff --git a/chromium/content/renderer/media/webmediaplayer_ms.cc b/chromium/content/renderer/media/webmediaplayer_ms.cc index eb28f7bc99c..3f64ff150ef 100644 --- a/chromium/content/renderer/media/webmediaplayer_ms.cc +++ b/chromium/content/renderer/media/webmediaplayer_ms.cc @@ -18,24 +18,24 @@ #include "content/renderer/media/webmediaplayer_util.h" #include "media/base/media_log.h" #include "media/base/video_frame.h" +#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" #include "third_party/WebKit/public/platform/WebRect.h" #include "third_party/WebKit/public/platform/WebSize.h" #include "third_party/WebKit/public/platform/WebURL.h" #include "third_party/WebKit/public/web/WebFrame.h" -#include "third_party/WebKit/public/web/WebMediaPlayerClient.h" #include "third_party/WebKit/public/web/WebView.h" #include "webkit/renderer/compositor_bindings/web_layer_impl.h" -using WebKit::WebCanvas; -using WebKit::WebMediaPlayer; -using WebKit::WebRect; -using WebKit::WebSize; +using blink::WebCanvas; +using blink::WebMediaPlayer; +using blink::WebRect; +using blink::WebSize; namespace content { WebMediaPlayerMS::WebMediaPlayerMS( - WebKit::WebFrame* frame, - WebKit::WebMediaPlayerClient* client, + blink::WebFrame* frame, + blink::WebMediaPlayerClient* client, base::WeakPtr<WebMediaPlayerDelegate> delegate, MediaStreamClient* media_stream_client, media::MediaLog* media_log) @@ -82,7 +82,7 @@ WebMediaPlayerMS::~WebMediaPlayerMS() { } void WebMediaPlayerMS::load(LoadType load_type, - const WebKit::WebURL& url, + const blink::WebURL& url, CORSMode cors_mode) { DVLOG(1) << "WebMediaPlayerMS::load"; DCHECK(thread_checker_.CalledOnValidThread()); @@ -204,14 +204,14 @@ bool WebMediaPlayerMS::hasAudio() const { return (audio_renderer_.get() != NULL); } -WebKit::WebSize WebMediaPlayerMS::naturalSize() const { +blink::WebSize WebMediaPlayerMS::naturalSize() const { DCHECK(thread_checker_.CalledOnValidThread()); gfx::Size size; if (current_frame_.get()) size = current_frame_->natural_size(); DVLOG(3) << "WebMediaPlayerMS::naturalSize, " << size.ToString(); - return WebKit::WebSize(size); + return blink::WebSize(size); } bool WebMediaPlayerMS::paused() const { @@ -251,7 +251,7 @@ WebMediaPlayer::ReadyState WebMediaPlayerMS::readyState() const { return ready_state_; } -const WebKit::WebTimeRanges& WebMediaPlayerMS::buffered() { +const blink::WebTimeRanges& WebMediaPlayerMS::buffered() { DCHECK(thread_checker_.CalledOnValidThread()); return buffered_; } @@ -423,7 +423,7 @@ void WebMediaPlayerMS::SetReadyState(WebMediaPlayer::ReadyState state) { GetClient()->readyStateChanged(); } -WebKit::WebMediaPlayerClient* WebMediaPlayerMS::GetClient() { +blink::WebMediaPlayerClient* WebMediaPlayerMS::GetClient() { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(client_); return client_; diff --git a/chromium/content/renderer/media/webmediaplayer_ms.h b/chromium/content/renderer/media/webmediaplayer_ms.h index 1ed75a392d6..8fa5ef5e1e2 100644 --- a/chromium/content/renderer/media/webmediaplayer_ms.h +++ b/chromium/content/renderer/media/webmediaplayer_ms.h @@ -13,10 +13,10 @@ #include "cc/layers/video_frame_provider.h" #include "media/filters/skcanvas_video_renderer.h" #include "skia/ext/platform_canvas.h" -#include "third_party/WebKit/public/web/WebMediaPlayer.h" +#include "third_party/WebKit/public/platform/WebMediaPlayer.h" #include "url/gurl.h" -namespace WebKit { +namespace blink { class WebFrame; class WebMediaPlayerClient; } @@ -47,24 +47,24 @@ class WebMediaPlayerDelegate; // AudioPlayer // plays audio streams. // -// WebKit::WebMediaPlayerClient +// blink::WebMediaPlayerClient // WebKit client of this media player object. class WebMediaPlayerMS - : public WebKit::WebMediaPlayer, + : public blink::WebMediaPlayer, public cc::VideoFrameProvider, public base::SupportsWeakPtr<WebMediaPlayerMS> { public: // Construct a WebMediaPlayerMS with reference to the client, and // a MediaStreamClient which provides VideoFrameProvider. - WebMediaPlayerMS(WebKit::WebFrame* frame, - WebKit::WebMediaPlayerClient* client, + WebMediaPlayerMS(blink::WebFrame* frame, + blink::WebMediaPlayerClient* client, base::WeakPtr<WebMediaPlayerDelegate> delegate, MediaStreamClient* media_stream_client, media::MediaLog* media_log); virtual ~WebMediaPlayerMS(); virtual void load(LoadType load_type, - const WebKit::WebURL& url, + const blink::WebURL& url, CORSMode cors_mode) OVERRIDE; // Playback controls. @@ -75,13 +75,13 @@ class WebMediaPlayerMS virtual void seek(double seconds); virtual void setRate(double rate); virtual void setVolume(double volume); - virtual void setPreload(WebKit::WebMediaPlayer::Preload preload) OVERRIDE; - virtual const WebKit::WebTimeRanges& buffered() OVERRIDE; + virtual void setPreload(blink::WebMediaPlayer::Preload preload) OVERRIDE; + virtual const blink::WebTimeRanges& buffered() OVERRIDE; virtual double maxTimeSeekable() const; // Methods for painting. - virtual void paint(WebKit::WebCanvas* canvas, - const WebKit::WebRect& rect, + virtual void paint(blink::WebCanvas* canvas, + const blink::WebRect& rect, unsigned char alpha) OVERRIDE; // True if the loaded media has a playable video/audio track. @@ -89,7 +89,7 @@ class WebMediaPlayerMS virtual bool hasAudio() const OVERRIDE; // Dimensions of the video. - virtual WebKit::WebSize naturalSize() const OVERRIDE; + virtual blink::WebSize naturalSize() const OVERRIDE; // Getters of playback state. virtual bool paused() const OVERRIDE; @@ -98,8 +98,8 @@ class WebMediaPlayerMS virtual double currentTime() const; // Internal states of loading and network. - virtual WebKit::WebMediaPlayer::NetworkState networkState() const OVERRIDE; - virtual WebKit::WebMediaPlayer::ReadyState readyState() const OVERRIDE; + virtual blink::WebMediaPlayer::NetworkState networkState() const OVERRIDE; + virtual blink::WebMediaPlayer::ReadyState readyState() const OVERRIDE; virtual bool didLoadingProgress() const OVERRIDE; @@ -131,23 +131,23 @@ class WebMediaPlayerMS // Helpers that set the network/ready state and notifies the client if // they've changed. - void SetNetworkState(WebKit::WebMediaPlayer::NetworkState state); - void SetReadyState(WebKit::WebMediaPlayer::ReadyState state); + void SetNetworkState(blink::WebMediaPlayer::NetworkState state); + void SetReadyState(blink::WebMediaPlayer::ReadyState state); // Getter method to |client_|. - WebKit::WebMediaPlayerClient* GetClient(); + blink::WebMediaPlayerClient* GetClient(); - WebKit::WebFrame* frame_; + blink::WebFrame* frame_; - WebKit::WebMediaPlayer::NetworkState network_state_; - WebKit::WebMediaPlayer::ReadyState ready_state_; + blink::WebMediaPlayer::NetworkState network_state_; + blink::WebMediaPlayer::ReadyState ready_state_; - WebKit::WebTimeRanges buffered_; + blink::WebTimeRanges buffered_; // Used for DCHECKs to ensure methods calls executed in the correct thread. base::ThreadChecker thread_checker_; - WebKit::WebMediaPlayerClient* client_; + blink::WebMediaPlayerClient* client_; base::WeakPtr<WebMediaPlayerDelegate> delegate_; diff --git a/chromium/content/renderer/media/webmediaplayer_util.cc b/chromium/content/renderer/media/webmediaplayer_util.cc index 741239addcc..a245f038b0a 100644 --- a/chromium/content/renderer/media/webmediaplayer_util.cc +++ b/chromium/content/renderer/media/webmediaplayer_util.cc @@ -7,7 +7,7 @@ #include <math.h> #include "media/base/media_keys.h" -#include "third_party/WebKit/public/web/WebMediaPlayerClient.h" +#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" namespace content { @@ -15,7 +15,7 @@ namespace content { #define COMPILE_ASSERT_MATCHING_ENUM(name) \ COMPILE_ASSERT( \ - static_cast<int>(WebKit::WebMediaPlayerClient::MediaKeyErrorCode ## name) == \ + static_cast<int>(blink::WebMediaPlayerClient::MediaKeyErrorCode ## name) == \ static_cast<int>(media::MediaKeys::k ## name ## Error), \ mismatching_enums) COMPILE_ASSERT_MATCHING_ENUM(Unknown); @@ -28,9 +28,9 @@ base::TimeDelta ConvertSecondsToTimestamp(double seconds) { microseconds > 0 ? microseconds + 0.5 : ceil(microseconds - 0.5)); } -WebKit::WebTimeRanges ConvertToWebTimeRanges( +blink::WebTimeRanges ConvertToWebTimeRanges( const media::Ranges<base::TimeDelta>& ranges) { - WebKit::WebTimeRanges result(ranges.size()); + blink::WebTimeRanges result(ranges.size()); for (size_t i = 0; i < ranges.size(); i++) { result[i].start = ranges.start(i).InSecondsF(); result[i].end = ranges.end(i).InSecondsF(); @@ -38,14 +38,14 @@ WebKit::WebTimeRanges ConvertToWebTimeRanges( return result; } -WebKit::WebMediaPlayer::NetworkState PipelineErrorToNetworkState( +blink::WebMediaPlayer::NetworkState PipelineErrorToNetworkState( media::PipelineStatus error) { DCHECK_NE(error, media::PIPELINE_OK); switch (error) { case media::PIPELINE_ERROR_NETWORK: case media::PIPELINE_ERROR_READ: - return WebKit::WebMediaPlayer::NetworkStateNetworkError; + return blink::WebMediaPlayer::NetworkStateNetworkError; // TODO(vrk): Because OnPipelineInitialize() directly reports the // NetworkStateFormatError instead of calling OnPipelineError(), I believe @@ -57,24 +57,24 @@ WebKit::WebMediaPlayer::NetworkState PipelineErrorToNetworkState( case media::DEMUXER_ERROR_COULD_NOT_PARSE: case media::DEMUXER_ERROR_NO_SUPPORTED_STREAMS: case media::DECODER_ERROR_NOT_SUPPORTED: - return WebKit::WebMediaPlayer::NetworkStateFormatError; + return blink::WebMediaPlayer::NetworkStateFormatError; case media::PIPELINE_ERROR_DECODE: case media::PIPELINE_ERROR_ABORT: case media::PIPELINE_ERROR_OPERATION_PENDING: case media::PIPELINE_ERROR_INVALID_STATE: - return WebKit::WebMediaPlayer::NetworkStateDecodeError; + return blink::WebMediaPlayer::NetworkStateDecodeError; case media::PIPELINE_ERROR_DECRYPT: // TODO(xhwang): Change to use NetworkStateDecryptError once it's added in // Webkit (see http://crbug.com/124486). - return WebKit::WebMediaPlayer::NetworkStateDecodeError; + return blink::WebMediaPlayer::NetworkStateDecodeError; case media::PIPELINE_OK: case media::PIPELINE_STATUS_MAX: NOTREACHED() << "Unexpected status! " << error; } - return WebKit::WebMediaPlayer::NetworkStateFormatError; + return blink::WebMediaPlayer::NetworkStateFormatError; } } // namespace content diff --git a/chromium/content/renderer/media/webmediaplayer_util.h b/chromium/content/renderer/media/webmediaplayer_util.h index 007980c7d09..3c2dacc6eab 100644 --- a/chromium/content/renderer/media/webmediaplayer_util.h +++ b/chromium/content/renderer/media/webmediaplayer_util.h @@ -8,8 +8,8 @@ #include "base/time/time.h" #include "media/base/pipeline_status.h" #include "media/base/ranges.h" +#include "third_party/WebKit/public/platform/WebMediaPlayer.h" #include "third_party/WebKit/public/platform/WebTimeRange.h" -#include "third_party/WebKit/public/web/WebMediaPlayer.h" namespace content { @@ -19,10 +19,10 @@ namespace content { // Refer to https://bugs.webkit.org/show_bug.cgi?id=52697 for details. base::TimeDelta ConvertSecondsToTimestamp(double seconds); -WebKit::WebTimeRanges ConvertToWebTimeRanges( +blink::WebTimeRanges ConvertToWebTimeRanges( const media::Ranges<base::TimeDelta>& ranges); -WebKit::WebMediaPlayer::NetworkState PipelineErrorToNetworkState( +blink::WebMediaPlayer::NetworkState PipelineErrorToNetworkState( media::PipelineStatus error); } // namespace content diff --git a/chromium/content/renderer/media/webmediasource_impl.cc b/chromium/content/renderer/media/webmediasource_impl.cc index a420f9d1b63..d1a2dfbc9ed 100644 --- a/chromium/content/renderer/media/webmediasource_impl.cc +++ b/chromium/content/renderer/media/webmediasource_impl.cc @@ -10,8 +10,8 @@ #include "third_party/WebKit/public/platform/WebCString.h" #include "third_party/WebKit/public/platform/WebString.h" -using ::WebKit::WebString; -using ::WebKit::WebMediaSource; +using ::blink::WebString; +using ::blink::WebMediaSource; namespace content { @@ -34,9 +34,9 @@ WebMediaSourceImpl::WebMediaSourceImpl( WebMediaSourceImpl::~WebMediaSourceImpl() {} WebMediaSource::AddStatus WebMediaSourceImpl::addSourceBuffer( - const WebKit::WebString& type, - const WebKit::WebVector<WebKit::WebString>& codecs, - WebKit::WebSourceBuffer** source_buffer) { + const blink::WebString& type, + const blink::WebVector<blink::WebString>& codecs, + blink::WebSourceBuffer** source_buffer) { std::string id = base::GenerateGUID(); std::vector<std::string> new_codecs(codecs.size()); for (size_t i = 0; i < codecs.size(); ++i) diff --git a/chromium/content/renderer/media/webmediasource_impl.h b/chromium/content/renderer/media/webmediasource_impl.h index 8d679943190..42d5eef9405 100644 --- a/chromium/content/renderer/media/webmediasource_impl.h +++ b/chromium/content/renderer/media/webmediasource_impl.h @@ -17,16 +17,16 @@ class ChunkDemuxer; namespace content { -class WebMediaSourceImpl : public WebKit::WebMediaSource { +class WebMediaSourceImpl : public blink::WebMediaSource { public: WebMediaSourceImpl(media::ChunkDemuxer* demuxer, media::LogCB log_cb); virtual ~WebMediaSourceImpl(); - // WebKit::WebMediaSource implementation. + // blink::WebMediaSource implementation. virtual AddStatus addSourceBuffer( - const WebKit::WebString& type, - const WebKit::WebVector<WebKit::WebString>& codecs, - WebKit::WebSourceBuffer** source_buffer) OVERRIDE; + const blink::WebString& type, + const blink::WebVector<blink::WebString>& codecs, + blink::WebSourceBuffer** source_buffer) OVERRIDE; virtual double duration() OVERRIDE; virtual void setDuration(double duration) OVERRIDE; virtual void markEndOfStream(EndOfStreamStatus status) OVERRIDE; diff --git a/chromium/content/renderer/media/webrtc/OWNERS b/chromium/content/renderer/media/webrtc/OWNERS new file mode 100644 index 00000000000..dbd443f2610 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/OWNERS @@ -0,0 +1,10 @@ +# Piranha Plant members. +xians@chromium.org +perkj@chromium.org +hclam@chromium.org +joi@chromium.org + +# To be able to roll new libjingle releases. +ronghuawu@chromium.org +mallinath@chromium.org +sergeyu@chromium.org
\ No newline at end of file diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_sink_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_video_sink_adapter.cc new file mode 100644 index 00000000000..652dec0c846 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/webrtc_video_sink_adapter.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/renderer/media/webrtc/webrtc_video_sink_adapter.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/message_loop/message_loop_proxy.h" +#include "content/renderer/media/native_handle_impl.h" +#include "media/base/video_frame.h" +#include "media/base/video_util.h" +#include "third_party/libjingle/source/talk/media/base/videoframe.h" +#include "third_party/WebKit/public/platform/WebMediaStreamSource.h" +#include "ui/gfx/size.h" + +using media::CopyYPlane; +using media::CopyUPlane; +using media::CopyVPlane; + +namespace content { + +WebRtcVideoSinkAdapter::WebRtcVideoSinkAdapter( + webrtc::VideoTrackInterface* video_track, + MediaStreamVideoSink* sink) + : message_loop_proxy_(base::MessageLoopProxy::current()), + sink_(sink), + video_track_(video_track), + state_(video_track->state()), + track_enabled_(video_track->enabled()) { + DCHECK(sink); + video_track_->AddRenderer(this); + video_track_->RegisterObserver(this); + DVLOG(1) << "WebRtcVideoSinkAdapter"; +} + +WebRtcVideoSinkAdapter::~WebRtcVideoSinkAdapter() { + video_track_->RemoveRenderer(this); + video_track_->UnregisterObserver(this); + DVLOG(1) << "~WebRtcVideoSinkAdapter"; +} + +void WebRtcVideoSinkAdapter::SetSize(int width, int height) { + NOTIMPLEMENTED(); +} + +void WebRtcVideoSinkAdapter::RenderFrame(const cricket::VideoFrame* frame) { + base::TimeDelta timestamp = base::TimeDelta::FromMilliseconds( + frame->GetTimeStamp() / talk_base::kNumNanosecsPerMillisec); + + scoped_refptr<media::VideoFrame> video_frame; + if (frame->GetNativeHandle() != NULL) { + NativeHandleImpl* handle = + static_cast<NativeHandleImpl*>(frame->GetNativeHandle()); + video_frame = static_cast<media::VideoFrame*>(handle->GetHandle()); + video_frame->SetTimestamp(timestamp); + } else { + gfx::Size size(frame->GetWidth(), frame->GetHeight()); + video_frame = media::VideoFrame::CreateFrame( + media::VideoFrame::YV12, size, gfx::Rect(size), size, timestamp); + + // Aspect ratio unsupported; DCHECK when there are non-square pixels. + DCHECK_EQ(frame->GetPixelWidth(), 1u); + DCHECK_EQ(frame->GetPixelHeight(), 1u); + + int y_rows = frame->GetHeight(); + int uv_rows = frame->GetHeight() / 2; // YV12 format. + CopyYPlane( + frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame.get()); + CopyUPlane( + frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame.get()); + CopyVPlane( + frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame.get()); + } + + message_loop_proxy_->PostTask( + FROM_HERE, base::Bind(&WebRtcVideoSinkAdapter::DoRenderFrameOnMainThread, + AsWeakPtr(), video_frame)); +} + +void WebRtcVideoSinkAdapter::OnChanged() { + DCHECK(message_loop_proxy_->BelongsToCurrentThread()); + + // TODO(perkj): OnChanged belongs to the base class of WebRtcVideoSinkAdapter + // common for both webrtc audio and video. + webrtc::MediaStreamTrackInterface::TrackState state = video_track_->state(); + if (state != state_) { + state_ = state; + switch (state) { + case webrtc::MediaStreamTrackInterface::kInitializing: + // Ignore the kInitializing state since there is no match in + // WebMediaStreamSource::ReadyState. + break; + case webrtc::MediaStreamTrackInterface::kLive: + sink_->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateLive); + break; + case webrtc::MediaStreamTrackInterface::kEnded: + sink_->OnReadyStateChanged( + blink::WebMediaStreamSource::ReadyStateEnded); + break; + default: + NOTREACHED(); + break; + } + } + if (track_enabled_ != video_track_->enabled()) { + track_enabled_ = video_track_->enabled(); + sink_->OnEnabledChanged(track_enabled_); + } +} + +void WebRtcVideoSinkAdapter::DoRenderFrameOnMainThread( + scoped_refptr<media::VideoFrame> video_frame) { + DCHECK(message_loop_proxy_->BelongsToCurrentThread()); + sink_->OnVideoFrame(video_frame); +} + +} // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_sink_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_video_sink_adapter.h new file mode 100644 index 00000000000..2f75a95ef35 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/webrtc_video_sink_adapter.h @@ -0,0 +1,60 @@ +// 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_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_SINK_ADAPTER_H_ +#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_SINK_ADAPTER_H_ + +#include "base/memory/weak_ptr.h" +#include "content/common/content_export.h" +#include "content/public/renderer/media_stream_video_sink.h" +#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" + +namespace base { +class MessageLoopProxy; +} + +namespace content { + +// WebRtcVideoSinkAdapter acts as the middle man between a +// webrtc:::VideoTrackInterface and a content::MediaStreamVideoSink. +// It is responsible for translating video data from a libjingle video type +// to a chrome video type. +class CONTENT_EXPORT WebRtcVideoSinkAdapter + : NON_EXPORTED_BASE(public webrtc::VideoRendererInterface), + NON_EXPORTED_BASE(public webrtc::ObserverInterface), + public base::SupportsWeakPtr<WebRtcVideoSinkAdapter> { + public: + WebRtcVideoSinkAdapter(webrtc::VideoTrackInterface* video_track, + MediaStreamVideoSink* sink); + virtual ~WebRtcVideoSinkAdapter(); + + MediaStreamVideoSink* sink() const { return sink_; } + + protected: + // webrtc::VideoRendererInterface implementation. May be called on + // a different thread. + virtual void SetSize(int width, int height) OVERRIDE; + virtual void RenderFrame(const cricket::VideoFrame* frame) OVERRIDE; + + // webrtc::ObserverInterface implementation. + // TODO(perkj): OnChanged should be implemented on a common base class used + // for both WebRtc Audio and Video tracks. + virtual void OnChanged() OVERRIDE; + + private: + void DoRenderFrameOnMainThread(scoped_refptr<media::VideoFrame> video_frame); + + scoped_refptr<base::MessageLoopProxy> message_loop_proxy_; + MediaStreamVideoSink* sink_; + // The video track the renderer is connected to. + scoped_refptr<webrtc::VideoTrackInterface> video_track_; + webrtc::MediaStreamTrackInterface::TrackState state_; + bool track_enabled_; + + DISALLOW_COPY_AND_ASSIGN(WebRtcVideoSinkAdapter); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_SINK_ADAPTER_H_ diff --git a/chromium/content/renderer/media/webrtc_audio_capturer.cc b/chromium/content/renderer/media/webrtc_audio_capturer.cc index c5127c191ad..391e7d77f59 100644 --- a/chromium/content/renderer/media/webrtc_audio_capturer.cc +++ b/chromium/content/renderer/media/webrtc_audio_capturer.cc @@ -8,11 +8,12 @@ #include "base/logging.h" #include "base/metrics/histogram.h" #include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "content/child/child_process.h" #include "content/renderer/media/audio_device_factory.h" #include "content/renderer/media/webrtc_audio_device_impl.h" #include "content/renderer/media/webrtc_local_audio_track.h" -#include "media/audio/audio_util.h" +#include "content/renderer/media/webrtc_logging.h" #include "media/audio/sample_rates.h" namespace content { @@ -56,10 +57,10 @@ class WebRtcAudioCapturer::TrackOwner } } - void SetCaptureFormat(const media::AudioParameters& params) { + void OnSetFormat(const media::AudioParameters& params) { base::AutoLock lock(lock_); if (delegate_) - delegate_->SetCaptureFormat(params); + delegate_->OnSetFormat(params); } void Reset() { @@ -67,12 +68,22 @@ class WebRtcAudioCapturer::TrackOwner delegate_ = NULL; } + void Stop() { + base::AutoLock lock(lock_); + DCHECK(delegate_); + + // This can be reentrant so reset |delegate_| before calling out. + WebRtcLocalAudioTrack* temp = delegate_; + delegate_ = NULL; + temp->Stop(); + } + // Wrapper which allows to use std::find_if() when adding and removing // sinks to/from the list. struct TrackWrapper { TrackWrapper(WebRtcLocalAudioTrack* track) : track_(track) {} bool operator()( - const scoped_refptr<WebRtcAudioCapturer::TrackOwner>& owner) { + const scoped_refptr<WebRtcAudioCapturer::TrackOwner>& owner) const { return owner->IsEqual(track_); } WebRtcLocalAudioTrack* track_; @@ -103,7 +114,8 @@ scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer() { } void WebRtcAudioCapturer::Reconfigure(int sample_rate, - media::ChannelLayout channel_layout) { + media::ChannelLayout channel_layout, + int effects) { DCHECK(thread_checker_.CalledOnValidThread()); int buffer_size = GetBufferSize(sample_rate); DVLOG(1) << "Using WebRTC input buffer size: " << buffer_size; @@ -113,40 +125,52 @@ void WebRtcAudioCapturer::Reconfigure(int sample_rate, // bits_per_sample is always 16 for now. int bits_per_sample = 16; - media::AudioParameters params(format, channel_layout, sample_rate, - bits_per_sample, buffer_size); - - TrackList tracks; + media::AudioParameters params(format, channel_layout, 0, sample_rate, + bits_per_sample, buffer_size, effects); { base::AutoLock auto_lock(lock_); - tracks = tracks_; params_ = params; - } - // Tell all audio_tracks which format we use. - for (TrackList::const_iterator it = tracks.begin(); - it != tracks.end(); ++it) - (*it)->SetCaptureFormat(params); + // Notify all tracks about the new format. + tracks_.TagAll(); + } } bool WebRtcAudioCapturer::Initialize(int render_view_id, - media::ChannelLayout channel_layout, - int sample_rate, - int buffer_size, - int session_id, - const std::string& device_id) { + media::ChannelLayout channel_layout, + int sample_rate, + int buffer_size, + int session_id, + const std::string& device_id, + int paired_output_sample_rate, + int paired_output_frames_per_buffer, + int effects) { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK_GE(render_view_id, 0); DVLOG(1) << "WebRtcAudioCapturer::Initialize()"; DVLOG(1) << "Audio input hardware channel layout: " << channel_layout; UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout", channel_layout, media::CHANNEL_LAYOUT_MAX); + WebRtcLogMessage(base::StringPrintf( + "WAC::Initialize. render_view_id=%d" + ", channel_layout=%d, sample_rate=%d, buffer_size=%d" + ", session_id=%d, paired_output_sample_rate=%d" + ", paired_output_frames_per_buffer=%d", + render_view_id, + channel_layout, + sample_rate, + buffer_size, + session_id, + paired_output_sample_rate, + paired_output_frames_per_buffer)); + render_view_id_ = render_view_id; session_id_ = session_id; device_id_ = device_id; hardware_buffer_size_ = buffer_size; + output_sample_rate_ = paired_output_sample_rate; + output_frames_per_buffer_= paired_output_frames_per_buffer; if (render_view_id == -1) { // Return true here to allow injecting a new source via SetCapturerSource() @@ -181,35 +205,33 @@ bool WebRtcAudioCapturer::Initialize(int render_view_id, return false; } - Reconfigure(sample_rate, channel_layout); - // Create and configure the default audio capturing source. The |source_| // will be overwritten if an external client later calls SetCapturerSource() // providing an alternative media::AudioCapturerSource. SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id), channel_layout, - static_cast<float>(sample_rate)); + static_cast<float>(sample_rate), + effects); return true; } WebRtcAudioCapturer::WebRtcAudioCapturer() - : source_(NULL), - running_(false), - agc_is_enabled_(false), + : running_(false), render_view_id_(-1), hardware_buffer_size_(0), session_id_(0), volume_(0), - source_provider_(new WebRtcLocalAudioSourceProvider()), - peer_connection_mode_(false) { - DCHECK(source_provider_.get()); + peer_connection_mode_(false), + output_sample_rate_(0), + output_frames_per_buffer_(0), + key_pressed_(false) { DVLOG(1) << "WebRtcAudioCapturer::WebRtcAudioCapturer()"; } WebRtcAudioCapturer::~WebRtcAudioCapturer() { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(tracks_.empty()); + DCHECK(tracks_.IsEmpty()); DCHECK(!running_); DVLOG(1) << "WebRtcAudioCapturer::~WebRtcAudioCapturer()"; } @@ -218,17 +240,21 @@ void WebRtcAudioCapturer::AddTrack(WebRtcLocalAudioTrack* track) { DCHECK(track); DVLOG(1) << "WebRtcAudioCapturer::AddTrack()"; + { + base::AutoLock auto_lock(lock_); + // Verify that |track| is not already added to the list. + DCHECK(!tracks_.Contains(TrackOwner::TrackWrapper(track))); + + // Add with a tag, so we remember to call OnSetFormat() on the new + // track. + scoped_refptr<TrackOwner> track_owner(new TrackOwner(track)); + tracks_.AddAndTag(track_owner); + } + // Start the source if the first audio track is connected to the capturer. // Start() will do nothing if the capturer has already been started. Start(); - base::AutoLock auto_lock(lock_); - // Verify that |track| is not already added to the list. - DCHECK(std::find_if(tracks_.begin(), tracks_.end(), - TrackOwner::TrackWrapper(track)) == tracks_.end()); - - track->SetCaptureFormat(params_); - tracks_.push_back(new WebRtcAudioCapturer::TrackOwner(track)); } void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) { @@ -237,20 +263,18 @@ void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) { bool stop_source = false; { base::AutoLock auto_lock(lock_); - // Get iterator to the first element for which WrapsSink(track) returns - // true. - TrackList::iterator it = std::find_if( - tracks_.begin(), tracks_.end(), TrackOwner::TrackWrapper(track)); - if (it != tracks_.end()) { - // Clear the delegate to ensure that no more capture callbacks will - // be sent to this sink. Also avoids a possible crash which can happen - // if this method is called while capturing is active. - (*it)->Reset(); - tracks_.erase(it); - } + + scoped_refptr<TrackOwner> removed_item = + tracks_.Remove(TrackOwner::TrackWrapper(track)); + + // Clear the delegate to ensure that no more capture callbacks will + // be sent to this sink. Also avoids a possible crash which can happen + // if this method is called while capturing is active. + if (removed_item.get()) + removed_item->Reset(); // Stop the source if the last audio track is going away. - stop_source = tracks_.empty(); + stop_source = tracks_.IsEmpty(); } if (stop_source) @@ -260,7 +284,8 @@ void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) { void WebRtcAudioCapturer::SetCapturerSource( const scoped_refptr<media::AudioCapturerSource>& source, media::ChannelLayout channel_layout, - float sample_rate) { + float sample_rate, + int effects) { DCHECK(thread_checker_.CalledOnValidThread()); DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << "," << "sample_rate=" << sample_rate << ")"; @@ -286,11 +311,10 @@ void WebRtcAudioCapturer::SetCapturerSource( // Dispatch the new parameters both to the sink(s) and to the new source. // The idea is to get rid of any dependency of the microphone parameters // which would normally be used by default. - Reconfigure(sample_rate, channel_layout); + Reconfigure(sample_rate, channel_layout, effects); // Make sure to grab the new parameters in case they were reconfigured. media::AudioParameters params = audio_parameters(); - source_provider_->Initialize(params); if (source.get()) source->Initialize(params, this, session_id_); @@ -317,43 +341,53 @@ void WebRtcAudioCapturer::EnablePeerConnectionMode() { render_view_id = render_view_id_; } + // Do nothing if the current buffer size is the WebRtc native buffer size. + media::AudioParameters params = audio_parameters(); + if (GetBufferSize(params.sample_rate()) == params.frames_per_buffer()) + return; + // Create a new audio stream as source which will open the hardware using // WebRtc native buffer size. - media::AudioParameters params = audio_parameters(); SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id), params.channel_layout(), - static_cast<float>(params.sample_rate())); + static_cast<float>(params.sample_rate()), + params.effects()); } void WebRtcAudioCapturer::Start() { DVLOG(1) << "WebRtcAudioCapturer::Start()"; base::AutoLock auto_lock(lock_); - if (running_) + if (running_ || !source_) return; // Start the data source, i.e., start capturing data from the current source. - // Note that, the source does not have to be a microphone. - if (source_.get()) { - // We need to set the AGC control before starting the stream. - source_->SetAutomaticGainControl(agc_is_enabled_); - source_->Start(); - } - + // We need to set the AGC control before starting the stream. + source_->SetAutomaticGainControl(true); + source_->Start(); running_ = true; } void WebRtcAudioCapturer::Stop() { DVLOG(1) << "WebRtcAudioCapturer::Stop()"; scoped_refptr<media::AudioCapturerSource> source; + TrackList::ItemList tracks; { base::AutoLock auto_lock(lock_); if (!running_) return; source = source_; + tracks = tracks_.Items(); + tracks_.Clear(); running_ = false; } + for (TrackList::ItemList::const_iterator it = tracks.begin(); + it != tracks.end(); + ++it) { + (*it)->Stop(); + } + if (source.get()) source->Stop(); } @@ -376,16 +410,6 @@ int WebRtcAudioCapturer::MaxVolume() const { return WebRtcAudioDeviceImpl::kMaxVolumeLevel; } -void WebRtcAudioCapturer::SetAutomaticGainControl(bool enable) { - base::AutoLock auto_lock(lock_); - // Store the setting since SetAutomaticGainControl() can be called before - // Initialize(), in this case stored setting will be applied in Start(). - agc_is_enabled_ = enable; - - if (source_.get()) - source_->SetAutomaticGainControl(enable); -} - void WebRtcAudioCapturer::Capture(media::AudioBus* audio_source, int audio_delay_milliseconds, double volume, @@ -404,8 +428,10 @@ void WebRtcAudioCapturer::Capture(media::AudioBus* audio_source, DCHECK_LE(volume, 1.6); #endif - TrackList tracks; + TrackList::ItemList tracks; + TrackList::ItemList tracks_to_notify_format; int current_volume = 0; + media::AudioParameters params; { base::AutoLock auto_lock(lock_); if (!running_) @@ -416,16 +442,26 @@ void WebRtcAudioCapturer::Capture(media::AudioBus* audio_source, // volume is higher than 255. volume_ = static_cast<int>((volume * MaxVolume()) + 0.5); current_volume = volume_; - tracks = tracks_; + audio_delay_ = base::TimeDelta::FromMilliseconds(audio_delay_milliseconds); + key_pressed_ = key_pressed; + tracks = tracks_.Items(); + tracks_.RetrieveAndClearTags(&tracks_to_notify_format); + + CHECK(params_.IsValid()); + CHECK_EQ(audio_source->channels(), params_.channels()); + CHECK_EQ(audio_source->frames(), params_.frames_per_buffer()); + params = params_; } - // Deliver captured data to source provider, which stores the data into FIFO - // for WebAudio to fetch. - source_provider_->DeliverData(audio_source, audio_delay_milliseconds, - current_volume, key_pressed); + // Notify the tracks on when the format changes. This will do nothing if + // |tracks_to_notify_format| is empty. + for (TrackList::ItemList::const_iterator it = tracks_to_notify_format.begin(); + it != tracks_to_notify_format.end(); ++it) { + (*it)->OnSetFormat(params); + } // Feed the data to the tracks. - for (TrackList::const_iterator it = tracks.begin(); + for (TrackList::ItemList::const_iterator it = tracks.begin(); it != tracks.end(); ++it) { (*it)->Capture(audio_source, audio_delay_milliseconds, @@ -442,6 +478,21 @@ media::AudioParameters WebRtcAudioCapturer::audio_parameters() const { return params_; } +bool WebRtcAudioCapturer::GetPairedOutputParameters( + int* session_id, + int* output_sample_rate, + int* output_frames_per_buffer) const { + // Don't set output parameters unless all of them are valid. + if (session_id_ <= 0 || !output_sample_rate_ || !output_frames_per_buffer_) + return false; + + *session_id = session_id_; + *output_sample_rate = output_sample_rate_; + *output_frames_per_buffer = output_frames_per_buffer_; + + return true; +} + int WebRtcAudioCapturer::GetBufferSize(int sample_rate) const { DCHECK(thread_checker_.CalledOnValidThread()); #if defined(OS_ANDROID) @@ -449,13 +500,27 @@ int WebRtcAudioCapturer::GetBufferSize(int sample_rate) const { return (2 * sample_rate / 100); #endif - // Use the native hardware buffer size in non peer connection mode. - if (!peer_connection_mode_ && hardware_buffer_size_) + // PeerConnection is running at a buffer size of 10ms data. A multiple of + // 10ms as the buffer size can give the best performance to PeerConnection. + int peer_connection_buffer_size = sample_rate / 100; + + // Use the native hardware buffer size in non peer connection mode when the + // platform is using a native buffer size smaller than the PeerConnection + // buffer size. + if (!peer_connection_mode_ && hardware_buffer_size_ && + hardware_buffer_size_ <= peer_connection_buffer_size) { return hardware_buffer_size_; + } - // WebRtc is running at a buffer size of 10ms data. Use a multiple of 10ms - // as the buffer size to achieve the best performance for WebRtc. return (sample_rate / 100); } +void WebRtcAudioCapturer::GetAudioProcessingParams( + base::TimeDelta* delay, int* volume, bool* key_pressed) { + base::AutoLock auto_lock(lock_); + *delay = audio_delay_; + *volume = volume_; + *key_pressed = key_pressed_; +} + } // namespace content diff --git a/chromium/content/renderer/media/webrtc_audio_capturer.h b/chromium/content/renderer/media/webrtc_audio_capturer.h index 21246798cc4..23391140411 100644 --- a/chromium/content/renderer/media/webrtc_audio_capturer.h +++ b/chromium/content/renderer/media/webrtc_audio_capturer.h @@ -12,8 +12,9 @@ #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" +#include "base/time/time.h" +#include "content/renderer/media/tagged_list.h" #include "content/renderer/media/webrtc_audio_device_impl.h" -#include "content/renderer/media/webrtc_local_audio_source_provider.h" #include "media/audio/audio_input_device.h" #include "media/base/audio_capturer_source.h" @@ -53,16 +54,22 @@ class CONTENT_EXPORT WebRtcAudioCapturer int sample_rate, int buffer_size, int session_id, - const std::string& device_id); + const std::string& device_id, + int paired_output_sample_rate, + int paired_output_frames_per_buffer, + int effects); // Add a audio track to the sinks of the capturer. // WebRtcAudioDeviceImpl calls this method on the main render thread but // other clients may call it from other threads. The current implementation // does not support multi-thread calling. + // The first AddTrack will implicitly trigger the Start() of this object. // Called on the main render thread or libjingle working thread. void AddTrack(WebRtcLocalAudioTrack* track); // Remove a audio track from the sinks of the capturer. + // If the track has been added to the capturer, it must call RemoveTrack() + // before it goes away. // Called on the main render thread or libjingle working thread. void RemoveTrack(WebRtcLocalAudioTrack* track); @@ -73,7 +80,8 @@ class CONTENT_EXPORT WebRtcAudioCapturer void SetCapturerSource( const scoped_refptr<media::AudioCapturerSource>& source, media::ChannelLayout channel_layout, - float sample_rate); + float sample_rate, + int effects); // Called when a stream is connecting to a peer connection. This will set // up the native buffer size for the stream in order to optimize the @@ -86,10 +94,6 @@ class CONTENT_EXPORT WebRtcAudioCapturer int Volume() const; int MaxVolume() const; - // Enables or disables the WebRtc AGC control. - // Called from a Libjingle working thread. - void SetAutomaticGainControl(bool enable); - bool is_recording() const { return running_; } // Audio parameters utilized by the audio capturer. Can be utilized by @@ -100,11 +104,26 @@ class CONTENT_EXPORT WebRtcAudioCapturer // of this accessor and if we can remove it. media::AudioParameters audio_parameters() const; + // Gets information about the paired output device. Returns true if such a + // device exists. + bool GetPairedOutputParameters(int* session_id, + int* output_sample_rate, + int* output_frames_per_buffer) const; + const std::string& device_id() const { return device_id_; } + int session_id() const { return session_id_; } + + // Stops recording audio. This method will empty its track lists since + // stopping the capturer will implicitly invalidate all its tracks. + // This method is exposed to the public because the media stream track can + // call Stop() on its source. + void Stop(); - WebKit::WebAudioSourceProvider* audio_source_provider() const { - return source_provider_.get(); - } + // Called by the WebAudioCapturerSource to get the audio processing params. + // This function is triggered by provideInput() on the WebAudio audio thread, + // TODO(xians): Remove after moving APM from WebRtc to Chrome. + void GetAudioProcessingParams(base::TimeDelta* delay, int* volume, + bool* key_pressed); protected: friend class base::RefCountedThreadSafe<WebRtcAudioCapturer>; @@ -113,7 +132,7 @@ class CONTENT_EXPORT WebRtcAudioCapturer private: class TrackOwner; - typedef std::list<scoped_refptr<TrackOwner> > TrackList; + typedef TaggedList<TrackOwner> TrackList; // AudioCapturerSource::CaptureCallback implementation. // Called on the AudioInputDevice audio thread. @@ -125,18 +144,14 @@ class CONTENT_EXPORT WebRtcAudioCapturer // Reconfigures the capturer with a new capture parameters. // Must be called without holding the lock. - void Reconfigure(int sample_rate, media::ChannelLayout channel_layout); + void Reconfigure(int sample_rate, media::ChannelLayout channel_layout, + int effects); // Starts recording audio. // Triggered by AddSink() on the main render thread or a Libjingle working // thread. It should NOT be called under |lock_|. void Start(); - // Stops recording audio. - // Triggered by RemoveSink() on the main render thread or a Libjingle working - // thread. It should NOT be called under |lock_|. - void Stop(); - // Helper function to get the buffer size based on |peer_connection_mode_| // and sample rate; int GetBufferSize(int sample_rate) const; @@ -145,10 +160,12 @@ class CONTENT_EXPORT WebRtcAudioCapturer base::ThreadChecker thread_checker_; // Protects |source_|, |audio_tracks_|, |running_|, |loopback_fifo_|, - // |params_|, |buffering_| and |agc_is_enabled_|. + // |params_| and |buffering_|. mutable base::Lock lock_; - // A list of audio tracks that the audio data is fed to. + // A tagged list of audio tracks that the audio data is fed + // to. Tagged items need to be notified that the audio format has + // changed. TrackList tracks_; // The audio data source from the browser process. @@ -159,9 +176,6 @@ class CONTENT_EXPORT WebRtcAudioCapturer bool running_; - // True when automatic gain control is enabled, false otherwise. - bool agc_is_enabled_; - int render_view_id_; // Cached value for the hardware native buffer size, used when @@ -179,15 +193,16 @@ class CONTENT_EXPORT WebRtcAudioCapturer // Range is [0, 255]. int volume_; - // The source provider to feed the capture data to other clients like - // WebAudio. - // TODO(xians): Move the source provider to track once we don't need to feed - // delay, volume, key_pressed information to WebAudioCapturerSource. - const scoped_ptr<WebRtcLocalAudioSourceProvider> source_provider_; - // Flag which affects the buffer size used by the capturer. bool peer_connection_mode_; + int output_sample_rate_; + int output_frames_per_buffer_; + + // Cache value for the audio processing params. + base::TimeDelta audio_delay_; + bool key_pressed_; + DISALLOW_COPY_AND_ASSIGN(WebRtcAudioCapturer); }; diff --git a/chromium/content/renderer/media/webrtc_audio_capturer_sink_owner.cc b/chromium/content/renderer/media/webrtc_audio_capturer_sink_owner.cc deleted file mode 100644 index 59de5107c0f..00000000000 --- a/chromium/content/renderer/media/webrtc_audio_capturer_sink_owner.cc +++ /dev/null @@ -1,57 +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/renderer/media/webrtc_audio_capturer_sink_owner.h" - -namespace content { - -WebRtcAudioCapturerSinkOwner::WebRtcAudioCapturerSinkOwner( - WebRtcAudioCapturerSink* sink) - : delegate_(sink) { -} - -int WebRtcAudioCapturerSinkOwner::CaptureData(const std::vector<int>& channels, - const int16* audio_data, - int sample_rate, - int number_of_channels, - int number_of_frames, - int audio_delay_milliseconds, - int current_volume, - bool need_audio_processing, - bool key_pressed) { - base::AutoLock lock(lock_); - if (delegate_) { - delegate_->CaptureData(channels, - audio_data, - sample_rate, - number_of_channels, - number_of_frames, - audio_delay_milliseconds, - current_volume, - need_audio_processing, - key_pressed); - } - - return 0; -} - -void WebRtcAudioCapturerSinkOwner::SetCaptureFormat( - const media::AudioParameters& params) { - base::AutoLock lock(lock_); - if (delegate_) - delegate_->SetCaptureFormat(params); -} - -bool WebRtcAudioCapturerSinkOwner::IsEqual( - const WebRtcAudioCapturerSink* other) const { - base::AutoLock lock(lock_); - return (other == delegate_); -} - -void WebRtcAudioCapturerSinkOwner::Reset() { - base::AutoLock lock(lock_); - delegate_ = NULL; -} - -} // namespace content diff --git a/chromium/content/renderer/media/webrtc_audio_capturer_sink_owner.h b/chromium/content/renderer/media/webrtc_audio_capturer_sink_owner.h deleted file mode 100644 index f338209224d..00000000000 --- a/chromium/content/renderer/media/webrtc_audio_capturer_sink_owner.h +++ /dev/null @@ -1,66 +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_RENDERER_MEDIA_WEBRTC_AUDIO_CAPTURER_SINK_OWNER_H_ -#define CONTENT_RENDERER_MEDIA_WEBRTC_AUDIO_CAPTURER_SINK_OWNER_H_ - -#include <vector> - -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "content/renderer/media/webrtc_audio_device_impl.h" -#include "media/audio/audio_parameters.h" - -namespace content { - -class WebRtcAudioCapturerSink; - -// Reference counted container of WebRtcAudioCapturerSink delegates. -class WebRtcAudioCapturerSinkOwner - : public base::RefCountedThreadSafe<WebRtcAudioCapturerSinkOwner>, - public WebRtcAudioCapturerSink { - public: - explicit WebRtcAudioCapturerSinkOwner(WebRtcAudioCapturerSink* sink); - - // WebRtcAudioCapturerSink implementation. - virtual int CaptureData(const std::vector<int>& channels, - const int16* audio_data, - int sample_rate, - int number_of_channels, - int number_of_frames, - int audio_delay_milliseconds, - int current_volume, - bool need_audio_processing, - bool key_pressed) OVERRIDE; - - virtual void SetCaptureFormat(const media::AudioParameters& params) OVERRIDE; - - bool IsEqual(const WebRtcAudioCapturerSink* other) const; - void Reset(); - - // Wrapper which allows to use std::find_if() when adding and removing - // sinks to/from the list. - struct WrapsSink { - WrapsSink(WebRtcAudioCapturerSink* sink) : sink_(sink) {} - bool operator()( - const scoped_refptr<WebRtcAudioCapturerSinkOwner>& owner) { - return owner->IsEqual(sink_); - } - WebRtcAudioCapturerSink* sink_; - }; - - protected: - virtual ~WebRtcAudioCapturerSinkOwner() {} - - private: - friend class base::RefCountedThreadSafe<WebRtcAudioCapturerSinkOwner>; - WebRtcAudioCapturerSink* delegate_; - mutable base::Lock lock_; - - DISALLOW_COPY_AND_ASSIGN(WebRtcAudioCapturerSinkOwner); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBRTC_AUDIO_CAPTURER_SINK_OWNER_H_ diff --git a/chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc b/chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc new file mode 100644 index 00000000000..184ba0155ab --- /dev/null +++ b/chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc @@ -0,0 +1,174 @@ +// 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/logging.h" +#include "content/renderer/media/rtc_media_constraints.h" +#include "content/renderer/media/webrtc_audio_capturer.h" +#include "content/renderer/media/webrtc_local_audio_track.h" +#include "media/audio/audio_parameters.h" +#include "media/base/audio_bus.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::_; +using ::testing::AtLeast; + +namespace content { + +namespace { + +// TODO(xians): Consolidate the similar methods in different unittests into +// one. +void ApplyFixedAudioConstraints(RTCMediaConstraints* constraints) { + // Constant constraint keys which enables default audio constraints on + // mediastreams with audio. + struct { + const char* key; + const char* value; + } static const kDefaultAudioConstraints[] = { + { webrtc::MediaConstraintsInterface::kEchoCancellation, + webrtc::MediaConstraintsInterface::kValueTrue }, + #if defined(OS_CHROMEOS) || defined(OS_MACOSX) + // Enable the extended filter mode AEC on platforms with known echo issues. + { webrtc::MediaConstraintsInterface::kExperimentalEchoCancellation, + webrtc::MediaConstraintsInterface::kValueTrue }, + #endif + { webrtc::MediaConstraintsInterface::kAutoGainControl, + webrtc::MediaConstraintsInterface::kValueTrue }, + { webrtc::MediaConstraintsInterface::kExperimentalAutoGainControl, + webrtc::MediaConstraintsInterface::kValueTrue }, + { webrtc::MediaConstraintsInterface::kNoiseSuppression, + webrtc::MediaConstraintsInterface::kValueTrue }, + { webrtc::MediaConstraintsInterface::kHighpassFilter, + webrtc::MediaConstraintsInterface::kValueTrue }, + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) { + constraints->AddMandatory(kDefaultAudioConstraints[i].key, + kDefaultAudioConstraints[i].value, false); + } +} + +class MockCapturerSource : public media::AudioCapturerSource { + public: + MockCapturerSource() {} + MOCK_METHOD3(Initialize, void(const media::AudioParameters& params, + CaptureCallback* callback, + int session_id)); + MOCK_METHOD0(Start, void()); + MOCK_METHOD0(Stop, void()); + MOCK_METHOD1(SetVolume, void(double volume)); + MOCK_METHOD1(SetAutomaticGainControl, void(bool enable)); + + protected: + virtual ~MockCapturerSource() {} +}; + +class MockPeerConnectionAudioSink : public PeerConnectionAudioSink { + public: + MockPeerConnectionAudioSink() {} + ~MockPeerConnectionAudioSink() {} + MOCK_METHOD9(OnData, int(const int16* audio_data, + int sample_rate, + int number_of_channels, + int number_of_frames, + const std::vector<int>& channels, + int audio_delay_milliseconds, + int current_volume, + bool need_audio_processing, + bool key_pressed)); + MOCK_METHOD1(OnSetFormat, void(const media::AudioParameters& params)); +}; + +} // namespace + +class WebRtcAudioCapturerTest : public testing::Test { + protected: + WebRtcAudioCapturerTest() +#if defined(OS_ANDROID) + : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, + media::CHANNEL_LAYOUT_STEREO, 48000, 16, 960) { + // Android works with a buffer size bigger than 20ms. +#else + : params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, + media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128) { +#endif + capturer_ = WebRtcAudioCapturer::CreateCapturer(); + capturer_->Initialize(-1, params_.channel_layout(), params_.sample_rate(), + params_.frames_per_buffer(), 0, std::string(), 0, 0, + params_.effects()); + capturer_source_ = new MockCapturerSource(); + EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), 0)); + capturer_->SetCapturerSource(capturer_source_, + params_.channel_layout(), + params_.sample_rate(), + params_.effects()); + + EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true)); + EXPECT_CALL(*capturer_source_.get(), Start()); + RTCMediaConstraints constraints; + ApplyFixedAudioConstraints(&constraints); + track_ = WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, + NULL, &constraints); + static_cast<WebRtcLocalAudioSourceProvider*>( + track_->audio_source_provider())->SetSinkParamsForTesting(params_); + track_->Start(); + EXPECT_TRUE(track_->enabled()); + } + + media::AudioParameters params_; + scoped_refptr<MockCapturerSource> capturer_source_; + scoped_refptr<WebRtcAudioCapturer> capturer_; + scoped_refptr<WebRtcLocalAudioTrack> track_; +}; + +// Pass the delay value, vollume and key_pressed info via capture callback, and +// those values should be correctly stored and passed to the track. +TEST_F(WebRtcAudioCapturerTest, VerifyAudioParams) { + // Connect a mock sink to the track. + scoped_ptr<MockPeerConnectionAudioSink> sink( + new MockPeerConnectionAudioSink()); + track_->AddSink(sink.get()); + + int delay_ms = 65; + bool key_pressed = true; + double volume = 0.9; + // MaxVolume() in WebRtcAudioCapturer is hard-coded to return 255, we add 0.5 + // to do the correct truncation as how the production code does. + int expected_volume_value = volume * capturer_->MaxVolume() + 0.5; + scoped_ptr<media::AudioBus> audio_bus = media::AudioBus::Create(params_); + audio_bus->Zero(); +#if defined(OS_ANDROID) + const int expected_buffer_size = params_.sample_rate() / 100; +#else + const int expected_buffer_size = params_.frames_per_buffer(); +#endif + bool expected_need_audio_processing = true; + media::AudioCapturerSource::CaptureCallback* callback = + static_cast<media::AudioCapturerSource::CaptureCallback*>(capturer_); + // Verify the sink is getting the correct values. + EXPECT_CALL(*sink, OnSetFormat(_)); + EXPECT_CALL(*sink, + OnData(_, params_.sample_rate(), params_.channels(), + expected_buffer_size, _, delay_ms, + expected_volume_value, expected_need_audio_processing, + key_pressed)).Times(AtLeast(1)); + callback->Capture(audio_bus.get(), delay_ms, volume, key_pressed); + + // Verify the cached values in the capturer fits what we expect. + base::TimeDelta cached_delay; + int cached_volume = !expected_volume_value; + bool cached_key_pressed = !key_pressed; + capturer_->GetAudioProcessingParams(&cached_delay, &cached_volume, + &cached_key_pressed); + EXPECT_EQ(cached_delay.InMilliseconds(), delay_ms); + EXPECT_EQ(cached_volume, expected_volume_value); + EXPECT_EQ(cached_key_pressed, key_pressed); + + track_->RemoveSink(sink.get()); + EXPECT_CALL(*capturer_source_.get(), Stop()); + capturer_->Stop(); +} + +} // namespace content diff --git a/chromium/content/renderer/media/webrtc_audio_device_impl.cc b/chromium/content/renderer/media/webrtc_audio_device_impl.cc index 0692ddc55ba..1daf048fe86 100644 --- a/chromium/content/renderer/media/webrtc_audio_device_impl.cc +++ b/chromium/content/renderer/media/webrtc_audio_device_impl.cc @@ -12,7 +12,6 @@ #include "content/renderer/media/webrtc_audio_renderer.h" #include "content/renderer/render_thread_impl.h" #include "media/audio/audio_parameters.h" -#include "media/audio/audio_util.h" #include "media/audio/sample_rates.h" using media::AudioParameters; @@ -28,7 +27,6 @@ WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl() initialized_(false), playing_(false), recording_(false), - agc_is_enabled_(false), microphone_volume_(0) { DVLOG(1) << "WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()"; } @@ -52,15 +50,15 @@ int32_t WebRtcAudioDeviceImpl::Release() { } return ret; } -int WebRtcAudioDeviceImpl::CaptureData(const std::vector<int>& channels, - const int16* audio_data, - int sample_rate, - int number_of_channels, - int number_of_frames, - int audio_delay_milliseconds, - int current_volume, - bool need_audio_processing, - bool key_pressed) { +int WebRtcAudioDeviceImpl::OnData(const int16* audio_data, + int sample_rate, + int number_of_channels, + int number_of_frames, + const std::vector<int>& channels, + int audio_delay_milliseconds, + int current_volume, + bool need_audio_processing, + bool key_pressed) { int total_delay_ms = 0; { base::AutoLock auto_lock(lock_); @@ -80,6 +78,7 @@ int WebRtcAudioDeviceImpl::CaptureData(const std::vector<int>& channels, // buffer is empty. const int16* audio_buffer = audio_data; const int samples_per_10_msec = (sample_rate / 100); + CHECK_EQ(number_of_frames % samples_per_10_msec, 0); int accumulated_audio_samples = 0; uint32_t new_volume = 0; while (accumulated_audio_samples < number_of_frames) { @@ -107,10 +106,9 @@ int WebRtcAudioDeviceImpl::CaptureData(const std::vector<int>& channels, return new_volume; } -void WebRtcAudioDeviceImpl::SetCaptureFormat( +void WebRtcAudioDeviceImpl::OnSetFormat( const media::AudioParameters& params) { - DVLOG(1) << "WebRtcAudioDeviceImpl::SetCaptureFormat()"; - DCHECK(thread_checker_.CalledOnValidThread()); + DVLOG(1) << "WebRtcAudioDeviceImpl::OnSetFormat()"; } void WebRtcAudioDeviceImpl::RenderData(uint8* audio_data, @@ -319,37 +317,6 @@ bool WebRtcAudioDeviceImpl::Recording() const { return recording_; } -int32_t WebRtcAudioDeviceImpl::SetAGC(bool enable) { - DVLOG(1) << "WebRtcAudioDeviceImpl::SetAGC(enable=" << enable << ")"; - DCHECK(initialized_); - - // Return early if we are not changing the AGC state. - if (enable == agc_is_enabled_) - return 0; - - // Set the AGC on all the capturers. It depends on the source of the - // capturer whether AGC is supported or not. - // The current implementation does not support changing the AGC state while - // recording. Using this approach simplifies the design and it is also - // inline with the latest WebRTC standard. - for (CapturerList::const_iterator iter = capturers_.begin(); - iter != capturers_.end(); ++iter) { - if (!(*iter)->is_recording()) - (*iter)->SetAutomaticGainControl(enable); - } - - agc_is_enabled_ = enable; - return 0; -} - -bool WebRtcAudioDeviceImpl::AGC() const { - DVLOG(1) << "WebRtcAudioDeviceImpl::AGC()"; - DCHECK(thread_checker_.CalledOnValidThread()); - // To reduce the usage of IPC messages, an internal AGC state is used. - // TODO(henrika): investigate if there is a need for a "deeper" getter. - return agc_is_enabled_; -} - int32_t WebRtcAudioDeviceImpl::SetMicrophoneVolume(uint32_t volume) { DVLOG(1) << "WebRtcAudioDeviceImpl::SetMicrophoneVolume(" << volume << ")"; DCHECK(initialized_); @@ -375,6 +342,7 @@ int32_t WebRtcAudioDeviceImpl::MicrophoneVolume(uint32_t* volume) const { return -1; *volume = static_cast<uint32_t>(capturer->Volume()); + return 0; } @@ -459,10 +427,6 @@ void WebRtcAudioDeviceImpl::AddAudioCapturer( DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(capturer.get()); - // Enable/disable the AGC on the new capture. - DCHECK(!capturer->is_recording()); - capturer->SetAutomaticGainControl(agc_is_enabled_); - // We only support one microphone today, which means the list can contain // only one capturer with a valid device id. DCHECK(capturer->device_id().empty() || !GetDefaultCapturer()); diff --git a/chromium/content/renderer/media/webrtc_audio_device_impl.h b/chromium/content/renderer/media/webrtc_audio_device_impl.h index b644178030b..f515c6e24cb 100644 --- a/chromium/content/renderer/media/webrtc_audio_device_impl.h +++ b/chromium/content/renderer/media/webrtc_audio_device_impl.h @@ -202,7 +202,7 @@ class WebRtcAudioRendererSource { virtual ~WebRtcAudioRendererSource() {} }; -class WebRtcAudioCapturerSink { +class PeerConnectionAudioSink { public: // Callback to deliver the captured interleaved data. // |channels| contains a vector of WebRtc VoE channels. @@ -216,29 +216,31 @@ class WebRtcAudioCapturerSink { // audio processing. // The return value is the new microphone volume, in the range of |0, 255]. // When the volume does not need to be updated, it returns 0. - virtual int CaptureData(const std::vector<int>& channels, - const int16* audio_data, - int sample_rate, - int number_of_channels, - int number_of_frames, - int audio_delay_milliseconds, - int current_volume, - bool need_audio_processing, - bool key_pressed) = 0; + virtual int OnData(const int16* audio_data, + int sample_rate, + int number_of_channels, + int number_of_frames, + const std::vector<int>& channels, + int audio_delay_milliseconds, + int current_volume, + bool need_audio_processing, + bool key_pressed) = 0; // Set the format for the capture audio parameters. - virtual void SetCaptureFormat(const media::AudioParameters& params) = 0; + // This is called when the capture format has changed, and it must be called + // on the same thread as calling CaptureData(). + virtual void OnSetFormat(const media::AudioParameters& params) = 0; protected: - virtual ~WebRtcAudioCapturerSink() {} + virtual ~PeerConnectionAudioSink() {} }; // Note that this class inherits from webrtc::AudioDeviceModule but due to // the high number of non-implemented methods, we move the cruft over to the // WebRtcAudioDeviceNotImpl. class CONTENT_EXPORT WebRtcAudioDeviceImpl - : NON_EXPORTED_BASE(public WebRtcAudioDeviceNotImpl), - NON_EXPORTED_BASE(public WebRtcAudioCapturerSink), + : NON_EXPORTED_BASE(public PeerConnectionAudioSink), + NON_EXPORTED_BASE(public WebRtcAudioDeviceNotImpl), NON_EXPORTED_BASE(public WebRtcAudioRendererSource) { public: // The maximum volume value WebRtc uses. @@ -278,11 +280,6 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl virtual int32_t StopRecording() OVERRIDE; virtual bool Recording() const OVERRIDE; - // Called on the main render thread and libJingle worker thread. - virtual int32_t SetAGC(bool enable) OVERRIDE; - - virtual bool AGC() const OVERRIDE; - // Called on the AudioInputDevice worker thread. virtual int32_t SetMicrophoneVolume(uint32_t volume) OVERRIDE; @@ -330,21 +327,21 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl // Make destructor private to ensure that we can only be deleted by Release(). virtual ~WebRtcAudioDeviceImpl(); - // WebRtcAudioCapturerSink implementation. + // PeerConnectionAudioSink implementation. // Called on the AudioInputDevice worker thread. - virtual int CaptureData(const std::vector<int>& channels, - const int16* audio_data, - int sample_rate, - int number_of_channels, - int number_of_frames, - int audio_delay_milliseconds, - int current_volume, - bool need_audio_processing, - bool key_pressed) OVERRIDE; + virtual int OnData(const int16* audio_data, + int sample_rate, + int number_of_channels, + int number_of_frames, + const std::vector<int>& channels, + int audio_delay_milliseconds, + int current_volume, + bool need_audio_processing, + bool key_pressed) OVERRIDE; - // Called on the main render thread. - virtual void SetCaptureFormat(const media::AudioParameters& params) OVERRIDE; + // Called on the AudioInputDevice worker thread. + virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE; // WebRtcAudioRendererSource implementation. @@ -392,9 +389,6 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl bool playing_; bool recording_; - // Local copy of the current Automatic Gain Control state. - bool agc_is_enabled_; - // Used for histograms of total recording and playout times. base::Time start_capture_time_; base::Time start_render_time_; diff --git a/chromium/content/renderer/media/webrtc_audio_device_not_impl.cc b/chromium/content/renderer/media/webrtc_audio_device_not_impl.cc index fd21fcb2ea6..a126acdaaf7 100644 --- a/chromium/content/renderer/media/webrtc_audio_device_not_impl.cc +++ b/chromium/content/renderer/media/webrtc_audio_device_not_impl.cc @@ -274,4 +274,12 @@ int32_t WebRtcAudioDeviceNotImpl::GetLoudspeakerStatus(bool* enabled) const { return 0; } +int32_t WebRtcAudioDeviceNotImpl::SetAGC(bool enable) { + return 0; +} + +bool WebRtcAudioDeviceNotImpl::AGC() const { + return true; +} + } // namespace content diff --git a/chromium/content/renderer/media/webrtc_audio_device_not_impl.h b/chromium/content/renderer/media/webrtc_audio_device_not_impl.h index af48ad4b81f..041c7d43a8c 100644 --- a/chromium/content/renderer/media/webrtc_audio_device_not_impl.h +++ b/chromium/content/renderer/media/webrtc_audio_device_not_impl.h @@ -106,6 +106,8 @@ class CONTENT_EXPORT WebRtcAudioDeviceNotImpl virtual int32_t ResetAudioDevice() OVERRIDE; virtual int32_t SetLoudspeakerStatus(bool enable) OVERRIDE; virtual int32_t GetLoudspeakerStatus(bool* enabled) const OVERRIDE; + virtual int32_t SetAGC(bool enable) OVERRIDE; + virtual bool AGC() const OVERRIDE; protected: virtual ~WebRtcAudioDeviceNotImpl() {}; diff --git a/chromium/content/renderer/media/webrtc_audio_device_unittest.cc b/chromium/content/renderer/media/webrtc_audio_device_unittest.cc index 7a194e6b451..d6821f6fba0 100644 --- a/chromium/content/renderer/media/webrtc_audio_device_unittest.cc +++ b/chromium/content/renderer/media/webrtc_audio_device_unittest.cc @@ -120,7 +120,8 @@ bool CreateAndInitializeCapturer(WebRtcAudioDeviceImpl* webrtc_audio_device) { media::ChannelLayout channel_layout = hardware_config->GetInputChannelLayout(); if (!capturer->Initialize(kRenderViewId, channel_layout, sample_rate, 0, 1, - media::AudioManagerBase::kDefaultDeviceId)) { + media::AudioManagerBase::kDefaultDeviceId, 0, 0, + media::AudioParameters::NO_EFFECTS)) { return false; } @@ -135,7 +136,7 @@ bool CreateAndInitializeCapturer(WebRtcAudioDeviceImpl* webrtc_audio_device) { // Also, connect the sink to the audio track. scoped_refptr<WebRtcLocalAudioTrack> CreateAndStartLocalAudioTrack(WebRtcAudioCapturer* capturer, - WebRtcAudioCapturerSink* sink) { + PeerConnectionAudioSink* sink) { scoped_refptr<WebRtcLocalAudioTrack> local_audio_track( WebRtcLocalAudioTrack::Create(std::string(), capturer, NULL, NULL, NULL)); local_audio_track->AddSink(sink); @@ -205,37 +206,38 @@ class WebRTCMediaProcessImpl : public webrtc::VoEMediaProcess { DISALLOW_COPY_AND_ASSIGN(WebRTCMediaProcessImpl); }; -class MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink { +// TODO(xians): Use MediaStreamAudioSink. +class MockMediaStreamAudioSink : public PeerConnectionAudioSink { public: - explicit MockWebRtcAudioCapturerSink(base::WaitableEvent* event) + explicit MockMediaStreamAudioSink(base::WaitableEvent* event) : event_(event) { DCHECK(event_); } - virtual ~MockWebRtcAudioCapturerSink() {} - - // WebRtcAudioCapturerSink implementation. - virtual int CaptureData(const std::vector<int>& channels, - const int16* audio_data, - int sample_rate, - int number_of_channels, - int number_of_frames, - int audio_delay_milliseconds, - int current_volume, - bool need_audio_processing, - bool key_pressed) OVERRIDE { + virtual ~MockMediaStreamAudioSink() {} + + // PeerConnectionAudioSink implementation. + virtual int OnData(const int16* audio_data, + int sample_rate, + int number_of_channels, + int number_of_frames, + const std::vector<int>& channels, + int audio_delay_milliseconds, + int current_volume, + bool need_audio_processing, + bool key_pressed) OVERRIDE { // Signal that a callback has been received. event_->Signal(); return 0; } // Set the format for the capture audio parameters. - virtual void SetCaptureFormat( + virtual void OnSetFormat( const media::AudioParameters& params) OVERRIDE {} private: base::WaitableEvent* event_; - DISALLOW_COPY_AND_ASSIGN(MockWebRtcAudioCapturerSink); + DISALLOW_COPY_AND_ASSIGN(MockMediaStreamAudioSink); }; class MockWebRtcAudioRendererSource : public WebRtcAudioRendererSource { @@ -294,8 +296,8 @@ void ReadDataFromSpeechFile(char* data, int length) { .Append(FILE_PATH_LITERAL("speech_16b_stereo_48kHz.raw")); DCHECK(base::PathExists(data_file)); int64 data_file_size64 = 0; - DCHECK(file_util::GetFileSize(data_file, &data_file_size64)); - EXPECT_EQ(length, file_util::ReadFile(data_file, data, length)); + DCHECK(base::GetFileSize(data_file, &data_file_size64)); + EXPECT_EQ(length, base::ReadFile(data_file, data, length)); DCHECK(data_file_size64 > length); } @@ -329,13 +331,13 @@ int RunWebRtcLoopbackTimeTest(media::AudioManager* manager, int err = base->Init(webrtc_audio_device.get()); EXPECT_EQ(0, err); - // We use SetCaptureFormat() and SetRenderFormat() to configure the audio + // We use OnSetFormat() and SetRenderFormat() to configure the audio // parameters so that this test can run on machine without hardware device. const media::AudioParameters params = media::AudioParameters( media::AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, 48000, 2, 480); - WebRtcAudioCapturerSink* capturer_sink = - static_cast<WebRtcAudioCapturerSink*>(webrtc_audio_device.get()); + PeerConnectionAudioSink* capturer_sink = + static_cast<PeerConnectionAudioSink*>(webrtc_audio_device.get()); WebRtcAudioRendererSource* renderer_source = static_cast<WebRtcAudioRendererSource*>(webrtc_audio_device.get()); renderer_source->SetRenderFormat(params); @@ -379,12 +381,12 @@ int RunWebRtcLoopbackTimeTest(media::AudioManager* manager, voe_channels.push_back(channel); for (int j = 0; j < kNumberOfPacketsForLoopbackTest; ++j) { // Sending fake capture data to WebRtc. - capturer_sink->CaptureData( - voe_channels, + capturer_sink->OnData( reinterpret_cast<int16*>(capture_data.get() + input_packet_size * j), params.sample_rate(), params.channels(), params.frames_per_buffer(), + voe_channels, kHardwareLatencyInMs, 1.0, enable_apm, @@ -512,20 +514,10 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_StartPlayout) { scoped_ptr<media::AudioHardwareConfig> config = CreateRealHardwareConfig(audio_manager_.get()); SetAudioHardwareConfig(config.get()); - media::AudioParameters params(config->GetOutputConfig()); if (!HardwareSampleRatesAreValid()) return; - EXPECT_CALL(media_observer(), - OnAudioStreamCreated(_, 1, params, StrEq(""))).Times(1); - EXPECT_CALL(media_observer(), - OnSetAudioStreamPlaying(_, 1, true)).Times(1); - EXPECT_CALL(media_observer(), - OnSetAudioStreamStatus(_, 1, StrEq("closed"))).Times(1); - EXPECT_CALL(media_observer(), - OnDeleteAudioStream(_, 1)).Times(AnyNumber()); - WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create()); ASSERT_TRUE(engine.valid()); ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get()); @@ -673,7 +665,7 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_StartRecording) { ch, webrtc::kRecordingPerChannel)); EXPECT_EQ(0, base->StopSend(ch)); - local_audio_track->Stop(); + webrtc_audio_device->GetDefaultCapturer()->Stop(); EXPECT_EQ(0, base->DeleteChannel(ch)); EXPECT_EQ(0, base->Terminate()); } @@ -698,20 +690,10 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_PlayLocalFile) { scoped_ptr<media::AudioHardwareConfig> config = CreateRealHardwareConfig(audio_manager_.get()); SetAudioHardwareConfig(config.get()); - media::AudioParameters params(config->GetOutputConfig()); if (!HardwareSampleRatesAreValid()) return; - EXPECT_CALL(media_observer(), - OnAudioStreamCreated(_, 1, params, StrEq(""))).Times(1); - EXPECT_CALL(media_observer(), - OnSetAudioStreamPlaying(_, 1, true)).Times(1); - EXPECT_CALL(media_observer(), - OnSetAudioStreamStatus(_, 1, StrEq("closed"))).Times(1); - EXPECT_CALL(media_observer(), - OnDeleteAudioStream(_, 1)).Times(AnyNumber()); - WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create()); ASSERT_TRUE(engine.valid()); ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get()); @@ -779,20 +761,10 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_FullDuplexAudioWithAGC) { scoped_ptr<media::AudioHardwareConfig> config = CreateRealHardwareConfig(audio_manager_.get()); SetAudioHardwareConfig(config.get()); - media::AudioParameters params(config->GetOutputConfig()); if (!HardwareSampleRatesAreValid()) return; - EXPECT_CALL(media_observer(), - OnAudioStreamCreated(_, 1, params, StrEq(""))).Times(1); - EXPECT_CALL(media_observer(), - OnSetAudioStreamPlaying(_, 1, true)); - EXPECT_CALL(media_observer(), - OnSetAudioStreamStatus(_, 1, StrEq("closed"))); - EXPECT_CALL(media_observer(), - OnDeleteAudioStream(_, 1)).Times(AnyNumber()); - WebRTCAutoDelete<webrtc::VoiceEngine> engine(webrtc::VoiceEngine::Create()); ASSERT_TRUE(engine.valid()); ScopedWebRTCPtr<webrtc::VoEBase> base(engine.get()); @@ -845,13 +817,13 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_FullDuplexAudioWithAGC) { proxy->Start(); proxy->Play(); - LOG(INFO) << ">> You should now be able to hear yourself in loopback..."; + VLOG(0) << ">> You should now be able to hear yourself in loopback..."; message_loop_.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(), base::TimeDelta::FromSeconds(2)); message_loop_.Run(); - local_audio_track->Stop(); + webrtc_audio_device->GetDefaultCapturer()->Stop(); proxy->Stop(); EXPECT_EQ(0, base->StopSend(ch)); EXPECT_EQ(0, base->StopPlayout(ch)); @@ -890,8 +862,8 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, DISABLED_WebRtcRecordingSetupTime) { EXPECT_TRUE(CreateAndInitializeCapturer(webrtc_audio_device.get())); base::WaitableEvent event(false, false); - scoped_ptr<MockWebRtcAudioCapturerSink> sink( - new MockWebRtcAudioCapturerSink(&event)); + scoped_ptr<MockMediaStreamAudioSink> sink( + new MockMediaStreamAudioSink(&event)); // Create and start a local audio track. Starting the audio track will connect // the audio track to the capturer and also start the source of the capturer. @@ -910,8 +882,7 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, DISABLED_WebRtcRecordingSetupTime) { int delay = (base::Time::Now() - start_time).InMilliseconds(); PrintPerfResultMs("webrtc_recording_setup_c", "t", delay); - local_audio_track->RemoveSink(sink.get()); - local_audio_track->Stop(); + webrtc_audio_device->GetDefaultCapturer()->Stop(); EXPECT_EQ(0, base->StopSend(ch)); EXPECT_EQ(0, base->DeleteChannel(ch)); EXPECT_EQ(0, base->Terminate()); @@ -934,20 +905,10 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_WebRtcPlayoutSetupTime) { scoped_ptr<media::AudioHardwareConfig> config = CreateRealHardwareConfig(audio_manager_.get()); SetAudioHardwareConfig(config.get()); - media::AudioParameters params(config->GetOutputConfig()); if (!HardwareSampleRatesAreValid()) return; - EXPECT_CALL(media_observer(), - OnAudioStreamCreated(_, 1, params, StrEq(""))).Times(1); - EXPECT_CALL(media_observer(), - OnSetAudioStreamStatus(_, 1, _)).Times(AnyNumber()); - EXPECT_CALL(media_observer(), - OnSetAudioStreamPlaying(_, 1, true)); - EXPECT_CALL(media_observer(), - OnDeleteAudioStream(_, 1)).Times(AnyNumber()); - base::WaitableEvent event(false, false); scoped_ptr<MockWebRtcAudioRendererSource> renderer_source( new MockWebRtcAudioRendererSource(&event)); @@ -980,6 +941,13 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_WebRtcPlayoutSetupTime) { TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_WebRtcLoopbackTimeWithoutSignalProcessing) { +#if defined(OS_WIN) + // This test hangs on WinXP: see http://crbug.com/318189. + if (base::win::GetVersion() <= base::win::VERSION_XP) { + LOG(WARNING) << "Test disabled due to the test hangs on WinXP."; + return; + } +#endif int latency = RunWebRtcLoopbackTimeTest(audio_manager_.get(), false); PrintPerfResultMs("webrtc_loopback_without_sigal_processing (100 packets)", "t", latency); @@ -996,6 +964,13 @@ TEST_F(MAYBE_WebRTCAudioDeviceTest, TEST_F(MAYBE_WebRTCAudioDeviceTest, MAYBE_WebRtcLoopbackTimeWithSignalProcessing) { +#if defined(OS_WIN) + // This test hangs on WinXP: see http://crbug.com/318189. + if (base::win::GetVersion() <= base::win::VERSION_XP) { + LOG(WARNING) << "Test disabled due to the test hangs on WinXP."; + return; + } +#endif int latency = RunWebRtcLoopbackTimeTest(audio_manager_.get(), true); PrintPerfResultMs("webrtc_loopback_with_signal_processing (100 packets)", "t", latency); diff --git a/chromium/content/renderer/media/webrtc_audio_renderer.cc b/chromium/content/renderer/media/webrtc_audio_renderer.cc index 9955b6e3169..dae29a506aa 100644 --- a/chromium/content/renderer/media/webrtc_audio_renderer.cc +++ b/chromium/content/renderer/media/webrtc_audio_renderer.cc @@ -7,8 +7,10 @@ #include "base/logging.h" #include "base/metrics/histogram.h" #include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "content/renderer/media/audio_device_factory.h" #include "content/renderer/media/webrtc_audio_device_impl.h" +#include "content/renderer/media/webrtc_logging.h" #include "media/audio/audio_output_device.h" #include "media/audio/audio_parameters.h" #include "media/audio/sample_rates.h" @@ -36,7 +38,6 @@ const int kValidOutputRates[] = {48000, 44100}; // low latency, currently 16000 is used to work around audio problem on some // Android devices. const int kValidOutputRates[] = {48000, 44100, 16000}; -const int kDefaultOutputBufferSize = 2048; #else const int kValidOutputRates[] = {44100}; #endif @@ -177,6 +178,13 @@ WebRtcAudioRenderer::WebRtcAudioRenderer(int source_render_view_id, fifo_delay_milliseconds_(0), sample_rate_(sample_rate), frames_per_buffer_(frames_per_buffer) { + WebRtcLogMessage(base::StringPrintf( + "WAR::WAR. source_render_view_id=%d" + ", session_id=%d, sample_rate=%d, frames_per_buffer=%d", + source_render_view_id, + session_id, + sample_rate, + frames_per_buffer)); } WebRtcAudioRenderer::~WebRtcAudioRenderer() { @@ -194,12 +202,8 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) { DCHECK(!sink_.get()); DCHECK(!source_); - // Use stereo output on all platforms exept Android. + // Use stereo output on all platforms. media::ChannelLayout channel_layout = media::CHANNEL_LAYOUT_STEREO; -#if defined(OS_ANDROID) - DVLOG(1) << "Using mono audio output for Android"; - channel_layout = media::CHANNEL_LAYOUT_MONO; -#endif // TODO(tommi,henrika): Maybe we should just change |sample_rate_| to be // immutable and change its value instead of using a temporary? @@ -255,11 +259,23 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) { media::AudioParameters sink_params; -#if defined(OS_ANDROID) - buffer_size = kDefaultOutputBufferSize; -#else + // Use native output siz as default. buffer_size = frames_per_buffer_; +#if defined(OS_ANDROID) + // TODO(henrika): Keep tuning this scheme and espcicially for low-latency + // cases. Might not be possible to come up with the perfect solution using + // the render side only. + const int frames_per_10ms = (sample_rate / 100); + if (buffer_size < 2 * frames_per_10ms) { + // Examples of low-latency frame sizes and the resulting |buffer_size|: + // Nexus 7 : 240 audio frames => 2*480 = 960 + // Nexus 10 : 256 => 2*441 = 882 + // Galaxy Nexus: 144 => 2*441 = 882 + buffer_size = 2 * frames_per_10ms; + DVLOG(1) << "Low-latency output detected on Android"; + } #endif + DVLOG(1) << "Using sink output buffer size: " << buffer_size; sink_params.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, channels, 0, sample_rate, 16, buffer_size); diff --git a/chromium/content/renderer/media/webrtc_local_audio_renderer.cc b/chromium/content/renderer/media/webrtc_local_audio_renderer.cc index 3b94e2416b3..6a92d906d32 100644 --- a/chromium/content/renderer/media/webrtc_local_audio_renderer.cc +++ b/chromium/content/renderer/media/webrtc_local_audio_renderer.cc @@ -7,6 +7,7 @@ #include "base/debug/trace_event.h" #include "base/logging.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/metrics/histogram.h" #include "base/synchronization/lock.h" #include "content/renderer/media/audio_device_factory.h" #include "content/renderer/media/webrtc_audio_capturer.h" @@ -16,20 +17,27 @@ namespace content { +namespace { + +enum LocalRendererSinkStates { + kSinkStarted = 0, + kSinkNeverStarted, + kSinkStatesMax // Must always be last! +}; + +} // namespace + // media::AudioRendererSink::RenderCallback implementation int WebRtcLocalAudioRenderer::Render( media::AudioBus* audio_bus, int audio_delay_milliseconds) { + TRACE_EVENT0("audio", "WebRtcLocalAudioRenderer::Render"); base::AutoLock auto_lock(thread_lock_); - if (!playing_) { + if (!playing_ || !volume_ || !loopback_fifo_) { audio_bus->Zero(); return 0; } - TRACE_EVENT0("audio", "WebRtcLocalAudioRenderer::Render"); - - DCHECK(loopback_fifo_.get() != NULL); - // Provide data by reading from the FIFO if the FIFO contains enough // to fulfill the request. if (loopback_fifo_->frames() >= audio_bus->frames()) { @@ -48,178 +56,182 @@ void WebRtcLocalAudioRenderer::OnRenderError() { NOTIMPLEMENTED(); } -// content::WebRtcAudioCapturerSink implementation -int WebRtcLocalAudioRenderer::CaptureData(const std::vector<int>& channels, - const int16* audio_data, - int sample_rate, - int number_of_channels, - int number_of_frames, - int audio_delay_milliseconds, - int current_volume, - bool need_audio_processing, - bool key_pressed) { +// content::MediaStreamAudioSink implementation +void WebRtcLocalAudioRenderer::OnData(const int16* audio_data, + int sample_rate, + int number_of_channels, + int number_of_frames) { + DCHECK(capture_thread_checker_.CalledOnValidThread()); TRACE_EVENT0("audio", "WebRtcLocalAudioRenderer::CaptureData"); base::AutoLock auto_lock(thread_lock_); - - if (!playing_) - return 0; + if (!playing_ || !volume_ || !loopback_fifo_) + return; // Push captured audio to FIFO so it can be read by a local sink. - if (loopback_fifo_) { - if (loopback_fifo_->frames() + number_of_frames <= - loopback_fifo_->max_frames()) { - scoped_ptr<media::AudioBus> audio_source = media::AudioBus::Create( - number_of_channels, number_of_frames); - audio_source->FromInterleaved(audio_data, - audio_source->frames(), - sizeof(audio_data[0])); - loopback_fifo_->Push(audio_source.get()); - - base::Time now = base::Time::Now(); - total_render_time_ += now - last_render_time_; - last_render_time_ = now; - } else { - DVLOG(1) << "FIFO is full"; - } + if (loopback_fifo_->frames() + number_of_frames <= + loopback_fifo_->max_frames()) { + scoped_ptr<media::AudioBus> audio_source = media::AudioBus::Create( + number_of_channels, number_of_frames); + audio_source->FromInterleaved(audio_data, + audio_source->frames(), + sizeof(audio_data[0])); + loopback_fifo_->Push(audio_source.get()); + + const base::TimeTicks now = base::TimeTicks::Now(); + total_render_time_ += now - last_render_time_; + last_render_time_ = now; + } else { + DVLOG(1) << "FIFO is full"; } - - return 0; } -void WebRtcLocalAudioRenderer::SetCaptureFormat( +void WebRtcLocalAudioRenderer::OnSetFormat( const media::AudioParameters& params) { - audio_params_ = params; + DVLOG(1) << "WebRtcLocalAudioRenderer::OnSetFormat()"; + // If the source is restarted, we might have changed to another capture + // thread. + capture_thread_checker_.DetachFromThread(); + DCHECK(capture_thread_checker_.CalledOnValidThread()); + + // Reset the |source_params_|, |sink_params_| and |loopback_fifo_| to match + // the new format. + { + base::AutoLock auto_lock(thread_lock_); + if (source_params_ == params) + return; + + source_params_ = params; + + sink_params_.Reset(source_params_.format(), + source_params_.channel_layout(), + source_params_.channels(), + source_params_.input_channels(), + source_params_.sample_rate(), + source_params_.bits_per_sample(), +#if defined(OS_ANDROID) + // On Android, input and output are using same sampling rate. In order to + // achieve low latency mode, we need use buffer size suggested by + // AudioManager for the sink paramters which will be used to decide + // buffer size for shared memory buffer. + frames_per_buffer_ +#else + 2 * source_params_.frames_per_buffer() +#endif + ); + + // TODO(henrika): we could add a more dynamic solution here but I prefer + // a fixed size combined with bad audio at overflow. The alternative is + // that we start to build up latency and that can be more difficult to + // detect. Tests have shown that the FIFO never contains more than 2 or 3 + // audio frames but I have selected a max size of ten buffers just + // in case since these tests were performed on a 16 core, 64GB Win 7 + // machine. We could also add some sort of error notifier in this area if + // the FIFO overflows. + loopback_fifo_.reset(new media::AudioFifo( + params.channels(), 10 * params.frames_per_buffer())); + } + + // Post a task on the main render thread to reconfigure the |sink_| with the + // new format. + message_loop_->PostTask( + FROM_HERE, + base::Bind(&WebRtcLocalAudioRenderer::ReconfigureSink, this, + params)); } // WebRtcLocalAudioRenderer::WebRtcLocalAudioRenderer implementation. WebRtcLocalAudioRenderer::WebRtcLocalAudioRenderer( - WebRtcLocalAudioTrack* audio_track, + const blink::WebMediaStreamTrack& audio_track, int source_render_view_id, int session_id, - int sample_rate, int frames_per_buffer) : audio_track_(audio_track), source_render_view_id_(source_render_view_id), session_id_(session_id), + message_loop_(base::MessageLoopProxy::current()), playing_(false), - sample_rate_(sample_rate), - frames_per_buffer_(frames_per_buffer) { - DCHECK(audio_track); + frames_per_buffer_(frames_per_buffer), + volume_(0.0), + sink_started_(false) { DVLOG(1) << "WebRtcLocalAudioRenderer::WebRtcLocalAudioRenderer()"; } WebRtcLocalAudioRenderer::~WebRtcLocalAudioRenderer() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(message_loop_->BelongsToCurrentThread()); DCHECK(!sink_.get()); DVLOG(1) << "WebRtcLocalAudioRenderer::~WebRtcLocalAudioRenderer()"; } void WebRtcLocalAudioRenderer::Start() { DVLOG(1) << "WebRtcLocalAudioRenderer::Start()"; - DCHECK(thread_checker_.CalledOnValidThread()); - // Add this class as sink to the audio track to ensure that we receive - // WebRtcAudioCapturerSink::CaptureData() callbacks for captured audio. - // |audio_params_| will be updated right after the AddCapturerAudioTrack(). - audio_track_->AddSink(this); + DCHECK(message_loop_->BelongsToCurrentThread()); - base::AutoLock auto_lock(thread_lock_); + // We get audio data from |audio_track_|... + MediaStreamAudioSink::AddToAudioTrack(this, audio_track_); + // ...and |sink_| will get audio data from us. DCHECK(!sink_.get()); - - // TODO(henrika): we could add a more dynamic solution here but I prefer - // a fixed size combined with bad audio at overflow. The alternative is - // that we start to build up latency and that can be more difficult to - // detect. Tests have shown that the FIFO never contains more than 2 or 3 - // audio frames but I have selected a max size of ten buffers just - // in case since these tests were performed on a 16 core, 64GB Win 7 - // machine. We could also add some sort of error notifier in this area if - // the FIFO overflows. - DCHECK(!loopback_fifo_); - loopback_fifo_.reset(new media::AudioFifo( - audio_params_.channels(), 10 * audio_params_.frames_per_buffer())); - - media::AudioParameters sink_params(audio_params_.format(), - audio_params_.channel_layout(), - audio_params_.sample_rate(), - audio_params_.bits_per_sample(), -#if defined(OS_ANDROID) - // On Android, input and output are using same sampling rate. In order to - // achieve low latency mode, we need use buffer size suggested by - // AudioManager for the sink paramters which will be used to decide - // buffer size for shared memory buffer. - frames_per_buffer_ -#else - 2 * audio_params_.frames_per_buffer() -#endif - ); - sink_ = AudioDeviceFactory::NewOutputDevice(source_render_view_id_); - // TODO(henrika): we could utilize the unified audio here instead and do - // sink_->InitializeIO(sink_params, 2, callback_.get()); - // It would then be possible to avoid using the WebRtcAudioCapturer. - sink_->InitializeUnifiedStream(sink_params, this, session_id_); - - // Start the capturer and local rendering. Note that, the capturer is owned - // by the WebRTC ADM and might already bee running. - sink_->Start(); - - last_render_time_ = base::Time::Now(); + base::AutoLock auto_lock(thread_lock_); + last_render_time_ = base::TimeTicks::Now(); playing_ = false; } void WebRtcLocalAudioRenderer::Stop() { DVLOG(1) << "WebRtcLocalAudioRenderer::Stop()"; - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!sink_.get()) - return; + DCHECK(message_loop_->BelongsToCurrentThread()); { base::AutoLock auto_lock(thread_lock_); playing_ = false; - - if (loopback_fifo_.get() != NULL) { - loopback_fifo_->Clear(); - loopback_fifo_.reset(); - } + loopback_fifo_.reset(); } // Stop the output audio stream, i.e, stop asking for data to render. - sink_->Stop(); - sink_ = NULL; + // It is safer to call Stop() on the |sink_| to clean up the resources even + // when the |sink_| is never started. + if (sink_) { + sink_->Stop(); + sink_ = NULL; + } + + if (!sink_started_) { + UMA_HISTOGRAM_ENUMERATION("Media.LocalRendererSinkStates", + kSinkNeverStarted, kSinkStatesMax); + } + sink_started_ = false; // Ensure that the capturer stops feeding us with captured audio. - // Note that, we do not stop the capturer here since it may still be used by - // the WebRTC ADM. - audio_track_->RemoveSink(this); - audio_track_ = NULL; + MediaStreamAudioSink::RemoveFromAudioTrack(this, audio_track_); } void WebRtcLocalAudioRenderer::Play() { DVLOG(1) << "WebRtcLocalAudioRenderer::Play()"; - DCHECK(thread_checker_.CalledOnValidThread()); - base::AutoLock auto_lock(thread_lock_); + DCHECK(message_loop_->BelongsToCurrentThread()); if (!sink_.get()) return; - // Resumes rendering by ensuring that WebRtcLocalAudioRenderer::Render() - // now reads data from the local FIFO. - playing_ = true; - last_render_time_ = base::Time::Now(); + { + base::AutoLock auto_lock(thread_lock_); + // Resumes rendering by ensuring that WebRtcLocalAudioRenderer::Render() + // now reads data from the local FIFO. + playing_ = true; + last_render_time_ = base::TimeTicks::Now(); + } - if (loopback_fifo_) - loopback_fifo_->Clear(); + // Note: If volume_ is currently muted, the |sink_| will not be started yet. + MaybeStartSink(); } void WebRtcLocalAudioRenderer::Pause() { DVLOG(1) << "WebRtcLocalAudioRenderer::Pause()"; - DCHECK(thread_checker_.CalledOnValidThread()); - base::AutoLock auto_lock(thread_lock_); + DCHECK(message_loop_->BelongsToCurrentThread()); if (!sink_.get()) return; + base::AutoLock auto_lock(thread_lock_); // Temporarily suspends rendering audio. // WebRtcLocalAudioRenderer::Render() will return early during this state // and only zeros will be provided to the active sink. @@ -228,14 +240,24 @@ void WebRtcLocalAudioRenderer::Pause() { void WebRtcLocalAudioRenderer::SetVolume(float volume) { DVLOG(1) << "WebRtcLocalAudioRenderer::SetVolume(" << volume << ")"; - DCHECK(thread_checker_.CalledOnValidThread()); - base::AutoLock auto_lock(thread_lock_); + DCHECK(message_loop_->BelongsToCurrentThread()); + + { + base::AutoLock auto_lock(thread_lock_); + // Cache the volume. + volume_ = volume; + } + + // Lazily start the |sink_| when the local renderer is unmuted during + // playing. + MaybeStartSink(); + if (sink_.get()) sink_->SetVolume(volume); } base::TimeDelta WebRtcLocalAudioRenderer::GetCurrentRenderTime() const { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(message_loop_->BelongsToCurrentThread()); base::AutoLock auto_lock(thread_lock_); if (!sink_.get()) return base::TimeDelta(); @@ -246,4 +268,46 @@ bool WebRtcLocalAudioRenderer::IsLocalRenderer() const { return true; } +void WebRtcLocalAudioRenderer::MaybeStartSink() { + DCHECK(message_loop_->BelongsToCurrentThread()); + DVLOG(1) << "WebRtcLocalAudioRenderer::MaybeStartSink()"; + + if (!sink_.get() || !source_params_.IsValid()) + return; + + base::AutoLock auto_lock(thread_lock_); + + // Clear up the old data in the FIFO. + loopback_fifo_->Clear(); + + if (!sink_params_.IsValid() || !playing_ || !volume_ || sink_started_) + return; + + DVLOG(1) << "WebRtcLocalAudioRenderer::MaybeStartSink() -- Starting sink_."; + sink_->InitializeUnifiedStream(sink_params_, this, session_id_); + sink_->Start(); + sink_started_ = true; + UMA_HISTOGRAM_ENUMERATION("Media.LocalRendererSinkStates", + kSinkStarted, kSinkStatesMax); +} + +void WebRtcLocalAudioRenderer::ReconfigureSink( + const media::AudioParameters& params) { + DCHECK(message_loop_->BelongsToCurrentThread()); + + DVLOG(1) << "WebRtcLocalAudioRenderer::ReconfigureSink()"; + + if (!sink_) + return; // WebRtcLocalAudioRenderer has not yet been started. + + // Stop |sink_| and re-create a new one to be initialized with different audio + // parameters. Then, invoke MaybeStartSink() to restart everything again. + if (sink_started_) { + sink_->Stop(); + sink_started_ = false; + } + sink_ = AudioDeviceFactory::NewOutputDevice(source_render_view_id_); + MaybeStartSink(); +} + } // namespace content diff --git a/chromium/content/renderer/media/webrtc_local_audio_renderer.h b/chromium/content/renderer/media/webrtc_local_audio_renderer.h index f77d523f4a6..e9871ece81b 100644 --- a/chromium/content/renderer/media/webrtc_local_audio_renderer.h +++ b/chromium/content/renderer/media/webrtc_local_audio_renderer.h @@ -9,12 +9,15 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" +#include "base/message_loop/message_loop_proxy.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" #include "content/common/content_export.h" +#include "content/public/renderer/media_stream_audio_sink.h" #include "content/renderer/media/media_stream_audio_renderer.h" #include "content/renderer/media/webrtc_audio_device_impl.h" #include "content/renderer/media/webrtc_local_audio_track.h" +#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" namespace media { class AudioBus; @@ -33,7 +36,7 @@ class WebRtcAudioCapturer; // It also implements media::AudioRendererSink::RenderCallback to render audio // data provided from a WebRtcLocalAudioTrack source. // When the audio layer in the browser process asks for data to render, this -// class provides the data by implementing the WebRtcAudioCapturerSink +// class provides the data by implementing the MediaStreamAudioSink // interface, i.e., we are a sink seen from the WebRtcAudioCapturer perspective. // TODO(henrika): improve by using similar principles as in RTCVideoRenderer // which register itself to the video track when the provider is started and @@ -41,16 +44,15 @@ class WebRtcAudioCapturer; // Tracking this at http://crbug.com/164813. class CONTENT_EXPORT WebRtcLocalAudioRenderer : NON_EXPORTED_BASE(public MediaStreamAudioRenderer), - NON_EXPORTED_BASE(public media::AudioRendererSink::RenderCallback), - NON_EXPORTED_BASE(public WebRtcAudioCapturerSink) { + NON_EXPORTED_BASE(public MediaStreamAudioSink), + NON_EXPORTED_BASE(public media::AudioRendererSink::RenderCallback) { public: // Creates a local renderer and registers a capturing |source| object. // The |source| is owned by the WebRtcAudioDeviceImpl. // Called on the main thread. - WebRtcLocalAudioRenderer(WebRtcLocalAudioTrack* audio_track, + WebRtcLocalAudioRenderer(const blink::WebMediaStreamTrack& audio_track, int source_render_view_id, int session_id, - int sample_rate, int frames_per_buffer); // MediaStreamAudioRenderer implementation. @@ -71,21 +73,16 @@ class CONTENT_EXPORT WebRtcLocalAudioRenderer virtual ~WebRtcLocalAudioRenderer(); private: - // WebRtcAudioCapturerSink implementation. + // MediaStreamAudioSink implementation. // Called on the AudioInputDevice worker thread. - virtual int CaptureData(const std::vector<int>& channels, - const int16* audio_data, - int sample_rate, - int number_of_channels, - int number_of_frames, - int audio_delay_milliseconds, - int current_volume, - bool need_audio_processing, - bool key_pressed) OVERRIDE; - - // Can be called on different user thread. - virtual void SetCaptureFormat(const media::AudioParameters& params) OVERRIDE; + virtual void OnData(const int16* audio_data, + int sample_rate, + int number_of_channels, + int number_of_frames) OVERRIDE; + + // Called on the AudioInputDevice worker thread. + virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE; // media::AudioRendererSink::RenderCallback implementation. // Render() is called on the AudioOutputDevice thread and OnRenderError() @@ -94,37 +91,52 @@ class CONTENT_EXPORT WebRtcLocalAudioRenderer int audio_delay_milliseconds) OVERRIDE; virtual void OnRenderError() OVERRIDE; + // Initializes and starts the |sink_| if + // we have received valid |source_params_| && + // |playing_| has been set to true && + // |volume_| is not zero. + void MaybeStartSink(); + + // Sets new |source_params_| and then re-initializes and restarts |sink_|. + void ReconfigureSink(const media::AudioParameters& params); + // The audio track which provides data to render. Given that this class // implements local loopback, the audio track is getting data from a capture // instance like a selected microphone and forwards the recorded data to its // sinks. The recorded data is stored in a FIFO and consumed // by this class when the sink asks for new data. - // The WebRtcAudioCapturer is today created by WebRtcAudioDeviceImpl. - scoped_refptr<WebRtcLocalAudioTrack> audio_track_; + // This class is calling MediaStreamAudioSink::AddToAudioTrack() and + // MediaStreamAudioSink::RemoveFromAudioTrack() to connect and disconnect + // with the audio track. + blink::WebMediaStreamTrack audio_track_; // The render view in which the audio is rendered into |sink_|. const int source_render_view_id_; const int session_id_; + // MessageLoop associated with the single thread that performs all control + // tasks. Set to the MessageLoop that invoked the ctor. + const scoped_refptr<base::MessageLoopProxy> message_loop_; + // The sink (destination) for rendered audio. scoped_refptr<media::AudioOutputDevice> sink_; - // Used to DCHECK that we are called on the correct thread. - base::ThreadChecker thread_checker_; - // Contains copies of captured audio frames. scoped_ptr<media::AudioFifo> loopback_fifo_; // Stores last time a render callback was received. The time difference // between a new time stamp and this value can be used to derive the // total render time. - base::Time last_render_time_; + base::TimeTicks last_render_time_; // Keeps track of total time audio has been rendered. base::TimeDelta total_render_time_; - // The audio parameters used by the renderer. - media::AudioParameters audio_params_; + // The audio parameters of the capture source. + media::AudioParameters source_params_; + + // The audio parameters used by the sink. + media::AudioParameters sink_params_; // Set when playing, cleared when paused. bool playing_; @@ -132,14 +144,22 @@ class CONTENT_EXPORT WebRtcLocalAudioRenderer // Protects |loopback_fifo_|, |playing_| and |sink_|. mutable base::Lock thread_lock_; - // The preferred sample rate and buffer sizes provided via the ctor. - const int sample_rate_; + // The preferred buffer size provided via the ctor. const int frames_per_buffer_; // The preferred device id of the output device or empty for the default // output device. const std::string output_device_id_; + // Cache value for the volume. + float volume_; + + // Flag to indicate whether |sink_| has been started yet. + bool sink_started_; + + // Used to DCHECK that some methods are called on the capture audio thread. + base::ThreadChecker capture_thread_checker_; + DISALLOW_COPY_AND_ASSIGN(WebRtcLocalAudioRenderer); }; diff --git a/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc b/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc index cc70c785a97..bc5f80dfe37 100644 --- a/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc +++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc @@ -9,9 +9,9 @@ #include "media/audio/audio_parameters.h" #include "media/base/audio_fifo.h" #include "media/base/audio_hardware_config.h" -#include "third_party/WebKit/public/web/WebAudioSourceProviderClient.h" +#include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h" -using WebKit::WebVector; +using blink::WebVector; namespace content { @@ -23,111 +23,101 @@ static const size_t kMaxNumberOfBuffers = 10; const size_t WebRtcLocalAudioSourceProvider::kWebAudioRenderBufferSize = 128; WebRtcLocalAudioSourceProvider::WebRtcLocalAudioSourceProvider() - : audio_delay_ms_(0), - volume_(1), - key_pressed_(false), - is_enabled_(false) { -} - -WebRtcLocalAudioSourceProvider::~WebRtcLocalAudioSourceProvider() { - if (audio_converter_.get()) - audio_converter_->RemoveInput(this); -} - -void WebRtcLocalAudioSourceProvider::Initialize( - const media::AudioParameters& source_params) { - DCHECK(thread_checker_.CalledOnValidThread()); - - // Use the native audio output hardware sample-rate for the sink. + : is_enabled_(false) { + // Get the native audio output hardware sample-rate for the sink. + // We need to check if RenderThreadImpl is valid here since the unittests + // do not have one and they will inject their own |sink_params_| for testing. if (RenderThreadImpl::current()) { media::AudioHardwareConfig* hardware_config = RenderThreadImpl::current()->GetAudioHardwareConfig(); int sample_rate = hardware_config->GetOutputSampleRate(); sink_params_.Reset( - source_params.format(), media::CHANNEL_LAYOUT_STEREO, 2, 0, - sample_rate, source_params.bits_per_sample(), + media::AudioParameters::AUDIO_PCM_LOW_LATENCY, + media::CHANNEL_LAYOUT_STEREO, 2, 0, sample_rate, 16, kWebAudioRenderBufferSize); - } else { - // This happens on unittests which does not have a valid RenderThreadImpl, - // the unittests should have injected their own |sink_params_| for testing. - DCHECK(sink_params_.IsValid()); } +} + +WebRtcLocalAudioSourceProvider::~WebRtcLocalAudioSourceProvider() { + if (audio_converter_.get()) + audio_converter_->RemoveInput(this); +} + +void WebRtcLocalAudioSourceProvider::OnSetFormat( + const media::AudioParameters& params) { + // We need detach the thread here because it will be a new capture thread + // calling OnSetFormat() and OnData() if the source is restarted. + capture_thread_checker_.DetachFromThread(); + DCHECK(capture_thread_checker_.CalledOnValidThread()); + DCHECK(params.IsValid()); + DCHECK(sink_params_.IsValid()); base::AutoLock auto_lock(lock_); - source_params_ = source_params; + source_params_ = params; // Create the audio converter with |disable_fifo| as false so that the // converter will request source_params.frames_per_buffer() each time. // This will not increase the complexity as there is only one client to // the converter. audio_converter_.reset( - new media::AudioConverter(source_params, sink_params_, false)); + new media::AudioConverter(params, sink_params_, false)); audio_converter_->AddInput(this); fifo_.reset(new media::AudioFifo( - source_params.channels(), - kMaxNumberOfBuffers * source_params.frames_per_buffer())); + params.channels(), + kMaxNumberOfBuffers * params.frames_per_buffer())); + input_bus_ = media::AudioBus::Create(params.channels(), + params.frames_per_buffer()); } -void WebRtcLocalAudioSourceProvider::DeliverData( - media::AudioBus* audio_source, - int audio_delay_milliseconds, - int volume, - bool key_pressed) { +void WebRtcLocalAudioSourceProvider::OnData( + const int16* audio_data, + int sample_rate, + int number_of_channels, + int number_of_frames) { + DCHECK(capture_thread_checker_.CalledOnValidThread()); base::AutoLock auto_lock(lock_); if (!is_enabled_) return; DCHECK(fifo_.get()); - if (fifo_->frames() + audio_source->frames() <= fifo_->max_frames()) { - fifo_->Push(audio_source); + // TODO(xians): A better way to handle the interleaved and deinterleaved + // format switching, see issue/317710. + DCHECK(input_bus_->frames() == number_of_frames); + DCHECK(input_bus_->channels() == number_of_channels); + input_bus_->FromInterleaved(audio_data, number_of_frames, 2); + + if (fifo_->frames() + number_of_frames <= fifo_->max_frames()) { + fifo_->Push(input_bus_.get()); } else { // This can happen if the data in FIFO is too slowed to be consumed or // WebAudio stops consuming data. DLOG(WARNING) << "Local source provicer FIFO is full" << fifo_->frames(); } - - // Cache the values for GetAudioProcessingParams(). - last_fill_ = base::TimeTicks::Now(); - audio_delay_ms_ = audio_delay_milliseconds; - volume_ = volume; - key_pressed_ = key_pressed; -} - -void WebRtcLocalAudioSourceProvider::GetAudioProcessingParams( - int* delay_ms, int* volume, bool* key_pressed) { - int elapsed_ms = 0; - if (!last_fill_.is_null()) { - elapsed_ms = static_cast<int>( - (base::TimeTicks::Now() - last_fill_).InMilliseconds()); - } - *delay_ms = audio_delay_ms_ + elapsed_ms + static_cast<int>( - 1000 * fifo_->frames() / source_params_.sample_rate() + 0.5); - *volume = volume_; - *key_pressed = key_pressed_; } void WebRtcLocalAudioSourceProvider::setClient( - WebKit::WebAudioSourceProviderClient* client) { + blink::WebAudioSourceProviderClient* client) { NOTREACHED(); } void WebRtcLocalAudioSourceProvider::provideInput( const WebVector<float*>& audio_data, size_t number_of_frames) { DCHECK_EQ(number_of_frames, kWebAudioRenderBufferSize); - if (!bus_wrapper_ || - static_cast<size_t>(bus_wrapper_->channels()) != audio_data.size()) { - bus_wrapper_ = media::AudioBus::CreateWrapper(audio_data.size()); + if (!output_wrapper_ || + static_cast<size_t>(output_wrapper_->channels()) != audio_data.size()) { + output_wrapper_ = media::AudioBus::CreateWrapper(audio_data.size()); } - bus_wrapper_->set_frames(number_of_frames); + output_wrapper_->set_frames(number_of_frames); for (size_t i = 0; i < audio_data.size(); ++i) - bus_wrapper_->SetChannelData(i, audio_data[i]); + output_wrapper_->SetChannelData(i, audio_data[i]); base::AutoLock auto_lock(lock_); - DCHECK(audio_converter_.get()); - DCHECK(fifo_.get()); + if (!audio_converter_) + return; + is_enabled_ = true; - audio_converter_->Convert(bus_wrapper_.get()); + audio_converter_->Convert(output_wrapper_.get()); } double WebRtcLocalAudioSourceProvider::ProvideInput( @@ -136,11 +126,9 @@ double WebRtcLocalAudioSourceProvider::ProvideInput( fifo_->Consume(audio_bus, 0, audio_bus->frames()); } else { audio_bus->Zero(); - if (!last_fill_.is_null()) { - DLOG(WARNING) << "Underrun, FIFO has data " << fifo_->frames() - << " samples but " << audio_bus->frames() - << " samples are needed"; - } + DVLOG(1) << "WARNING: Underrun, FIFO has data " << fifo_->frames() + << " samples but " << audio_bus->frames() + << " samples are needed"; } return 1.0; @@ -148,7 +136,6 @@ double WebRtcLocalAudioSourceProvider::ProvideInput( void WebRtcLocalAudioSourceProvider::SetSinkParamsForTesting( const media::AudioParameters& sink_params) { - DCHECK(thread_checker_.CalledOnValidThread()); sink_params_ = sink_params; } diff --git a/chromium/content/renderer/media/webrtc_local_audio_source_provider.h b/chromium/content/renderer/media/webrtc_local_audio_source_provider.h index 23ba215db81..eb437fabe59 100644 --- a/chromium/content/renderer/media/webrtc_local_audio_source_provider.h +++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider.h @@ -5,14 +5,17 @@ #ifndef CONTENT_RENDERER_MEDIA_WEBRTC_LOCAL_AUDIO_SOURCE_PROVIDER_H_ #define CONTENT_RENDERER_MEDIA_WEBRTC_LOCAL_AUDIO_SOURCE_PROVIDER_H_ +#include <vector> + #include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" #include "content/common/content_export.h" +#include "content/public/renderer/media_stream_audio_sink.h" #include "media/base/audio_converter.h" +#include "third_party/WebKit/public/platform/WebAudioSourceProvider.h" #include "third_party/WebKit/public/platform/WebVector.h" -#include "third_party/WebKit/public/web/WebAudioSourceProvider.h" namespace media { class AudioBus; @@ -21,14 +24,14 @@ class AudioFifo; class AudioParameters; } -namespace WebKit { +namespace blink { class WebAudioSourceProviderClient; } namespace content { // WebRtcLocalAudioSourceProvider provides a bridge between classes: -// WebRtcAudioCapturer ---> WebKit::WebAudioSourceProvider +// WebRtcAudioCapturer ---> blink::WebAudioSourceProvider // // WebRtcLocalAudioSourceProvider works as a sink to the WebRtcAudiocapturer // and store the capture data to a FIFO. When the media stream is connected to @@ -37,33 +40,25 @@ namespace content { // // All calls are protected by a lock. class CONTENT_EXPORT WebRtcLocalAudioSourceProvider - : NON_EXPORTED_BASE(public media::AudioConverter::InputCallback), - NON_EXPORTED_BASE(public WebKit::WebAudioSourceProvider) { + : NON_EXPORTED_BASE(public blink::WebAudioSourceProvider), + NON_EXPORTED_BASE(public media::AudioConverter::InputCallback), + NON_EXPORTED_BASE(public MediaStreamAudioSink) { public: static const size_t kWebAudioRenderBufferSize; WebRtcLocalAudioSourceProvider(); virtual ~WebRtcLocalAudioSourceProvider(); - // Initialize function for the souce provider. This can be called multiple - // times if the source format has changed. - void Initialize(const media::AudioParameters& source_params); - - // Called by the WebRtcAudioCapturer to deliever captured data into fifo on - // the capture audio thread. - void DeliverData(media::AudioBus* audio_source, - int audio_delay_milliseconds, - int volume, - bool key_pressed); - - // Called by the WebAudioCapturerSource to get the audio processing params. - // This function is triggered by provideInput() on the WebAudio audio thread, - // so it has been under the protection of |lock_|. - void GetAudioProcessingParams(int* delay_ms, int* volume, bool* key_pressed); + // MediaStreamAudioSink implementation. + virtual void OnData(const int16* audio_data, + int sample_rate, + int number_of_channels, + int number_of_frames) OVERRIDE; + virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE; - // WebKit::WebAudioSourceProvider implementation. - virtual void setClient(WebKit::WebAudioSourceProviderClient* client) OVERRIDE; - virtual void provideInput(const WebKit::WebVector<float*>& audio_data, + // blink::WebAudioSourceProvider implementation. + virtual void setClient(blink::WebAudioSourceProviderClient* client) OVERRIDE; + virtual void provideInput(const blink::WebVector<float*>& audio_data, size_t number_of_frames) OVERRIDE; // media::AudioConverter::Inputcallback implementation. @@ -82,15 +77,13 @@ class CONTENT_EXPORT WebRtcLocalAudioSourceProvider void SetSinkParamsForTesting(const media::AudioParameters& sink_params); private: - // Used to DCHECK that we are called on the correct thread. - base::ThreadChecker thread_checker_; + // Used to DCHECK that some methods are called on the capture audio thread. + base::ThreadChecker capture_thread_checker_; scoped_ptr<media::AudioConverter> audio_converter_; scoped_ptr<media::AudioFifo> fifo_; - scoped_ptr<media::AudioBus> bus_wrapper_; - int audio_delay_ms_; - int volume_; - bool key_pressed_; + scoped_ptr<media::AudioBus> input_bus_; + scoped_ptr<media::AudioBus> output_wrapper_; bool is_enabled_; media::AudioParameters source_params_; media::AudioParameters sink_params_; diff --git a/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc b/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc index c23ce0ee634..5b7e8526898 100644 --- a/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc +++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc @@ -19,23 +19,25 @@ class WebRtcLocalAudioSourceProviderTest : public testing::Test { media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_STEREO, 2, 0, 44100, 16, WebRtcLocalAudioSourceProvider::kWebAudioRenderBufferSize); - source_bus_ = media::AudioBus::Create(source_params_); + const int length = + source_params_.frames_per_buffer() * source_params_.channels(); + source_data_.reset(new int16[length]); sink_bus_ = media::AudioBus::Create(sink_params_); source_provider_.reset(new WebRtcLocalAudioSourceProvider()); source_provider_->SetSinkParamsForTesting(sink_params_); - source_provider_->Initialize(source_params_); + source_provider_->OnSetFormat(source_params_); } media::AudioParameters source_params_; + scoped_ptr<int16[]> source_data_; media::AudioParameters sink_params_; - scoped_ptr<media::AudioBus> source_bus_; scoped_ptr<media::AudioBus> sink_bus_; scoped_ptr<WebRtcLocalAudioSourceProvider> source_provider_; }; TEST_F(WebRtcLocalAudioSourceProviderTest, VerifyDataFlow) { // Point the WebVector into memory owned by |sink_bus_|. - WebKit::WebVector<float*> audio_data( + blink::WebVector<float*> audio_data( static_cast<size_t>(sink_bus_->channels())); for (size_t i = 0; i < audio_data.size(); ++i) audio_data[i] = sink_bus_->channel(i); @@ -47,12 +49,15 @@ TEST_F(WebRtcLocalAudioSourceProviderTest, VerifyDataFlow) { EXPECT_TRUE(sink_bus_->channel(0)[0] == 0); // Set the value of source data to be 1. - for (int i = 0; i < source_params_.frames_per_buffer(); ++i) { - source_bus_->channel(0)[i] = 1; - } + const int length = + source_params_.frames_per_buffer() * source_params_.channels(); + std::fill(source_data_.get(), source_data_.get() + length, 1); // Deliver data to |source_provider_|. - source_provider_->DeliverData(source_bus_.get(), 0, 0, false); + source_provider_->OnData(source_data_.get(), + source_params_.sample_rate(), + source_params_.channels(), + source_params_.frames_per_buffer()); // Consume the first packet in the resampler, which contains only zero. // And the consumption of the data will trigger pulling the real packet from @@ -69,7 +74,10 @@ TEST_F(WebRtcLocalAudioSourceProviderTest, VerifyDataFlow) { } // Prepare the second packet for featching. - source_provider_->DeliverData(source_bus_.get(), 0, 0, false); + source_provider_->OnData(source_data_.get(), + source_params_.sample_rate(), + source_params_.channels(), + source_params_.frames_per_buffer()); // Verify the packets. for (int i = 0; i < source_params_.frames_per_buffer(); @@ -83,39 +91,4 @@ TEST_F(WebRtcLocalAudioSourceProviderTest, VerifyDataFlow) { } } -TEST_F(WebRtcLocalAudioSourceProviderTest, VerifyAudioProcessingParams) { - // Point the WebVector into memory owned by |sink_bus_|. - WebKit::WebVector<float*> audio_data( - static_cast<size_t>(sink_bus_->channels())); - for (size_t i = 0; i < audio_data.size(); ++i) - audio_data[i] = sink_bus_->channel(i); - - // Enable the source provider. - source_provider_->provideInput(audio_data, sink_params_.frames_per_buffer()); - - // Deliver data to |source_provider_| with audio processing params. - int source_delay = 5; - int source_volume = 255; - bool source_key_pressed = true; - source_provider_->DeliverData(source_bus_.get(), source_delay, - source_volume, source_key_pressed); - - int delay = 0, volume = 0; - bool key_pressed = false; - source_provider_->GetAudioProcessingParams(&delay, &volume, &key_pressed); - EXPECT_EQ(volume, source_volume); - EXPECT_EQ(key_pressed, source_key_pressed); - int expected_delay = source_delay + static_cast<int>( - source_bus_->frames() / source_params_.sample_rate() + 0.5); - EXPECT_GE(delay, expected_delay); - - // Sleep a few ms to simulate processing time. This should increase the delay - // value as time passes. - int cached_delay = delay; - const int kSleepMs = 10; - base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(kSleepMs)); - source_provider_->GetAudioProcessingParams(&delay, &volume, &key_pressed); - EXPECT_GT(delay, cached_delay); -} - } // namespace content diff --git a/chromium/content/renderer/media/webrtc_local_audio_track.cc b/chromium/content/renderer/media/webrtc_local_audio_track.cc index c79757613fe..8afa06feab2 100644 --- a/chromium/content/renderer/media/webrtc_local_audio_track.cc +++ b/chromium/content/renderer/media/webrtc_local_audio_track.cc @@ -4,9 +4,12 @@ #include "content/renderer/media/webrtc_local_audio_track.h" +#include "content/public/renderer/media_stream_audio_sink.h" +#include "content/renderer/media/media_stream_audio_sink_owner.h" +#include "content/renderer/media/media_stream_audio_track_sink.h" +#include "content/renderer/media/peer_connection_audio_sink_owner.h" #include "content/renderer/media/webaudio_capturer_source.h" #include "content/renderer/media/webrtc_audio_capturer.h" -#include "content/renderer/media/webrtc_audio_capturer_sink_owner.h" #include "content/renderer/media/webrtc_local_audio_source_provider.h" #include "media/base/audio_fifo.h" #include "third_party/libjingle/source/talk/media/base/audiorenderer.h" @@ -54,28 +57,39 @@ bool NeedsAudioProcessing( // This is a temporary audio buffer with parameters used to send data to // callbacks. -class WebRtcLocalAudioTrack::ConfiguredBuffer : - public base::RefCounted<WebRtcLocalAudioTrack::ConfiguredBuffer> { +class WebRtcLocalAudioTrack::ConfiguredBuffer { public: - ConfiguredBuffer() : sink_buffer_size_(0) {} + ConfiguredBuffer() {} + virtual ~ConfiguredBuffer() {} - void Initialize(const media::AudioParameters& params) { + void Configure(const media::AudioParameters& params) { DCHECK(params.IsValid()); - params_ = params; - // Use 10ms as the sink buffer size since that is the native packet size - // WebRtc is running on. - sink_buffer_size_ = params.sample_rate() / 100; - audio_wrapper_ = - media::AudioBus::Create(params.channels(), sink_buffer_size_); - buffer_.reset(new int16[sink_buffer_size_ * params.channels()]); + // PeerConnection uses 10ms as the sink buffer size as its native packet + // size. We use the native PeerConnection buffer size to achieve the best + // performance when a PeerConnection is connected with a track. + int sink_buffer_size = params.sample_rate() / 100; + if (params.frames_per_buffer() < sink_buffer_size) { + // When the source is running with a buffer size smaller than the peer + // connection buffer size, that means no PeerConnection is connected + // to the track, use the same buffer size as the incoming format to + // avoid extra FIFO for WebAudio. + sink_buffer_size = params.frames_per_buffer(); + } + params_.Reset(params.format(), params.channel_layout(), params.channels(), + params.input_channels(), params.sample_rate(), + params.bits_per_sample(), sink_buffer_size); + + audio_wrapper_ = media::AudioBus::Create(params_.channels(), + params_.frames_per_buffer()); + buffer_.reset(new int16[params_.frames_per_buffer() * params_.channels()]); // The size of the FIFO should be at least twice of the source buffer size // or twice of the sink buffer size. int buffer_size = std::max( kMaxNumberOfBuffersInFifo * params.frames_per_buffer(), - kMaxNumberOfBuffersInFifo * sink_buffer_size_); - fifo_.reset(new media::AudioFifo(params.channels(), buffer_size)); + kMaxNumberOfBuffersInFifo * params_.frames_per_buffer()); + fifo_.reset(new media::AudioFifo(params_.channels(), buffer_size)); } void Push(media::AudioBus* audio_source) { @@ -95,18 +109,15 @@ class WebRtcLocalAudioTrack::ConfiguredBuffer : } int16* buffer() const { return buffer_.get(); } + + // Format of the output audio buffer. const media::AudioParameters& params() const { return params_; } - int sink_buffer_size() const { return sink_buffer_size_; } private: - ~ConfiguredBuffer() {} - friend class base::RefCounted<WebRtcLocalAudioTrack::ConfiguredBuffer>; - media::AudioParameters params_; scoped_ptr<media::AudioBus> audio_wrapper_; scoped_ptr<media::AudioFifo> fifo_; scoped_ptr<int16[]> buffer_; - int sink_buffer_size_; }; scoped_refptr<WebRtcLocalAudioTrack> WebRtcLocalAudioTrack::Create( @@ -131,13 +142,18 @@ WebRtcLocalAudioTrack::WebRtcLocalAudioTrack( capturer_(capturer), webaudio_source_(webaudio_source), track_source_(track_source), - need_audio_processing_(NeedsAudioProcessing(constraints)) { + need_audio_processing_(NeedsAudioProcessing(constraints)), + buffer_(new ConfiguredBuffer()) { DCHECK(capturer.get() || webaudio_source); + if (!webaudio_source_) { + source_provider_.reset(new WebRtcLocalAudioSourceProvider()); + AddSink(source_provider_.get()); + } DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()"; } WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(main_render_thread_checker_.CalledOnValidThread()); DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()"; // Users might not call Stop() on the track. Stop(); @@ -147,47 +163,59 @@ void WebRtcLocalAudioTrack::Capture(media::AudioBus* audio_source, int audio_delay_milliseconds, int volume, bool key_pressed) { + DCHECK(capture_thread_checker_.CalledOnValidThread()); scoped_refptr<WebRtcAudioCapturer> capturer; std::vector<int> voe_channels; - int sample_rate = 0; - int number_of_channels = 0; - int number_of_frames = 0; - SinkList sinks; - scoped_refptr<ConfiguredBuffer> current_buffer; + SinkList::ItemList sinks; + SinkList::ItemList sinks_to_notify_format; + bool is_webaudio_source = false; { base::AutoLock auto_lock(lock_); capturer = capturer_; voe_channels = voe_channels_; - current_buffer = buffer_; - sample_rate = current_buffer->params().sample_rate(); - number_of_channels = current_buffer->params().channels(); - number_of_frames = current_buffer->sink_buffer_size(); - sinks = sinks_; + sinks = sinks_.Items(); + sinks_.RetrieveAndClearTags(&sinks_to_notify_format); + is_webaudio_source = (webaudio_source_.get() != NULL); + } + + // Notify the tracks on when the format changes. This will do nothing if + // |sinks_to_notify_format| is empty. + for (SinkList::ItemList::const_iterator it = sinks_to_notify_format.begin(); + it != sinks_to_notify_format.end(); ++it) { + (*it)->OnSetFormat(buffer_->params()); } // Push the data to the fifo. - current_buffer->Push(audio_source); - // Only turn off the audio processing when the constraint is set to false as - // well as there is no correct delay value. - bool need_audio_processing = need_audio_processing_ ? - need_audio_processing_ : (audio_delay_milliseconds != 0); + buffer_->Push(audio_source); + + // When the source is WebAudio, turn off the audio processing if the delay + // value is 0 even though the constraint is set to true. In such case, it + // indicates the data is not from microphone. + // TODO(xians): remove the flag when supporting one APM per audio track. + // See crbug/264611 for details. + bool need_audio_processing = need_audio_processing_; + if (is_webaudio_source && need_audio_processing) + need_audio_processing = (audio_delay_milliseconds != 0); + int current_volume = volume; - while (current_buffer->Consume()) { + while (buffer_->Consume()) { // Feed the data to the sinks. // TODO (jiayl): we should not pass the real audio data down if the track is // disabled. This is currently done so to feed input to WebRTC typing // detection and should be changed when audio processing is moved from // WebRTC to the track. - for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) { - int new_volume = (*it)->CaptureData(voe_channels, - current_buffer->buffer(), - sample_rate, - number_of_channels, - number_of_frames, - audio_delay_milliseconds, - current_volume, - need_audio_processing, - key_pressed); + for (SinkList::ItemList::const_iterator it = sinks.begin(); + it != sinks.end(); + ++it) { + int new_volume = (*it)->OnData(buffer_->buffer(), + buffer_->params().sample_rate(), + buffer_->params().channels(), + buffer_->params().frames_per_buffer(), + voe_channels, + audio_delay_milliseconds, + current_volume, + need_audio_processing, + key_pressed); if (new_volume != 0 && capturer.get()) { // Feed the new volume to WebRtc while changing the volume on the // browser. @@ -198,26 +226,20 @@ void WebRtcLocalAudioTrack::Capture(media::AudioBus* audio_source, } } -void WebRtcLocalAudioTrack::SetCaptureFormat( +void WebRtcLocalAudioTrack::OnSetFormat( const media::AudioParameters& params) { - if (!params.IsValid()) - return; + DVLOG(1) << "WebRtcLocalAudioTrack::OnSetFormat()"; + // If the source is restarted, we might have changed to another capture + // thread. + capture_thread_checker_.DetachFromThread(); + DCHECK(capture_thread_checker_.CalledOnValidThread()); - scoped_refptr<ConfiguredBuffer> new_buffer(new ConfiguredBuffer()); - new_buffer->Initialize(params); + DCHECK(params.IsValid()); + buffer_->Configure(params); - SinkList sinks; - { - base::AutoLock auto_lock(lock_); - buffer_ = new_buffer; - sinks = sinks_; - } - - // Update all the existing sinks with the new format. - for (SinkList::const_iterator it = sinks.begin(); - it != sinks.end(); ++it) { - (*it)->SetCaptureFormat(params); - } + base::AutoLock auto_lock(lock_); + // Remember to notify all sinks of the new format. + sinks_.TagAll(); } void WebRtcLocalAudioTrack::AddChannel(int channel_id) { @@ -257,65 +279,101 @@ std::string WebRtcLocalAudioTrack::kind() const { return kAudioTrackKind; } -void WebRtcLocalAudioTrack::AddSink(WebRtcAudioCapturerSink* sink) { - DCHECK(thread_checker_.CalledOnValidThread()); +void WebRtcLocalAudioTrack::AddSink(MediaStreamAudioSink* sink) { + DCHECK(main_render_thread_checker_.CalledOnValidThread()); DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()"; base::AutoLock auto_lock(lock_); - if (buffer_.get()) - sink->SetCaptureFormat(buffer_->params()); // Verify that |sink| is not already added to the list. - DCHECK(std::find_if( - sinks_.begin(), sinks_.end(), - WebRtcAudioCapturerSinkOwner::WrapsSink(sink)) == sinks_.end()); - - // Create (and add to the list) a new WebRtcAudioCapturerSinkOwner which owns - // the |sink| and delagates all calls to the WebRtcAudioCapturerSink - // interface. - sinks_.push_back(new WebRtcAudioCapturerSinkOwner(sink)); + DCHECK(!sinks_.Contains( + MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink))); + + // Create (and add to the list) a new MediaStreamAudioTrackSink + // which owns the |sink| and delagates all calls to the + // MediaStreamAudioSink interface. It will be tagged in the list, so + // we remember to call OnSetFormat() on the new sink. + scoped_refptr<MediaStreamAudioTrackSink> sink_owner( + new MediaStreamAudioSinkOwner(sink)); + sinks_.AddAndTag(sink_owner); } -void WebRtcLocalAudioTrack::RemoveSink( - WebRtcAudioCapturerSink* sink) { - DCHECK(thread_checker_.CalledOnValidThread()); +void WebRtcLocalAudioTrack::RemoveSink(MediaStreamAudioSink* sink) { + DCHECK(main_render_thread_checker_.CalledOnValidThread()); DVLOG(1) << "WebRtcLocalAudioTrack::RemoveSink()"; base::AutoLock auto_lock(lock_); - // Get iterator to the first element for which WrapsSink(sink) returns true. - SinkList::iterator it = std::find_if( - sinks_.begin(), sinks_.end(), - WebRtcAudioCapturerSinkOwner::WrapsSink(sink)); - if (it != sinks_.end()) { - // Clear the delegate to ensure that no more capture callbacks will - // be sent to this sink. Also avoids a possible crash which can happen - // if this method is called while capturing is active. - (*it)->Reset(); - sinks_.erase(it); - } + + scoped_refptr<MediaStreamAudioTrackSink> removed_item = sinks_.Remove( + MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink)); + + // Clear the delegate to ensure that no more capture callbacks will + // be sent to this sink. Also avoids a possible crash which can happen + // if this method is called while capturing is active. + if (removed_item.get()) + removed_item->Reset(); +} + +void WebRtcLocalAudioTrack::AddSink(PeerConnectionAudioSink* sink) { + DCHECK(main_render_thread_checker_.CalledOnValidThread()); + DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()"; + base::AutoLock auto_lock(lock_); + + // Verify that |sink| is not already added to the list. + DCHECK(!sinks_.Contains( + MediaStreamAudioTrackSink::WrapsPeerConnectionSink(sink))); + + // Create (and add to the list) a new MediaStreamAudioTrackSink + // which owns the |sink| and delagates all calls to the + // MediaStreamAudioSink interface. It will be tagged in the list, so + // we remember to call OnSetFormat() on the new sink. + scoped_refptr<MediaStreamAudioTrackSink> sink_owner( + new PeerConnectionAudioSinkOwner(sink)); + sinks_.AddAndTag(sink_owner); +} + +void WebRtcLocalAudioTrack::RemoveSink(PeerConnectionAudioSink* sink) { + DCHECK(main_render_thread_checker_.CalledOnValidThread()); + DVLOG(1) << "WebRtcLocalAudioTrack::RemoveSink()"; + + base::AutoLock auto_lock(lock_); + + scoped_refptr<MediaStreamAudioTrackSink> removed_item = sinks_.Remove( + MediaStreamAudioTrackSink::WrapsPeerConnectionSink(sink)); + // Clear the delegate to ensure that no more capture callbacks will + // be sent to this sink. Also avoids a possible crash which can happen + // if this method is called while capturing is active. + if (removed_item.get()) + removed_item->Reset(); } void WebRtcLocalAudioTrack::Start() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(main_render_thread_checker_.CalledOnValidThread()); DVLOG(1) << "WebRtcLocalAudioTrack::Start()"; if (webaudio_source_.get()) { // If the track is hooking up with WebAudio, do NOT add the track to the // capturer as its sink otherwise two streams in different clock will be // pushed through the same track. - WebRtcLocalAudioSourceProvider* source_provider = NULL; - if (capturer_.get()) { - source_provider = static_cast<WebRtcLocalAudioSourceProvider*>( - capturer_->audio_source_provider()); - } - webaudio_source_->Start(this, source_provider); + webaudio_source_->Start(this, capturer_.get()); return; } if (capturer_.get()) capturer_->AddTrack(this); + + SinkList::ItemList sinks; + { + base::AutoLock auto_lock(lock_); + sinks = sinks_.Items(); + } + for (SinkList::ItemList::const_iterator it = sinks.begin(); + it != sinks.end(); + ++it) { + (*it)->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateLive); + } } void WebRtcLocalAudioTrack::Stop() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(main_render_thread_checker_.CalledOnValidThread()); DVLOG(1) << "WebRtcLocalAudioTrack::Stop()"; if (!capturer_.get() && !webaudio_source_.get()) return; @@ -327,21 +385,28 @@ void WebRtcLocalAudioTrack::Stop() { // in such case and no need to call RemoveTrack(). webaudio_source_->Stop(); } else { + // It is necessary to call RemoveTrack on the |capturer_| to avoid getting + // audio callback after Stop(). capturer_->RemoveTrack(this); } // Protect the pointers using the lock when accessing |sinks_| and // setting the |capturer_| to NULL. - SinkList sinks; + SinkList::ItemList sinks; { base::AutoLock auto_lock(lock_); - sinks = sinks_; + sinks = sinks_.Items(); + sinks_.Clear(); webaudio_source_ = NULL; capturer_ = NULL; } - for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) + for (SinkList::ItemList::const_iterator it = sinks.begin(); + it != sinks.end(); + ++it){ + (*it)->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateEnded); (*it)->Reset(); + } } } // namespace content diff --git a/chromium/content/renderer/media/webrtc_local_audio_track.h b/chromium/content/renderer/media/webrtc_local_audio_track.h index 01b11208021..0ad463b2cdf 100644 --- a/chromium/content/renderer/media/webrtc_local_audio_track.h +++ b/chromium/content/renderer/media/webrtc_local_audio_track.h @@ -10,7 +10,10 @@ #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" +#include "content/renderer/media/media_stream_audio_track_sink.h" +#include "content/renderer/media/tagged_list.h" #include "content/renderer/media/webrtc_audio_device_impl.h" +#include "content/renderer/media/webrtc_local_audio_source_provider.h" #include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h" #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h" #include "third_party/libjingle/source/talk/app/webrtc/mediastreamtrack.h" @@ -26,12 +29,14 @@ class AudioBus; namespace content { +class MediaStreamAudioSink; +class MediaStreamAudioSinkOwner; +class PeerConnectionAudioSink; class WebAudioCapturerSource; class WebRtcAudioCapturer; -class WebRtcAudioCapturerSinkOwner; // A WebRtcLocalAudioTrack instance contains the implementations of -// MediaStreamTrack and WebRtcAudioCapturerSink. +// MediaStreamTrack and MediaStreamAudioSink. // When an instance is created, it will register itself as a track to the // WebRtcAudioCapturer to get the captured data, and forward the data to // its |sinks_|. The data flow can be stopped by disabling the audio track. @@ -47,14 +52,20 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack webrtc::AudioSourceInterface* track_source, const webrtc::MediaConstraintsInterface* constraints); - // Add a sink to the track. This function will trigger a SetCaptureFormat() + // Add a sink to the track. This function will trigger a OnSetFormat() // call on the |sink|. // Called on the main render thread. - void AddSink(WebRtcAudioCapturerSink* sink); + void AddSink(MediaStreamAudioSink* sink); // Remove a sink from the track. // Called on the main render thread. - void RemoveSink(WebRtcAudioCapturerSink* sink); + void RemoveSink(MediaStreamAudioSink* sink); + + // Add/remove PeerConnection sink to/from the track. + // TODO(xians): Remove these two methods after PeerConnection can use the + // same sink interface as MediaStreamAudioSink. + void AddSink(PeerConnectionAudioSink* sink); + void RemoveSink(PeerConnectionAudioSink* sink); // Starts the local audio track. Called on the main render thread and // should be called only once when audio track is created. @@ -65,6 +76,7 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack void Stop(); // Method called by the capturer to deliver the capture data. + // Call on the capture audio thread. void Capture(media::AudioBus* audio_source, int audio_delay_milliseconds, int volume, @@ -72,8 +84,12 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack // Method called by the capturer to set the audio parameters used by source // of the capture data.. - // Can be called on different user threads. - void SetCaptureFormat(const media::AudioParameters& params); + // Call on the capture audio thread. + void OnSetFormat(const media::AudioParameters& params); + + blink::WebAudioSourceProvider* audio_source_provider() const { + return source_provider_.get(); + } protected: WebRtcLocalAudioTrack( @@ -86,7 +102,7 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack virtual ~WebRtcLocalAudioTrack(); private: - typedef std::list<scoped_refptr<WebRtcAudioCapturerSinkOwner> > SinkList; + typedef TaggedList<MediaStreamAudioTrackSink> SinkList; // cricket::AudioCapturer implementation. virtual void AddChannel(int channel_id) OVERRIDE; @@ -111,24 +127,33 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack // TODO(xians): merge |track_source_| to |capturer_|. talk_base::scoped_refptr<webrtc::AudioSourceInterface> track_source_; - // A list of sinks that the audio data is fed to. + // A tagged list of sinks that the audio data is fed to. Tags + // indicate tracks that need to be notified that the audio format + // has changed. SinkList sinks_; - // Used to DCHECK that we are called on the correct thread. - base::ThreadChecker thread_checker_; + // Used to DCHECK that some methods are called on the main render thread. + base::ThreadChecker main_render_thread_checker_; + + // Used to DCHECK that some methods are called on the capture audio thread. + base::ThreadChecker capture_thread_checker_; // Protects |params_| and |sinks_|. mutable base::Lock lock_; - // A vector of WebRtc VoE channels that the capturer sends datat to. + // A vector of WebRtc VoE channels that the capturer sends data to. std::vector<int> voe_channels_; bool need_audio_processing_; // Buffers used for temporary storage during capture callbacks. - // Allocated during initialization. + // Allocated and accessed only on the capture audio thread. class ConfiguredBuffer; - scoped_refptr<ConfiguredBuffer> buffer_; + scoped_ptr<ConfiguredBuffer> buffer_; + + // The source provider to feed the track data to other clients like + // WebAudio. + scoped_ptr<WebRtcLocalAudioSourceProvider> source_provider_; DISALLOW_COPY_AND_ASSIGN(WebRtcLocalAudioTrack); }; diff --git a/chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc b/chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc index 1014ebe3332..a43577669d6 100644 --- a/chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc +++ b/chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc @@ -6,6 +6,7 @@ #include "base/test/test_timeouts.h" #include "content/renderer/media/rtc_media_constraints.h" #include "content/renderer/media/webrtc_audio_capturer.h" +#include "content/renderer/media/webrtc_audio_device_impl.h" #include "content/renderer/media/webrtc_local_audio_source_provider.h" #include "content/renderer/media/webrtc_local_audio_track.h" #include "media/audio/audio_parameters.h" @@ -32,12 +33,13 @@ ACTION_P(SignalEvent, event) { // the |WebRtcAudioCapturer|. class FakeAudioThread : public base::PlatformThread::Delegate { public: - explicit FakeAudioThread(const scoped_refptr<WebRtcAudioCapturer>& capturer) + FakeAudioThread(const scoped_refptr<WebRtcAudioCapturer>& capturer, + const media::AudioParameters& params) : capturer_(capturer), thread_(), closure_(false, false) { DCHECK(capturer.get()); - audio_bus_ = media::AudioBus::Create(capturer_->audio_parameters()); + audio_bus_ = media::AudioBus::Create(params); } virtual ~FakeAudioThread() { DCHECK(thread_.is_null()); } @@ -81,32 +83,56 @@ class FakeAudioThread : public base::PlatformThread::Delegate { class MockCapturerSource : public media::AudioCapturerSource { public: - MockCapturerSource() {} - MOCK_METHOD3(Initialize, void(const media::AudioParameters& params, - CaptureCallback* callback, - int session_id)); - MOCK_METHOD0(Start, void()); - MOCK_METHOD0(Stop, void()); + explicit MockCapturerSource(WebRtcAudioCapturer* capturer) + : capturer_(capturer) {} + MOCK_METHOD3(OnInitialize, void(const media::AudioParameters& params, + CaptureCallback* callback, + int session_id)); + MOCK_METHOD0(OnStart, void()); + MOCK_METHOD0(OnStop, void()); MOCK_METHOD1(SetVolume, void(double volume)); MOCK_METHOD1(SetAutomaticGainControl, void(bool enable)); + virtual void Initialize(const media::AudioParameters& params, + CaptureCallback* callback, + int session_id) OVERRIDE { + DCHECK(params.IsValid()); + params_ = params; + OnInitialize(params, callback, session_id); + } + virtual void Start() OVERRIDE { + audio_thread_.reset(new FakeAudioThread(capturer_, params_)); + audio_thread_->Start(); + OnStart(); + } + virtual void Stop() OVERRIDE { + audio_thread_->Stop(); + audio_thread_.reset(); + OnStop(); + } protected: virtual ~MockCapturerSource() {} + + private: + scoped_ptr<FakeAudioThread> audio_thread_; + WebRtcAudioCapturer* capturer_; + media::AudioParameters params_; }; -class MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink { +// TODO(xians): Use MediaStreamAudioSink. +class MockMediaStreamAudioSink : public PeerConnectionAudioSink { public: - MockWebRtcAudioCapturerSink() {} - ~MockWebRtcAudioCapturerSink() {} - int CaptureData(const std::vector<int>& channels, - const int16* audio_data, - int sample_rate, - int number_of_channels, - int number_of_frames, - int audio_delay_milliseconds, - int current_volume, - bool need_audio_processing, - bool key_pressed) OVERRIDE { + MockMediaStreamAudioSink() {} + ~MockMediaStreamAudioSink() {} + int OnData(const int16* audio_data, + int sample_rate, + int number_of_channels, + int number_of_frames, + const std::vector<int>& channels, + int audio_delay_milliseconds, + int current_volume, + bool need_audio_processing, + bool key_pressed) OVERRIDE { CaptureData(channels.size(), sample_rate, number_of_channels, @@ -126,7 +152,7 @@ class MockWebRtcAudioCapturerSink : public WebRtcAudioCapturerSink { int current_volume, bool need_audio_processing, bool key_pressed)); - MOCK_METHOD1(SetCaptureFormat, void(const media::AudioParameters& params)); + MOCK_METHOD1(OnSetFormat, void(const media::AudioParameters& params)); }; } // namespace @@ -137,34 +163,18 @@ class WebRtcLocalAudioTrackTest : public ::testing::Test { params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_STEREO, 2, 0, 48000, 16, 480); capturer_ = WebRtcAudioCapturer::CreateCapturer(); - WebRtcLocalAudioSourceProvider* source_provider = - static_cast<WebRtcLocalAudioSourceProvider*>( - capturer_->audio_source_provider()); - source_provider->SetSinkParamsForTesting(params_); - capturer_source_ = new MockCapturerSource(); - EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), 0)) + capturer_source_ = new MockCapturerSource(capturer_.get()); + EXPECT_CALL(*capturer_source_.get(), OnInitialize(_, capturer_.get(), 0)) .WillOnce(Return()); capturer_->SetCapturerSource(capturer_source_, params_.channel_layout(), - params_.sample_rate()); - - EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(false)) - .WillOnce(Return()); - - // Start the audio thread used by the |capturer_source_|. - audio_thread_.reset(new FakeAudioThread(capturer_)); - audio_thread_->Start(); - } - - virtual void TearDown() { - audio_thread_->Stop(); - audio_thread_.reset(); + params_.sample_rate(), + params_.effects()); } media::AudioParameters params_; scoped_refptr<MockCapturerSource> capturer_source_; scoped_refptr<WebRtcAudioCapturer> capturer_; - scoped_ptr<FakeAudioThread> audio_thread_; }; // Creates a capturer and audio track, fakes its audio thread, and @@ -172,11 +182,14 @@ class WebRtcLocalAudioTrackTest : public ::testing::Test { // get data callback when the track is connected to the capturer but not when // the track is disconnected from the capturer. TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) { - EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); + EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true)); + EXPECT_CALL(*capturer_source_.get(), OnStart()); RTCMediaConstraints constraints; scoped_refptr<WebRtcLocalAudioTrack> track = WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, &constraints); + static_cast<WebRtcLocalAudioSourceProvider*>( + track->audio_source_provider())->SetSinkParamsForTesting(params_); track->Start(); EXPECT_TRUE(track->enabled()); @@ -186,11 +199,10 @@ TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) { static_cast<webrtc::AudioTrackInterface*>(track.get())-> GetRenderer()->AddChannel(i); } - scoped_ptr<MockWebRtcAudioCapturerSink> sink( - new MockWebRtcAudioCapturerSink()); + scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink()); const media::AudioParameters params = capturer_->audio_parameters(); base::WaitableEvent event(false, false); - EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return()); + EXPECT_CALL(*sink, OnSetFormat(_)).WillOnce(Return()); EXPECT_CALL(*sink, CaptureData(kNumberOfNetworkChannels, params.sample_rate(), @@ -206,9 +218,8 @@ TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) { EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); track->RemoveSink(sink.get()); - EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); - track->Stop(); - track = NULL; + EXPECT_CALL(*capturer_source_.get(), OnStop()).WillOnce(Return()); + capturer_->Stop(); } // The same setup as ConnectAndDisconnectOneSink, but enable and disable the @@ -217,22 +228,24 @@ TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) { // callback. // TODO(xians): Enable this test after resolving the racing issue that TSAN // reports on MediaStreamTrack::enabled(); -TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) { - EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); +TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) { + EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true)); + EXPECT_CALL(*capturer_source_.get(), OnStart()); RTCMediaConstraints constraints; scoped_refptr<WebRtcLocalAudioTrack> track = WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, &constraints); + static_cast<WebRtcLocalAudioSourceProvider*>( + track->audio_source_provider())->SetSinkParamsForTesting(params_); track->Start(); static_cast<webrtc::AudioTrackInterface*>(track.get())-> GetRenderer()->AddChannel(0); EXPECT_TRUE(track->enabled()); EXPECT_TRUE(track->set_enabled(false)); - scoped_ptr<MockWebRtcAudioCapturerSink> sink( - new MockWebRtcAudioCapturerSink()); + scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink()); const media::AudioParameters params = capturer_->audio_parameters(); base::WaitableEvent event(false, false); - EXPECT_CALL(*sink, SetCaptureFormat(_)).WillOnce(Return()); + EXPECT_CALL(*sink, OnSetFormat(_)).Times(1); EXPECT_CALL(*sink, CaptureData(1, params.sample_rate(), @@ -260,28 +273,31 @@ TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) { EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); track->RemoveSink(sink.get()); - EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); - track->Stop(); + EXPECT_CALL(*capturer_source_.get(), OnStop()).WillOnce(Return()); + capturer_->Stop(); track = NULL; } // Create multiple audio tracks and enable/disable them, verify that the audio // callbacks appear/disappear. -TEST_F(WebRtcLocalAudioTrackTest, MultipleAudioTracks) { - EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(Return()); +// Flaky due to a data race, see http://crbug.com/295418 +TEST_F(WebRtcLocalAudioTrackTest, DISABLED_MultipleAudioTracks) { + EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true)); + EXPECT_CALL(*capturer_source_.get(), OnStart()); RTCMediaConstraints constraints; scoped_refptr<WebRtcLocalAudioTrack> track_1 = WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, &constraints); + static_cast<WebRtcLocalAudioSourceProvider*>( + track_1->audio_source_provider())->SetSinkParamsForTesting(params_); track_1->Start(); static_cast<webrtc::AudioTrackInterface*>(track_1.get())-> GetRenderer()->AddChannel(0); EXPECT_TRUE(track_1->enabled()); - scoped_ptr<MockWebRtcAudioCapturerSink> sink_1( - new MockWebRtcAudioCapturerSink()); + scoped_ptr<MockMediaStreamAudioSink> sink_1(new MockMediaStreamAudioSink()); const media::AudioParameters params = capturer_->audio_parameters(); base::WaitableEvent event_1(false, false); - EXPECT_CALL(*sink_1, SetCaptureFormat(_)).WillOnce(Return()); + EXPECT_CALL(*sink_1, OnSetFormat(_)).WillOnce(Return()); EXPECT_CALL(*sink_1, CaptureData(1, params.sample_rate(), @@ -298,6 +314,8 @@ TEST_F(WebRtcLocalAudioTrackTest, MultipleAudioTracks) { scoped_refptr<WebRtcLocalAudioTrack> track_2 = WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, &constraints); + static_cast<WebRtcLocalAudioSourceProvider*>( + track_2->audio_source_provider())->SetSinkParamsForTesting(params_); track_2->Start(); static_cast<webrtc::AudioTrackInterface*>(track_2.get())-> GetRenderer()->AddChannel(1); @@ -307,9 +325,8 @@ TEST_F(WebRtcLocalAudioTrackTest, MultipleAudioTracks) { event_1.Reset(); base::WaitableEvent event_2(false, false); - scoped_ptr<MockWebRtcAudioCapturerSink> sink_2( - new MockWebRtcAudioCapturerSink()); - EXPECT_CALL(*sink_2, SetCaptureFormat(_)).WillOnce(Return()); + scoped_ptr<MockMediaStreamAudioSink> sink_2(new MockMediaStreamAudioSink()); + EXPECT_CALL(*sink_2, OnSetFormat(_)).WillOnce(Return()); EXPECT_CALL(*sink_1, CaptureData(1, params.sample_rate(), @@ -338,27 +355,32 @@ TEST_F(WebRtcLocalAudioTrackTest, MultipleAudioTracks) { track_1->Stop(); track_1 = NULL; - EXPECT_CALL(*capturer_source_.get(), Stop()).WillOnce(Return()); + EXPECT_CALL(*capturer_source_.get(), OnStop()).WillOnce(Return()); track_2->RemoveSink(sink_2.get()); track_2->Stop(); track_2 = NULL; + + capturer_->Stop(); } // Start one track and verify the capturer is correctly starting its source. // And it should be fine to not to call Stop() explicitly. TEST_F(WebRtcLocalAudioTrackTest, StartOneAudioTrack) { - EXPECT_CALL(*capturer_source_.get(), Start()).Times(1); + EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true)); + EXPECT_CALL(*capturer_source_.get(), OnStart()); RTCMediaConstraints constraints; scoped_refptr<WebRtcLocalAudioTrack> track = WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, &constraints); + static_cast<WebRtcLocalAudioSourceProvider*>( + track->audio_source_provider())->SetSinkParamsForTesting(params_); track->Start(); // When the track goes away, it will automatically stop the // |capturer_source_|. - EXPECT_CALL(*capturer_source_.get(), Stop()); - track->Stop(); + EXPECT_CALL(*capturer_source_.get(), OnStop()); + capturer_->Stop(); track = NULL; } @@ -367,91 +389,97 @@ TEST_F(WebRtcLocalAudioTrackTest, StartOneAudioTrack) { TEST_F(WebRtcLocalAudioTrackTest, StartAndStopAudioTracks) { // Starting the first audio track will start the |capturer_source_|. base::WaitableEvent event(false, false); - EXPECT_CALL(*capturer_source_.get(), Start()).WillOnce(SignalEvent(&event)); + EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true)); + EXPECT_CALL(*capturer_source_.get(), OnStart()).WillOnce(SignalEvent(&event)); RTCMediaConstraints constraints; scoped_refptr<WebRtcLocalAudioTrack> track_1 = WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, &constraints); static_cast<webrtc::AudioTrackInterface*>(track_1.get())-> GetRenderer()->AddChannel(0); + static_cast<WebRtcLocalAudioSourceProvider*>( + track_1->audio_source_provider())->SetSinkParamsForTesting(params_); track_1->Start(); EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); // Verify the data flow by connecting the sink to |track_1|. - scoped_ptr<MockWebRtcAudioCapturerSink> sink( - new MockWebRtcAudioCapturerSink()); + scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink()); event.Reset(); + EXPECT_CALL(*sink, OnSetFormat(_)).WillOnce(SignalEvent(&event)); EXPECT_CALL(*sink, CaptureData(_, _, _, _, 0, 0, false, false)) .Times(AnyNumber()).WillRepeatedly(Return()); - EXPECT_CALL(*sink, SetCaptureFormat(_)).Times(1); track_1->AddSink(sink.get()); + EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); // Start the second audio track will not start the |capturer_source_| // since it has been started. - EXPECT_CALL(*capturer_source_.get(), Start()).Times(0); + EXPECT_CALL(*capturer_source_.get(), OnStart()).Times(0); scoped_refptr<WebRtcLocalAudioTrack> track_2 = WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, &constraints); + static_cast<WebRtcLocalAudioSourceProvider*>( + track_2->audio_source_provider())->SetSinkParamsForTesting(params_); track_2->Start(); static_cast<webrtc::AudioTrackInterface*>(track_2.get())-> GetRenderer()->AddChannel(1); - // Stop the first audio track will not stop the |capturer_source_|. - EXPECT_CALL(*capturer_source_.get(), Stop()).Times(0); - track_1->RemoveSink(sink.get()); - track_1->Stop(); - track_1 = NULL; + // Stop the capturer will clear up the track lists in the capturer. + EXPECT_CALL(*capturer_source_.get(), OnStop()); + capturer_->Stop(); - EXPECT_CALL(*sink, CaptureData(_, _, _, _, 0, 0, false, false)) - .Times(AnyNumber()).WillRepeatedly(Return()); - EXPECT_CALL(*sink, SetCaptureFormat(_)).Times(1); + // Adding a new track to the capturer. track_2->AddSink(sink.get()); + EXPECT_CALL(*sink, OnSetFormat(_)).Times(0); - // Stop the last audio track will stop the |capturer_source_|. + // Stop the capturer again will not trigger stopping the source of the + // capturer again.. event.Reset(); - EXPECT_CALL(*capturer_source_.get(), Stop()) - .Times(1).WillOnce(SignalEvent(&event)); - track_2->Stop(); - track_2->RemoveSink(sink.get()); - track_2 = NULL; - EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); + EXPECT_CALL(*capturer_source_.get(), OnStop()).Times(0); + capturer_->Stop(); } // Set new source to the existing capturer. TEST_F(WebRtcLocalAudioTrackTest, SetNewSourceForCapturerAfterStartTrack) { // Setup the audio track and start the track. - EXPECT_CALL(*capturer_source_.get(), Start()).Times(1); + EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true)); + EXPECT_CALL(*capturer_source_.get(), OnStart()); RTCMediaConstraints constraints; scoped_refptr<WebRtcLocalAudioTrack> track = WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, &constraints); + static_cast<WebRtcLocalAudioSourceProvider*>( + track->audio_source_provider())->SetSinkParamsForTesting(params_); track->Start(); // Setting new source to the capturer and the track should still get packets. - scoped_refptr<MockCapturerSource> new_source(new MockCapturerSource()); - EXPECT_CALL(*capturer_source_.get(), Stop()); - EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(false)); - EXPECT_CALL(*new_source.get(), Initialize(_, capturer_.get(), 0)) + scoped_refptr<MockCapturerSource> new_source( + new MockCapturerSource(capturer_.get())); + EXPECT_CALL(*capturer_source_.get(), OnStop()); + EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(true)); + EXPECT_CALL(*new_source.get(), OnInitialize(_, capturer_.get(), 0)) .WillOnce(Return()); - EXPECT_CALL(*new_source.get(), Start()).WillOnce(Return()); + EXPECT_CALL(*new_source.get(), OnStart()); capturer_->SetCapturerSource(new_source, params_.channel_layout(), - params_.sample_rate()); + params_.sample_rate(), + params_.effects()); // Stop the track. - EXPECT_CALL(*new_source.get(), Stop()); - track->Stop(); - track = NULL; + EXPECT_CALL(*new_source.get(), OnStop()); + capturer_->Stop(); } // Create a new capturer with new source, connect it to a new audio track. TEST_F(WebRtcLocalAudioTrackTest, ConnectTracksToDifferentCapturers) { // Setup the first audio track and start it. - EXPECT_CALL(*capturer_source_.get(), Start()).Times(1); + EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true)); + EXPECT_CALL(*capturer_source_.get(), OnStart()); RTCMediaConstraints constraints; scoped_refptr<WebRtcLocalAudioTrack> track_1 = WebRtcLocalAudioTrack::Create(std::string(), capturer_, NULL, NULL, &constraints); + static_cast<WebRtcLocalAudioSourceProvider*>( + track_1->audio_source_provider())->SetSinkParamsForTesting(params_); track_1->Start(); // Connect a number of network channels to the |track_1|. @@ -461,41 +489,34 @@ TEST_F(WebRtcLocalAudioTrackTest, ConnectTracksToDifferentCapturers) { GetRenderer()->AddChannel(i); } // Verify the data flow by connecting the |sink_1| to |track_1|. - scoped_ptr<MockWebRtcAudioCapturerSink> sink_1( - new MockWebRtcAudioCapturerSink()); + scoped_ptr<MockMediaStreamAudioSink> sink_1(new MockMediaStreamAudioSink()); EXPECT_CALL( *sink_1.get(), CaptureData( kNumberOfNetworkChannelsForTrack1, 48000, 2, _, 0, 0, false, false)) .Times(AnyNumber()).WillRepeatedly(Return()); - EXPECT_CALL(*sink_1.get(), SetCaptureFormat(_)).Times(1); + EXPECT_CALL(*sink_1.get(), OnSetFormat(_)).Times(AnyNumber()); track_1->AddSink(sink_1.get()); // Create a new capturer with new source with different audio format. scoped_refptr<WebRtcAudioCapturer> new_capturer( WebRtcAudioCapturer::CreateCapturer()); - WebRtcLocalAudioSourceProvider* source_provider = - static_cast<WebRtcLocalAudioSourceProvider*>( - new_capturer->audio_source_provider()); - source_provider->SetSinkParamsForTesting(params_); - scoped_refptr<MockCapturerSource> new_source(new MockCapturerSource()); - EXPECT_CALL(*new_source.get(), Initialize(_, new_capturer.get(), 0)) - .WillOnce(Return()); - EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(false)) - .WillOnce(Return()); + scoped_refptr<MockCapturerSource> new_source( + new MockCapturerSource(new_capturer.get())); + EXPECT_CALL(*new_source.get(), OnInitialize(_, new_capturer.get(), 0)); new_capturer->SetCapturerSource(new_source, media::CHANNEL_LAYOUT_MONO, - 44100); - - // Start the audio thread used by the new source. - scoped_ptr<FakeAudioThread> audio_thread(new FakeAudioThread(new_capturer)); - audio_thread->Start(); + 44100, + media::AudioParameters::NO_EFFECTS); // Setup the second audio track, connect it to the new capturer and start it. - EXPECT_CALL(*new_source.get(), Start()).Times(1); + EXPECT_CALL(*new_source.get(), SetAutomaticGainControl(true)); + EXPECT_CALL(*new_source.get(), OnStart()); scoped_refptr<WebRtcLocalAudioTrack> track_2 = WebRtcLocalAudioTrack::Create(std::string(), new_capturer, NULL, NULL, &constraints); + static_cast<WebRtcLocalAudioSourceProvider*>( + track_2->audio_source_provider())->SetSinkParamsForTesting(params_); track_2->Start(); // Connect a number of network channels to the |track_2|. @@ -505,30 +526,81 @@ TEST_F(WebRtcLocalAudioTrackTest, ConnectTracksToDifferentCapturers) { GetRenderer()->AddChannel(i); } // Verify the data flow by connecting the |sink_2| to |track_2|. - scoped_ptr<MockWebRtcAudioCapturerSink> sink_2( - new MockWebRtcAudioCapturerSink()); + scoped_ptr<MockMediaStreamAudioSink> sink_2(new MockMediaStreamAudioSink()); + base::WaitableEvent event(false, false); EXPECT_CALL( *sink_2, CaptureData( kNumberOfNetworkChannelsForTrack2, 44100, 1, _, 0, 0, false, false)) .Times(AnyNumber()).WillRepeatedly(Return()); - EXPECT_CALL(*sink_2, SetCaptureFormat(_)).Times(1); + EXPECT_CALL(*sink_2, OnSetFormat(_)).WillOnce(SignalEvent(&event)); track_2->AddSink(sink_2.get()); + EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); + + // Stopping the new source will stop the second track. + event.Reset(); + EXPECT_CALL(*new_source.get(), OnStop()) + .Times(1).WillOnce(SignalEvent(&event)); + new_capturer->Stop(); + EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); + + // Stop the capturer of the first audio track. + EXPECT_CALL(*capturer_source_.get(), OnStop()); + capturer_->Stop(); +} - // Stop the second audio track will stop the new source. + +// Make sure a audio track can deliver packets with a buffer size smaller than +// 10ms when it is not connected with a peer connection. +TEST_F(WebRtcLocalAudioTrackTest, TrackWorkWithSmallBufferSize) { + // Setup a capturer which works with a buffer size smaller than 10ms. + media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, + media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128); + + // Create a capturer with new source which works with the format above. + scoped_refptr<WebRtcAudioCapturer> capturer( + WebRtcAudioCapturer::CreateCapturer()); + scoped_refptr<MockCapturerSource> source( + new MockCapturerSource(capturer.get())); + capturer->Initialize(-1, params.channel_layout(), params.sample_rate(), + params.frames_per_buffer(), 0, std::string(), 0, 0, + params.effects()); + + EXPECT_CALL(*source.get(), OnInitialize(_, capturer.get(), 0)); + capturer->SetCapturerSource(source, params.channel_layout(), + params.sample_rate(), params.effects()); + + // Setup a audio track, connect it to the capturer and start it. + EXPECT_CALL(*source.get(), SetAutomaticGainControl(true)); + EXPECT_CALL(*source.get(), OnStart()); + RTCMediaConstraints constraints; + scoped_refptr<WebRtcLocalAudioTrack> track = + WebRtcLocalAudioTrack::Create(std::string(), capturer, NULL, NULL, + &constraints); + static_cast<WebRtcLocalAudioSourceProvider*>( + track->audio_source_provider())->SetSinkParamsForTesting(params); + track->Start(); + + // Verify the data flow by connecting the |sink| to |track|. + scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink()); base::WaitableEvent event(false, false); - EXPECT_CALL(*new_source.get(), Stop()).Times(1).WillOnce(SignalEvent(&event)); - track_2->Stop(); - track_2->RemoveSink(sink_2.get()); - track_2 = NULL; + EXPECT_CALL(*sink, OnSetFormat(_)).Times(1); + // Verify the sinks are getting the packets with an expecting buffer size. +#if defined(OS_ANDROID) + const int expected_buffer_size = params.sample_rate() / 100; +#else + const int expected_buffer_size = params.frames_per_buffer(); +#endif + EXPECT_CALL(*sink, CaptureData( + 0, params.sample_rate(), params.channels(), expected_buffer_size, + 0, 0, false, false)) + .Times(AtLeast(1)).WillRepeatedly(SignalEvent(&event)); + track->AddSink(sink.get()); EXPECT_TRUE(event.TimedWait(TestTimeouts::tiny_timeout())); - audio_thread->Stop(); - audio_thread.reset(); - // Stop the first audio track. - EXPECT_CALL(*capturer_source_.get(), Stop()); - track_1->Stop(); - track_1 = NULL; + // Stopping the new source will stop the second track. + EXPECT_CALL(*source, OnStop()).Times(1); + capturer->Stop(); } } // namespace content diff --git a/chromium/content/renderer/media/webrtc_logging_initializer.cc b/chromium/content/renderer/media/webrtc_logging.cc index d0d95b46ba6..2bdc7a33e5a 100644 --- a/chromium/content/renderer/media/webrtc_logging_initializer.cc +++ b/chromium/content/renderer/media/webrtc_logging.cc @@ -2,11 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media/webrtc_logging_initializer.h" +#include "content/renderer/media/webrtc_logging.h" -#include "content/public/renderer/render_thread.h" #include "content/public/renderer/webrtc_log_message_delegate.h" -#include "content/renderer/render_thread_impl.h" #include "third_party/libjingle/overrides/talk/base/logging.h" namespace content { @@ -21,12 +19,8 @@ void InitWebRtcLoggingDelegate(WebRtcLogMessageDelegate* delegate) { g_webrtc_logging_delegate = delegate; } -void InitWebRtcLogging(const std::string& app_session_id, - const std::string& app_url) { - if (g_webrtc_logging_delegate) { - g_webrtc_logging_delegate->InitLogging(app_session_id, app_url); - talk_base::InitDiagnosticLoggingDelegateFunction(WebRtcLogMessage); - } +void InitWebRtcLogging() { + talk_base::InitDiagnosticLoggingDelegateFunction(WebRtcLogMessage); } void WebRtcLogMessage(const std::string& message) { diff --git a/chromium/content/renderer/media/webrtc_logging.h b/chromium/content/renderer/media/webrtc_logging.h new file mode 100644 index 00000000000..0aafa9cc7d5 --- /dev/null +++ b/chromium/content/renderer/media/webrtc_logging.h @@ -0,0 +1,22 @@ +// 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_RENDERER_WEBRTC_LOGGING_H_ +#define CONTENT_RENDERER_WEBRTC_LOGGING_H_ + +#include <string> + +namespace content { + +// This function will add |message| to the diagnostic WebRTC log, if started. +// Otherwise it will be ignored. Note that this log may be uploaded to a +// server by the embedder - no sensitive information should be logged. May be +// called on any thread. +// TODO(grunell): Create a macro for adding log messages. Messages should +// probably also go to the ordinary logging stream. +void WebRtcLogMessage(const std::string& message); + +} // namespace content + +#endif // CONTENT_RENDERER_WEBRTC_LOGGING_H_ diff --git a/chromium/content/renderer/media/webrtc_logging_initializer.h b/chromium/content/renderer/media/webrtc_logging_initializer.h deleted file mode 100644 index 08abc66a7fd..00000000000 --- a/chromium/content/renderer/media/webrtc_logging_initializer.h +++ /dev/null @@ -1,23 +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_RENDERER_WEBRTC_LOGGING_INITIALIZER_H_ -#define CONTENT_RENDERER_WEBRTC_LOGGING_INITIALIZER_H_ - -#include <string> - -namespace content { - -class WebRtcLogMessageDelegate; - -// Must be called on IO thread. -void InitWebRtcLogging(const std::string& app_session_id, - const std::string& app_url); - -// May be called on any thread. -void WebRtcLogMessage(const std::string& message); - -} // namespace content - -#endif // CONTENT_RENDERER_WEBRTC_LOGGING_INITIALIZER_H_ diff --git a/chromium/content/renderer/media/webrtc_logging_noop.cc b/chromium/content/renderer/media/webrtc_logging_noop.cc new file mode 100644 index 00000000000..00bfdefbe3b --- /dev/null +++ b/chromium/content/renderer/media/webrtc_logging_noop.cc @@ -0,0 +1,11 @@ +// 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/renderer/media/webrtc_logging.h" + +namespace content { + +void WebRtcLogMessage(const std::string& message) {} + +} // namespace content diff --git a/chromium/content/renderer/media/websourcebuffer_impl.cc b/chromium/content/renderer/media/websourcebuffer_impl.cc index dc568572663..c9429779d82 100644 --- a/chromium/content/renderer/media/websourcebuffer_impl.cc +++ b/chromium/content/renderer/media/websourcebuffer_impl.cc @@ -36,9 +36,9 @@ WebSourceBufferImpl::~WebSourceBufferImpl() { DCHECK(!demuxer_) << "Object destroyed w/o removedFromMediaSource() call"; } -WebKit::WebTimeRanges WebSourceBufferImpl::buffered() { +blink::WebTimeRanges WebSourceBufferImpl::buffered() { media::Ranges<base::TimeDelta> ranges = demuxer_->GetBufferedRanges(id_); - WebKit::WebTimeRanges result(ranges.size()); + blink::WebTimeRanges result(ranges.size()); for (size_t i = 0; i < ranges.size(); i++) { result[i].start = ranges.start(i).InSecondsF(); result[i].end = ranges.end(i).InSecondsF(); diff --git a/chromium/content/renderer/media/websourcebuffer_impl.h b/chromium/content/renderer/media/websourcebuffer_impl.h index 1f05f3b32f9..abfec405ad2 100644 --- a/chromium/content/renderer/media/websourcebuffer_impl.h +++ b/chromium/content/renderer/media/websourcebuffer_impl.h @@ -9,7 +9,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" -#include "third_party/WebKit/public/web/WebSourceBuffer.h" +#include "third_party/WebKit/public/platform/WebSourceBuffer.h" namespace media { class ChunkDemuxer; @@ -17,13 +17,13 @@ class ChunkDemuxer; namespace content { -class WebSourceBufferImpl : public WebKit::WebSourceBuffer { +class WebSourceBufferImpl : public blink::WebSourceBuffer { public: WebSourceBufferImpl(const std::string& id, media::ChunkDemuxer* demuxer); virtual ~WebSourceBufferImpl(); - // WebKit::WebSourceBuffer implementation. - virtual WebKit::WebTimeRanges buffered() OVERRIDE; + // blink::WebSourceBuffer implementation. + virtual blink::WebTimeRanges buffered() OVERRIDE; virtual void append(const unsigned char* data, unsigned length) OVERRIDE; virtual void abort() OVERRIDE; // TODO(acolwell): Add OVERRIDE when Blink-side changes land. diff --git a/chromium/content/renderer/memory_benchmarking_extension.cc b/chromium/content/renderer/memory_benchmarking_extension.cc index e463fcfff09..50d5dcc436e 100644 --- a/chromium/content/renderer/memory_benchmarking_extension.cc +++ b/chromium/content/renderer/memory_benchmarking_extension.cc @@ -41,12 +41,13 @@ class MemoryBenchmarkingWrapper : public v8::Extension { "};" ) {} - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( + virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate( + v8::Isolate* isolate, v8::Handle<v8::String> name) OVERRIDE { - if (name->Equals(v8::String::New("IsHeapProfilerRunning"))) - return v8::FunctionTemplate::New(IsHeapProfilerRunning); - else if (name->Equals(v8::String::New("HeapProfilerDump"))) - return v8::FunctionTemplate::New(HeapProfilerDump); + if (name->Equals(v8::String::NewFromUtf8(isolate, "IsHeapProfilerRunning"))) + return v8::FunctionTemplate::New(isolate, IsHeapProfilerRunning); + else if (name->Equals(v8::String::NewFromUtf8(isolate, "HeapProfilerDump"))) + return v8::FunctionTemplate::New(isolate, HeapProfilerDump); return v8::Handle<v8::FunctionTemplate>(); } @@ -60,10 +61,10 @@ class MemoryBenchmarkingWrapper : public v8::Extension { const v8::FunctionCallbackInfo<v8::Value>& args) { std::string process_type; if (args.Length() && args[0]->IsString()) - process_type = *v8::String::AsciiValue(args[0]); + process_type = *v8::String::Utf8Value(args[0]); std::string reason("benchmarking_extension"); if (args.Length() > 1 && args[1]->IsString()) - reason = *v8::String::AsciiValue(args[1]); + reason = *v8::String::Utf8Value(args[1]); if (process_type == "browser") { content::RenderThreadImpl::current()->Send( new MemoryBenchmarkHostMsg_HeapProfilerDump(reason)); diff --git a/chromium/content/renderer/menu_item_builder.cc b/chromium/content/renderer/menu_item_builder.cc index 5946c41bb71..0bbd5d89190 100644 --- a/chromium/content/renderer/menu_item_builder.cc +++ b/chromium/content/renderer/menu_item_builder.cc @@ -8,14 +8,14 @@ namespace content { -MenuItem MenuItemBuilder::Build(const WebKit::WebMenuItemInfo& item) { +MenuItem MenuItemBuilder::Build(const blink::WebMenuItemInfo& item) { MenuItem result; result.label = item.label; result.tool_tip = item.toolTip; result.type = static_cast<MenuItem::Type>(item.type); result.action = item.action; - result.rtl = (item.textDirection == WebKit::WebTextDirectionRightToLeft); + result.rtl = (item.textDirection == blink::WebTextDirectionRightToLeft); result.has_directional_override = item.hasTextDirectionOverride; result.enabled = item.enabled; result.checked = item.checked; diff --git a/chromium/content/renderer/menu_item_builder.h b/chromium/content/renderer/menu_item_builder.h index 8f007bdd9db..f82a4587a1b 100644 --- a/chromium/content/renderer/menu_item_builder.h +++ b/chromium/content/renderer/menu_item_builder.h @@ -5,7 +5,7 @@ #ifndef CONTENT_RENDERER_MENU_ITEM_BUILDER_H_ #define CONTENT_RENDERER_MENU_ITEM_BUILDER_H_ -namespace WebKit { +namespace blink { struct WebMenuItemInfo; } @@ -14,7 +14,7 @@ struct MenuItem; class MenuItemBuilder { public: - static MenuItem Build(const WebKit::WebMenuItemInfo& item); + static MenuItem Build(const blink::WebMenuItemInfo& item); }; } // namespace content diff --git a/chromium/content/renderer/mhtml_generator.cc b/chromium/content/renderer/mhtml_generator.cc index 0a1c78578e8..95300441c2e 100644 --- a/chromium/content/renderer/mhtml_generator.cc +++ b/chromium/content/renderer/mhtml_generator.cc @@ -48,8 +48,8 @@ void MHTMLGenerator::NotifyBrowser(int job_id, int64 data_size) { // TODO(jcivelli): write the chunks in deferred tasks to give a chance to the // message loop to process other events. int64 MHTMLGenerator::GenerateMHTML() { - WebKit::WebCString mhtml = - WebKit::WebPageSerializer::serializeToMHTML(render_view()->GetWebView()); + blink::WebCString mhtml = + blink::WebPageSerializer::serializeToMHTML(render_view()->GetWebView()); const size_t chunk_size = 1024; const char* data = mhtml.data(); size_t total_bytes_written = 0; diff --git a/chromium/content/renderer/mouse_lock_dispatcher.cc b/chromium/content/renderer/mouse_lock_dispatcher.cc index 56ec66d5552..f72e1e05889 100644 --- a/chromium/content/renderer/mouse_lock_dispatcher.cc +++ b/chromium/content/renderer/mouse_lock_dispatcher.cc @@ -58,7 +58,7 @@ bool MouseLockDispatcher::IsMouseLockedTo(LockTarget* target) { } bool MouseLockDispatcher::WillHandleMouseEvent( - const WebKit::WebMouseEvent& event) { + const blink::WebMouseEvent& event) { if (mouse_locked_ && target_) return target_->HandleMouseLockedInputEvent(event); return false; diff --git a/chromium/content/renderer/mouse_lock_dispatcher.h b/chromium/content/renderer/mouse_lock_dispatcher.h index 6423b7d8f07..29b8e4f1261 100644 --- a/chromium/content/renderer/mouse_lock_dispatcher.h +++ b/chromium/content/renderer/mouse_lock_dispatcher.h @@ -8,9 +8,9 @@ #include "base/basictypes.h" #include "content/common/content_export.h" -namespace WebKit { +namespace blink { class WebMouseEvent; -} // namespace WebKit +} // namespace blink namespace content { @@ -28,7 +28,7 @@ class CONTENT_EXPORT MouseLockDispatcher { virtual void OnMouseLockLost() = 0; // A mouse lock is enabled and mouse events are being delievered. virtual bool HandleMouseLockedInputEvent( - const WebKit::WebMouseEvent& event) = 0; + const blink::WebMouseEvent& event) = 0; }; // Locks the mouse to the |target|. If true is returned, an asynchronous @@ -43,7 +43,7 @@ class CONTENT_EXPORT MouseLockDispatcher { bool IsMouseLockedTo(LockTarget* target); // Allow lock target to consumed a mouse event, if it does return true. - bool WillHandleMouseEvent(const WebKit::WebMouseEvent& event); + bool WillHandleMouseEvent(const blink::WebMouseEvent& event); // Subclasses or users have to call these methods to report mouse lock events // from the browser. diff --git a/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc b/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc index f9c44c22353..ef18331d530 100644 --- a/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc +++ b/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc @@ -21,7 +21,7 @@ class MockLockTarget : public MouseLockDispatcher::LockTarget { MOCK_METHOD1(OnLockMouseACK, void(bool)); MOCK_METHOD0(OnMouseLockLost, void()); MOCK_METHOD1(HandleMouseLockedInputEvent, - bool(const WebKit::WebMouseEvent&)); + bool(const blink::WebMouseEvent&)); }; // MouseLockDispatcher is a RenderViewObserver, and we test it by creating a @@ -90,7 +90,7 @@ TEST_F(MouseLockDispatcherTest, BasicMockLockTarget) { EXPECT_TRUE(dispatcher()->IsMouseLockedTo(target_)); // Receive mouse event. - dispatcher()->WillHandleMouseEvent(WebKit::WebMouseEvent()); + dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent()); // Unlock. dispatcher()->UnlockMouse(target_); @@ -120,7 +120,7 @@ TEST_F(MouseLockDispatcherTest, DeleteAndUnlock) { dispatcher()->OnLockTargetDestroyed(target_); delete target_; target_ = NULL; - dispatcher()->WillHandleMouseEvent(WebKit::WebMouseEvent()); + dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent()); view()->OnMessageReceived(ViewMsg_MouseLockLost(route_id_)); EXPECT_FALSE(dispatcher()->IsMouseLockedTo(target_)); } @@ -171,7 +171,7 @@ TEST_F(MouseLockDispatcherTest, MouseEventsNotReceived) { EXPECT_CALL(*target_, HandleMouseLockedInputEvent(_)).Times(0); // (Don't) receive mouse event. - dispatcher()->WillHandleMouseEvent(WebKit::WebMouseEvent()); + dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent()); // Lock. EXPECT_TRUE(dispatcher()->LockMouse(target_)); @@ -179,7 +179,7 @@ TEST_F(MouseLockDispatcherTest, MouseEventsNotReceived) { EXPECT_TRUE(dispatcher()->IsMouseLockedTo(target_)); // Receive mouse event. - dispatcher()->WillHandleMouseEvent(WebKit::WebMouseEvent()); + dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent()); // Unlock. dispatcher()->UnlockMouse(target_); @@ -187,7 +187,7 @@ TEST_F(MouseLockDispatcherTest, MouseEventsNotReceived) { EXPECT_FALSE(dispatcher()->IsMouseLockedTo(target_)); // (Don't) receive mouse event. - dispatcher()->WillHandleMouseEvent(WebKit::WebMouseEvent()); + dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent()); } // Test multiple targets @@ -216,7 +216,7 @@ TEST_F(MouseLockDispatcherTest, MultipleTargets) { EXPECT_FALSE(dispatcher()->LockMouse(alternate_target_)); // Receive mouse event to only one target. - dispatcher()->WillHandleMouseEvent(WebKit::WebMouseEvent()); + dispatcher()->WillHandleMouseEvent(blink::WebMouseEvent()); // Unlock alternate target has no effect. dispatcher()->UnlockMouse(alternate_target_); diff --git a/chromium/content/renderer/notification_provider.cc b/chromium/content/renderer/notification_provider.cc index fc7504226b6..07b5241aec6 100644 --- a/chromium/content/renderer/notification_provider.cc +++ b/chromium/content/renderer/notification_provider.cc @@ -15,14 +15,14 @@ #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" #include "third_party/WebKit/public/web/WebView.h" -using WebKit::WebDocument; -using WebKit::WebNotification; -using WebKit::WebNotificationPresenter; -using WebKit::WebNotificationPermissionCallback; -using WebKit::WebSecurityOrigin; -using WebKit::WebString; -using WebKit::WebURL; -using WebKit::WebUserGestureIndicator; +using blink::WebDocument; +using blink::WebNotification; +using blink::WebNotificationPresenter; +using blink::WebNotificationPermissionCallback; +using blink::WebSecurityOrigin; +using blink::WebString; +using blink::WebURL; +using blink::WebUserGestureIndicator; namespace content { @@ -32,15 +32,21 @@ NotificationProvider::NotificationProvider(RenderViewImpl* render_view) } NotificationProvider::~NotificationProvider() { - manager_.DetachAll(); } bool NotificationProvider::show(const WebNotification& notification) { + WebDocument document = render_view()->GetWebView()->mainFrame()->document(); int notification_id = manager_.RegisterNotification(notification); - if (notification.isHTML()) - return ShowHTML(notification, notification_id); - else - return ShowText(notification, notification_id); + + ShowDesktopNotificationHostMsgParams params; + params.origin = GURL(document.securityOrigin().toString()); + params.icon_url = notification.iconURL(); + params.title = notification.title(); + params.body = notification.body(); + params.direction = notification.direction(); + params.notification_id = notification_id; + params.replace_id = notification.replaceId(); + return Send(new DesktopNotificationHostMsg_Show(routing_id(), params)); } void NotificationProvider::cancel(const WebNotification& notification) { @@ -101,35 +107,6 @@ bool NotificationProvider::OnMessageReceived(const IPC::Message& message) { return handled; } -bool NotificationProvider::ShowHTML(const WebNotification& notification, - int id) { - DCHECK(notification.isHTML()); - ShowDesktopNotificationHostMsgParams params; - WebDocument document = render_view()->GetWebView()->mainFrame()->document(); - params.origin = GURL(document.securityOrigin().toString()); - params.is_html = true; - params.contents_url = notification.url(); - params.notification_id = id; - params.replace_id = notification.replaceId(); - return Send(new DesktopNotificationHostMsg_Show(routing_id(), params)); -} - -bool NotificationProvider::ShowText(const WebNotification& notification, - int id) { - DCHECK(!notification.isHTML()); - ShowDesktopNotificationHostMsgParams params; - params.is_html = false; - WebDocument document = render_view()->GetWebView()->mainFrame()->document(); - params.origin = GURL(document.securityOrigin().toString()); - params.icon_url = notification.iconURL(); - params.title = notification.title(); - params.body = notification.body(); - params.direction = notification.direction(); - params.notification_id = id; - params.replace_id = notification.replaceId(); - return Send(new DesktopNotificationHostMsg_Show(routing_id(), params)); -} - void NotificationProvider::OnDisplay(int id) { WebNotification notification; bool found = manager_.GetNotification(id, ¬ification); diff --git a/chromium/content/renderer/notification_provider.h b/chromium/content/renderer/notification_provider.h index ababece3271..8abafb1caf7 100644 --- a/chromium/content/renderer/notification_provider.h +++ b/chromium/content/renderer/notification_provider.h @@ -10,7 +10,7 @@ #include "third_party/WebKit/public/web/WebNotification.h" #include "third_party/WebKit/public/web/WebNotificationPresenter.h" -namespace WebKit { +namespace blink { class WebNotificationPermissionCallback; } @@ -20,7 +20,7 @@ class RenderViewImpl; // NotificationProvider class is owned by the RenderView. Only // to be used on the main thread. class NotificationProvider : public RenderViewObserver, - public WebKit::WebNotificationPresenter { + public blink::WebNotificationPresenter { public: explicit NotificationProvider(RenderViewImpl* render_view); virtual ~NotificationProvider(); @@ -29,22 +29,18 @@ class NotificationProvider : public RenderViewObserver, // RenderView::Observer implementation. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - // WebKit::WebNotificationPresenter interface. - virtual bool show(const WebKit::WebNotification& proxy); - virtual void cancel(const WebKit::WebNotification& proxy); - virtual void objectDestroyed(const WebKit::WebNotification& proxy); - virtual WebKit::WebNotificationPresenter::Permission checkPermission( - const WebKit::WebSecurityOrigin& origin); - virtual void requestPermission(const WebKit::WebSecurityOrigin& origin, - WebKit::WebNotificationPermissionCallback* callback); - - // Internal methods used to show notifications. - bool ShowHTML(const WebKit::WebNotification& notification, int id); - bool ShowText(const WebKit::WebNotification& notification, int id); + // blink::WebNotificationPresenter interface. + virtual bool show(const blink::WebNotification& proxy); + virtual void cancel(const blink::WebNotification& proxy); + virtual void objectDestroyed(const blink::WebNotification& proxy); + virtual blink::WebNotificationPresenter::Permission checkPermission( + const blink::WebSecurityOrigin& origin); + virtual void requestPermission(const blink::WebSecurityOrigin& origin, + blink::WebNotificationPermissionCallback* callback); // IPC handlers. void OnDisplay(int id); - void OnError(int id, const WebKit::WebString& message); + void OnError(int id, const blink::WebString& message); void OnClose(int id, bool by_user); void OnClick(int id); void OnPermissionRequestComplete(int id); diff --git a/chromium/content/renderer/npapi/plugin_channel_host.cc b/chromium/content/renderer/npapi/plugin_channel_host.cc index c276d33384b..679288f5133 100644 --- a/chromium/content/renderer/npapi/plugin_channel_host.cc +++ b/chromium/content/renderer/npapi/plugin_channel_host.cc @@ -127,7 +127,7 @@ bool PluginChannelHost::OnControlMessageReceived(const IPC::Message& message) { } void PluginChannelHost::OnSetException(const std::string& message) { - WebKit::WebBindings::setException(NULL, message.c_str()); + blink::WebBindings::setException(NULL, message.c_str()); } void PluginChannelHost::OnPluginShuttingDown() { diff --git a/chromium/content/renderer/npapi/webplugin_delegate_proxy.cc b/chromium/content/renderer/npapi/webplugin_delegate_proxy.cc index 80cb2ea2879..d7f847240b0 100644 --- a/chromium/content/renderer/npapi/webplugin_delegate_proxy.cc +++ b/chromium/content/renderer/npapi/webplugin_delegate_proxy.cc @@ -31,6 +31,7 @@ #include "content/child/npapi/webplugin_resource_client.h" #include "content/child/plugin_messages.h" #include "content/common/content_constants_internal.h" +#include "content/common/frame_messages.h" #include "content/common/view_messages.h" #include "content/public/renderer/content_renderer_client.h" #include "content/renderer/npapi/plugin_channel_host.h" @@ -53,7 +54,6 @@ #include "ui/gfx/size.h" #include "ui/gfx/skia_util.h" #include "webkit/common/cursors/webcursor.h" -#include "webkit/glue/webkit_glue.h" #if defined(OS_POSIX) #include "ipc/ipc_channel_posix.h" @@ -67,12 +67,12 @@ #include "content/public/common/sandbox_init.h" #endif -using WebKit::WebBindings; -using WebKit::WebCursorInfo; -using WebKit::WebDragData; -using WebKit::WebInputEvent; -using WebKit::WebString; -using WebKit::WebView; +using blink::WebBindings; +using blink::WebCursorInfo; +using blink::WebDragData; +using blink::WebInputEvent; +using blink::WebString; +using blink::WebView; namespace content { @@ -203,8 +203,10 @@ class ResourceClientProxy : public WebPluginResourceClient { WebPluginDelegateProxy::WebPluginDelegateProxy( WebPluginImpl* plugin, const std::string& mime_type, - const base::WeakPtr<RenderViewImpl>& render_view) + const base::WeakPtr<RenderViewImpl>& render_view, + RenderFrameImpl* render_frame) : render_view_(render_view), + render_frame_(render_frame), plugin_(plugin), uses_shared_bitmaps_(false), #if defined(OS_MACOSX) @@ -306,8 +308,8 @@ bool WebPluginDelegateProxy::Initialize( #endif IPC::ChannelHandle channel_handle; - if (!RenderThreadImpl::current()->Send(new ViewHostMsg_OpenChannelToPlugin( - render_view_->routing_id(), url, page_url_, mime_type_, + if (!RenderThreadImpl::current()->Send(new FrameHostMsg_OpenChannelToPlugin( + render_frame_->GetRoutingID(), url, page_url_, mime_type_, &channel_handle, &info_))) { continue; } @@ -317,7 +319,8 @@ bool WebPluginDelegateProxy::Initialize( // shouldn't happen, since if we got here the plugin should exist) or the // plugin crashed on initialization. if (!info_.path.empty()) { - render_view_->PluginCrashed(info_.path, base::kNullProcessId); + render_view_->main_render_frame()->PluginCrashed( + info_.path, base::kNullProcessId); LOG(ERROR) << "Plug-in crashed on start"; // Return true so that the plugin widget is created and we can paint the @@ -489,8 +492,10 @@ void WebPluginDelegateProxy::OnChannelError() { } plugin_->Invalidate(); } - if (!channel_host_->expecting_shutdown()) - render_view_->PluginCrashed(info_.path, channel_host_->peer_pid()); + if (!channel_host_->expecting_shutdown()) { + render_view_->main_render_frame()->PluginCrashed( + info_.path, channel_host_->peer_pid()); + } #if defined(OS_MACOSX) || defined(OS_WIN) // Ensure that the renderer doesn't think the plugin still has focus. @@ -666,14 +671,6 @@ bool WebPluginDelegateProxy::CreateSharedBitmap( return !!canvas->get(); } -#if defined(OS_MACOSX) -// Flips |rect| vertically within an enclosing rect with height |height|. -// Intended for converting rects between flipped and non-flipped contexts. -static void FlipRectVerticallyWithHeight(gfx::Rect* rect, int height) { - rect->set_y(height - rect->bottom()); -} -#endif - void WebPluginDelegateProxy::Paint(SkCanvas* canvas, const gfx::Rect& damaged_rect) { // Limit the damaged rectangle to whatever is contained inside the plugin @@ -755,7 +752,7 @@ NPP WebPluginDelegateProxy::GetPluginNPP() { return npp_.get(); } -bool WebPluginDelegateProxy::GetFormValue(string16* value) { +bool WebPluginDelegateProxy::GetFormValue(base::string16* value) { bool success = false; Send(new PluginMsg_GetFormValue(instance_id_, value, &success)); return success; @@ -806,7 +803,7 @@ void WebPluginDelegateProxy::SetContentAreaFocus(bool has_focus) { #if defined(OS_WIN) void WebPluginDelegateProxy::ImeCompositionUpdated( - const string16& text, + const base::string16& text, const std::vector<int>& clauses, const std::vector<int>& target, int cursor_position, @@ -821,7 +818,7 @@ void WebPluginDelegateProxy::ImeCompositionUpdated( Send(msg); } -void WebPluginDelegateProxy::ImeCompositionCompleted(const string16& text, +void WebPluginDelegateProxy::ImeCompositionCompleted(const base::string16& text, int plugin_id) { // Dispatch the IME text if this plug-in is the focused one. if (instance_id_ != plugin_id) @@ -848,7 +845,7 @@ void WebPluginDelegateProxy::SetContainerVisibility(bool is_visible) { if (is_visible) { gfx::Rect window_frame = render_view_->rootWindowRect(); gfx::Rect view_frame = render_view_->windowRect(); - WebKit::WebView* webview = render_view_->webview(); + blink::WebView* webview = render_view_->webview(); msg = new PluginMsg_ContainerShown(instance_id_, window_frame, view_frame, webview && webview->isActive()); } else { @@ -870,7 +867,7 @@ void WebPluginDelegateProxy::WindowFrameChanged(gfx::Rect window_frame, msg->set_unblock(true); Send(msg); } -void WebPluginDelegateProxy::ImeCompositionCompleted(const string16& text, +void WebPluginDelegateProxy::ImeCompositionCompleted(const base::string16& text, int plugin_id) { // If the message isn't intended for this plugin, there's nothing to do. if (instance_id_ != plugin_id) @@ -935,7 +932,7 @@ void WebPluginDelegateProxy::OnNotifyIMEStatus(int input_type, ViewHostMsg_SelectionBounds_Params bounds_params; bounds_params.anchor_rect = bounds_params.focus_rect = caret_rect; bounds_params.anchor_dir = bounds_params.focus_dir = - WebKit::WebTextDirectionLeftToRight; + blink::WebTextDirectionLeftToRight; bounds_params.is_anchor_first = true; render_view_->Send(new ViewHostMsg_SelectionBoundsChanged( render_view_->routing_id(), @@ -1215,7 +1212,8 @@ bool WebPluginDelegateProxy::UseSynchronousGeometryUpdates() { // Need to update geometry synchronously with WMP, otherwise if a site // scripts the plugin to start playing while it's in the middle of handling // an update geometry message, videos don't play. See urls in bug 20260. - if (info_.name.find(ASCIIToUTF16("Windows Media Player")) != string16::npos) + if (info_.name.find(ASCIIToUTF16("Windows Media Player")) != + base::string16::npos) return true; // The move networks plugin needs to be informed of geometry updates diff --git a/chromium/content/renderer/npapi/webplugin_delegate_proxy.h b/chromium/content/renderer/npapi/webplugin_delegate_proxy.h index 542986fa26d..dfa4842a694 100644 --- a/chromium/content/renderer/npapi/webplugin_delegate_proxy.h +++ b/chromium/content/renderer/npapi/webplugin_delegate_proxy.h @@ -38,6 +38,7 @@ class WaitableEvent; namespace content { class NPObjectStub; class PluginChannelHost; +class RenderFrameImpl; class RenderViewImpl; class WebPluginImpl; @@ -51,7 +52,8 @@ class WebPluginDelegateProxy public: WebPluginDelegateProxy(WebPluginImpl* plugin, const std::string& mime_type, - const base::WeakPtr<RenderViewImpl>& render_view); + const base::WeakPtr<RenderViewImpl>& render_view, + RenderFrameImpl* render_frame); // WebPluginDelegate implementation: virtual void PluginDestroyed() OVERRIDE; @@ -64,11 +66,11 @@ class WebPluginDelegateProxy virtual void Paint(SkCanvas* canvas, const gfx::Rect& rect) OVERRIDE; virtual NPObject* GetPluginScriptableObject() OVERRIDE; virtual struct _NPP* GetPluginNPP() OVERRIDE; - virtual bool GetFormValue(string16* value) OVERRIDE; + virtual bool GetFormValue(base::string16* value) OVERRIDE; virtual void DidFinishLoadWithReason(const GURL& url, NPReason reason, int notify_id) OVERRIDE; virtual void SetFocus(bool focused) OVERRIDE; - virtual bool HandleInputEvent(const WebKit::WebInputEvent& event, + virtual bool HandleInputEvent(const blink::WebInputEvent& event, WebCursor::CursorInfo* cursor) OVERRIDE; virtual int GetProcessId() OVERRIDE; @@ -78,14 +80,15 @@ class WebPluginDelegateProxy #if defined(OS_WIN) // Informs the plugin that plugin IME has updated its status. virtual void ImeCompositionUpdated( - const string16& text, + const base::string16& text, const std::vector<int>& clauses, const std::vector<int>& target, int cursor_position, int plugin_id); // Informs the plugin that plugin IME has completed. // If |text| is empty, composition was cancelled. - virtual void ImeCompositionCompleted(const string16& text, int plugin_id); + virtual void ImeCompositionCompleted(const base::string16& text, + int plugin_id); #endif #if defined(OS_MACOSX) // Informs the plugin that its enclosing window has gained or lost focus. @@ -96,7 +99,8 @@ class WebPluginDelegateProxy virtual void WindowFrameChanged(gfx::Rect window_frame, gfx::Rect view_frame); // Informs the plugin that plugin IME has completed. // If |text| is empty, composition was cancelled. - virtual void ImeCompositionCompleted(const string16& text, int plugin_id); + virtual void ImeCompositionCompleted(const base::string16& text, + int plugin_id); #endif // IPC::Listener implementation: @@ -251,6 +255,7 @@ class WebPluginDelegateProxy #endif base::WeakPtr<RenderViewImpl> render_view_; + RenderFrameImpl* render_frame_; WebPluginImpl* plugin_; bool uses_shared_bitmaps_; #if defined(OS_MACOSX) diff --git a/chromium/content/renderer/npapi/webplugin_impl.cc b/chromium/content/renderer/npapi/webplugin_impl.cc index 13874f3fbb1..ed6436f5bb5 100644 --- a/chromium/content/renderer/npapi/webplugin_impl.cc +++ b/chromium/content/renderer/npapi/webplugin_impl.cc @@ -24,6 +24,7 @@ #include "content/public/common/content_switches.h" #include "content/public/renderer/content_renderer_client.h" #include "content/renderer/npapi/webplugin_delegate_proxy.h" +#include "content/renderer/render_frame_impl.h" #include "content/renderer/render_process.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_view_impl.h" @@ -33,6 +34,7 @@ #include "skia/ext/platform_canvas.h" #include "third_party/WebKit/public/platform/WebCString.h" #include "third_party/WebKit/public/platform/WebCookieJar.h" +#include "third_party/WebKit/public/platform/WebCursorInfo.h" #include "third_party/WebKit/public/platform/WebData.h" #include "third_party/WebKit/public/platform/WebHTTPBody.h" #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" @@ -42,7 +44,6 @@ #include "third_party/WebKit/public/platform/WebURLLoaderClient.h" #include "third_party/WebKit/public/platform/WebURLResponse.h" #include "third_party/WebKit/public/web/WebConsoleMessage.h" -#include "third_party/WebKit/public/web/WebCursorInfo.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebInputEvent.h" @@ -57,32 +58,32 @@ #include "webkit/child/multipart_response_delegate.h" #include "webkit/renderer/compositor_bindings/web_layer_impl.h" -using WebKit::WebCanvas; -using WebKit::WebConsoleMessage; -using WebKit::WebCookieJar; -using WebKit::WebCString; -using WebKit::WebCursorInfo; -using WebKit::WebData; -using WebKit::WebDataSource; -using WebKit::WebFrame; -using WebKit::WebHTTPBody; -using WebKit::WebHTTPHeaderVisitor; -using WebKit::WebInputEvent; -using WebKit::WebKeyboardEvent; -using WebKit::WebMouseEvent; -using WebKit::WebPluginContainer; -using WebKit::WebPluginParams; -using WebKit::WebRect; -using WebKit::WebString; -using WebKit::WebURL; -using WebKit::WebURLError; -using WebKit::WebURLLoader; -using WebKit::WebURLLoaderClient; -using WebKit::WebURLLoaderOptions; -using WebKit::WebURLRequest; -using WebKit::WebURLResponse; -using WebKit::WebVector; -using WebKit::WebView; +using blink::WebCanvas; +using blink::WebConsoleMessage; +using blink::WebCookieJar; +using blink::WebCString; +using blink::WebCursorInfo; +using blink::WebData; +using blink::WebDataSource; +using blink::WebFrame; +using blink::WebHTTPBody; +using blink::WebHTTPHeaderVisitor; +using blink::WebInputEvent; +using blink::WebKeyboardEvent; +using blink::WebMouseEvent; +using blink::WebPluginContainer; +using blink::WebPluginParams; +using blink::WebRect; +using blink::WebString; +using blink::WebURL; +using blink::WebURLError; +using blink::WebURLLoader; +using blink::WebURLLoaderClient; +using blink::WebURLLoaderOptions; +using blink::WebURLRequest; +using blink::WebURLResponse; +using blink::WebVector; +using blink::WebView; using webkit_glue::MultipartResponseDelegate; namespace content { @@ -212,14 +213,14 @@ void GetResponseInfo(const WebURLResponse& response, } // namespace -// WebKit::WebPlugin ---------------------------------------------------------- +// blink::WebPlugin ---------------------------------------------------------- struct WebPluginImpl::ClientInfo { unsigned long id; WebPluginResourceClient* client; - WebKit::WebURLRequest request; + blink::WebURLRequest request; bool pending_failure_notification; - linked_ptr<WebKit::WebURLLoader> loader; + linked_ptr<blink::WebURLLoader> loader; bool notify_redirects; bool is_plugin_src_load; int64 data_offset; @@ -249,9 +250,9 @@ bool WebPluginImpl::initialize(WebPluginContainer* container) { if (!ok) { plugin_delegate->PluginDestroyed(); - WebKit::WebPlugin* replacement_plugin = + blink::WebPlugin* replacement_plugin = GetContentClient()->renderer()->CreatePluginReplacement( - render_view_.get(), file_path_); + render_frame_, file_path_); if (!replacement_plugin) return false; @@ -286,7 +287,7 @@ NPP WebPluginImpl::pluginNPP() { return npp_; } -bool WebPluginImpl::getFormValue(WebKit::WebString& value) { +bool WebPluginImpl::getFormValue(blink::WebString& value) { if (!delegate_) return false; base::string16 form_value; @@ -481,10 +482,12 @@ WebPluginImpl::WebPluginImpl( WebFrame* webframe, const WebPluginParams& params, const base::FilePath& file_path, - const base::WeakPtr<RenderViewImpl>& render_view) + const base::WeakPtr<RenderViewImpl>& render_view, + RenderFrameImpl* render_frame) : windowless_(false), window_(gfx::kNullPluginWindow), accepts_input_events_(false), + render_frame_(render_frame), render_view_(render_view), webframe_(webframe), delegate_(NULL), @@ -648,7 +651,8 @@ WebPluginDelegate* WebPluginImpl::CreatePluginDelegate() { #endif } - return new WebPluginDelegateProxy(this, mime_type_, render_view_); + return new WebPluginDelegateProxy( + this, mime_type_, render_view_, render_frame_); } WebPluginImpl::RoutingStatus WebPluginImpl::RouteToFrame( @@ -968,7 +972,8 @@ void WebPluginImpl::didReceiveResponse(WebURLLoader* loader, &upper_bound, &instance_size); } else if (response.httpStatusCode() == kHttpResponseSuccessStatusCode) { - RenderThreadImpl::current()->RecordUserMetrics("Plugin_200ForByteRange"); + RenderThreadImpl::current()->RecordAction( + UserMetricsAction("Plugin_200ForByteRange")); // If the client issued a byte range request and the server responds with // HTTP 200 OK, it indicates that the server does not support byte range // requests. @@ -1194,8 +1199,8 @@ void WebPluginImpl::HandleURLRequestInternal(const char* url, if (!delegate_) return; - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDirectNPAPIRequests)) { + if (!CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableDirectNPAPIRequests)) { // We got here either because the plugin called GetURL/PostURL, or because // we're fetching the data for an embed tag. If we're in multi-process mode, // we want to fetch the data in the plugin process as the renderer won't be @@ -1487,7 +1492,7 @@ void WebPluginImpl::TearDownPluginInstance( weak_factory_.InvalidateWeakPtrs(); } -void WebPluginImpl::SetReferrer(WebKit::WebURLRequest* request, +void WebPluginImpl::SetReferrer(blink::WebURLRequest* request, Referrer referrer_flag) { switch (referrer_flag) { case DOCUMENT_URL: diff --git a/chromium/content/renderer/npapi/webplugin_impl.h b/chromium/content/renderer/npapi/webplugin_impl.h index 9c7bf011875..1b7049c8654 100644 --- a/chromium/content/renderer/npapi/webplugin_impl.h +++ b/chromium/content/renderer/npapi/webplugin_impl.h @@ -29,7 +29,7 @@ namespace cc { class IOSurfaceLayer; } -namespace WebKit { +namespace blink { class WebFrame; class WebLayer; class WebPluginContainer; @@ -43,7 +43,7 @@ class MultipartResponseDelegate; } // namespace webkit_glue namespace content { - +class RenderFrameImpl; class RenderViewImpl; class WebPluginDelegate; @@ -51,50 +51,51 @@ class WebPluginDelegate; // after changing out of WebCore types, to a delegate. The delegate may // be in a different process. class WebPluginImpl : public WebPlugin, - public WebKit::WebPlugin, - public WebKit::WebURLLoaderClient { + public blink::WebPlugin, + public blink::WebURLLoaderClient { public: WebPluginImpl( - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params, + blink::WebFrame* frame, + const blink::WebPluginParams& params, const base::FilePath& file_path, - const base::WeakPtr<RenderViewImpl>& render_view); + const base::WeakPtr<RenderViewImpl>& render_view, + RenderFrameImpl* render_frame); virtual ~WebPluginImpl(); // Helper function for sorting post data. - CONTENT_EXPORT static bool SetPostData(WebKit::WebURLRequest* request, + CONTENT_EXPORT static bool SetPostData(blink::WebURLRequest* request, const char* buf, uint32 length); - WebKit::WebFrame* webframe() { return webframe_; } + blink::WebFrame* webframe() { return webframe_; } WebPluginDelegate* delegate() { return delegate_; } - // WebKit::WebPlugin methods: + // blink::WebPlugin methods: virtual bool initialize( - WebKit::WebPluginContainer* container); + blink::WebPluginContainer* container); virtual void destroy(); virtual NPObject* scriptableObject(); virtual struct _NPP* pluginNPP(); - virtual bool getFormValue(WebKit::WebString& value); + virtual bool getFormValue(blink::WebString& value); virtual void paint( - WebKit::WebCanvas* canvas, const WebKit::WebRect& paint_rect); + blink::WebCanvas* canvas, const blink::WebRect& paint_rect); virtual void updateGeometry( - const WebKit::WebRect& frame_rect, const WebKit::WebRect& clip_rect, - const WebKit::WebVector<WebKit::WebRect>& cut_outs, bool is_visible); + const blink::WebRect& frame_rect, const blink::WebRect& clip_rect, + const blink::WebVector<blink::WebRect>& cut_outs, bool is_visible); virtual void updateFocus(bool focused); virtual void updateVisibility(bool visible); virtual bool acceptsInputEvents(); virtual bool handleInputEvent( - const WebKit::WebInputEvent& event, WebKit::WebCursorInfo& cursor_info); - virtual void didReceiveResponse(const WebKit::WebURLResponse& response); + const blink::WebInputEvent& event, blink::WebCursorInfo& cursor_info); + virtual void didReceiveResponse(const blink::WebURLResponse& response); virtual void didReceiveData(const char* data, int data_length); virtual void didFinishLoading(); - virtual void didFailLoading(const WebKit::WebURLError& error); + virtual void didFailLoading(const blink::WebURLError& error); virtual void didFinishLoadingFrameRequest( - const WebKit::WebURL& url, void* notify_data); + const blink::WebURL& url, void* notify_data); virtual void didFailLoadingFrameRequest( - const WebKit::WebURL& url, void* notify_data, - const WebKit::WebURLError& error); + const blink::WebURL& url, void* notify_data, + const blink::WebURLError& error); virtual bool isPlaceholder() OVERRIDE; // WebPlugin implementation: @@ -200,31 +201,31 @@ class WebPluginImpl : public WebPlugin, gfx::Rect GetWindowClipRect(const gfx::Rect& rect); // Sets the actual Widget for the plugin. - void SetContainer(WebKit::WebPluginContainer* container); + void SetContainer(blink::WebPluginContainer* container); // Destroys the plugin instance. // The response_handle_to_ignore parameter if not NULL indicates the // resource handle to be left valid during plugin shutdown. - void TearDownPluginInstance(WebKit::WebURLLoader* loader_to_ignore); + void TearDownPluginInstance(blink::WebURLLoader* loader_to_ignore); // WebURLLoaderClient implementation. We implement this interface in the // renderer process, and then use the simple WebPluginResourceClient interface // to relay the callbacks to the plugin. - virtual void willSendRequest(WebKit::WebURLLoader* loader, - WebKit::WebURLRequest& request, - const WebKit::WebURLResponse& response); - virtual void didSendData(WebKit::WebURLLoader* loader, + virtual void willSendRequest(blink::WebURLLoader* loader, + blink::WebURLRequest& request, + const blink::WebURLResponse& response); + virtual void didSendData(blink::WebURLLoader* loader, unsigned long long bytes_sent, unsigned long long total_bytes_to_be_sent); - virtual void didReceiveResponse(WebKit::WebURLLoader* loader, - const WebKit::WebURLResponse& response); + virtual void didReceiveResponse(blink::WebURLLoader* loader, + const blink::WebURLResponse& response); - virtual void didReceiveData(WebKit::WebURLLoader* loader, const char *buffer, + virtual void didReceiveData(blink::WebURLLoader* loader, const char *buffer, int data_length, int encoded_data_length); - virtual void didFinishLoading(WebKit::WebURLLoader* loader, + virtual void didFinishLoading(blink::WebURLLoader* loader, double finishTime); - virtual void didFail(WebKit::WebURLLoader* loader, - const WebKit::WebURLError& error); + virtual void didFail(blink::WebURLLoader* loader, + const blink::WebURLError& error); // Helper function to remove the stored information about a resource // request given its index in m_clients. @@ -232,13 +233,13 @@ class WebPluginImpl : public WebPlugin, // Helper function to remove the stored information about a resource // request given a handle. - void RemoveClient(WebKit::WebURLLoader* loader); + void RemoveClient(blink::WebURLLoader* loader); // Handles HTTP multipart responses, i.e. responses received with a HTTP // status code of 206. // Returns false if response is not multipart (may be if we requested // single range). - bool HandleHttpMultipartResponse(const WebKit::WebURLResponse& response, + bool HandleHttpMultipartResponse(const blink::WebURLResponse& response, WebPluginResourceClient* client); void HandleURLRequestInternal(const char* url, @@ -254,7 +255,7 @@ class WebPluginImpl : public WebPlugin, // Tears down the existing plugin instance and creates a new plugin instance // to handle the response identified by the loader parameter. - bool ReinitializePluginForResponse(WebKit::WebURLLoader* loader); + bool ReinitializePluginForResponse(blink::WebURLLoader* loader); // Delayed task for downloading the plugin source URL. void OnDownloadPluginSrcUrl(); @@ -262,11 +263,11 @@ class WebPluginImpl : public WebPlugin, struct ClientInfo; // Helper functions - WebPluginResourceClient* GetClientFromLoader(WebKit::WebURLLoader* loader); - ClientInfo* GetClientInfoFromLoader(WebKit::WebURLLoader* loader); + WebPluginResourceClient* GetClientFromLoader(blink::WebURLLoader* loader); + ClientInfo* GetClientInfoFromLoader(blink::WebURLLoader* loader); // Helper function to set the referrer on the request passed in. - void SetReferrer(WebKit::WebURLRequest* request, Referrer referrer_flag); + void SetReferrer(blink::WebURLRequest* request, Referrer referrer_flag); // Check for invalid chars like @, ;, \ before the first / (in path). bool IsValidUrl(const GURL& url, Referrer referrer_flag); @@ -283,16 +284,17 @@ class WebPluginImpl : public WebPlugin, int32 next_io_surface_height_; uint32 next_io_surface_id_; scoped_refptr<cc::IOSurfaceLayer> io_surface_layer_; - scoped_ptr<WebKit::WebLayer> web_layer_; + scoped_ptr<blink::WebLayer> web_layer_; #endif bool accepts_input_events_; + RenderFrameImpl* render_frame_; base::WeakPtr<RenderViewImpl> render_view_; - WebKit::WebFrame* webframe_; + blink::WebFrame* webframe_; WebPluginDelegate* delegate_; // This is just a weak reference. - WebKit::WebPluginContainer* container_; + blink::WebPluginContainer* container_; // Unique identifier for this plugin, used to track script objects. struct _NPP* npp_; diff --git a/chromium/content/renderer/npapi/webplugin_impl_unittest.cc b/chromium/content/renderer/npapi/webplugin_impl_unittest.cc index df1371cf620..dd3b83eda5e 100644 --- a/chromium/content/renderer/npapi/webplugin_impl_unittest.cc +++ b/chromium/content/renderer/npapi/webplugin_impl_unittest.cc @@ -9,9 +9,9 @@ #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURLRequest.h" -using WebKit::WebHTTPBody; -using WebKit::WebString; -using WebKit::WebURLRequest; +using blink::WebHTTPBody; +using blink::WebString; +using blink::WebURLRequest; namespace content { diff --git a/chromium/content/renderer/p2p/ipc_network_manager.cc b/chromium/content/renderer/p2p/ipc_network_manager.cc index 34a65c53b35..bd7923d9aa1 100644 --- a/chromium/content/renderer/p2p/ipc_network_manager.cc +++ b/chromium/content/renderer/p2p/ipc_network_manager.cc @@ -46,18 +46,32 @@ void IpcNetworkManager::OnNetworkListChanged( if (!network_list_received_) network_list_received_ = true; + // Note: 32 and 64 are the arbitrary(kind of) prefix length used to + // differentiate IPv4 and IPv6 addresses. + // talk_base::Network uses these prefix_length to compare network + // interfaces discovered. std::vector<talk_base::Network*> networks; for (net::NetworkInterfaceList::const_iterator it = list.begin(); it != list.end(); it++) { - uint32 address; - if (it->address.size() != net::kIPv4AddressSize) - continue; - memcpy(&address, &it->address[0], sizeof(uint32)); - address = talk_base::NetworkToHost32(address); - talk_base::Network* network = new talk_base::Network( - it->name, it->name, talk_base::IPAddress(address), 32); - network->AddIP(talk_base::IPAddress(address)); - networks.push_back(network); + if (it->address.size() == net::kIPv4AddressSize) { + uint32 address; + memcpy(&address, &it->address[0], sizeof(uint32)); + address = talk_base::NetworkToHost32(address); + talk_base::Network* network = new talk_base::Network( + it->name, it->name, talk_base::IPAddress(address), 32); + network->AddIP(talk_base::IPAddress(address)); + networks.push_back(network); + } else if (it->address.size() == net::kIPv6AddressSize) { + in6_addr address; + memcpy(&address, &it->address[0], sizeof(in6_addr)); + talk_base::IPAddress ip6_addr(address); + if (!talk_base::IPIsPrivate(ip6_addr)) { + talk_base::Network* network = new talk_base::Network( + it->name, it->name, ip6_addr, 64); + network->AddIP(ip6_addr); + networks.push_back(network); + } + } } bool changed = false; diff --git a/chromium/content/renderer/p2p/ipc_socket_factory.cc b/chromium/content/renderer/p2p/ipc_socket_factory.cc index ced8822dc9b..04825c35f75 100644 --- a/chromium/content/renderer/p2p/ipc_socket_factory.cc +++ b/chromium/content/renderer/p2p/ipc_socket_factory.cc @@ -10,7 +10,9 @@ #include "base/debug/trace_event.h" #include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" -#include "content/renderer/p2p/socket_client.h" +#include "content/public/renderer/p2p_socket_client_delegate.h" +#include "content/renderer/p2p/host_address_request.h" +#include "content/renderer/p2p/socket_client_impl.h" #include "content/renderer/p2p/socket_dispatcher.h" #include "jingle/glue/utils.h" #include "third_party/libjingle/source/talk/base/asyncpacketsocket.h" @@ -35,13 +37,13 @@ const size_t kMaximumInFlightBytes = 64 * 1024; // 64 KB // using P2PSocketClient that works over IPC-channel. It must be used // on the thread it was created. class IpcPacketSocket : public talk_base::AsyncPacketSocket, - public P2PSocketClient::Delegate { + public P2PSocketClientDelegate { public: IpcPacketSocket(); virtual ~IpcPacketSocket(); // Always takes ownership of client even if initialization fails. - bool Init(P2PSocketType type, P2PSocketClient* client, + bool Init(P2PSocketType type, P2PSocketClientImpl* client, const talk_base::SocketAddress& local_address, const talk_base::SocketAddress& remote_address); @@ -60,14 +62,16 @@ class IpcPacketSocket : public talk_base::AsyncPacketSocket, virtual int GetError() const OVERRIDE; virtual void SetError(int error) OVERRIDE; - // P2PSocketClient::Delegate implementation. + // P2PSocketClientDelegate implementation. virtual void OnOpen(const net::IPEndPoint& address) OVERRIDE; - virtual void OnIncomingTcpConnection(const net::IPEndPoint& address, - P2PSocketClient* client) OVERRIDE; + virtual void OnIncomingTcpConnection( + const net::IPEndPoint& address, + P2PSocketClient* client) OVERRIDE; virtual void OnSendComplete() OVERRIDE; virtual void OnError() OVERRIDE; virtual void OnDataReceived(const net::IPEndPoint& address, - const std::vector<char>& data) OVERRIDE; + const std::vector<char>& data, + const base::TimeTicks& timestamp) OVERRIDE; private: enum InternalState { @@ -148,7 +152,8 @@ void IpcPacketSocket::TraceSendThrottlingState() const { in_flight_packet_sizes_.size()); } -bool IpcPacketSocket::Init(P2PSocketType type, P2PSocketClient* client, +bool IpcPacketSocket::Init(P2PSocketType type, + P2PSocketClientImpl* client, const talk_base::SocketAddress& local_address, const talk_base::SocketAddress& remote_address) { DCHECK_EQ(base::MessageLoop::current(), message_loop_); @@ -173,7 +178,7 @@ bool IpcPacketSocket::Init(P2PSocketType type, P2PSocketClient* client, return false; } - client_->Init(type, local_endpoint, remote_endpoint, this); + client->Init(type, local_endpoint, remote_endpoint, this); return true; } @@ -190,7 +195,7 @@ void IpcPacketSocket::InitAcceptedTcp( remote_address_ = remote_address; state_ = IS_OPEN; TraceSendThrottlingState(); - client_->set_delegate(this); + client_->SetDelegate(this); } // talk_base::AsyncPacketSocket interface. @@ -237,7 +242,9 @@ int IpcPacketSocket::SendTo(const void *data, size_t data_size, if (data_size > send_bytes_available_) { TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock", - TRACE_EVENT_SCOPE_THREAD, "id", client_->socket_id()); + TRACE_EVENT_SCOPE_THREAD, + "id", + client_->GetSocketID()); writable_signal_expected_ = true; error_ = EWOULDBLOCK; return -1; @@ -256,7 +263,8 @@ int IpcPacketSocket::SendTo(const void *data, size_t data_size, const char* data_char = reinterpret_cast<const char*>(data); std::vector<char> data_vector(data_char, data_char + data_size); - client_->Send(address_chrome, data_vector); + client_->SendWithDscp(address_chrome, data_vector, + static_cast<net::DiffServCodePoint>(dscp)); // Fake successful send. The caller ignores result anyway. return data_size; @@ -374,7 +382,8 @@ void IpcPacketSocket::OnError() { } void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address, - const std::vector<char>& data) { + const std::vector<char>& data, + const base::TimeTicks& timestamp) { DCHECK_EQ(base::MessageLoop::current(), message_loop_); talk_base::SocketAddress address_lj; @@ -385,7 +394,9 @@ void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address, return; } - SignalReadPacket(this, &data[0], data.size(), address_lj); + talk_base::PacketTime packet_time(timestamp.ToInternalValue(), 0); + SignalReadPacket(this, &data[0], data.size(), address_lj, + packet_time); } } // namespace @@ -401,7 +412,8 @@ IpcPacketSocketFactory::~IpcPacketSocketFactory() { talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateUdpSocket( const talk_base::SocketAddress& local_address, int min_port, int max_port) { talk_base::SocketAddress crome_address; - P2PSocketClient* socket_client = new P2PSocketClient(socket_dispatcher_); + P2PSocketClientImpl* socket_client = + new P2PSocketClientImpl(socket_dispatcher_); scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); // TODO(sergeyu): Respect local_address and port limits here (need // to pass them over IPC channel to the browser). @@ -421,7 +433,8 @@ talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateServerTcpSocket( P2PSocketType type = (opts & talk_base::PacketSocketFactory::OPT_STUN) ? P2P_SOCKET_STUN_TCP_SERVER : P2P_SOCKET_TCP_SERVER; - P2PSocketClient* socket_client = new P2PSocketClient(socket_dispatcher_); + P2PSocketClientImpl* socket_client = + new P2PSocketClientImpl(socket_dispatcher_); scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); if (!socket->Init(type, socket_client, local_address, talk_base::SocketAddress())) { @@ -446,12 +459,18 @@ talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateClientTcpSocket( type = (opts & talk_base::PacketSocketFactory::OPT_STUN) ? P2P_SOCKET_STUN_TCP_CLIENT : P2P_SOCKET_TCP_CLIENT; } - P2PSocketClient* socket_client = new P2PSocketClient(socket_dispatcher_); + P2PSocketClientImpl* socket_client = + new P2PSocketClientImpl(socket_dispatcher_); scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); - if (!socket->Init(type, socket_client, local_address, - remote_address)) + if (!socket->Init(type, socket_client, local_address, remote_address)) return NULL; return socket.release(); } +talk_base::AsyncResolverInterface* +IpcPacketSocketFactory::CreateAsyncResolver() { + NOTREACHED(); + return NULL; +} + } // namespace content diff --git a/chromium/content/renderer/p2p/ipc_socket_factory.h b/chromium/content/renderer/p2p/ipc_socket_factory.h index cb418838958..cba98b3c0d0 100644 --- a/chromium/content/renderer/p2p/ipc_socket_factory.h +++ b/chromium/content/renderer/p2p/ipc_socket_factory.h @@ -40,6 +40,7 @@ class IpcPacketSocketFactory : public talk_base::PacketSocketFactory { const talk_base::ProxyInfo& proxy_info, const std::string& user_agent, int opts) OVERRIDE; + virtual talk_base::AsyncResolverInterface* CreateAsyncResolver() OVERRIDE; private: P2PSocketDispatcher* socket_dispatcher_; diff --git a/chromium/content/renderer/p2p/port_allocator.cc b/chromium/content/renderer/p2p/port_allocator.cc index 2c5b8e44d88..280e04d7bc8 100644 --- a/chromium/content/renderer/p2p/port_allocator.cc +++ b/chromium/content/renderer/p2p/port_allocator.cc @@ -21,12 +21,12 @@ #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebURLLoaderOptions.h" -using WebKit::WebString; -using WebKit::WebURL; -using WebKit::WebURLLoader; -using WebKit::WebURLLoaderOptions; -using WebKit::WebURLRequest; -using WebKit::WebURLResponse; +using blink::WebString; +using blink::WebURL; +using blink::WebURLLoader; +using blink::WebURLLoaderOptions; +using blink::WebURLRequest; +using blink::WebURLResponse; namespace content { @@ -69,7 +69,7 @@ P2PPortAllocator::Config::RelayServerConfig::~RelayServerConfig() { } P2PPortAllocator::P2PPortAllocator( - WebKit::WebFrame* web_frame, + blink::WebFrame* web_frame, P2PSocketDispatcher* socket_dispatcher, talk_base::NetworkManager* network_manager, talk_base::PacketSocketFactory* socket_factory, @@ -153,8 +153,8 @@ void P2PPortAllocatorSession::didFinishLoading(WebURLLoader* loader, ParseRelayResponse(); } -void P2PPortAllocatorSession::didFail(WebKit::WebURLLoader* loader, - const WebKit::WebURLError& error) { +void P2PPortAllocatorSession::didFail(blink::WebURLLoader* loader, + const blink::WebURLError& error) { DCHECK_EQ(loader, relay_session_request_.get()); DCHECK_NE(error.reason, 0); diff --git a/chromium/content/renderer/p2p/port_allocator.h b/chromium/content/renderer/p2p/port_allocator.h index 5c0a4fc332e..eb50aeff4cb 100644 --- a/chromium/content/renderer/p2p/port_allocator.h +++ b/chromium/content/renderer/p2p/port_allocator.h @@ -11,10 +11,10 @@ #include "third_party/WebKit/public/platform/WebURLLoaderClient.h" #include "third_party/libjingle/source/talk/p2p/client/basicportallocator.h" -namespace WebKit { +namespace blink { class WebFrame; class WebURLLoader; -} // namespace WebKit +} // namespace blink namespace content { @@ -54,7 +54,7 @@ class P2PPortAllocator : public cricket::BasicPortAllocator { bool disable_tcp_transport; }; - P2PPortAllocator(WebKit::WebFrame* web_frame, + P2PPortAllocator(blink::WebFrame* web_frame, P2PSocketDispatcher* socket_dispatcher, talk_base::NetworkManager* network_manager, talk_base::PacketSocketFactory* socket_factory, @@ -70,7 +70,7 @@ class P2PPortAllocator : public cricket::BasicPortAllocator { private: friend class P2PPortAllocatorSession; - WebKit::WebFrame* web_frame_; + blink::WebFrame* web_frame_; P2PSocketDispatcher* socket_dispatcher_; Config config_; @@ -78,7 +78,7 @@ class P2PPortAllocator : public cricket::BasicPortAllocator { }; class P2PPortAllocatorSession : public cricket::BasicPortAllocatorSession, - public WebKit::WebURLLoaderClient { + public blink::WebURLLoaderClient { public: P2PPortAllocatorSession( P2PPortAllocator* allocator, @@ -88,15 +88,15 @@ class P2PPortAllocatorSession : public cricket::BasicPortAllocatorSession, const std::string& ice_password); virtual ~P2PPortAllocatorSession(); - // WebKit::WebURLLoaderClient overrides. - virtual void didReceiveData(WebKit::WebURLLoader* loader, + // blink::WebURLLoaderClient overrides. + virtual void didReceiveData(blink::WebURLLoader* loader, const char* data, int data_length, int encoded_data_length) OVERRIDE; - virtual void didFinishLoading(WebKit::WebURLLoader* loader, + virtual void didFinishLoading(blink::WebURLLoader* loader, double finish_time) OVERRIDE; - virtual void didFail(WebKit::WebURLLoader* loader, - const WebKit::WebURLError& error) OVERRIDE; + virtual void didFail(blink::WebURLLoader* loader, + const blink::WebURLError& error) OVERRIDE; protected: // Overrides for cricket::BasicPortAllocatorSession. @@ -134,7 +134,7 @@ class P2PPortAllocatorSession : public cricket::BasicPortAllocatorSession, std::vector<RelayServer> relay_info_; - scoped_ptr<WebKit::WebURLLoader> relay_session_request_; + scoped_ptr<blink::WebURLLoader> relay_session_request_; int relay_session_attempts_; std::string relay_session_response_; talk_base::SocketAddress relay_ip_; diff --git a/chromium/content/renderer/p2p/socket_client.cc b/chromium/content/renderer/p2p/socket_client.cc deleted file mode 100644 index 68797db66cc..00000000000 --- a/chromium/content/renderer/p2p/socket_client.cc +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (c) 2011 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/renderer/p2p/socket_client.h" - -#include "base/bind.h" -#include "base/message_loop/message_loop_proxy.h" -#include "content/common/p2p_messages.h" -#include "content/renderer/p2p/socket_dispatcher.h" - -namespace content { - -P2PSocketClient::P2PSocketClient(P2PSocketDispatcher* dispatcher) - : dispatcher_(dispatcher), - ipc_message_loop_(dispatcher->message_loop()), - delegate_message_loop_(base::MessageLoopProxy::current()), - socket_id_(0), delegate_(NULL), - state_(STATE_UNINITIALIZED) { -} - -P2PSocketClient::~P2PSocketClient() { - CHECK(state_ == STATE_CLOSED || state_ == STATE_UNINITIALIZED); -} - -void P2PSocketClient::Init( - P2PSocketType type, - const net::IPEndPoint& local_address, - const net::IPEndPoint& remote_address, - P2PSocketClient::Delegate* delegate) { - DCHECK(delegate_message_loop_->BelongsToCurrentThread()); - // |delegate_| is only accessesed on |delegate_message_loop_|. - delegate_ = delegate; - - ipc_message_loop_->PostTask( - FROM_HERE, base::Bind(&P2PSocketClient::DoInit, this, type, local_address, - remote_address)); -} - -void P2PSocketClient::DoInit(P2PSocketType type, - const net::IPEndPoint& local_address, - const net::IPEndPoint& remote_address) { - DCHECK_EQ(state_, STATE_UNINITIALIZED); - DCHECK(delegate_); - state_ = STATE_OPENING; - socket_id_ = dispatcher_->RegisterClient(this); - dispatcher_->SendP2PMessage(new P2PHostMsg_CreateSocket( - type, socket_id_, local_address, remote_address)); -} - -void P2PSocketClient::Send(const net::IPEndPoint& address, - const std::vector<char>& data) { - if (!ipc_message_loop_->BelongsToCurrentThread()) { - ipc_message_loop_->PostTask( - FROM_HERE, base::Bind(&P2PSocketClient::Send, this, address, data)); - return; - } - - // Can send data only when the socket is open. - DCHECK(state_ == STATE_OPEN || state_ == STATE_ERROR); - if (state_ == STATE_OPEN) { - dispatcher_->SendP2PMessage(new P2PHostMsg_Send(socket_id_, address, data)); - } -} - -void P2PSocketClient::Close() { - DCHECK(delegate_message_loop_->BelongsToCurrentThread()); - - delegate_ = NULL; - - ipc_message_loop_->PostTask( - FROM_HERE, base::Bind(&P2PSocketClient::DoClose, this)); -} - -void P2PSocketClient::DoClose() { - DCHECK(ipc_message_loop_->BelongsToCurrentThread()); - if (dispatcher_) { - if (state_ == STATE_OPEN || state_ == STATE_OPENING || - state_ == STATE_ERROR) { - dispatcher_->SendP2PMessage(new P2PHostMsg_DestroySocket(socket_id_)); - } - dispatcher_->UnregisterClient(socket_id_); - } - - state_ = STATE_CLOSED; -} - -void P2PSocketClient::set_delegate(Delegate* delegate) { - DCHECK(delegate_message_loop_->BelongsToCurrentThread()); - delegate_ = delegate; -} - -void P2PSocketClient::OnSocketCreated(const net::IPEndPoint& address) { - DCHECK(ipc_message_loop_->BelongsToCurrentThread()); - DCHECK_EQ(state_, STATE_OPENING); - state_ = STATE_OPEN; - - delegate_message_loop_->PostTask( - FROM_HERE, - base::Bind(&P2PSocketClient::DeliverOnSocketCreated, this, address)); -} - -void P2PSocketClient::DeliverOnSocketCreated(const net::IPEndPoint& address) { - DCHECK(delegate_message_loop_->BelongsToCurrentThread()); - if (delegate_) - delegate_->OnOpen(address); -} - -void P2PSocketClient::OnIncomingTcpConnection(const net::IPEndPoint& address) { - DCHECK(ipc_message_loop_->BelongsToCurrentThread()); - DCHECK_EQ(state_, STATE_OPEN); - - scoped_refptr<P2PSocketClient> new_client = new P2PSocketClient(dispatcher_); - new_client->socket_id_ = dispatcher_->RegisterClient(new_client.get()); - new_client->state_ = STATE_OPEN; - new_client->delegate_message_loop_ = delegate_message_loop_; - - dispatcher_->SendP2PMessage(new P2PHostMsg_AcceptIncomingTcpConnection( - socket_id_, address, new_client->socket_id_)); - - delegate_message_loop_->PostTask( - FROM_HERE, base::Bind(&P2PSocketClient::DeliverOnIncomingTcpConnection, - this, address, new_client)); -} - -void P2PSocketClient::DeliverOnIncomingTcpConnection( - const net::IPEndPoint& address, scoped_refptr<P2PSocketClient> new_client) { - DCHECK(delegate_message_loop_->BelongsToCurrentThread()); - if (delegate_) { - delegate_->OnIncomingTcpConnection(address, new_client.get()); - } else { - // Just close the socket if there is no delegate to accept it. - new_client->Close(); - } -} - -void P2PSocketClient::OnSendComplete() { - DCHECK(ipc_message_loop_->BelongsToCurrentThread()); - - delegate_message_loop_->PostTask( - FROM_HERE, base::Bind(&P2PSocketClient::DeliverOnSendComplete, this)); -} - -void P2PSocketClient::DeliverOnSendComplete() { - DCHECK(delegate_message_loop_->BelongsToCurrentThread()); - if (delegate_) - delegate_->OnSendComplete(); -} - -void P2PSocketClient::OnError() { - DCHECK(ipc_message_loop_->BelongsToCurrentThread()); - state_ = STATE_ERROR; - - delegate_message_loop_->PostTask( - FROM_HERE, base::Bind(&P2PSocketClient::DeliverOnError, this)); -} - -void P2PSocketClient::DeliverOnError() { - DCHECK(delegate_message_loop_->BelongsToCurrentThread()); - if (delegate_) - delegate_->OnError(); -} - -void P2PSocketClient::OnDataReceived(const net::IPEndPoint& address, - const std::vector<char>& data) { - DCHECK(ipc_message_loop_->BelongsToCurrentThread()); - DCHECK_EQ(STATE_OPEN, state_); - delegate_message_loop_->PostTask( - FROM_HERE, - base::Bind(&P2PSocketClient::DeliverOnDataReceived, this, address, data)); -} - -void P2PSocketClient::DeliverOnDataReceived(const net::IPEndPoint& address, - const std::vector<char>& data) { - DCHECK(delegate_message_loop_->BelongsToCurrentThread()); - if (delegate_) - delegate_->OnDataReceived(address, data); -} - -void P2PSocketClient::Detach() { - DCHECK(ipc_message_loop_->BelongsToCurrentThread()); - dispatcher_ = NULL; - OnError(); -} - -} // namespace content diff --git a/chromium/content/renderer/p2p/socket_client_impl.cc b/chromium/content/renderer/p2p/socket_client_impl.cc new file mode 100644 index 00000000000..b0d58498090 --- /dev/null +++ b/chromium/content/renderer/p2p/socket_client_impl.cc @@ -0,0 +1,243 @@ +// 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/renderer/p2p/socket_client_impl.h" + +#include "base/bind.h" +#include "base/message_loop/message_loop_proxy.h" +#include "content/common/p2p_messages.h" +#include "content/public/renderer/p2p_socket_client_delegate.h" +#include "content/renderer/p2p/socket_dispatcher.h" +#include "content/renderer/render_thread_impl.h" +#include "crypto/random.h" + +namespace { + +uint64 GetUniqueId(uint32 random_socket_id, uint32 packet_id) { + uint64 uid = random_socket_id; + uid <<= 32; + uid |= packet_id; + return uid; +} + +} // namespace + +namespace content { + +scoped_refptr<P2PSocketClient> P2PSocketClient::Create( + P2PSocketType type, + const net::IPEndPoint& local_address, + const net::IPEndPoint& remote_address, + P2PSocketClientDelegate* delegate) { + P2PSocketClientImpl *impl = new P2PSocketClientImpl( + RenderThreadImpl::current()->p2p_socket_dispatcher()); + impl->Init(type, local_address, remote_address, delegate); + return impl; +} + +P2PSocketClientImpl::P2PSocketClientImpl(P2PSocketDispatcher* dispatcher) + : dispatcher_(dispatcher), + ipc_message_loop_(dispatcher->message_loop()), + delegate_message_loop_(base::MessageLoopProxy::current()), + socket_id_(0), delegate_(NULL), + state_(STATE_UNINITIALIZED), + random_socket_id_(0), + next_packet_id_(0) { + crypto::RandBytes(&random_socket_id_, sizeof(random_socket_id_)); +} + +P2PSocketClientImpl::~P2PSocketClientImpl() { + CHECK(state_ == STATE_CLOSED || state_ == STATE_UNINITIALIZED); +} + +void P2PSocketClientImpl::Init( + P2PSocketType type, + const net::IPEndPoint& local_address, + const net::IPEndPoint& remote_address, + P2PSocketClientDelegate* delegate) { + DCHECK(delegate_message_loop_->BelongsToCurrentThread()); + // |delegate_| is only accessesed on |delegate_message_loop_|. + delegate_ = delegate; + + ipc_message_loop_->PostTask( + FROM_HERE, base::Bind(&P2PSocketClientImpl::DoInit, + this, + type, + local_address, + remote_address)); +} + +void P2PSocketClientImpl::DoInit(P2PSocketType type, + const net::IPEndPoint& local_address, + const net::IPEndPoint& remote_address) { + DCHECK_EQ(state_, STATE_UNINITIALIZED); + DCHECK(delegate_); + state_ = STATE_OPENING; + socket_id_ = dispatcher_->RegisterClient(this); + dispatcher_->SendP2PMessage(new P2PHostMsg_CreateSocket( + type, socket_id_, local_address, remote_address)); +} + +void P2PSocketClientImpl::SendWithDscp( + const net::IPEndPoint& address, + const std::vector<char>& data, + net::DiffServCodePoint dscp) { + if (!ipc_message_loop_->BelongsToCurrentThread()) { + ipc_message_loop_->PostTask( + FROM_HERE, base::Bind( + &P2PSocketClientImpl::SendWithDscp, this, address, data, dscp)); + return; + } + + // Can send data only when the socket is open. + DCHECK(state_ == STATE_OPEN || state_ == STATE_ERROR); + if (state_ == STATE_OPEN) { + uint64 unique_id = GetUniqueId(random_socket_id_, ++next_packet_id_); + TRACE_EVENT_ASYNC_BEGIN0("p2p", "Send", unique_id); + dispatcher_->SendP2PMessage(new P2PHostMsg_Send(socket_id_, address, data, + dscp, unique_id)); + } +} + +void P2PSocketClientImpl::Send(const net::IPEndPoint& address, + const std::vector<char>& data) { + SendWithDscp(address, data, net::DSCP_DEFAULT); +} + +void P2PSocketClientImpl::Close() { + DCHECK(delegate_message_loop_->BelongsToCurrentThread()); + + delegate_ = NULL; + + ipc_message_loop_->PostTask( + FROM_HERE, base::Bind(&P2PSocketClientImpl::DoClose, this)); +} + +void P2PSocketClientImpl::DoClose() { + DCHECK(ipc_message_loop_->BelongsToCurrentThread()); + if (dispatcher_) { + if (state_ == STATE_OPEN || state_ == STATE_OPENING || + state_ == STATE_ERROR) { + dispatcher_->SendP2PMessage(new P2PHostMsg_DestroySocket(socket_id_)); + } + dispatcher_->UnregisterClient(socket_id_); + } + + state_ = STATE_CLOSED; +} + +int P2PSocketClientImpl::GetSocketID() const { + return socket_id_; +} + +void P2PSocketClientImpl::SetDelegate(P2PSocketClientDelegate* delegate) { + DCHECK(delegate_message_loop_->BelongsToCurrentThread()); + delegate_ = delegate; +} + +void P2PSocketClientImpl::OnSocketCreated(const net::IPEndPoint& address) { + DCHECK(ipc_message_loop_->BelongsToCurrentThread()); + DCHECK_EQ(state_, STATE_OPENING); + state_ = STATE_OPEN; + + delegate_message_loop_->PostTask( + FROM_HERE, + base::Bind(&P2PSocketClientImpl::DeliverOnSocketCreated, this, address)); +} + +void P2PSocketClientImpl::DeliverOnSocketCreated( + const net::IPEndPoint& address) { + DCHECK(delegate_message_loop_->BelongsToCurrentThread()); + if (delegate_) + delegate_->OnOpen(address); +} + +void P2PSocketClientImpl::OnIncomingTcpConnection( + const net::IPEndPoint& address) { + DCHECK(ipc_message_loop_->BelongsToCurrentThread()); + DCHECK_EQ(state_, STATE_OPEN); + + scoped_refptr<P2PSocketClientImpl> new_client = + new P2PSocketClientImpl(dispatcher_); + new_client->socket_id_ = dispatcher_->RegisterClient(new_client.get()); + new_client->state_ = STATE_OPEN; + new_client->delegate_message_loop_ = delegate_message_loop_; + + dispatcher_->SendP2PMessage(new P2PHostMsg_AcceptIncomingTcpConnection( + socket_id_, address, new_client->socket_id_)); + + delegate_message_loop_->PostTask( + FROM_HERE, base::Bind( + &P2PSocketClientImpl::DeliverOnIncomingTcpConnection, + this, address, new_client)); +} + +void P2PSocketClientImpl::DeliverOnIncomingTcpConnection( + const net::IPEndPoint& address, + scoped_refptr<P2PSocketClient> new_client) { + DCHECK(delegate_message_loop_->BelongsToCurrentThread()); + if (delegate_) { + delegate_->OnIncomingTcpConnection(address, new_client.get()); + } else { + // Just close the socket if there is no delegate to accept it. + new_client->Close(); + } +} + +void P2PSocketClientImpl::OnSendComplete() { + DCHECK(ipc_message_loop_->BelongsToCurrentThread()); + + delegate_message_loop_->PostTask( + FROM_HERE, base::Bind(&P2PSocketClientImpl::DeliverOnSendComplete, this)); +} + +void P2PSocketClientImpl::DeliverOnSendComplete() { + DCHECK(delegate_message_loop_->BelongsToCurrentThread()); + if (delegate_) + delegate_->OnSendComplete(); +} + +void P2PSocketClientImpl::OnError() { + DCHECK(ipc_message_loop_->BelongsToCurrentThread()); + state_ = STATE_ERROR; + + delegate_message_loop_->PostTask( + FROM_HERE, base::Bind(&P2PSocketClientImpl::DeliverOnError, this)); +} + +void P2PSocketClientImpl::DeliverOnError() { + DCHECK(delegate_message_loop_->BelongsToCurrentThread()); + if (delegate_) + delegate_->OnError(); +} + +void P2PSocketClientImpl::OnDataReceived(const net::IPEndPoint& address, + const std::vector<char>& data, + const base::TimeTicks& timestamp) { + DCHECK(ipc_message_loop_->BelongsToCurrentThread()); + DCHECK_EQ(STATE_OPEN, state_); + delegate_message_loop_->PostTask( + FROM_HERE, + base::Bind(&P2PSocketClientImpl::DeliverOnDataReceived, + this, + address, + data, + timestamp)); +} + +void P2PSocketClientImpl::DeliverOnDataReceived( + const net::IPEndPoint& address, const std::vector<char>& data, + const base::TimeTicks& timestamp) { + DCHECK(delegate_message_loop_->BelongsToCurrentThread()); + if (delegate_) + delegate_->OnDataReceived(address, data, timestamp); +} + +void P2PSocketClientImpl::Detach() { + DCHECK(ipc_message_loop_->BelongsToCurrentThread()); + dispatcher_ = NULL; + OnError(); +} + +} // namespace content diff --git a/chromium/content/renderer/p2p/socket_client.h b/chromium/content/renderer/p2p/socket_client_impl.h index fd8537e7242..305a993a752 100644 --- a/chromium/content/renderer/p2p/socket_client.h +++ b/chromium/content/renderer/p2p/socket_client_impl.h @@ -1,14 +1,15 @@ -// Copyright (c) 2011 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. -#ifndef CONTENT_RENDERER_P2P_SOCKET_CLIENT_H_ -#define CONTENT_RENDERER_P2P_SOCKET_CLIENT_H_ +#ifndef CONTENT_RENDERER_P2P_SOCKET_CLIENT_IMPL_H_ +#define CONTENT_RENDERER_P2P_SOCKET_CLIENT_IMPL_H_ #include <vector> #include "base/memory/ref_counted.h" -#include "content/common/p2p_sockets.h" +#include "content/public/common/p2p_socket_type.h" +#include "content/public/renderer/p2p_socket_client.h" #include "net/base/ip_endpoint.h" namespace base { @@ -19,49 +20,41 @@ namespace content { class P2PSocketDispatcher; -// P2P socket that rountes all calls over IPC. +// P2P socket that routes all calls over IPC. // // The object runs on two threads: IPC thread and delegate thread. The // IPC thread is used to interact with P2PSocketDispatcher. All // callbacks to the user of this class are called on the delegate // thread which is specified in Init(). -class P2PSocketClient : public base::RefCountedThreadSafe<P2PSocketClient> { +class P2PSocketClientImpl : public P2PSocketClient { public: - // Delegate is called on the the same thread on which P2PSocketCLient is - // created. - class Delegate { - public: - virtual ~Delegate() { } - - virtual void OnOpen(const net::IPEndPoint& address) = 0; - virtual void OnIncomingTcpConnection(const net::IPEndPoint& address, - P2PSocketClient* client) = 0; - virtual void OnSendComplete() = 0; - virtual void OnError() = 0; - virtual void OnDataReceived(const net::IPEndPoint& address, - const std::vector<char>& data) = 0; - }; - - explicit P2PSocketClient(P2PSocketDispatcher* dispatcher); + explicit P2PSocketClientImpl(P2PSocketDispatcher* dispatcher); // Initialize socket of the specified |type| and connected to the // specified |address|. |address| matters only when |type| is set to // P2P_SOCKET_TCP_CLIENT. - void Init(P2PSocketType type, - const net::IPEndPoint& local_address, - const net::IPEndPoint& remote_address, - Delegate* delegate); + virtual void Init(P2PSocketType type, + const net::IPEndPoint& local_address, + const net::IPEndPoint& remote_address, + P2PSocketClientDelegate* delegate); // Send the |data| to the |address|. - void Send(const net::IPEndPoint& address, const std::vector<char>& data); + virtual void Send(const net::IPEndPoint& address, + const std::vector<char>& data) OVERRIDE; + + // Send the |data| to the |address| using Differentiated Services Code Point + // |dscp|. + virtual void SendWithDscp(const net::IPEndPoint& address, + const std::vector<char>& data, + net::DiffServCodePoint dscp) OVERRIDE; // Must be called before the socket is destroyed. The delegate may // not be called after |closed_task| is executed. - void Close(); + virtual void Close() OVERRIDE; - int socket_id() const { return socket_id_; } + virtual int GetSocketID() const OVERRIDE; - void set_delegate(Delegate* delegate); + virtual void SetDelegate(P2PSocketClientDelegate* delegate) OVERRIDE; private: enum State { @@ -74,10 +67,7 @@ class P2PSocketClient : public base::RefCountedThreadSafe<P2PSocketClient> { friend class P2PSocketDispatcher; - // Calls destructor. - friend class base::RefCountedThreadSafe<P2PSocketClient>; - - virtual ~P2PSocketClient(); + virtual ~P2PSocketClientImpl(); // Message handlers that run on IPC thread. void OnSocketCreated(const net::IPEndPoint& address); @@ -86,7 +76,8 @@ class P2PSocketClient : public base::RefCountedThreadSafe<P2PSocketClient> { void OnSendComplete(); void OnError(); void OnDataReceived(const net::IPEndPoint& address, - const std::vector<char>& data); + const std::vector<char>& data, + const base::TimeTicks& timestamp); // Proxy methods that deliver messages to the delegate thread. void DeliverOnSocketCreated(const net::IPEndPoint& address); @@ -96,7 +87,8 @@ class P2PSocketClient : public base::RefCountedThreadSafe<P2PSocketClient> { void DeliverOnSendComplete(); void DeliverOnError(); void DeliverOnDataReceived(const net::IPEndPoint& address, - const std::vector<char>& data); + const std::vector<char>& data, + const base::TimeTicks& timestamp); // Scheduled on the IPC thread to finish initialization. void DoInit(P2PSocketType type, @@ -113,12 +105,16 @@ class P2PSocketClient : public base::RefCountedThreadSafe<P2PSocketClient> { scoped_refptr<base::MessageLoopProxy> ipc_message_loop_; scoped_refptr<base::MessageLoopProxy> delegate_message_loop_; int socket_id_; - Delegate* delegate_; + P2PSocketClientDelegate* delegate_; State state_; - DISALLOW_COPY_AND_ASSIGN(P2PSocketClient); + // These two fields are used to identify packets for tracing. + uint32 random_socket_id_; + uint32 next_packet_id_; + + DISALLOW_COPY_AND_ASSIGN(P2PSocketClientImpl); }; } // namespace content -#endif // CONTENT_RENDERER_P2P_SOCKET_CLIENT_H_ +#endif // CONTENT_RENDERER_P2P_SOCKET_CLIENT_IMPL_H_ diff --git a/chromium/content/renderer/p2p/socket_dispatcher.cc b/chromium/content/renderer/p2p/socket_dispatcher.cc index e3a47a17e82..1b2a6fce0af 100644 --- a/chromium/content/renderer/p2p/socket_dispatcher.cc +++ b/chromium/content/renderer/p2p/socket_dispatcher.cc @@ -11,7 +11,7 @@ #include "content/common/p2p_messages.h" #include "content/renderer/p2p/host_address_request.h" #include "content/renderer/p2p/network_list_observer.h" -#include "content/renderer/p2p/socket_client.h" +#include "content/renderer/p2p/socket_client_impl.h" #include "content/renderer/render_view_impl.h" namespace content { @@ -27,7 +27,7 @@ P2PSocketDispatcher::P2PSocketDispatcher( P2PSocketDispatcher::~P2PSocketDispatcher() { network_list_observers_->AssertEmpty(); - for (IDMap<P2PSocketClient>::iterator i(&clients_); !i.IsAtEnd(); + for (IDMap<P2PSocketClientImpl>::iterator i(&clients_); !i.IsAtEnd(); i.Advance()) { i.GetCurrentValue()->Detach(); } @@ -88,7 +88,7 @@ base::MessageLoopProxy* P2PSocketDispatcher::message_loop() { return message_loop_.get(); } -int P2PSocketDispatcher::RegisterClient(P2PSocketClient* client) { +int P2PSocketDispatcher::RegisterClient(P2PSocketClientImpl* client) { DCHECK(message_loop_->BelongsToCurrentThread()); return clients_.Add(client); } @@ -139,7 +139,7 @@ void P2PSocketDispatcher::OnGetHostAddressResult( void P2PSocketDispatcher::OnSocketCreated( int socket_id, const net::IPEndPoint& address) { - P2PSocketClient* client = GetClient(socket_id); + P2PSocketClientImpl* client = GetClient(socket_id); if (client) { client->OnSocketCreated(address); } @@ -147,21 +147,21 @@ void P2PSocketDispatcher::OnSocketCreated( void P2PSocketDispatcher::OnIncomingTcpConnection( int socket_id, const net::IPEndPoint& address) { - P2PSocketClient* client = GetClient(socket_id); + P2PSocketClientImpl* client = GetClient(socket_id); if (client) { client->OnIncomingTcpConnection(address); } } void P2PSocketDispatcher::OnSendComplete(int socket_id) { - P2PSocketClient* client = GetClient(socket_id); + P2PSocketClientImpl* client = GetClient(socket_id); if (client) { client->OnSendComplete(); } } void P2PSocketDispatcher::OnError(int socket_id) { - P2PSocketClient* client = GetClient(socket_id); + P2PSocketClientImpl* client = GetClient(socket_id); if (client) { client->OnError(); } @@ -169,15 +169,16 @@ void P2PSocketDispatcher::OnError(int socket_id) { void P2PSocketDispatcher::OnDataReceived( int socket_id, const net::IPEndPoint& address, - const std::vector<char>& data) { - P2PSocketClient* client = GetClient(socket_id); + const std::vector<char>& data, + const base::TimeTicks& timestamp) { + P2PSocketClientImpl* client = GetClient(socket_id); if (client) { - client->OnDataReceived(address, data); + client->OnDataReceived(address, data, timestamp); } } -P2PSocketClient* P2PSocketDispatcher::GetClient(int socket_id) { - P2PSocketClient* client = clients_.Lookup(socket_id); +P2PSocketClientImpl* P2PSocketDispatcher::GetClient(int socket_id) { + P2PSocketClientImpl* client = clients_.Lookup(socket_id); if (client == NULL) { // This may happen if the socket was closed, but the browser side // hasn't processed the close message by the time it sends the diff --git a/chromium/content/renderer/p2p/socket_dispatcher.h b/chromium/content/renderer/p2p/socket_dispatcher.h index 34c78a15e87..b1bea29ef11 100644 --- a/chromium/content/renderer/p2p/socket_dispatcher.h +++ b/chromium/content/renderer/p2p/socket_dispatcher.h @@ -29,7 +29,7 @@ #include "base/observer_list_threadsafe.h" #include "base/synchronization/lock.h" #include "content/common/content_export.h" -#include "content/common/p2p_sockets.h" +#include "content/public/common/p2p_socket_type.h" #include "ipc/ipc_channel_proxy.h" #include "net/base/net_util.h" @@ -46,7 +46,7 @@ namespace content { class NetworkListObserver; class RenderViewImpl; class P2PHostAddressRequest; -class P2PSocketClient; +class P2PSocketClientImpl; class CONTENT_EXPORT P2PSocketDispatcher : public IPC::ChannelProxy::MessageFilter { @@ -68,7 +68,7 @@ class CONTENT_EXPORT P2PSocketDispatcher private: friend class P2PHostAddressRequest; - friend class P2PSocketClient; + friend class P2PSocketClientImpl; // Send a message asynchronously. virtual void Send(IPC::Message* message); @@ -83,7 +83,7 @@ class CONTENT_EXPORT P2PSocketDispatcher base::MessageLoopProxy* message_loop(); // Called by P2PSocketClient. - int RegisterClient(P2PSocketClient* client); + int RegisterClient(P2PSocketClientImpl* client); void UnregisterClient(int id); void SendP2PMessage(IPC::Message* msg); @@ -100,12 +100,13 @@ class CONTENT_EXPORT P2PSocketDispatcher void OnSendComplete(int socket_id); void OnError(int socket_id); void OnDataReceived(int socket_id, const net::IPEndPoint& address, - const std::vector<char>& data); + const std::vector<char>& data, + const base::TimeTicks& timestamp); - P2PSocketClient* GetClient(int socket_id); + P2PSocketClientImpl* GetClient(int socket_id); scoped_refptr<base::MessageLoopProxy> message_loop_; - IDMap<P2PSocketClient> clients_; + IDMap<P2PSocketClientImpl> clients_; IDMap<P2PHostAddressRequest> host_address_requests_; diff --git a/chromium/content/renderer/pepper/OWNERS b/chromium/content/renderer/pepper/OWNERS index cb5435cc3d1..ddbd3b66d38 100644 --- a/chromium/content/renderer/pepper/OWNERS +++ b/chromium/content/renderer/pepper/OWNERS @@ -1,6 +1,7 @@ bbudge@chromium.org dmichael@chromium.org raymes@chromium.org +teravest@chromium.org yzshen@chromium.org per-file usb_key_code_*=garykac@chromium.org diff --git a/chromium/content/renderer/pepper/content_decryptor_delegate.cc b/chromium/content/renderer/pepper/content_decryptor_delegate.cc index ce910379015..49790db2b7b 100644 --- a/chromium/content/renderer/pepper/content_decryptor_delegate.cc +++ b/chromium/content/renderer/pepper/content_decryptor_delegate.cc @@ -44,7 +44,7 @@ namespace { bool MakeBufferResource(PP_Instance instance, const uint8* data, uint32_t size, scoped_refptr<PPB_Buffer_Impl>* resource) { - TRACE_EVENT0("eme", "ContentDecryptorDelegate - MakeBufferResource"); + TRACE_EVENT0("media", "ContentDecryptorDelegate - MakeBufferResource"); DCHECK(resource); if (!data || !size) { @@ -218,6 +218,27 @@ PP_DecryptorStreamType MediaDecryptorStreamTypeToPpStreamType( } } +media::SampleFormat PpDecryptedSampleFormatToMediaSampleFormat( + PP_DecryptedSampleFormat result) { + switch (result) { + case PP_DECRYPTEDSAMPLEFORMAT_U8: + return media::kSampleFormatU8; + case PP_DECRYPTEDSAMPLEFORMAT_S16: + return media::kSampleFormatS16; + case PP_DECRYPTEDSAMPLEFORMAT_S32: + return media::kSampleFormatS32; + case PP_DECRYPTEDSAMPLEFORMAT_F32: + return media::kSampleFormatF32; + case PP_DECRYPTEDSAMPLEFORMAT_PLANAR_S16: + return media::kSampleFormatPlanarS16; + case PP_DECRYPTEDSAMPLEFORMAT_PLANAR_F32: + return media::kSampleFormatPlanarF32; + default: + NOTREACHED(); + return media::kUnknownSampleFormat; + } +} + } // namespace ContentDecryptorDelegate::ContentDecryptorDelegate( @@ -232,76 +253,66 @@ ContentDecryptorDelegate::ContentDecryptorDelegate( pending_video_decoder_init_request_id_(0), pending_audio_decode_request_id_(0), pending_video_decode_request_id_(0), - weak_ptr_factory_(this), - weak_this_(weak_ptr_factory_.GetWeakPtr()), - audio_sample_format_(media::kUnknownSampleFormat), audio_samples_per_second_(0), audio_channel_count_(0), - audio_bytes_per_frame_(0) { + weak_ptr_factory_(this) { + weak_this_ = weak_ptr_factory_.GetWeakPtr(); } ContentDecryptorDelegate::~ContentDecryptorDelegate() { } -void ContentDecryptorDelegate::Initialize(const std::string& key_system, - bool can_challenge_platform) { +void ContentDecryptorDelegate::Initialize(const std::string& key_system) { DCHECK(!key_system.empty()); DCHECK(key_system_.empty()); key_system_ = key_system; plugin_decryption_interface_->Initialize( pp_instance_, - StringVar::StringToPPVar(key_system_), - PP_FromBool(can_challenge_platform)); + StringVar::StringToPPVar(key_system_)); } -void ContentDecryptorDelegate::SetKeyEventCallbacks( - const media::KeyAddedCB& key_added_cb, - const media::KeyErrorCB& key_error_cb, - const media::KeyMessageCB& key_message_cb) { - key_added_cb_ = key_added_cb; - key_error_cb_ = key_error_cb; - key_message_cb_ = key_message_cb; +void ContentDecryptorDelegate::SetSessionEventCallbacks( + const media::SessionCreatedCB& session_created_cb, + const media::SessionMessageCB& session_message_cb, + const media::SessionReadyCB& session_ready_cb, + const media::SessionClosedCB& session_closed_cb, + const media::SessionErrorCB& session_error_cb) { + session_created_cb_ = session_created_cb; + session_message_cb_ = session_message_cb; + session_ready_cb_ = session_ready_cb; + session_closed_cb_ = session_closed_cb; + session_error_cb_ = session_error_cb; } -bool ContentDecryptorDelegate::GenerateKeyRequest(const std::string& type, - const uint8* init_data, - int init_data_length) { +bool ContentDecryptorDelegate::CreateSession(uint32 session_id, + const std::string& type, + const uint8* init_data, + int init_data_length) { PP_Var init_data_array = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( init_data_length, init_data); - plugin_decryption_interface_->GenerateKeyRequest( - pp_instance_, - StringVar::StringToPPVar(type), - init_data_array); + plugin_decryption_interface_->CreateSession(pp_instance_, + session_id, + StringVar::StringToPPVar(type), + init_data_array); return true; } -bool ContentDecryptorDelegate::AddKey(const std::string& session_id, - const uint8* key, - int key_length, - const uint8* init_data, - int init_data_length) { - PP_Var key_array = - PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(key_length, - key); - PP_Var init_data_array = +bool ContentDecryptorDelegate::UpdateSession(uint32 session_id, + const uint8* response, + int response_length) { + PP_Var response_array = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( - init_data_length, init_data); - - plugin_decryption_interface_->AddKey( - pp_instance_, - StringVar::StringToPPVar(session_id), - key_array, - init_data_array); + response_length, response); + plugin_decryption_interface_->UpdateSession( + pp_instance_, session_id, response_array); return true; } -bool ContentDecryptorDelegate::CancelKeyRequest(const std::string& session_id) { - plugin_decryption_interface_->CancelKeyRequest( - pp_instance_, - StringVar::StringToPPVar(session_id)); +bool ContentDecryptorDelegate::ReleaseSession(uint32 session_id) { + plugin_decryption_interface_->ReleaseSession(pp_instance_, session_id); return true; } @@ -405,10 +416,8 @@ bool ContentDecryptorDelegate::InitializeAudioDecoder( pp_decoder_config.samples_per_second = decoder_config.samples_per_second(); pp_decoder_config.request_id = next_decryption_request_id_++; - audio_sample_format_ = decoder_config.sample_format(); audio_samples_per_second_ = pp_decoder_config.samples_per_second; audio_channel_count_ = pp_decoder_config.channel_count; - audio_bytes_per_frame_ = decoder_config.bytes_per_frame(); scoped_refptr<PPB_Buffer_Impl> extra_data_resource; if (!MakeBufferResource(pp_instance_, @@ -553,7 +562,7 @@ bool ContentDecryptorDelegate::DecryptAndDecodeVideo( const uint32_t request_id = next_decryption_request_id_++; DVLOG(2) << "DecryptAndDecodeVideo() - request_id " << request_id; TRACE_EVENT_ASYNC_BEGIN0( - "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id); + "media", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id); PP_EncryptedBlockInfo block_info = {}; if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { @@ -580,38 +589,28 @@ bool ContentDecryptorDelegate::DecryptAndDecodeVideo( return true; } -void ContentDecryptorDelegate::NeedKey(PP_Var key_system_var, - PP_Var session_id_var, - PP_Var init_data_var) { - // TODO(ddorwin): Remove from PPB_ContentDecryptor_Private. - NOTREACHED(); -} - -void ContentDecryptorDelegate::KeyAdded(PP_Var key_system_var, - PP_Var session_id_var) { - if (key_added_cb_.is_null()) +void ContentDecryptorDelegate::OnSessionCreated(uint32 session_id, + PP_Var web_session_id_var) { + if (session_created_cb_.is_null()) return; - StringVar* session_id_string = StringVar::FromPPVar(session_id_var); + StringVar* session_id_string = StringVar::FromPPVar(web_session_id_var); + if (!session_id_string) { - key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0); + OnSessionError(session_id, media::MediaKeys::kUnknownError, 0); return; } - key_added_cb_.Run(session_id_string->value()); + session_created_cb_.Run(session_id, session_id_string->value()); } -void ContentDecryptorDelegate::KeyMessage(PP_Var key_system_var, - PP_Var session_id_var, - PP_Var message_var, - PP_Var default_url_var) { - if (key_message_cb_.is_null()) +void ContentDecryptorDelegate::OnSessionMessage(uint32 session_id, + PP_Var message_var, + PP_Var default_url_var) { + if (session_message_cb_.is_null()) return; - StringVar* session_id_string = StringVar::FromPPVar(session_id_var); - - ArrayBufferVar* message_array_buffer = - ArrayBufferVar::FromPPVar(message_var); + ArrayBufferVar* message_array_buffer = ArrayBufferVar::FromPPVar(message_var); std::vector<uint8> message; if (message_array_buffer) { @@ -621,32 +620,37 @@ void ContentDecryptorDelegate::KeyMessage(PP_Var key_system_var, StringVar* default_url_string = StringVar::FromPPVar(default_url_var); - if (!session_id_string || !default_url_string) { - key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0); + if (!default_url_string) { + OnSessionError(session_id, media::MediaKeys::kUnknownError, 0); return; } - key_message_cb_.Run(session_id_string->value(), - message, - default_url_string->value()); + session_message_cb_.Run(session_id, message, default_url_string->value()); } -void ContentDecryptorDelegate::KeyError(PP_Var key_system_var, - PP_Var session_id_var, - int32_t media_error, - int32_t system_code) { - if (key_error_cb_.is_null()) +void ContentDecryptorDelegate::OnSessionReady(uint32 session_id) { + if (session_ready_cb_.is_null()) return; - StringVar* session_id_string = StringVar::FromPPVar(session_id_var); - if (!session_id_string) { - key_error_cb_.Run(std::string(), media::MediaKeys::kUnknownError, 0); + session_ready_cb_.Run(session_id); +} + +void ContentDecryptorDelegate::OnSessionClosed(uint32 session_id) { + if (session_closed_cb_.is_null()) + return; + + session_closed_cb_.Run(session_id); +} + +void ContentDecryptorDelegate::OnSessionError(uint32 session_id, + int32_t media_error, + int32_t system_code) { + if (session_error_cb_.is_null()) return; - } - key_error_cb_.Run(session_id_string->value(), - static_cast<media::MediaKeys::KeyError>(media_error), - system_code); + session_error_cb_.Run(session_id, + static_cast<media::MediaKeys::KeyError>(media_error), + system_code); } void ContentDecryptorDelegate::DecoderInitializeDone( @@ -799,7 +803,7 @@ void ContentDecryptorDelegate::DeliverFrame( } TRACE_EVENT_ASYNC_END0( - "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id); + "media", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id); DCHECK(!pending_video_decode_cb_.is_null()); pending_video_decode_request_id_ = 0; @@ -852,12 +856,12 @@ void ContentDecryptorDelegate::DeliverFrame( void ContentDecryptorDelegate::DeliverSamples( PP_Resource audio_frames, - const PP_DecryptedBlockInfo* block_info) { - DCHECK(block_info); + const PP_DecryptedSampleInfo* sample_info) { + DCHECK(sample_info); - FreeBuffer(block_info->tracking_info.buffer_id); + FreeBuffer(sample_info->tracking_info.buffer_id); - const uint32_t request_id = block_info->tracking_info.request_id; + const uint32_t request_id = sample_info->tracking_info.request_id; DVLOG(2) << "DeliverSamples() - request_id: " << request_id; // If the request ID is not valid or does not match what's saved, do nothing. @@ -874,15 +878,19 @@ void ContentDecryptorDelegate::DeliverSamples( const media::Decryptor::AudioBuffers empty_frames; media::Decryptor::Status status = - PpDecryptResultToMediaDecryptorStatus(block_info->result); + PpDecryptResultToMediaDecryptorStatus(sample_info->result); if (status != media::Decryptor::kSuccess) { audio_decode_cb.Run(status, empty_frames); return; } + media::SampleFormat sample_format = + PpDecryptedSampleFormatToMediaSampleFormat(sample_info->format); + media::Decryptor::AudioBuffers audio_frame_list; if (!DeserializeAudioFrames(audio_frames, - block_info->data_size, + sample_info->data_size, + sample_format, &audio_frame_list)) { NOTREACHED() << "CDM did not serialize the buffer correctly."; audio_decode_cb.Run(media::Decryptor::kError, empty_frames); @@ -925,7 +933,7 @@ bool ContentDecryptorDelegate::MakeMediaBufferResource( media::Decryptor::StreamType stream_type, const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, scoped_refptr<PPB_Buffer_Impl>* resource) { - TRACE_EVENT0("eme", "ContentDecryptorDelegate::MakeMediaBufferResource"); + TRACE_EVENT0("media", "ContentDecryptorDelegate::MakeMediaBufferResource"); // End of stream buffers are represented as null resources. if (encrypted_buffer->end_of_stream()) { @@ -995,6 +1003,7 @@ void ContentDecryptorDelegate::SetBufferToFreeInTrackingInfo( bool ContentDecryptorDelegate::DeserializeAudioFrames( PP_Resource audio_frames, size_t data_size, + media::SampleFormat sample_format, media::Decryptor::AudioBuffers* frames) { DCHECK(frames); EnterResourceNoLock<PPB_Buffer_API> enter(audio_frames, true); @@ -1012,6 +1021,13 @@ bool ContentDecryptorDelegate::DeserializeAudioFrames( const uint8* cur = static_cast<uint8*>(mapper.data()); size_t bytes_left = data_size; + const int audio_bytes_per_frame = + media::SampleFormatToBytesPerChannel(sample_format) * + audio_channel_count_; + + // Allocate space for the channel pointers given to AudioBuffer. + std::vector<const uint8*> channel_ptrs( + audio_channel_count_, static_cast<const uint8*>(NULL)); do { int64 timestamp = 0; int64 frame_size = -1; @@ -1034,13 +1050,18 @@ bool ContentDecryptorDelegate::DeserializeAudioFrames( return false; } - const uint8* data[] = {cur}; - int frame_count = frame_size / audio_bytes_per_frame_; + // Setup channel pointers. AudioBuffer::CopyFrom() will only use the first + // one in the case of interleaved data. + const int size_per_channel = frame_size / audio_channel_count_; + for (int i = 0; i < audio_channel_count_; ++i) + channel_ptrs[i] = cur + i * size_per_channel; + + const int frame_count = frame_size / audio_bytes_per_frame; scoped_refptr<media::AudioBuffer> frame = media::AudioBuffer::CopyFrom( - audio_sample_format_, + sample_format, audio_channel_count_, frame_count, - data, + &channel_ptrs[0], base::TimeDelta::FromMicroseconds(timestamp), base::TimeDelta::FromMicroseconds(audio_samples_per_second_ / frame_count)); diff --git a/chromium/content/renderer/pepper/content_decryptor_delegate.h b/chromium/content/renderer/pepper/content_decryptor_delegate.h index f58ef9f6073..352817dd011 100644 --- a/chromium/content/renderer/pepper/content_decryptor_delegate.h +++ b/chromium/content/renderer/pepper/content_decryptor_delegate.h @@ -39,23 +39,24 @@ class ContentDecryptorDelegate { const PPP_ContentDecryptor_Private* plugin_decryption_interface); ~ContentDecryptorDelegate(); - void Initialize(const std::string& key_system, - const bool can_challenge_platform); + void Initialize(const std::string& key_system); - void SetKeyEventCallbacks(const media::KeyAddedCB& key_added_cb, - const media::KeyErrorCB& key_error_cb, - const media::KeyMessageCB& key_message_cb); + void SetSessionEventCallbacks( + const media::SessionCreatedCB& session_created_cb, + const media::SessionMessageCB& session_message_cb, + const media::SessionReadyCB& session_ready_cb, + const media::SessionClosedCB& session_closed_cb, + const media::SessionErrorCB& session_error_cb); // Provides access to PPP_ContentDecryptor_Private. - bool GenerateKeyRequest(const std::string& type, - const uint8* init_data, - int init_data_length); - bool AddKey(const std::string& session_id, - const uint8* key, - int key_length, - const uint8* init_data, - int init_data_length); - bool CancelKeyRequest(const std::string& session_id); + bool CreateSession(uint32 session_id, + const std::string& type, + const uint8* init_data, + int init_data_length); + bool UpdateSession(uint32 session_id, + const uint8* response, + int response_length); + bool ReleaseSession(uint32 session_id); bool Decrypt(media::Decryptor::StreamType stream_type, const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, const media::Decryptor::DecryptCB& decrypt_cb); @@ -79,18 +80,15 @@ class ContentDecryptorDelegate { const media::Decryptor::VideoDecodeCB& video_decode_cb); // PPB_ContentDecryptor_Private dispatching methods. - // TODO(ddorwin): Remove this method. - void NeedKey(PP_Var key_system, PP_Var session_id, PP_Var init_data); - // TODO(ddorwin): Remove key_system_var parameter from these methods. - void KeyAdded(PP_Var key_system, PP_Var session_id); - void KeyMessage(PP_Var key_system, - PP_Var session_id, - PP_Var message, - PP_Var default_url); - void KeyError(PP_Var key_system, - PP_Var session_id, - int32_t media_error, - int32_t system_code); + void OnSessionCreated(uint32 session_id, PP_Var web_session_id_var); + void OnSessionMessage(uint32 session_id, + PP_Var message, + PP_Var destination_url); + void OnSessionReady(uint32 session_id); + void OnSessionClosed(uint32 session_id); + void OnSessionError(uint32 session_id, + int32_t media_error, + int32_t system_code); void DeliverBlock(PP_Resource decrypted_block, const PP_DecryptedBlockInfo* block_info); void DecoderInitializeDone(PP_DecryptorStreamType decoder_type, @@ -103,7 +101,7 @@ class ContentDecryptorDelegate { void DeliverFrame(PP_Resource decrypted_frame, const PP_DecryptedFrameInfo* frame_info); void DeliverSamples(PP_Resource audio_frames, - const PP_DecryptedBlockInfo* block_info); + const PP_DecryptedSampleInfo* sample_info); private: // Cancels the pending decrypt-and-decode callback for |stream_type|. @@ -132,6 +130,7 @@ class ContentDecryptorDelegate { // buffers in |frames|. Returns true upon success. bool DeserializeAudioFrames(PP_Resource audio_frames, size_t data_size, + media::SampleFormat sample_format, media::Decryptor::AudioBuffers* frames); const PP_Instance pp_instance_; @@ -140,10 +139,12 @@ class ContentDecryptorDelegate { // TODO(ddorwin): Remove after updating the Pepper API to not use key system. std::string key_system_; - // Callbacks for firing key events. - media::KeyAddedCB key_added_cb_; - media::KeyErrorCB key_error_cb_; - media::KeyMessageCB key_message_cb_; + // Callbacks for firing session events. + media::SessionCreatedCB session_created_cb_; + media::SessionMessageCB session_message_cb_; + media::SessionReadyCB session_ready_cb_; + media::SessionClosedCB session_closed_cb_; + media::SessionErrorCB session_error_cb_; gfx::Size natural_size_; @@ -177,14 +178,12 @@ class ContentDecryptorDelegate { std::queue<uint32_t> free_buffers_; - base::WeakPtrFactory<ContentDecryptorDelegate> weak_ptr_factory_; - base::WeakPtr<ContentDecryptorDelegate> weak_this_; - // Keep track of audio parameters. - media::SampleFormat audio_sample_format_; int audio_samples_per_second_; int audio_channel_count_; - int audio_bytes_per_frame_; + + base::WeakPtr<ContentDecryptorDelegate> weak_this_; + base::WeakPtrFactory<ContentDecryptorDelegate> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(ContentDecryptorDelegate); }; diff --git a/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc b/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc index 0b59503a37c..0bd3fdf8729 100644 --- a/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc +++ b/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc @@ -10,7 +10,6 @@ #include "content/public/renderer/content_renderer_client.h" #include "content/renderer/pepper/pepper_audio_input_host.h" #include "content/renderer/pepper/pepper_file_chooser_host.h" -#include "content/renderer/pepper/pepper_file_io_host.h" #include "content/renderer/pepper/pepper_file_ref_renderer_host.h" #include "content/renderer/pepper/pepper_file_system_host.h" #include "content/renderer/pepper/pepper_graphics_2d_host.h" @@ -20,11 +19,13 @@ #include "content/renderer/pepper/pepper_video_destination_host.h" #include "content/renderer/pepper/pepper_video_source_host.h" #include "content/renderer/pepper/pepper_websocket_host.h" +#include "content/renderer/pepper/ppb_image_data_impl.h" #include "content/renderer/pepper/renderer_ppapi_host_impl.h" #include "ppapi/host/resource_host.h" #include "ppapi/proxy/ppapi_message_utils.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/serialized_structs.h" +#include "ppapi/shared_impl/ppb_image_data_shared.h" #include "third_party/WebKit/public/platform/WebURL.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebElement.h" @@ -35,11 +36,14 @@ using ppapi::proxy::SerializedTrueTypeFontDesc; using ppapi::UnpackMessage; namespace content { + +#if defined(ENABLE_WEBRTC) namespace { +#if defined(ENABLE_WEBRTC) bool CanUseMediaStreamAPI(const RendererPpapiHost* host, PP_Instance instance) { - WebKit::WebPluginContainer* container = + blink::WebPluginContainer* container = host->GetContainerForInstance(instance); if (!container) return false; @@ -49,8 +53,10 @@ bool CanUseMediaStreamAPI(const RendererPpapiHost* host, GetContentClient()->renderer(); return content_renderer_client->AllowPepperMediaStreamAPI(document_url); } +#endif // defined(ENABLE_WEBRTC) -} +} // namespace +#endif // defined(ENABLE_WEBRTC) ContentRendererPepperHostFactory::ContentRendererPepperHostFactory( RendererPpapiHostImpl* host) @@ -73,9 +79,6 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost( // Public interfaces. switch (message.type()) { - case PpapiHostMsg_FileIO_Create::ID: - return scoped_ptr<ResourceHost>(new PepperFileIOHost( - host_, instance, params.pp_resource())); case PpapiHostMsg_FileRef_CreateInternal::ID: { PP_Resource file_system; std::string internal_path; @@ -106,9 +109,11 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost( NOTREACHED(); return scoped_ptr<ResourceHost>(); } + scoped_refptr<PPB_ImageData_Impl> image_data(new PPB_ImageData_Impl( + instance, ppapi::PPB_ImageData_Shared::PLATFORM)); return scoped_ptr<ResourceHost>( PepperGraphics2DHost::Create(host_, instance, params.pp_resource(), - size, is_always_opaque)); + size, is_always_opaque, image_data)); } case PpapiHostMsg_URLLoader_Create::ID: return scoped_ptr<ResourceHost>(new PepperURLLoaderHost( diff --git a/chromium/content/renderer/pepper/event_conversion.cc b/chromium/content/renderer/pepper/event_conversion.cc index 0df48952943..b7c06016f77 100644 --- a/chromium/content/renderer/pepper/event_conversion.cc +++ b/chromium/content/renderer/pepper/event_conversion.cc @@ -26,14 +26,14 @@ using ppapi::EventTimeToPPTimeTicks; using ppapi::InputEventData; using ppapi::PPTimeTicksToEventTime; -using WebKit::WebInputEvent; -using WebKit::WebKeyboardEvent; -using WebKit::WebMouseEvent; -using WebKit::WebMouseWheelEvent; -using WebKit::WebString; -using WebKit::WebTouchEvent; -using WebKit::WebTouchPoint; -using WebKit::WebUChar; +using blink::WebInputEvent; +using blink::WebKeyboardEvent; +using blink::WebMouseEvent; +using blink::WebMouseWheelEvent; +using blink::WebString; +using blink::WebTouchEvent; +using blink::WebTouchPoint; +using blink::WebUChar; namespace content { diff --git a/chromium/content/renderer/pepper/event_conversion.h b/chromium/content/renderer/pepper/event_conversion.h index edaa7309912..81aa6b3acf7 100644 --- a/chromium/content/renderer/pepper/event_conversion.h +++ b/chromium/content/renderer/pepper/event_conversion.h @@ -17,7 +17,7 @@ namespace ppapi { struct InputEventData; } -namespace WebKit { +namespace blink { class WebGamepads; class WebInputEvent; } @@ -27,24 +27,24 @@ namespace content { // Converts the given WebKit event to one or possibly multiple PP_InputEvents. // The generated events will be filled into the given vector. On failure, no // events will ge generated and the vector will be empty. -void CreateInputEventData(const WebKit::WebInputEvent& event, +void CreateInputEventData(const blink::WebInputEvent& event, std::vector<ppapi::InputEventData >* pp_events); // Creates a WebInputEvent from the given PP_InputEvent. If it fails, returns // NULL. The caller owns the created object on success. -WebKit::WebInputEvent* CreateWebInputEvent(const ppapi::InputEventData& event); +blink::WebInputEvent* CreateWebInputEvent(const ppapi::InputEventData& event); // Creates an array of WebInputEvents to make the given event look like a user // input event on all platforms. |plugin_x| and |plugin_y| should be the // coordinates of a point within the plugin's area on the page. -std::vector<linked_ptr<WebKit::WebInputEvent> > CreateSimulatedWebInputEvents( +std::vector<linked_ptr<blink::WebInputEvent> > CreateSimulatedWebInputEvents( const ppapi::InputEventData& event, int plugin_x, int plugin_y); // Returns the PPAPI event class for the given WebKit event type. The given // type should not be "Undefined" since there's no corresponding PPAPI class. -PP_InputEvent_Class ClassifyInputEvent(WebKit::WebInputEvent::Type type); +PP_InputEvent_Class ClassifyInputEvent(blink::WebInputEvent::Type type); } // namespace content diff --git a/chromium/content/renderer/pepper/fake_pepper_plugin_instance.cc b/chromium/content/renderer/pepper/fake_pepper_plugin_instance.cc new file mode 100644 index 00000000000..af0ba49c0ee --- /dev/null +++ b/chromium/content/renderer/pepper/fake_pepper_plugin_instance.cc @@ -0,0 +1,81 @@ +// Copyright (c) 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/renderer/pepper/fake_pepper_plugin_instance.h" + +#include "ppapi/c/pp_errors.h" +#include "ppapi/shared_impl/ppapi_permissions.h" + +namespace content { + +FakePepperPluginInstance::~FakePepperPluginInstance() {} + +content::RenderView* FakePepperPluginInstance::GetRenderView() { + return NULL; +} + +blink::WebPluginContainer* FakePepperPluginInstance::GetContainer() { + return NULL; +} + +v8::Isolate* FakePepperPluginInstance::GetIsolate() const { + return NULL; +} + +ppapi::VarTracker* FakePepperPluginInstance::GetVarTracker() { + return NULL; +} + +const GURL& FakePepperPluginInstance::GetPluginURL() { + return gurl_; +} + +base::FilePath FakePepperPluginInstance::GetModulePath() { + return base::FilePath(); +} + +PP_Resource FakePepperPluginInstance::CreateImage(gfx::ImageSkia* source_image, + float scale) { + return 0; +} + +PP_ExternalPluginResult FakePepperPluginInstance::SwitchToOutOfProcessProxy( + const base::FilePath& file_path, + ppapi::PpapiPermissions permissions, + const IPC::ChannelHandle& channel_handle, + base::ProcessId plugin_pid, + int plugin_child_id) { + return PP_EXTERNAL_PLUGIN_FAILED; +} + +void FakePepperPluginInstance::SetAlwaysOnTop(bool on_top) {} + +bool FakePepperPluginInstance::IsFullPagePlugin() { + return false; +} + +bool FakePepperPluginInstance::FlashSetFullscreen(bool fullscreen, + bool delay_report) { + return false; +} + +bool FakePepperPluginInstance::IsRectTopmost(const gfx::Rect& rect) { + return false; +} + +int32_t FakePepperPluginInstance::Navigate( + const ppapi::URLRequestInfoData& request, + const char* target, + bool from_user_action) { + return PP_ERROR_FAILED; +} + +int FakePepperPluginInstance::MakePendingFileRefRendererHost( + const base::FilePath& path) { + return 0; +} + +void FakePepperPluginInstance::SetEmbedProperty(PP_Var key, PP_Var value) {} + +} // namespace content diff --git a/chromium/content/renderer/pepper/fake_pepper_plugin_instance.h b/chromium/content/renderer/pepper/fake_pepper_plugin_instance.h new file mode 100644 index 00000000000..f492b33facb --- /dev/null +++ b/chromium/content/renderer/pepper/fake_pepper_plugin_instance.h @@ -0,0 +1,49 @@ +// Copyright (c) 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_RENDERER_PEPPER_FAKE_PEPPER_PLUGIN_INSTANCE_H_ +#define CONTENT_RENDERER_PEPPER_FAKE_PEPPER_PLUGIN_INSTANCE_H_ + +#include "content/public/renderer/pepper_plugin_instance.h" +#include "url/gurl.h" + +namespace content { + +class FakePepperPluginInstance : public PepperPluginInstance { + public: + virtual ~FakePepperPluginInstance(); + + // PepperPluginInstance overrides. + virtual content::RenderView* GetRenderView() OVERRIDE; + virtual blink::WebPluginContainer* GetContainer() OVERRIDE; + virtual v8::Isolate* GetIsolate() const OVERRIDE; + virtual ppapi::VarTracker* GetVarTracker() OVERRIDE; + virtual const GURL& GetPluginURL() OVERRIDE; + virtual base::FilePath GetModulePath() OVERRIDE; + virtual PP_Resource CreateImage(gfx::ImageSkia* source_image, + float scale) OVERRIDE; + virtual PP_ExternalPluginResult SwitchToOutOfProcessProxy( + const base::FilePath& file_path, + ppapi::PpapiPermissions permissions, + const IPC::ChannelHandle& channel_handle, + base::ProcessId plugin_pid, + int plugin_child_id) OVERRIDE; + virtual void SetAlwaysOnTop(bool on_top) OVERRIDE; + virtual bool IsFullPagePlugin() OVERRIDE; + virtual bool FlashSetFullscreen(bool fullscreen, bool delay_report) OVERRIDE; + virtual bool IsRectTopmost(const gfx::Rect& rect) OVERRIDE; + virtual int32_t Navigate(const ppapi::URLRequestInfoData& request, + const char* target, + bool from_user_action) OVERRIDE; + virtual int MakePendingFileRefRendererHost( + const base::FilePath& path) OVERRIDE; + virtual void SetEmbedProperty(PP_Var key, PP_Var value) OVERRIDE; + + private: + GURL gurl_; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_PEPPER_FAKE_PEPPER_PLUGIN_INSTANCE_H_ diff --git a/chromium/content/renderer/pepper/fullscreen_container.h b/chromium/content/renderer/pepper/fullscreen_container.h index 81ee53d8554..d91cc668f49 100644 --- a/chromium/content/renderer/pepper/fullscreen_container.h +++ b/chromium/content/renderer/pepper/fullscreen_container.h @@ -5,11 +5,11 @@ #ifndef CONTENT_RENDERER_PEPPER_PPB_FULLSCREEN_CONTAINER_IMPL_H_ #define CONTENT_RENDERER_PEPPER_PPB_FULLSCREEN_CONTAINER_IMPL_H_ -namespace WebKit { +namespace blink { class WebLayer; struct WebCursorInfo; struct WebRect; -} // namespace WebKit +} // namespace blink namespace content { @@ -21,19 +21,19 @@ class FullscreenContainer { virtual void Invalidate() = 0; // Invalidates a partial region of the plugin. - virtual void InvalidateRect(const WebKit::WebRect&) = 0; + virtual void InvalidateRect(const blink::WebRect&) = 0; // Scrolls a partial region of the plugin in the given direction. - virtual void ScrollRect(int dx, int dy, const WebKit::WebRect&) = 0; + virtual void ScrollRect(int dx, int dy, const blink::WebRect&) = 0; // Destroys the fullscreen window. This also destroys the FullscreenContainer // instance. virtual void Destroy() = 0; // Notifies the container that the mouse cursor has changed. - virtual void DidChangeCursor(const WebKit::WebCursorInfo& cursor) = 0; + virtual void DidChangeCursor(const blink::WebCursorInfo& cursor) = 0; - virtual void SetLayer(WebKit::WebLayer* layer) = 0; + virtual void SetLayer(blink::WebLayer* layer) = 0; protected: virtual ~FullscreenContainer() {} diff --git a/chromium/content/renderer/pepper/host_array_buffer_var.cc b/chromium/content/renderer/pepper/host_array_buffer_var.cc index b6b719dab56..d8d4cec8bf9 100644 --- a/chromium/content/renderer/pepper/host_array_buffer_var.cc +++ b/chromium/content/renderer/pepper/host_array_buffer_var.cc @@ -18,7 +18,7 @@ #include "ppapi/c/pp_instance.h" using ppapi::ArrayBufferVar; -using WebKit::WebArrayBuffer; +using blink::WebArrayBuffer; namespace content { diff --git a/chromium/content/renderer/pepper/host_array_buffer_var.h b/chromium/content/renderer/pepper/host_array_buffer_var.h index 9ba1d7c6c56..13bd80630de 100644 --- a/chromium/content/renderer/pepper/host_array_buffer_var.h +++ b/chromium/content/renderer/pepper/host_array_buffer_var.h @@ -17,7 +17,7 @@ namespace content { class HostArrayBufferVar : public ppapi::ArrayBufferVar { public: explicit HostArrayBufferVar(uint32 size_in_bytes); - explicit HostArrayBufferVar(const WebKit::WebArrayBuffer& buffer); + explicit HostArrayBufferVar(const blink::WebArrayBuffer& buffer); explicit HostArrayBufferVar(uint32 size_in_bytes, base::SharedMemoryHandle handle); @@ -30,12 +30,12 @@ class HostArrayBufferVar : public ppapi::ArrayBufferVar { int* host_shm_handle_id, base::SharedMemoryHandle* plugin_shm_handle) OVERRIDE; - WebKit::WebArrayBuffer& webkit_buffer() { return buffer_; } + blink::WebArrayBuffer& webkit_buffer() { return buffer_; } private: virtual ~HostArrayBufferVar(); - WebKit::WebArrayBuffer buffer_; + blink::WebArrayBuffer buffer_; // Tracks whether the data in the buffer is valid. bool valid_; diff --git a/chromium/content/renderer/pepper/host_dispatcher_wrapper.cc b/chromium/content/renderer/pepper/host_dispatcher_wrapper.cc index 68ae4ebc090..8707d94b1a8 100644 --- a/chromium/content/renderer/pepper/host_dispatcher_wrapper.cc +++ b/chromium/content/renderer/pepper/host_dispatcher_wrapper.cc @@ -12,9 +12,6 @@ #include "content/renderer/pepper/renderer_ppapi_host_impl.h" #include "content/renderer/pepper/renderer_restrict_dispatch_group.h" #include "content/renderer/render_view_impl.h" -#include "third_party/WebKit/public/web/WebDocument.h" -#include "third_party/WebKit/public/web/WebElement.h" -#include "third_party/WebKit/public/web/WebPluginContainer.h" namespace content { @@ -87,7 +84,7 @@ void HostDispatcherWrapper::AddInstance(PP_Instance instance) { PepperRendererInstanceData( 0, // The render process id will be supplied in the browser. render_view->GetRoutingID(), - plugin_instance->GetContainer()->element().document().url(), + host->GetDocumentURL(instance), plugin_instance->GetPluginURL()), is_external_)); } diff --git a/chromium/content/renderer/pepper/host_globals.cc b/chromium/content/renderer/pepper/host_globals.cc index e35ea320791..31c5f0bd410 100644 --- a/chromium/content/renderer/pepper/host_globals.cc +++ b/chromium/content/renderer/pepper/host_globals.cc @@ -29,14 +29,14 @@ using ppapi::CheckIdType; using ppapi::MakeTypedId; using ppapi::PPIdType; using ppapi::ResourceTracker; -using WebKit::WebConsoleMessage; -using WebKit::WebString; +using blink::WebConsoleMessage; +using blink::WebString; namespace content { namespace { -typedef std::set<WebKit::WebPluginContainer*> ContainerSet; +typedef std::set<blink::WebPluginContainer*> ContainerSet; // Adds all WebPluginContainers associated with the given module to the set. void GetAllContainersForModule(PluginModule* module, @@ -177,7 +177,7 @@ void HostGlobals::BroadcastLogWithSource(PP_Module pp_module, (*i)->element().document().frame()->addMessageToConsole(message); } -base::TaskRunner* HostGlobals::GetFileTaskRunner(PP_Instance instance) { +base::TaskRunner* HostGlobals::GetFileTaskRunner() { return RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(); } diff --git a/chromium/content/renderer/pepper/host_globals.h b/chromium/content/renderer/pepper/host_globals.h index 761fa915743..9d1b289d506 100644 --- a/chromium/content/renderer/pepper/host_globals.h +++ b/chromium/content/renderer/pepper/host_globals.h @@ -51,7 +51,7 @@ class HostGlobals : public ppapi::PpapiGlobals { const std::string& source, const std::string& value) OVERRIDE; virtual ppapi::MessageLoopShared* GetCurrentMessageLoop() OVERRIDE; - virtual base::TaskRunner* GetFileTaskRunner(PP_Instance instance) OVERRIDE; + virtual base::TaskRunner* GetFileTaskRunner() OVERRIDE; HostVarTracker* host_var_tracker() { return &host_var_tracker_; diff --git a/chromium/content/renderer/pepper/host_resource_var.cc b/chromium/content/renderer/pepper/host_resource_var.cc index a59bed37f6f..810a949965e 100644 --- a/chromium/content/renderer/pepper/host_resource_var.cc +++ b/chromium/content/renderer/pepper/host_resource_var.cc @@ -9,16 +9,29 @@ namespace content { HostResourceVar::HostResourceVar() : pp_resource_(0) {} HostResourceVar::HostResourceVar(PP_Resource pp_resource) - : pp_resource_(pp_resource) {} + : pp_resource_(pp_resource), + pending_renderer_host_id_(0), + pending_browser_host_id_(0) {} -HostResourceVar::HostResourceVar(const IPC::Message& creation_message) +HostResourceVar::HostResourceVar(int pending_renderer_host_id, + const IPC::Message& creation_message) : pp_resource_(0), + pending_renderer_host_id_(pending_renderer_host_id), + pending_browser_host_id_(0), creation_message_(new IPC::Message(creation_message)) {} PP_Resource HostResourceVar::GetPPResource() const { return pp_resource_; } +int HostResourceVar::GetPendingRendererHostId() const { + return pending_renderer_host_id_; +} + +int HostResourceVar::GetPendingBrowserHostId() const { + return pending_browser_host_id_; +} + const IPC::Message* HostResourceVar::GetCreationMessage() const { return creation_message_.get(); } diff --git a/chromium/content/renderer/pepper/host_resource_var.h b/chromium/content/renderer/pepper/host_resource_var.h index 79fe487041d..cc6b0577f4d 100644 --- a/chromium/content/renderer/pepper/host_resource_var.h +++ b/chromium/content/renderer/pepper/host_resource_var.h @@ -24,23 +24,38 @@ class HostResourceVar : public ppapi::ResourceVar { explicit HostResourceVar(PP_Resource pp_resource); // Makes a resource var with a pending resource host. - // The |creation_message| contains data needed to create the plugin-side - // resource. Its type depends on the type of resource. - explicit HostResourceVar(const IPC::Message& creation_message); + // The |pending_renderer_host_id| is a pending resource host ID in the + // renderer to attach from the plugin. Depending on the type of resource, this + // may be 0. The |creation_message| contains additional data needed to create + // the plugin-side resource. Its type depends on the type of resource. + HostResourceVar(int pending_renderer_host_id, + const IPC::Message& creation_message); // ResourceVar override. virtual PP_Resource GetPPResource() const OVERRIDE; + virtual int GetPendingRendererHostId() const OVERRIDE; + virtual int GetPendingBrowserHostId() const OVERRIDE; virtual const IPC::Message* GetCreationMessage() const OVERRIDE; virtual bool IsPending() const OVERRIDE; + void set_pending_browser_host_id(int id) { + pending_browser_host_id_ = id; + } + protected: virtual ~HostResourceVar(); private: // Real resource ID in the plugin. 0 if one has not yet been created - // (indicating that there is a pending host resource). + // (indicating that there is a pending resource host). PP_Resource pp_resource_; + // Pending resource host ID in the renderer. + int pending_renderer_host_id_; + + // Pending resource host ID in the browser. + int pending_browser_host_id_; + // If the plugin-side resource has not yet been created, carries a message to // create a resource of the specific type on the plugin side. Otherwise, NULL. scoped_ptr<IPC::Message> creation_message_; diff --git a/chromium/content/renderer/pepper/host_var_tracker.cc b/chromium/content/renderer/pepper/host_var_tracker.cc index ed67dbaa616..27f2977b08e 100644 --- a/chromium/content/renderer/pepper/host_var_tracker.cc +++ b/chromium/content/renderer/pepper/host_var_tracker.cc @@ -103,6 +103,17 @@ int HostVarTracker::GetLiveNPObjectVarsForInstance(PP_Instance instance) const { return static_cast<int>(found->second->size()); } +PP_Var HostVarTracker::MakeResourcePPVarFromMessage( + PP_Instance instance, + const IPC::Message& creation_message, + int pending_renderer_id, + int pending_browser_id) { + // On the host side, the creation message is ignored when creating a resource. + // Therefore, a call to this function indicates a null resource. Return the + // resource 0. + return MakeResourcePPVar(0); +} + ppapi::ResourceVar* HostVarTracker::MakeResourceVar(PP_Resource pp_resource) { return new HostResourceVar(pp_resource); } diff --git a/chromium/content/renderer/pepper/host_var_tracker.h b/chromium/content/renderer/pepper/host_var_tracker.h index 858c3015e3d..5ab4df458ba 100644 --- a/chromium/content/renderer/pepper/host_var_tracker.h +++ b/chromium/content/renderer/pepper/host_var_tracker.h @@ -55,6 +55,11 @@ class HostVarTracker : public ppapi::VarTracker { PP_Instance instance) const; // VarTracker public implementation. + virtual PP_Var MakeResourcePPVarFromMessage( + PP_Instance instance, + const IPC::Message& creation_message, + int pending_renderer_id, + int pending_browser_id) OVERRIDE; virtual ppapi::ResourceVar* MakeResourceVar(PP_Resource pp_resource) OVERRIDE; virtual void DidDeleteInstance(PP_Instance instance) OVERRIDE; diff --git a/chromium/content/renderer/pepper/host_var_tracker_unittest.cc b/chromium/content/renderer/pepper/host_var_tracker_unittest.cc index 24932dbb8df..048680558d7 100644 --- a/chromium/content/renderer/pepper/host_var_tracker_unittest.cc +++ b/chromium/content/renderer/pepper/host_var_tracker_unittest.cc @@ -59,7 +59,7 @@ NPObject* NewTrackedNPObject() { class ReleaseNPObject { public: void operator()(NPObject* o) const { - WebKit::WebBindings::releaseObject(o); + blink::WebBindings::releaseObject(o); } }; diff --git a/chromium/content/renderer/pepper/message_channel.cc b/chromium/content/renderer/pepper/message_channel.cc index c41be2f451a..7c5961cfbe2 100644 --- a/chromium/content/renderer/pepper/message_channel.cc +++ b/chromium/content/renderer/pepper/message_channel.cc @@ -32,12 +32,12 @@ using ppapi::ArrayBufferVar; using ppapi::PpapiGlobals; using ppapi::StringVar; -using WebKit::WebBindings; -using WebKit::WebElement; -using WebKit::WebDOMEvent; -using WebKit::WebDOMMessageEvent; -using WebKit::WebPluginContainer; -using WebKit::WebSerializedScriptValue; +using blink::WebBindings; +using blink::WebElement; +using blink::WebDOMEvent; +using blink::WebDOMMessageEvent; +using blink::WebPluginContainer; +using blink::WebSerializedScriptValue; namespace content { @@ -105,8 +105,9 @@ PP_Var CopyPPVar(const PP_Var& var) { case PP_VARTYPE_ARRAY: case PP_VARTYPE_DICTIONARY: case PP_VARTYPE_RESOURCE: - // These types are not supported by PostMessage in-process. - NOTREACHED(); + // These types are not supported by PostMessage in-process. In some rare + // cases with the NaCl plugin, they may be sent but they will be dropped + // anyway (see crbug.com/318837 for details). return PP_MakeUndefined(); } NOTREACHED(); @@ -189,6 +190,12 @@ bool MessageChannelHasProperty(NPObject* np_obj, NPIdentifier name) { if (!np_obj) return false; + MessageChannel* message_channel = ToMessageChannel(np_obj); + if (message_channel) { + if (message_channel->GetReadOnlyProperty(name, NULL)) + return true; + } + // Invoke on the passthrough object, if we have one. NPObject* passthrough = ToPassThroughObject(np_obj); if (passthrough) @@ -205,6 +212,12 @@ bool MessageChannelGetProperty(NPObject* np_obj, NPIdentifier name, if (IdentifierIsPostMessage(name)) return false; + MessageChannel* message_channel = ToMessageChannel(np_obj); + if (message_channel) { + if (message_channel->GetReadOnlyProperty(name, result)) + return true; + } + // Invoke on the passthrough object, if we have one. NPObject* passthrough = ToPassThroughObject(np_obj); if (passthrough) @@ -289,8 +302,8 @@ MessageChannel::MessageChannel(PepperPluginInstanceImpl* instance) : instance_(instance), passthrough_object_(NULL), np_object_(NULL), - weak_ptr_factory_(this), - early_message_queue_state_(QUEUE_MESSAGES) { + early_message_queue_state_(QUEUE_MESSAGES), + weak_ptr_factory_(this) { // Now create an NPObject for receiving calls to postMessage. This sets the // reference count to 1. We release it in the destructor. NPObject* obj = WebBindings::createObject(instance_->instanceNPP(), @@ -344,7 +357,7 @@ void MessageChannel::NPVariantToPPVar(const NPVariant* variant) { // shouldn't result in a deep copy. v8::Handle<v8::Value> v8_value = WebBindings::toV8Value(variant); V8VarConverter(instance_->pp_instance()).FromV8Value( - v8_value, v8::Context::GetCurrent(), + v8_value, v8::Isolate::GetCurrent()->GetCurrentContext(), base::Bind(&MessageChannel::NPVariantToPPVarComplete, weak_ptr_factory_.GetWeakPtr(), result_iterator)); return; @@ -546,4 +559,20 @@ void MessageChannel::SetPassthroughObject(NPObject* passthrough) { passthrough_object_ = passthrough; } +bool MessageChannel::GetReadOnlyProperty(NPIdentifier key, + NPVariant *value) const { + std::map<NPIdentifier, ppapi::ScopedPPVar>::const_iterator it = + internal_properties_.find(key); + if (it != internal_properties_.end()) { + if (value) + return PPVarToNPVariant(it->second.get(), value); + return true; + } + return false; +} + +void MessageChannel::SetReadOnlyProperty(PP_Var key, PP_Var value) { + internal_properties_[PPVarToNPIdentifier(key)] = ppapi::ScopedPPVar(value); +} + } // namespace content diff --git a/chromium/content/renderer/pepper/message_channel.h b/chromium/content/renderer/pepper/message_channel.h index e4e14233593..43aa0f95a62 100644 --- a/chromium/content/renderer/pepper/message_channel.h +++ b/chromium/content/renderer/pepper/message_channel.h @@ -7,6 +7,7 @@ #include <deque> #include <list> +#include <map> #include "base/memory/weak_ptr.h" #include "ppapi/shared_impl/resource.h" @@ -81,6 +82,9 @@ class MessageChannel { void QueueJavaScriptMessages(); void StopQueueingJavaScriptMessages(); + bool GetReadOnlyProperty(NPIdentifier key, NPVariant* value) const; + void SetReadOnlyProperty(PP_Var key, PP_Var value); + private: // Struct for storing the result of a NPVariant being converted to a PP_Var. struct VarConversionResult { @@ -119,20 +123,16 @@ class MessageChannel { // Post a message to the onmessage handler for this channel's instance // synchronously. This is used by PostMessageToJavaScript. void PostMessageToJavaScriptImpl( - const WebKit::WebSerializedScriptValue& message_data); + const blink::WebSerializedScriptValue& message_data); // Post a message to the PPP_Instance HandleMessage function for this // channel's instance. This is used by PostMessageToNative. void PostMessageToNativeImpl(PP_Var message_data); void DrainEarlyMessageQueue(); - // This is used to ensure pending tasks will not fire after this object is - // destroyed. - base::WeakPtrFactory<MessageChannel> weak_ptr_factory_; - // TODO(teravest): Remove all the tricky DRAIN_CANCELLED logic once // PluginInstance::ResetAsProxied() is gone. - std::deque<WebKit::WebSerializedScriptValue> early_message_queue_; + std::deque<blink::WebSerializedScriptValue> early_message_queue_; enum EarlyMessageQueueState { QUEUE_MESSAGES, // Queue JS messages. SEND_DIRECTLY, // Post JS messages directly. @@ -147,6 +147,12 @@ class MessageChannel { // the order in which messages are processed is preserved. std::list<VarConversionResult> converted_var_queue_; + std::map<NPIdentifier, ppapi::ScopedPPVar> internal_properties_; + + // This is used to ensure pending tasks will not fire after this object is + // destroyed. + base::WeakPtrFactory<MessageChannel> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(MessageChannel); }; diff --git a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.cc b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.cc index b0ee2a7aa66..2354f0bd385 100644 --- a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.cc +++ b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.cc @@ -4,6 +4,7 @@ #include "content/renderer/pepper/mock_renderer_ppapi_host.h" +#include "content/renderer/pepper/fake_pepper_plugin_instance.h" #include "ui/gfx/point.h" namespace content { @@ -14,7 +15,8 @@ MockRendererPpapiHost::MockRendererPpapiHost(RenderView* render_view, ppapi_host_(&sink_, ppapi::PpapiPermissions()), render_view_(render_view), pp_instance_(instance), - has_user_gesture_(false) { + has_user_gesture_(false), + plugin_instance_(new FakePepperPluginInstance) { } MockRendererPpapiHost::~MockRendererPpapiHost() { @@ -30,7 +32,11 @@ bool MockRendererPpapiHost::IsValidInstance(PP_Instance instance) const { PepperPluginInstance* MockRendererPpapiHost::GetPluginInstance( PP_Instance instance) const { - NOTIMPLEMENTED(); + return plugin_instance_.get(); +} + +RenderFrame* MockRendererPpapiHost::GetRenderFrameForInstance( + PP_Instance instance) const { return NULL; } @@ -41,7 +47,7 @@ RenderView* MockRendererPpapiHost::GetRenderViewForInstance( return NULL; } -WebKit::WebPluginContainer* MockRendererPpapiHost::GetContainerForInstance( +blink::WebPluginContainer* MockRendererPpapiHost::GetContainerForInstance( PP_Instance instance) const { NOTIMPLEMENTED(); return NULL; @@ -60,7 +66,7 @@ int MockRendererPpapiHost::GetRoutingIDForWidget(PP_Instance instance) const { return 0; } -gfx::Point MockRendererPpapiHost::PluginPointToRenderView( +gfx::Point MockRendererPpapiHost::PluginPointToRenderFrame( PP_Instance instance, const gfx::Point& pt) const { return gfx::Point(); @@ -74,7 +80,6 @@ IPC::PlatformFileForTransit MockRendererPpapiHost::ShareHandleWithRemote( } bool MockRendererPpapiHost::IsRunningInProcess() const { - NOTIMPLEMENTED(); return false; } @@ -86,4 +91,9 @@ void MockRendererPpapiHost::CreateBrowserResourceHosts( return; } +GURL MockRendererPpapiHost::GetDocumentURL(PP_Instance instance) const { + NOTIMPLEMENTED(); + return GURL(); +} + } // namespace content diff --git a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h index 8f22d239ea3..c9d282ac99e 100644 --- a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h +++ b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h @@ -6,12 +6,14 @@ #define CONTENT_RENDERER_PEPPER_MOCK_RENDERER_PPAPI_HOST_H_ #include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" #include "content/public/renderer/renderer_ppapi_host.h" #include "content/renderer/pepper/content_renderer_pepper_host_factory.h" #include "ppapi/host/ppapi_host.h" #include "ppapi/proxy/resource_message_test_sink.h" namespace content { +class FakePepperPluginInstance; class PluginModule; // A mock RendererPpapiHost for testing resource hosts. Messages sent by @@ -35,14 +37,16 @@ class MockRendererPpapiHost : public RendererPpapiHost { virtual bool IsValidInstance(PP_Instance instance) const OVERRIDE; virtual PepperPluginInstance* GetPluginInstance( PP_Instance instance) const OVERRIDE; + virtual RenderFrame* GetRenderFrameForInstance( + PP_Instance instance) const OVERRIDE; virtual RenderView* GetRenderViewForInstance( PP_Instance instance) const OVERRIDE; - virtual WebKit::WebPluginContainer* GetContainerForInstance( + virtual blink::WebPluginContainer* GetContainerForInstance( PP_Instance instance) const OVERRIDE; virtual base::ProcessId GetPluginPID() const OVERRIDE; virtual bool HasUserGesture(PP_Instance instance) const OVERRIDE; virtual int GetRoutingIDForWidget(PP_Instance instance) const OVERRIDE; - virtual gfx::Point PluginPointToRenderView( + virtual gfx::Point PluginPointToRenderFrame( PP_Instance instance, const gfx::Point& pt) const OVERRIDE; virtual IPC::PlatformFileForTransit ShareHandleWithRemote( @@ -54,6 +58,7 @@ class MockRendererPpapiHost : public RendererPpapiHost { const std::vector<IPC::Message>& nested_msgs, const base::Callback<void( const std::vector<int>&)>& callback) const OVERRIDE; + virtual GURL GetDocumentURL(PP_Instance instance) const OVERRIDE; private: ppapi::proxy::ResourceMessageTestSink sink_; @@ -64,6 +69,8 @@ class MockRendererPpapiHost : public RendererPpapiHost { bool has_user_gesture_; + scoped_ptr<FakePepperPluginInstance> plugin_instance_; + DISALLOW_COPY_AND_ASSIGN(MockRendererPpapiHost); }; diff --git a/chromium/content/renderer/pepper/npapi_glue.cc b/chromium/content/renderer/pepper/npapi_glue.cc index 678a410019c..8489c4d3fbd 100644 --- a/chromium/content/renderer/pepper/npapi_glue.cc +++ b/chromium/content/renderer/pepper/npapi_glue.cc @@ -28,10 +28,10 @@ using ppapi::NPObjectVar; using ppapi::PpapiGlobals; using ppapi::StringVar; using ppapi::Var; -using WebKit::WebArrayBuffer; -using WebKit::WebBindings; -using WebKit::WebFrame; -using WebKit::WebPluginContainer; +using blink::WebArrayBuffer; +using blink::WebBindings; +using blink::WebFrame; +using blink::WebPluginContainer; namespace content { diff --git a/chromium/content/renderer/pepper/npobject_var.cc b/chromium/content/renderer/pepper/npobject_var.cc index 690dd229eeb..c45d0d2822a 100644 --- a/chromium/content/renderer/pepper/npobject_var.cc +++ b/chromium/content/renderer/pepper/npobject_var.cc @@ -10,7 +10,7 @@ #include "ppapi/c/pp_var.h" #include "third_party/WebKit/public/web/WebBindings.h" -using WebKit::WebBindings; +using blink::WebBindings; namespace ppapi { diff --git a/chromium/content/renderer/pepper/pepper_audio_input_host.cc b/chromium/content/renderer/pepper/pepper_audio_input_host.cc index 331bb49065f..19aa2b1b285 100644 --- a/chromium/content/renderer/pepper/pepper_audio_input_host.cc +++ b/chromium/content/renderer/pepper/pepper_audio_input_host.cc @@ -12,15 +12,11 @@ #include "content/renderer/pepper/renderer_ppapi_host_impl.h" #include "content/renderer/render_view_impl.h" #include "ipc/ipc_message.h" -#include "media/audio/shared_memory_util.h" #include "ppapi/c/pp_errors.h" #include "ppapi/host/dispatch_host_message.h" #include "ppapi/host/ppapi_host.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/serialized_structs.h" -#include "third_party/WebKit/public/web/WebDocument.h" -#include "third_party/WebKit/public/web/WebElement.h" -#include "third_party/WebKit/public/web/WebPluginContainer.h" namespace content { @@ -54,7 +50,8 @@ PepperAudioInputHost::PepperAudioInputHost( this, PepperMediaDeviceManager::GetForRenderView( host->GetRenderViewForInstance(pp_instance())), - PP_DEVICETYPE_DEV_AUDIOCAPTURE) { + PP_DEVICETYPE_DEV_AUDIOCAPTURE, + host->GetDocumentURL(instance)) { } PepperAudioInputHost::~PepperAudioInputHost() { @@ -100,9 +97,8 @@ int32_t PepperAudioInputHost::OnOpen( if (audio_input_) return PP_ERROR_FAILED; - PepperPluginInstanceImpl* instance = - renderer_ppapi_host_->GetPluginInstanceImpl(pp_instance()); - if (!instance) + GURL document_url = renderer_ppapi_host_->GetDocumentURL(pp_instance()); + if (!document_url.is_valid()) return PP_ERROR_FAILED; // When it is done, we'll get called back on StreamCreated() or @@ -112,7 +108,7 @@ int32_t PepperAudioInputHost::OnOpen( audio_input_ = PepperPlatformAudioInput::Create( render_view->AsWeakPtr(), device_id, - instance->container()->element().document().url(), + document_url, static_cast<int>(sample_rate), static_cast<int>(sample_frame_count), this); if (audio_input_) { @@ -169,13 +165,7 @@ void PepperAudioInputHost::OnOpenComplete( scoped_socket, scoped_shared_memory, &temp_socket, &temp_shmem); serialized_socket_handle.set_socket(temp_socket); - // Note that we must call TotalSharedMemorySizeInBytes() because extra space - // in shared memory is allocated for book-keeping, so the actual size of the - // shared memory buffer is larger than |shared_memory_size|. When sending to - // NaCl, NaClIPCAdapter expects this size to match the size of the full - // shared memory buffer. - serialized_shared_memory_handle.set_shmem( - temp_shmem, media::TotalSharedMemorySizeInBytes(shared_memory_size)); + serialized_shared_memory_handle.set_shmem(temp_shmem, shared_memory_size); } // Send all the values, even on error. This simplifies some of our cleanup diff --git a/chromium/content/renderer/pepper/pepper_browser_connection.cc b/chromium/content/renderer/pepper/pepper_browser_connection.cc index 803f3df96c9..dfb24298131 100644 --- a/chromium/content/renderer/pepper/pepper_browser_connection.cc +++ b/chromium/content/renderer/pepper/pepper_browser_connection.cc @@ -9,16 +9,16 @@ #include "base/logging.h" #include "content/common/view_messages.h" #include "content/renderer/pepper/pepper_in_process_router.h" -#include "content/renderer/render_view_impl.h" +#include "content/renderer/render_frame_impl.h" #include "ipc/ipc_message_macros.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/resource_message_params.h" namespace content { -PepperBrowserConnection::PepperBrowserConnection(RenderView* render_view) - : RenderViewObserver(render_view), - RenderViewObserverTracker<PepperBrowserConnection>(render_view), +PepperBrowserConnection::PepperBrowserConnection(RenderFrame* render_frame) + : RenderFrameObserver(render_frame), + RenderFrameObserverTracker<PepperBrowserConnection>(render_frame), next_sequence_number_(1) { } diff --git a/chromium/content/renderer/pepper/pepper_browser_connection.h b/chromium/content/renderer/pepper/pepper_browser_connection.h index bef0ba2db1c..cfc5603cff9 100644 --- a/chromium/content/renderer/pepper/pepper_browser_connection.h +++ b/chromium/content/renderer/pepper/pepper_browser_connection.h @@ -11,12 +11,14 @@ #include "base/callback.h" #include "base/files/file_path.h" -#include "content/public/renderer/render_view_observer.h" -#include "content/public/renderer/render_view_observer_tracker.h" +#include "content/public/renderer/render_frame_observer.h" +#include "content/public/renderer/render_frame_observer_tracker.h" #include "ppapi/c/pp_file_info.h" #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_resource.h" +class GURL; + namespace content { // This class represents a connection from the renderer to the browser for @@ -24,12 +26,12 @@ namespace content { // and renderer communicate about ResourceHosts, they should pass the plugin // process ID to identify which plugin they are talking about. class PepperBrowserConnection - : public RenderViewObserver, - public RenderViewObserverTracker<PepperBrowserConnection> { + : public RenderFrameObserver, + public RenderFrameObserverTracker<PepperBrowserConnection> { public: typedef base::Callback<void(const std::vector<int>&)> PendingResourceIDCallback; - explicit PepperBrowserConnection(RenderView* render_view); + explicit PepperBrowserConnection(RenderFrame* render_frame); virtual ~PepperBrowserConnection(); virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; diff --git a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc index 9ec6373a096..28beb20936e 100644 --- a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc +++ b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc @@ -34,6 +34,9 @@ class PepperDeviceEnumerationHostHelper::ScopedRequest requested_(false), request_id_(0), sync_call_(false) { + if (!owner_->document_url_.is_valid()) + return; + requested_ = true; // Note that the callback passed into @@ -46,6 +49,7 @@ class PepperDeviceEnumerationHostHelper::ScopedRequest sync_call_ = true; request_id_ = owner_->delegate_->EnumerateDevices( owner_->device_type_, + owner_->document_url_, base::Bind(&ScopedRequest::EnumerateDevicesCallbackBody, AsWeakPtr())); sync_call_ = false; } @@ -61,7 +65,6 @@ class PepperDeviceEnumerationHostHelper::ScopedRequest private: void EnumerateDevicesCallbackBody( int request_id, - bool succeeded, const std::vector<ppapi::DeviceRefData>& devices) { if (sync_call_) { base::MessageLoop::current()->PostTask( @@ -69,11 +72,10 @@ class PepperDeviceEnumerationHostHelper::ScopedRequest base::Bind(&ScopedRequest::EnumerateDevicesCallbackBody, AsWeakPtr(), request_id, - succeeded, devices)); } else { DCHECK_EQ(request_id_, request_id); - callback_.Run(request_id, succeeded, devices); + callback_.Run(request_id, devices); // This object may have been destroyed at this point. } } @@ -91,10 +93,12 @@ class PepperDeviceEnumerationHostHelper::ScopedRequest PepperDeviceEnumerationHostHelper::PepperDeviceEnumerationHostHelper( ppapi::host::ResourceHost* resource_host, Delegate* delegate, - PP_DeviceType_Dev device_type) + PP_DeviceType_Dev device_type, + const GURL& document_url) : resource_host_(resource_host), delegate_(delegate), - device_type_(device_type) { + device_type_(device_type), + document_url_(document_url) { } PepperDeviceEnumerationHostHelper::~PepperDeviceEnumerationHostHelper() { @@ -165,31 +169,27 @@ int32_t PepperDeviceEnumerationHostHelper::OnStopMonitoringDeviceChange( void PepperDeviceEnumerationHostHelper::OnEnumerateDevicesComplete( int /* request_id */, - bool succeeded, const std::vector<ppapi::DeviceRefData>& devices) { DCHECK(enumerate_devices_context_.get()); enumerate_.reset(NULL); - enumerate_devices_context_->params.set_result( - succeeded ? PP_OK : PP_ERROR_FAILED); + enumerate_devices_context_->params.set_result(PP_OK); resource_host_->host()->SendReply( *enumerate_devices_context_, - PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply( - succeeded ? devices : std::vector<ppapi::DeviceRefData>())); + PpapiPluginMsg_DeviceEnumeration_EnumerateDevicesReply(devices)); enumerate_devices_context_.reset(); } void PepperDeviceEnumerationHostHelper::OnNotifyDeviceChange( uint32_t callback_id, int /* request_id */, - bool succeeded, const std::vector<ppapi::DeviceRefData>& devices) { resource_host_->host()->SendUnsolicitedReply( resource_host_->pp_resource(), PpapiPluginMsg_DeviceEnumeration_NotifyDeviceChange( callback_id, - succeeded ? devices : std::vector<ppapi::DeviceRefData>())); + devices)); } } // namespace content diff --git a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h index 5773845561b..4142dec758e 100644 --- a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h +++ b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h @@ -12,6 +12,7 @@ #include "base/memory/scoped_ptr.h" #include "content/common/content_export.h" #include "ppapi/c/dev/ppb_device_ref_dev.h" +#include "url/gurl.h" namespace ppapi { struct DeviceRefData; @@ -42,13 +43,13 @@ class CONTENT_EXPORT PepperDeviceEnumerationHostHelper { typedef base::Callback< void (int /* request_id */, - bool /* succeeded */, const std::vector<ppapi::DeviceRefData>& /* devices */)> EnumerateDevicesCallback; // Enumerates devices of the specified type. The request ID passed into the // callback will be the same as the return value. virtual int EnumerateDevices(PP_DeviceType_Dev type, + const GURL& document_url, const EnumerateDevicesCallback& callback) = 0; // Stop enumerating devices of the specified |request_id|. The |request_id| // is the return value of EnumerateDevicesCallback. @@ -58,7 +59,8 @@ class CONTENT_EXPORT PepperDeviceEnumerationHostHelper { // |resource_host| and |delegate| must outlive this object. PepperDeviceEnumerationHostHelper(ppapi::host::ResourceHost* resource_host, Delegate* delegate, - PP_DeviceType_Dev device_type); + PP_DeviceType_Dev device_type, + const GURL& document_url); ~PepperDeviceEnumerationHostHelper(); // Returns true if the message has been handled. @@ -84,12 +86,10 @@ class CONTENT_EXPORT PepperDeviceEnumerationHostHelper { void OnEnumerateDevicesComplete( int request_id, - bool succeeded, const std::vector<ppapi::DeviceRefData>& devices); void OnNotifyDeviceChange( uint32_t callback_id, int request_id, - bool succeeded, const std::vector<ppapi::DeviceRefData>& devices); // Non-owning pointers. @@ -97,6 +97,7 @@ class CONTENT_EXPORT PepperDeviceEnumerationHostHelper { Delegate* delegate_; PP_DeviceType_Dev device_type_; + GURL document_url_; scoped_ptr<ScopedRequest> enumerate_; scoped_ptr<ScopedRequest> monitor_; diff --git a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc index 895bdd8e273..298e953bf64 100644 --- a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc +++ b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc @@ -18,6 +18,7 @@ #include "ppapi/proxy/resource_message_test_sink.h" #include "ppapi/shared_impl/ppapi_permissions.h" #include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" namespace content { @@ -34,6 +35,7 @@ class TestDelegate : public PepperDeviceEnumerationHostHelper::Delegate { virtual int EnumerateDevices( PP_DeviceType_Dev /* type */, + const GURL& /* document_url */, const EnumerateDevicesCallback& callback) OVERRIDE { last_used_id_++; callbacks_[last_used_id_] = callback; @@ -50,14 +52,13 @@ class TestDelegate : public PepperDeviceEnumerationHostHelper::Delegate { // Returns false if |request_id| is not found. bool SimulateEnumerateResult( int request_id, - bool succeeded, const std::vector<ppapi::DeviceRefData>& devices) { std::map<int, EnumerateDevicesCallback>::iterator iter = callbacks_.find(request_id); if (iter == callbacks_.end()) return false; - iter->second.Run(request_id, succeeded, devices); + iter->second.Run(request_id, devices); return true; } @@ -78,7 +79,8 @@ class PepperDeviceEnumerationHostHelperTest : public testing::Test { : ppapi_host_(&sink_, ppapi::PpapiPermissions()), resource_host_(&ppapi_host_, 12345, 67890), device_enumeration_(&resource_host_, &delegate_, - PP_DEVICETYPE_DEV_AUDIOCAPTURE) { + PP_DEVICETYPE_DEV_AUDIOCAPTURE, + GURL("http://example.com")) { } virtual ~PepperDeviceEnumerationHostHelperTest() {} @@ -150,7 +152,7 @@ TEST_F(PepperDeviceEnumerationHostHelperTest, EnumerateDevices) { data_item.name = "name_2"; data_item.id = "id_2"; data.push_back(data_item); - ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id, true, data)); + ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id, data)); // StopEnumerateDevices() should have been called since the EnumerateDevices // message is not a persistent request. @@ -181,7 +183,7 @@ TEST_F(PepperDeviceEnumerationHostHelperTest, MonitorDeviceChange) { int request_id = delegate_.last_used_id(); std::vector<ppapi::DeviceRefData> data; - ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id, true, data)); + ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id, data)); // StopEnumerateDevices() shouldn't be called because the MonitorDeviceChange // message is a persistent request. @@ -198,7 +200,7 @@ TEST_F(PepperDeviceEnumerationHostHelperTest, MonitorDeviceChange) { data_item.name = "name_2"; data_item.id = "id_2"; data.push_back(data_item); - ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id, true, data)); + ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id, data)); EXPECT_EQ(1U, delegate_.GetRegisteredCallbackCount()); CheckNotifyDeviceChangeMessage(callback_id, data); @@ -214,7 +216,7 @@ TEST_F(PepperDeviceEnumerationHostHelperTest, MonitorDeviceChange) { data_item.name = "name_3"; data_item.id = "id_3"; data.push_back(data_item); - ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id2, true, data)); + ASSERT_TRUE(delegate_.SimulateEnumerateResult(request_id2, data)); CheckNotifyDeviceChangeMessage(callback_id2, data); diff --git a/chromium/content/renderer/pepper/pepper_file_chooser_host.cc b/chromium/content/renderer/pepper/pepper_file_chooser_host.cc index e73694ac336..ca13f5a7949 100644 --- a/chromium/content/renderer/pepper/pepper_file_chooser_host.cc +++ b/chromium/content/renderer/pepper/pepper_file_chooser_host.cc @@ -22,7 +22,7 @@ namespace content { class PepperFileChooserHost::CompletionHandler - : public WebKit::WebFileChooserCompletion { + : public blink::WebFileChooserCompletion { public: CompletionHandler(const base::WeakPtr<PepperFileChooserHost>& host) : host_(host) { @@ -31,7 +31,7 @@ class PepperFileChooserHost::CompletionHandler virtual ~CompletionHandler() {} virtual void didChooseFile( - const WebKit::WebVector<WebKit::WebString>& file_names) { + const blink::WebVector<blink::WebString>& file_names) { if (host_.get()) { std::vector<PepperFileChooserHost::ChosenFileInfo> files; for (size_t i = 0; i < file_names.size(); i++) { @@ -45,7 +45,7 @@ class PepperFileChooserHost::CompletionHandler delete this; } virtual void didChooseFile( - const WebKit::WebVector<SelectedFileInfo>& file_names) { + const blink::WebVector<SelectedFileInfo>& file_names) { if (host_.get()) { std::vector<PepperFileChooserHost::ChosenFileInfo> files; for (size_t i = 0; i < file_names.size(); i++) { @@ -145,17 +145,17 @@ int32_t PepperFileChooserHost::OnShow( return PP_ERROR_NO_USER_GESTURE; } - WebKit::WebFileChooserParams params; + blink::WebFileChooserParams params; if (save_as) { params.saveAs = true; - params.initialValue = WebKit::WebString::fromUTF8( + params.initialValue = blink::WebString::fromUTF8( suggested_file_name.data(), suggested_file_name.size()); } else { params.multiSelect = open_multiple; } - std::vector<WebKit::WebString> mine_types(accept_mime_types.size()); + std::vector<blink::WebString> mine_types(accept_mime_types.size()); for (size_t i = 0; i < accept_mime_types.size(); i++) { - mine_types[i] = WebKit::WebString::fromUTF8( + mine_types[i] = blink::WebString::fromUTF8( accept_mime_types[i].data(), accept_mime_types[i].size()); } params.acceptTypes = mine_types; diff --git a/chromium/content/renderer/pepper/pepper_file_io_host.cc b/chromium/content/renderer/pepper/pepper_file_io_host.cc deleted file mode 100644 index 6add31ae0d6..00000000000 --- a/chromium/content/renderer/pepper/pepper_file_io_host.cc +++ /dev/null @@ -1,563 +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/renderer/pepper/pepper_file_io_host.h" - -#include "base/bind.h" -#include "base/callback.h" -#include "base/callback_helpers.h" -#include "base/command_line.h" -#include "base/files/file_util_proxy.h" -#include "content/child/child_thread.h" -#include "content/child/fileapi/file_system_dispatcher.h" -#include "content/child/quota_dispatcher.h" -#include "content/common/fileapi/file_system_messages.h" -#include "content/common/view_messages.h" -#include "content/public/common/content_client.h" -#include "content/public/renderer/content_renderer_client.h" -#include "content/renderer/pepper/pepper_file_ref_renderer_host.h" -#include "content/renderer/pepper/quota_file_io.h" -#include "content/renderer/pepper/renderer_ppapi_host_impl.h" -#include "content/renderer/render_thread_impl.h" -#include "ppapi/c/pp_errors.h" -#include "ppapi/c/ppb_file_io.h" -#include "ppapi/host/dispatch_host_message.h" -#include "ppapi/host/ppapi_host.h" -#include "ppapi/proxy/ppapi_messages.h" -#include "ppapi/shared_impl/file_type_conversion.h" -#include "ppapi/shared_impl/time_conversion.h" -#include "ppapi/thunk/enter.h" -#include "third_party/WebKit/public/web/WebPluginContainer.h" - -namespace content { - -using ppapi::FileIOStateManager; -using ppapi::PPTimeToTime; -using ppapi::host::ReplyMessageContext; -using ppapi::thunk::EnterResourceNoLock; - -namespace { - -typedef base::Callback<void (base::PlatformFileError)> PlatformGeneralCallback; - -int32_t ErrorOrByteNumber(int32_t pp_error, int32_t byte_number) { - // On the plugin side, some callbacks expect a parameter that means different - // things depending on whether is negative or not. We translate for those - // callbacks here. - return pp_error == PP_OK ? byte_number : pp_error; -} - -class QuotaCallbackTranslator : public QuotaDispatcher::Callback { - public: - typedef QuotaFileIO::Delegate::AvailableSpaceCallback PluginCallback; - explicit QuotaCallbackTranslator(const PluginCallback& cb) : callback_(cb) {} - virtual void DidQueryStorageUsageAndQuota(int64 usage, int64 quota) OVERRIDE { - callback_.Run(std::max(static_cast<int64>(0), quota - usage)); - } - virtual void DidGrantStorageQuota(int64 granted_quota) OVERRIDE { - NOTREACHED(); - } - virtual void DidFail(quota::QuotaStatusCode error) OVERRIDE { - callback_.Run(0); - } - private: - PluginCallback callback_; -}; - -class QuotaFileIODelegate : public QuotaFileIO::Delegate { - public: - QuotaFileIODelegate() {} - virtual ~QuotaFileIODelegate() {} - - virtual void QueryAvailableSpace( - const GURL& origin, - quota::StorageType type, - const AvailableSpaceCallback& callback) OVERRIDE { - ChildThread::current()->quota_dispatcher()->QueryStorageUsageAndQuota( - origin, type, new QuotaCallbackTranslator(callback)); - } - virtual void WillUpdateFile(const GURL& file_path) OVERRIDE { - ChildThread::current()->Send(new FileSystemHostMsg_WillUpdate(file_path)); - } - virtual void DidUpdateFile(const GURL& file_path, int64_t delta) OVERRIDE { - ChildThread::current()->Send(new FileSystemHostMsg_DidUpdate( - file_path, delta)); - } - virtual scoped_refptr<base::MessageLoopProxy> - GetFileThreadMessageLoopProxy() OVERRIDE { - return RenderThreadImpl::current()->GetFileThreadMessageLoopProxy(); - } -}; - -typedef base::Callback< - void (base::PlatformFileError error, - base::PassPlatformFile file, - quota::QuotaLimitType quota_policy, - const PepperFileIOHost::NotifyCloseFileCallback& close_file_callback)> - AsyncOpenFileSystemURLCallback; - -void DoNotifyCloseFile(int file_open_id, base::PlatformFileError error) { - ChildThread::current()->file_system_dispatcher()->NotifyCloseFile( - file_open_id); -} - -void DidOpenFileSystemURL(const AsyncOpenFileSystemURLCallback& callback, - base::PlatformFile file, - int file_open_id, - quota::QuotaLimitType quota_policy) { - callback.Run(base::PLATFORM_FILE_OK, - base::PassPlatformFile(&file), - quota_policy, - base::Bind(&DoNotifyCloseFile, file_open_id)); - // Make sure we won't leak file handle if the requester has died. - if (file != base::kInvalidPlatformFileValue) { - base::FileUtilProxy::Close( - RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(), - file, - base::Bind(&DoNotifyCloseFile, file_open_id)); - } -} - -void DidFailOpenFileSystemURL(const AsyncOpenFileSystemURLCallback& callback, - base::PlatformFileError error_code) { - base::PlatformFile invalid_file = base::kInvalidPlatformFileValue; - callback.Run(error_code, - base::PassPlatformFile(&invalid_file), - quota::kQuotaLimitTypeUnknown, - PepperFileIOHost::NotifyCloseFileCallback()); -} - -} // namespace - -PepperFileIOHost::PepperFileIOHost(RendererPpapiHost* host, - PP_Instance instance, - PP_Resource resource) - : ResourceHost(host->GetPpapiHost(), instance, resource), - renderer_ppapi_host_(host), - file_(base::kInvalidPlatformFileValue), - file_system_type_(PP_FILESYSTEMTYPE_INVALID), - quota_policy_(quota::kQuotaLimitTypeUnknown), - is_running_in_process_(host->IsRunningInProcess()), - open_flags_(0), - routing_id_(RenderThreadImpl::current()->GenerateRoutingID()), - weak_factory_(this) { - ChildThread::current()->AddRoute(routing_id_, this); -} - -PepperFileIOHost::~PepperFileIOHost() { - OnHostMsgClose(NULL); - ChildThread::current()->RemoveRoute(routing_id_); -} - -int32_t PepperFileIOHost::OnResourceMessageReceived( - const IPC::Message& msg, - ppapi::host::HostMessageContext* context) { - IPC_BEGIN_MESSAGE_MAP(PepperFileIOHost, msg) - PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Open, - OnHostMsgOpen) - PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Touch, - OnHostMsgTouch) - PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Write, - OnHostMsgWrite) - PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_SetLength, - OnHostMsgSetLength) - PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Flush, - OnHostMsgFlush) - PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Close, - OnHostMsgClose) - PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_WillWrite, - OnHostMsgWillWrite) - PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_WillSetLength, - OnHostMsgWillSetLength) - PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_GetOSFileDescriptor, - OnHostMsgGetOSFileDescriptor) - PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_RequestOSFileHandle, - OnHostMsgRequestOSFileHandle) - IPC_END_MESSAGE_MAP() - return PP_ERROR_FAILED; -} - -bool PepperFileIOHost::OnMessageReceived(const IPC::Message& msg) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(PepperFileIOHost, msg) - IPC_MESSAGE_HANDLER(ViewMsg_AsyncOpenPepperFile_ACK, OnAsyncFileOpened) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - -void PepperFileIOHost::OnAsyncFileOpened( - base::PlatformFileError error_code, - IPC::PlatformFileForTransit file_for_transit, - int message_id) { - AsyncOpenFileCallback* callback = - pending_async_open_files_.Lookup(message_id); - DCHECK(callback); - pending_async_open_files_.Remove(message_id); - - base::PlatformFile file = - IPC::PlatformFileForTransitToPlatformFile(file_for_transit); - callback->Run(error_code, base::PassPlatformFile(&file)); - // Make sure we won't leak file handle if the requester has died. - if (file != base::kInvalidPlatformFileValue) { - base::FileUtilProxy::Close( - RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(), - file, - base::FileUtilProxy::StatusCallback()); - } - delete callback; -} - -int32_t PepperFileIOHost::OnHostMsgOpen( - ppapi::host::HostMessageContext* context, - PP_Resource file_ref_resource, - int32_t open_flags) { - int32_t rv = state_manager_.CheckOperationState( - FileIOStateManager::OPERATION_EXCLUSIVE, false); - if (rv != PP_OK) - return rv; - - open_flags_ = open_flags; - if (!ppapi::PepperFileOpenFlagsToPlatformFileFlags(open_flags, NULL)) - return PP_ERROR_BADARGUMENT; - - ppapi::host::ResourceHost* resource_host = - renderer_ppapi_host_->GetPpapiHost()->GetResourceHost(file_ref_resource); - if (!resource_host || !resource_host->IsFileRefHost()) - return PP_ERROR_BADRESOURCE; - PepperFileRefRendererHost* file_ref_host = - static_cast<PepperFileRefRendererHost*>(resource_host); - - file_system_type_ = file_ref_host->GetFileSystemType(); - if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) { - file_system_url_ = file_ref_host->GetFileSystemURL(); - FileSystemDispatcher* file_system_dispatcher = - ChildThread::current()->file_system_dispatcher(); - - AsyncOpenFileSystemURLCallback callback = base::Bind( - &PepperFileIOHost::ExecutePlatformOpenFileSystemURLCallback, - weak_factory_.GetWeakPtr(), - context->MakeReplyMessageContext()); - file_system_dispatcher->OpenPepperFile( - file_system_url_, open_flags, - base::Bind(&DidOpenFileSystemURL, callback), - base::Bind(&DidFailOpenFileSystemURL, callback)); - } else { - int message_id = pending_async_open_files_.Add(new AsyncOpenFileCallback( - base::Bind(&PepperFileIOHost::ExecutePlatformOpenFileCallback, - weak_factory_.GetWeakPtr(), - context->MakeReplyMessageContext()))); - RenderThreadImpl::current()->Send(new ViewHostMsg_AsyncOpenPepperFile( - routing_id_, - file_ref_host->GetExternalFilePath(), - open_flags_, - message_id)); - } - state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); - return PP_OK_COMPLETIONPENDING; -} - -int32_t PepperFileIOHost::OnHostMsgTouch( - ppapi::host::HostMessageContext* context, - PP_Time last_access_time, - PP_Time last_modified_time) { - int32_t rv = state_manager_.CheckOperationState( - FileIOStateManager::OPERATION_EXCLUSIVE, true); - if (rv != PP_OK) - return rv; - - if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) { - FileSystemDispatcher* file_system_dispatcher = - ChildThread::current()->file_system_dispatcher(); - file_system_dispatcher->TouchFile( - file_system_url_, - PPTimeToTime(last_access_time), - PPTimeToTime(last_modified_time), - base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback, - weak_factory_.GetWeakPtr(), - context->MakeReplyMessageContext())); - state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); - return PP_OK_COMPLETIONPENDING; - } - - // TODO(nhiroki): fix a failure of FileIO.Touch for an external filesystem on - // Mac and Linux due to sandbox restrictions (http://crbug.com/101128). - if (!base::FileUtilProxy::Touch( - RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(), - file_, - PPTimeToTime(last_access_time), - PPTimeToTime(last_modified_time), - base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback, - weak_factory_.GetWeakPtr(), - context->MakeReplyMessageContext()))) - return PP_ERROR_FAILED; - - state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); - return PP_OK_COMPLETIONPENDING; -} - -int32_t PepperFileIOHost::OnHostMsgWrite( - ppapi::host::HostMessageContext* context, - int64_t offset, - const std::string& buffer) { - int32_t rv = state_manager_.CheckOperationState( - FileIOStateManager::OPERATION_WRITE, true); - if (rv != PP_OK) - return rv; - - if (quota_file_io_) { - if (!quota_file_io_->Write( - offset, buffer.c_str(), buffer.size(), - base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback, - weak_factory_.GetWeakPtr(), - context->MakeReplyMessageContext()))) - return PP_ERROR_FAILED; - } else { - if (!base::FileUtilProxy::Write( - RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(), - file_, - offset, - buffer.c_str(), - buffer.size(), - base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback, - weak_factory_.GetWeakPtr(), - context->MakeReplyMessageContext()))) - return PP_ERROR_FAILED; - } - - state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE); - return PP_OK_COMPLETIONPENDING; -} - -int32_t PepperFileIOHost::OnHostMsgSetLength( - ppapi::host::HostMessageContext* context, - int64_t length) { - int32_t rv = state_manager_.CheckOperationState( - FileIOStateManager::OPERATION_EXCLUSIVE, true); - if (rv != PP_OK) - return rv; - - if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) { - FileSystemDispatcher* file_system_dispatcher = - ChildThread::current()->file_system_dispatcher(); - file_system_dispatcher->Truncate( - file_system_url_, length, NULL, - base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback, - weak_factory_.GetWeakPtr(), - context->MakeReplyMessageContext())); - } else { - // TODO(nhiroki): fix a failure of FileIO.SetLength for an external - // filesystem on Mac due to sandbox restrictions (http://crbug.com/156077). - if (!base::FileUtilProxy::Truncate( - RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(), - file_, - length, - base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback, - weak_factory_.GetWeakPtr(), - context->MakeReplyMessageContext()))) - return PP_ERROR_FAILED; - } - - state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); - return PP_OK_COMPLETIONPENDING; -} - -int32_t PepperFileIOHost::OnHostMsgFlush( - ppapi::host::HostMessageContext* context) { - int32_t rv = state_manager_.CheckOperationState( - FileIOStateManager::OPERATION_EXCLUSIVE, true); - if (rv != PP_OK) - return rv; - - if (!base::FileUtilProxy::Flush( - RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(), - file_, - base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback, - weak_factory_.GetWeakPtr(), - context->MakeReplyMessageContext()))) - return PP_ERROR_FAILED; - - state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); - return PP_OK_COMPLETIONPENDING; -} - -int32_t PepperFileIOHost::OnHostMsgClose( - ppapi::host::HostMessageContext* context) { - if (file_ != base::kInvalidPlatformFileValue) { - base::FileUtilProxy::Close( - RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(), - file_, - base::ResetAndReturn(¬ify_close_file_callback_)); - file_ = base::kInvalidPlatformFileValue; - quota_file_io_.reset(); - } - return PP_OK; -} - -int32_t PepperFileIOHost::OnHostMsgWillWrite( - ppapi::host::HostMessageContext* context, - int64_t offset, - int32_t bytes_to_write) { - int32_t rv = state_manager_.CheckOperationState( - FileIOStateManager::OPERATION_EXCLUSIVE, true); - if (rv != PP_OK) - return rv; - - if (!quota_file_io_) - return PP_OK; - - if (!quota_file_io_->WillWrite( - offset, bytes_to_write, - base::Bind(&PepperFileIOHost::ExecutePlatformWriteCallback, - weak_factory_.GetWeakPtr(), - context->MakeReplyMessageContext()))) - return PP_ERROR_FAILED; - - state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); - return PP_OK_COMPLETIONPENDING; -} - -int32_t PepperFileIOHost::OnHostMsgWillSetLength( - ppapi::host::HostMessageContext* context, - int64_t length) { - int32_t rv = state_manager_.CheckOperationState( - FileIOStateManager::OPERATION_EXCLUSIVE, true); - if (rv != PP_OK) - return rv; - - if (!quota_file_io_) - return PP_OK; - - if (!quota_file_io_->WillSetLength( - length, - base::Bind(&PepperFileIOHost::ExecutePlatformGeneralCallback, - weak_factory_.GetWeakPtr(), - context->MakeReplyMessageContext()))) - return PP_ERROR_FAILED; - - state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE); - return PP_OK_COMPLETIONPENDING; -} - -int32_t PepperFileIOHost::OnHostMsgRequestOSFileHandle( - ppapi::host::HostMessageContext* context) { - if (!is_running_in_process_ && - quota_policy_ != quota::kQuotaLimitTypeUnlimited) - return PP_ERROR_FAILED; - - // Whitelist to make it privately accessible. - if (!GetContentClient()->renderer()->IsPluginAllowedToCallRequestOSFileHandle( - renderer_ppapi_host_->GetContainerForInstance(pp_instance()))) - return PP_ERROR_NOACCESS; - - IPC::PlatformFileForTransit file = - renderer_ppapi_host_->ShareHandleWithRemote(file_, false); - if (file == IPC::InvalidPlatformFileForTransit()) - return PP_ERROR_FAILED; - ppapi::host::ReplyMessageContext reply_context = - context->MakeReplyMessageContext(); - ppapi::proxy::SerializedHandle file_handle; - file_handle.set_file_handle(file, open_flags_); - reply_context.params.AppendHandle(file_handle); - host()->SendReply(reply_context, - PpapiPluginMsg_FileIO_RequestOSFileHandleReply()); - return PP_OK_COMPLETIONPENDING; -} - -int32_t PepperFileIOHost::OnHostMsgGetOSFileDescriptor( - ppapi::host::HostMessageContext* context) { - if (!is_running_in_process_) - return PP_ERROR_FAILED; - - int32_t fd = -#if defined(OS_POSIX) - file_; -#elif defined(OS_WIN) - reinterpret_cast<uintptr_t>(file_); -#else - -1; -#endif - - host()->SendReply(context->MakeReplyMessageContext(), - PpapiPluginMsg_FileIO_GetOSFileDescriptorReply(fd)); - return PP_OK_COMPLETIONPENDING; -} - -void PepperFileIOHost::ExecutePlatformGeneralCallback( - ppapi::host::ReplyMessageContext reply_context, - base::PlatformFileError error_code) { - reply_context.params.set_result( - ppapi::PlatformFileErrorToPepperError(error_code)); - host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply()); - state_manager_.SetOperationFinished(); -} - -void PepperFileIOHost::ExecutePlatformOpenFileCallback( - ppapi::host::ReplyMessageContext reply_context, - base::PlatformFileError error_code, - base::PassPlatformFile file) { - int32_t pp_error = ppapi::PlatformFileErrorToPepperError(error_code); - if (pp_error == PP_OK) - state_manager_.SetOpenSucceed(); - - DCHECK(file_ == base::kInvalidPlatformFileValue); - file_ = file.ReleaseValue(); - - DCHECK(!quota_file_io_.get()); - if (file_ != base::kInvalidPlatformFileValue) { - if (file_system_type_ == PP_FILESYSTEMTYPE_LOCALTEMPORARY || - file_system_type_ == PP_FILESYSTEMTYPE_LOCALPERSISTENT) { - quota_file_io_.reset(new QuotaFileIO( - new QuotaFileIODelegate, file_, file_system_url_, file_system_type_)); - } - - IPC::PlatformFileForTransit file_for_transit = - renderer_ppapi_host_->ShareHandleWithRemote(file_, false); - if (!(file_for_transit == IPC::InvalidPlatformFileForTransit())) { - // Send the file descriptor to the plugin process. This is used in the - // plugin for any file operations that can be done there. - int32_t flags_to_send = open_flags_; - if (!host()->permissions().HasPermission(ppapi::PERMISSION_DEV)) { - // IMPORTANT: Clear PP_FILEOPENFLAG_WRITE and PP_FILEOPENFLAG_APPEND so - // the plugin can't write and so bypass our quota checks. - flags_to_send = - open_flags_ & ~(PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_APPEND); - } - ppapi::proxy::SerializedHandle file_handle; - file_handle.set_file_handle(file_for_transit, flags_to_send); - reply_context.params.AppendHandle(file_handle); - } - } - - reply_context.params.set_result(pp_error); - host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenReply()); - state_manager_.SetOperationFinished(); -} - -void PepperFileIOHost::ExecutePlatformOpenFileSystemURLCallback( - ppapi::host::ReplyMessageContext reply_context, - base::PlatformFileError error_code, - base::PassPlatformFile file, - quota::QuotaLimitType quota_policy, - const PepperFileIOHost::NotifyCloseFileCallback& callback) { - if (error_code == base::PLATFORM_FILE_OK) - notify_close_file_callback_ = callback; - quota_policy_ = quota_policy; - ExecutePlatformOpenFileCallback(reply_context, error_code, file); -} - -void PepperFileIOHost::ExecutePlatformWriteCallback( - ppapi::host::ReplyMessageContext reply_context, - base::PlatformFileError error_code, - int bytes_written) { - // On the plugin side, the callback expects a parameter with different meaning - // depends on whether is negative or not. It is the result here. We translate - // for the callback. - int32_t pp_error = ppapi::PlatformFileErrorToPepperError(error_code); - reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_written)); - host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply()); - state_manager_.SetOperationFinished(); -} - -} // namespace content diff --git a/chromium/content/renderer/pepper/pepper_file_io_host.h b/chromium/content/renderer/pepper/pepper_file_io_host.h deleted file mode 100644 index 0525a6c605b..00000000000 --- a/chromium/content/renderer/pepper/pepper_file_io_host.h +++ /dev/null @@ -1,148 +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_RENDERER_PEPPER_PEPPER_FILE_IO_HOST_H_ -#define CONTENT_RENDERER_PEPPER_PEPPER_FILE_IO_HOST_H_ - -#include <set> -#include <string> - -#include "base/basictypes.h" -#include "base/callback_forward.h" -#include "base/id_map.h" -#include "base/memory/weak_ptr.h" -#include "base/platform_file.h" -#include "content/public/renderer/renderer_ppapi_host.h" -#include "ipc/ipc_listener.h" -#include "ipc/ipc_platform_file.h" -#include "ppapi/host/host_message_context.h" -#include "ppapi/host/resource_host.h" -#include "ppapi/shared_impl/file_io_state_manager.h" -#include "ppapi/thunk/ppb_file_ref_api.h" -#include "url/gurl.h" -#include "webkit/common/quota/quota_types.h" - -using ppapi::host::ReplyMessageContext; - -namespace content { -class QuotaFileIO; - -class PepperFileIOHost : public ppapi::host::ResourceHost, - public base::SupportsWeakPtr<PepperFileIOHost>, - public IPC::Listener { - public: - typedef base::Callback<void (base::PlatformFileError)> - NotifyCloseFileCallback; - - PepperFileIOHost(RendererPpapiHost* host, - PP_Instance instance, - PP_Resource resource); - virtual ~PepperFileIOHost(); - - // ppapi::host::ResourceHost override. - virtual int32_t OnResourceMessageReceived( - const IPC::Message& msg, - ppapi::host::HostMessageContext* context) OVERRIDE; - - private: - // IPC::Listener implementation. - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - - void OnAsyncFileOpened( - base::PlatformFileError error_code, - IPC::PlatformFileForTransit file_for_transit, - int message_id); - - int32_t OnHostMsgOpen(ppapi::host::HostMessageContext* context, - PP_Resource file_ref_resource, - int32_t open_flags); - int32_t OnHostMsgTouch(ppapi::host::HostMessageContext* context, - PP_Time last_access_time, - PP_Time last_modified_time); - int32_t OnHostMsgWrite(ppapi::host::HostMessageContext* context, - int64_t offset, - const std::string& buffer); - int32_t OnHostMsgSetLength(ppapi::host::HostMessageContext* context, - int64_t length); - int32_t OnHostMsgClose(ppapi::host::HostMessageContext* context); - int32_t OnHostMsgFlush(ppapi::host::HostMessageContext* context); - // Private API. - int32_t OnHostMsgRequestOSFileHandle( - ppapi::host::HostMessageContext* context); - // Trusted API. - int32_t OnHostMsgGetOSFileDescriptor( - ppapi::host::HostMessageContext* context); - int32_t OnHostMsgWillWrite(ppapi::host::HostMessageContext* context, - int64_t offset, - int32_t bytes_to_write); - int32_t OnHostMsgWillSetLength(ppapi::host::HostMessageContext* context, - int64_t length); - - // Callback handlers. These mostly convert the PlatformFileError to the - // 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); - void ExecutePlatformOpenFileSystemURLCallback( - ReplyMessageContext reply_context, - base::PlatformFileError error_code, - base::PassPlatformFile file, - quota::QuotaLimitType quota_policy, - const NotifyCloseFileCallback& callback); - void ExecutePlatformQueryCallback(ReplyMessageContext reply_context, - base::PlatformFileError error_code, - const base::PlatformFileInfo& file_info); - void ExecutePlatformReadCallback(ReplyMessageContext reply_context, - base::PlatformFileError error_code, - const char* data, int bytes_read); - void ExecutePlatformWriteCallback(ReplyMessageContext reply_context, - base::PlatformFileError error_code, - int bytes_written); - - RendererPpapiHost* renderer_ppapi_host_; - base::PlatformFile file_; - - // The file system type specified in the Open() call. This will be - // PP_FILESYSTEMTYPE_INVALID before open was called. This value does not - // indicate that the open command actually succeeded. - PP_FileSystemType file_system_type_; - - // Valid only for PP_FILESYSTEMTYPE_LOCAL{PERSISTENT,TEMPORARY}. - GURL file_system_url_; - - // Used to check if we can pass file handle to plugins. - quota::QuotaLimitType quota_policy_; - - // Callback function for notifying when the file handle is closed. - NotifyCloseFileCallback notify_close_file_callback_; - - // 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_; - - bool is_running_in_process_; - - int32_t open_flags_; - - ppapi::FileIOStateManager state_manager_; - - int routing_id_; - - typedef base::Callback<void (base::PlatformFileError, base::PassPlatformFile)> - AsyncOpenFileCallback; - - IDMap<AsyncOpenFileCallback> pending_async_open_files_; - - base::WeakPtrFactory<PepperFileIOHost> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(PepperFileIOHost); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_PEPPER_PEPPER_FILE_IO_HOST_H_ diff --git a/chromium/content/renderer/pepper/pepper_file_system_host.cc b/chromium/content/renderer/pepper/pepper_file_system_host.cc index 00c580b6d31..be5cead8240 100644 --- a/chromium/content/renderer/pepper/pepper_file_system_host.cc +++ b/chromium/content/renderer/pepper/pepper_file_system_host.cc @@ -15,33 +15,15 @@ #include "ppapi/host/dispatch_host_message.h" #include "ppapi/host/ppapi_host.h" #include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/shared_impl/file_system_util.h" #include "ppapi/shared_impl/file_type_conversion.h" #include "third_party/WebKit/public/web/WebDocument.h" -#include "third_party/WebKit/public/web/WebElement.h" #include "third_party/WebKit/public/web/WebFrame.h" -#include "third_party/WebKit/public/web/WebPluginContainer.h" #include "third_party/WebKit/public/web/WebView.h" #include "webkit/common/fileapi/file_system_util.h" namespace content { -namespace { - -bool LooksLikeAGuid(const std::string& fsid) { - const size_t kExpectedFsIdSize = 32; - if (fsid.size() != kExpectedFsIdSize) - return false; - for (std::string::const_iterator it = fsid.begin(); it != fsid.end(); ++it) { - if (('A' <= *it && *it <= 'F') || - ('0' <= *it && *it <= '9')) - continue; - return false; - } - return true; -} - -} // namespace - PepperFileSystemHost::PepperFileSystemHost(RendererPpapiHost* host, PP_Instance instance, PP_Resource resource, @@ -54,6 +36,20 @@ PepperFileSystemHost::PepperFileSystemHost(RendererPpapiHost* host, weak_factory_(this) { } +PepperFileSystemHost::PepperFileSystemHost(RendererPpapiHost* host, + PP_Instance instance, + PP_Resource resource, + const GURL& root_url, + PP_FileSystemType type) + : ResourceHost(host->GetPpapiHost(), instance, resource), + renderer_ppapi_host_(host), + type_(type), + opened_(true), + root_url_(root_url), + called_open_(true), + weak_factory_(this) { +} + PepperFileSystemHost::~PepperFileSystemHost() { } @@ -102,33 +98,21 @@ int32_t PepperFileSystemHost::OnHostMsgOpen( return PP_ERROR_INPROGRESS; called_open_ = true; - fileapi::FileSystemType file_system_type; - switch (type_) { - case PP_FILESYSTEMTYPE_LOCALTEMPORARY: - file_system_type = fileapi::kFileSystemTypeTemporary; - break; - case PP_FILESYSTEMTYPE_LOCALPERSISTENT: - file_system_type = fileapi::kFileSystemTypePersistent; - break; - case PP_FILESYSTEMTYPE_EXTERNAL: - file_system_type = fileapi::kFileSystemTypeExternal; - break; - default: - return PP_ERROR_FAILED; - } - - PepperPluginInstance* plugin_instance = - renderer_ppapi_host_->GetPluginInstance(pp_instance()); - if (!plugin_instance) + fileapi::FileSystemType file_system_type = + ppapi::PepperFileSystemTypeToFileSystemType(type_); + if (file_system_type == fileapi::kFileSystemTypeUnknown) + return PP_ERROR_FAILED; + + GURL document_url = renderer_ppapi_host_->GetDocumentURL(pp_instance()); + if (!document_url.is_valid()) return PP_ERROR_FAILED; FileSystemDispatcher* file_system_dispatcher = ChildThread::current()->file_system_dispatcher(); reply_context_ = context->MakeReplyMessageContext(); file_system_dispatcher->OpenFileSystem( - GURL(plugin_instance->GetContainer()->element().document().url()). - GetOrigin(), - file_system_type, expected_size, true /* create */, + document_url.GetOrigin(), + file_system_type, base::Bind(&PepperFileSystemHost::DidOpenFileSystem, weak_factory_.GetWeakPtr()), base::Bind(&PepperFileSystemHost::DidFailOpenFileSystem, @@ -138,18 +122,28 @@ int32_t PepperFileSystemHost::OnHostMsgOpen( int32_t PepperFileSystemHost::OnHostMsgInitIsolatedFileSystem( ppapi::host::HostMessageContext* context, - const std::string& fsid) { + const std::string& fsid, + PP_IsolatedFileSystemType_Private type) { + // Do not allow multiple opens. + if (called_open_) + return PP_ERROR_INPROGRESS; called_open_ = true; + // Do a sanity check. - if (!LooksLikeAGuid(fsid)) + if (!fileapi::ValidateIsolatedFileSystemId(fsid)) return PP_ERROR_BADARGUMENT; + RenderView* view = renderer_ppapi_host_->GetRenderViewForInstance(pp_instance()); if (!view) return PP_ERROR_FAILED; + const GURL& url = view->GetWebView()->mainFrame()->document().url(); + const std::string root_name = ppapi::IsolatedFileSystemTypeToRootName(type); + if (root_name.empty()) + return PP_ERROR_BADARGUMENT; root_url_ = GURL(fileapi::GetIsolatedFileSystemRootURIString( - url.GetOrigin(), fsid, "crxfs")); + url.GetOrigin(), fsid, root_name)); opened_ = true; return PP_OK; } diff --git a/chromium/content/renderer/pepper/pepper_file_system_host.h b/chromium/content/renderer/pepper/pepper_file_system_host.h index 3ff8d4d6e21..0e0be311c1c 100644 --- a/chromium/content/renderer/pepper/pepper_file_system_host.h +++ b/chromium/content/renderer/pepper/pepper_file_system_host.h @@ -5,9 +5,12 @@ #ifndef CONTENT_RENDERER_PEPPER_PEPPER_FILE_SYSTEM_HOST_H_ #define CONTENT_RENDERER_PEPPER_PEPPER_FILE_SYSTEM_HOST_H_ +#include <string> + #include "base/basictypes.h" #include "base/memory/weak_ptr.h" #include "ppapi/c/pp_file_info.h" +#include "ppapi/c/private/ppb_isolated_file_system_private.h" #include "ppapi/host/host_message_context.h" #include "ppapi/host/resource_host.h" #include "url/gurl.h" @@ -16,13 +19,24 @@ namespace content { class RendererPpapiHost; -class PepperFileSystemHost : - public ppapi::host::ResourceHost, - public base::SupportsWeakPtr<PepperFileSystemHost> { +class PepperFileSystemHost + : public ppapi::host::ResourceHost, + public base::SupportsWeakPtr<PepperFileSystemHost> { public: + // Creates a new PepperFileSystemHost for a file system of a given |type|. The + // host will not be connected to any specific file system, and will need to + // subsequently be opened before use. + PepperFileSystemHost(RendererPpapiHost* host, + PP_Instance instance, + PP_Resource resource, + PP_FileSystemType type); + // Creates a new PepperFileSystemHost with an existing file system at the + // given |root_url| and of the given |type|. The file system must already be + // opened. Once created, the PepperFileSystemHost is already opened for use. PepperFileSystemHost(RendererPpapiHost* host, PP_Instance instance, PP_Resource resource, + const GURL& root_url, PP_FileSystemType type); virtual ~PepperFileSystemHost(); @@ -46,7 +60,8 @@ class PepperFileSystemHost : int64_t expected_size); int32_t OnHostMsgInitIsolatedFileSystem( ppapi::host::HostMessageContext* context, - const std::string& fsid); + const std::string& fsid, + PP_IsolatedFileSystemType_Private type); RendererPpapiHost* renderer_ppapi_host_; ppapi::host::ReplyMessageContext reply_context_; diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc index 8fb9841d645..51034591b8b 100644 --- a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc +++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc @@ -23,11 +23,11 @@ #include "ppapi/host/host_message_context.h" #include "ppapi/host/ppapi_host.h" #include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/shared_impl/ppb_view_shared.h" #include "ppapi/thunk/enter.h" #include "skia/ext/platform_canvas.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/blit.h" -#include "ui/gfx/point.h" #include "ui/gfx/point_conversions.h" #include "ui/gfx/rect.h" #include "ui/gfx/rect_conversions.h" @@ -136,7 +136,8 @@ struct PepperGraphics2DHost::QueuedOperation { enum Type { PAINT, SCROLL, - REPLACE + REPLACE, + SET_OFFSET }; QueuedOperation(Type t) @@ -160,18 +161,24 @@ struct PepperGraphics2DHost::QueuedOperation { // Valid when type == REPLACE. scoped_refptr<PPB_ImageData_Impl> replace_image; + + // Valid when type == SET_OFFSET. + gfx::Point offset; }; // static -PepperGraphics2DHost* PepperGraphics2DHost::Create(RendererPpapiHost* host, - PP_Instance instance, - PP_Resource resource, - const PP_Size& size, - PP_Bool is_always_opaque) { +PepperGraphics2DHost* PepperGraphics2DHost::Create( + RendererPpapiHost* host, + PP_Instance instance, + PP_Resource resource, + const PP_Size& size, + PP_Bool is_always_opaque, + scoped_refptr<PPB_ImageData_Impl> backing_store) { PepperGraphics2DHost* resource_host = new PepperGraphics2DHost(host, instance, resource); if (!resource_host->Init(size.width, size.height, - PP_ToBool(is_always_opaque))) { + PP_ToBool(is_always_opaque), + backing_store)) { delete resource_host; return NULL; } @@ -188,9 +195,9 @@ PepperGraphics2DHost::PepperGraphics2DHost(RendererPpapiHost* host, offscreen_flush_pending_(false), is_always_opaque_(false), scale_(1.0f), - weak_ptr_factory_(this), is_running_in_process_(host->IsRunningInProcess()), - texture_mailbox_modified_(true) {} + texture_mailbox_modified_(true), + resize_mode_(PP_GRAPHICS2D_DEV_RESIZEMODE_DEFAULT) {} PepperGraphics2DHost::~PepperGraphics2DHost() { // Unbind from the instance when destroyed if we're still bound. @@ -198,10 +205,13 @@ PepperGraphics2DHost::~PepperGraphics2DHost() { bound_instance_->BindGraphics(bound_instance_->pp_instance(), 0); } -bool PepperGraphics2DHost::Init(int width, int height, bool is_always_opaque) { +bool PepperGraphics2DHost::Init( + int width, + int height, + bool is_always_opaque, + scoped_refptr<PPB_ImageData_Impl> backing_store) { // The underlying PPB_ImageData_Impl will validate the dimensions. - image_data_ = new PPB_ImageData_Impl(pp_instance(), - PPB_ImageData_Impl::PLATFORM); + image_data_ = backing_store; if (!image_data_->Init(PPB_ImageData_Impl::GetNativeImageDataFormat(), width, height, true) || !image_data_->Map()) { @@ -226,13 +236,19 @@ int32_t PepperGraphics2DHost::OnResourceMessageReceived( PPAPI_DISPATCH_HOST_RESOURCE_CALL( PpapiHostMsg_Graphics2D_ReplaceContents, OnHostMsgReplaceContents) - PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( + PPAPI_DISPATCH_HOST_RESOURCE_CALL( PpapiHostMsg_Graphics2D_Flush, OnHostMsgFlush) PPAPI_DISPATCH_HOST_RESOURCE_CALL( PpapiHostMsg_Graphics2D_Dev_SetScale, OnHostMsgSetScale) PPAPI_DISPATCH_HOST_RESOURCE_CALL( + PpapiHostMsg_Graphics2D_SetOffset, + OnHostMsgSetOffset) + PPAPI_DISPATCH_HOST_RESOURCE_CALL( + PpapiHostMsg_Graphics2D_SetResizeMode, + OnHostMsgSetResizeMode) + PPAPI_DISPATCH_HOST_RESOURCE_CALL( PpapiHostMsg_Graphics2D_ReadImageData, OnHostMsgReadImageData) IPC_END_MESSAGE_MAP() @@ -323,7 +339,7 @@ bool PepperGraphics2DHost::BindToInstance( // The |backing_bitmap| must be clipped to the |plugin_rect| to avoid painting // outside the plugin area. This can happen if the plugin has been resized since // PaintImageData verified the image is within the plugin size. -void PepperGraphics2DHost::Paint(WebKit::WebCanvas* canvas, +void PepperGraphics2DHost::Paint(blink::WebCanvas* canvas, const gfx::Rect& plugin_rect, const gfx::Rect& paint_rect) { TRACE_EVENT0("pepper", "PepperGraphics2DHost::Paint"); @@ -380,17 +396,20 @@ void PepperGraphics2DHost::Paint(WebKit::WebCanvas* canvas, origin.set(SkIntToScalar(plugin_rect.x()), SkIntToScalar(plugin_rect.y())); SkPoint pixel_origin = origin; - if (scale_ != 1.0f && scale_ > 0.0f) { - float inverse_scale = 1.0f / scale_; - pixel_origin.scale(inverse_scale); - canvas->scale(scale_, scale_); + + gfx::PointF resize_scale(GetResizeScale()); + gfx::PointF scale(ScalePoint(resize_scale, scale_)); + if ((scale.x() != 1.0f || scale.y() != 1.0f) && + scale.x() > 0.0f && scale.y() > 0.0f) { + canvas->scale(scale.x(), scale.y()); + pixel_origin.set(pixel_origin.x() * (1.0f / scale.x()), + pixel_origin.y() * (1.0f / scale.y())); } + pixel_origin.offset(SkIntToScalar(plugin_offset_.x()), + SkIntToScalar(plugin_offset_.y())); canvas->drawBitmap(image, pixel_origin.x(), pixel_origin.y(), &paint); } -void PepperGraphics2DHost::ViewWillInitiatePaint() { -} - void PepperGraphics2DHost::ViewInitiatedPaint() { } @@ -402,6 +421,11 @@ void PepperGraphics2DHost::ViewFlushedPaint() { } } +void PepperGraphics2DHost::DidChangeView(const ppapi::ViewData& view_data) { + gfx::Size old_plugin_size = current_plugin_size_; + current_plugin_size_ = PP_ToGfxSize(view_data.rect.size); +} + void PepperGraphics2DHost::SetScale(float scale) { scale_ = scale; } @@ -418,6 +442,27 @@ PPB_ImageData_Impl* PepperGraphics2DHost::ImageData() { return image_data_.get(); } +gfx::Size PepperGraphics2DHost::Size() const { + if (!image_data_) + return gfx::Size(); + return gfx::Size(image_data_->width(), image_data_->height()); +} + +gfx::PointF PepperGraphics2DHost::GetResizeScale() const { + switch (resize_mode_) { + case PP_GRAPHICS2D_DEV_RESIZEMODE_DEFAULT: + return gfx::PointF(1.0f, 1.0f); + case PP_GRAPHICS2D_DEV_RESIZEMODE_STRETCH: + if (flushed_plugin_size_.IsEmpty()) + return gfx::PointF(1.0f, 1.0f); + return gfx::PointF( + 1.0f * current_plugin_size_.width() / flushed_plugin_size_.width(), + 1.0f * current_plugin_size_.height() / flushed_plugin_size_.height()); + } + NOTREACHED(); + return gfx::PointF(1.0f, 1.0f); +} + int32_t PepperGraphics2DHost::OnHostMsgPaintImageData( ppapi::host::HostMessageContext* context, const ppapi::HostResource& image_data, @@ -510,7 +555,8 @@ int32_t PepperGraphics2DHost::OnHostMsgReplaceContents( } int32_t PepperGraphics2DHost::OnHostMsgFlush( - ppapi::host::HostMessageContext* context) { + ppapi::host::HostMessageContext* context, + const ppapi::ViewData& view_data) { // Don't allow more than one pending flush at a time. if (HasPendingFlush()) return PP_ERROR_INPROGRESS; @@ -518,10 +564,10 @@ int32_t PepperGraphics2DHost::OnHostMsgFlush( PP_Resource old_image_data = 0; flush_reply_context_ = context->MakeReplyMessageContext(); if (is_running_in_process_) - return Flush(NULL); + return Flush(NULL, PP_ToGfxSize(view_data.rect.size)); // Reuse image data when running out of process. - int32_t result = Flush(&old_image_data); + int32_t result = Flush(&old_image_data, PP_ToGfxSize(view_data.rect.size)); if (old_image_data) { // If the Graphics2D has an old image data it's not using any more, send @@ -547,6 +593,22 @@ int32_t PepperGraphics2DHost::OnHostMsgSetScale( return PP_ERROR_BADARGUMENT; } +int32_t PepperGraphics2DHost::OnHostMsgSetOffset( + ppapi::host::HostMessageContext* context, + const PP_Point& offset) { + QueuedOperation operation(QueuedOperation::SET_OFFSET); + operation.offset = PP_ToGfxPoint(offset); + queued_operations_.push_back(operation); + return PP_OK; +} + +int32_t PepperGraphics2DHost::OnHostMsgSetResizeMode( + ppapi::host::HostMessageContext* context, + PP_Graphics2D_Dev_ResizeMode resize_mode) { + resize_mode_ = resize_mode; + return PP_OK; +} + int32_t PepperGraphics2DHost::OnHostMsgReadImageData( ppapi::host::HostMessageContext* context, PP_Resource image, @@ -586,13 +648,15 @@ void PepperGraphics2DHost::AttachedToNewLayer() { texture_mailbox_modified_ = true; } -int32_t PepperGraphics2DHost::Flush(PP_Resource* old_image_data) { +int32_t PepperGraphics2DHost::Flush(PP_Resource* old_image_data, + const gfx::Size& flushed_plugin_size) { bool done_replace_contents = false; bool no_update_visible = true; bool is_plugin_visible = true; for (size_t i = 0; i < queued_operations_.size(); i++) { QueuedOperation& operation = queued_operations_[i]; gfx::Rect op_rect; + gfx::Rect old_op_rect; switch (operation.type) { case QueuedOperation::PAINT: ExecutePaintImageData(operation.paint_image.get(), @@ -616,16 +680,28 @@ int32_t PepperGraphics2DHost::Flush(PP_Resource* old_image_data) { done_replace_contents ? NULL : old_image_data); done_replace_contents = true; break; + case QueuedOperation::SET_OFFSET: + old_op_rect = gfx::Rect(plugin_offset_.x(), plugin_offset_.y(), + image_data_->width(), image_data_->height()); + plugin_offset_ = operation.offset; + // The offset is applied below for |op_rect|. + op_rect = gfx::Rect(image_data_->width(), image_data_->height()); + break; } + op_rect.Offset(plugin_offset_.x(), plugin_offset_.y()); + // For correctness with accelerated compositing, we must issue an invalidate // on the full op_rect even if it is partially or completely off-screen. // However, if we issue an invalidate for a clipped-out region, WebKit will - // do nothing and we won't get any ViewWillInitiatePaint/ViewFlushedPaint - // calls, leaving our callback stranded. So we still need to check whether - // the repainted area is visible to determine how to deal with the callback. - if (bound_instance_ && !op_rect.IsEmpty()) { + // do nothing and we won't get any ViewFlushedPaint calls, leaving our + // callback stranded. So we still need to check whether the repainted area + // is visible to determine how to deal with the callback. + if (bound_instance_ && (!op_rect.IsEmpty() || !old_op_rect.IsEmpty())) { gfx::Point scroll_delta(operation.scroll_dx, operation.scroll_dy); + if (!ConvertToLogicalPixels(scale_, &old_op_rect, NULL)) { + NOTREACHED(); + } if (!ConvertToLogicalPixels(scale_, &op_rect, operation.type == QueuedOperation::SCROLL ? @@ -639,23 +715,29 @@ int32_t PepperGraphics2DHost::Flush(PP_Resource* old_image_data) { // Set |no_update_visible| to false if the change overlaps the visible // area. - gfx::Rect visible_changed_rect = gfx::IntersectRects(clip, op_rect); - if (!visible_changed_rect.IsEmpty()) + if (!gfx::IntersectRects(clip, op_rect).IsEmpty() || + !gfx::IntersectRects(clip, old_op_rect).IsEmpty()) { no_update_visible = false; + } // Notify the plugin of the entire change (op_rect), even if it is // partially or completely off-screen. if (operation.type == QueuedOperation::SCROLL) { bound_instance_->ScrollRect(scroll_delta.x(), scroll_delta.y(), op_rect); + DCHECK(old_op_rect.IsEmpty()); } else { - bound_instance_->InvalidateRect(op_rect); + if (!op_rect.IsEmpty()) + bound_instance_->InvalidateRect(op_rect); + if (!old_op_rect.IsEmpty()) + bound_instance_->InvalidateRect(old_op_rect); } texture_mailbox_modified_ = true; } } queued_operations_.clear(); + flushed_plugin_size_ = flushed_plugin_size; if (!bound_instance_) { // As promised in the API, we always schedule callback when unbound. ScheduleOffscreenFlushAck(); @@ -762,7 +844,7 @@ void PepperGraphics2DHost::ScheduleOffscreenFlushAck() { base::MessageLoop::current()->PostDelayedTask( FROM_HERE, base::Bind(&PepperGraphics2DHost::SendOffscreenFlushAck, - weak_ptr_factory_.GetWeakPtr()), + AsWeakPtr()), base::TimeDelta::FromMilliseconds(kOffscreenCallbackDelayMs)); } diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host.h b/chromium/content/renderer/pepper/pepper_graphics_2d_host.h index 7179398d11b..cda286a2df8 100644 --- a/chromium/content/renderer/pepper/pepper_graphics_2d_host.h +++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host.h @@ -11,10 +11,13 @@ #include "base/compiler_specific.h" #include "base/memory/weak_ptr.h" #include "content/common/content_export.h" +#include "ppapi/c/dev/ppb_graphics_2d_dev.h" #include "ppapi/c/ppb_graphics_2d.h" #include "ppapi/host/host_message_context.h" #include "ppapi/host/resource_host.h" #include "third_party/WebKit/public/platform/WebCanvas.h" +#include "ui/gfx/point.h" +#include "ui/gfx/size.h" namespace cc { class SingleReleaseCallback; @@ -22,10 +25,13 @@ class TextureMailbox; } namespace gfx { -class Point; class Rect; } +namespace ppapi { +struct ViewData; +} + namespace content { class PepperPluginInstanceImpl; @@ -36,11 +42,13 @@ class CONTENT_EXPORT PepperGraphics2DHost : public ppapi::host::ResourceHost, public base::SupportsWeakPtr<PepperGraphics2DHost> { public: - static PepperGraphics2DHost* Create(RendererPpapiHost* host, - PP_Instance instance, - PP_Resource resource, - const PP_Size& size, - PP_Bool is_always_opaque); + static PepperGraphics2DHost* Create( + RendererPpapiHost* host, + PP_Instance instance, + PP_Resource resource, + const PP_Size& size, + PP_Bool is_always_opaque, + scoped_refptr<PPB_ImageData_Impl> backing_store); virtual ~PepperGraphics2DHost(); @@ -58,7 +66,7 @@ class CONTENT_EXPORT PepperGraphics2DHost // is already bound to a different instance, and nothing will happen. bool BindToInstance(PepperPluginInstanceImpl* new_instance); // Paints the current backing store to the web page. - void Paint(WebKit::WebCanvas* canvas, + void Paint(blink::WebCanvas* canvas, const gfx::Rect& plugin_rect, const gfx::Rect& paint_rect); @@ -69,21 +77,32 @@ class CONTENT_EXPORT PepperGraphics2DHost // Notifications about the view's progress painting. See PluginInstance. // These messages are used to send Flush callbacks to the plugin. - void ViewWillInitiatePaint(); void ViewInitiatedPaint(); void ViewFlushedPaint(); + void DidChangeView(const ppapi::ViewData& view_data); + void SetScale(float scale); float GetScale() const; bool IsAlwaysOpaque() const; PPB_ImageData_Impl* ImageData(); + gfx::Size Size() const; + + // The amount to resize the backing store by when painting to the canvas. + // This is used to stretch the backing store when resizing the plugin element. + gfx::PointF GetResizeScale() const; + // The offset of the backing store into the plugin element. + gfx::Point plugin_offset() const { return plugin_offset_; } private: PepperGraphics2DHost(RendererPpapiHost* host, PP_Instance instance, PP_Resource resource); - bool Init(int width, int height, bool is_always_opaque); + bool Init(int width, + int height, + bool is_always_opaque, + scoped_refptr<PPB_ImageData_Impl> backing_store); int32_t OnHostMsgPaintImageData(ppapi::host::HostMessageContext* context, const ppapi::HostResource& image_data, @@ -96,16 +115,22 @@ class CONTENT_EXPORT PepperGraphics2DHost const PP_Point& amount); int32_t OnHostMsgReplaceContents(ppapi::host::HostMessageContext* context, const ppapi::HostResource& image_data); - int32_t OnHostMsgFlush(ppapi::host::HostMessageContext* context); + int32_t OnHostMsgFlush(ppapi::host::HostMessageContext* context, + const ppapi::ViewData& view_data); int32_t OnHostMsgSetScale(ppapi::host::HostMessageContext* context, float scale); + int32_t OnHostMsgSetOffset(ppapi::host::HostMessageContext* context, + const PP_Point& offset); + int32_t OnHostMsgSetResizeMode(ppapi::host::HostMessageContext* context, + PP_Graphics2D_Dev_ResizeMode resize_mode); int32_t OnHostMsgReadImageData(ppapi::host::HostMessageContext* context, PP_Resource image, const PP_Point& top_left); // If |old_image_data| is not NULL, a previous used ImageData object will be // reused. This is used by ReplaceContents. - int32_t Flush(PP_Resource* old_image_data); + int32_t Flush(PP_Resource* old_image_data, + const gfx::Size& flushed_plugin_size); // Called internally to execute the different queued commands. The // parameters to these functions will have already been validated. The last @@ -143,7 +168,6 @@ class CONTENT_EXPORT PepperGraphics2DHost gfx::Rect* op_rect, gfx::Point* delta); - RendererPpapiHost* renderer_ppapi_host_; scoped_refptr<PPB_ImageData_Impl> image_data_; @@ -173,13 +197,27 @@ class CONTENT_EXPORT PepperGraphics2DHost // DIP float scale_; - base::WeakPtrFactory<PepperGraphics2DHost> weak_ptr_factory_; - ppapi::host::ReplyMessageContext flush_reply_context_; bool is_running_in_process_; bool texture_mailbox_modified_; + bool is_using_texture_layer_; + + // The offset into the plugin area at which to draw the contents of the + // graphics context. + gfx::Point plugin_offset_; + + // The size of the plugin element from the plugin's perspective at the last + // time Flush() was called. Because the plugin runs in a separate process and + // the size of the plugin element in the renderer is updated asynchronously, + // it may believe that the plugin element is a different size to what it + // actually is. + gfx::Size flushed_plugin_size_; + // The current size of the plugin element. + gfx::Size current_plugin_size_; + + PP_Graphics2D_Dev_ResizeMode resize_mode_; friend class PepperGraphics2DHostTest; DISALLOW_COPY_AND_ASSIGN(PepperGraphics2DHost); diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host_unittest.cc b/chromium/content/renderer/pepper/pepper_graphics_2d_host_unittest.cc index 78a8fe01ae1..b17dfa71886 100644 --- a/chromium/content/renderer/pepper/pepper_graphics_2d_host_unittest.cc +++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host_unittest.cc @@ -5,10 +5,21 @@ #include "content/renderer/pepper/pepper_graphics_2d_host.h" #include "base/basictypes.h" +#include "base/message_loop/message_loop.h" +#include "content/renderer/pepper/gfx_conversion.h" +#include "content/renderer/pepper/mock_renderer_ppapi_host.h" +#include "content/renderer/pepper/ppb_image_data_impl.h" +#include "ppapi/shared_impl/ppb_view_shared.h" +#include "ppapi/shared_impl/proxy_lock.h" +#include "ppapi/shared_impl/test_globals.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/public/platform/WebCanvas.h" +#include "third_party/skia/include/core/SkCanvas.h" #include "ui/gfx/point.h" #include "ui/gfx/rect.h" +using blink::WebCanvas; + namespace content { class PepperGraphics2DHostTest : public testing::Test { @@ -18,6 +29,89 @@ class PepperGraphics2DHostTest : public testing::Test { gfx::Point* delta) { return PepperGraphics2DHost::ConvertToLogicalPixels(scale, op_rect, delta); } + + PepperGraphics2DHostTest() + : message_loop_(base::MessageLoop::TYPE_DEFAULT), + renderer_ppapi_host_(NULL, 12345) {} + + virtual ~PepperGraphics2DHostTest() { + ppapi::ProxyAutoLock proxy_lock; + host_.reset(); + } + + void Init(PP_Instance instance, + const PP_Size& backing_store_size, + const PP_Rect& plugin_rect) { + renderer_view_data_.rect = plugin_rect; + PluginViewUpdated(); + test_globals_.GetResourceTracker()->DidCreateInstance(instance); + scoped_refptr<PPB_ImageData_Impl> backing_store( + new PPB_ImageData_Impl(instance, PPB_ImageData_Impl::ForTest())); + host_.reset(PepperGraphics2DHost::Create( + &renderer_ppapi_host_, instance, 12345, backing_store_size, PP_FALSE, + backing_store)); + DCHECK(host_.get()); + } + + void PaintImageData(PPB_ImageData_Impl* image_data) { + ppapi::HostResource image_data_resource; + image_data_resource.SetHostResource(image_data->pp_instance(), + image_data->pp_resource()); + host_->OnHostMsgPaintImageData(NULL, image_data_resource, + PP_Point(), false, PP_Rect()); + } + + void SetOffset(const PP_Point& point) { + host_->OnHostMsgSetOffset(NULL, point); + } + + void Flush() { + ppapi::host::HostMessageContext context( + ppapi::proxy::ResourceMessageCallParams(host_->pp_resource(), 0)); + host_->OnHostMsgFlush(&context, plugin_view_data_); + host_->ViewFlushedPaint(); + host_->SendOffscreenFlushAck(); + } + + void PaintToWebCanvas(SkBitmap* bitmap) { + scoped_ptr<WebCanvas> canvas(new WebCanvas(*bitmap)); + gfx::Rect plugin_rect(PP_ToGfxRect(renderer_view_data_.rect)); + host_->Paint(canvas.get(), plugin_rect, + gfx::Rect(0, 0, plugin_rect.width(), plugin_rect.height())); + } + + void DidChangeView(const PP_Rect& plugin_rect) { + renderer_view_data_.rect = plugin_rect; + host_->DidChangeView(renderer_view_data_); + } + + void PluginViewUpdated() { + plugin_view_data_ = renderer_view_data_; + } + + void SetResizeMode(PP_Graphics2D_Dev_ResizeMode resize_mode) { + host_->OnHostMsgSetResizeMode(NULL, resize_mode); + } + + void ResetPageBitmap(SkBitmap* bitmap) { + PP_Rect plugin_rect = renderer_view_data_.rect; + int width = plugin_rect.point.x + plugin_rect.size.width; + int height = plugin_rect.point.y + plugin_rect.size.height; + if (bitmap->isNull() || bitmap->width() != width || + bitmap->height() != height) { + bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height); + bitmap->allocPixels(); + } + bitmap->eraseColor(0); + } + + private: + ppapi::ViewData renderer_view_data_; + ppapi::ViewData plugin_view_data_; + scoped_ptr<PepperGraphics2DHost> host_; + base::MessageLoop message_loop_; + MockRendererPpapiHost renderer_ppapi_host_; + ppapi::TestGlobals test_globals_; }; TEST_F(PepperGraphics2DHostTest, ConvertToLogicalPixels) { @@ -89,4 +183,212 @@ TEST_F(PepperGraphics2DHostTest, ConvertToLogicalPixels) { } } +TEST_F(PepperGraphics2DHostTest, SetOffset) { + ppapi::ProxyAutoLock proxy_lock; + + // Initialize the backing store. + PP_Instance instance = 12345; + PP_Size backing_store_size = { 300, 300 }; + PP_Rect plugin_rect = PP_MakeRectFromXYWH(0, 0, 500, 500); + Init(instance, backing_store_size, plugin_rect); + + // Paint the entire backing store red. + scoped_refptr<PPB_ImageData_Impl> image_data( + new PPB_ImageData_Impl(instance, PPB_ImageData_Impl::ForTest())); + image_data->Init(PPB_ImageData_Impl::GetNativeImageDataFormat(), + backing_store_size.width, + backing_store_size.height, + true); + { + ImageDataAutoMapper auto_mapper(image_data.get()); + image_data->GetMappedBitmap()->eraseColor( + SkColorSetARGBMacro(255, 255, 0, 0)); + } + PaintImageData(image_data.get()); + Flush(); + + // Set up the actual and expected bitmaps/canvas. + SkBitmap actual_bitmap; + ResetPageBitmap(&actual_bitmap); + SkBitmap expected_bitmap; + ResetPageBitmap(&expected_bitmap); + + // Paint the backing store to the canvas. + PaintToWebCanvas(&actual_bitmap); + expected_bitmap.eraseArea( + SkIRect::MakeWH(backing_store_size.width, backing_store_size.height), + SkColorSetARGBMacro(255, 255, 0, 0)); + EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0), + actual_bitmap.getAddr(0, 0), + expected_bitmap.getSize()), 0); + + // Set the offset. + PP_Point offset = { 20, 20 }; + SetOffset(offset); + ResetPageBitmap(&actual_bitmap); + PaintToWebCanvas(&actual_bitmap); + // No flush has occurred so the result should be the same. + EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0), + actual_bitmap.getAddr(0, 0), + expected_bitmap.getSize()), 0); + + // Flush the offset and the location of the rectangle should have shifted. + Flush(); + ResetPageBitmap(&actual_bitmap); + PaintToWebCanvas(&actual_bitmap); + ResetPageBitmap(&expected_bitmap); + expected_bitmap.eraseArea( + SkIRect::MakeXYWH(offset.x, offset.y, + backing_store_size.width, backing_store_size.height), + SkColorSetARGBMacro(255, 255, 0, 0)); + EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0), + actual_bitmap.getAddr(0, 0), + expected_bitmap.getSize()), 0); +} + +TEST_F(PepperGraphics2DHostTest, ResizeModeDefault) { + ppapi::ProxyAutoLock proxy_lock; + + // Initialize the backing store. + PP_Instance instance = 12345; + PP_Size backing_store_size = { 300, 300 }; + PP_Rect plugin_rect = PP_MakeRectFromXYWH(0, 0, 300, 300); + Init(instance, backing_store_size, plugin_rect); + + // Paint the entire backing store red. + scoped_refptr<PPB_ImageData_Impl> image_data( + new PPB_ImageData_Impl(instance, PPB_ImageData_Impl::ForTest())); + image_data->Init(PPB_ImageData_Impl::GetNativeImageDataFormat(), + backing_store_size.width, + backing_store_size.height, + true); + { + ImageDataAutoMapper auto_mapper(image_data.get()); + image_data->GetMappedBitmap()->eraseColor( + SkColorSetARGBMacro(255, 255, 0, 0)); + } + PaintImageData(image_data.get()); + Flush(); + + // Set up the actual and expected bitmaps/canvas. + SkBitmap actual_bitmap; + ResetPageBitmap(&actual_bitmap); + SkBitmap expected_bitmap; + ResetPageBitmap(&expected_bitmap); + + // Paint the backing store to the canvas. + PaintToWebCanvas(&actual_bitmap); + expected_bitmap.eraseArea( + SkIRect::MakeWH(backing_store_size.width, backing_store_size.height), + SkColorSetARGBMacro(255, 255, 0, 0)); + EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0), + actual_bitmap.getAddr(0, 0), + expected_bitmap.getSize()), 0); + + // Resize the plugin. + DidChangeView(PP_MakeRectFromXYWH(0, 0, 500, 500)); + // Paint the backing store again, it shouldn't have changed. + ResetPageBitmap(&actual_bitmap); + PaintToWebCanvas(&actual_bitmap); + ResetPageBitmap(&expected_bitmap); + expected_bitmap.eraseArea( + SkIRect::MakeWH(backing_store_size.width, backing_store_size.height), + SkColorSetARGBMacro(255, 255, 0, 0)); + EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0), + actual_bitmap.getAddr(0, 0), + expected_bitmap.getSize()), 0); + + // Let the plugin know about the updated view and reflush the original image. + PluginViewUpdated(); + PaintImageData(image_data.get()); + Flush(); + // Paint the backing store again, it shouldn't have changed. + ResetPageBitmap(&actual_bitmap); + PaintToWebCanvas(&actual_bitmap); + EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0), + actual_bitmap.getAddr(0, 0), + expected_bitmap.getSize()), 0); +} + +TEST_F(PepperGraphics2DHostTest, ResizeModeStretch) { + ppapi::ProxyAutoLock proxy_lock; + + // Initialize the backing store. + PP_Instance instance = 12345; + PP_Size backing_store_size = { 300, 300 }; + PP_Rect plugin_rect = PP_MakeRectFromXYWH(0, 0, 300, 300); + Init(instance, backing_store_size, plugin_rect); + SetResizeMode(PP_GRAPHICS2D_DEV_RESIZEMODE_STRETCH); + + // Paint the entire backing store red. + scoped_refptr<PPB_ImageData_Impl> image_data( + new PPB_ImageData_Impl(instance, PPB_ImageData_Impl::ForTest())); + image_data->Init(PPB_ImageData_Impl::GetNativeImageDataFormat(), + backing_store_size.width, + backing_store_size.height, + true); + { + ImageDataAutoMapper auto_mapper(image_data.get()); + image_data->GetMappedBitmap()->eraseColor( + SkColorSetARGBMacro(255, 255, 0, 0)); + } + PaintImageData(image_data.get()); + Flush(); + + // Set up the actual and expected bitmaps/canvas. + SkBitmap actual_bitmap; + ResetPageBitmap(&actual_bitmap); + SkBitmap expected_bitmap; + ResetPageBitmap(&expected_bitmap); + + // Paint the backing store to the canvas. + PaintToWebCanvas(&actual_bitmap); + expected_bitmap.eraseArea( + SkIRect::MakeWH(backing_store_size.width, backing_store_size.height), + SkColorSetARGBMacro(255, 255, 0, 0)); + EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0), + actual_bitmap.getAddr(0, 0), + expected_bitmap.getSize()), 0); + + // Resize the plugin. + plugin_rect = PP_MakeRectFromXYWH(0, 0, 500, 500); + DidChangeView(plugin_rect); + ResetPageBitmap(&actual_bitmap); + ResetPageBitmap(&expected_bitmap); + + // Paint the backing store again, it should be stretched even though no new + // image has been flushed. + PaintToWebCanvas(&actual_bitmap); + expected_bitmap.eraseColor(SkColorSetARGBMacro(255, 255, 0, 0)); + EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0), + actual_bitmap.getAddr(0, 0), + expected_bitmap.getSize()), 0); + + // Re-flush the original image data and paint it, it should be stretched as + // well. + PaintImageData(image_data.get()); + Flush(); + ResetPageBitmap(&actual_bitmap); + PaintToWebCanvas(&actual_bitmap); + EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0), + actual_bitmap.getAddr(0, 0), + expected_bitmap.getSize()), 0); + + // Let the plugin know about the updated view. + PluginViewUpdated(); + + // Now flush the image data again, it should be at the original size. + PaintImageData(image_data.get()); + Flush(); + ResetPageBitmap(&actual_bitmap); + PaintToWebCanvas(&actual_bitmap); + ResetPageBitmap(&expected_bitmap); + expected_bitmap.eraseArea( + SkIRect::MakeWH(backing_store_size.width, backing_store_size.height), + SkColorSetARGBMacro(255, 255, 0, 0)); + EXPECT_EQ(memcmp(expected_bitmap.getAddr(0, 0), + actual_bitmap.getAddr(0, 0), + expected_bitmap.getSize()), 0); +} + } // namespace content diff --git a/chromium/content/renderer/pepper/pepper_hung_plugin_filter.cc b/chromium/content/renderer/pepper/pepper_hung_plugin_filter.cc index 10282125e0c..ba4af0e22bb 100644 --- a/chromium/content/renderer/pepper/pepper_hung_plugin_filter.cc +++ b/chromium/content/renderer/pepper/pepper_hung_plugin_filter.cc @@ -6,7 +6,7 @@ #include "base/bind.h" #include "content/child/child_process.h" -#include "content/common/view_messages.h" +#include "content/common/frame_messages.h" #include "content/renderer/render_thread_impl.h" namespace content { @@ -26,10 +26,10 @@ const int kBlockedHardThresholdSec = kHungThresholdSec * 1.5; PepperHungPluginFilter::PepperHungPluginFilter( const base::FilePath& plugin_path, - int view_routing_id, + int frame_routing_id, int plugin_child_id) : plugin_path_(plugin_path), - view_routing_id_(view_routing_id), + frame_routing_id_(frame_routing_id), plugin_child_id_(plugin_child_id), filter_(RenderThread::Get()->GetSyncMessageFilter()), io_loop_(ChildProcess::current()->io_message_loop_proxy()), @@ -151,8 +151,8 @@ void PepperHungPluginFilter::OnHangTimer() { } void PepperHungPluginFilter::SendHungMessage(bool is_hung) { - filter_->Send(new ViewHostMsg_PepperPluginHung( - view_routing_id_, plugin_child_id_, plugin_path_, is_hung)); + filter_->Send(new FrameHostMsg_PepperPluginHung( + frame_routing_id_, plugin_child_id_, plugin_path_, is_hung)); } } // namespace content diff --git a/chromium/content/renderer/pepper/pepper_hung_plugin_filter.h b/chromium/content/renderer/pepper/pepper_hung_plugin_filter.h index 9f8bad3e51f..ee83674800f 100644 --- a/chromium/content/renderer/pepper/pepper_hung_plugin_filter.h +++ b/chromium/content/renderer/pepper/pepper_hung_plugin_filter.h @@ -30,12 +30,12 @@ namespace content { class PepperHungPluginFilter : public ppapi::proxy::HostDispatcher::SyncMessageStatusReceiver { public: - // The |view_routing_id| is the ID of the render_view so that this class can - // send messages to the browser via that view's route. The |plugin_child_id| + // The |frame_routing_id| is the ID of the render_frame so that this class can + // send messages to the browser via that frame's route. The |plugin_child_id| // is the ID in the browser process of the pepper plugin process host. We use // this to identify the proper plugin process to terminate. PepperHungPluginFilter(const base::FilePath& plugin_path, - int view_routing_id, + int frame_routing_id, int plugin_child_id); // SyncMessageStatusReceiver implementation. @@ -75,7 +75,7 @@ class PepperHungPluginFilter base::Lock lock_; base::FilePath plugin_path_; - int view_routing_id_; + int frame_routing_id_; int plugin_child_id_; // Used to post messages to the renderer <-> browser message channel from diff --git a/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc b/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc index cb10ff269c8..23ed785ac5f 100644 --- a/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc +++ b/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc @@ -16,7 +16,6 @@ #include "ipc/ipc_message.h" #include "ipc/ipc_message_macros.h" #include "ppapi/host/ppapi_host.h" -#include "ppapi/proxy/ext_crx_file_system_private_resource.h" #include "ppapi/proxy/file_chooser_resource.h" #include "ppapi/proxy/file_io_resource.h" #include "ppapi/proxy/file_ref_resource.h" diff --git a/chromium/content/renderer/pepper/pepper_in_process_router.cc b/chromium/content/renderer/pepper/pepper_in_process_router.cc index 1446426dd77..45755e1d4d8 100644 --- a/chromium/content/renderer/pepper/pepper_in_process_router.cc +++ b/chromium/content/renderer/pepper/pepper_in_process_router.cc @@ -7,8 +7,8 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" #include "content/public/renderer/render_thread.h" -#include "content/public/renderer/render_view.h" #include "content/renderer/pepper/renderer_ppapi_host_impl.h" +#include "content/renderer/render_frame_impl.h" #include "ipc/ipc_message.h" #include "ipc/ipc_sender.h" #include "ppapi/proxy/ppapi_messages.h" @@ -65,9 +65,9 @@ IPC::Sender* PepperInProcessRouter::GetRendererToPluginSender() { ppapi::proxy::Connection PepperInProcessRouter::GetPluginConnection( PP_Instance instance) { int routing_id = 0; - RenderView* view = host_impl_->GetRenderViewForInstance(instance); - if (view) - routing_id = view->GetRoutingID(); + RenderFrame* frame = host_impl_->GetRenderFrameForInstance(instance); + if (frame) + routing_id = frame->GetRoutingID(); return ppapi::proxy::Connection(browser_channel_.get(), plugin_to_host_router_.get(), routing_id); diff --git a/chromium/content/renderer/pepper/pepper_media_device_manager.cc b/chromium/content/renderer/pepper/pepper_media_device_manager.cc index 35318163012..9704980e3a1 100644 --- a/chromium/content/renderer/pepper/pepper_media_device_manager.cc +++ b/chromium/content/renderer/pepper/pepper_media_device_manager.cc @@ -45,6 +45,7 @@ PepperMediaDeviceManager::~PepperMediaDeviceManager() { int PepperMediaDeviceManager::EnumerateDevices( PP_DeviceType_Dev type, + const GURL& document_url, const EnumerateDevicesCallback& callback) { enumerate_callbacks_[next_id_] = callback; int request_id = next_id_++; @@ -53,14 +54,15 @@ int PepperMediaDeviceManager::EnumerateDevices( GetRenderViewImpl()->media_stream_dispatcher()->EnumerateDevices( request_id, AsWeakPtr(), PepperMediaDeviceManager::FromPepperDeviceType(type), - GURL()); + document_url.GetOrigin()); #else base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind( - &PepperMediaDeviceManager::OnDevicesEnumerationFailed, + &PepperMediaDeviceManager::OnDevicesEnumerated, AsWeakPtr(), - request_id)); + request_id, + StreamDeviceInfoArray())); #endif return request_id; @@ -152,18 +154,30 @@ void PepperMediaDeviceManager::OnStreamGenerated( void PepperMediaDeviceManager::OnStreamGenerationFailed(int request_id) { } -void PepperMediaDeviceManager::OnStopGeneratedStream(const std::string& label) { +void PepperMediaDeviceManager::OnDeviceStopped( + const std::string& label, + const StreamDeviceInfo& device_info) { } void PepperMediaDeviceManager::OnDevicesEnumerated( int request_id, const StreamDeviceInfoArray& device_array) { - NotifyDevicesEnumerated(request_id, true, device_array); -} + EnumerateCallbackMap::iterator iter = enumerate_callbacks_.find(request_id); + if (iter == enumerate_callbacks_.end()) { + // This might be enumerated result sent before StopEnumerateDevices is + // called since EnumerateDevices is persistent request. + return; + } + + EnumerateDevicesCallback callback = iter->second; -void PepperMediaDeviceManager::OnDevicesEnumerationFailed( - int request_id) { - NotifyDevicesEnumerated(request_id, false, StreamDeviceInfoArray()); + std::vector<ppapi::DeviceRefData> devices; + devices.reserve(device_array.size()); + for (StreamDeviceInfoArray::const_iterator info = + device_array.begin(); info != device_array.end(); ++info) { + devices.push_back(FromStreamDeviceInfo(*info)); + } + callback.Run(request_id, devices); } void PepperMediaDeviceManager::OnDeviceOpened( @@ -209,30 +223,6 @@ PP_DeviceType_Dev PepperMediaDeviceManager::FromMediaStreamType( } } -void PepperMediaDeviceManager::NotifyDevicesEnumerated( - int request_id, - bool succeeded, - const StreamDeviceInfoArray& device_array) { - EnumerateCallbackMap::iterator iter = enumerate_callbacks_.find(request_id); - if (iter == enumerate_callbacks_.end()) { - // This might be enumerated result sent before StopEnumerateDevices is - // called since EnumerateDevices is persistent request. - return; - } - - EnumerateDevicesCallback callback = iter->second; - - std::vector<ppapi::DeviceRefData> devices; - if (succeeded) { - devices.reserve(device_array.size()); - for (StreamDeviceInfoArray::const_iterator info = - device_array.begin(); info != device_array.end(); ++info) { - devices.push_back(FromStreamDeviceInfo(*info)); - } - } - callback.Run(request_id, succeeded, devices); -} - void PepperMediaDeviceManager::NotifyDeviceOpened( int request_id, bool succeeded, diff --git a/chromium/content/renderer/pepper/pepper_media_device_manager.h b/chromium/content/renderer/pepper/pepper_media_device_manager.h index 67d8976e0d4..ff67101d4a9 100644 --- a/chromium/content/renderer/pepper/pepper_media_device_manager.h +++ b/chromium/content/renderer/pepper/pepper_media_device_manager.h @@ -29,6 +29,7 @@ class PepperMediaDeviceManager // PepperDeviceEnumerationHostHelper::Delegate implementation: virtual int EnumerateDevices( PP_DeviceType_Dev type, + const GURL& document_url, const EnumerateDevicesCallback& callback) OVERRIDE; virtual void StopEnumerateDevices(int request_id) OVERRIDE; @@ -60,11 +61,11 @@ class PepperMediaDeviceManager const StreamDeviceInfoArray& audio_device_array, const StreamDeviceInfoArray& video_device_array) OVERRIDE; virtual void OnStreamGenerationFailed(int request_id) OVERRIDE; - virtual void OnStopGeneratedStream(const std::string& label) OVERRIDE; + virtual void OnDeviceStopped(const std::string& label, + const StreamDeviceInfo& device_info) OVERRIDE; virtual void OnDevicesEnumerated( int request_id, const StreamDeviceInfoArray& device_array) OVERRIDE; - virtual void OnDevicesEnumerationFailed(int request_id) OVERRIDE; virtual void OnDeviceOpened( int request_id, const std::string& label, @@ -78,11 +79,6 @@ class PepperMediaDeviceManager private: PepperMediaDeviceManager(RenderView* render_view); - void NotifyDevicesEnumerated( - int request_id, - bool succeeded, - const StreamDeviceInfoArray& device_array); - void NotifyDeviceOpened(int request_id, bool succeeded, const std::string& label); diff --git a/chromium/content/renderer/pepper/pepper_platform_context_3d.cc b/chromium/content/renderer/pepper/pepper_platform_context_3d.cc index e080e16bd2d..b9fd07b67d5 100644 --- a/chromium/content/renderer/pepper/pepper_platform_context_3d.cc +++ b/chromium/content/renderer/pepper/pepper_platform_context_3d.cc @@ -11,13 +11,10 @@ #include "content/renderer/render_thread_impl.h" #include "gpu/command_buffer/client/gles2_cmd_helper.h" #include "gpu/command_buffer/client/gles2_implementation.h" -#include "gpu/ipc/command_buffer_proxy.h" #include "ppapi/c/pp_graphics_3d.h" #include "ui/gl/gpu_preference.h" #include "url/gurl.h" -#ifdef ENABLE_GPU - namespace content { PlatformContext3D::PlatformContext3D() @@ -134,6 +131,10 @@ gpu::CommandBuffer* PlatformContext3D::GetCommandBuffer() { return command_buffer_; } +gpu::GpuControl* PlatformContext3D::GetGpuControl() { + return command_buffer_; +} + int PlatformContext3D::GetCommandBufferRouteId() { DCHECK(command_buffer_); return command_buffer_->GetRouteID(); @@ -148,8 +149,8 @@ void PlatformContext3D::SetOnConsoleMessageCallback( console_message_callback_ = task; } -bool PlatformContext3D::Echo(const base::Closure& task) { - return command_buffer_->Echo(task); +void PlatformContext3D::Echo(const base::Closure& task) { + command_buffer_->Echo(task); } void PlatformContext3D::OnContextLost() { @@ -167,5 +168,3 @@ void PlatformContext3D::OnConsoleMessage(const std::string& msg, int id) { } } // namespace content - -#endif // ENABLE_GPU diff --git a/chromium/content/renderer/pepper/pepper_platform_context_3d.h b/chromium/content/renderer/pepper/pepper_platform_context_3d.h index 842871a45fd..2520bbd65da 100644 --- a/chromium/content/renderer/pepper/pepper_platform_context_3d.h +++ b/chromium/content/renderer/pepper/pepper_platform_context_3d.h @@ -12,8 +12,6 @@ #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" #include "gpu/command_buffer/common/mailbox.h" -#ifdef ENABLE_GPU - class CommandBufferProxy; namespace gpu { class CommandBuffer; @@ -43,6 +41,9 @@ class PlatformContext3D { // destroyed. gpu::CommandBuffer* GetCommandBuffer(); + // Returns the GpuControl class that services out-of-band messages. + gpu::GpuControl* GetGpuControl(); + // If the command buffer is routed in the GPU channel, return the route id. // Otherwise return 0. int GetCommandBufferRouteId(); @@ -58,7 +59,7 @@ class PlatformContext3D { void SetOnConsoleMessageCallback(const ConsoleMessageCallback& callback); // Run the callback once the channel has been flushed. - bool Echo(const base::Closure& task); + void Echo(const base::Closure& task); private: bool InitRaw(); @@ -76,6 +77,4 @@ class PlatformContext3D { } // namespace content -#endif // ENABLE_GPU - #endif // CONTENT_RENDERER_PEPPER_PEPPER_PLATFORM_CONTEXT_3D_H_ diff --git a/chromium/content/renderer/pepper/pepper_platform_video_capture.cc b/chromium/content/renderer/pepper/pepper_platform_video_capture.cc index 86ce45d8453..dc58ad44e68 100644 --- a/chromium/content/renderer/pepper/pepper_platform_video_capture.cc +++ b/chromium/content/renderer/pepper/pepper_platform_video_capture.cc @@ -46,7 +46,7 @@ PepperPlatformVideoCapture::PepperPlatformVideoCapture( void PepperPlatformVideoCapture::StartCapture( media::VideoCapture::EventHandler* handler, - const media::VideoCaptureCapability& capability) { + const media::VideoCaptureParams& params) { DCHECK(handler == handler_); if (unbalanced_start_) @@ -55,7 +55,7 @@ void PepperPlatformVideoCapture::StartCapture( if (video_capture_) { unbalanced_start_ = true; AddRef(); // Will be balanced in OnRemoved(). - video_capture_->StartCapture(handler_proxy_.get(), capability); + video_capture_->StartCapture(handler_proxy_.get(), params); } } @@ -75,14 +75,6 @@ bool PepperPlatformVideoCapture::CaptureStarted() { return handler_proxy_->state().started; } -int PepperPlatformVideoCapture::CaptureWidth() { - return handler_proxy_->state().width; -} - -int PepperPlatformVideoCapture::CaptureHeight() { - return handler_proxy_->state().height; -} - int PepperPlatformVideoCapture::CaptureFrameRate() { return handler_proxy_->state().frame_rate; } @@ -146,13 +138,6 @@ void PepperPlatformVideoCapture::OnFrameReady( handler_->OnFrameReady(capture, frame); } -void PepperPlatformVideoCapture::OnDeviceInfoReceived( - VideoCapture* capture, - const media::VideoCaptureParams& device_info) { - if (handler_) - handler_->OnDeviceInfoReceived(capture, device_info); -} - PepperPlatformVideoCapture::~PepperPlatformVideoCapture() { DCHECK(!video_capture_); DCHECK(label_.empty()); diff --git a/chromium/content/renderer/pepper/pepper_platform_video_capture.h b/chromium/content/renderer/pepper/pepper_platform_video_capture.h index 5ecde2e73de..609eaa34e11 100644 --- a/chromium/content/renderer/pepper/pepper_platform_video_capture.h +++ b/chromium/content/renderer/pepper/pepper_platform_video_capture.h @@ -42,11 +42,9 @@ class PepperPlatformVideoCapture // media::VideoCapture implementation. virtual void StartCapture( media::VideoCapture::EventHandler* handler, - const media::VideoCaptureCapability& capability) OVERRIDE; + const media::VideoCaptureParams& params) OVERRIDE; virtual void StopCapture(media::VideoCapture::EventHandler* handler) OVERRIDE; virtual bool CaptureStarted() OVERRIDE; - virtual int CaptureWidth() OVERRIDE; - virtual int CaptureHeight() OVERRIDE; virtual int CaptureFrameRate() OVERRIDE; // media::VideoCapture::EventHandler implementation @@ -58,9 +56,6 @@ class PepperPlatformVideoCapture virtual void OnFrameReady( VideoCapture* capture, const scoped_refptr<media::VideoFrame>& frame) OVERRIDE; - virtual void OnDeviceInfoReceived( - VideoCapture* capture, - const media::VideoCaptureParams& device_info) OVERRIDE; protected: friend class base::RefCounted<PepperPlatformVideoCapture>; diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc index f8b2cfface3..c6d6582132c 100644 --- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc +++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc @@ -45,8 +45,10 @@ #include "content/renderer/pepper/renderer_ppapi_host_impl.h" #include "content/renderer/pepper/url_request_info_util.h" #include "content/renderer/pepper/url_response_info_util.h" +#include "content/renderer/render_frame_impl.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_view_impl.h" +#include "content/renderer/render_widget.h" #include "content/renderer/render_widget_fullscreen_pepper.h" #include "content/renderer/sad_plugin.h" #include "media/base/audio_hardware_config.h" @@ -87,6 +89,7 @@ #include "printing/units.h" #include "skia/ext/platform_canvas.h" #include "skia/ext/platform_device.h" +#include "third_party/WebKit/public/platform/WebCursorInfo.h" #include "third_party/WebKit/public/platform/WebGamepads.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURL.h" @@ -94,7 +97,6 @@ #include "third_party/WebKit/public/platform/WebURLRequest.h" #include "third_party/WebKit/public/web/WebBindings.h" #include "third_party/WebKit/public/web/WebCompositionUnderline.h" -#include "third_party/WebKit/public/web/WebCursorInfo.h" #include "third_party/WebKit/public/web/WebDataSource.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebElement.h" @@ -117,6 +119,10 @@ #include "v8/include/v8.h" #include "webkit/renderer/compositor_bindings/web_layer_impl.h" +#if defined(OS_CHROMEOS) +#include "ui/events/keycodes/keyboard_codes_posix.h" +#endif + #if defined(OS_MACOSX) #include "printing/metafile_impl.h" #endif // defined(OS_MACOSX) @@ -148,27 +154,27 @@ using ppapi::thunk::PPB_ImageData_API; using ppapi::Var; using ppapi::ArrayBufferVar; using ppapi::ViewData; -using WebKit::WebBindings; -using WebKit::WebCanvas; -using WebKit::WebCursorInfo; -using WebKit::WebDocument; -using WebKit::WebElement; -using WebKit::WebFrame; -using WebKit::WebInputEvent; -using WebKit::WebPlugin; -using WebKit::WebPluginContainer; -using WebKit::WebPrintParams; -using WebKit::WebPrintScalingOption; -using WebKit::WebScopedUserGesture; -using WebKit::WebString; -using WebKit::WebURLError; -using WebKit::WebURLLoader; -using WebKit::WebURLLoaderClient; -using WebKit::WebURLRequest; -using WebKit::WebURLResponse; -using WebKit::WebUserGestureIndicator; -using WebKit::WebUserGestureToken; -using WebKit::WebView; +using blink::WebBindings; +using blink::WebCanvas; +using blink::WebCursorInfo; +using blink::WebDocument; +using blink::WebElement; +using blink::WebFrame; +using blink::WebInputEvent; +using blink::WebPlugin; +using blink::WebPluginContainer; +using blink::WebPrintParams; +using blink::WebPrintScalingOption; +using blink::WebScopedUserGesture; +using blink::WebString; +using blink::WebURLError; +using blink::WebURLLoader; +using blink::WebURLLoaderClient; +using blink::WebURLRequest; +using blink::WebURLResponse; +using blink::WebUserGestureIndicator; +using blink::WebUserGestureToken; +using blink::WebView; namespace content { @@ -298,20 +304,20 @@ COMPILE_ASSERT_MATCHING_ENUM(TypeGrabbing, PP_MOUSECURSOR_TYPE_GRABBING); // Do not assert WebCursorInfo::TypeCustom == PP_CURSORTYPE_CUSTOM; // PP_CURSORTYPE_CUSTOM is pinned to allow new cursor types. -COMPILE_ASSERT_PRINT_SCALING_MATCHING_ENUM(WebKit::WebPrintScalingOptionNone, +COMPILE_ASSERT_PRINT_SCALING_MATCHING_ENUM(blink::WebPrintScalingOptionNone, PP_PRINTSCALINGOPTION_NONE); COMPILE_ASSERT_PRINT_SCALING_MATCHING_ENUM( - WebKit::WebPrintScalingOptionFitToPrintableArea, + blink::WebPrintScalingOptionFitToPrintableArea, PP_PRINTSCALINGOPTION_FIT_TO_PRINTABLE_AREA); COMPILE_ASSERT_PRINT_SCALING_MATCHING_ENUM( - WebKit::WebPrintScalingOptionSourceSize, PP_PRINTSCALINGOPTION_SOURCE_SIZE); + blink::WebPrintScalingOptionSourceSize, PP_PRINTSCALINGOPTION_SOURCE_SIZE); // Sets |*security_origin| to be the WebKit security origin associated with the // document containing the given plugin instance. On success, returns true. If // the instance is invalid, returns false and |*security_origin| will be // unchanged. bool SecurityOriginForInstance(PP_Instance instance_id, - WebKit::WebSecurityOrigin* security_origin) { + blink::WebSecurityOrigin* security_origin) { PepperPluginInstanceImpl* instance = HostGlobals::Get()->GetInstance(instance_id); if (!instance) @@ -333,6 +339,33 @@ scoped_ptr<const char*[]> StringVectorToArgArray( return array.Pass(); } +// Returns true if this is a "system reserved" key which should not be sent to +// a plugin. Some poorly behaving plugins (like Flash) incorrectly report that +// they handle all keys sent to them. This can prevent keystrokes from working +// for things like screen brightness and volume control. +bool IsReservedSystemInputEvent(const blink::WebInputEvent& event) { +#if defined(OS_CHROMEOS) + if (event.type != WebInputEvent::KeyDown && + event.type != WebInputEvent::KeyUp) + return false; + const blink::WebKeyboardEvent& key_event = + static_cast<const blink::WebKeyboardEvent&>(event); + switch (key_event.windowsKeyCode) { + case ui::VKEY_BRIGHTNESS_DOWN: + case ui::VKEY_BRIGHTNESS_UP: + case ui::VKEY_KBD_BRIGHTNESS_DOWN: + case ui::VKEY_KBD_BRIGHTNESS_UP: + case ui::VKEY_VOLUME_MUTE: + case ui::VKEY_VOLUME_DOWN: + case ui::VKEY_VOLUME_UP: + return true; + default: + return false; + } +#endif // defined(OS_CHROMEOS) + return false; +} + class PluginInstanceLockTarget : public MouseLockDispatcher::LockTarget { public: PluginInstanceLockTarget(PepperPluginInstanceImpl* plugin) @@ -347,7 +380,7 @@ class PluginInstanceLockTarget : public MouseLockDispatcher::LockTarget { } virtual bool HandleMouseLockedInputEvent( - const WebKit::WebMouseEvent &event) OVERRIDE { + const blink::WebMouseEvent &event) OVERRIDE { plugin_->HandleMouseLockedInputEvent(event); return true; } @@ -361,7 +394,7 @@ class PluginInstanceLockTarget : public MouseLockDispatcher::LockTarget { // static PepperPluginInstanceImpl* PepperPluginInstanceImpl::Create( - RenderViewImpl* render_view, + RenderFrameImpl* render_frame, PluginModule* module, WebPluginContainer* container, const GURL& plugin_url) { @@ -371,7 +404,7 @@ PepperPluginInstanceImpl* PepperPluginInstanceImpl::Create( PPP_Instance_Combined::Create(get_plugin_interface_func); if (!ppp_instance_combined) return NULL; - return new PepperPluginInstanceImpl(render_view, module, + return new PepperPluginInstanceImpl(render_frame, module, ppp_instance_combined, container, plugin_url); } @@ -435,19 +468,19 @@ PPB_Gamepad_API* PepperPluginInstanceImpl::GamepadImpl::AsPPB_Gamepad_API() { void PepperPluginInstanceImpl::GamepadImpl::Sample( PP_Instance instance, PP_GamepadsSampleData* data) { - WebKit::WebGamepads webkit_data; + blink::WebGamepads webkit_data; RenderThreadImpl::current()->SampleGamepads(&webkit_data); ConvertWebKitGamepadData( - *reinterpret_cast<const ppapi::WebKitGamepads*>(&webkit_data), data); + bit_cast<ppapi::WebKitGamepads>(webkit_data), data); } PepperPluginInstanceImpl::PepperPluginInstanceImpl( - RenderViewImpl* render_view, + RenderFrameImpl* render_frame, PluginModule* module, ppapi::PPP_Instance_Combined* instance_interface, WebPluginContainer* container, const GURL& plugin_url) - : render_view_(render_view), + : render_frame_(render_frame), module_(module), instance_interface_(instance_interface), pp_instance_(0), @@ -456,7 +489,6 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl( plugin_url_(plugin_url), full_frame_(false), sent_initial_did_change_view_(false), - view_change_weak_ptr_factory_(this), bound_graphics_2d_platform_(NULL), has_webkit_focus_(false), has_content_area_focus_(false), @@ -493,25 +525,28 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl( document_loader_(NULL), external_document_load_(false), npp_(new NPP_t), - isolate_(v8::Isolate::GetCurrent()) { + isolate_(v8::Isolate::GetCurrent()), + is_deleted_(false), + view_change_weak_ptr_factory_(this), + weak_factory_(this) { pp_instance_ = HostGlobals::Get()->AddInstance(this); memset(¤t_print_settings_, 0, sizeof(current_print_settings_)); module_->InstanceCreated(this); - if (render_view) { // NULL in tests - render_view->PepperInstanceCreated(this); - view_data_.is_page_visible = !render_view->is_hidden(); + if (render_frame) { // NULL in tests + render_frame->PepperInstanceCreated(this); + view_data_.is_page_visible = !render_frame_->GetRenderWidget()->is_hidden(); // Set the initial focus. - SetContentAreaFocus(render_view_->has_focus()); + SetContentAreaFocus(render_frame_->GetRenderWidget()->has_focus()); if (!module_->IsProxied()) { PepperBrowserConnection* browser_connection = - PepperBrowserConnection::Get(render_view_); + PepperBrowserConnection::Get(render_frame_); browser_connection->DidCreateInProcessInstance( pp_instance(), - render_view_->GetRoutingID(), + render_frame_->render_view()->GetRoutingID(), container_->element().document().url(), GetPluginURL()); } @@ -542,12 +577,12 @@ PepperPluginInstanceImpl::~PepperPluginInstanceImpl() { if (TrackedCallback::IsPending(lock_mouse_callback_)) lock_mouse_callback_->Abort(); - if (render_view_) - render_view_->PepperInstanceDeleted(this); + if (render_frame_) + render_frame_->PepperInstanceDeleted(this); - if (!module_->IsProxied() && render_view_) { + if (!module_->IsProxied() && render_frame_) { PepperBrowserConnection* browser_connection = - PepperBrowserConnection::Get(render_view_); + PepperBrowserConnection::Get(render_frame_); browser_connection->DidDeleteInProcessInstance(pp_instance()); } @@ -569,6 +604,8 @@ PepperPluginInstanceImpl::~PepperPluginInstanceImpl() { // returned, then it needs to keep its own reference on the stack. void PepperPluginInstanceImpl::Delete() { + is_deleted_ = true; + // Keep a reference on the stack. See NOTE above. scoped_refptr<PepperPluginInstanceImpl> ref(this); // Force the MessageChannel to release its "passthrough object" which should @@ -599,6 +636,10 @@ void PepperPluginInstanceImpl::Delete() { container_ = NULL; } +bool PepperPluginInstanceImpl::is_deleted() const { + return is_deleted_; +} + void PepperPluginInstanceImpl::Paint(WebCanvas* canvas, const gfx::Rect& plugin_rect, const gfx::Rect& paint_rect) { @@ -675,7 +716,7 @@ void PepperPluginInstanceImpl::InstanceCrashed() { BindGraphics(pp_instance(), 0); InvalidateRect(gfx::Rect()); - render_view_->PluginCrashed(module_->path(), module_->GetPeerProcessId()); + render_frame_->PluginCrashed(module_->path(), module_->GetPeerProcessId()); UnSetAndDeleteLockTargetAdapter(); } @@ -721,8 +762,9 @@ bool PepperPluginInstanceImpl::Initialize( UpdateTouchEventRequest(); container_->setWantsWheelEvents(IsAcceptingWheelEvents()); - SetGPUHistogram(ppapi::Preferences(render_view_->webkit_preferences()), - arg_names, arg_values); + SetGPUHistogram(ppapi::Preferences( + render_frame_->render_view()->webkit_preferences()), + arg_names, arg_values); argn_ = arg_names; argv_ = arg_values; @@ -738,7 +780,7 @@ bool PepperPluginInstanceImpl::Initialize( } bool PepperPluginInstanceImpl::HandleDocumentLoad( - const WebKit::WebURLResponse& response) { + const blink::WebURLResponse& response) { DCHECK(!document_loader_); if (external_document_load_) { // The external proxy isn't available, so save the response and record @@ -782,7 +824,7 @@ bool PepperPluginInstanceImpl::HandleDocumentLoad( pp_instance(), response, base::Bind(&PepperPluginInstanceImpl::DidDataFromWebURLResponse, - AsWeakPtr(), + weak_factory_.GetWeakPtr(), response, pending_host_id)); @@ -794,7 +836,7 @@ bool PepperPluginInstanceImpl::HandleDocumentLoad( bool PepperPluginInstanceImpl::SendCompositionEventToPlugin( PP_InputEvent_Type type, const base::string16& text) { - std::vector<WebKit::WebCompositionUnderline> empty; + std::vector<blink::WebCompositionUnderline> empty; return SendCompositionEventWithUnderlineInformationToPlugin( type, text, empty, static_cast<int>(text.size()), static_cast<int>(text.size())); @@ -804,7 +846,7 @@ bool PepperPluginInstanceImpl:: SendCompositionEventWithUnderlineInformationToPlugin( PP_InputEvent_Type type, const base::string16& text, - const std::vector<WebKit::WebCompositionUnderline>& underlines, + const std::vector<blink::WebCompositionUnderline>& underlines, int selection_start, int selection_end) { // Keep a reference on the stack. See NOTE above. @@ -893,7 +935,7 @@ bool PepperPluginInstanceImpl::HandleCompositionStart( bool PepperPluginInstanceImpl::HandleCompositionUpdate( const base::string16& text, - const std::vector<WebKit::WebCompositionUnderline>& underlines, + const std::vector<blink::WebCompositionUnderline>& underlines, int selection_start, int selection_end) { return SendCompositionEventWithUnderlineInformationToPlugin( @@ -948,18 +990,22 @@ gfx::Rect PepperPluginInstanceImpl::GetCaretBounds() const { } bool PepperPluginInstanceImpl::HandleInputEvent( - const WebKit::WebInputEvent& event, + const blink::WebInputEvent& event, WebCursorInfo* cursor_info) { TRACE_EVENT0("ppapi", "PepperPluginInstanceImpl::HandleInputEvent"); if (WebInputEvent::isMouseEventType(event.type)) { - render_view_->PepperDidReceiveMouseEvent(this); + render_frame_->PepperDidReceiveMouseEvent(this); } // Don't dispatch input events to crashed plugins. if (module()->is_crashed()) return false; + // Don't send reserved system key events to plugins. + if (IsReservedSystemInputEvent(event)) + return false; + // Keep a reference on the stack. See NOTE above. scoped_refptr<PepperPluginInstanceImpl> ref(this); @@ -1052,7 +1098,8 @@ void PepperPluginInstanceImpl::ViewChanged( WebDocument document = element.document(); bool is_fullscreen_element = (element == document.fullScreenElement()); if (!view_data_.is_fullscreen && desired_fullscreen_state_ && - render_view_->is_fullscreen() && is_fullscreen_element) { + render_frame()->GetRenderWidget()->is_fullscreen() && + is_fullscreen_element) { // Entered fullscreen. Only possible via SetFullscreen(). view_data_.is_fullscreen = true; } else if (view_data_.is_fullscreen && !is_fullscreen_element) { @@ -1114,13 +1161,6 @@ void PepperPluginInstanceImpl::PageVisibilityChanged(bool is_visible) { SendDidChangeView(); } -void PepperPluginInstanceImpl::ViewWillInitiatePaint() { - if (bound_graphics_2d_platform_) - bound_graphics_2d_platform_->ViewWillInitiatePaint(); - else if (bound_graphics_3d_.get()) - bound_graphics_3d_->ViewWillInitiatePaint(); -} - void PepperPluginInstanceImpl::ViewInitiatedPaint() { if (bound_graphics_2d_platform_) bound_graphics_2d_platform_->ViewInitiatedPaint(); @@ -1346,12 +1386,22 @@ bool PepperPluginInstanceImpl::LoadPrintInterface() { } bool PepperPluginInstanceImpl::LoadPrivateInterface() { + // If this is a NaCl app, we want to talk to the trusted NaCl plugin to + // call GetInstanceObject. This is necessary to ensure that the properties + // the trusted plugin exposes (readyState and lastError) work properly. Note + // that untrusted NaCl apps are not allowed to provide PPP_InstancePrivate, + // so it's correct to never look up PPP_InstancePrivate for them. + // + // If this is *not* a NaCl plugin, original_module_ will never be set; we talk + // to the "real" module. + scoped_refptr<PluginModule> module = original_module_ ? original_module_ : + module_; // Only check for the interface if the plugin has private permission. - if (!module_->permissions().HasPermission(ppapi::PERMISSION_PRIVATE)) + if (!module->permissions().HasPermission(ppapi::PERMISSION_PRIVATE)) return false; if (!plugin_private_interface_) { plugin_private_interface_ = static_cast<const PPP_Instance_Private*>( - module_->GetPluginInterface(PPP_INSTANCE_PRIVATE_INTERFACE)); + module->GetPluginInterface(PPP_INSTANCE_PRIVATE_INTERFACE)); } return !!plugin_private_interface_; @@ -1398,7 +1448,7 @@ void PepperPluginInstanceImpl::SendFocusChangeNotification() { scoped_refptr<PepperPluginInstanceImpl> ref(this); bool has_focus = PluginHasFocus(); - render_view_->PepperFocusChanged(this, has_focus); + render_frame_->PepperFocusChanged(this, has_focus); // instance_interface_ may have been cleared in Delete() if the // PepperWebPluginImpl is destroyed. @@ -1410,8 +1460,8 @@ void PepperPluginInstanceImpl::UpdateTouchEventRequest() { bool raw_touch = (filtered_input_event_mask_ & PP_INPUTEVENT_CLASS_TOUCH) || (input_event_mask_ & PP_INPUTEVENT_CLASS_TOUCH); container_->requestTouchEventType(raw_touch ? - WebKit::WebPluginContainer::TouchEventRequestTypeRaw : - WebKit::WebPluginContainer::TouchEventRequestTypeSynthesizedMouse); + blink::WebPluginContainer::TouchEventRequestTypeRaw : + blink::WebPluginContainer::TouchEventRequestTypeSynthesizedMouse); } bool PepperPluginInstanceImpl::IsAcceptingWheelEvents() const { @@ -1448,16 +1498,6 @@ void PepperPluginInstanceImpl::SendDidChangeView() { last_sent_view_data_.Equals(view_data_))) return; // Nothing to update. - const PP_Size& size = view_data_.rect.size; - // Avoid sending a notification with a huge rectangle. - if (size.width < 0 || size.width > kMaxPluginSideLength || - size.height < 0 || size.height > kMaxPluginSideLength || - // We know this won't overflow due to above checks. - static_cast<uint32>(size.width) * static_cast<uint32>(size.height) > - kMaxPluginSize) { - return; - } - sent_initial_did_change_view_ = true; last_sent_view_data_ = view_data_; ScopedPPResource resource( @@ -1465,9 +1505,16 @@ void PepperPluginInstanceImpl::SendDidChangeView() { (new PPB_View_Shared(ppapi::OBJECT_IS_IMPL, pp_instance(), view_data_))->GetReference()); - instance_interface_->DidChangeView(pp_instance(), resource, - &view_data_.rect, - &view_data_.clip_rect); + if (bound_graphics_2d_platform_) + bound_graphics_2d_platform_->DidChangeView(view_data_); + + // It's possible that Delete() has been called but the renderer hasn't + // released its reference to this object yet. + if (instance_interface_) { + instance_interface_->DidChangeView(pp_instance(), resource, + &view_data_.rect, + &view_data_.clip_rect); + } } void PepperPluginInstanceImpl::ReportGeometry() { @@ -1537,7 +1584,7 @@ int PepperPluginInstanceImpl::PrintBegin(const WebPrintParams& print_params) { } bool PepperPluginInstanceImpl::PrintPage(int page_number, - WebKit::WebCanvas* canvas) { + blink::WebCanvas* canvas) { #if defined(ENABLE_FULL_PRINTING) DCHECK(plugin_print_interface_); PP_PrintPageNumberRange_Dev page_range; @@ -1563,7 +1610,7 @@ bool PepperPluginInstanceImpl::PrintPage(int page_number, bool PepperPluginInstanceImpl::PrintPageHelper( PP_PrintPageNumberRange_Dev* page_ranges, int num_ranges, - WebKit::WebCanvas* canvas) { + blink::WebCanvas* canvas) { // Keep a reference on the stack. See NOTE above. scoped_refptr<PepperPluginInstanceImpl> ref(this); DCHECK(plugin_print_interface_); @@ -1639,7 +1686,9 @@ bool PepperPluginInstanceImpl::SetFullscreen(bool fullscreen) { if (fullscreen == IsFullscreenOrPending()) return false; - if (fullscreen && !render_view_->IsPluginFullscreenAllowed()) + if (fullscreen && + !render_frame_->render_view()->renderer_preferences(). + plugin_fullscreen_allowed) return false; // Check whether we are trying to switch while the state is in transition. @@ -1717,7 +1766,7 @@ bool PepperPluginInstanceImpl::IsViewAccelerated() { } bool PepperPluginInstanceImpl::PrintPDFOutput(PP_Resource print_output, - WebKit::WebCanvas* canvas) { + blink::WebCanvas* canvas) { #if defined(ENABLE_FULL_PRINTING) ppapi::thunk::EnterResourceNoLock<PPB_Buffer_API> enter(print_output, true); if (enter.failed()) @@ -1827,8 +1876,9 @@ void PepperPluginInstanceImpl::UpdateLayer() { if ((want_layer == !!texture_layer_.get()) && (want_3d_layer == layer_is_hardware_) && - layer_bound_to_fullscreen_ == !!fullscreen_container_) + layer_bound_to_fullscreen_ == !!fullscreen_container_) { return; + } if (texture_layer_) { if (!layer_bound_to_fullscreen_) @@ -1874,10 +1924,6 @@ unsigned PepperPluginInstanceImpl::PrepareTexture() { return 0; } -WebKit::WebGraphicsContext3D* PepperPluginInstanceImpl::Context3d() { - return NULL; -} - bool PepperPluginInstanceImpl::PrepareTextureMailbox( cc::TextureMailbox* mailbox, scoped_ptr<cc::SingleReleaseCallback>* release_callback, @@ -1925,9 +1971,9 @@ void PepperPluginInstanceImpl::OnMouseLockLost() { } void PepperPluginInstanceImpl::HandleMouseLockedInputEvent( - const WebKit::WebMouseEvent& event) { + const blink::WebMouseEvent& event) { // |cursor_info| is ignored since it is hidden when the mouse is locked. - WebKit::WebCursorInfo cursor_info; + blink::WebCursorInfo cursor_info; HandleInputEvent(event, &cursor_info); } @@ -1966,7 +2012,7 @@ bool PepperPluginInstanceImpl::SimulateIMEEvent( SimulateImeSetCompositionEvent(input_event); break; case PP_INPUTEVENT_TYPE_IME_TEXT: - render_view_->SimulateImeConfirmComposition( + render_frame_->SimulateImeConfirmComposition( UTF8ToUTF16(input_event.character_text), gfx::Range()); break; default: @@ -1987,9 +2033,9 @@ void PepperPluginInstanceImpl::SimulateImeSetCompositionEvent( base::string16 utf16_text = base::UTF8ToUTF16AndAdjustOffsets(input_event.character_text, &offsets); - std::vector<WebKit::WebCompositionUnderline> underlines; + std::vector<blink::WebCompositionUnderline> underlines; for (size_t i = 2; i + 1 < offsets.size(); ++i) { - WebKit::WebCompositionUnderline underline; + blink::WebCompositionUnderline underline; underline.startOffset = offsets[i]; underline.endOffset = offsets[i + 1]; if (input_event.composition_target_segment == static_cast<int32_t>(i - 2)) @@ -1997,7 +2043,7 @@ void PepperPluginInstanceImpl::SimulateImeSetCompositionEvent( underlines.push_back(underline); } - render_view_->SimulateImeSetComposition( + render_frame_->SimulateImeSetComposition( utf16_text, underlines, offsets[0], offsets[1]); } @@ -2141,7 +2187,7 @@ PP_Var PepperPluginInstanceImpl::ExecuteScript(PP_Instance instance, NPVariant result; bool ok = false; if (IsProcessingUserGesture()) { - WebKit::WebScopedUserGesture user_gesture(CurrentUserGestureToken()); + blink::WebScopedUserGesture user_gesture(CurrentUserGestureToken()); ok = WebBindings::evaluate(NULL, frame->windowObject(), &np_script, &result); } else { @@ -2175,35 +2221,43 @@ uint32_t PepperPluginInstanceImpl::GetAudioHardwareOutputBufferSize( PP_Var PepperPluginInstanceImpl::GetDefaultCharSet(PP_Instance instance) { return StringVar::StringToPPVar( - render_view_->webkit_preferences().default_encoding); + render_frame_->render_view()->webkit_preferences().default_encoding); } // These PPB_ContentDecryptor_Private calls are responses to // PPP_ContentDecryptor_Private calls made on |content_decryptor_delegate_|. // Therefore, |content_decryptor_delegate_| must have been initialized when // the following methods are called. -void PepperPluginInstanceImpl::KeyAdded(PP_Instance instance, - PP_Var key_system_var, - PP_Var session_id_var) { - content_decryptor_delegate_->KeyAdded(key_system_var, session_id_var); +void PepperPluginInstanceImpl::SessionCreated(PP_Instance instance, + uint32_t session_id, + PP_Var web_session_id_var) { + content_decryptor_delegate_->OnSessionCreated(session_id, web_session_id_var); +} + +void PepperPluginInstanceImpl::SessionMessage(PP_Instance instance, + uint32_t session_id, + PP_Var message_var, + PP_Var destination_url) { + content_decryptor_delegate_->OnSessionMessage( + session_id, message_var, destination_url); +} + +void PepperPluginInstanceImpl::SessionReady(PP_Instance instance, + uint32_t session_id) { + content_decryptor_delegate_->OnSessionReady(session_id); } -void PepperPluginInstanceImpl::KeyMessage(PP_Instance instance, - PP_Var key_system_var, - PP_Var session_id_var, - PP_Var message_var, - PP_Var default_url_var) { - content_decryptor_delegate_->KeyMessage( - key_system_var, session_id_var, message_var, default_url_var); +void PepperPluginInstanceImpl::SessionClosed(PP_Instance instance, + uint32_t session_id) { + content_decryptor_delegate_->OnSessionClosed(session_id); } -void PepperPluginInstanceImpl::KeyError(PP_Instance instance, - PP_Var key_system_var, - PP_Var session_id_var, - int32_t media_error, - int32_t system_code) { - content_decryptor_delegate_->KeyError( - key_system_var, session_id_var, media_error, system_code); +void PepperPluginInstanceImpl::SessionError(PP_Instance instance, + uint32_t session_id, + int32_t media_error, + int32_t system_code) { + content_decryptor_delegate_->OnSessionError( + session_id, media_error, system_code); } void PepperPluginInstanceImpl::DeliverBlock( @@ -2248,8 +2302,8 @@ void PepperPluginInstanceImpl::DeliverFrame( void PepperPluginInstanceImpl::DeliverSamples( PP_Instance instance, PP_Resource audio_frames, - const PP_DecryptedBlockInfo* block_info) { - content_decryptor_delegate_->DeliverSamples(audio_frames, block_info); + const PP_DecryptedSampleInfo* sample_info) { + content_decryptor_delegate_->DeliverSamples(audio_frames, sample_info); } void PepperPluginInstanceImpl::NumberOfFindResultsChanged( @@ -2257,15 +2311,15 @@ void PepperPluginInstanceImpl::NumberOfFindResultsChanged( int32_t total, PP_Bool final_result) { DCHECK_NE(find_identifier_, -1); - render_view_->reportFindInPageMatchCount( + render_frame_->reportFindInPageMatchCount( find_identifier_, total, PP_ToBool(final_result)); } void PepperPluginInstanceImpl::SelectedFindResultChanged(PP_Instance instance, int32_t index) { DCHECK_NE(find_identifier_, -1); - render_view_->reportFindInPageSelection( - find_identifier_, index + 1, WebKit::WebRect()); + render_frame_->reportFindInPageSelection( + find_identifier_, index + 1, blink::WebRect()); } PP_Bool PepperPluginInstanceImpl::IsFullscreen(PP_Instance instance) { @@ -2279,7 +2333,7 @@ PP_Bool PepperPluginInstanceImpl::SetFullscreen(PP_Instance instance, PP_Bool PepperPluginInstanceImpl::GetScreenSize(PP_Instance instance, PP_Size* size) { - WebKit::WebScreenInfo info = render_view_->screenInfo(); + blink::WebScreenInfo info = render_frame()->GetRenderWidget()->screenInfo(); *size = PP_MakeSize(info.rect.width, info.rect.height); return PP_TRUE; } @@ -2291,12 +2345,12 @@ ppapi::Resource* PepperPluginInstanceImpl::GetSingletonResource( switch (id) { case ppapi::BROKER_SINGLETON_ID: case ppapi::BROWSER_FONT_SINGLETON_ID: - case ppapi::CRX_FILESYSTEM_SINGLETON_ID: case ppapi::EXTENSIONS_COMMON_SINGLETON_ID: case ppapi::FLASH_CLIPBOARD_SINGLETON_ID: case ppapi::FLASH_FILE_SINGLETON_ID: case ppapi::FLASH_FULLSCREEN_SINGLETON_ID: case ppapi::FLASH_SINGLETON_ID: + case ppapi::ISOLATED_FILESYSTEM_SINGLETON_ID: case ppapi::NETWORK_PROXY_SINGLETON_ID: case ppapi::PDF_SINGLETON_ID: case ppapi::TRUETYPE_FONT_SINGLETON_ID: @@ -2352,7 +2406,8 @@ void PepperPluginInstanceImpl::ZoomLimitsChanged(PP_Instance instance, } double minimum_level = ZoomFactorToZoomLevel(minimum_factor); double maximum_level = ZoomFactorToZoomLevel(maximum_factor); - render_view_->webview()->zoomLimitsChanged(minimum_level, maximum_level); + render_frame_->render_view()->webview()->zoomLimitsChanged( + minimum_level, maximum_level); } void PepperPluginInstanceImpl::PostMessage(PP_Instance instance, @@ -2439,7 +2494,7 @@ void PepperPluginInstanceImpl::SetTextInputType(PP_Instance instance, if (itype < 0 || itype > ui::TEXT_INPUT_TYPE_URL) itype = ui::TEXT_INPUT_TYPE_NONE; text_input_type_ = static_cast<ui::TextInputType>(itype); - render_view_->PepperTextInputTypeChanged(this); + render_frame_->PepperTextInputTypeChanged(this); } void PepperPluginInstanceImpl::UpdateCaretPosition( @@ -2449,11 +2504,11 @@ void PepperPluginInstanceImpl::UpdateCaretPosition( text_input_caret_ = PP_ToGfxRect(caret); text_input_caret_bounds_ = PP_ToGfxRect(bounding_box); text_input_caret_set_ = true; - render_view_->PepperCaretPositionChanged(this); + render_frame_->PepperCaretPositionChanged(this); } void PepperPluginInstanceImpl::CancelCompositionText(PP_Instance instance) { - render_view_->PepperCancelComposition(this); + render_frame_->PepperCancelComposition(this); } void PepperPluginInstanceImpl::SelectionChanged(PP_Instance instance) { @@ -2468,7 +2523,7 @@ void PepperPluginInstanceImpl::SelectionChanged(PP_Instance instance) { base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(&PepperPluginInstanceImpl::RequestSurroundingText, - AsWeakPtr(), + weak_factory_.GetWeakPtr(), static_cast<size_t>(kExtraCharsForTextInput))); } @@ -2479,7 +2534,7 @@ void PepperPluginInstanceImpl::UpdateSurroundingText(PP_Instance instance, surrounding_text_ = text; selection_caret_ = caret; selection_anchor_ = anchor; - render_view_->PepperSelectionChanged(this); + render_frame_->PepperSelectionChanged(this); } PP_Var PepperPluginInstanceImpl::ResolveRelativeToDocument( @@ -2503,7 +2558,7 @@ PP_Bool PepperPluginInstanceImpl::DocumentCanRequest(PP_Instance instance, if (!url_string) return PP_FALSE; - WebKit::WebSecurityOrigin security_origin; + blink::WebSecurityOrigin security_origin; if (!SecurityOriginForInstance(instance, &security_origin)) return PP_FALSE; @@ -2517,11 +2572,11 @@ PP_Bool PepperPluginInstanceImpl::DocumentCanRequest(PP_Instance instance, PP_Bool PepperPluginInstanceImpl::DocumentCanAccessDocument( PP_Instance instance, PP_Instance target) { - WebKit::WebSecurityOrigin our_origin; + blink::WebSecurityOrigin our_origin; if (!SecurityOriginForInstance(instance, &our_origin)) return PP_FALSE; - WebKit::WebSecurityOrigin target_origin; + blink::WebSecurityOrigin target_origin; if (!SecurityOriginForInstance(instance, &target_origin)) return PP_FALSE; @@ -2531,7 +2586,7 @@ PP_Bool PepperPluginInstanceImpl::DocumentCanAccessDocument( PP_Var PepperPluginInstanceImpl::GetDocumentURL( PP_Instance instance, PP_URLComponents_Dev* components) { - WebKit::WebDocument document = container()->element().document(); + blink::WebDocument document = container()->element().document(); return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(document.url(), components); } @@ -2546,7 +2601,7 @@ PP_Var PepperPluginInstanceImpl::GetPluginInstanceURL( PP_Var PepperPluginInstanceImpl::GetPluginReferrerURL( PP_Instance instance, PP_URLComponents_Dev* components) { - WebKit::WebDocument document = container()->element().document(); + blink::WebDocument document = container()->element().document(); if (!full_frame_) return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(document.url(), components); @@ -2623,7 +2678,7 @@ PP_ExternalPluginResult PepperPluginInstanceImpl::ResetAsProxied( document_loader_ = NULL; // Pass the response to the new proxy. HandleDocumentLoad(external_document_response_); - external_document_response_ = WebKit::WebURLResponse(); + external_document_response_ = blink::WebURLResponse(); // Replay any document load events we've received to the real loader. external_document_loader_->ReplayReceivedData(document_loader_); external_document_loader_.reset(NULL); @@ -2642,22 +2697,22 @@ NPP PepperPluginInstanceImpl::instanceNPP() { return npp_.get(); } -v8::Isolate* PepperPluginInstanceImpl::GetIsolate() const { - return isolate_; -} - PepperPluginInstance* PepperPluginInstance::Get(PP_Instance instance_id) { return HostGlobals::Get()->GetInstance(instance_id); } RenderView* PepperPluginInstanceImpl::GetRenderView() { - return render_view_; + return render_frame_->render_view(); } -WebKit::WebPluginContainer* PepperPluginInstanceImpl::GetContainer() { +blink::WebPluginContainer* PepperPluginInstanceImpl::GetContainer() { return container_; } +v8::Isolate* PepperPluginInstanceImpl::GetIsolate() const { + return isolate_; +} + ppapi::VarTracker* PepperPluginInstanceImpl::GetVarTracker() { return HostGlobals::Get()->GetVarTracker(); } @@ -2672,11 +2727,9 @@ base::FilePath PepperPluginInstanceImpl::GetModulePath() { PP_Resource PepperPluginInstanceImpl::CreateImage(gfx::ImageSkia* source_image, float scale) { - ui::ScaleFactor scale_factor = ui::GetScaleFactorFromScale(scale); - gfx::ImageSkiaRep image_skia_rep = source_image->GetRepresentation( - scale_factor); + gfx::ImageSkiaRep image_skia_rep = source_image->GetRepresentation(scale); - if (image_skia_rep.is_null() || image_skia_rep.scale_factor() != scale_factor) + if (image_skia_rep.is_null() || image_skia_rep.scale() != scale) return 0; scoped_refptr<PPB_ImageData_Impl> image_data(new PPB_ImageData_Impl( @@ -2717,7 +2770,7 @@ PP_ExternalPluginResult PepperPluginInstanceImpl::SwitchToOutOfProcessProxy( RendererPpapiHostImpl* renderer_ppapi_host = external_plugin_module->CreateOutOfProcessModule( - render_view_, + render_frame_, file_path, permissions, channel_handle, @@ -2742,7 +2795,7 @@ void PepperPluginInstanceImpl::DoSetCursor(WebCursorInfo* cursor) { if (fullscreen_container_) { fullscreen_container_->DidChangeCursor(*cursor); } else { - render_view_->PepperDidChangeCursor(this, *cursor); + render_frame_->PepperDidChangeCursor(this, *cursor); } } @@ -2763,14 +2816,17 @@ bool PepperPluginInstanceImpl::FlashSetFullscreen(bool fullscreen, if (fullscreen == FlashIsFullscreenOrPending()) return true; - if (fullscreen && !render_view_->IsPluginFullscreenAllowed()) + if (fullscreen && + !render_frame_->render_view()->renderer_preferences(). + plugin_fullscreen_allowed) return false; // Unbind current 2D or 3D graphics context. VLOG(1) << "Setting fullscreen to " << (fullscreen ? "on" : "off"); if (fullscreen) { DCHECK(!fullscreen_container_); - fullscreen_container_ = render_view_->CreatePepperFullscreenContainer(this); + fullscreen_container_ = + render_frame_->CreatePepperFullscreenContainer(this); UpdateLayer(); } else { DCHECK(fullscreen_container_); @@ -2854,17 +2910,22 @@ int PepperPluginInstanceImpl::MakePendingFileRefRendererHost( scoped_ptr<ppapi::host::ResourceHost>(file_ref_host)); } +void PepperPluginInstanceImpl::SetEmbedProperty(PP_Var key, + PP_Var value) { + message_channel_->SetReadOnlyProperty(key, value); +} + bool PepperPluginInstanceImpl::CanAccessMainFrame() const { if (!container_) return false; - WebKit::WebDocument containing_document = container_->element().document(); + blink::WebDocument containing_document = container_->element().document(); if (!containing_document.frame() || !containing_document.frame()->view() || !containing_document.frame()->view()->mainFrame()) { return false; } - WebKit::WebDocument main_document = + blink::WebDocument main_document = containing_document.frame()->view()->mainFrame()->document(); return containing_document.securityOrigin().canAccess( @@ -2882,7 +2943,7 @@ void PepperPluginInstanceImpl::KeepSizeAttributesBeforeFullscreen() { } void PepperPluginInstanceImpl::SetSizeAttributesForFullscreen() { - WebKit::WebScreenInfo info = render_view_->screenInfo(); + blink::WebScreenInfo info = render_frame_->GetRenderWidget()->screenInfo(); screen_size_for_fullscreen_ = gfx::Size(info.rect.width, info.rect.height); std::string width = StringPrintf("%d", screen_size_for_fullscreen_.width()); std::string height = StringPrintf("%d", screen_size_for_fullscreen_.height()); @@ -2937,7 +2998,7 @@ MouseLockDispatcher* PepperPluginInstanceImpl::GetMouseLockDispatcher() { static_cast<RenderWidgetFullscreenPepper*>(fullscreen_container_); return container->mouse_lock_dispatcher(); } else { - return render_view_->mouse_lock_dispatcher(); + return render_frame_->render_view()->mouse_lock_dispatcher(); } } @@ -2949,7 +3010,7 @@ void PepperPluginInstanceImpl::UnSetAndDeleteLockTargetAdapter() { } void PepperPluginInstanceImpl::DidDataFromWebURLResponse( - const WebKit::WebURLResponse& response, + const blink::WebURLResponse& response, int pending_host_id, const ppapi::URLResponseInfoData& data) { RendererPpapiHostImpl* host_impl = module_->renderer_ppapi_host(); diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h index 42d7d7139e2..0ed093f9d52 100644 --- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h +++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h @@ -63,7 +63,7 @@ struct _NPP; class SkBitmap; class TransportDIB; -namespace WebKit { +namespace blink { class WebInputEvent; class WebLayer; class WebMouseEvent; @@ -105,6 +105,7 @@ class PluginObject; class PPB_Graphics3D_Impl; class PPB_ImageData_Impl; class PPB_URLLoader_Impl; +class RenderFrameImpl; class RenderViewImpl; // Represents one time a plugin appears on one web page. @@ -113,7 +114,6 @@ class RenderViewImpl; // ResourceTracker. class CONTENT_EXPORT PepperPluginInstanceImpl : public base::RefCounted<PepperPluginInstanceImpl>, - public base::SupportsWeakPtr<PepperPluginInstanceImpl>, public NON_EXPORTED_BASE(PepperPluginInstance), public ppapi::PPB_Instance_Shared, public NON_EXPORTED_BASE(cc::TextureLayerClient) { @@ -123,15 +123,15 @@ class CONTENT_EXPORT PepperPluginInstanceImpl // get_plugin_interface function. If the plugin does not support any valid // PPP_Instance interface, returns NULL. static PepperPluginInstanceImpl* Create( - RenderViewImpl* render_view, + RenderFrameImpl* render_frame, PluginModule* module, - WebKit::WebPluginContainer* container, + blink::WebPluginContainer* container, const GURL& plugin_url); - RenderViewImpl* render_view() const { return render_view_; } + RenderFrameImpl* render_frame() const { return render_frame_; } PluginModule* module() const { return module_.get(); } MessageChannel& message_channel() { return *message_channel_; } - WebKit::WebPluginContainer* container() const { return container_; } + blink::WebPluginContainer* container() const { return container_; } // Returns the PP_Instance uniquely identifying this instance. Guaranteed // nonzero. @@ -147,8 +147,11 @@ class CONTENT_EXPORT PepperPluginInstanceImpl // the WebPlugin implementation when WebKit is about to remove the plugin. void Delete(); + // Returns true if Delete() has been called on this object. + bool is_deleted() const; + // Paints the current backing store to the web page. - void Paint(WebKit::WebCanvas* canvas, + void Paint(blink::WebCanvas* canvas, const gfx::Rect& plugin_rect, const gfx::Rect& paint_rect); @@ -178,9 +181,9 @@ class CONTENT_EXPORT PepperPluginInstanceImpl bool Initialize(const std::vector<std::string>& arg_names, const std::vector<std::string>& arg_values, bool full_frame); - bool HandleDocumentLoad(const WebKit::WebURLResponse& response); - bool HandleInputEvent(const WebKit::WebInputEvent& event, - WebKit::WebCursorInfo* cursor_info); + bool HandleDocumentLoad(const blink::WebURLResponse& response); + bool HandleInputEvent(const blink::WebInputEvent& event, + blink::WebCursorInfo* cursor_info); PP_Var GetInstanceObject(); void ViewChanged(const gfx::Rect& position, const gfx::Rect& clip, const std::vector<gfx::Rect>& cut_outs_rects); @@ -189,7 +192,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl bool HandleCompositionStart(const base::string16& text); bool HandleCompositionUpdate( const base::string16& text, - const std::vector<WebKit::WebCompositionUnderline>& underlines, + const std::vector<blink::WebCompositionUnderline>& underlines, int selection_start, int selection_end); bool HandleCompositionEnd(const base::string16& text); @@ -208,10 +211,9 @@ class CONTENT_EXPORT PepperPluginInstanceImpl // Notification about page visibility. The default is "visible". void PageVisibilityChanged(bool is_visible); - // Notifications that the view is about to paint, has started painting, and - // has flushed the painted content to the screen. These messages are used to - // send Flush callbacks to the plugin for DeviceContext2D/3D. - void ViewWillInitiatePaint(); + // Notifications that the view has started painting, and has flushed the + // painted content to the screen. These messages are used to send Flush + // callbacks to the plugin for DeviceContext2D/3D. void ViewInitiatedPaint(); void ViewFlushedPaint(); @@ -242,12 +244,12 @@ class CONTENT_EXPORT PepperPluginInstanceImpl bool SupportsPrintInterface(); bool IsPrintScalingDisabled(); - int PrintBegin(const WebKit::WebPrintParams& print_params); - bool PrintPage(int page_number, WebKit::WebCanvas* canvas); + int PrintBegin(const blink::WebPrintParams& print_params); + bool PrintPage(int page_number, blink::WebCanvas* canvas); void PrintEnd(); bool CanRotateView(); - void RotateView(WebKit::WebPlugin::RotationType type); + void RotateView(blink::WebPlugin::RotationType type); // There are 2 implementations of the fullscreen interface // PPB_FlashFullscreen is used by Pepper Flash. @@ -311,14 +313,14 @@ class CONTENT_EXPORT PepperPluginInstanceImpl // Returns the user gesture token to use for creating a WebScopedUserGesture, // if IsProcessingUserGesture returned true. - WebKit::WebUserGestureToken CurrentUserGestureToken(); + blink::WebUserGestureToken CurrentUserGestureToken(); // A mouse lock request was pending and this reports success or failure. void OnLockMouseACK(bool succeeded); // A mouse lock was in place, but has been lost. void OnMouseLockLost(); // A mouse lock is enabled and mouse events are being delivered. - void HandleMouseLockedInputEvent(const WebKit::WebMouseEvent& event); + void HandleMouseLockedInputEvent(const blink::WebMouseEvent& event); // Simulates an input event to the plugin by passing it down to WebKit, // which sends it back up to the plugin as if it came from the user. @@ -334,10 +336,10 @@ class CONTENT_EXPORT PepperPluginInstanceImpl // case is non-NULL as long as the corresponding loader resource is alive. // This pointer is non-owning, so the loader must use set_document_loader to // clear itself when it is destroyed. - WebKit::WebURLLoaderClient* document_loader() const { + blink::WebURLLoaderClient* document_loader() const { return document_loader_; } - void set_document_loader(WebKit::WebURLLoaderClient* loader) { + void set_document_loader(blink::WebURLLoaderClient* loader) { document_loader_ = loader; } @@ -345,7 +347,8 @@ class CONTENT_EXPORT PepperPluginInstanceImpl // PluginInstance implementation virtual RenderView* GetRenderView() OVERRIDE; - virtual WebKit::WebPluginContainer* GetContainer() OVERRIDE; + virtual blink::WebPluginContainer* GetContainer() OVERRIDE; + virtual v8::Isolate* GetIsolate() const OVERRIDE; virtual ppapi::VarTracker* GetVarTracker() OVERRIDE; virtual const GURL& GetPluginURL() OVERRIDE; virtual base::FilePath GetModulePath() OVERRIDE; @@ -366,6 +369,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl bool from_user_action) OVERRIDE; virtual int MakePendingFileRefRendererHost( const base::FilePath& path) OVERRIDE; + virtual void SetEmbedProperty(PP_Var key, PP_Var value) OVERRIDE; // PPB_Instance_API implementation. virtual PP_Bool BindGraphics(PP_Instance instance, @@ -442,19 +446,20 @@ class CONTENT_EXPORT PepperPluginInstanceImpl PP_URLComponents_Dev* components) OVERRIDE; // PPB_ContentDecryptor_Private implementation. - virtual void KeyAdded(PP_Instance instance, - PP_Var key_system, - PP_Var session_id) OVERRIDE; - virtual void KeyMessage(PP_Instance instance, - PP_Var key_system, - PP_Var session_id, - PP_Var message, - PP_Var default_url) OVERRIDE; - virtual void KeyError(PP_Instance instance, - PP_Var key_system, - PP_Var session_id, - int32_t media_error, - int32_t system_code) OVERRIDE; + virtual void SessionCreated(PP_Instance instance, + uint32_t session_id, + PP_Var web_session_id_var) OVERRIDE; + virtual void SessionMessage(PP_Instance instance, + uint32_t session_id, + PP_Var message, + PP_Var destination_url) OVERRIDE; + virtual void SessionReady(PP_Instance instance, uint32_t session_id) OVERRIDE; + virtual void SessionClosed(PP_Instance instance, + uint32_t session_id) OVERRIDE; + virtual void SessionError(PP_Instance instance, + uint32_t session_id, + int32_t media_error, + int32_t system_code) OVERRIDE; virtual void DeliverBlock(PP_Instance instance, PP_Resource decrypted_block, const PP_DecryptedBlockInfo* block_info) OVERRIDE; @@ -471,9 +476,10 @@ class CONTENT_EXPORT PepperPluginInstanceImpl virtual void DeliverFrame(PP_Instance instance, PP_Resource decrypted_frame, const PP_DecryptedFrameInfo* frame_info) OVERRIDE; - virtual void DeliverSamples(PP_Instance instance, - PP_Resource audio_frames, - const PP_DecryptedBlockInfo* block_info) OVERRIDE; + virtual void DeliverSamples( + PP_Instance instance, + PP_Resource audio_frames, + const PP_DecryptedSampleInfo* sample_info) OVERRIDE; // Reset this instance as proxied. Assigns the instance a new module, resets // cached interfaces to point to the out-of-process proxy and re-sends @@ -493,13 +499,8 @@ class CONTENT_EXPORT PepperPluginInstanceImpl // itself when making NPObject scripting calls to WebBindings. struct _NPP* instanceNPP(); - // Returns the v8::Isolate that was current when this Instance was created. - // This is not inlined so as to avoid an unnecessary header include of v8.h. - v8::Isolate* GetIsolate() const; - // cc::TextureLayerClient implementation. virtual unsigned PrepareTexture() OVERRIDE; - virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE; virtual bool PrepareTextureMailbox( cc::TextureMailbox* mailbox, scoped_ptr<cc::SingleReleaseCallback>* release_callback, @@ -514,27 +515,27 @@ class CONTENT_EXPORT PepperPluginInstanceImpl // Class to record document load notifications and play them back once the // real document loader becomes available. Used only by external instances. - class ExternalDocumentLoader : public WebKit::WebURLLoaderClient { + class ExternalDocumentLoader : public blink::WebURLLoaderClient { public: ExternalDocumentLoader(); virtual ~ExternalDocumentLoader(); void ReplayReceivedData(WebURLLoaderClient* document_loader); - // WebKit::WebURLLoaderClient implementation. - virtual void didReceiveData(WebKit::WebURLLoader* loader, + // blink::WebURLLoaderClient implementation. + virtual void didReceiveData(blink::WebURLLoader* loader, const char* data, int data_length, int encoded_data_length); - virtual void didFinishLoading(WebKit::WebURLLoader* loader, + virtual void didFinishLoading(blink::WebURLLoader* loader, double finish_time); - virtual void didFail(WebKit::WebURLLoader* loader, - const WebKit::WebURLError& error); + virtual void didFail(blink::WebURLLoader* loader, + const blink::WebURLError& error); private: std::list<std::string> data_; bool finished_loading_; - scoped_ptr<WebKit::WebURLError> error_; + scoped_ptr<blink::WebURLError> error_; }; // Implements PPB_Gamepad_API. This is just to avoid having an excessive @@ -555,10 +556,10 @@ class CONTENT_EXPORT PepperPluginInstanceImpl // objects. This constructor is private so that we can hide the // PPP_Instance_Combined details while still having 1 constructor to maintain // for member initialization. - PepperPluginInstanceImpl(RenderViewImpl* render_view, + PepperPluginInstanceImpl(RenderFrameImpl* render_frame, PluginModule* module, ppapi::PPP_Instance_Combined* instance_interface, - WebKit::WebPluginContainer* container, + blink::WebPluginContainer* container, const GURL& plugin_url); bool LoadFindInterface(); @@ -594,12 +595,12 @@ class CONTENT_EXPORT PepperPluginInstanceImpl // best format to use. Returns false if the plugin does not support any // print format that we can handle (we can handle only PDF). bool GetPreferredPrintOutputFormat(PP_PrintOutputFormat_Dev* format); - bool PrintPDFOutput(PP_Resource print_output, WebKit::WebCanvas* canvas); + bool PrintPDFOutput(PP_Resource print_output, blink::WebCanvas* canvas); // Updates the layer for compositing. This creates a layer and attaches to the // container if: - // - we have a bound Graphics3D - // - the Graphics3D has a texture + // - we have a bound Graphics3D and the Graphics3D has a texture, OR + // we have a bound Graphics2D and are using software compositing // - we are not in Flash full-screen mode (or transitioning to it) // Otherwise it destroys the layer. // It does either operation lazily. @@ -608,9 +609,9 @@ class CONTENT_EXPORT PepperPluginInstanceImpl // Internal helper function for PrintPage(). bool PrintPageHelper(PP_PrintPageNumberRange_Dev* page_ranges, int num_ranges, - WebKit::WebCanvas* canvas); + blink::WebCanvas* canvas); - void DoSetCursor(WebKit::WebCursorInfo* cursor); + void DoSetCursor(blink::WebCursorInfo* cursor); // Internal helper functions for HandleCompositionXXX(). bool SendCompositionEventToPlugin( @@ -619,7 +620,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl bool SendCompositionEventWithUnderlineInformationToPlugin( PP_InputEvent_Type type, const base::string16& text, - const std::vector<WebKit::WebCompositionUnderline>& underlines, + const std::vector<blink::WebCompositionUnderline>& underlines, int selection_start, int selection_end); @@ -647,11 +648,11 @@ class CONTENT_EXPORT PepperPluginInstanceImpl void UnSetAndDeleteLockTargetAdapter(); void DidDataFromWebURLResponse( - const WebKit::WebURLResponse& response, + const blink::WebURLResponse& response, int pending_host_id, const ppapi::URLResponseInfoData& data); - RenderViewImpl* render_view_; + RenderFrameImpl* render_frame_; scoped_refptr<PluginModule> module_; scoped_ptr<ppapi::PPP_Instance_Combined> instance_interface_; // If this is the NaCl plugin, we create a new module when we switch to the @@ -663,9 +664,9 @@ class CONTENT_EXPORT PepperPluginInstanceImpl PP_Instance pp_instance_; // NULL until we have been initialized. - WebKit::WebPluginContainer* container_; + blink::WebPluginContainer* container_; scoped_refptr<cc::TextureLayer> texture_layer_; - scoped_ptr<WebKit::WebLayer> web_layer_; + scoped_ptr<blink::WebLayer> web_layer_; bool layer_bound_to_fullscreen_; bool layer_is_hardware_; @@ -687,13 +688,6 @@ class CONTENT_EXPORT PepperPluginInstanceImpl // same as the default values. bool sent_initial_did_change_view_; - // We use a weak ptr factory for scheduling DidChangeView events so that we - // can tell whether updates are pending and consolidate them. When there's - // already a weak ptr pending (HasWeakPtrs is true), code should update the - // view_data_ but not send updates. This also allows us to cancel scheduled - // view change events. - base::WeakPtrFactory<PepperPluginInstanceImpl> view_change_weak_ptr_factory_; - // The current device context for painting in 2D and 3D. scoped_refptr<PPB_Graphics3D_Impl> bound_graphics_3d_; PepperGraphics2DHost* bound_graphics_2d_platform_; @@ -748,7 +742,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl // to generate the entire PDF given the variables below: // // The most recently used WebCanvas, guaranteed to be valid. - skia::RefPtr<WebKit::WebCanvas> canvas_; + skia::RefPtr<blink::WebCanvas> canvas_; // An array of page ranges. std::vector<PP_PrintPageNumberRange_Dev> ranges_; @@ -761,7 +755,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl const PPP_Graphics3D* plugin_graphics_3d_interface_; // Contains the cursor if it's set by the plugin. - scoped_ptr<WebKit::WebCursorInfo> cursor_; + scoped_ptr<blink::WebCursorInfo> cursor_; // Set to true if this plugin thinks it will always be on top. This allows us // to use a more optimized painting path in some cases. @@ -794,10 +788,10 @@ class CONTENT_EXPORT PepperPluginInstanceImpl // WebKit does not resize the plugin when going into fullscreen mode, so we do // this here by modifying the various plugin attributes and then restoring // them on exit. - WebKit::WebString width_before_fullscreen_; - WebKit::WebString height_before_fullscreen_; - WebKit::WebString border_before_fullscreen_; - WebKit::WebString style_before_fullscreen_; + blink::WebString width_before_fullscreen_; + blink::WebString height_before_fullscreen_; + blink::WebString border_before_fullscreen_; + blink::WebString style_before_fullscreen_; gfx::Size screen_size_for_fullscreen_; // The MessageChannel used to implement bidirectional postMessage for the @@ -831,7 +825,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl // Track pending user gestures so out-of-process plugins can respond to // a user gesture after it has been processed. PP_TimeTicks pending_user_gesture_; - WebKit::WebUserGestureToken pending_user_gesture_token_; + blink::WebUserGestureToken pending_user_gesture_token_; // We store the arguments so we can re-send them if we are reset to talk to // NaCl via the IPC NaCl proxy. @@ -839,9 +833,9 @@ class CONTENT_EXPORT PepperPluginInstanceImpl std::vector<std::string> argv_; // Non-owning pointer to the document loader, if any. - WebKit::WebURLLoaderClient* document_loader_; + blink::WebURLLoaderClient* document_loader_; // State for deferring document loads. Used only by external instances. - WebKit::WebURLResponse external_document_response_; + blink::WebURLResponse external_document_response_; scoped_ptr<ExternalDocumentLoader> external_document_loader_; bool external_document_load_; @@ -859,6 +853,16 @@ class CONTENT_EXPORT PepperPluginInstanceImpl scoped_ptr<MouseLockDispatcher::LockTarget> lock_target_; + bool is_deleted_; + + // We use a weak ptr factory for scheduling DidChangeView events so that we + // can tell whether updates are pending and consolidate them. When there's + // already a weak ptr pending (HasWeakPtrs is true), code should update the + // view_data_ but not send updates. This also allows us to cancel scheduled + // view change events. + base::WeakPtrFactory<PepperPluginInstanceImpl> view_change_weak_ptr_factory_; + base::WeakPtrFactory<PepperPluginInstanceImpl> weak_factory_; + friend class PpapiPluginInstanceTest; DISALLOW_COPY_AND_ASSIGN(PepperPluginInstanceImpl); }; diff --git a/chromium/content/renderer/pepper/pepper_plugin_registry.cc b/chromium/content/renderer/pepper/pepper_plugin_registry.cc index a5ae34643c4..5939ce16d23 100644 --- a/chromium/content/renderer/pepper/pepper_plugin_registry.cc +++ b/chromium/content/renderer/pepper/pepper_plugin_registry.cc @@ -6,6 +6,7 @@ #include "base/logging.h" #include "content/common/pepper_plugin_list.h" +#include "content/renderer/pepper/pepper_plugin_instance_impl.h" #include "content/renderer/pepper/plugin_module.h" #include "ppapi/shared_impl/ppapi_permissions.h" @@ -16,8 +17,10 @@ PepperPluginRegistry* PepperPluginRegistry::GetInstance() { static PepperPluginRegistry* registry = NULL; // This object leaks. It is a temporary hack to work around a crash. // http://code.google.com/p/chromium/issues/detail?id=63234 - if (!registry) + if (!registry) { registry = new PepperPluginRegistry; + registry->Initialize(); + } return registry; } @@ -41,10 +44,29 @@ const PepperPluginInfo* PepperPluginRegistry::GetInfoForPlugin( } PluginModule* PepperPluginRegistry::GetLiveModule(const base::FilePath& path) { - NonOwningModuleMap::iterator it = live_modules_.find(path); - if (it == live_modules_.end()) + NonOwningModuleMap::iterator module_iter = live_modules_.find(path); + if (module_iter == live_modules_.end()) return NULL; - return it->second; + + // Check the instances for the module to see if they've all been Delete()d. + // We don't want to return a PluginModule in that case, since the plugin may + // have exited already. + const PluginModule::PluginInstanceSet& instance_set = + module_iter->second->GetAllInstances(); + + // If instance_set is empty, InstanceCreated() hasn't been called yet, so + // it's safe to return the PluginModule. + if (instance_set.empty()) + return module_iter->second; + + PluginModule::PluginInstanceSet::const_iterator instance_iter = + instance_set.begin(); + while (instance_iter != instance_set.end()) { + if (!(*instance_iter)->is_deleted()) + return module_iter->second; + ++instance_iter; + } + return NULL; } void PepperPluginRegistry::AddLiveModule(const base::FilePath& path, @@ -79,6 +101,9 @@ PepperPluginRegistry::~PepperPluginRegistry() { } PepperPluginRegistry::PepperPluginRegistry() { +} + +void PepperPluginRegistry::Initialize() { ComputePepperPluginList(&plugin_list_); // Note that in each case, AddLiveModule must be called before completing diff --git a/chromium/content/renderer/pepper/pepper_plugin_registry.h b/chromium/content/renderer/pepper/pepper_plugin_registry.h index 7bd6ff9f62c..83319a9be68 100644 --- a/chromium/content/renderer/pepper/pepper_plugin_registry.h +++ b/chromium/content/renderer/pepper/pepper_plugin_registry.h @@ -47,6 +47,7 @@ class PepperPluginRegistry { private: PepperPluginRegistry(); + void Initialize(); // All known pepper plugins. std::vector<PepperPluginInfo> plugin_list_; diff --git a/chromium/content/renderer/pepper/pepper_truetype_font_win.cc b/chromium/content/renderer/pepper/pepper_truetype_font_win.cc index e515bd18671..6d040445dd8 100644 --- a/chromium/content/renderer/pepper/pepper_truetype_font_win.cc +++ b/chromium/content/renderer/pepper/pepper_truetype_font_win.cc @@ -223,11 +223,15 @@ int32_t PepperTrueTypeFontWin::GetTable(uint32_t table_tag, DWORD safe_length = std::min(table_size - safe_offset, static_cast<DWORD>(max_data_length)); data->resize(safe_length); - table_size = GetFontData(hdc, table_tag, safe_offset, - reinterpret_cast<uint8_t*>(&(*data)[0]), - safe_length); - if (table_size == GDI_ERROR) - return PP_ERROR_FAILED; + if (safe_length == 0) { + table_size = 0; + } else { + table_size = GetFontData(hdc, table_tag, safe_offset, + reinterpret_cast<uint8_t*>(&(*data)[0]), + safe_length); + if (table_size == GDI_ERROR) + return PP_ERROR_FAILED; + } return static_cast<int32_t>(table_size); } diff --git a/chromium/content/renderer/pepper/pepper_url_loader_host.cc b/chromium/content/renderer/pepper/pepper_url_loader_host.cc index 3f0dbc963e0..178548ee718 100644 --- a/chromium/content/renderer/pepper/pepper_url_loader_host.cc +++ b/chromium/content/renderer/pepper/pepper_url_loader_host.cc @@ -27,14 +27,14 @@ #include "third_party/WebKit/public/web/WebSecurityOrigin.h" #include "third_party/WebKit/public/web/WebURLLoaderOptions.h" -using WebKit::WebFrame; -using WebKit::WebString; -using WebKit::WebURL; -using WebKit::WebURLError; -using WebKit::WebURLLoader; -using WebKit::WebURLLoaderOptions; -using WebKit::WebURLRequest; -using WebKit::WebURLResponse; +using blink::WebFrame; +using blink::WebString; +using blink::WebURL; +using blink::WebURLError; +using blink::WebURLLoader; +using blink::WebURLLoaderOptions; +using blink::WebURLRequest; +using blink::WebURLResponse; #ifdef _MSC_VER // Do not warn about use of std::copy with raw pointers. @@ -98,7 +98,7 @@ PepperURLLoaderHost::~PepperURLLoaderHost() { // re-entering the scoped_ptr destructor with the same scoped_ptr object // via loader_.reset(). Be sure that loader_ is first NULL then destroy // the scoped_ptr. See http://crbug.com/159429. - scoped_ptr<WebKit::WebURLLoader> for_destruction_only(loader_.release()); + scoped_ptr<blink::WebURLLoader> for_destruction_only(loader_.release()); } int32_t PepperURLLoaderHost::OnResourceMessageReceived( @@ -367,7 +367,7 @@ void PepperURLLoaderHost::Close() { GetFrame()->stopLoading(); } -WebKit::WebFrame* PepperURLLoaderHost::GetFrame() { +blink::WebFrame* PepperURLLoaderHost::GetFrame() { PepperPluginInstance* instance_object = renderer_ppapi_host_->GetPluginInstance(pp_instance()); if (!instance_object) diff --git a/chromium/content/renderer/pepper/pepper_url_loader_host.h b/chromium/content/renderer/pepper/pepper_url_loader_host.h index e515174eb40..2790c785c74 100644 --- a/chromium/content/renderer/pepper/pepper_url_loader_host.h +++ b/chromium/content/renderer/pepper/pepper_url_loader_host.h @@ -16,7 +16,7 @@ #include "ppapi/shared_impl/url_response_info_data.h" #include "third_party/WebKit/public/platform/WebURLLoaderClient.h" -namespace WebKit { +namespace blink { class WebFrame; class WebURLLoader; } @@ -27,7 +27,7 @@ class RendererPpapiHostImpl; class PepperURLLoaderHost : public ppapi::host::ResourceHost, - public WebKit::WebURLLoaderClient { + public blink::WebURLLoaderClient { public: // If main_document_loader is true, PP_Resource must be 0 since it will be // pending until the plugin resource attaches to it. @@ -42,26 +42,26 @@ class PepperURLLoaderHost const IPC::Message& msg, ppapi::host::HostMessageContext* context) OVERRIDE; - // WebKit::WebURLLoaderClient implementation. - virtual void willSendRequest(WebKit::WebURLLoader* loader, - WebKit::WebURLRequest& new_request, - const WebKit::WebURLResponse& redir_response); - virtual void didSendData(WebKit::WebURLLoader* loader, + // blink::WebURLLoaderClient implementation. + virtual void willSendRequest(blink::WebURLLoader* loader, + blink::WebURLRequest& new_request, + const blink::WebURLResponse& redir_response); + virtual void didSendData(blink::WebURLLoader* loader, unsigned long long bytes_sent, unsigned long long total_bytes_to_be_sent); - virtual void didReceiveResponse(WebKit::WebURLLoader* loader, - const WebKit::WebURLResponse& response); - virtual void didDownloadData(WebKit::WebURLLoader* loader, + virtual void didReceiveResponse(blink::WebURLLoader* loader, + const blink::WebURLResponse& response); + virtual void didDownloadData(blink::WebURLLoader* loader, int data_length, int encoded_data_length); - virtual void didReceiveData(WebKit::WebURLLoader* loader, + virtual void didReceiveData(blink::WebURLLoader* loader, const char* data, int data_length, int encoded_data_length); - virtual void didFinishLoading(WebKit::WebURLLoader* loader, + virtual void didFinishLoading(blink::WebURLLoader* loader, double finish_time); - virtual void didFail(WebKit::WebURLLoader* loader, - const WebKit::WebURLError& error); + virtual void didFail(blink::WebURLLoader* loader, + const blink::WebURLError& error); private: // ResourceHost protected overrides. @@ -96,14 +96,14 @@ class PepperURLLoaderHost void Close(); // Returns the frame for the current request. - WebKit::WebFrame* GetFrame(); + blink::WebFrame* GetFrame(); // Calls SetDefersLoading on the current load. This encapsulates the logic // differences between document loads and regular ones. void SetDefersLoading(bool defers_loading); // Converts a WebURLResponse to a URLResponseInfo and saves it. - void SaveResponse(const WebKit::WebURLResponse& response); + void SaveResponse(const blink::WebURLResponse& response); void DidDataFromWebURLResponse(const ppapi::URLResponseInfoData& data); // Sends the UpdateProgress message (if necessary) to the plugin. @@ -129,7 +129,7 @@ class PepperURLLoaderHost // always NULL check this value before using it. In the case of a main // document load, you would call the functions on the document to cancel the // load, etc. since there is no loader. - scoped_ptr<WebKit::WebURLLoader> loader_; + scoped_ptr<blink::WebURLLoader> loader_; int64_t bytes_sent_; int64_t total_bytes_to_be_sent_; diff --git a/chromium/content/renderer/pepper/pepper_url_request_unittest.cc b/chromium/content/renderer/pepper/pepper_url_request_unittest.cc index 00a2c6bc349..4f171ff0a7a 100644 --- a/chromium/content/renderer/pepper/pepper_url_request_unittest.cc +++ b/chromium/content/renderer/pepper/pepper_url_request_unittest.cc @@ -24,13 +24,13 @@ // test it by making sure the conversion routines actually work at the same // time. -using WebKit::WebCString; -using WebKit::WebFrame; -using WebKit::WebFrameClient; -using WebKit::WebString; -using WebKit::WebView; -using WebKit::WebURL; -using WebKit::WebURLRequest; +using blink::WebCString; +using blink::WebFrame; +using blink::WebFrameClient; +using blink::WebString; +using blink::WebView; +using blink::WebURL; +using blink::WebURLRequest; namespace { diff --git a/chromium/content/renderer/pepper/pepper_video_capture_host.cc b/chromium/content/renderer/pepper/pepper_video_capture_host.cc index cf06bcaf1d0..732842402d6 100644 --- a/chromium/content/renderer/pepper/pepper_video_capture_host.cc +++ b/chromium/content/renderer/pepper/pepper_video_capture_host.cc @@ -17,9 +17,6 @@ #include "ppapi/shared_impl/host_resource.h" #include "ppapi/thunk/enter.h" #include "ppapi/thunk/ppb_buffer_api.h" -#include "third_party/WebKit/public/web/WebDocument.h" -#include "third_party/WebKit/public/web/WebElement.h" -#include "third_party/WebKit/public/web/WebPluginContainer.h" using ppapi::HostResource; using ppapi::TrackedCallback; @@ -46,7 +43,8 @@ PepperVideoCaptureHost::PepperVideoCaptureHost(RendererPpapiHostImpl* host, this, PepperMediaDeviceManager::GetForRenderView( host->GetRenderViewForInstance(pp_instance())), - PP_DEVICETYPE_DEV_VIDEOCAPTURE) { + PP_DEVICETYPE_DEV_VIDEOCAPTURE, + host->GetDocumentURL(instance)) { } PepperVideoCaptureHost::~PepperVideoCaptureHost() { @@ -118,6 +116,10 @@ void PepperVideoCaptureHost::OnError(media::VideoCapture* capture, int error_code) { // Today, the media layer only sends "1" as an error. DCHECK(error_code == 1); + PostErrorReply(); +} + +void PepperVideoCaptureHost::PostErrorReply() { // It either comes because some error was detected while starting (e.g. 2 // conflicting "master" resolution), or because the browser failed to start // the capture. @@ -133,6 +135,12 @@ void PepperVideoCaptureHost::OnFrameReady( media::VideoCapture* capture, const scoped_refptr<media::VideoFrame>& frame) { DCHECK(frame.get()); + + if (alloc_size_ != frame->coded_size()) { + AllocBuffers(frame->coded_size(), capture->CaptureFrameRate()); + alloc_size_ = frame->coded_size(); + } + for (uint32_t i = 0; i < buffers_.size(); ++i) { if (!buffers_[i].in_use) { DCHECK_EQ(frame->format(), media::VideoFrame::I420); @@ -165,13 +173,13 @@ void PepperVideoCaptureHost::OnFrameReady( } } -void PepperVideoCaptureHost::OnDeviceInfoReceived( - media::VideoCapture* capture, - const media::VideoCaptureParams& device_info) { +void PepperVideoCaptureHost::AllocBuffers( + const gfx::Size& resolution, + int frame_rate) { PP_VideoCaptureDeviceInfo_Dev info = { - static_cast<uint32_t>(device_info.width), - static_cast<uint32_t>(device_info.height), - static_cast<uint32_t>(device_info.frame_rate) + static_cast<uint32_t>(resolution.width()), + static_cast<uint32_t>(resolution.height()), + static_cast<uint32_t>(frame_rate) }; ReleaseBuffers(); @@ -246,7 +254,7 @@ void PepperVideoCaptureHost::OnDeviceInfoReceived( // capture. SetStatus(PP_VIDEO_CAPTURE_STATUS_STOPPING, true); platform_video_capture_->StopCapture(this); - OnError(capture, PP_ERROR_NOMEMORY); + PostErrorReply(); return; } @@ -265,9 +273,8 @@ int32_t PepperVideoCaptureHost::OnOpen( SetRequestedInfo(requested_info, buffer_count); - PepperPluginInstance* instance = - renderer_ppapi_host_->GetPluginInstance(pp_instance()); - if (!instance) + GURL document_url = renderer_ppapi_host_->GetDocumentURL(pp_instance()); + if (!document_url.is_valid()) return PP_ERROR_FAILED; RenderViewImpl* render_view = static_cast<RenderViewImpl*>( @@ -275,7 +282,7 @@ int32_t PepperVideoCaptureHost::OnOpen( platform_video_capture_ = new PepperPlatformVideoCapture( render_view->AsWeakPtr(), device_id, - instance->GetContainer()->element().document().url(), this); + document_url, this); open_reply_context_ = context->MakeReplyMessageContext(); @@ -292,7 +299,7 @@ int32_t PepperVideoCaptureHost::OnStartCapture( // It's safe to call this regardless it's capturing or not, because // PepperPlatformVideoCapture maintains the state. - platform_video_capture_->StartCapture(this, capability_); + platform_video_capture_->StartCapture(this, video_capture_params_); return PP_OK; } @@ -358,12 +365,11 @@ void PepperVideoCaptureHost::SetRequestedInfo( // Clamp the buffer count to between 1 and |kMaxBuffers|. buffer_count_hint_ = std::min(std::max(buffer_count, 1U), kMaxBuffers); - capability_.width = device_info.width; - capability_.height = device_info.height; - capability_.frame_rate = device_info.frames_per_second; - capability_.expected_capture_delay = 0; // Ignored. - capability_.color = media::PIXEL_FORMAT_I420; - capability_.interlaced = false; // Ignored. + video_capture_params_.requested_format = media::VideoCaptureFormat( + gfx::Size(device_info.width, device_info.height), + device_info.frames_per_second, + media::PIXEL_FORMAT_I420); + video_capture_params_.allow_resolution_change = false; } void PepperVideoCaptureHost::DetachPlatformVideoCapture() { diff --git a/chromium/content/renderer/pepper/pepper_video_capture_host.h b/chromium/content/renderer/pepper/pepper_video_capture_host.h index ab6a3046a2d..a8312a2f5a8 100644 --- a/chromium/content/renderer/pepper/pepper_video_capture_host.h +++ b/chromium/content/renderer/pepper/pepper_video_capture_host.h @@ -47,9 +47,6 @@ class PepperVideoCaptureHost virtual void OnFrameReady( media::VideoCapture* capture, const scoped_refptr<media::VideoFrame>& frame) OVERRIDE; - virtual void OnDeviceInfoReceived( - media::VideoCapture* capture, - const media::VideoCaptureParams& device_info) OVERRIDE; private: int32_t OnOpen(ppapi::host::HostMessageContext* context, @@ -64,6 +61,9 @@ class PepperVideoCaptureHost int32_t StopCapture(); int32_t Close(); + void PostErrorReply(); + void AllocBuffers(const gfx::Size& resolution, + int frame_rate); void ReleaseBuffers(); void SendStatus(); @@ -88,10 +88,11 @@ class PepperVideoCaptureHost RendererPpapiHostImpl* renderer_ppapi_host_; + gfx::Size alloc_size_; std::vector<BufferInfo> buffers_; size_t buffer_count_hint_; - media::VideoCaptureCapability capability_; + media::VideoCaptureParams video_capture_params_; PP_VideoCaptureStatus_Dev status_; diff --git a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc index acbe8388353..129ee455222 100644 --- a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc +++ b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc @@ -32,23 +32,24 @@ #include "url/gurl.h" using ppapi::NPObjectVar; -using WebKit::WebCanvas; -using WebKit::WebPlugin; -using WebKit::WebPluginContainer; -using WebKit::WebPluginParams; -using WebKit::WebPoint; -using WebKit::WebPrintParams; -using WebKit::WebRect; -using WebKit::WebSize; -using WebKit::WebString; -using WebKit::WebURL; -using WebKit::WebVector; +using blink::WebCanvas; +using blink::WebPlugin; +using blink::WebPluginContainer; +using blink::WebPluginParams; +using blink::WebPoint; +using blink::WebPrintParams; +using blink::WebRect; +using blink::WebSize; +using blink::WebString; +using blink::WebURL; +using blink::WebVector; namespace content { struct PepperWebPluginImpl::InitData { scoped_refptr<PluginModule> module; base::WeakPtr<RenderViewImpl> render_view; + RenderFrame* render_frame; std::vector<std::string> arg_names; std::vector<std::string> arg_values; GURL url; @@ -57,7 +58,8 @@ struct PepperWebPluginImpl::InitData { PepperWebPluginImpl::PepperWebPluginImpl( PluginModule* plugin_module, const WebPluginParams& params, - const base::WeakPtr<RenderViewImpl>& render_view) + const base::WeakPtr<RenderViewImpl>& render_view, + RenderFrame* render_frame) : init_data_(new InitData()), full_frame_(params.loadManually), instance_object_(PP_MakeUndefined()), @@ -65,6 +67,7 @@ PepperWebPluginImpl::PepperWebPluginImpl( DCHECK(plugin_module); init_data_->module = plugin_module; init_data_->render_view = render_view; + init_data_->render_frame = render_frame; for (size_t i = 0; i < params.attributeNames.size(); ++i) { init_data_->arg_names.push_back(params.attributeNames[i].utf8()); init_data_->arg_values.push_back(params.attributeValues[i].utf8()); @@ -78,14 +81,14 @@ PepperWebPluginImpl::PepperWebPluginImpl( PepperWebPluginImpl::~PepperWebPluginImpl() { } -WebKit::WebPluginContainer* PepperWebPluginImpl::container() const { +blink::WebPluginContainer* PepperWebPluginImpl::container() const { return container_; } bool PepperWebPluginImpl::initialize(WebPluginContainer* container) { // The plugin delegate may have gone away. instance_ = init_data_->module->CreateInstance( - init_data_->render_view.get(), container, init_data_->url); + init_data_->render_view->main_render_frame(), container, init_data_->url); if (!instance_.get()) return false; @@ -99,9 +102,9 @@ bool PepperWebPluginImpl::initialize(WebPluginContainer* container) { instance_->Delete(); instance_ = NULL; - WebKit::WebPlugin* replacement_plugin = + blink::WebPlugin* replacement_plugin = GetContentClient()->renderer()->CreatePluginReplacement( - init_data_->render_view.get(), init_data_->module->path()); + init_data_->render_frame, init_data_->module->path()); if (!replacement_plugin || !replacement_plugin->initialize(container)) return false; @@ -147,7 +150,7 @@ NPObject* PepperWebPluginImpl::scriptableObject() { } NPObject* message_channel_np_object(instance_->message_channel().np_object()); // The object is expected to be retained before it is returned. - WebKit::WebBindings::retainObject(message_channel_np_object); + blink::WebBindings::retainObject(message_channel_np_object); return message_channel_np_object; } @@ -189,46 +192,46 @@ bool PepperWebPluginImpl::acceptsInputEvents() { return true; } -bool PepperWebPluginImpl::handleInputEvent(const WebKit::WebInputEvent& event, - WebKit::WebCursorInfo& cursor_info) { +bool PepperWebPluginImpl::handleInputEvent(const blink::WebInputEvent& event, + blink::WebCursorInfo& cursor_info) { if (instance_->FlashIsFullscreenOrPending()) return false; return instance_->HandleInputEvent(event, &cursor_info); } void PepperWebPluginImpl::didReceiveResponse( - const WebKit::WebURLResponse& response) { + const blink::WebURLResponse& response) { DCHECK(!instance_->document_loader()); instance_->HandleDocumentLoad(response); } void PepperWebPluginImpl::didReceiveData(const char* data, int data_length) { - WebKit::WebURLLoaderClient* document_loader = instance_->document_loader(); + blink::WebURLLoaderClient* document_loader = instance_->document_loader(); if (document_loader) document_loader->didReceiveData(NULL, data, data_length, 0); } void PepperWebPluginImpl::didFinishLoading() { - WebKit::WebURLLoaderClient* document_loader = instance_->document_loader(); + blink::WebURLLoaderClient* document_loader = instance_->document_loader(); if (document_loader) document_loader->didFinishLoading(NULL, 0.0); } -void PepperWebPluginImpl::didFailLoading(const WebKit::WebURLError& error) { - WebKit::WebURLLoaderClient* document_loader = instance_->document_loader(); +void PepperWebPluginImpl::didFailLoading(const blink::WebURLError& error) { + blink::WebURLLoaderClient* document_loader = instance_->document_loader(); if (document_loader) document_loader->didFail(NULL, error); } void PepperWebPluginImpl::didFinishLoadingFrameRequest( - const WebKit::WebURL& url, + const blink::WebURL& url, void* notify_data) { } void PepperWebPluginImpl::didFailLoadingFrameRequest( - const WebKit::WebURL& url, + const blink::WebURL& url, void* notify_data, - const WebKit::WebURLError& error) { + const blink::WebURLError& error) { } bool PepperWebPluginImpl::hasSelection() const { @@ -251,7 +254,7 @@ void PepperWebPluginImpl::setZoomLevel(double level, bool text_only) { instance_->Zoom(content::ZoomLevelToZoomFactor(level), text_only); } -bool PepperWebPluginImpl::startFind(const WebKit::WebString& search_text, +bool PepperWebPluginImpl::startFind(const blink::WebString& search_text, bool case_sensitive, int identifier) { return instance_->StartFind(search_text, case_sensitive, identifier); @@ -278,7 +281,7 @@ int PepperWebPluginImpl::printBegin(const WebPrintParams& print_params) { } bool PepperWebPluginImpl::printPage(int page_number, - WebKit::WebCanvas* canvas) { + blink::WebCanvas* canvas) { return instance_->PrintPage(page_number, canvas); } diff --git a/chromium/content/renderer/pepper/pepper_webplugin_impl.h b/chromium/content/renderer/pepper/pepper_webplugin_impl.h index c96b44e33cb..600dd578d5b 100644 --- a/chromium/content/renderer/pepper/pepper_webplugin_impl.h +++ b/chromium/content/renderer/pepper/pepper_webplugin_impl.h @@ -17,7 +17,7 @@ struct _NPP; -namespace WebKit { +namespace blink { struct WebPluginParams; struct WebPrintParams; } @@ -27,49 +27,51 @@ namespace content { class PepperPluginInstanceImpl; class PluginModule; class PPB_URLLoader_Impl; +class RenderFrame; class RenderViewImpl; -class PepperWebPluginImpl : public WebKit::WebPlugin { +class PepperWebPluginImpl : public blink::WebPlugin { public: PepperWebPluginImpl(PluginModule* module, - const WebKit::WebPluginParams& params, - const base::WeakPtr<RenderViewImpl>& render_view); + const blink::WebPluginParams& params, + const base::WeakPtr<RenderViewImpl>& render_view, + RenderFrame* render_frame); PepperPluginInstanceImpl* instance() { return instance_.get(); } - // WebKit::WebPlugin implementation. - virtual WebKit::WebPluginContainer* container() const; - virtual bool initialize(WebKit::WebPluginContainer* container); + // blink::WebPlugin implementation. + virtual blink::WebPluginContainer* container() const; + virtual bool initialize(blink::WebPluginContainer* container); virtual void destroy(); virtual NPObject* scriptableObject(); virtual struct _NPP* pluginNPP(); - virtual bool getFormValue(WebKit::WebString& value); - virtual void paint(WebKit::WebCanvas* canvas, const WebKit::WebRect& rect); + virtual bool getFormValue(blink::WebString& value); + virtual void paint(blink::WebCanvas* canvas, const blink::WebRect& rect); virtual void updateGeometry( - const WebKit::WebRect& frame_rect, - const WebKit::WebRect& clip_rect, - const WebKit::WebVector<WebKit::WebRect>& cut_outs_rects, + const blink::WebRect& frame_rect, + const blink::WebRect& clip_rect, + const blink::WebVector<blink::WebRect>& cut_outs_rects, bool is_visible); virtual void updateFocus(bool focused); virtual void updateVisibility(bool visible); virtual bool acceptsInputEvents(); - virtual bool handleInputEvent(const WebKit::WebInputEvent& event, - WebKit::WebCursorInfo& cursor_info); - virtual void didReceiveResponse(const WebKit::WebURLResponse& response); + virtual bool handleInputEvent(const blink::WebInputEvent& event, + blink::WebCursorInfo& cursor_info); + virtual void didReceiveResponse(const blink::WebURLResponse& response); virtual void didReceiveData(const char* data, int data_length); virtual void didFinishLoading(); - virtual void didFailLoading(const WebKit::WebURLError&); - virtual void didFinishLoadingFrameRequest(const WebKit::WebURL& url, + virtual void didFailLoading(const blink::WebURLError&); + virtual void didFinishLoadingFrameRequest(const blink::WebURL& url, void* notify_data); - virtual void didFailLoadingFrameRequest(const WebKit::WebURL& url, + virtual void didFailLoadingFrameRequest(const blink::WebURL& url, void* notify_data, - const WebKit::WebURLError& error); + const blink::WebURLError& error); virtual bool hasSelection() const; - virtual WebKit::WebString selectionAsText() const; - virtual WebKit::WebString selectionAsMarkup() const; - virtual WebKit::WebURL linkAtPosition(const WebKit::WebPoint& position) const; + virtual blink::WebString selectionAsText() const; + virtual blink::WebString selectionAsMarkup() const; + virtual blink::WebURL linkAtPosition(const blink::WebPoint& position) const; virtual void setZoomLevel(double level, bool text_only); - virtual bool startFind(const WebKit::WebString& search_text, + virtual bool startFind(const blink::WebString& search_text, bool case_sensitive, int identifier); virtual void selectFindResult(bool forward); @@ -77,8 +79,8 @@ class PepperWebPluginImpl : public WebKit::WebPlugin { virtual bool supportsPaginatedPrint() OVERRIDE; virtual bool isPrintScalingDisabled() OVERRIDE; - virtual int printBegin(const WebKit::WebPrintParams& print_params) OVERRIDE; - virtual bool printPage(int page_number, WebKit::WebCanvas* canvas) OVERRIDE; + virtual int printBegin(const blink::WebPrintParams& print_params) OVERRIDE; + virtual bool printPage(int page_number, blink::WebCanvas* canvas) OVERRIDE; virtual void printEnd() OVERRIDE; virtual bool canRotateView() OVERRIDE; @@ -98,7 +100,7 @@ class PepperWebPluginImpl : public WebKit::WebPlugin { scoped_refptr<PepperPluginInstanceImpl> instance_; gfx::Rect plugin_rect_; PP_Var instance_object_; - WebKit::WebPluginContainer* container_; + blink::WebPluginContainer* container_; DISALLOW_COPY_AND_ASSIGN(PepperWebPluginImpl); }; diff --git a/chromium/content/renderer/pepper/pepper_websocket_host.cc b/chromium/content/renderer/pepper/pepper_websocket_host.cc index 78870ef21b0..a88fdb54e47 100644 --- a/chromium/content/renderer/pepper/pepper_websocket_host.cc +++ b/chromium/content/renderer/pepper/pepper_websocket_host.cc @@ -22,11 +22,11 @@ #include "third_party/WebKit/public/web/WebPluginContainer.h" #include "third_party/WebKit/public/web/WebSocket.h" -using WebKit::WebArrayBuffer; -using WebKit::WebDocument; -using WebKit::WebString; -using WebKit::WebSocket; -using WebKit::WebURL; +using blink::WebArrayBuffer; +using blink::WebDocument; +using blink::WebString; +using blink::WebSocket; +using blink::WebURL; namespace content { @@ -77,7 +77,7 @@ void PepperWebSocketHost::didConnect() { protocol)); } -void PepperWebSocketHost::didReceiveMessage(const WebKit::WebString& message) { +void PepperWebSocketHost::didReceiveMessage(const blink::WebString& message) { // Dispose packets after receiving an error. if (error_was_received_) return; @@ -90,7 +90,7 @@ void PepperWebSocketHost::didReceiveMessage(const WebKit::WebString& message) { } void PepperWebSocketHost::didReceiveArrayBuffer( - const WebKit::WebArrayBuffer& binaryData) { + const blink::WebArrayBuffer& binaryData) { // Dispose packets after receiving an error. if (error_was_received_) return; @@ -135,7 +135,7 @@ void PepperWebSocketHost::didStartClosingHandshake() { void PepperWebSocketHost::didClose(unsigned long unhandled_buffered_amount, ClosingHandshakeCompletionStatus status, unsigned short code, - const WebKit::WebString& reason) { + const blink::WebString& reason) { if (connecting_) { connecting_ = false; connect_reply_.params.set_result(PP_ERROR_FAILED); @@ -224,8 +224,8 @@ int32_t PepperWebSocketHost::OnHostMsgConnect( // Convert protocols to WebString. WebString web_protocols = WebString::fromUTF8(protocol_string); - // Create WebKit::WebSocket object and connect. - WebKit::WebPluginContainer* container = + // Create blink::WebSocket object and connect. + blink::WebPluginContainer* container = renderer_ppapi_host_->GetContainerForInstance(pp_instance()); if (!container) return PP_ERROR_BADARGUMENT; diff --git a/chromium/content/renderer/pepper/pepper_websocket_host.h b/chromium/content/renderer/pepper/pepper_websocket_host.h index 7c8d5b2a614..3447fcf91a7 100644 --- a/chromium/content/renderer/pepper/pepper_websocket_host.h +++ b/chromium/content/renderer/pepper/pepper_websocket_host.h @@ -27,7 +27,7 @@ class RendererPpapiHost; class CONTENT_EXPORT PepperWebSocketHost : public ppapi::host::ResourceHost, - public NON_EXPORTED_BASE(::WebKit::WebSocketClient) { + public NON_EXPORTED_BASE(::blink::WebSocketClient) { public: explicit PepperWebSocketHost(RendererPpapiHost* host, PP_Instance instance, @@ -40,15 +40,15 @@ class CONTENT_EXPORT PepperWebSocketHost // WebSocketClient implementation. virtual void didConnect(); - virtual void didReceiveMessage(const WebKit::WebString& message); - virtual void didReceiveArrayBuffer(const WebKit::WebArrayBuffer& binaryData); + virtual void didReceiveMessage(const blink::WebString& message); + virtual void didReceiveArrayBuffer(const blink::WebArrayBuffer& binaryData); virtual void didReceiveMessageError(); virtual void didUpdateBufferedAmount(unsigned long buffered_amount); virtual void didStartClosingHandshake(); virtual void didClose(unsigned long unhandled_buffered_amount, ClosingHandshakeCompletionStatus status, unsigned short code, - const WebKit::WebString& reason); + const blink::WebString& reason); private: // IPC message handlers. int32_t OnHostMsgConnect(ppapi::host::HostMessageContext* context, @@ -89,7 +89,7 @@ class CONTENT_EXPORT PepperWebSocketHost // Keeps the WebKit side WebSocket object. This is used for calling WebKit // side functions via WebKit API. - scoped_ptr<WebKit::WebSocket> websocket_; + scoped_ptr<blink::WebSocket> websocket_; DISALLOW_COPY_AND_ASSIGN(PepperWebSocketHost); }; diff --git a/chromium/content/renderer/pepper/plugin_module.cc b/chromium/content/renderer/pepper/plugin_module.cc index d8c193cbb9b..8ffc89e7adc 100644 --- a/chromium/content/renderer/pepper/plugin_module.cc +++ b/chromium/content/renderer/pepper/plugin_module.cc @@ -30,6 +30,7 @@ #include "content/renderer/pepper/ppb_video_decoder_impl.h" #include "content/renderer/pepper/renderer_ppapi_host_impl.h" #include "content/renderer/render_view_impl.h" +#include "ppapi/c/dev/ppb_alarms_dev.h" #include "ppapi/c/dev/ppb_audio_input_dev.h" #include "ppapi/c/dev/ppb_buffer_dev.h" #include "ppapi/c/dev/ppb_char_set_dev.h" @@ -46,18 +47,17 @@ #include "ppapi/c/dev/ppb_printing_dev.h" #include "ppapi/c/dev/ppb_resource_array_dev.h" #include "ppapi/c/dev/ppb_scrollbar_dev.h" -#include "ppapi/c/dev/ppb_testing_dev.h" #include "ppapi/c/dev/ppb_text_input_dev.h" #include "ppapi/c/dev/ppb_trace_event_dev.h" #include "ppapi/c/dev/ppb_truetype_font_dev.h" #include "ppapi/c/dev/ppb_url_util_dev.h" #include "ppapi/c/dev/ppb_var_deprecated.h" +#include "ppapi/c/dev/ppb_var_resource_dev.h" #include "ppapi/c/dev/ppb_video_capture_dev.h" #include "ppapi/c/dev/ppb_video_decoder_dev.h" #include "ppapi/c/dev/ppb_view_dev.h" #include "ppapi/c/dev/ppb_widget_dev.h" #include "ppapi/c/dev/ppb_zoom_dev.h" -#include "ppapi/c/extensions/dev/ppb_ext_alarms_dev.h" #include "ppapi/c/extensions/dev/ppb_ext_socket_dev.h" #include "ppapi/c/pp_module.h" #include "ppapi/c/pp_resource.h" @@ -111,11 +111,14 @@ #include "ppapi/c/private/ppb_flash_print.h" #include "ppapi/c/private/ppb_host_resolver_private.h" #include "ppapi/c/private/ppb_instance_private.h" +#include "ppapi/c/private/ppb_isolated_file_system_private.h" +#include "ppapi/c/private/ppb_output_protection_private.h" #include "ppapi/c/private/ppb_pdf.h" #include "ppapi/c/private/ppb_proxy_private.h" #include "ppapi/c/private/ppb_talk_private.h" #include "ppapi/c/private/ppb_tcp_server_socket_private.h" #include "ppapi/c/private/ppb_tcp_socket_private.h" +#include "ppapi/c/private/ppb_testing_private.h" #include "ppapi/c/private/ppb_udp_socket_private.h" #include "ppapi/c/private/ppb_uma_private.h" #include "ppapi/c/private/ppb_video_destination_private.h" @@ -125,7 +128,6 @@ #include "ppapi/c/trusted/ppb_browser_font_trusted.h" #include "ppapi/c/trusted/ppb_char_set_trusted.h" #include "ppapi/c/trusted/ppb_file_chooser_trusted.h" -#include "ppapi/c/trusted/ppb_file_io_trusted.h" #include "ppapi/c/trusted/ppb_url_loader_trusted.h" #include "ppapi/shared_impl/callback_tracker.h" #include "ppapi/shared_impl/ppapi_preferences.h" @@ -284,7 +286,7 @@ void SetMinimumArrayBufferSizeForShmem(PP_Instance /*instance*/, // Does nothing. Not needed in-process. } -const PPB_Testing_Dev testing_interface = { +const PPB_Testing_Private testing_interface = { &ReadImageData, &RunMessageLoop, &QuitMessageLoop, @@ -334,10 +336,8 @@ const void* InternalGetInterface(const char* name) { // in production code. if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnablePepperTesting)) { - if (strcmp(name, PPB_TESTING_DEV_INTERFACE) == 0 || - strcmp(name, PPB_TESTING_DEV_INTERFACE_0_9) == 0) { + if (strcmp(name, PPB_TESTING_PRIVATE_INTERFACE) == 0) return &testing_interface; - } } return NULL; } @@ -382,7 +382,7 @@ bool LoadEntryPointsFromLibrary( return true; } -void CreateHostForInProcessModule(RenderViewImpl* render_view, +void CreateHostForInProcessModule(RenderFrameImpl* render_frame, PluginModule* module, const WebPluginInfo& webplugin_info) { // First time an in-process plugin was used, make a host for it. @@ -394,9 +394,8 @@ void CreateHostForInProcessModule(RenderViewImpl* render_view, PepperPluginRegistry::GetInstance()->GetInfoForPlugin( webplugin_info)->permissions); RendererPpapiHostImpl* host_impl = - RendererPpapiHostImpl::CreateOnModuleForInProcess( - module, perms); - render_view->PepperPluginCreated(host_impl); + RendererPpapiHostImpl::CreateOnModuleForInProcess(module, perms); + render_frame->PepperPluginCreated(host_impl); } } // namespace @@ -551,11 +550,11 @@ bool PluginModule::SupportsInterface(const char* name) { } PepperPluginInstanceImpl* PluginModule::CreateInstance( - RenderViewImpl* render_view, - WebKit::WebPluginContainer* container, + RenderFrameImpl* render_frame, + blink::WebPluginContainer* container, const GURL& plugin_url) { PepperPluginInstanceImpl* instance = PepperPluginInstanceImpl::Create( - render_view, this, container, plugin_url); + render_frame, this, container, plugin_url); if (!instance) { LOG(WARNING) << "Plugin doesn't support instance interface, failing."; return NULL; @@ -630,7 +629,7 @@ PepperBroker* PluginModule::GetBroker() { } RendererPpapiHostImpl* PluginModule::CreateOutOfProcessModule( - RenderViewImpl* render_view, + RenderFrameImpl* render_frame, const base::FilePath& path, ppapi::PpapiPermissions permissions, const IPC::ChannelHandle& channel_handle, @@ -638,7 +637,7 @@ RendererPpapiHostImpl* PluginModule::CreateOutOfProcessModule( int plugin_child_id, bool is_external) { scoped_refptr<PepperHungPluginFilter> hung_filter(new PepperHungPluginFilter( - path, render_view->GetRoutingID(), plugin_child_id)); + path, render_frame->GetRoutingID(), plugin_child_id)); scoped_ptr<HostDispatcherWrapper> dispatcher( new HostDispatcherWrapper(this, peer_pid, @@ -648,14 +647,14 @@ RendererPpapiHostImpl* PluginModule::CreateOutOfProcessModule( if (!dispatcher->Init( channel_handle, &GetInterface, - ppapi::Preferences(render_view->webkit_preferences()), + ppapi::Preferences(render_frame->render_view()->webkit_preferences()), hung_filter.get())) return NULL; RendererPpapiHostImpl* host_impl = RendererPpapiHostImpl::CreateOnModuleForOutOfProcess( this, dispatcher->dispatcher(), permissions); - render_view->PepperPluginCreated(host_impl); + render_frame->PepperPluginCreated(host_impl); InitAsProxied(dispatcher.release()); return host_impl; @@ -680,7 +679,7 @@ bool PluginModule::InitializeModule( } scoped_refptr<PluginModule> PluginModule::Create( - RenderViewImpl* render_view, + RenderFrameImpl* render_frame, const WebPluginInfo& webplugin_info, bool* pepper_plugin_was_registered) { *pepper_plugin_was_registered = true; @@ -694,7 +693,7 @@ scoped_refptr<PluginModule> PluginModule::Create( // If the module exists and no embedder state was associated with it, // then the module was one of the ones preloaded and is an in-process // plugin. We need to associate our host state with it. - CreateHostForInProcessModule(render_view, module.get(), webplugin_info); + CreateHostForInProcessModule(render_frame, module.get(), webplugin_info); } return module; } @@ -719,7 +718,7 @@ scoped_refptr<PluginModule> PluginModule::Create( IPC::ChannelHandle channel_handle; base::ProcessId peer_pid; int plugin_child_id = 0; - render_view->Send(new ViewHostMsg_OpenChannelToPepperPlugin( + render_frame->Send(new ViewHostMsg_OpenChannelToPepperPlugin( path, &channel_handle, &peer_pid, &plugin_child_id)); if (channel_handle.name.empty()) { // Couldn't be initialized. @@ -731,7 +730,7 @@ scoped_refptr<PluginModule> PluginModule::Create( module = new PluginModule(info->name, path, permissions); PepperPluginRegistry::GetInstance()->AddLiveModule(path, module.get()); - if (!module->CreateOutOfProcessModule(render_view, + if (!module->CreateOutOfProcessModule(render_frame, path, permissions, channel_handle, diff --git a/chromium/content/renderer/pepper/plugin_module.h b/chromium/content/renderer/pepper/plugin_module.h index daadf3cdec9..ad9463c45ad 100644 --- a/chromium/content/renderer/pepper/plugin_module.h +++ b/chromium/content/renderer/pepper/plugin_module.h @@ -41,16 +41,16 @@ namespace IPC { struct ChannelHandle; } -namespace WebKit { +namespace blink { class WebPluginContainer; -} // namespace WebKit +} // namespace blink namespace content { class HostDispatcherWrapper; class PepperPluginInstanceImpl; class PepperBroker; class RendererPpapiHostImpl; -class RenderViewImpl; +class RenderFrameImpl; struct WebPluginInfo; // Represents one plugin library loaded into one renderer. This library may @@ -139,8 +139,8 @@ class CONTENT_EXPORT PluginModule : const ppapi::PpapiPermissions& permissions() const { return permissions_; } PepperPluginInstanceImpl* CreateInstance( - RenderViewImpl* render_view, - WebKit::WebPluginContainer* container, + RenderFrameImpl* render_frame, + blink::WebPluginContainer* container, const GURL& plugin_url); // Returns "some" plugin instance associated with this module. This is not @@ -189,7 +189,7 @@ class CONTENT_EXPORT PluginModule : // Create a new HostDispatcher for proxying, hook it to the PluginModule, // and perform other common initialization. RendererPpapiHostImpl* CreateOutOfProcessModule( - RenderViewImpl* render_view, + RenderFrameImpl* render_frame, const base::FilePath& path, ppapi::PpapiPermissions permissions, const IPC::ChannelHandle& channel_handle, @@ -212,7 +212,7 @@ class CONTENT_EXPORT PluginModule : // the second is that the plugin failed to initialize. In this case, // |*pepper_plugin_was_registered| will be set to true and the caller should // not fall back on any other plugin types. - static scoped_refptr<PluginModule> Create(RenderViewImpl* render_view, + static scoped_refptr<PluginModule> Create(RenderFrameImpl* render_frame, const WebPluginInfo& webplugin_info, bool* pepper_plugin_was_registered); diff --git a/chromium/content/renderer/pepper/plugin_object.cc b/chromium/content/renderer/pepper/plugin_object.cc index 7746846a288..55e4c6c08ec 100644 --- a/chromium/content/renderer/pepper/plugin_object.cc +++ b/chromium/content/renderer/pepper/plugin_object.cc @@ -27,7 +27,7 @@ using ppapi::PpapiGlobals; using ppapi::StringVar; using ppapi::Var; -using WebKit::WebBindings; +using blink::WebBindings; namespace content { diff --git a/chromium/content/renderer/pepper/ppb_broker_impl.cc b/chromium/content/renderer/pepper/ppb_broker_impl.cc index f68d257e145..882c5db74aa 100644 --- a/chromium/content/renderer/pepper/ppb_broker_impl.cc +++ b/chromium/content/renderer/pepper/ppb_broker_impl.cc @@ -84,7 +84,7 @@ int32_t PPB_Broker_Impl::Connect( RenderThreadImpl::current()->Send( new ViewHostMsg_RequestPpapiBrokerPermission( - plugin_instance->render_view()->GetRoutingID(), + plugin_instance->render_frame()->render_view()->GetRoutingID(), routing_id_, GetDocumentUrl(), broker_path)); diff --git a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc index b48d68ab030..1564279f7b4 100644 --- a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc +++ b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc @@ -27,10 +27,10 @@ using ppapi::thunk::EnterResourceNoLock; using ppapi::thunk::PPB_Graphics3D_API; -using WebKit::WebConsoleMessage; -using WebKit::WebFrame; -using WebKit::WebPluginContainer; -using WebKit::WebString; +using blink::WebConsoleMessage; +using blink::WebFrame; +using blink::WebPluginContainer; +using blink::WebString; namespace content { @@ -160,7 +160,7 @@ gpu::CommandBuffer::State PPB_Graphics3D_Impl::FlushSyncFast( } uint32_t PPB_Graphics3D_Impl::InsertSyncPoint() { - return GetCommandBuffer()->InsertSyncPoint(); + return platform_context_->GetGpuControl()->InsertSyncPoint(); } bool PPB_Graphics3D_Impl::BindToInstance(bool bind) { @@ -172,9 +172,6 @@ bool PPB_Graphics3D_Impl::IsOpaque() { return platform_context_->IsOpaque(); } -void PPB_Graphics3D_Impl::ViewWillInitiatePaint() { -} - void PPB_Graphics3D_Impl::ViewInitiatedPaint() { commit_pending_ = false; @@ -189,6 +186,10 @@ gpu::CommandBuffer* PPB_Graphics3D_Impl::GetCommandBuffer() { return platform_context_->GetCommandBuffer(); } +gpu::GpuControl* PPB_Graphics3D_Impl::GetGpuControl() { + return platform_context_->GetGpuControl(); +} + int32 PPB_Graphics3D_Impl::DoSwapBuffers() { // We do not have a GLES2 implementation when using an OOP proxy. // The plugin-side proxy is responsible for adding the SwapBuffers command @@ -333,7 +334,11 @@ void PPB_Graphics3D_Impl::SendContextLost() { static_cast<const PPP_Graphics3D*>( instance->module()->GetPluginInterface( PPP_GRAPHICS_3D_INTERFACE)); - if (ppp_graphics_3d) + // We have to check *again* that the instance exists, because it could have + // been deleted during GetPluginInterface(). Even the PluginModule could be + // deleted, but in that case, the instance should also be gone, so the + // GetInstance check covers both cases. + if (ppp_graphics_3d && HostGlobals::Get()->GetInstance(this_pp_instance)) ppp_graphics_3d->Graphics3DContextLost(this_pp_instance); } diff --git a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h index 3e1c797526b..d4d4c2bad28 100644 --- a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h +++ b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h @@ -45,7 +45,6 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared { // Notifications about the view's progress painting. See PluginInstance. // These messages are used to send Flush callbacks to the plugin. - void ViewWillInitiatePaint(); void ViewInitiatedPaint(); void ViewFlushedPaint(); @@ -55,6 +54,7 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared { virtual ~PPB_Graphics3D_Impl(); // ppapi::PPB_Graphics3D_Shared overrides. virtual gpu::CommandBuffer* GetCommandBuffer() OVERRIDE; + virtual gpu::GpuControl* GetGpuControl() OVERRIDE; virtual int32 DoSwapBuffers() OVERRIDE; private: diff --git a/chromium/content/renderer/pepper/ppb_image_data_impl.cc b/chromium/content/renderer/pepper/ppb_image_data_impl.cc index 9ea83d5e2f4..80cc38dcd3d 100644 --- a/chromium/content/renderer/pepper/ppb_image_data_impl.cc +++ b/chromium/content/renderer/pepper/ppb_image_data_impl.cc @@ -25,6 +25,19 @@ using ppapi::thunk::PPB_ImageData_API; namespace content { +namespace { +// Returns true if the ImageData shared memory should be allocated in the +// browser process for the current platform. +bool IsBrowserAllocated() { +#if defined(OS_POSIX) && !defined(TOOLKIT_GTK) && !defined(OS_ANDROID) + // On the Mac, shared memory has to be created in the browser in order to + // work in the sandbox. + return true; +#endif + return false; +} +} // namespace + PPB_ImageData_Impl::PPB_ImageData_Impl(PP_Instance instance, PPB_ImageData_Shared::ImageDataType type) : Resource(ppapi::OBJECT_IS_IMPL, instance), @@ -33,7 +46,7 @@ PPB_ImageData_Impl::PPB_ImageData_Impl(PP_Instance instance, height_(0) { switch (type) { case PPB_ImageData_Shared::PLATFORM: - backend_.reset(new ImageDataPlatformBackend); + backend_.reset(new ImageDataPlatformBackend(IsBrowserAllocated())); return; case PPB_ImageData_Shared::SIMPLE: backend_.reset(new ImageDataSimpleBackend); @@ -43,6 +56,15 @@ PPB_ImageData_Impl::PPB_ImageData_Impl(PP_Instance instance, NOTREACHED(); } +PPB_ImageData_Impl::PPB_ImageData_Impl(PP_Instance instance, + ForTest) + : Resource(ppapi::OBJECT_IS_IMPL, instance), + format_(PP_IMAGEDATAFORMAT_BGRA_PREMUL), + width_(0), + height_(0) { + backend_.reset(new ImageDataPlatformBackend(false)); +} + PPB_ImageData_Impl::~PPB_ImageData_Impl() { } @@ -127,19 +149,22 @@ const SkBitmap* PPB_ImageData_Impl::GetMappedBitmap() const { // ImageDataPlatformBackend ---------------------------------------------------- -ImageDataPlatformBackend::ImageDataPlatformBackend() +ImageDataPlatformBackend::ImageDataPlatformBackend(bool is_browser_allocated) : width_(0), - height_(0) { + height_(0), + is_browser_allocated_(is_browser_allocated) { } // On POSIX, we have to tell the browser to free the transport DIB. ImageDataPlatformBackend::~ImageDataPlatformBackend() { -#if defined(OS_POSIX) && !defined(TOOLKIT_GTK) && !defined(OS_ANDROID) - if (dib_) { - RenderThreadImpl::current()->Send( - new ViewHostMsg_FreeTransportDIB(dib_->id())); - } + if (is_browser_allocated_) { +#if defined(OS_POSIX) + if (dib_) { + RenderThreadImpl::current()->Send( + new ViewHostMsg_FreeTransportDIB(dib_->id())); + } #endif + } } bool ImageDataPlatformBackend::Init(PPB_ImageData_Impl* impl, @@ -152,30 +177,32 @@ bool ImageDataPlatformBackend::Init(PPB_ImageData_Impl* impl, uint32 buffer_size = width_ * height_ * 4; // Allocate the transport DIB and the PlatformCanvas pointing to it. -#if defined(OS_POSIX) && !defined(TOOLKIT_GTK) && !defined(OS_ANDROID) - // On the Mac, shared memory has to be created in the browser in order to - // work in the sandbox. Do this by sending a message to the browser - // requesting a TransportDIB (see also - // chrome/renderer/webplugin_delegate_proxy.cc, method - // WebPluginDelegateProxy::CreateBitmap() for similar code). The TransportDIB - // is cached in the browser, and is freed (in typical cases) by the - // TransportDIB's destructor. - TransportDIB::Handle dib_handle; - IPC::Message* msg = new ViewHostMsg_AllocTransportDIB(buffer_size, - true, - &dib_handle); - if (!RenderThreadImpl::current()->Send(msg)) - return false; - if (!TransportDIB::is_valid_handle(dib_handle)) - return false; - - TransportDIB* dib = TransportDIB::CreateWithHandle(dib_handle); -#else - static int next_dib_id = 0; - TransportDIB* dib = TransportDIB::Create(buffer_size, next_dib_id++); - if (!dib) - return false; + TransportDIB* dib = NULL; + if (is_browser_allocated_) { +#if defined(OS_POSIX) + // Allocate the image data by sending a message to the browser requesting a + // TransportDIB (see also chrome/renderer/webplugin_delegate_proxy.cc, + // method WebPluginDelegateProxy::CreateBitmap() for similar code). The + // TransportDIB is cached in the browser, and is freed (in typical cases) by + // the TransportDIB's destructor. + TransportDIB::Handle dib_handle; + IPC::Message* msg = new ViewHostMsg_AllocTransportDIB(buffer_size, + true, + &dib_handle); + if (!RenderThreadImpl::current()->Send(msg)) + return false; + if (!TransportDIB::is_valid_handle(dib_handle)) + return false; + + dib = TransportDIB::CreateWithHandle(dib_handle); #endif + } else { + static int next_dib_id = 0; + dib = TransportDIB::Create(buffer_size, next_dib_id++); + if (!dib) + return false; + } + DCHECK(dib); dib_.reset(dib); return true; } @@ -198,7 +225,7 @@ void* ImageDataPlatformBackend::Map() { skia::GetTopDevice(*mapped_canvas_)->accessBitmap(true); // Our platform bitmaps are set to opaque by default, which we don't want. - const_cast<SkBitmap&>(bitmap).setIsOpaque(false); + const_cast<SkBitmap&>(bitmap).setAlphaType(kPremul_SkAlphaType); bitmap.lockPixels(); return bitmap.getAddr32(0, 0); @@ -273,7 +300,7 @@ void* ImageDataSimpleBackend::Map() { shared_memory_->Map(skia_bitmap_.getSize()); skia_bitmap_.setPixels(shared_memory_->memory()); // Our platform bitmaps are set to opaque by default, which we don't want. - skia_bitmap_.setIsOpaque(false); + skia_bitmap_.setAlphaType(kPremul_SkAlphaType); skia_canvas_.reset(new SkCanvas(skia_bitmap_)); return skia_bitmap_.getAddr32(0, 0); } diff --git a/chromium/content/renderer/pepper/ppb_image_data_impl.h b/chromium/content/renderer/pepper/ppb_image_data_impl.h index a16bbfa104b..49c399b1d39 100644 --- a/chromium/content/renderer/pepper/ppb_image_data_impl.h +++ b/chromium/content/renderer/pepper/ppb_image_data_impl.h @@ -54,6 +54,11 @@ class CONTENT_EXPORT PPB_ImageData_Impl PPB_ImageData_Impl(PP_Instance instance, PPB_ImageData_Shared::ImageDataType type); + // Constructor used for unittests. The ImageData is always allocated locally. + struct ForTest {}; + PPB_ImageData_Impl(PP_Instance instance, + ForTest); + bool Init(PP_ImageDataFormat format, int width, int height, bool init_to_zero); @@ -102,7 +107,9 @@ class CONTENT_EXPORT PPB_ImageData_Impl class ImageDataPlatformBackend : public PPB_ImageData_Impl::Backend { public: - ImageDataPlatformBackend(); + // |is_browser_allocated| indicates whether the backing shared memory should + // be allocated by the browser process. + ImageDataPlatformBackend(bool is_browser_allocated); virtual ~ImageDataPlatformBackend(); // PPB_ImageData_Impl::Backend implementation. @@ -124,6 +131,8 @@ class ImageDataPlatformBackend : public PPB_ImageData_Impl::Backend { int height_; scoped_ptr<TransportDIB> dib_; + bool is_browser_allocated_; + // When the device is mapped, this is the image. Null when umapped. scoped_ptr<SkCanvas> mapped_canvas_; diff --git a/chromium/content/renderer/pepper/ppb_scrollbar_impl.cc b/chromium/content/renderer/pepper/ppb_scrollbar_impl.cc index fb01c597569..326c7003183 100644 --- a/chromium/content/renderer/pepper/ppb_scrollbar_impl.cc +++ b/chromium/content/renderer/pepper/ppb_scrollbar_impl.cc @@ -27,10 +27,10 @@ #endif using ppapi::thunk::PPB_Scrollbar_API; -using WebKit::WebInputEvent; -using WebKit::WebRect; -using WebKit::WebScrollbar; -using WebKit::WebPluginScrollbar; +using blink::WebInputEvent; +using blink::WebRect; +using blink::WebScrollbar; +using blink::WebPluginScrollbar; namespace content { @@ -59,7 +59,7 @@ void PPB_Scrollbar_Impl::Init(bool vertical) { scrollbar_.reset(WebPluginScrollbar::createForPlugin( vertical ? WebScrollbar::Vertical : WebScrollbar::Horizontal, plugin_instance->container(), - static_cast<WebKit::WebPluginScrollbarClient*>(this))); + static_cast<blink::WebPluginScrollbarClient*>(this))); } PPB_Scrollbar_API* PPB_Scrollbar_Impl::AsPPB_Scrollbar_API() { @@ -168,7 +168,7 @@ void PPB_Scrollbar_Impl::SetLocationInternal(const PP_Rect* location) { location->size.height)); } -void PPB_Scrollbar_Impl::valueChanged(WebKit::WebPluginScrollbar* scrollbar) { +void PPB_Scrollbar_Impl::valueChanged(blink::WebPluginScrollbar* scrollbar) { PluginModule* plugin_module = HostGlobals::Get()->GetInstance(pp_instance())->module(); if (!plugin_module) @@ -206,8 +206,8 @@ void PPB_Scrollbar_Impl::overlayChanged(WebPluginScrollbar* scrollbar) { } void PPB_Scrollbar_Impl::invalidateScrollbarRect( - WebKit::WebPluginScrollbar* scrollbar, - const WebKit::WebRect& rect) { + blink::WebPluginScrollbar* scrollbar, + const blink::WebRect& rect) { gfx::Rect gfx_rect(rect.x, rect.y, rect.width, @@ -217,8 +217,8 @@ void PPB_Scrollbar_Impl::invalidateScrollbarRect( // since the PPB_Scrollbar_Impl code is still in the middle of updating its // internal state. // Note: we use a WeakPtrFactory here so that a lingering callback can not - // modify the lifetime of this object. Otherwise, WebKit::WebPluginScrollbar - // could outlive WebKit::WebPluginContainer, which is against its contract. + // modify the lifetime of this object. Otherwise, blink::WebPluginScrollbar + // could outlive blink::WebPluginContainer, which is against its contract. base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(&PPB_Scrollbar_Impl::NotifyInvalidate, @@ -226,8 +226,8 @@ void PPB_Scrollbar_Impl::invalidateScrollbarRect( } void PPB_Scrollbar_Impl::getTickmarks( - WebKit::WebPluginScrollbar* scrollbar, - WebKit::WebVector<WebKit::WebRect>* tick_marks) const { + blink::WebPluginScrollbar* scrollbar, + blink::WebVector<blink::WebRect>* tick_marks) const { if (tickmarks_.empty()) { WebRect* rects = NULL; tick_marks->assign(rects, 0); diff --git a/chromium/content/renderer/pepper/ppb_scrollbar_impl.h b/chromium/content/renderer/pepper/ppb_scrollbar_impl.h index eb7906b26b0..f649c816d8c 100644 --- a/chromium/content/renderer/pepper/ppb_scrollbar_impl.h +++ b/chromium/content/renderer/pepper/ppb_scrollbar_impl.h @@ -20,7 +20,7 @@ namespace content { class PPB_Scrollbar_Impl : public PPB_Widget_Impl, public ppapi::thunk::PPB_Scrollbar_API, - public WebKit::WebPluginScrollbarClient { + public blink::WebPluginScrollbarClient { public: static PP_Resource Create(PP_Instance instance, bool vertical); @@ -50,20 +50,20 @@ class PPB_Scrollbar_Impl : public PPB_Widget_Impl, const ppapi::InputEventData& data) OVERRIDE; virtual void SetLocationInternal(const PP_Rect* location) OVERRIDE; - // WebKit::WebPluginScrollbarClient implementation. - virtual void valueChanged(WebKit::WebPluginScrollbar* scrollbar) OVERRIDE; - virtual void overlayChanged(WebKit::WebPluginScrollbar* scrollbar) OVERRIDE; - virtual void invalidateScrollbarRect(WebKit::WebPluginScrollbar* scrollbar, - const WebKit::WebRect& rect) OVERRIDE; + // blink::WebPluginScrollbarClient implementation. + virtual void valueChanged(blink::WebPluginScrollbar* scrollbar) OVERRIDE; + virtual void overlayChanged(blink::WebPluginScrollbar* scrollbar) OVERRIDE; + virtual void invalidateScrollbarRect(blink::WebPluginScrollbar* scrollbar, + const blink::WebRect& rect) OVERRIDE; virtual void getTickmarks( - WebKit::WebPluginScrollbar* scrollbar, - WebKit::WebVector<WebKit::WebRect>* tick_marks) const OVERRIDE; + blink::WebPluginScrollbar* scrollbar, + blink::WebVector<blink::WebRect>* tick_marks) const OVERRIDE; void NotifyInvalidate(); gfx::Rect dirty_; - std::vector<WebKit::WebRect> tickmarks_; - scoped_ptr<WebKit::WebPluginScrollbar> scrollbar_; + std::vector<blink::WebRect> tickmarks_; + scoped_ptr<blink::WebPluginScrollbar> scrollbar_; // Used so that the post task for Invalidate doesn't keep an extra reference. base::WeakPtrFactory<PPB_Scrollbar_Impl> weak_ptr_factory_; diff --git a/chromium/content/renderer/pepper/ppb_var_deprecated_impl.cc b/chromium/content/renderer/pepper/ppb_var_deprecated_impl.cc index 23472fac26c..6f12733c1a4 100644 --- a/chromium/content/renderer/pepper/ppb_var_deprecated_impl.cc +++ b/chromium/content/renderer/pepper/ppb_var_deprecated_impl.cc @@ -24,7 +24,7 @@ using ppapi::NPObjectVar; using ppapi::PpapiGlobals; using ppapi::StringVar; using ppapi::Var; -using WebKit::WebBindings; +using blink::WebBindings; namespace content { @@ -333,7 +333,7 @@ PP_Var CallDeprecated(PP_Var var, return PP_MakeUndefined(); PepperPluginInstanceImpl* plugin = accessor.GetPluginInstance(); if (plugin && plugin->IsProcessingUserGesture()) { - WebKit::WebScopedUserGesture user_gesture( + blink::WebScopedUserGesture user_gesture( plugin->CurrentUserGestureToken()); return InternalCallDeprecated(&accessor, method_name, argc, argv, exception); diff --git a/chromium/content/renderer/pepper/quota_file_io.cc b/chromium/content/renderer/pepper/quota_file_io.cc deleted file mode 100644 index a5e4f6b3dd1..00000000000 --- a/chromium/content/renderer/pepper/quota_file_io.cc +++ /dev/null @@ -1,390 +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/renderer/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" -#include "content/renderer/pepper/host_globals.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: - PendingOperationBase(QuotaFileIO* quota_io, bool is_will_operation) - : quota_io_(quota_io), is_will_operation_(is_will_operation) { - DCHECK(quota_io_); - quota_io_->WillUpdate(); - } - - QuotaFileIO* quota_io_; - const bool is_will_operation_; -}; - -class QuotaFileIO::WriteOperation : public PendingOperationBase { - public: - WriteOperation(QuotaFileIO* quota_io, - bool is_will_operation, - int64_t offset, - const char* buffer, - int32_t bytes_to_write, - const WriteCallback& callback) - : PendingOperationBase(quota_io, is_will_operation), - offset_(offset), - bytes_to_write_(bytes_to_write), - callback_(callback), - finished_(false), - status_(base::PLATFORM_FILE_OK), - bytes_written_(0), - weak_factory_(this) { - if (!is_will_operation) { - // 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; - } - if (is_will_operation_) { - // Assuming the write will succeed. - DidFinish(base::PLATFORM_FILE_OK, bytes_to_write_); - 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, - bool is_will_operation, - int64_t length, - const StatusCallback& callback) - : PendingOperationBase(quota_io, is_will_operation), - 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 (is_will_operation_) { - DidFinish(base::PLATFORM_FILE_OK); - 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, false, 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, false, length, callback); - return RegisterOperationForQuotaChecks(op); -} - -bool QuotaFileIO::WillWrite( - int64_t offset, int32_t bytes_to_write, const WriteCallback& callback) { - WriteOperation* op = new WriteOperation( - this, true, offset, NULL, bytes_to_write, callback); - return RegisterOperationForQuotaChecks(op); -} - -bool QuotaFileIO::WillSetLength(int64_t length, - const StatusCallback& callback) { - DCHECK(pending_operations_.empty()); - SetLengthOperation* op = new SetLengthOperation(this, true, 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/chromium/content/renderer/pepper/quota_file_io.h b/chromium/content/renderer/pepper/quota_file_io.h deleted file mode 100644 index 8dbcd2a115f..00000000000 --- a/chromium/content/renderer/pepper/quota_file_io.h +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) 2011 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_RENDERER_PEPPER_QUOTA_FILE_IO_H_ -#define CONTENT_RENDERER_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 in this renderer. - 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/WillSetLength cannot be called while there're any in-flight - // operations. For Write/WillWrite 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 WillWrite(int64_t offset, - int32_t bytes_to_write, - const WriteCallback& callback); - - CONTENT_EXPORT bool SetLength(int64_t length, - const StatusCallback& callback); - CONTENT_EXPORT bool WillSetLength(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_RENDERER_PEPPER_QUOTA_FILE_IO_H_ diff --git a/chromium/content/renderer/pepper/quota_file_io_unittest.cc b/chromium/content/renderer/pepper/quota_file_io_unittest.cc deleted file mode 100644 index 2321c9f369e..00000000000 --- a/chromium/content/renderer/pepper/quota_file_io_unittest.cc +++ /dev/null @@ -1,496 +0,0 @@ -// Copyright (c) 2011 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/renderer/pepper/pepper_plugin_instance_impl.h" -#include "content/renderer/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(bool will_operation) { - // 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, will_operation); - 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(); - - if (will_operation) { - // WillWrite doesn't actually write. - EXPECT_EQ(0, GetPlatformFileSize()); - // Adjust the actual file size to 'fake' write to proceed testing. - SetPlatformFileSize(8); - } else { - 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, will_operation); - 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(); - - if (will_operation) { - EXPECT_EQ(8, GetPlatformFileSize()); - SetPlatformFileSize(10); - } else { - 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, will_operation); - 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(); - - if (will_operation) { - EXPECT_EQ(10, GetPlatformFileSize()); - SetPlatformFileSize(15); - } else { - 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, will_operation); - 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(); - - if (will_operation) { - EXPECT_EQ(15, GetPlatformFileSize()); - } else { - 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, will_operation); - 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(); - - if (will_operation) { - EXPECT_EQ(15, GetPlatformFileSize()); - SetPlatformFileSize(24); - } else { - 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, will_operation); - 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, will_operation); - 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, will_operation); - 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(); - - if (!will_operation) { - EXPECT_EQ(29, GetPlatformFileSize()); - ReadPlatformFile(&read_buffer); - EXPECT_EQ(std::string("12ABCDEF9012345\0\0\0\0\0XXXABCDEF", 29), - read_buffer); - } - } - - void SetLengthTestBody(bool will_operation) { - delegate()->set_available_space(100); - - SetLength(0, will_operation); - 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, will_operation); - 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(); - - if (will_operation) { - EXPECT_EQ(0, GetPlatformFileSize()); - SetPlatformFileSize(8); - } else { - EXPECT_EQ(8, GetPlatformFileSize()); - } - - SetLength(16, will_operation); - 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(); - - if (will_operation) { - EXPECT_EQ(8, GetPlatformFileSize()); - SetPlatformFileSize(16); - } else { - EXPECT_EQ(16, GetPlatformFileSize()); - } - - SetLength(4, will_operation); - 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(); - - if (will_operation) { - EXPECT_EQ(16, GetPlatformFileSize()); - SetPlatformFileSize(4); - } else { - EXPECT_EQ(4, GetPlatformFileSize()); - } - - SetLength(0, will_operation); - 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(); - - if (will_operation) { - EXPECT_EQ(4, GetPlatformFileSize()); - SetPlatformFileSize(0); - } else { - EXPECT_EQ(0, GetPlatformFileSize()); - } - - delegate()->set_available_space(5); - - // Quota error case. - SetLength(7, will_operation); - 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, bool will_operation) { - if (will_operation) { - ASSERT_TRUE(quota_file_io_->WillWrite( - offset, data.size(), - base::Bind(&QuotaFileIOTest::DidWrite, weak_factory_.GetWeakPtr()))); - } else { - ASSERT_TRUE(quota_file_io_->Write( - offset, data.c_str(), data.size(), - base::Bind(&QuotaFileIOTest::DidWrite, weak_factory_.GetWeakPtr()))); - } - } - - void SetLength(int64_t length, bool will_operation) { - if (will_operation) { - ASSERT_TRUE(quota_file_io_->WillSetLength( - length, - base::Bind(&QuotaFileIOTest::DidSetLength, - weak_factory_.GetWeakPtr()))); - } else { - 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(false); -} - -TEST_F(QuotaFileIOTest, WillWrite) { - WriteTestBody(true); -} - -TEST_F(QuotaFileIOTest, SetLength) { - SetLengthTestBody(false); -} - -TEST_F(QuotaFileIOTest, WillSetLength) { - SetLengthTestBody(true); -} - -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], false); - Write(5, data1[1], false); - Write(8, data1[2], false); - 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], false); - Write(20, data2[1], false); - 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/chromium/content/renderer/pepper/renderer_ppapi_host_impl.cc b/chromium/content/renderer/pepper/renderer_ppapi_host_impl.cc index 5c41003d71f..5014c9898ef 100644 --- a/chromium/content/renderer/pepper/renderer_ppapi_host_impl.cc +++ b/chromium/content/renderer/pepper/renderer_ppapi_host_impl.cc @@ -132,6 +132,17 @@ ppapi::host::PpapiHost* RendererPpapiHostImpl::GetPpapiHost() { return ppapi_host_.get(); } +RenderFrame* RendererPpapiHostImpl::GetRenderFrameForInstance( + PP_Instance instance) const { + PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance); + if (!instance_object) + return NULL; + + // Since we're the embedder, we can make assumptions about the helper on + // the instance and get back to our RenderFrame. + return instance_object->render_frame(); +} + RenderView* RendererPpapiHostImpl::GetRenderViewForInstance( PP_Instance instance) const { PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance); @@ -140,7 +151,7 @@ RenderView* RendererPpapiHostImpl::GetRenderViewForInstance( // Since we're the embedder, we can make assumptions about the helper on // the instance and get back to our RenderView. - return instance_object->render_view(); + return instance_object->render_frame()->render_view(); } bool RendererPpapiHostImpl::IsValidInstance(PP_Instance instance) const { @@ -152,7 +163,7 @@ PepperPluginInstance* RendererPpapiHostImpl::GetPluginInstance( return GetAndValidateInstance(instance); } -WebKit::WebPluginContainer* RendererPpapiHostImpl::GetContainerForInstance( +blink::WebPluginContainer* RendererPpapiHostImpl::GetContainerForInstance( PP_Instance instance) const { PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance); if (!instance_object) @@ -188,19 +199,20 @@ int RendererPpapiHostImpl::GetRoutingIDForWidget(PP_Instance instance) const { return GetRenderViewForInstance(instance)->GetRoutingID(); } -gfx::Point RendererPpapiHostImpl::PluginPointToRenderView( +gfx::Point RendererPpapiHostImpl::PluginPointToRenderFrame( PP_Instance instance, const gfx::Point& pt) const { PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance); if (!plugin_instance) return pt; - RenderViewImpl* render_view = static_cast<RenderViewImpl*>( - GetRenderViewForInstance(instance)); + RenderFrameImpl* render_frame = static_cast<RenderFrameImpl*>( + GetRenderFrameForInstance(instance)); if (plugin_instance->view_data().is_fullscreen || plugin_instance->flash_fullscreen()) { - WebKit::WebRect window_rect = render_view->windowRect(); - WebKit::WebRect screen_rect = render_view->screenInfo().rect; + blink::WebRect window_rect = render_frame->GetRenderWidget()->windowRect(); + blink::WebRect screen_rect = + render_frame->GetRenderWidget()->screenInfo().rect; return gfx::Point(pt.x() - window_rect.x + screen_rect.x, pt.y() - window_rect.y + screen_rect.y); } @@ -231,9 +243,9 @@ void RendererPpapiHostImpl::CreateBrowserResourceHosts( PP_Instance instance, const std::vector<IPC::Message>& nested_msgs, const base::Callback<void(const std::vector<int>&)>& callback) const { - RenderView* render_view = GetRenderViewForInstance(instance); + RenderFrame* render_frame = GetRenderFrameForInstance(instance); PepperBrowserConnection* browser_connection = - PepperBrowserConnection::Get(render_view); + PepperBrowserConnection::Get(render_frame); if (!browser_connection) { base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, std::vector<int>(nested_msgs.size(), 0))); @@ -245,6 +257,14 @@ void RendererPpapiHostImpl::CreateBrowserResourceHosts( } } +GURL RendererPpapiHostImpl::GetDocumentURL(PP_Instance instance) const { + PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance); + if (!instance_object) + return GURL(); + + return instance_object->container()->element().document().url(); +} + PepperPluginInstanceImpl* RendererPpapiHostImpl::GetAndValidateInstance( PP_Instance pp_instance) const { PepperPluginInstanceImpl* instance = diff --git a/chromium/content/renderer/pepper/renderer_ppapi_host_impl.h b/chromium/content/renderer/pepper/renderer_ppapi_host_impl.h index b7a0a53a505..c2ad0d1cb0d 100644 --- a/chromium/content/renderer/pepper/renderer_ppapi_host_impl.h +++ b/chromium/content/renderer/pepper/renderer_ppapi_host_impl.h @@ -78,14 +78,16 @@ class RendererPpapiHostImpl : public RendererPpapiHost { virtual bool IsValidInstance(PP_Instance instance) const OVERRIDE; virtual PepperPluginInstance* GetPluginInstance( PP_Instance instance) const OVERRIDE; + virtual RenderFrame* GetRenderFrameForInstance( + PP_Instance instance) const OVERRIDE; virtual RenderView* GetRenderViewForInstance( PP_Instance instance) const OVERRIDE; - virtual WebKit::WebPluginContainer* GetContainerForInstance( + virtual blink::WebPluginContainer* GetContainerForInstance( PP_Instance instance) const OVERRIDE; virtual base::ProcessId GetPluginPID() const OVERRIDE; virtual bool HasUserGesture(PP_Instance instance) const OVERRIDE; virtual int GetRoutingIDForWidget(PP_Instance instance) const OVERRIDE; - virtual gfx::Point PluginPointToRenderView( + virtual gfx::Point PluginPointToRenderFrame( PP_Instance instance, const gfx::Point& pt) const OVERRIDE; virtual IPC::PlatformFileForTransit ShareHandleWithRemote( @@ -97,6 +99,7 @@ class RendererPpapiHostImpl : public RendererPpapiHost { const std::vector<IPC::Message>& nested_msgs, const base::Callback<void( const std::vector<int>&)>& callback) const OVERRIDE; + virtual GURL GetDocumentURL(PP_Instance instance) const OVERRIDE; private: RendererPpapiHostImpl(PluginModule* module, diff --git a/chromium/content/renderer/pepper/resource_converter.cc b/chromium/content/renderer/pepper/resource_converter.cc index 4f9f5d99cd2..5054c2dc3a4 100644 --- a/chromium/content/renderer/pepper/resource_converter.cc +++ b/chromium/content/renderer/pepper/resource_converter.cc @@ -7,22 +7,84 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" #include "content/public/renderer/renderer_ppapi_host.h" +#include "content/renderer/pepper/pepper_file_system_host.h" #include "ipc/ipc_message.h" +#include "ppapi/host/ppapi_host.h" +#include "ppapi/host/resource_host.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/shared_impl/resource_var.h" #include "ppapi/shared_impl/scoped_pp_var.h" +#include "third_party/WebKit/public/platform/WebFileSystem.h" +#include "third_party/WebKit/public/web/WebDOMFileSystem.h" namespace { void FlushComplete( const base::Callback<void(bool)>& callback, - const std::vector<PP_Var>& browser_host_resource_vars, + const std::vector<scoped_refptr<content::HostResourceVar> >& browser_vars, const std::vector<int>& pending_host_ids) { - CHECK(browser_host_resource_vars.size() == pending_host_ids.size()); - for (size_t i = 0; i < browser_host_resource_vars.size(); ++i) { - // TODO(raymes): Set the pending browser host ID in the resource var. + CHECK(browser_vars.size() == pending_host_ids.size()); + for (size_t i = 0; i < browser_vars.size(); ++i) { + browser_vars[i]->set_pending_browser_host_id(pending_host_ids[i]); } callback.Run(true); } +// Converts a blink::WebFileSystem::Type to a PP_FileSystemType. +PP_FileSystemType WebFileSystemTypeToPPAPI(blink::WebFileSystem::Type type) { + switch (type) { + case blink::WebFileSystem::TypeTemporary: + return PP_FILESYSTEMTYPE_LOCALTEMPORARY; + case blink::WebFileSystem::TypePersistent: + return PP_FILESYSTEMTYPE_LOCALPERSISTENT; + case blink::WebFileSystem::TypeIsolated: + return PP_FILESYSTEMTYPE_ISOLATED; + case blink::WebFileSystem::TypeExternal: + return PP_FILESYSTEMTYPE_EXTERNAL; + default: + NOTREACHED(); + return PP_FILESYSTEMTYPE_LOCALTEMPORARY; + } +} + +// Given a V8 value containing a DOMFileSystem, creates a resource host and +// returns the resource information for serialization. +// On error, false. +bool DOMFileSystemToResource( + PP_Instance instance, + content::RendererPpapiHost* host, + const blink::WebDOMFileSystem& dom_file_system, + int* pending_renderer_id, + scoped_ptr<IPC::Message>* create_message, + scoped_ptr<IPC::Message>* browser_host_create_message) { + DCHECK(!dom_file_system.isNull()); + + PP_FileSystemType file_system_type = + WebFileSystemTypeToPPAPI(dom_file_system.type()); + GURL root_url = dom_file_system.rootURL(); + + // External file systems are not currently supported. (Without this check, + // there would be a CHECK-fail in FileRefResource.) + // TODO(mgiuca): Support external file systems. + if (file_system_type == PP_FILESYSTEMTYPE_EXTERNAL) + return false; + + *pending_renderer_id = host->GetPpapiHost()->AddPendingResourceHost( + scoped_ptr<ppapi::host::ResourceHost>( + new content::PepperFileSystemHost(host, instance, 0, root_url, + file_system_type))); + if (*pending_renderer_id == 0) + return false; + + create_message->reset( + new PpapiPluginMsg_FileSystem_CreateFromPendingHost(file_system_type)); + + browser_host_create_message->reset( + new PpapiHostMsg_FileSystem_CreateFromRenderer(root_url.spec(), + file_system_type)); + return true; +} + } // namespace namespace content { @@ -38,37 +100,69 @@ ResourceConverterImpl::ResourceConverterImpl(PP_Instance instance, ResourceConverterImpl::~ResourceConverterImpl() { // Verify Flush() was called. DCHECK(browser_host_create_messages_.empty()); - DCHECK(browser_host_resource_vars.empty()); + DCHECK(browser_vars.empty()); } -bool ResourceConverterImpl::FromV8Value(v8::Handle<v8::Value> val, +bool ResourceConverterImpl::FromV8Value(v8::Handle<v8::Object> val, v8::Handle<v8::Context> context, - PP_Var* result) { + PP_Var* result, + bool* was_resource) { + v8::Context::Scope context_scope(context); + v8::HandleScope handle_scope(context->GetIsolate()); + + *was_resource = false; + + blink::WebDOMFileSystem dom_file_system = + blink::WebDOMFileSystem::fromV8Value(val); + if (!dom_file_system.isNull()) { + int pending_renderer_id; + scoped_ptr<IPC::Message> create_message; + scoped_ptr<IPC::Message> browser_host_create_message; + if (!DOMFileSystemToResource(instance_, host_, dom_file_system, + &pending_renderer_id, &create_message, + &browser_host_create_message)) { + return false; + } + DCHECK(create_message); + DCHECK(browser_host_create_message); + scoped_refptr<HostResourceVar> result_var = + CreateResourceVarWithBrowserHost( + pending_renderer_id, *create_message, *browser_host_create_message); + *result = result_var->GetPPVar(); + *was_resource = true; + return true; + } - return false; + // The value was not convertible to a resource. Return true with + // |was_resource| set to false. As per the interface of FromV8Value, |result| + // may be left unmodified in this case. + return true; } void ResourceConverterImpl::Flush(const base::Callback<void(bool)>& callback) { host_->CreateBrowserResourceHosts( instance_, browser_host_create_messages_, - base::Bind(&FlushComplete, callback, browser_host_resource_vars)); + base::Bind(&FlushComplete, callback, browser_vars)); browser_host_create_messages_.clear(); - browser_host_resource_vars.clear(); + browser_vars.clear(); } -PP_Var ResourceConverterImpl::CreateResourceVar( +scoped_refptr<HostResourceVar> ResourceConverterImpl::CreateResourceVar( + int pending_renderer_id, const IPC::Message& create_message) { - // TODO(raymes): Create a ResourceVar here. - return PP_MakeUndefined(); + return new HostResourceVar(pending_renderer_id, create_message); } -PP_Var ResourceConverterImpl::CreateResourceVarWithBrowserHost( +scoped_refptr<HostResourceVar> +ResourceConverterImpl::CreateResourceVarWithBrowserHost( + int pending_renderer_id, const IPC::Message& create_message, const IPC::Message& browser_host_create_message) { - PP_Var result = CreateResourceVar(create_message); + scoped_refptr<HostResourceVar> result = + CreateResourceVar(pending_renderer_id, create_message); browser_host_create_messages_.push_back(browser_host_create_message); - browser_host_resource_vars.push_back(result); + browser_vars.push_back(result); return result; } diff --git a/chromium/content/renderer/pepper/resource_converter.h b/chromium/content/renderer/pepper/resource_converter.h index 7d9fd1ec7d9..a52f7ad83ce 100644 --- a/chromium/content/renderer/pepper/resource_converter.h +++ b/chromium/content/renderer/pepper/resource_converter.h @@ -10,7 +10,9 @@ #include "base/basictypes.h" #include "base/callback.h" #include "base/compiler_specific.h" +#include "base/memory/ref_counted.h" #include "content/common/content_export.h" +#include "content/renderer/pepper/host_resource_var.h" #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_var.h" #include "v8/include/v8.h" @@ -35,24 +37,41 @@ class CONTENT_EXPORT ResourceConverter { // Flush() must be called before any vars created by the ResourceConverter // are valid. It handles creating any resource hosts that need to be created. virtual void Flush(const base::Callback<void(bool)>& callback) = 0; + + // Attempts to convert a V8 object to a PP_Var with type PP_VARTYPE_RESOURCE. + // On success, writes the resulting var to |result|, sets |was_resource| to + // true and returns true. If |val| is not a resource, sets |was_resource| to + // false and returns true. If an error occurs, returns false. + virtual bool FromV8Value(v8::Handle<v8::Object> val, + v8::Handle<v8::Context> context, + PP_Var* result, + bool* was_resource) = 0; }; class ResourceConverterImpl : public ResourceConverter { public: ResourceConverterImpl(PP_Instance instance, RendererPpapiHost* host); virtual ~ResourceConverterImpl(); - virtual void Flush(const base::Callback<void(bool)>& callback) OVERRIDE; - bool FromV8Value(v8::Handle<v8::Value> val, - v8::Handle<v8::Context> context, - PP_Var* result); + // ResourceConverter overrides. + virtual void Flush(const base::Callback<void(bool)>& callback) OVERRIDE; + virtual bool FromV8Value(v8::Handle<v8::Object> val, + v8::Handle<v8::Context> context, + PP_Var* result, + bool* was_resource) OVERRIDE; private: - // Creates a resource var with the given message to be sent to the plugin. - PP_Var CreateResourceVar(const IPC::Message& create_message); - // Creates a resource var with the given message to send to the plugin and a - // message to create the browser host. - PP_Var CreateResourceVarWithBrowserHost( + // Creates a resource var with the given |pending_renderer_id| and + // |create_message| to be sent to the plugin. + scoped_refptr<HostResourceVar> CreateResourceVar( + int pending_renderer_id, + const IPC::Message& create_message); + // Creates a resource var with the given |pending_renderer_id| and + // |create_message| to be sent to the plugin. Also sends + // |browser_host_create_message| to the browser, and asynchronously stores the + // resulting browser host ID in the newly created var. + scoped_refptr<HostResourceVar> CreateResourceVarWithBrowserHost( + int pending_renderer_id, const IPC::Message& create_message, const IPC::Message& browser_host_create_message); @@ -62,11 +81,11 @@ class ResourceConverterImpl : public ResourceConverter { RendererPpapiHost* host_; // A list of the messages to create the browser hosts. This is a parallel - // array to |browser_host_resource_vars|. It is kept as a parallel array so - // that it can be conveniently passed to |CreateBrowserResourceHosts|. + // array to |browser_vars|. It is kept as a parallel array so that it can be + // conveniently passed to |CreateBrowserResourceHosts|. std::vector<IPC::Message> browser_host_create_messages_; // A list of the resource vars associated with browser hosts. - std::vector<PP_Var> browser_host_resource_vars; + std::vector<scoped_refptr<HostResourceVar> > browser_vars; DISALLOW_COPY_AND_ASSIGN(ResourceConverterImpl); }; diff --git a/chromium/content/renderer/pepper/resource_creation_impl.cc b/chromium/content/renderer/pepper/resource_creation_impl.cc index 178236edf68..d9ed442aecd 100644 --- a/chromium/content/renderer/pepper/resource_creation_impl.cc +++ b/chromium/content/renderer/pepper/resource_creation_impl.cc @@ -216,6 +216,11 @@ PP_Resource ResourceCreationImpl::CreateNetworkMonitor(PP_Instance instance) { return 0; // Not supported in-process. } +PP_Resource ResourceCreationImpl::CreateOutputProtectionPrivate( + PP_Instance instance) { + return 0; // Not supported in-process. +} + PP_Resource ResourceCreationImpl::CreatePlatformVerificationPrivate( PP_Instance instance) { return 0; // Not supported in-process. diff --git a/chromium/content/renderer/pepper/resource_creation_impl.h b/chromium/content/renderer/pepper/resource_creation_impl.h index d5b61b8fd54..ac54b6b442a 100644 --- a/chromium/content/renderer/pepper/resource_creation_impl.h +++ b/chromium/content/renderer/pepper/resource_creation_impl.h @@ -110,6 +110,8 @@ class ResourceCreationImpl : public ppapi::thunk::ResourceCreationAPI { uint32_t size) OVERRIDE; virtual PP_Resource CreateScrollbar(PP_Instance instance, PP_Bool vertical) OVERRIDE; + virtual PP_Resource CreateOutputProtectionPrivate( + PP_Instance instance) OVERRIDE; virtual PP_Resource CreateTalk(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateTCPServerSocketPrivate( PP_Instance instance) OVERRIDE; diff --git a/chromium/content/renderer/pepper/url_request_info_util.cc b/chromium/content/renderer/pepper/url_request_info_util.cc index 92ecdfbfde0..500b7bd2e75 100644 --- a/chromium/content/renderer/pepper/url_request_info_util.cc +++ b/chromium/content/renderer/pepper/url_request_info_util.cc @@ -32,12 +32,12 @@ using ppapi::Resource; using ppapi::URLRequestInfoData; using ppapi::thunk::EnterResourceNoLock; -using WebKit::WebData; -using WebKit::WebHTTPBody; -using WebKit::WebString; -using WebKit::WebFrame; -using WebKit::WebURL; -using WebKit::WebURLRequest; +using blink::WebData; +using blink::WebHTTPBody; +using blink::WebString; +using blink::WebFrame; +using blink::WebURL; +using blink::WebURLRequest; namespace content { @@ -177,7 +177,7 @@ bool CreateWebURLRequest(PP_Instance instance, if (data->has_custom_user_agent) { bool was_after_preconnect_request = false; dest->setExtraData(new webkit_glue::WebURLRequestExtraDataImpl( - WebKit::WebReferrerPolicyDefault, // Ignored. + blink::WebReferrerPolicyDefault, // Ignored. WebString::fromUTF8(data->custom_user_agent), was_after_preconnect_request)); } diff --git a/chromium/content/renderer/pepper/url_request_info_util.h b/chromium/content/renderer/pepper/url_request_info_util.h index 2fb40e676a2..aaafb234703 100644 --- a/chromium/content/renderer/pepper/url_request_info_util.h +++ b/chromium/content/renderer/pepper/url_request_info_util.h @@ -13,7 +13,7 @@ namespace ppapi { struct URLRequestInfoData; } -namespace WebKit { +namespace blink { class WebFrame; class WebURLRequest; } @@ -26,8 +26,8 @@ namespace content { // pointers) will be populated by this function on success. CONTENT_EXPORT bool CreateWebURLRequest(PP_Instance instance, ppapi::URLRequestInfoData* data, - WebKit::WebFrame* frame, - WebKit::WebURLRequest* dest); + blink::WebFrame* frame, + blink::WebURLRequest* dest); // Returns true if universal access is required to use the given request. CONTENT_EXPORT bool URLRequestRequiresUniversalAccess( diff --git a/chromium/content/renderer/pepper/url_response_info_util.cc b/chromium/content/renderer/pepper/url_response_info_util.cc index eda54d4ba5b..6349226a1db 100644 --- a/chromium/content/renderer/pepper/url_response_info_util.cc +++ b/chromium/content/renderer/pepper/url_response_info_util.cc @@ -19,9 +19,9 @@ #include "third_party/WebKit/public/platform/WebURL.h" #include "third_party/WebKit/public/platform/WebURLResponse.h" -using WebKit::WebHTTPHeaderVisitor; -using WebKit::WebString; -using WebKit::WebURLResponse; +using blink::WebHTTPHeaderVisitor; +using blink::WebString; +using blink::WebURLResponse; namespace content { diff --git a/chromium/content/renderer/pepper/url_response_info_util.h b/chromium/content/renderer/pepper/url_response_info_util.h index ee0c23839f7..d7570627ed0 100644 --- a/chromium/content/renderer/pepper/url_response_info_util.h +++ b/chromium/content/renderer/pepper/url_response_info_util.h @@ -9,7 +9,7 @@ #include "ppapi/c/pp_instance.h" #include "ppapi/shared_impl/url_response_info_data.h" -namespace WebKit { +namespace blink { class WebURLResponse; } @@ -24,7 +24,7 @@ typedef base::Callback<void(const ppapi::URLResponseInfoData&)> // passed to the plugin. void DataFromWebURLResponse(RendererPpapiHostImpl* host_impl, PP_Instance pp_instance, - const WebKit::WebURLResponse& response, + const blink::WebURLResponse& response, const DataFromWebURLResponseCallback& callback); } // namespace content diff --git a/chromium/content/renderer/pepper/usb_key_code_conversion.cc b/chromium/content/renderer/pepper/usb_key_code_conversion.cc index a166593c5bf..129e663a5ed 100644 --- a/chromium/content/renderer/pepper/usb_key_code_conversion.cc +++ b/chromium/content/renderer/pepper/usb_key_code_conversion.cc @@ -6,7 +6,7 @@ #include "build/build_config.h" -using WebKit::WebKeyboardEvent; +using blink::WebKeyboardEvent; namespace content { diff --git a/chromium/content/renderer/pepper/usb_key_code_conversion.h b/chromium/content/renderer/pepper/usb_key_code_conversion.h index 1fcd04a9a18..9554c57222a 100644 --- a/chromium/content/renderer/pepper/usb_key_code_conversion.h +++ b/chromium/content/renderer/pepper/usb_key_code_conversion.h @@ -7,9 +7,9 @@ #include "ppapi/c/pp_stdint.h" -namespace WebKit { +namespace blink { class WebKeyboardEvent; -} // namespace WebKit +} // namespace blink namespace content { @@ -18,11 +18,11 @@ namespace content { // The code consists of the USB Page (in the high-order 16-bit word) and // USB Usage Id of the key. If no translation can be performed then zero // is returned. -uint32_t UsbKeyCodeForKeyboardEvent(const WebKit::WebKeyboardEvent& key_event); +uint32_t UsbKeyCodeForKeyboardEvent(const blink::WebKeyboardEvent& key_event); // Returns a string that represents the UI Event |code| parameter as specified // in http://www.w3.org/TR/uievents/ -const char* CodeForKeyboardEvent(const WebKit::WebKeyboardEvent& key_event); +const char* CodeForKeyboardEvent(const blink::WebKeyboardEvent& key_event); } // namespace content diff --git a/chromium/content/renderer/pepper/usb_key_code_conversion_linux.cc b/chromium/content/renderer/pepper/usb_key_code_conversion_linux.cc index c50fe4ebb38..8b9a4a52181 100644 --- a/chromium/content/renderer/pepper/usb_key_code_conversion_linux.cc +++ b/chromium/content/renderer/pepper/usb_key_code_conversion_linux.cc @@ -6,9 +6,9 @@ #include "base/basictypes.h" #include "third_party/WebKit/public/web/WebInputEvent.h" -#include "ui/base/keycodes/keycode_converter.h" +#include "ui/events/keycodes/dom4/keycode_converter.h" -using WebKit::WebKeyboardEvent; +using blink::WebKeyboardEvent; namespace content { diff --git a/chromium/content/renderer/pepper/usb_key_code_conversion_mac.cc b/chromium/content/renderer/pepper/usb_key_code_conversion_mac.cc index bcead0e7895..c701b48453c 100644 --- a/chromium/content/renderer/pepper/usb_key_code_conversion_mac.cc +++ b/chromium/content/renderer/pepper/usb_key_code_conversion_mac.cc @@ -6,9 +6,9 @@ #include "base/basictypes.h" #include "third_party/WebKit/public/web/WebInputEvent.h" -#include "ui/base/keycodes/keycode_converter.h" +#include "ui/events/keycodes/dom4/keycode_converter.h" -using WebKit::WebKeyboardEvent; +using blink::WebKeyboardEvent; namespace content { diff --git a/chromium/content/renderer/pepper/usb_key_code_conversion_win.cc b/chromium/content/renderer/pepper/usb_key_code_conversion_win.cc index b04cd7366b3..c9e0592b843 100644 --- a/chromium/content/renderer/pepper/usb_key_code_conversion_win.cc +++ b/chromium/content/renderer/pepper/usb_key_code_conversion_win.cc @@ -6,9 +6,9 @@ #include "base/basictypes.h" #include "third_party/WebKit/public/web/WebInputEvent.h" -#include "ui/base/keycodes/keycode_converter.h" +#include "ui/events/keycodes/dom4/keycode_converter.h" -using WebKit::WebKeyboardEvent; +using blink::WebKeyboardEvent; namespace content { @@ -23,8 +23,13 @@ uint32_t UsbKeyCodeForKeyboardEvent(const WebKeyboardEvent& key_event) { } const char* CodeForKeyboardEvent(const WebKeyboardEvent& key_event) { + // Extract the scancode and extended bit from the native key event's lParam. + int scancode = (key_event.nativeKeyCode >> 16) & 0x000000FF; + if ((key_event.nativeKeyCode & (1 << 24)) != 0) + scancode |= 0xe000; + ui::KeycodeConverter* key_converter = ui::KeycodeConverter::GetInstance(); - return key_converter->NativeKeycodeToCode(key_event.nativeKeyCode); + return key_converter->NativeKeycodeToCode(scancode); } } // namespace content diff --git a/chromium/content/renderer/pepper/v8_var_converter.cc b/chromium/content/renderer/pepper/v8_var_converter.cc index 062922aed12..3f8b37e2878 100644 --- a/chromium/content/renderer/pepper/v8_var_converter.cc +++ b/chromium/content/renderer/pepper/v8_var_converter.cc @@ -81,7 +81,8 @@ typedef base::hash_set<HashedHandle> ParentHandleSet; // associated with it in the map will be returned, otherwise a new V8 value will // be created and added to the map. |did_create| indicates whether a new v8 // value was created as a result of calling the function. -bool GetOrCreateV8Value(const PP_Var& var, +bool GetOrCreateV8Value(v8::Isolate* isolate, + const PP_Var& var, v8::Handle<v8::Value>* result, bool* did_create, VarHandleMap* visited_ids, @@ -100,13 +101,15 @@ bool GetOrCreateV8Value(const PP_Var& var, switch (var.type) { case PP_VARTYPE_UNDEFINED: - *result = v8::Undefined(); + *result = v8::Undefined(isolate); break; case PP_VARTYPE_NULL: - *result = v8::Null(); + *result = v8::Null(isolate); break; case PP_VARTYPE_BOOL: - *result = (var.value.as_bool == PP_TRUE) ? v8::True() : v8::False(); + *result = (var.value.as_bool == PP_TRUE) + ? v8::True(isolate) + : v8::False(isolate); break; case PP_VARTYPE_INT32: *result = v8::Integer::New(var.value.as_int); @@ -125,7 +128,10 @@ bool GetOrCreateV8Value(const PP_Var& var, // Create a string object rather than a string primitive. This allows us // to have multiple references to the same string in javascript, which // matches the reference behavior of PP_Vars. - *result = v8::String::New(value.c_str(), value.size())->ToObject(); + *result = v8::String::NewFromUtf8(isolate, + value.c_str(), + v8::String::kNormalString, + value.size())->ToObject(); break; } case PP_VARTYPE_ARRAY_BUFFER: { @@ -137,12 +143,11 @@ bool GetOrCreateV8Value(const PP_Var& var, } HostArrayBufferVar* host_buffer = static_cast<HostArrayBufferVar*>(buffer); - *result = - v8::Local<v8::Value>::New(host_buffer->webkit_buffer().toV8Value()); + *result = host_buffer->webkit_buffer().toV8Value(); break; } case PP_VARTYPE_ARRAY: - *result = v8::Array::New(); + *result = v8::Array::New(isolate); break; case PP_VARTYPE_DICTIONARY: *result = v8::Object::New(); @@ -151,7 +156,6 @@ bool GetOrCreateV8Value(const PP_Var& var, case PP_VARTYPE_RESOURCE: // TODO(mgiuca): Convert PP_VARTYPE_RESOURCE vars into the correct V8 // type. (http://crbug.com/177017) - NOTREACHED(); result->Clear(); return false; } @@ -168,6 +172,7 @@ bool GetOrCreateV8Value(const PP_Var& var, // the map. |did_create| indicates if a new PP_Var was created as a result of // calling the function. bool GetOrCreateVar(v8::Handle<v8::Value> val, + v8::Handle<v8::Context> context, PP_Var* result, bool* did_create, HandleVarMap* visited_handles, @@ -207,14 +212,20 @@ bool GetOrCreateVar(v8::Handle<v8::Value> val, } else if (val->IsArray()) { *result = (new ArrayVar())->GetPPVar(); } else if (val->IsObject()) { - scoped_ptr<WebKit::WebArrayBuffer> web_array_buffer( - WebKit::WebArrayBuffer::createFromV8Value(val)); + scoped_ptr<blink::WebArrayBuffer> web_array_buffer( + blink::WebArrayBuffer::createFromV8Value(val)); if (web_array_buffer.get()) { scoped_refptr<HostArrayBufferVar> buffer_var(new HostArrayBufferVar( *web_array_buffer)); *result = buffer_var->GetPPVar(); } else { - *result = (new DictionaryVar())->GetPPVar(); + bool was_resource; + if (!resource_converter->FromV8Value(val->ToObject(), context, result, + &was_resource)) + return false; + if (!was_resource) { + *result = (new DictionaryVar())->GetPPVar(); + } } } else { // Silently ignore the case where we can't convert to a Var as we may @@ -268,14 +279,15 @@ bool V8VarConverter::ToV8Value(const PP_Var& var, v8::Handle<v8::Context> context, v8::Handle<v8::Value>* result) { v8::Context::Scope context_scope(context); - v8::HandleScope handle_scope(context->GetIsolate()); + v8::Isolate* isolate = context->GetIsolate(); + v8::EscapableHandleScope handle_scope(isolate); VarHandleMap visited_ids; ParentVarSet parent_ids; std::stack<StackEntry<PP_Var> > stack; stack.push(StackEntry<PP_Var>(var)); - v8::Handle<v8::Value> root; + v8::Local<v8::Value> root; bool is_root = true; while (!stack.empty()) { @@ -292,7 +304,7 @@ bool V8VarConverter::ToV8Value(const PP_Var& var, } bool did_create = false; - if (!GetOrCreateV8Value(current_var, ¤t_v8, &did_create, + if (!GetOrCreateV8Value(isolate, current_var, ¤t_v8, &did_create, &visited_ids, &parent_ids)) { return false; } @@ -316,7 +328,7 @@ bool V8VarConverter::ToV8Value(const PP_Var& var, for (size_t i = 0; i < array_var->elements().size(); ++i) { const PP_Var& child_var = array_var->elements()[i].get(); v8::Handle<v8::Value> child_v8; - if (!GetOrCreateV8Value(child_var, &child_v8, &did_create, + if (!GetOrCreateV8Value(isolate, child_var, &child_v8, &did_create, &visited_ids, &parent_ids)) { return false; } @@ -346,14 +358,18 @@ bool V8VarConverter::ToV8Value(const PP_Var& var, const std::string& key = iter->first; const PP_Var& child_var = iter->second.get(); v8::Handle<v8::Value> child_v8; - if (!GetOrCreateV8Value(child_var, &child_v8, &did_create, + if (!GetOrCreateV8Value(isolate, child_var, &child_v8, &did_create, &visited_ids, &parent_ids)) { return false; } if (did_create && CanHaveChildren(child_var)) stack.push(child_var); v8::TryCatch try_catch; - v8_object->Set(v8::String::New(key.c_str(), key.length()), child_v8); + v8_object->Set(v8::String::NewFromUtf8(isolate, + key.c_str(), + v8::String::kNormalString, + key.length()), + child_v8); if (try_catch.HasCaught()) { LOG(ERROR) << "Setter for property " << key.c_str() << " threw an " << "exception."; @@ -363,7 +379,7 @@ bool V8VarConverter::ToV8Value(const PP_Var& var, } } - *result = handle_scope.Close(root); + *result = handle_scope.Escape(root); return true; } @@ -396,7 +412,7 @@ void V8VarConverter::FromV8Value( } bool did_create = false; - if (!GetOrCreateVar(current_v8, ¤t_var, &did_create, + if (!GetOrCreateVar(current_v8, context, ¤t_var, &did_create, &visited_handles, &parent_handles, resource_converter_.get())) { message_loop_proxy_->PostTask(FROM_HERE, @@ -436,7 +452,7 @@ void V8VarConverter::FromV8Value( continue; PP_Var child_var; - if (!GetOrCreateVar(child_v8, &child_var, &did_create, + if (!GetOrCreateVar(child_v8, context, &child_var, &did_create, &visited_handles, &parent_handles, resource_converter_.get())) { message_loop_proxy_->PostTask(FROM_HERE, @@ -467,7 +483,7 @@ void V8VarConverter::FromV8Value( // Extend this test to cover more types as necessary and if sensible. if (!key->IsString() && !key->IsNumber()) { - NOTREACHED() << "Key \"" << *v8::String::AsciiValue(key) << "\" " + NOTREACHED() << "Key \"" << *v8::String::Utf8Value(key) << "\" " "is neither a string nor a number"; message_loop_proxy_->PostTask(FROM_HERE, base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); @@ -489,7 +505,7 @@ void V8VarConverter::FromV8Value( } PP_Var child_var; - if (!GetOrCreateVar(child_v8, &child_var, &did_create, + if (!GetOrCreateVar(child_v8, context, &child_var, &did_create, &visited_handles, &parent_handles, resource_converter_.get())) { message_loop_proxy_->PostTask(FROM_HERE, diff --git a/chromium/content/renderer/pepper/v8_var_converter_unittest.cc b/chromium/content/renderer/pepper/v8_var_converter_unittest.cc index 878c39bc623..afe85fddf3c 100644 --- a/chromium/content/renderer/pepper/v8_var_converter_unittest.cc +++ b/chromium/content/renderer/pepper/v8_var_converter_unittest.cc @@ -49,6 +49,13 @@ class MockResourceConverter : public content::ResourceConverter { virtual void Flush(const base::Callback<void(bool)>& callback) OVERRIDE { callback.Run(true); } + virtual bool FromV8Value(v8::Handle<v8::Object> val, + v8::Handle<v8::Context> context, + PP_Var* result, + bool* was_resource) OVERRIDE { + *was_resource = false; + return true; + } }; // Maps PP_Var IDs to the V8 value handle they correspond to. @@ -162,7 +169,7 @@ class V8VarConverterTest : public testing::Test { context_.Reset(isolate_, v8::Context::New(isolate_, NULL, global)); } virtual void TearDown() { - context_.Dispose(); + context_.Reset(); ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty()); ProxyLock::Release(); } @@ -194,9 +201,9 @@ class V8VarConverterTest : public testing::Test { bool RoundTrip(const PP_Var& var, PP_Var* result) { v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); v8::Handle<v8::Value> v8_result; if (!converter_->ToV8Value(var, context, &v8_result)) return false; @@ -322,9 +329,9 @@ TEST_F(V8VarConverterTest, DictionaryArrayRoundTripTest) { TEST_F(V8VarConverterTest, Cycles) { // Check that cycles aren't converted. v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); // Var->V8 conversion. { @@ -358,14 +365,17 @@ TEST_F(V8VarConverterTest, Cycles) { // V8->Var conversion. { - v8::Handle<v8::Object> object = v8::Object::New(); - v8::Handle<v8::Array> array = v8::Array::New(); + v8::Handle<v8::Object> object = v8::Object::New(isolate_); + v8::Handle<v8::Array> array = v8::Array::New(isolate_); PP_Var var_result; // Array <-> dictionary cycle. std::string key = "1"; - object->Set(v8::String::New(key.c_str(), key.length()), array); + object->Set( + v8::String::NewFromUtf8( + isolate_, key.c_str(), v8::String::kNormalString, key.length()), + array); array->Set(0, object); ASSERT_FALSE(FromV8ValueSync(object, context, &var_result)); @@ -388,7 +398,9 @@ TEST_F(V8VarConverterTest, StrangeDictionaryKeyTest) { { // Test non-string key types. They should be cast to strings. v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); + v8::Local<v8::Context> context = + v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); const char* source = "(function() {" "return {" @@ -401,7 +413,8 @@ TEST_F(V8VarConverterTest, StrangeDictionaryKeyTest) { "};" "})();"; - v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); + v8::Handle<v8::Script> script( + v8::Script::New(v8::String::NewFromUtf8(isolate_, source))); v8::Handle<v8::Object> object = script->Run().As<v8::Object>(); ASSERT_FALSE(object.IsEmpty()); diff --git a/chromium/content/renderer/render_frame_impl.cc b/chromium/content/renderer/render_frame_impl.cc index 2cec72d37c3..2d9628e41b9 100644 --- a/chromium/content/renderer/render_frame_impl.cc +++ b/chromium/content/renderer/render_frame_impl.cc @@ -4,12 +4,19 @@ #include "content/renderer/render_frame_impl.h" +#include <map> +#include <string> + #include "base/command_line.h" +#include "base/i18n/char_iterator.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "content/child/appcache/appcache_dispatcher.h" +#include "content/child/plugin_messages.h" #include "content/child/quota_dispatcher.h" #include "content/child/request_extra_data.h" +#include "content/child/service_worker/web_service_worker_provider_impl.h" +#include "content/common/frame_messages.h" #include "content/common/socket_stream_handle_data.h" #include "content/common/swapped_out_messages.h" #include "content/common/view_messages.h" @@ -19,15 +26,20 @@ #include "content/public/renderer/content_renderer_client.h" #include "content/public/renderer/document_state.h" #include "content/public/renderer/navigation_state.h" +#include "content/public/renderer/render_frame_observer.h" +#include "content/renderer/accessibility/renderer_accessibility.h" #include "content/renderer/browser_plugin/browser_plugin.h" #include "content/renderer/browser_plugin/browser_plugin_manager.h" #include "content/renderer/internal_document_state_data.h" +#include "content/renderer/npapi/plugin_channel_host.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_view_impl.h" +#include "content/renderer/render_widget_fullscreen_pepper.h" #include "content/renderer/renderer_webapplicationcachehost_impl.h" #include "content/renderer/websharedworker_proxy.h" #include "net/base/net_errors.h" #include "net/http/http_util.h" +#include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURL.h" #include "third_party/WebKit/public/platform/WebURLError.h" @@ -40,38 +52,53 @@ #include "third_party/WebKit/public/web/WebPluginParams.h" #include "third_party/WebKit/public/web/WebSearchableFormData.h" #include "third_party/WebKit/public/web/WebSecurityOrigin.h" -#include "third_party/WebKit/public/web/WebStorageQuotaCallbacks.h" #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" #include "third_party/WebKit/public/web/WebView.h" #include "webkit/child/weburlresponse_extradata_impl.h" +#if defined(ENABLE_PLUGINS) +#include "content/renderer/npapi/webplugin_impl.h" +#include "content/renderer/pepper/pepper_browser_connection.h" +#include "content/renderer/pepper/pepper_plugin_instance_impl.h" +#include "content/renderer/pepper/pepper_webplugin_impl.h" +#include "content/renderer/pepper/plugin_module.h" +#endif + #if defined(ENABLE_WEBRTC) #include "content/renderer/media/rtc_peer_connection_handler.h" #endif -using WebKit::WebDataSource; -using WebKit::WebDocument; -using WebKit::WebFrame; -using WebKit::WebNavigationPolicy; -using WebKit::WebPluginParams; -using WebKit::WebReferrerPolicy; -using WebKit::WebSearchableFormData; -using WebKit::WebSecurityOrigin; -using WebKit::WebStorageQuotaCallbacks; -using WebKit::WebString; -using WebKit::WebURL; -using WebKit::WebURLError; -using WebKit::WebURLRequest; -using WebKit::WebURLResponse; -using WebKit::WebUserGestureIndicator; -using WebKit::WebVector; -using WebKit::WebView; +using blink::WebDataSource; +using blink::WebDocument; +using blink::WebFrame; +using blink::WebNavigationPolicy; +using blink::WebPluginParams; +using blink::WebReferrerPolicy; +using blink::WebSearchableFormData; +using blink::WebSecurityOrigin; +using blink::WebServiceWorkerProvider; +using blink::WebStorageQuotaCallbacks; +using blink::WebString; +using blink::WebURL; +using blink::WebURLError; +using blink::WebURLRequest; +using blink::WebURLResponse; +using blink::WebUserGestureIndicator; +using blink::WebVector; +using blink::WebView; using base::Time; using base::TimeDelta; using webkit_glue::WebURLResponseExtraDataImpl; namespace content { +namespace { + +typedef std::map<blink::WebFrame*, RenderFrameImpl*> FrameMap; +base::LazyInstance<FrameMap> g_child_frame_map = LAZY_INSTANCE_INITIALIZER; + +} // namespace + static RenderFrameImpl* (*g_create_render_frame_impl)(RenderViewImpl*, int32) = NULL; @@ -80,13 +107,10 @@ RenderFrameImpl* RenderFrameImpl::Create(RenderViewImpl* render_view, int32 routing_id) { DCHECK(routing_id != MSG_ROUTING_NONE); - RenderFrameImpl* render_frame = NULL; if (g_create_render_frame_impl) - render_frame = g_create_render_frame_impl(render_view, routing_id); + return g_create_render_frame_impl(render_view, routing_id); else - render_frame = new RenderFrameImpl(render_view, routing_id); - - return render_frame; + return new RenderFrameImpl(render_view, routing_id); } // static @@ -102,18 +126,318 @@ RenderFrameImpl::RenderFrameImpl(RenderViewImpl* render_view, int routing_id) routing_id_(routing_id), is_swapped_out_(false), is_detaching_(false) { + RenderThread::Get()->AddRoute(routing_id_, this); +#if defined(ENABLE_PLUGINS) + new PepperBrowserConnection(this); +#endif + + GetContentClient()->renderer()->RenderFrameCreated(this); } RenderFrameImpl::~RenderFrameImpl() { + FOR_EACH_OBSERVER(RenderFrameObserver, observers_, RenderFrameGone()); + FOR_EACH_OBSERVER(RenderFrameObserver, observers_, OnDestruct()); + RenderThread::Get()->RemoveRoute(routing_id_); } -int RenderFrameImpl::GetRoutingID() const { - return routing_id_; +RenderWidget* RenderFrameImpl::GetRenderWidget() { + return render_view_; +} + +#if defined(ENABLE_PLUGINS) +void RenderFrameImpl::PepperPluginCreated(RendererPpapiHost* host) { + FOR_EACH_OBSERVER(RenderFrameObserver, observers_, + DidCreatePepperPlugin(host)); +} + +void RenderFrameImpl::PepperInstanceCreated( + PepperPluginInstanceImpl* instance) { + active_pepper_instances_.insert(instance); +} + +void RenderFrameImpl::PepperInstanceDeleted( + PepperPluginInstanceImpl* instance) { + active_pepper_instances_.erase(instance); + + if (render_view_->pepper_last_mouse_event_target() == instance) + render_view_->set_pepper_last_mouse_event_target(NULL); + if (render_view_->focused_pepper_plugin() == instance) + PepperFocusChanged(instance, false); +} + +void RenderFrameImpl::PepperDidChangeCursor( + PepperPluginInstanceImpl* instance, + const blink::WebCursorInfo& cursor) { + // Update the cursor appearance immediately if the requesting plugin is the + // one which receives the last mouse event. Otherwise, the new cursor won't be + // picked up until the plugin gets the next input event. That is bad if, e.g., + // the plugin would like to set an invisible cursor when there isn't any user + // input for a while. + if (instance == render_view_->pepper_last_mouse_event_target()) + GetRenderWidget()->didChangeCursor(cursor); +} + +void RenderFrameImpl::PepperDidReceiveMouseEvent( + PepperPluginInstanceImpl* instance) { + render_view_->set_pepper_last_mouse_event_target(instance); +} + +void RenderFrameImpl::PepperFocusChanged(PepperPluginInstanceImpl* instance, + bool focused) { + if (focused) + render_view_->set_focused_pepper_plugin(instance); + else if (render_view_->focused_pepper_plugin() == instance) + render_view_->set_focused_pepper_plugin(NULL); + + GetRenderWidget()->UpdateTextInputType(); + GetRenderWidget()->UpdateSelectionBounds(); +} + +void RenderFrameImpl::PepperTextInputTypeChanged( + PepperPluginInstanceImpl* instance) { + if (instance != render_view_->focused_pepper_plugin()) + return; + + GetRenderWidget()->UpdateTextInputType(); + if (render_view_->renderer_accessibility()) { + render_view_->renderer_accessibility()->FocusedNodeChanged( + blink::WebNode()); + } +} + +void RenderFrameImpl::PepperCaretPositionChanged( + PepperPluginInstanceImpl* instance) { + if (instance != render_view_->focused_pepper_plugin()) + return; + GetRenderWidget()->UpdateSelectionBounds(); +} + +void RenderFrameImpl::PepperCancelComposition( + PepperPluginInstanceImpl* instance) { + if (instance != render_view_->focused_pepper_plugin()) + return; + Send(new ViewHostMsg_ImeCancelComposition(render_view_->GetRoutingID()));; +#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA) + GetRenderWidget()->UpdateCompositionInfo(true); +#endif +} + +void RenderFrameImpl::PepperSelectionChanged( + PepperPluginInstanceImpl* instance) { + if (instance != render_view_->focused_pepper_plugin()) + return; + render_view_->SyncSelectionIfRequired(); +} + +RenderWidgetFullscreenPepper* RenderFrameImpl::CreatePepperFullscreenContainer( + PepperPluginInstanceImpl* plugin) { + GURL active_url; + if (render_view_->webview() && render_view_->webview()->mainFrame()) + active_url = GURL(render_view_->webview()->mainFrame()->document().url()); + RenderWidgetFullscreenPepper* widget = RenderWidgetFullscreenPepper::Create( + GetRenderWidget()->routing_id(), plugin, active_url, + GetRenderWidget()->screenInfo()); + widget->show(blink::WebNavigationPolicyIgnore); + return widget; +} + +bool RenderFrameImpl::IsPepperAcceptingCompositionEvents() const { + if (!render_view_->focused_pepper_plugin()) + return false; + return render_view_->focused_pepper_plugin()-> + IsPluginAcceptingCompositionEvents(); +} + +void RenderFrameImpl::PluginCrashed(const base::FilePath& plugin_path, + base::ProcessId plugin_pid) { + // TODO(jam): dispatch this IPC in RenderFrameHost and switch to use + // routing_id_ as a result. + Send(new FrameHostMsg_PluginCrashed(routing_id_, plugin_path, plugin_pid)); +} + +void RenderFrameImpl::DidInitiatePaint() { + // Notify all instances that we painted. The same caveats apply as for + // ViewFlushedPaint regarding instances closing themselves, so we take + // similar precautions. + PepperPluginSet plugins = active_pepper_instances_; + for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) { + if (active_pepper_instances_.find(*i) != active_pepper_instances_.end()) + (*i)->ViewInitiatedPaint(); + } +} + +void RenderFrameImpl::DidFlushPaint() { + // Notify all instances that we flushed. This will call into the plugin, and + // we it may ask to close itself as a result. This will, in turn, modify our + // set, possibly invalidating the iterator. So we iterate on a copy that + // won't change out from under us. + PepperPluginSet plugins = active_pepper_instances_; + for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) { + // The copy above makes sure our iterator is never invalid if some plugins + // are destroyed. But some plugin may decide to close all of its views in + // response to a paint in one of them, so we need to make sure each one is + // still "current" before using it. + // + // It's possible that a plugin was destroyed, but another one was created + // with the same address. In this case, we'll call ViewFlushedPaint on that + // new plugin. But that's OK for this particular case since we're just + // notifying all of our instances that the view flushed, and the new one is + // one of our instances. + // + // What about the case where a new one is created in a callback at a new + // address and we don't issue the callback? We're still OK since this + // callback is used for flush callbacks and we could not have possibly + // started a new paint for the new plugin while processing a previous paint + // for an existing one. + if (active_pepper_instances_.find(*i) != active_pepper_instances_.end()) + (*i)->ViewFlushedPaint(); + } +} + +PepperPluginInstanceImpl* RenderFrameImpl::GetBitmapForOptimizedPluginPaint( + const gfx::Rect& paint_bounds, + TransportDIB** dib, + gfx::Rect* location, + gfx::Rect* clip, + float* scale_factor) { + for (PepperPluginSet::iterator i = active_pepper_instances_.begin(); + i != active_pepper_instances_.end(); ++i) { + PepperPluginInstanceImpl* instance = *i; + // In Flash fullscreen , the plugin contents should be painted onto the + // fullscreen widget instead of the web page. + if (!instance->FlashIsFullscreenOrPending() && + instance->GetBitmapForOptimizedPluginPaint(paint_bounds, dib, location, + clip, scale_factor)) + return *i; + } + return NULL; +} + +void RenderFrameImpl::PageVisibilityChanged(bool shown) { + // Inform PPAPI plugins that their page is no longer visible. + for (PepperPluginSet::iterator i = active_pepper_instances_.begin(); + i != active_pepper_instances_.end(); ++i) + (*i)->PageVisibilityChanged(shown); +} + +void RenderFrameImpl::OnSetFocus(bool enable) { + // Notify all Pepper plugins. + for (PepperPluginSet::iterator i = active_pepper_instances_.begin(); + i != active_pepper_instances_.end(); ++i) + (*i)->SetContentAreaFocus(enable); +} + +void RenderFrameImpl::WillHandleMouseEvent(const blink::WebMouseEvent& event) { + // This method is called for every mouse event that the render view receives. + // And then the mouse event is forwarded to WebKit, which dispatches it to the + // event target. Potentially a Pepper plugin will receive the event. + // In order to tell whether a plugin gets the last mouse event and which it + // is, we set |pepper_last_mouse_event_target_| to NULL here. If a plugin gets + // the event, it will notify us via DidReceiveMouseEvent() and set itself as + // |pepper_last_mouse_event_target_|. + render_view_->set_pepper_last_mouse_event_target(NULL); } +void RenderFrameImpl::SimulateImeSetComposition( + const base::string16& text, + const std::vector<blink::WebCompositionUnderline>& underlines, + int selection_start, + int selection_end) { + render_view_->OnImeSetComposition( + text, underlines, selection_start, selection_end); +} + +void RenderFrameImpl::SimulateImeConfirmComposition( + const base::string16& text, + const gfx::Range& replacement_range) { + render_view_->OnImeConfirmComposition(text, replacement_range, false); +} + + +void RenderFrameImpl::OnImeSetComposition( + const base::string16& text, + const std::vector<blink::WebCompositionUnderline>& underlines, + int selection_start, + int selection_end) { + // When a PPAPI plugin has focus, we bypass WebKit. + if (!IsPepperAcceptingCompositionEvents()) { + pepper_composition_text_ = text; + } else { + // TODO(kinaba) currently all composition events are sent directly to + // plugins. Use DOM event mechanism after WebKit is made aware about + // plugins that support composition. + // The code below mimics the behavior of WebCore::Editor::setComposition. + + // Empty -> nonempty: composition started. + if (pepper_composition_text_.empty() && !text.empty()) { + render_view_->focused_pepper_plugin()->HandleCompositionStart( + base::string16()); + } + // Nonempty -> empty: composition canceled. + if (!pepper_composition_text_.empty() && text.empty()) { + render_view_->focused_pepper_plugin()->HandleCompositionEnd( + base::string16()); + } + pepper_composition_text_ = text; + // Nonempty: composition is ongoing. + if (!pepper_composition_text_.empty()) { + render_view_->focused_pepper_plugin()->HandleCompositionUpdate( + pepper_composition_text_, underlines, selection_start, + selection_end); + } + } +} + +void RenderFrameImpl::OnImeConfirmComposition( + const base::string16& text, + const gfx::Range& replacement_range, + bool keep_selection) { + // When a PPAPI plugin has focus, we bypass WebKit. + // Here, text.empty() has a special meaning. It means to commit the last + // update of composition text (see + // RenderWidgetHost::ImeConfirmComposition()). + const base::string16& last_text = text.empty() ? pepper_composition_text_ + : text; + + // last_text is empty only when both text and pepper_composition_text_ is. + // Ignore it. + if (last_text.empty()) + return; + + if (!IsPepperAcceptingCompositionEvents()) { + base::i18n::UTF16CharIterator iterator(&last_text); + int32 i = 0; + while (iterator.Advance()) { + blink::WebKeyboardEvent char_event; + char_event.type = blink::WebInputEvent::Char; + char_event.timeStampSeconds = base::Time::Now().ToDoubleT(); + char_event.modifiers = 0; + char_event.windowsKeyCode = last_text[i]; + char_event.nativeKeyCode = last_text[i]; + + const int32 char_start = i; + for (; i < iterator.array_pos(); ++i) { + char_event.text[i - char_start] = last_text[i]; + char_event.unmodifiedText[i - char_start] = last_text[i]; + } + + if (GetRenderWidget()->webwidget()) + GetRenderWidget()->webwidget()->handleInputEvent(char_event); + } + } else { + // Mimics the order of events sent by WebKit. + // See WebCore::Editor::setComposition() for the corresponding code. + render_view_->focused_pepper_plugin()->HandleCompositionEnd(last_text); + render_view_->focused_pepper_plugin()->HandleTextInput(last_text); + } + pepper_composition_text_.clear(); +} + +#endif // ENABLE_PLUGINS + bool RenderFrameImpl::Send(IPC::Message* message) { if (is_detaching_ || - (is_swapped_out_ && + ((is_swapped_out_ || render_view_->is_swapped_out()) && !SwappedOutMessages::CanSendWhileSwappedOut(message))) { delete message; return false; @@ -123,85 +447,121 @@ bool RenderFrameImpl::Send(IPC::Message* message) { } bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) { + ObserverListBase<RenderFrameObserver>::Iterator it(observers_); + RenderFrameObserver* observer; + while ((observer = it.GetNext()) != NULL) { + if (observer->OnMessageReceived(msg)) + return true; + } + // TODO(ajwong): Fill in with message handlers as various components // are migrated over to understand frames. return false; } -// WebKit::WebFrameClient implementation ------------------------------------- +RenderView* RenderFrameImpl::GetRenderView() { + return render_view_; +} + +int RenderFrameImpl::GetRoutingID() { + return routing_id_; +} + +WebPreferences& RenderFrameImpl::GetWebkitPreferences() { + return render_view_->GetWebkitPreferences(); +} + +int RenderFrameImpl::ShowContextMenu(ContextMenuClient* client, + const ContextMenuParams& params) { + return render_view_->ShowContextMenu(client, params); +} + +void RenderFrameImpl::CancelContextMenu(int request_id) { + return render_view_->CancelContextMenu(request_id); +} + +blink::WebPlugin* RenderFrameImpl::CreatePlugin( + blink::WebFrame* frame, + const WebPluginInfo& info, + const blink::WebPluginParams& params) { +#if defined(ENABLE_PLUGINS) + bool pepper_plugin_was_registered = false; + scoped_refptr<PluginModule> pepper_module(PluginModule::Create( + this, info, &pepper_plugin_was_registered)); + if (pepper_plugin_was_registered) { + if (pepper_module.get()) { + // TODO(jam): change to take RenderFrame. + return new PepperWebPluginImpl( + pepper_module.get(), params, render_view_->AsWeakPtr(), this); + } + } +#if defined(OS_CHROMEOS) + LOG(WARNING) << "Pepper module/plugin creation failed."; + return NULL; +#else + // TODO(jam): change to take RenderFrame. + return new WebPluginImpl(frame, params, info.path, render_view_->AsWeakPtr(), + this); +#endif +#else + return NULL; +#endif +} -WebKit::WebPlugin* RenderFrameImpl::createPlugin( - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params) { - WebKit::WebPlugin* plugin = NULL; +void RenderFrameImpl::LoadURLExternally( + blink::WebFrame* frame, + const blink::WebURLRequest& request, + blink::WebNavigationPolicy policy) { + loadURLExternally(frame, request, policy); +} + +// blink::WebFrameClient implementation ---------------------------------------- + +blink::WebPlugin* RenderFrameImpl::createPlugin( + blink::WebFrame* frame, + const blink::WebPluginParams& params) { + blink::WebPlugin* plugin = NULL; if (GetContentClient()->renderer()->OverrideCreatePlugin( - render_view_, frame, params, &plugin)) { + this, frame, params, &plugin)) { return plugin; } -#if defined(ENABLE_PLUGINS) if (UTF16ToASCII(params.mimeType) == kBrowserPluginMimeType) { return render_view_->GetBrowserPluginManager()->CreateBrowserPlugin( - render_view_, frame, params); + render_view_, frame); } +#if defined(ENABLE_PLUGINS) WebPluginInfo info; std::string mime_type; - bool found = render_view_->GetPluginInfo( - params.url, frame->top()->document().url(), params.mimeType.utf8(), - &info, &mime_type); + bool found = false; + Send(new FrameHostMsg_GetPluginInfo( + routing_id_, params.url, frame->top()->document().url(), + params.mimeType.utf8(), &found, &info, &mime_type)); if (!found) return NULL; WebPluginParams params_to_use = params; params_to_use.mimeType = WebString::fromUTF8(mime_type); - return render_view_->CreatePlugin(frame, info, params_to_use); + return CreatePlugin(frame, info, params_to_use); #else return NULL; #endif // defined(ENABLE_PLUGINS) } -WebKit::WebSharedWorker* RenderFrameImpl::createSharedWorker( - WebKit::WebFrame* frame, - const WebKit::WebURL& url, - const WebKit::WebString& name, - unsigned long long document_id) { - int route_id = MSG_ROUTING_NONE; - bool exists = false; - bool url_mismatch = false; - ViewHostMsg_CreateWorker_Params params; - params.url = url; - params.name = name; - params.document_id = document_id; - params.render_view_route_id = render_view_->GetRoutingID(); - params.route_id = MSG_ROUTING_NONE; - params.script_resource_appcache_id = 0; - render_view_->Send(new ViewHostMsg_LookupSharedWorker( - params, &exists, &route_id, &url_mismatch)); - if (url_mismatch) { - return NULL; - } else { - return new WebSharedWorkerProxy(RenderThreadImpl::current(), - document_id, - exists, - route_id, - render_view_->GetRoutingID()); - } -} - -WebKit::WebMediaPlayer* RenderFrameImpl::createMediaPlayer( - WebKit::WebFrame* frame, - const WebKit::WebURL& url, - WebKit::WebMediaPlayerClient* client) { +blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer( + blink::WebFrame* frame, + const blink::WebURL& url, + blink::WebMediaPlayerClient* client) { // TODO(nasko): Moving the implementation here involves moving a few media // related client objects here or referencing them in the RenderView. Needs // more work to understand where the proper place for those objects is. - return render_view_->createMediaPlayer(frame, url, client); + return render_view_->CreateMediaPlayer(this, frame, url, client); } -WebKit::WebApplicationCacheHost* RenderFrameImpl::createApplicationCacheHost( - WebKit::WebFrame* frame, - WebKit::WebApplicationCacheHostClient* client) { +blink::WebApplicationCacheHost* RenderFrameImpl::createApplicationCacheHost( + blink::WebFrame* frame, + blink::WebApplicationCacheHostClient* client) { if (!frame || !frame->view()) return NULL; return new RendererWebApplicationCacheHostImpl( @@ -209,26 +569,75 @@ WebKit::WebApplicationCacheHost* RenderFrameImpl::createApplicationCacheHost( RenderThreadImpl::current()->appcache_dispatcher()->backend_proxy()); } -WebKit::WebCookieJar* RenderFrameImpl::cookieJar(WebKit::WebFrame* frame) { +blink::WebWorkerPermissionClientProxy* +RenderFrameImpl::createWorkerPermissionClientProxy(WebFrame* frame) { + if (!frame || !frame->view()) + return NULL; + return GetContentClient()->renderer()->CreateWorkerPermissionClientProxy( + RenderViewImpl::FromWebView(frame->view()), frame); +} + +blink::WebCookieJar* RenderFrameImpl::cookieJar(blink::WebFrame* frame) { return render_view_->cookieJar(frame); } -void RenderFrameImpl::didAccessInitialDocument(WebKit::WebFrame* frame) { +blink::WebServiceWorkerProvider* RenderFrameImpl::createServiceWorkerProvider( + blink::WebFrame* frame, + blink::WebServiceWorkerProviderClient* client) { + return new WebServiceWorkerProviderImpl( + ChildThread::current()->thread_safe_sender(), + make_scoped_ptr(client)); +} + +void RenderFrameImpl::didAccessInitialDocument(blink::WebFrame* frame) { render_view_->didAccessInitialDocument(frame); } -void RenderFrameImpl::didCreateFrame(WebKit::WebFrame* parent, - WebKit::WebFrame* child) { - render_view_->Send(new ViewHostMsg_FrameAttached( - render_view_->GetRoutingID(), parent->identifier(), child->identifier(), - UTF16ToUTF8(child->assignedName()))); +blink::WebFrame* RenderFrameImpl::createChildFrame( + blink::WebFrame* parent, + const blink::WebString& name) { + RenderFrameImpl* child_render_frame = this; + long long child_frame_identifier = WebFrame::generateEmbedderIdentifier(); + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) { + // Synchronously notify the browser of a child frame creation to get the + // routing_id for the RenderFrame. + int routing_id; + Send(new FrameHostMsg_CreateChildFrame(routing_id_, + parent->identifier(), + child_frame_identifier, + UTF16ToUTF8(name), + &routing_id)); + child_render_frame = RenderFrameImpl::Create(render_view_, routing_id); + } + + blink::WebFrame* web_frame = WebFrame::create(child_render_frame, + child_frame_identifier); + + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) { + g_child_frame_map.Get().insert( + std::make_pair(web_frame, child_render_frame)); + } + + return web_frame; } -void RenderFrameImpl::didDisownOpener(WebKit::WebFrame* frame) { +void RenderFrameImpl::didDisownOpener(blink::WebFrame* frame) { render_view_->didDisownOpener(frame); } -void RenderFrameImpl::frameDetached(WebKit::WebFrame* frame) { +void RenderFrameImpl::frameDetached(blink::WebFrame* frame) { + // NOTE: This function is called on the frame that is being detached and not + // the parent frame. This is different from createChildFrame() which is + // called on the parent frame. + CHECK(!is_detaching_); + + int64 parent_frame_id = -1; + if (frame->parent()) + parent_frame_id = frame->parent()->identifier(); + + Send(new FrameHostMsg_Detach(routing_id_, parent_frame_id, + frame->identifier())); + // Currently multiple WebCore::Frames can send frameDetached to a single // RenderFrameImpl. This is legacy behavior from when RenderViewImpl served // as a shared WebFrameClient for multiple Webcore::Frame objects. It also @@ -236,32 +645,42 @@ void RenderFrameImpl::frameDetached(WebKit::WebFrame* frame) { // even though one WebCore::Frame may have detached itself, others will // still need to use this object. if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) { - // TODO(ajwong): Add CHECK(!is_detaching_) once we guarantee each - // RenderFrameImpl is only used by one WebCore::Frame. + // The |is_detaching_| flag disables Send(). FrameHostMsg_Detach must be + // sent before setting |is_detaching_| to true. In contrast, Observers + // should only be notified afterwards so they cannot call back into and + // have IPCs fired off. is_detaching_ = true; } - int64 parent_frame_id = -1; - if (frame->parent()) - parent_frame_id = frame->parent()->identifier(); - - render_view_->Send(new ViewHostMsg_FrameDetached(render_view_->GetRoutingID(), - parent_frame_id, - frame->identifier())); - // Call back to RenderViewImpl for observers to be notified. // TODO(nasko): Remove once we have RenderFrameObserver. render_view_->frameDetached(frame); + + frame->close(); + + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) { + // If the frame does not have a parent, it is the main frame. The main + // frame is owned by the containing RenderViewHost so it does not require + // any cleanup here. + if (frame->parent()) { + FrameMap::iterator it = g_child_frame_map.Get().find(frame); + DCHECK(it != g_child_frame_map.Get().end()); + DCHECK_EQ(it->second, this); + g_child_frame_map.Get().erase(it); + delete this; + // Object is invalid after this point. + } + } } -void RenderFrameImpl::willClose(WebKit::WebFrame* frame) { +void RenderFrameImpl::willClose(blink::WebFrame* frame) { // Call back to RenderViewImpl for observers to be notified. // TODO(nasko): Remove once we have RenderFrameObserver. render_view_->willClose(frame); } -void RenderFrameImpl::didChangeName(WebKit::WebFrame* frame, - const WebKit::WebString& name) { +void RenderFrameImpl::didChangeName(blink::WebFrame* frame, + const blink::WebString& name) { if (!render_view_->renderer_preferences_.report_frame_name_changes) return; @@ -272,19 +691,27 @@ void RenderFrameImpl::didChangeName(WebKit::WebFrame* frame, UTF16ToUTF8(name))); } -void RenderFrameImpl::loadURLExternally(WebKit::WebFrame* frame, - const WebKit::WebURLRequest& request, - WebKit::WebNavigationPolicy policy) { +void RenderFrameImpl::didMatchCSS( + blink::WebFrame* frame, + const blink::WebVector<blink::WebString>& newly_matching_selectors, + const blink::WebVector<blink::WebString>& stopped_matching_selectors) { + render_view_->didMatchCSS( + frame, newly_matching_selectors, stopped_matching_selectors); +} + +void RenderFrameImpl::loadURLExternally(blink::WebFrame* frame, + const blink::WebURLRequest& request, + blink::WebNavigationPolicy policy) { loadURLExternally(frame, request, policy, WebString()); } void RenderFrameImpl::loadURLExternally( - WebKit::WebFrame* frame, - const WebKit::WebURLRequest& request, - WebKit::WebNavigationPolicy policy, - const WebKit::WebString& suggested_name) { + blink::WebFrame* frame, + const blink::WebURLRequest& request, + blink::WebNavigationPolicy policy, + const blink::WebString& suggested_name) { Referrer referrer(RenderViewImpl::GetReferrerFromRequest(frame, request)); - if (policy == WebKit::WebNavigationPolicyDownload) { + if (policy == blink::WebNavigationPolicyDownload) { render_view_->Send(new ViewHostMsg_DownloadUrl(render_view_->GetRoutingID(), request.url(), referrer, suggested_name)); @@ -293,36 +720,36 @@ void RenderFrameImpl::loadURLExternally( } } -WebKit::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation( - WebKit::WebFrame* frame, - WebKit::WebDataSource::ExtraData* extra_data, - const WebKit::WebURLRequest& request, - WebKit::WebNavigationType type, - WebKit::WebNavigationPolicy default_policy, +blink::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation( + blink::WebFrame* frame, + blink::WebDataSource::ExtraData* extra_data, + const blink::WebURLRequest& request, + blink::WebNavigationType type, + blink::WebNavigationPolicy default_policy, bool is_redirect) { return render_view_->decidePolicyForNavigation( frame, extra_data, request, type, default_policy, is_redirect); } -WebKit::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation( - WebKit::WebFrame* frame, - const WebKit::WebURLRequest& request, - WebKit::WebNavigationType type, - WebKit::WebNavigationPolicy default_policy, +blink::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation( + blink::WebFrame* frame, + const blink::WebURLRequest& request, + blink::WebNavigationType type, + blink::WebNavigationPolicy default_policy, bool is_redirect) { return render_view_->decidePolicyForNavigation( frame, request, type, default_policy, is_redirect); } -void RenderFrameImpl::willSendSubmitEvent(WebKit::WebFrame* frame, - const WebKit::WebFormElement& form) { +void RenderFrameImpl::willSendSubmitEvent(blink::WebFrame* frame, + const blink::WebFormElement& form) { // Call back to RenderViewImpl for observers to be notified. // TODO(nasko): Remove once we have RenderFrameObserver. render_view_->willSendSubmitEvent(frame, form); } -void RenderFrameImpl::willSubmitForm(WebKit::WebFrame* frame, - const WebKit::WebFormElement& form) { +void RenderFrameImpl::willSubmitForm(blink::WebFrame* frame, + const blink::WebFormElement& form) { DocumentState* document_state = DocumentState::FromDataSource(frame->provisionalDataSource()); NavigationState* navigation_state = document_state->navigation_state(); @@ -345,8 +772,8 @@ void RenderFrameImpl::willSubmitForm(WebKit::WebFrame* frame, render_view_->willSubmitForm(frame, form); } -void RenderFrameImpl::didCreateDataSource(WebKit::WebFrame* frame, - WebKit::WebDataSource* datasource) { +void RenderFrameImpl::didCreateDataSource(blink::WebFrame* frame, + blink::WebDataSource* datasource) { // TODO(nasko): Move implementation here. Needed state: // * pending_navigation_params_ // * webview @@ -356,24 +783,64 @@ void RenderFrameImpl::didCreateDataSource(WebKit::WebFrame* frame, render_view_->didCreateDataSource(frame, datasource); } -void RenderFrameImpl::didStartProvisionalLoad(WebKit::WebFrame* frame) { - // TODO(nasko): Move implementation here. Needed state: - // * is_swapped_out_ - // * navigation_gesture_ - // * completed_client_redirect_src_ - render_view_->didStartProvisionalLoad(frame); +void RenderFrameImpl::didStartProvisionalLoad(blink::WebFrame* frame) { + WebDataSource* ds = frame->provisionalDataSource(); + + // In fast/loader/stop-provisional-loads.html, we abort the load before this + // callback is invoked. + if (!ds) + return; + + DocumentState* document_state = DocumentState::FromDataSource(ds); + + // We should only navigate to swappedout:// when is_swapped_out_ is true. + CHECK((ds->request().url() != GURL(kSwappedOutURL)) || + render_view_->is_swapped_out()) << + "Heard swappedout:// when not swapped out."; + + // Update the request time if WebKit has better knowledge of it. + if (document_state->request_time().is_null()) { + double event_time = ds->triggeringEventTime(); + if (event_time != 0.0) + document_state->set_request_time(Time::FromDoubleT(event_time)); + } + + // Start time is only set after request time. + document_state->set_start_load_time(Time::Now()); + + bool is_top_most = !frame->parent(); + if (is_top_most) { + render_view_->set_navigation_gesture( + WebUserGestureIndicator::isProcessingUserGesture() ? + NavigationGestureUser : NavigationGestureAuto); + } else if (ds->replacesCurrentHistoryItem()) { + // Subframe navigations that don't add session history items must be + // marked with AUTO_SUBFRAME. See also didFailProvisionalLoad for how we + // handle loading of error pages. + document_state->navigation_state()->set_transition_type( + PAGE_TRANSITION_AUTO_SUBFRAME); + } + + FOR_EACH_OBSERVER( + RenderViewObserver, render_view_->observers(), + DidStartProvisionalLoad(frame)); + + Send(new FrameHostMsg_DidStartProvisionalLoadForFrame( + routing_id_, frame->identifier(), + frame->parent() ? frame->parent()->identifier() : -1, + is_top_most, ds->request().url())); } void RenderFrameImpl::didReceiveServerRedirectForProvisionalLoad( - WebKit::WebFrame* frame) { + blink::WebFrame* frame) { // TODO(nasko): Move implementation here. Needed state: // * page_id_ render_view_->didReceiveServerRedirectForProvisionalLoad(frame); } void RenderFrameImpl::didFailProvisionalLoad( - WebKit::WebFrame* frame, - const WebKit::WebURLError& error) { + blink::WebFrame* frame, + const blink::WebURLError& error) { // TODO(nasko): Move implementation here. Needed state: // * page_id_ // * pending_navigation_params_ @@ -383,7 +850,7 @@ void RenderFrameImpl::didFailProvisionalLoad( render_view_->didFailProvisionalLoad(frame, error); } -void RenderFrameImpl::didCommitProvisionalLoad(WebKit::WebFrame* frame, +void RenderFrameImpl::didCommitProvisionalLoad(blink::WebFrame* frame, bool is_new_navigation) { // TODO(nasko): Move implementation here. Needed state: // * page_id_ @@ -398,7 +865,7 @@ void RenderFrameImpl::didCommitProvisionalLoad(WebKit::WebFrame* frame, render_view_->didCommitProvisionalLoad(frame, is_new_navigation); } -void RenderFrameImpl::didClearWindowObject(WebKit::WebFrame* frame) { +void RenderFrameImpl::didClearWindowObject(blink::WebFrame* frame) { // TODO(nasko): Move implementation here. Needed state: // * enabled_bindings_ // * dom_automation_controller_ @@ -406,7 +873,7 @@ void RenderFrameImpl::didClearWindowObject(WebKit::WebFrame* frame) { render_view_->didClearWindowObject(frame); } -void RenderFrameImpl::didCreateDocumentElement(WebKit::WebFrame* frame) { +void RenderFrameImpl::didCreateDocumentElement(blink::WebFrame* frame) { // Notify the browser about non-blank documents loading in the top frame. GURL url = frame->document().url(); if (url.is_valid() && url.spec() != kAboutBlankURL) { @@ -423,60 +890,60 @@ void RenderFrameImpl::didCreateDocumentElement(WebKit::WebFrame* frame) { render_view_->didCreateDocumentElement(frame); } -void RenderFrameImpl::didReceiveTitle(WebKit::WebFrame* frame, - const WebKit::WebString& title, - WebKit::WebTextDirection direction) { +void RenderFrameImpl::didReceiveTitle(blink::WebFrame* frame, + const blink::WebString& title, + blink::WebTextDirection direction) { // TODO(nasko): Investigate wheather implementation should move here. render_view_->didReceiveTitle(frame, title, direction); } -void RenderFrameImpl::didChangeIcon(WebKit::WebFrame* frame, - WebKit::WebIconURL::Type icon_type) { +void RenderFrameImpl::didChangeIcon(blink::WebFrame* frame, + blink::WebIconURL::Type icon_type) { // TODO(nasko): Investigate wheather implementation should move here. render_view_->didChangeIcon(frame, icon_type); } -void RenderFrameImpl::didFinishDocumentLoad(WebKit::WebFrame* frame) { +void RenderFrameImpl::didFinishDocumentLoad(blink::WebFrame* frame) { // TODO(nasko): Move implementation here. No state needed, just observers // notification in before updating encoding. render_view_->didFinishDocumentLoad(frame); } -void RenderFrameImpl::didHandleOnloadEvents(WebKit::WebFrame* frame) { +void RenderFrameImpl::didHandleOnloadEvents(blink::WebFrame* frame) { // TODO(nasko): Move implementation here. Needed state: // * page_id_ render_view_->didHandleOnloadEvents(frame); } -void RenderFrameImpl::didFailLoad(WebKit::WebFrame* frame, - const WebKit::WebURLError& error) { +void RenderFrameImpl::didFailLoad(blink::WebFrame* frame, + const blink::WebURLError& error) { // TODO(nasko): Move implementation here. No state needed. render_view_->didFailLoad(frame, error); } -void RenderFrameImpl::didFinishLoad(WebKit::WebFrame* frame) { +void RenderFrameImpl::didFinishLoad(blink::WebFrame* frame) { // TODO(nasko): Move implementation here. No state needed, just observers // notification before sending message to the browser process. render_view_->didFinishLoad(frame); } -void RenderFrameImpl::didNavigateWithinPage(WebKit::WebFrame* frame, +void RenderFrameImpl::didNavigateWithinPage(blink::WebFrame* frame, bool is_new_navigation) { // TODO(nasko): Move implementation here. No state needed, just observers // notification before sending message to the browser process. render_view_->didNavigateWithinPage(frame, is_new_navigation); } -void RenderFrameImpl::didUpdateCurrentHistoryItem(WebKit::WebFrame* frame) { +void RenderFrameImpl::didUpdateCurrentHistoryItem(blink::WebFrame* frame) { // TODO(nasko): Move implementation here. Needed methods: // * StartNavStateSyncTimerIfNecessary render_view_->didUpdateCurrentHistoryItem(frame); } void RenderFrameImpl::willRequestAfterPreconnect( - WebKit::WebFrame* frame, - WebKit::WebURLRequest& request) { - WebKit::WebReferrerPolicy referrer_policy = WebKit::WebReferrerPolicyDefault; + blink::WebFrame* frame, + blink::WebURLRequest& request) { + blink::WebReferrerPolicy referrer_policy = blink::WebReferrerPolicyDefault; WebString custom_user_agent; if (request.extraData()) { @@ -498,10 +965,10 @@ void RenderFrameImpl::willRequestAfterPreconnect( } void RenderFrameImpl::willSendRequest( - WebKit::WebFrame* frame, + blink::WebFrame* frame, unsigned identifier, - WebKit::WebURLRequest& request, - const WebKit::WebURLResponse& redirect_response) { + blink::WebURLRequest& request, + const blink::WebURLResponse& redirect_response) { // The request my be empty during tests. if (request.url().isEmpty()) return; @@ -536,7 +1003,7 @@ void RenderFrameImpl::willSendRequest( if (internal_data->is_cache_policy_override_set()) request.setCachePolicy(internal_data->cache_policy_override()); - WebKit::WebReferrerPolicy referrer_policy; + blink::WebReferrerPolicy referrer_policy; if (internal_data->is_referrer_policy_set()) { referrer_policy = internal_data->referrer_policy(); internal_data->clear_referrer_policy(); @@ -565,10 +1032,26 @@ void RenderFrameImpl::willSendRequest( } } + // Attach |should_replace_current_entry| state to requests so that, should + // this navigation later require a request transfer, all state is preserved + // when it is re-created in the new process. + bool should_replace_current_entry = false; + if (navigation_state->is_content_initiated()) { + should_replace_current_entry = data_source->replacesCurrentHistoryItem(); + } else { + // If the navigation is browser-initiated, the NavigationState contains the + // correct value instead of the WebDataSource. + // + // TODO(davidben): Avoid this awkward duplication of state. See comment on + // NavigationState::should_replace_current_entry(). + should_replace_current_entry = + navigation_state->should_replace_current_entry(); + } request.setExtraData( new RequestExtraData(referrer_policy, custom_user_agent, was_after_preconnect_request, + routing_id_, (frame == top_frame), frame->identifier(), GURL(frame->document().securityOrigin().toString()), @@ -576,6 +1059,7 @@ void RenderFrameImpl::willSendRequest( frame->parent() ? frame->parent()->identifier() : -1, navigation_state->allow_download(), transition_type, + should_replace_current_entry, navigation_state->transferred_request_child_id(), navigation_state->transferred_request_request_id())); @@ -613,9 +1097,9 @@ void RenderFrameImpl::willSendRequest( } void RenderFrameImpl::didReceiveResponse( - WebKit::WebFrame* frame, + blink::WebFrame* frame, unsigned identifier, - const WebKit::WebURLResponse& response) { + const blink::WebURLResponse& response) { // Only do this for responses that correspond to a provisional data source // of the top-most frame. If we have a provisional data source, then we // can't have any sub-resources yet, so we know that this response must @@ -658,7 +1142,7 @@ void RenderFrameImpl::didReceiveResponse( internal_data->set_use_error_page(true); } -void RenderFrameImpl::didFinishResourceLoad(WebKit::WebFrame* frame, +void RenderFrameImpl::didFinishResourceLoad(blink::WebFrame* frame, unsigned identifier) { // TODO(nasko): Move implementation here. Needed state: // * devtools_agent_ @@ -668,9 +1152,9 @@ void RenderFrameImpl::didFinishResourceLoad(WebKit::WebFrame* frame, } void RenderFrameImpl::didLoadResourceFromMemoryCache( - WebKit::WebFrame* frame, - const WebKit::WebURLRequest& request, - const WebKit::WebURLResponse& response) { + blink::WebFrame* frame, + const blink::WebURLRequest& request, + const blink::WebURLResponse& response) { // The recipients of this message have no use for data: URLs: they don't // affect the page's insecure content list and are not in the disk cache. To // prevent large (1M+) data: URLs from crashing in the IPC system, we simply @@ -690,28 +1174,37 @@ void RenderFrameImpl::didLoadResourceFromMemoryCache( ResourceType::FromTargetType(request.targetType()))); } -void RenderFrameImpl::didDisplayInsecureContent(WebKit::WebFrame* frame) { +void RenderFrameImpl::didDisplayInsecureContent(blink::WebFrame* frame) { render_view_->Send(new ViewHostMsg_DidDisplayInsecureContent( render_view_->GetRoutingID())); } void RenderFrameImpl::didRunInsecureContent( - WebKit::WebFrame* frame, - const WebKit::WebSecurityOrigin& origin, - const WebKit::WebURL& target) { + blink::WebFrame* frame, + const blink::WebSecurityOrigin& origin, + const blink::WebURL& target) { render_view_->Send(new ViewHostMsg_DidRunInsecureContent( render_view_->GetRoutingID(), origin.toString().utf8(), target)); } +void RenderFrameImpl::didAbortLoading(blink::WebFrame* frame) { +#if defined(ENABLE_PLUGINS) + if (frame != render_view_->webview()->mainFrame()) + return; + PluginChannelHost::Broadcast( + new PluginHostMsg_DidAbortLoading(render_view_->GetRoutingID())); +#endif +} + void RenderFrameImpl::didExhaustMemoryAvailableForScript( - WebKit::WebFrame* frame) { + blink::WebFrame* frame) { render_view_->Send(new ViewHostMsg_JSOutOfMemory( render_view_->GetRoutingID())); } -void RenderFrameImpl::didCreateScriptContext(WebKit::WebFrame* frame, +void RenderFrameImpl::didCreateScriptContext(blink::WebFrame* frame, v8::Handle<v8::Context> context, int extension_group, int world_id) { @@ -719,32 +1212,32 @@ void RenderFrameImpl::didCreateScriptContext(WebKit::WebFrame* frame, frame, context, extension_group, world_id); } -void RenderFrameImpl::willReleaseScriptContext(WebKit::WebFrame* frame, +void RenderFrameImpl::willReleaseScriptContext(blink::WebFrame* frame, v8::Handle<v8::Context> context, int world_id) { GetContentClient()->renderer()->WillReleaseScriptContext( frame, context, world_id); } -void RenderFrameImpl::didFirstVisuallyNonEmptyLayout(WebKit::WebFrame* frame) { +void RenderFrameImpl::didFirstVisuallyNonEmptyLayout(blink::WebFrame* frame) { render_view_->didFirstVisuallyNonEmptyLayout(frame); } -void RenderFrameImpl::didChangeContentsSize(WebKit::WebFrame* frame, - const WebKit::WebSize& size) { +void RenderFrameImpl::didChangeContentsSize(blink::WebFrame* frame, + const blink::WebSize& size) { // TODO(nasko): Move implementation here. Needed state: // * cached_has_main_frame_horizontal_scrollbar_ // * cached_has_main_frame_vertical_scrollbar_ render_view_->didChangeContentsSize(frame, size); } -void RenderFrameImpl::didChangeScrollOffset(WebKit::WebFrame* frame) { +void RenderFrameImpl::didChangeScrollOffset(blink::WebFrame* frame) { // TODO(nasko): Move implementation here. Needed methods: // * StartNavStateSyncTimerIfNecessary render_view_->didChangeScrollOffset(frame); } -void RenderFrameImpl::willInsertBody(WebKit::WebFrame* frame) { +void RenderFrameImpl::willInsertBody(blink::WebFrame* frame) { if (!frame->parent()) { render_view_->Send(new ViewHostMsg_WillInsertBody( render_view_->GetRoutingID())); @@ -766,22 +1259,22 @@ void RenderFrameImpl::reportFindInPageMatchCount(int request_id, void RenderFrameImpl::reportFindInPageSelection( int request_id, int active_match_ordinal, - const WebKit::WebRect& selection_rect) { + const blink::WebRect& selection_rect) { render_view_->Send(new ViewHostMsg_Find_Reply( render_view_->GetRoutingID(), request_id, -1, selection_rect, active_match_ordinal, false)); } void RenderFrameImpl::requestStorageQuota( - WebKit::WebFrame* frame, - WebKit::WebStorageQuotaType type, + blink::WebFrame* frame, + blink::WebStorageQuotaType type, unsigned long long requested_size, - WebKit::WebStorageQuotaCallbacks* callbacks) { + blink::WebStorageQuotaCallbacks* callbacks) { DCHECK(frame); WebSecurityOrigin origin = frame->document().securityOrigin(); if (origin.isUnique()) { // Unique origins cannot store persistent state. - callbacks->didFail(WebKit::WebStorageQuotaErrorAbort); + callbacks->didFail(blink::WebStorageQuotaErrorAbort); return; } ChildThread::current()->quota_dispatcher()->RequestStorageQuota( @@ -791,35 +1284,35 @@ void RenderFrameImpl::requestStorageQuota( } void RenderFrameImpl::willOpenSocketStream( - WebKit::WebSocketStreamHandle* handle) { + blink::WebSocketStreamHandle* handle) { SocketStreamHandleData::AddToHandle(handle, render_view_->GetRoutingID()); } void RenderFrameImpl::willStartUsingPeerConnectionHandler( - WebKit::WebFrame* frame, - WebKit::WebRTCPeerConnectionHandler* handler) { + blink::WebFrame* frame, + blink::WebRTCPeerConnectionHandler* handler) { #if defined(ENABLE_WEBRTC) static_cast<RTCPeerConnectionHandler*>(handler)->associateWithFrame(frame); #endif } bool RenderFrameImpl::willCheckAndDispatchMessageEvent( - WebKit::WebFrame* sourceFrame, - WebKit::WebFrame* targetFrame, - WebKit::WebSecurityOrigin targetOrigin, - WebKit::WebDOMMessageEvent event) { + blink::WebFrame* sourceFrame, + blink::WebFrame* targetFrame, + blink::WebSecurityOrigin targetOrigin, + blink::WebDOMMessageEvent event) { // TODO(nasko): Move implementation here. Needed state: // * is_swapped_out_ return render_view_->willCheckAndDispatchMessageEvent( sourceFrame, targetFrame, targetOrigin, event); } -WebKit::WebString RenderFrameImpl::userAgentOverride( - WebKit::WebFrame* frame, - const WebKit::WebURL& url) { +blink::WebString RenderFrameImpl::userAgentOverride( + blink::WebFrame* frame, + const blink::WebURL& url) { if (!render_view_->webview() || !render_view_->webview()->mainFrame() || render_view_->renderer_preferences_.user_agent_override.empty()) { - return WebKit::WebString(); + return blink::WebString(); } // If we're in the middle of committing a load, the data source we need @@ -836,16 +1329,16 @@ WebKit::WebString RenderFrameImpl::userAgentOverride( if (internal_data && internal_data->is_overriding_user_agent()) return WebString::fromUTF8( render_view_->renderer_preferences_.user_agent_override); - return WebKit::WebString(); + return blink::WebString(); } -WebKit::WebString RenderFrameImpl::doNotTrackValue(WebKit::WebFrame* frame) { +blink::WebString RenderFrameImpl::doNotTrackValue(blink::WebFrame* frame) { if (render_view_->renderer_preferences_.enable_do_not_track) return WebString::fromUTF8("1"); return WebString(); } -bool RenderFrameImpl::allowWebGL(WebKit::WebFrame* frame, bool default_value) { +bool RenderFrameImpl::allowWebGL(blink::WebFrame* frame, bool default_value) { if (!default_value) return false; @@ -858,7 +1351,7 @@ bool RenderFrameImpl::allowWebGL(WebKit::WebFrame* frame, bool default_value) { return !blocked; } -void RenderFrameImpl::didLoseWebGLContext(WebKit::WebFrame* frame, +void RenderFrameImpl::didLoseWebGLContext(blink::WebFrame* frame, int arb_robustness_status_code) { render_view_->Send(new ViewHostMsg_DidLose3DContext( GURL(frame->top()->document().securityOrigin().toString()), @@ -866,4 +1359,13 @@ void RenderFrameImpl::didLoseWebGLContext(WebKit::WebFrame* frame, arb_robustness_status_code)); } +void RenderFrameImpl::AddObserver(RenderFrameObserver* observer) { + observers_.AddObserver(observer); +} + +void RenderFrameImpl::RemoveObserver(RenderFrameObserver* observer) { + observer->RenderFrameGone(); + observers_.RemoveObserver(observer); +} + } // namespace content diff --git a/chromium/content/renderer/render_frame_impl.h b/chromium/content/renderer/render_frame_impl.h index b6940f96e91..2d26bd28ee6 100644 --- a/chromium/content/renderer/render_frame_impl.h +++ b/chromium/content/renderer/render_frame_impl.h @@ -5,19 +5,44 @@ #ifndef CONTENT_RENDERER_RENDER_FRAME_IMPL_H_ #define CONTENT_RENDERER_RENDER_FRAME_IMPL_H_ +#include <set> +#include <vector> + #include "base/basictypes.h" +#include "base/files/file_path.h" +#include "base/observer_list.h" +#include "base/process/process_handle.h" +#include "base/strings/string16.h" #include "content/public/renderer/render_frame.h" #include "ipc/ipc_message.h" #include "third_party/WebKit/public/web/WebDataSource.h" #include "third_party/WebKit/public/web/WebFrameClient.h" +class TransportDIB; + +namespace blink { +class WebMouseEvent; +struct WebCompositionUnderline; +struct WebCursorInfo; +} + +namespace gfx { +class Range; +class Rect; +} + namespace content { +class PepperPluginInstanceImpl; +class RendererPpapiHost; +class RenderFrameObserver; class RenderViewImpl; +class RenderWidget; +class RenderWidgetFullscreenPepper; class CONTENT_EXPORT RenderFrameImpl : public RenderFrame, - NON_EXPORTED_BASE(public WebKit::WebFrameClient) { + NON_EXPORTED_BASE(public blink::WebFrameClient) { public: // Creates a new RenderFrame. |render_view| is the RenderView object that this // frame belongs to. @@ -30,163 +55,289 @@ class CONTENT_EXPORT RenderFrameImpl virtual ~RenderFrameImpl(); + // TODO(jam): this is a temporary getter until all the code is transitioned + // to using RenderFrame instead of RenderView. + RenderViewImpl* render_view() { return render_view_; } + + // Returns the RenderWidget associated with this frame. + RenderWidget* GetRenderWidget(); + +#if defined(ENABLE_PLUGINS) + // Notification that a PPAPI plugin has been created. + void PepperPluginCreated(RendererPpapiHost* host); + + // Indicates that the given instance has been created. + void PepperInstanceCreated(PepperPluginInstanceImpl* instance); + + // Indicates that the given instance is being destroyed. This is called from + // the destructor, so it's important that the instance is not dereferenced + // from this call. + void PepperInstanceDeleted(PepperPluginInstanceImpl* instance); + + // Notifies that |instance| has changed the cursor. + // This will update the cursor appearance if it is currently over the plugin + // instance. + void PepperDidChangeCursor(PepperPluginInstanceImpl* instance, + const blink::WebCursorInfo& cursor); + + // Notifies that |instance| has received a mouse event. + void PepperDidReceiveMouseEvent(PepperPluginInstanceImpl* instance); + + // Notification that the given plugin is focused or unfocused. + void PepperFocusChanged(PepperPluginInstanceImpl* instance, bool focused); + + // Informs the render view that a PPAPI plugin has changed text input status. + void PepperTextInputTypeChanged(PepperPluginInstanceImpl* instance); + void PepperCaretPositionChanged(PepperPluginInstanceImpl* instance); + + // Cancels current composition. + void PepperCancelComposition(PepperPluginInstanceImpl* instance); + + // Informs the render view that a PPAPI plugin has changed selection. + void PepperSelectionChanged(PepperPluginInstanceImpl* instance); + + // Creates a fullscreen container for a pepper plugin instance. + RenderWidgetFullscreenPepper* CreatePepperFullscreenContainer( + PepperPluginInstanceImpl* plugin); + + bool IsPepperAcceptingCompositionEvents() const; + + // Notification that the given plugin has crashed. + void PluginCrashed(const base::FilePath& plugin_path, + base::ProcessId plugin_pid); + + // These map to virtual methods on RenderWidget that are used to call out to + // RenderView. + // TODO(jam): once we get rid of RenderView, RenderFrame will own RenderWidget + // and methods would be on a delegate interface. + void DidInitiatePaint(); + void DidFlushPaint(); + PepperPluginInstanceImpl* GetBitmapForOptimizedPluginPaint( + const gfx::Rect& paint_bounds, + TransportDIB** dib, + gfx::Rect* location, + gfx::Rect* clip, + float* scale_factor); + void PageVisibilityChanged(bool shown); + void OnSetFocus(bool enable); + void WillHandleMouseEvent(const blink::WebMouseEvent& event); + + // Simulates IME events for testing purpose. + void SimulateImeSetComposition( + const base::string16& text, + const std::vector<blink::WebCompositionUnderline>& underlines, + int selection_start, + int selection_end); + void SimulateImeConfirmComposition(const base::string16& text, + const gfx::Range& replacement_range); + + // TODO(jam): remove these once the IPC handler moves from RenderView to + // RenderFrame. + void OnImeSetComposition( + const base::string16& text, + const std::vector<blink::WebCompositionUnderline>& underlines, + int selection_start, + int selection_end); + void OnImeConfirmComposition( + const base::string16& text, + const gfx::Range& replacement_range, + bool keep_selection); +#endif // ENABLE_PLUGINS + // IPC::Sender virtual bool Send(IPC::Message* msg) OVERRIDE; // IPC::Listener virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; - // WebKit::WebFrameClient implementation ------------------------------------- - virtual WebKit::WebPlugin* createPlugin( - WebKit::WebFrame* frame, - const WebKit::WebPluginParams& params); - virtual WebKit::WebSharedWorker* createSharedWorker( - WebKit::WebFrame* frame, - const WebKit::WebURL& url, - const WebKit::WebString& name, - unsigned long long document_id); - virtual WebKit::WebMediaPlayer* createMediaPlayer( - WebKit::WebFrame* frame, - const WebKit::WebURL& url, - WebKit::WebMediaPlayerClient* client); - virtual WebKit::WebApplicationCacheHost* createApplicationCacheHost( - WebKit::WebFrame* frame, - WebKit::WebApplicationCacheHostClient* client); - virtual WebKit::WebCookieJar* cookieJar(WebKit::WebFrame* frame); - virtual void didAccessInitialDocument(WebKit::WebFrame* frame); - virtual void didCreateFrame(WebKit::WebFrame* parent, - WebKit::WebFrame* child); - virtual void didDisownOpener(WebKit::WebFrame* frame); - virtual void frameDetached(WebKit::WebFrame* frame); - virtual void willClose(WebKit::WebFrame* frame); - virtual void didChangeName(WebKit::WebFrame* frame, - const WebKit::WebString& name); - virtual void loadURLExternally(WebKit::WebFrame* frame, - const WebKit::WebURLRequest& request, - WebKit::WebNavigationPolicy policy); + // RenderFrame implementation: + virtual RenderView* GetRenderView() OVERRIDE; + virtual int GetRoutingID() OVERRIDE; + virtual WebPreferences& GetWebkitPreferences() OVERRIDE; + virtual int ShowContextMenu(ContextMenuClient* client, + const ContextMenuParams& params) OVERRIDE; + virtual void CancelContextMenu(int request_id) OVERRIDE; + virtual blink::WebPlugin* CreatePlugin( + blink::WebFrame* frame, + const WebPluginInfo& info, + const blink::WebPluginParams& params) OVERRIDE; + virtual void LoadURLExternally( + blink::WebFrame* frame, + const blink::WebURLRequest& request, + blink::WebNavigationPolicy policy) OVERRIDE; + + // blink::WebFrameClient implementation ------------------------------------- + virtual blink::WebPlugin* createPlugin( + blink::WebFrame* frame, + const blink::WebPluginParams& params); + virtual blink::WebMediaPlayer* createMediaPlayer( + blink::WebFrame* frame, + const blink::WebURL& url, + blink::WebMediaPlayerClient* client); + virtual blink::WebApplicationCacheHost* createApplicationCacheHost( + blink::WebFrame* frame, + blink::WebApplicationCacheHostClient* client); + virtual blink::WebWorkerPermissionClientProxy* + createWorkerPermissionClientProxy(blink::WebFrame* frame); + virtual blink::WebCookieJar* cookieJar(blink::WebFrame* frame); + virtual blink::WebServiceWorkerProvider* createServiceWorkerProvider( + blink::WebFrame* frame, + blink::WebServiceWorkerProviderClient*); + virtual void didAccessInitialDocument(blink::WebFrame* frame); + virtual blink::WebFrame* createChildFrame(blink::WebFrame* parent, + const blink::WebString& name); + virtual void didDisownOpener(blink::WebFrame* frame); + virtual void frameDetached(blink::WebFrame* frame); + virtual void willClose(blink::WebFrame* frame); + virtual void didChangeName(blink::WebFrame* frame, + const blink::WebString& name); + virtual void didMatchCSS( + blink::WebFrame* frame, + const blink::WebVector<blink::WebString>& newly_matching_selectors, + const blink::WebVector<blink::WebString>& stopped_matching_selectors); + virtual void loadURLExternally(blink::WebFrame* frame, + const blink::WebURLRequest& request, + blink::WebNavigationPolicy policy); virtual void loadURLExternally( - WebKit::WebFrame* frame, - const WebKit::WebURLRequest& request, - WebKit::WebNavigationPolicy policy, - const WebKit::WebString& suggested_name); - virtual WebKit::WebNavigationPolicy decidePolicyForNavigation( - WebKit::WebFrame* frame, - WebKit::WebDataSource::ExtraData* extra_data, - const WebKit::WebURLRequest& request, - WebKit::WebNavigationType type, - WebKit::WebNavigationPolicy default_policy, + blink::WebFrame* frame, + const blink::WebURLRequest& request, + blink::WebNavigationPolicy policy, + const blink::WebString& suggested_name); + virtual blink::WebNavigationPolicy decidePolicyForNavigation( + blink::WebFrame* frame, + blink::WebDataSource::ExtraData* extra_data, + const blink::WebURLRequest& request, + blink::WebNavigationType type, + blink::WebNavigationPolicy default_policy, bool is_redirect); // DEPRECATED - virtual WebKit::WebNavigationPolicy decidePolicyForNavigation( - WebKit::WebFrame* frame, - const WebKit::WebURLRequest& request, - WebKit::WebNavigationType type, - WebKit::WebNavigationPolicy default_policy, + virtual blink::WebNavigationPolicy decidePolicyForNavigation( + blink::WebFrame* frame, + const blink::WebURLRequest& request, + blink::WebNavigationType type, + blink::WebNavigationPolicy default_policy, bool is_redirect); - virtual void willSendSubmitEvent(WebKit::WebFrame* frame, - const WebKit::WebFormElement& form); - virtual void willSubmitForm(WebKit::WebFrame* frame, - const WebKit::WebFormElement& form); - virtual void didCreateDataSource(WebKit::WebFrame* frame, - WebKit::WebDataSource* datasource); - virtual void didStartProvisionalLoad(WebKit::WebFrame* frame); + virtual void willSendSubmitEvent(blink::WebFrame* frame, + const blink::WebFormElement& form); + virtual void willSubmitForm(blink::WebFrame* frame, + const blink::WebFormElement& form); + virtual void didCreateDataSource(blink::WebFrame* frame, + blink::WebDataSource* datasource); + virtual void didStartProvisionalLoad(blink::WebFrame* frame); virtual void didReceiveServerRedirectForProvisionalLoad( - WebKit::WebFrame* frame); + blink::WebFrame* frame); virtual void didFailProvisionalLoad( - WebKit::WebFrame* frame, - const WebKit::WebURLError& error); - virtual void didCommitProvisionalLoad(WebKit::WebFrame* frame, + blink::WebFrame* frame, + const blink::WebURLError& error); + virtual void didCommitProvisionalLoad(blink::WebFrame* frame, bool is_new_navigation); - virtual void didClearWindowObject(WebKit::WebFrame* frame); - virtual void didCreateDocumentElement(WebKit::WebFrame* frame); - virtual void didReceiveTitle(WebKit::WebFrame* frame, - const WebKit::WebString& title, - WebKit::WebTextDirection direction); - virtual void didChangeIcon(WebKit::WebFrame* frame, - WebKit::WebIconURL::Type icon_type); - virtual void didFinishDocumentLoad(WebKit::WebFrame* frame); - virtual void didHandleOnloadEvents(WebKit::WebFrame* frame); - virtual void didFailLoad(WebKit::WebFrame* frame, - const WebKit::WebURLError& error); - virtual void didFinishLoad(WebKit::WebFrame* frame); - virtual void didNavigateWithinPage(WebKit::WebFrame* frame, + virtual void didClearWindowObject(blink::WebFrame* frame); + virtual void didCreateDocumentElement(blink::WebFrame* frame); + virtual void didReceiveTitle(blink::WebFrame* frame, + const blink::WebString& title, + blink::WebTextDirection direction); + virtual void didChangeIcon(blink::WebFrame* frame, + blink::WebIconURL::Type icon_type); + virtual void didFinishDocumentLoad(blink::WebFrame* frame); + virtual void didHandleOnloadEvents(blink::WebFrame* frame); + virtual void didFailLoad(blink::WebFrame* frame, + const blink::WebURLError& error); + virtual void didFinishLoad(blink::WebFrame* frame); + virtual void didNavigateWithinPage(blink::WebFrame* frame, bool is_new_navigation); - virtual void didUpdateCurrentHistoryItem(WebKit::WebFrame* frame); - virtual void willRequestAfterPreconnect(WebKit::WebFrame* frame, - WebKit::WebURLRequest& request); + virtual void didUpdateCurrentHistoryItem(blink::WebFrame* frame); + virtual void willRequestAfterPreconnect(blink::WebFrame* frame, + blink::WebURLRequest& request); virtual void willSendRequest( - WebKit::WebFrame* frame, + blink::WebFrame* frame, unsigned identifier, - WebKit::WebURLRequest& request, - const WebKit::WebURLResponse& redirect_response); + blink::WebURLRequest& request, + const blink::WebURLResponse& redirect_response); virtual void didReceiveResponse( - WebKit::WebFrame* frame, + blink::WebFrame* frame, unsigned identifier, - const WebKit::WebURLResponse& response); - virtual void didFinishResourceLoad(WebKit::WebFrame* frame, + const blink::WebURLResponse& response); + virtual void didFinishResourceLoad(blink::WebFrame* frame, unsigned identifier); virtual void didLoadResourceFromMemoryCache( - WebKit::WebFrame* frame, - const WebKit::WebURLRequest& request, - const WebKit::WebURLResponse& response); - virtual void didDisplayInsecureContent(WebKit::WebFrame* frame); - virtual void didRunInsecureContent(WebKit::WebFrame* frame, - const WebKit::WebSecurityOrigin& origin, - const WebKit::WebURL& target); + blink::WebFrame* frame, + const blink::WebURLRequest& request, + const blink::WebURLResponse& response); + virtual void didDisplayInsecureContent(blink::WebFrame* frame); + virtual void didRunInsecureContent(blink::WebFrame* frame, + const blink::WebSecurityOrigin& origin, + const blink::WebURL& target); + virtual void didAbortLoading(blink::WebFrame* frame); virtual void didExhaustMemoryAvailableForScript( - WebKit::WebFrame* frame); - virtual void didCreateScriptContext(WebKit::WebFrame* frame, + blink::WebFrame* frame); + virtual void didCreateScriptContext(blink::WebFrame* frame, v8::Handle<v8::Context> context, int extension_group, int world_id); - virtual void willReleaseScriptContext(WebKit::WebFrame* frame, + virtual void willReleaseScriptContext(blink::WebFrame* frame, v8::Handle<v8::Context> context, int world_id); - virtual void didFirstVisuallyNonEmptyLayout(WebKit::WebFrame* frame); - virtual void didChangeContentsSize(WebKit::WebFrame* frame, - const WebKit::WebSize& size); - virtual void didChangeScrollOffset(WebKit::WebFrame* frame); - virtual void willInsertBody(WebKit::WebFrame* frame); + virtual void didFirstVisuallyNonEmptyLayout(blink::WebFrame* frame); + virtual void didChangeContentsSize(blink::WebFrame* frame, + const blink::WebSize& size); + virtual void didChangeScrollOffset(blink::WebFrame* frame); + virtual void willInsertBody(blink::WebFrame* frame); virtual void reportFindInPageMatchCount(int request_id, int count, bool final_update); virtual void reportFindInPageSelection(int request_id, int active_match_ordinal, - const WebKit::WebRect& sel); + const blink::WebRect& sel); virtual void requestStorageQuota( - WebKit::WebFrame* frame, - WebKit::WebStorageQuotaType type, + blink::WebFrame* frame, + blink::WebStorageQuotaType type, unsigned long long requested_size, - WebKit::WebStorageQuotaCallbacks* callbacks); + blink::WebStorageQuotaCallbacks* callbacks); virtual void willOpenSocketStream( - WebKit::WebSocketStreamHandle* handle); + blink::WebSocketStreamHandle* handle); virtual void willStartUsingPeerConnectionHandler( - WebKit::WebFrame* frame, - WebKit::WebRTCPeerConnectionHandler* handler); + blink::WebFrame* frame, + blink::WebRTCPeerConnectionHandler* handler); virtual bool willCheckAndDispatchMessageEvent( - WebKit::WebFrame* sourceFrame, - WebKit::WebFrame* targetFrame, - WebKit::WebSecurityOrigin targetOrigin, - WebKit::WebDOMMessageEvent event); - virtual WebKit::WebString userAgentOverride( - WebKit::WebFrame* frame, - const WebKit::WebURL& url); - virtual WebKit::WebString doNotTrackValue(WebKit::WebFrame* frame); - virtual bool allowWebGL(WebKit::WebFrame* frame, bool default_value); - virtual void didLoseWebGLContext(WebKit::WebFrame* frame, + blink::WebFrame* sourceFrame, + blink::WebFrame* targetFrame, + blink::WebSecurityOrigin targetOrigin, + blink::WebDOMMessageEvent event); + virtual blink::WebString userAgentOverride( + blink::WebFrame* frame, + const blink::WebURL& url); + virtual blink::WebString doNotTrackValue(blink::WebFrame* frame); + virtual bool allowWebGL(blink::WebFrame* frame, bool default_value); + virtual void didLoseWebGLContext(blink::WebFrame* frame, int arb_robustness_status_code); protected: RenderFrameImpl(RenderViewImpl* render_view, int32 routing_id); private: - int GetRoutingID() const; + friend class RenderFrameObserver; + + // Functions to add and remove observers for this object. + void AddObserver(RenderFrameObserver* observer); + void RemoveObserver(RenderFrameObserver* observer); RenderViewImpl* render_view_; int routing_id_; bool is_swapped_out_; bool is_detaching_; +#if defined(ENABLE_PLUGINS) + typedef std::set<PepperPluginInstanceImpl*> PepperPluginSet; + PepperPluginSet active_pepper_instances_; + + // Current text input composition text. Empty if no composition is in + // progress. + base::string16 pepper_composition_text_; +#endif + + // All the registered observers. + ObserverList<RenderFrameObserver> observers_; + DISALLOW_COPY_AND_ASSIGN(RenderFrameImpl); }; diff --git a/chromium/content/renderer/render_process_impl.cc b/chromium/content/renderer/render_process_impl.cc index 20d181b2682..4bce329a065 100644 --- a/chromium/content/renderer/render_process_impl.cc +++ b/chromium/content/renderer/render_process_impl.cc @@ -36,6 +36,10 @@ #include "base/mac/mac_util.h" #endif +#if defined(OS_ANDROID) +#include "base/android/sys_utils.h" +#endif + namespace content { RenderProcessImpl::RenderProcessImpl() @@ -68,6 +72,11 @@ RenderProcessImpl::RenderProcessImpl() // Out of process dev tools rely upon auto break behavior. webkit_glue::SetJavaScriptFlags("--debugger-auto-break"); +#if defined(OS_ANDROID) + if (base::android::SysUtils::IsLowEndDevice()) + webkit_glue::SetJavaScriptFlags("--optimize-for-size"); +#endif + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); if (command_line.HasSwitch(switches::kJavaScriptFlags)) { webkit_glue::SetJavaScriptFlags( @@ -81,7 +90,7 @@ RenderProcessImpl::RenderProcessImpl() RenderProcessImpl::~RenderProcessImpl() { #ifndef NDEBUG - int count = WebKit::WebFrame::instanceCount(); + int count = blink::WebFrame::instanceCount(); if (count) DLOG(ERROR) << "WebFrame LEAKED " << count << " TIMES"; #endif diff --git a/chromium/content/renderer/render_thread_impl.cc b/chromium/content/renderer/render_thread_impl.cc index 857c87e4407..e910b8bf80d 100644 --- a/chromium/content/renderer/render_thread_impl.cc +++ b/chromium/content/renderer/render_thread_impl.cc @@ -44,7 +44,9 @@ #include "content/common/dom_storage/dom_storage_messages.h" #include "content/common/gpu/client/context_provider_command_buffer.h" #include "content/common/gpu/client/gpu_channel_host.h" +#include "content/common/gpu/client/gpu_memory_buffer_impl.h" #include "content/common/gpu/gpu_messages.h" +#include "content/common/gpu/gpu_process_launch_causes.h" #include "content/common/resource_messages.h" #include "content/common/view_messages.h" #include "content/public/common/content_constants.h" @@ -62,8 +64,8 @@ #include "content/renderer/gamepad_shared_memory_reader.h" #include "content/renderer/gpu/compositor_output_surface.h" #include "content/renderer/gpu/gpu_benchmarking_extension.h" -#include "content/renderer/gpu/input_event_filter.h" -#include "content/renderer/gpu/input_handler_manager.h" +#include "content/renderer/input/input_event_filter.h" +#include "content/renderer/input/input_handler_manager.h" #include "content/renderer/media/audio_input_message_filter.h" #include "content/renderer/media/audio_message_filter.h" #include "content/renderer/media/audio_renderer_mixer_manager.h" @@ -79,6 +81,7 @@ #include "content/renderer/render_process_impl.h" #include "content/renderer/render_view_impl.h" #include "content/renderer/renderer_webkitplatformsupport_impl.h" +#include "content/renderer/service_worker/embedded_worker_dispatcher.h" #include "content/renderer/skia_benchmarking_extension.h" #include "grit/content_resources.h" #include "ipc/ipc_channel_handle.h" @@ -102,13 +105,11 @@ #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" #include "third_party/WebKit/public/web/WebScriptController.h" #include "third_party/WebKit/public/web/WebSecurityPolicy.h" -#include "third_party/WebKit/public/web/WebSharedWorkerRepository.h" #include "third_party/WebKit/public/web/WebView.h" #include "ui/base/layout.h" #include "ui/base/ui_base_switches.h" #include "v8/include/v8.h" #include "webkit/child/worker_task_runner.h" -#include "webkit/glue/webkit_glue.h" #include "webkit/renderer/compositor_bindings/web_external_bitmap_impl.h" #if defined(OS_WIN) @@ -121,6 +122,10 @@ #include "content/child/npapi/np_channel_base.h" #endif +#if defined(OS_MACOSX) +#include "third_party/WebKit/public/web/mac/WebScrollbarTheme.h" +#endif + #if defined(OS_POSIX) #include "ipc/ipc_channel_posix.h" #endif @@ -136,14 +141,14 @@ #endif using base::ThreadRestrictions; -using WebKit::WebDocument; -using WebKit::WebFrame; -using WebKit::WebNetworkStateNotifier; -using WebKit::WebRuntimeFeatures; -using WebKit::WebScriptController; -using WebKit::WebSecurityPolicy; -using WebKit::WebString; -using WebKit::WebView; +using blink::WebDocument; +using blink::WebFrame; +using blink::WebNetworkStateNotifier; +using blink::WebRuntimeFeatures; +using blink::WebScriptController; +using blink::WebSecurityPolicy; +using blink::WebString; +using blink::WebView; namespace content { @@ -235,7 +240,7 @@ void EnableWebCoreLogChannels(const std::string& channels) { return; base::StringTokenizer t(channels, ", "); while (t.GetNext()) - WebKit::enableLogChannel(t.token().c_str()); + blink::enableLogChannel(t.token().c_str()); } } // namespace @@ -311,7 +316,7 @@ void RenderThreadImpl::Init() { #if defined(OS_MACOSX) || defined(OS_ANDROID) // On Mac and Android, the select popups are rendered by the browser. - WebKit::WebView::setUseExternalPopupMenus(true); + blink::WebView::setUseExternalPopupMenus(true); #endif lazy_tls.Pointer()->Set(this); @@ -341,6 +346,7 @@ void RenderThreadImpl::Init() { dom_storage_dispatcher_.reset(new DomStorageDispatcher()); main_thread_indexed_db_dispatcher_.reset(new IndexedDBDispatcher( thread_safe_sender())); + embedded_worker_dispatcher_.reset(new EmbeddedWorkerDispatcher()); media_stream_center_ = NULL; @@ -370,7 +376,7 @@ void RenderThreadImpl::Init() { midi_message_filter_ = new MIDIMessageFilter(GetIOMessageLoopProxy()); AddFilter(midi_message_filter_.get()); - AddFilter(new IndexedDBMessageFilter(thread_safe_sender())); + AddFilter((new IndexedDBMessageFilter(thread_safe_sender()))->GetFilter()); GetContentClient()->renderer()->RenderThreadStarted(); @@ -398,6 +404,12 @@ void RenderThreadImpl::Init() { memory_pressure_listener_.reset(new base::MemoryPressureListener( base::Bind(&RenderThreadImpl::OnMemoryPressure, base::Unretained(this)))); + renderer_process_id_ = base::kNullProcessId; + + // AllocateGpuMemoryBuffer must be used exclusively on one thread but + // it doesn't have to be the same thread RenderThreadImpl is created on. + allocate_gpu_memory_buffer_thread_checker_.DetachFromThread(); + TRACE_EVENT_END_ETW("RenderThreadImpl::Init", 0, ""); } @@ -411,8 +423,10 @@ void RenderThreadImpl::Shutdown() { ChildThread::Shutdown(); // Wait for all databases to be closed. - if (web_database_observer_impl_) - web_database_observer_impl_->WaitForAllDatabasesToClose(); + if (webkit_platform_support_) { + webkit_platform_support_->web_database_observer_impl()-> + WaitForAllDatabasesToClose(); + } // Shutdown in reverse of the initialization order. if (devtools_agent_message_filter_.get()) { @@ -452,7 +466,7 @@ void RenderThreadImpl::Shutdown() { main_thread_indexed_db_dispatcher_.reset(); if (webkit_platform_support_) - WebKit::shutdown(); + blink::shutdown(); lazy_tls.Pointer()->Set(NULL); @@ -464,33 +478,24 @@ void RenderThreadImpl::Shutdown() { // Leak shared contexts on other threads, as we can not get to the correct // thread to destroy them. - if (shared_contexts_compositor_thread_.get()) - shared_contexts_compositor_thread_->set_leak_on_destroy(); + if (offscreen_compositor_contexts_.get()) + offscreen_compositor_contexts_->set_leak_on_destroy(); } bool RenderThreadImpl::Send(IPC::Message* msg) { // Certain synchronous messages cannot always be processed synchronously by - // the browser, e.g., Chrome frame communicating with the embedding browser. - // This could cause a complete hang of Chrome if a windowed plug-in is trying - // to communicate with the renderer thread since the browser's UI thread - // could be stuck (within a Windows API call) trying to synchronously - // communicate with the plug-in. The remedy is to pump messages on this - // thread while the browser is processing this request. This creates an - // opportunity for re-entrancy into WebKit, so we need to take care to disable - // callbacks, timers, and pending network loads that could trigger such - // callbacks. + // the browser, e.g., putting up UI and waiting for the user. This could cause + // a complete hang of Chrome if a windowed plug-in is trying to communicate + // with the renderer thread since the browser's UI thread could be stuck + // (within a Windows API call) trying to synchronously communicate with the + // plug-in. The remedy is to pump messages on this thread while the browser + // is processing this request. This creates an opportunity for re-entrancy + // into WebKit, so we need to take care to disable callbacks, timers, and + // pending network loads that could trigger such callbacks. bool pumping_events = false; if (msg->is_sync()) { if (msg->is_caller_pumping_messages()) { pumping_events = true; - } else { - if ((msg->type() == ViewHostMsg_GetCookies::ID || - msg->type() == ViewHostMsg_GetRawCookies::ID || - msg->type() == ViewHostMsg_CookiesEnabled::ID) && - GetContentClient()->renderer()-> - ShouldPumpEventsDuringCookieMessage()) { - pumping_events = true; - } } } @@ -592,10 +597,6 @@ void RenderThreadImpl::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) { channel()->RemoveFilter(filter); } -void RenderThreadImpl::SetOutgoingMessageFilter( - IPC::ChannelProxy::OutgoingMessageFilter* filter) { -} - void RenderThreadImpl::AddObserver(RenderProcessObserver* observer) { observers_.AddObserver(observer); } @@ -641,9 +642,7 @@ void RenderThreadImpl::EnsureWebKitInitialized() { return; webkit_platform_support_.reset(new RendererWebKitPlatformSupportImpl); - WebKit::initialize(webkit_platform_support_.get()); - WebKit::setSharedWorkerRepository( - webkit_platform_support_.get()->sharedWorkerRepository()); + blink::initialize(webkit_platform_support_.get()); const CommandLine& command_line = *CommandLine::ForCurrentProcess(); @@ -657,18 +656,7 @@ void RenderThreadImpl::EnsureWebKitInitialized() { #endif if (!compositor_message_loop_proxy_.get()) { compositor_thread_.reset(new base::Thread("Compositor")); -#if defined(OS_POSIX) - // Workaround for crbug.com/293736 - // On Posix, MessagePumpDefault uses system time, so delayed tasks (for - // compositor scheduling) work incorrectly across system time changes - // (e.g. tlsdate). So instead, use an IO loop, which uses libevent, that - // uses monotonic time (immune to these problems). - base::Thread::Options options; - options.message_loop_type = base::MessageLoop::TYPE_IO; - compositor_thread_->StartWithOptions(options); -#else compositor_thread_->Start(); -#endif #if defined(OS_ANDROID) compositor_thread_->SetPriority(base::kThreadPriority_Display); #endif @@ -715,10 +703,6 @@ void RenderThreadImpl::EnsureWebKitInitialized() { EnableWebCoreLogChannels( command_line.GetSwitchValueASCII(switches::kWebCoreLogChannels)); - web_database_observer_impl_.reset( - new WebDatabaseObserverImpl(sync_message_filter())); - WebKit::WebDatabase::setObserver(web_database_observer_impl_.get()); - SetRuntimeFeaturesDefaultsAndUpdateFromArgs(command_line); if (!media::IsMediaLibraryInitialized()) { @@ -745,7 +729,11 @@ void RenderThreadImpl::RegisterSchemes() { WebSecurityPolicy::registerURLSchemeAsEmptyDocument(swappedout_scheme); } -void RenderThreadImpl::RecordUserMetrics(const std::string& action) { +void RenderThreadImpl::RecordAction(const UserMetricsAction& action) { + Send(new ViewHostMsg_UserMetricsRecordAction(action.str_)); +} + +void RenderThreadImpl::RecordComputedAction(const std::string& action) { Send(new ViewHostMsg_UserMetricsRecordAction(action)); } @@ -883,88 +871,106 @@ void RenderThreadImpl::PostponeIdleNotification() { } scoped_refptr<RendererGpuVideoAcceleratorFactories> -RenderThreadImpl::GetGpuFactories( - const scoped_refptr<base::MessageLoopProxy>& factories_loop) { +RenderThreadImpl::GetGpuFactories() { DCHECK(IsMainThread()); + scoped_refptr<GpuChannelHost> gpu_channel_host = GetGpuChannel(); const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); scoped_refptr<RendererGpuVideoAcceleratorFactories> gpu_factories; if (!cmd_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) { if (!gpu_va_context_provider_ || gpu_va_context_provider_->DestroyedOnMainThread()) { + if (!gpu_channel_host) { + gpu_channel_host = EstablishGpuChannelSync( + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE); + } gpu_va_context_provider_ = ContextProviderCommandBuffer::Create( make_scoped_ptr( WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( - this, - WebKit::WebGraphicsContext3D::Attributes(), - GURL("chrome://gpu/RenderThreadImpl::GetGpuVDAContext3D"))), + gpu_channel_host.get(), + blink::WebGraphicsContext3D::Attributes(), + GURL("chrome://gpu/RenderThreadImpl::GetGpuVDAContext3D"), + WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits())), "GPU-VideoAccelerator-Offscreen"); } } - GpuChannelHost* gpu_channel_host = GetGpuChannel(); if (gpu_channel_host) { gpu_factories = new RendererGpuVideoAcceleratorFactories( - gpu_channel_host, factories_loop, gpu_va_context_provider_); + gpu_channel_host.get(), gpu_va_context_provider_); } return gpu_factories; } scoped_ptr<WebGraphicsContext3DCommandBufferImpl> RenderThreadImpl::CreateOffscreenContext3d() { - WebKit::WebGraphicsContext3D::Attributes attributes; + blink::WebGraphicsContext3D::Attributes attributes; attributes.shareResources = true; attributes.depth = false; attributes.stencil = false; attributes.antialias = false; attributes.noAutomaticFlushes = true; + scoped_refptr<GpuChannelHost> gpu_channel_host(EstablishGpuChannelSync( + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)); return make_scoped_ptr( WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( - this, + gpu_channel_host.get(), attributes, - GURL("chrome://gpu/RenderThreadImpl::CreateOffscreenContext3d"))); + GURL("chrome://gpu/RenderThreadImpl::CreateOffscreenContext3d"), + WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits())); } scoped_refptr<cc::ContextProvider> -RenderThreadImpl::OffscreenContextProviderForMainThread() { +RenderThreadImpl::OffscreenCompositorContextProvider() { DCHECK(IsMainThread()); #if defined(OS_ANDROID) if (SynchronousCompositorFactory* factory = SynchronousCompositorFactory::GetInstance()) { + if (compositor_message_loop_proxy_) + return factory->GetOffscreenContextProviderForCompositorThread(); return factory->GetOffscreenContextProviderForMainThread(); } #endif - if (!shared_contexts_main_thread_.get() || - shared_contexts_main_thread_->DestroyedOnMainThread()) { - shared_contexts_main_thread_ = ContextProviderCommandBuffer::Create( + if (!offscreen_compositor_contexts_.get() || + offscreen_compositor_contexts_->DestroyedOnMainThread()) { + offscreen_compositor_contexts_ = ContextProviderCommandBuffer::Create( CreateOffscreenContext3d(), - "Compositor-Offscreen-MainThread"); - if (shared_contexts_main_thread_.get() && - !shared_contexts_main_thread_->BindToCurrentThread()) - shared_contexts_main_thread_ = NULL; + "Compositor-Offscreen"); } - return shared_contexts_main_thread_; + return offscreen_compositor_contexts_; } scoped_refptr<cc::ContextProvider> -RenderThreadImpl::OffscreenContextProviderForCompositorThread() { +RenderThreadImpl::SharedMainThreadContextProvider() { DCHECK(IsMainThread()); - #if defined(OS_ANDROID) if (SynchronousCompositorFactory* factory = - SynchronousCompositorFactory::GetInstance()) { - return factory->GetOffscreenContextProviderForCompositorThread(); - } + SynchronousCompositorFactory::GetInstance()) + return factory->GetOffscreenContextProviderForMainThread(); #endif - if (!shared_contexts_compositor_thread_.get() || - shared_contexts_compositor_thread_->DestroyedOnMainThread()) { - shared_contexts_compositor_thread_ = ContextProviderCommandBuffer::Create( - CreateOffscreenContext3d(), "Compositor-Offscreen"); + if (!shared_main_thread_contexts_ || + shared_main_thread_contexts_->DestroyedOnMainThread()) { + if (compositor_message_loop_proxy_) { + // In threaded compositing mode, we have to create a new ContextProvider + // to bind to the main thread since the compositor's is bound to the + // compositor thread. + shared_main_thread_contexts_ = + ContextProviderCommandBuffer::Create(CreateOffscreenContext3d(), + "Offscreen-MainThread"); + } else { + // In single threaded mode, we can use the same context provider. + shared_main_thread_contexts_ = + static_cast<ContextProviderCommandBuffer*>( + OffscreenCompositorContextProvider().get()); + } } - return shared_contexts_compositor_thread_; + if (shared_main_thread_contexts_ && + !shared_main_thread_contexts_->BindToCurrentThread()) + shared_main_thread_contexts_ = NULL; + return shared_main_thread_contexts_; } AudioRendererMixerManager* RenderThreadImpl::GetAudioRendererMixerManager() { @@ -993,7 +999,7 @@ media::AudioHardwareConfig* RenderThreadImpl::GetAudioHardwareConfig() { #if defined(OS_WIN) void RenderThreadImpl::PreCacheFontCharacters(const LOGFONT& log_font, - const string16& str) { + const base::string16& str) { Send(new ViewHostMsg_PreCacheFontCharacters(log_font, str)); } @@ -1059,6 +1065,38 @@ void RenderThreadImpl::DeleteImage(int32 image_id, int32 sync_point) { NOTREACHED(); } +scoped_ptr<gfx::GpuMemoryBuffer> RenderThreadImpl::AllocateGpuMemoryBuffer( + size_t width, + size_t height, + unsigned internalformat) { + DCHECK(allocate_gpu_memory_buffer_thread_checker_.CalledOnValidThread()); + + if (!GpuMemoryBufferImpl::IsFormatValid(internalformat)) + return scoped_ptr<gfx::GpuMemoryBuffer>(); + + gfx::GpuMemoryBufferHandle handle; + bool success; + IPC::Message* message = + new ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer(width, + height, + internalformat, + &handle); + + // Allow calling this from the compositor thread. + if (base::MessageLoop::current() == message_loop()) + success = ChildThread::Send(message); + else + success = sync_message_filter()->Send(message); + + if (!success) + return scoped_ptr<gfx::GpuMemoryBuffer>(); + + return GpuMemoryBufferImpl::Create( + handle, + gfx::Size(width, height), + internalformat).PassAs<gfx::GpuMemoryBuffer>(); +} + void RenderThreadImpl::DoNotSuspendWebKitSharedTimer() { suspend_webkit_shared_timer_ = false; } @@ -1084,7 +1122,8 @@ bool RenderThreadImpl::OnControlMessageReceived(const IPC::Message& msg) { // Some messages are handled by delegates. if (appcache_dispatcher_->OnMessageReceived(msg) || - dom_storage_dispatcher_->OnMessageReceived(msg)) { + dom_storage_dispatcher_->OnMessageReceived(msg) || + embedded_worker_dispatcher_->OnMessageReceived(msg)) { return true; } @@ -1098,8 +1137,14 @@ bool RenderThreadImpl::OnControlMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(ViewMsg_PurgePluginListCache, OnPurgePluginListCache) IPC_MESSAGE_HANDLER(ViewMsg_NetworkStateChanged, OnNetworkStateChanged) IPC_MESSAGE_HANDLER(ViewMsg_TempCrashWithData, OnTempCrashWithData) + IPC_MESSAGE_HANDLER(ViewMsg_SetRendererProcessID, OnSetRendererProcessID) +#if defined(OS_ANDROID) IPC_MESSAGE_HANDLER(ViewMsg_SetWebKitSharedTimersSuspended, OnSetWebKitSharedTimersSuspended) +#endif +#if defined(OS_MACOSX) + IPC_MESSAGE_HANDLER(ViewMsg_UpdateScrollbarTheme, OnUpdateScrollbarTheme) +#endif IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -1164,12 +1209,12 @@ GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync( shutdown_event_ = ChildProcess::current()->GetShutDownEvent(); gpu_channel_ = GpuChannelHost::Create( - this, 0, client_id, gpu_info, channel_handle); + this, 0, gpu_info, channel_handle); return gpu_channel_.get(); } -WebKit::WebMediaStreamCenter* RenderThreadImpl::CreateMediaStreamCenter( - WebKit::WebMediaStreamCenterClient* client) { +blink::WebMediaStreamCenter* RenderThreadImpl::CreateMediaStreamCenter( + blink::WebMediaStreamCenterClient* client) { #if defined(OS_ANDROID) if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableWebRTC)) @@ -1219,7 +1264,7 @@ void RenderThreadImpl::OnPurgePluginListCache(bool reload_pages) { // refresh temporarily to prevent each renderer process causing the list to be // regenerated. webkit_platform_support_->set_plugin_refresh_allowed(false); - WebKit::resetPluginCache(reload_pages); + blink::resetPluginCache(reload_pages); webkit_platform_support_->set_plugin_refresh_allowed(true); FOR_EACH_OBSERVER(RenderProcessObserver, observers_, PluginListChanged()); @@ -1235,9 +1280,27 @@ void RenderThreadImpl::OnTempCrashWithData(const GURL& data) { CHECK(false); } +void RenderThreadImpl::OnSetRendererProcessID(base::ProcessId process_id) { + renderer_process_id_ = process_id; +} + +#if defined(OS_ANDROID) void RenderThreadImpl::OnSetWebKitSharedTimersSuspended(bool suspend) { ToggleWebKitSharedTimer(suspend); } +#endif + +#if defined(OS_MACOSX) +void RenderThreadImpl::OnUpdateScrollbarTheme(float initial_button_delay, + float autoscroll_button_delay, + bool jump_on_track_click, + bool redraw) { + blink::WebScrollbarTheme::updateScrollbars(initial_button_delay, + autoscroll_button_delay, + jump_on_track_click, + redraw); +} +#endif void RenderThreadImpl::OnMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { @@ -1248,7 +1311,7 @@ void RenderThreadImpl::OnMemoryPressure( // Trigger full v8 garbage collection on critical memory notification. v8::V8::LowMemoryNotification(); // Clear the image cache. - WebKit::WebImageCache::clear(); + blink::WebImageCache::clear(); // Purge Skia font cache, by setting it to 0 and then again to the previous // limit. size_t font_cache_limit = SkGraphics::SetFontCacheLimit(0); @@ -1275,18 +1338,7 @@ RenderThreadImpl::GetMediaThreadMessageLoopProxy() { DCHECK(message_loop() == base::MessageLoop::current()); if (!media_thread_) { media_thread_.reset(new base::Thread("Media")); -#if defined(OS_POSIX) - // Workaround for crbug.com/293736 - // On Posix, MessagePumpDefault uses system time, so delayed tasks (for - // compositor scheduling) work incorrectly across system time changes - // (e.g. tlsdate). So instead, use an IO loop, which uses libevent, that - // uses monotonic time (immune to these problems). - base::Thread::Options options; - options.message_loop_type = base::MessageLoop::TYPE_IO; - media_thread_->StartWithOptions(options); -#else media_thread_->Start(); -#endif #if defined(OS_ANDROID) renderer_demuxer_ = new RendererDemuxerAndroid(); @@ -1304,10 +1356,14 @@ void RenderThreadImpl::SetFlingCurveParameters( } -void RenderThreadImpl::SampleGamepads(WebKit::WebGamepads* data) { +void RenderThreadImpl::SampleGamepads(blink::WebGamepads* data) { if (!gamepad_shared_memory_reader_) gamepad_shared_memory_reader_.reset(new GamepadSharedMemoryReader); gamepad_shared_memory_reader_->SampleGamepads(*data); } +base::ProcessId RenderThreadImpl::renderer_process_id() const { + return renderer_process_id_; +} + } // namespace content diff --git a/chromium/content/renderer/render_thread_impl.h b/chromium/content/renderer/render_thread_impl.h index ad4f888422c..5dffc8d8b5c 100644 --- a/chromium/content/renderer/render_thread_impl.h +++ b/chromium/content/renderer/render_thread_impl.h @@ -11,13 +11,14 @@ #include "base/memory/memory_pressure_listener.h" #include "base/observer_list.h" +#include "base/process/process_handle.h" #include "base/strings/string16.h" +#include "base/threading/thread_checker.h" #include "base/timer/timer.h" #include "build/build_config.h" #include "content/child/child_thread.h" #include "content/common/content_export.h" #include "content/common/gpu/client/gpu_channel_host.h" -#include "content/common/gpu/gpu_process_launch_causes.h" #include "content/public/renderer/render_thread.h" #include "content/renderer/media/renderer_gpu_video_accelerator_factories.h" #include "ipc/ipc_channel_proxy.h" @@ -27,7 +28,7 @@ class GrContext; class SkBitmap; struct ViewMsg_New_Params; -namespace WebKit { +namespace blink { class WebGamepads; class WebGraphicsContext3D; class WebMediaStreamCenter; @@ -77,6 +78,7 @@ class ContextProviderCommandBuffer; class DBMessageFilter; class DevToolsAgentFilter; class DomStorageDispatcher; +class EmbeddedWorkerDispatcher; class GamepadSharedMemoryReader; class GpuChannelHost; class IndexedDBDispatcher; @@ -91,7 +93,6 @@ class RendererDemuxerAndroid; class RendererWebKitPlatformSupportImpl; class RenderProcessObserver; class VideoCaptureImplManager; -class WebDatabaseObserverImpl; class WebGraphicsContext3DCommandBufferImpl; class WebRTCIdentityService; @@ -133,8 +134,6 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, virtual int GenerateRoutingID() OVERRIDE; virtual void AddFilter(IPC::ChannelProxy::MessageFilter* filter) OVERRIDE; virtual void RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) OVERRIDE; - virtual void SetOutgoingMessageFilter( - IPC::ChannelProxy::OutgoingMessageFilter* filter) OVERRIDE; virtual void AddObserver(RenderProcessObserver* observer) OVERRIDE; virtual void RemoveObserver(RenderProcessObserver* observer) OVERRIDE; virtual void SetResourceDispatcherDelegate( @@ -142,7 +141,8 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, virtual void WidgetHidden() OVERRIDE; virtual void WidgetRestored() OVERRIDE; virtual void EnsureWebKitInitialized() OVERRIDE; - virtual void RecordUserMetrics(const std::string& action) OVERRIDE; + virtual void RecordAction(const UserMetricsAction& action) OVERRIDE; + virtual void RecordComputedAction(const std::string& action) OVERRIDE; virtual scoped_ptr<base::SharedMemory> HostAllocateSharedMemoryBuffer( size_t buffer_size) OVERRIDE; virtual void RegisterExtension(v8::Extension* extension) OVERRIDE; @@ -164,7 +164,7 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, // established or if it has been lost (for example if the GPU plugin crashed). // If there is a pending asynchronous request, it will be completed by the // time this routine returns. - virtual GpuChannelHost* EstablishGpuChannelSync(CauseForGpuLaunch) OVERRIDE; + GpuChannelHost* EstablishGpuChannelSync(CauseForGpuLaunch); // These methods modify how the next message is sent. Normally, when sending @@ -206,6 +206,10 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, return dom_storage_dispatcher_.get(); } + EmbeddedWorkerDispatcher* embedded_worker_dispatcher() const { + return embedded_worker_dispatcher_.get(); + } + AudioInputMessageFilter* audio_input_message_filter() { return audio_input_message_filter_.get(); } @@ -226,8 +230,8 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, // Creates the embedder implementation of WebMediaStreamCenter. // The resulting object is owned by WebKit and deleted by WebKit at tear-down. - WebKit::WebMediaStreamCenter* CreateMediaStreamCenter( - WebKit::WebMediaStreamCenterClient* client); + blink::WebMediaStreamCenter* CreateMediaStreamCenter( + blink::WebMediaStreamCenterClient* client); // Returns a factory used for creating RTC PeerConnection objects. MediaStreamDependencyFactory* GetMediaStreamDependencyFactory(); @@ -264,14 +268,10 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, // not sent for at least one notification delay. void PostponeIdleNotification(); - // Gets gpu factories, which will run on |factories_loop|. - scoped_refptr<RendererGpuVideoAcceleratorFactories> GetGpuFactories( - const scoped_refptr<base::MessageLoopProxy>& factories_loop); + scoped_refptr<RendererGpuVideoAcceleratorFactories> GetGpuFactories(); - scoped_refptr<cc::ContextProvider> - OffscreenContextProviderForMainThread(); - scoped_refptr<cc::ContextProvider> - OffscreenContextProviderForCompositorThread(); + scoped_refptr<cc::ContextProvider> OffscreenCompositorContextProvider(); + scoped_refptr<cc::ContextProvider> SharedMainThreadContextProvider(); // AudioRendererMixerManager instance which manages renderer side mixer // instances shared based on configured audio parameters. Lazily created on @@ -284,7 +284,8 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, media::AudioHardwareConfig* GetAudioHardwareConfig(); #if defined(OS_WIN) - void PreCacheFontCharacters(const LOGFONT& log_font, const string16& str); + void PreCacheFontCharacters(const LOGFONT& log_font, + const base::string16& str); #endif #if defined(ENABLE_WEBRTC) @@ -343,7 +344,12 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, const std::vector<float>& new_touchscreen); // Retrieve current gamepad data. - void SampleGamepads(WebKit::WebGamepads* data); + void SampleGamepads(blink::WebGamepads* data); + + // Get the browser process's notion of the renderer process's ID. + // This is the first argument to RenderWidgetHost::FromID. Ideally + // this would be available on all platforms via base::Process. + base::ProcessId renderer_process_id() const; private: // ChildThread @@ -364,6 +370,10 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, int32 image_id, const CreateImageCallback& callback) OVERRIDE; virtual void DeleteImage(int32 image_id, int32 sync_point) OVERRIDE; + virtual scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer( + size_t width, + size_t height, + unsigned internalformat) OVERRIDE; void Init(); @@ -376,9 +386,18 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, void OnNetworkStateChanged(bool online); void OnGetAccessibilityTree(); void OnTempCrashWithData(const GURL& data); - void OnSetWebKitSharedTimersSuspended(bool suspend); + void OnSetRendererProcessID(base::ProcessId process_id); void OnMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); +#if defined(OS_ANDROID) + void OnSetWebKitSharedTimersSuspended(bool suspend); +#endif +#if defined(OS_MACOSX) + void OnUpdateScrollbarTheme(float initial_button_delay, + float autoscroll_button_delay, + bool jump_on_track_click, + bool redraw); +#endif void IdleHandlerInForegroundTab(); @@ -389,9 +408,10 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, scoped_ptr<DomStorageDispatcher> dom_storage_dispatcher_; scoped_ptr<IndexedDBDispatcher> main_thread_indexed_db_dispatcher_; scoped_ptr<RendererWebKitPlatformSupportImpl> webkit_platform_support_; + scoped_ptr<EmbeddedWorkerDispatcher> embedded_worker_dispatcher_; // Used on the render thread and deleted by WebKit at shutdown. - WebKit::WebMediaStreamCenter* media_stream_center_; + blink::WebMediaStreamCenter* media_stream_center_; // Used on the renderer and IPC threads. scoped_refptr<DBMessageFilter> db_message_filter_; @@ -415,9 +435,6 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, // Used on multiple threads. scoped_refptr<VideoCaptureImplManager> vc_manager_; - // Used on multiple script execution context threads. - scoped_ptr<WebDatabaseObserverImpl> web_database_observer_impl_; - #if defined(OS_WIN) // Initialize COM when using plugins outside the sandbox. scoped_ptr<base::win::ScopedCOMInitializer> initialize_com_; @@ -470,9 +487,8 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, scoped_ptr<InputHandlerManager> input_handler_manager_; scoped_refptr<IPC::ForwardingMessageFilter> compositor_output_surface_filter_; - scoped_refptr<ContextProviderCommandBuffer> shared_contexts_main_thread_; - scoped_refptr<ContextProviderCommandBuffer> - shared_contexts_compositor_thread_; + scoped_refptr<ContextProviderCommandBuffer> offscreen_compositor_contexts_; + scoped_refptr<ContextProviderCommandBuffer> shared_main_thread_contexts_; ObserverList<RenderProcessObserver> observers_; @@ -489,6 +505,13 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, scoped_ptr<GamepadSharedMemoryReader> gamepad_shared_memory_reader_; + base::ProcessId renderer_process_id_; + + // TODO(reveman): Allow AllocateGpuMemoryBuffer to be called from + // multiple threads. Current allocation mechanism for IOSurface + // backed GpuMemoryBuffers prevent this. crbug.com/325045 + base::ThreadChecker allocate_gpu_memory_buffer_thread_checker_; + DISALLOW_COPY_AND_ASSIGN(RenderThreadImpl); }; diff --git a/chromium/content/renderer/render_view_browsertest.cc b/chromium/content/renderer/render_view_browsertest.cc index a66e041ce9d..d378ab6a24a 100644 --- a/chromium/content/renderer/render_view_browsertest.cc +++ b/chromium/content/renderer/render_view_browsertest.cc @@ -7,6 +7,7 @@ #include "base/memory/shared_memory.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/win/windows_version.h" #include "content/common/ssl_status_serialization.h" #include "content/common/view_messages.h" #include "content/public/browser/native_web_keyboard_event.h" @@ -51,24 +52,28 @@ #if defined(USE_AURA) && defined(USE_X11) #include <X11/Xlib.h> -#include "ui/base/x/x11_util.h" #include "ui/events/event_constants.h" #include "ui/events/keycodes/keyboard_code_conversion.h" +#include "ui/events/test/events_test_utils_x11.h" #endif -using WebKit::WebFrame; -using WebKit::WebInputEvent; -using WebKit::WebMouseEvent; -using WebKit::WebRuntimeFeatures; -using WebKit::WebString; -using WebKit::WebTextDirection; -using WebKit::WebURLError; +#if defined(USE_OZONE) +#include "ui/events/keycodes/keyboard_code_conversion.h" +#endif + +using blink::WebFrame; +using blink::WebInputEvent; +using blink::WebMouseEvent; +using blink::WebRuntimeFeatures; +using blink::WebString; +using blink::WebTextDirection; +using blink::WebURLError; namespace content { namespace { -#if defined(USE_AURA) && defined(USE_X11) +#if (defined(USE_AURA) && defined(USE_X11)) || defined(USE_OZONE) // Converts MockKeyboard::Modifiers to ui::EventFlags. int ConvertMockKeyboardModifier(MockKeyboard::Modifiers modifiers) { static struct ModifierMap { @@ -125,11 +130,10 @@ class RenderViewImplTest : public RenderViewTest { virtual void SetUp() OVERRIDE { RenderViewTest::SetUp(); - // This test depends on Blink flag InputModeAttribute, which is enabled - // under only test. Content browser test doesn't enable the feature so we - // need enable it manually. - // TODO(yoichio): Remove this if InputMode feature is enabled by default. - WebRuntimeFeatures::enableInputModeAttribute(true); + // Enable Blink's experimental and test only features so that test code + // does not have to bother enabling each feature. + WebRuntimeFeatures::enableExperimentalFeatures(true); + WebRuntimeFeatures::enableTestOnlyFeatures(true); } RenderViewImpl* view() { @@ -140,7 +144,7 @@ class RenderViewImplTest : public RenderViewTest { int SendKeyEvent(MockKeyboard::Layout layout, int key_code, MockKeyboard::Modifiers modifiers, - string16* output) { + base::string16* output) { #if defined(OS_WIN) // Retrieve the Unicode character for the given tuple (keyboard-layout, // key-code, and modifiers). @@ -194,30 +198,25 @@ class RenderViewImplTest : public RenderViewTest { CHECK(output); const int flags = ConvertMockKeyboardModifier(modifiers); - XEvent xevent1; - InitXKeyEventForTesting(ui::ET_KEY_PRESSED, - static_cast<ui::KeyboardCode>(key_code), - flags, - &xevent1); - ui::KeyEvent event1(&xevent1, false); + ui::ScopedXI2Event xevent; + xevent.InitKeyEvent(ui::ET_KEY_PRESSED, + static_cast<ui::KeyboardCode>(key_code), + flags); + ui::KeyEvent event1(xevent, false); NativeWebKeyboardEvent keydown_event(&event1); SendNativeKeyEvent(keydown_event); - XEvent xevent2; - InitXKeyEventForTesting(ui::ET_KEY_PRESSED, - static_cast<ui::KeyboardCode>(key_code), - flags, - &xevent2); - ui::KeyEvent event2(&xevent2, true); + xevent.InitKeyEvent(ui::ET_KEY_PRESSED, + static_cast<ui::KeyboardCode>(key_code), + flags); + ui::KeyEvent event2(xevent, true); NativeWebKeyboardEvent char_event(&event2); SendNativeKeyEvent(char_event); - XEvent xevent3; - InitXKeyEventForTesting(ui::ET_KEY_RELEASED, - static_cast<ui::KeyboardCode>(key_code), - flags, - &xevent3); - ui::KeyEvent event3(&xevent3, false); + xevent.InitKeyEvent(ui::ET_KEY_RELEASED, + static_cast<ui::KeyboardCode>(key_code), + flags); + ui::KeyEvent event3(xevent, false); NativeWebKeyboardEvent keyup_event(&event3); SendNativeKeyEvent(keyup_event); @@ -225,6 +224,39 @@ class RenderViewImplTest : public RenderViewTest { flags); output->assign(1, static_cast<char16>(c)); return 1; +#elif defined(USE_OZONE) + const int flags = ConvertMockKeyboardModifier(modifiers); + + // Ozone's native events are ui::Events. So first create the "native" event, + // then create the actual ui::KeyEvent with the native event. + ui::KeyEvent keydown_native_event(ui::ET_KEY_PRESSED, + static_cast<ui::KeyboardCode>(key_code), + flags, + true); + ui::KeyEvent keydown_event(&keydown_native_event, false); + NativeWebKeyboardEvent keydown_web_event(&keydown_event); + SendNativeKeyEvent(keydown_web_event); + + ui::KeyEvent char_native_event(ui::ET_KEY_PRESSED, + static_cast<ui::KeyboardCode>(key_code), + flags, + true); + ui::KeyEvent char_event(&char_native_event, true); + NativeWebKeyboardEvent char_web_event(&char_event); + SendNativeKeyEvent(char_web_event); + + ui::KeyEvent keyup_native_event(ui::ET_KEY_RELEASED, + static_cast<ui::KeyboardCode>(key_code), + flags, + true); + ui::KeyEvent keyup_event(&keyup_native_event, false); + NativeWebKeyboardEvent keyup_web_event(&keyup_event); + SendNativeKeyEvent(keyup_web_event); + + long c = GetCharacterFromKeyCode(static_cast<ui::KeyboardCode>(key_code), + flags); + output->assign(1, static_cast<char16>(c)); + return 1; #elif defined(TOOLKIT_GTK) // We ignore |layout|, which means we are only testing the layout of the // current locale. TODO(estade): fix this to respect |layout|. @@ -246,9 +278,9 @@ class RenderViewImplTest : public RenderViewTest { SendNativeKeyEvent(webkit_event); // Need to add a char event after the key down. - if (webkit_event.type == WebKit::WebInputEvent::RawKeyDown) { + if (webkit_event.type == blink::WebInputEvent::RawKeyDown) { NativeWebKeyboardEvent char_event = webkit_event; - char_event.type = WebKit::WebInputEvent::Char; + char_event.type = blink::WebInputEvent::Char; char_event.skip_in_browser = true; SendNativeKeyEvent(char_event); } @@ -321,13 +353,13 @@ TEST_F(RenderViewImplTest, OnNavigationHttpPost) { // Check post data sent to browser matches EXPECT_TRUE(host_nav_params.a.page_state.IsValid()); - const WebKit::WebHistoryItem item = PageStateToHistoryItem( + const blink::WebHistoryItem item = PageStateToHistoryItem( host_nav_params.a.page_state); - WebKit::WebHTTPBody body = item.httpBody(); - WebKit::WebHTTPBody::Element element; + blink::WebHTTPBody body = item.httpBody(); + blink::WebHTTPBody::Element element; bool successful = body.elementAt(0, element); EXPECT_TRUE(successful); - EXPECT_EQ(WebKit::WebHTTPBody::Element::TypeData, element.type); + EXPECT_EQ(blink::WebHTTPBody::Element::TypeData, element.type); EXPECT_EQ(length, element.data.size()); EXPECT_EQ(0, memcmp(raw_data, element.data.data(), length)); } @@ -340,38 +372,68 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicy) { state.set_navigation_state(NavigationState::CreateContentInitiated()); // Navigations to normal HTTP URLs can be handled locally. - WebKit::WebURLRequest request(GURL("http://foo.com")); - WebKit::WebNavigationPolicy policy = view()->decidePolicyForNavigation( + blink::WebURLRequest request(GURL("http://foo.com")); + blink::WebNavigationPolicy policy = view()->decidePolicyForNavigation( GetMainFrame(), &state, request, - WebKit::WebNavigationTypeLinkClicked, - WebKit::WebNavigationPolicyCurrentTab, + blink::WebNavigationTypeLinkClicked, + blink::WebNavigationPolicyCurrentTab, false); - EXPECT_EQ(WebKit::WebNavigationPolicyCurrentTab, policy); + EXPECT_EQ(blink::WebNavigationPolicyCurrentTab, policy); // Verify that form posts to WebUI URLs will be sent to the browser process. - WebKit::WebURLRequest form_request(GURL("chrome://foo")); + blink::WebURLRequest form_request(GURL("chrome://foo")); form_request.setHTTPMethod("POST"); policy = view()->decidePolicyForNavigation( GetMainFrame(), &state, form_request, - WebKit::WebNavigationTypeFormSubmitted, - WebKit::WebNavigationPolicyCurrentTab, + blink::WebNavigationTypeFormSubmitted, + blink::WebNavigationPolicyCurrentTab, false); - EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy); + EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy); // Verify that popup links to WebUI URLs also are sent to browser. - WebKit::WebURLRequest popup_request(GURL("chrome://foo")); + blink::WebURLRequest popup_request(GURL("chrome://foo")); policy = view()->decidePolicyForNavigation( GetMainFrame(), &state, popup_request, - WebKit::WebNavigationTypeLinkClicked, - WebKit::WebNavigationPolicyNewForegroundTab, + blink::WebNavigationTypeLinkClicked, + blink::WebNavigationPolicyNewForegroundTab, false); - EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy); + EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy); +} + +TEST_F(RenderViewImplTest, DecideNavigationPolicyHandlesAllTopLevel) { + DocumentState state; + state.set_navigation_state(NavigationState::CreateContentInitiated()); + + RendererPreferences prefs = view()->renderer_preferences(); + prefs.browser_handles_all_top_level_requests = true; + view()->OnSetRendererPrefs(prefs); + + const blink::WebNavigationType kNavTypes[] = { + blink::WebNavigationTypeLinkClicked, + blink::WebNavigationTypeFormSubmitted, + blink::WebNavigationTypeBackForward, + blink::WebNavigationTypeReload, + blink::WebNavigationTypeFormResubmitted, + blink::WebNavigationTypeOther, + }; + + blink::WebURLRequest request(GURL("http://foo.com")); + for (size_t i = 0; i < arraysize(kNavTypes); ++i) { + blink::WebNavigationPolicy policy = view()->decidePolicyForNavigation( + GetMainFrame(), + &state, + request, + kNavTypes[i], + blink::WebNavigationPolicyCurrentTab, + false); + EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy); + } } TEST_F(RenderViewImplTest, DecideNavigationPolicyForWebUI) { @@ -382,55 +444,55 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicyForWebUI) { state.set_navigation_state(NavigationState::CreateContentInitiated()); // Navigations to normal HTTP URLs will be sent to browser process. - WebKit::WebURLRequest request(GURL("http://foo.com")); - WebKit::WebNavigationPolicy policy = view()->decidePolicyForNavigation( + blink::WebURLRequest request(GURL("http://foo.com")); + blink::WebNavigationPolicy policy = view()->decidePolicyForNavigation( GetMainFrame(), &state, request, - WebKit::WebNavigationTypeLinkClicked, - WebKit::WebNavigationPolicyCurrentTab, + blink::WebNavigationTypeLinkClicked, + blink::WebNavigationPolicyCurrentTab, false); - EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy); + EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy); // Navigations to WebUI URLs will also be sent to browser process. - WebKit::WebURLRequest webui_request(GURL("chrome://foo")); + blink::WebURLRequest webui_request(GURL("chrome://foo")); policy = view()->decidePolicyForNavigation( GetMainFrame(), &state, webui_request, - WebKit::WebNavigationTypeLinkClicked, - WebKit::WebNavigationPolicyCurrentTab, + blink::WebNavigationTypeLinkClicked, + blink::WebNavigationPolicyCurrentTab, false); - EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy); + EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy); // Verify that form posts to data URLs will be sent to the browser process. - WebKit::WebURLRequest data_request(GURL("data:text/html,foo")); + blink::WebURLRequest data_request(GURL("data:text/html,foo")); data_request.setHTTPMethod("POST"); policy = view()->decidePolicyForNavigation( GetMainFrame(), &state, data_request, - WebKit::WebNavigationTypeFormSubmitted, - WebKit::WebNavigationPolicyCurrentTab, + blink::WebNavigationTypeFormSubmitted, + blink::WebNavigationPolicyCurrentTab, false); - EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy); + EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy); // Verify that a popup that creates a view first and then navigates to a // normal HTTP URL will be sent to the browser process, even though the // new view does not have any enabled_bindings_. - WebKit::WebURLRequest popup_request(GURL("http://foo.com")); - WebKit::WebView* new_web_view = view()->createView( - GetMainFrame(), popup_request, WebKit::WebWindowFeatures(), "foo", - WebKit::WebNavigationPolicyNewForegroundTab); + blink::WebURLRequest popup_request(GURL("http://foo.com")); + blink::WebView* new_web_view = view()->createView( + GetMainFrame(), popup_request, blink::WebWindowFeatures(), "foo", + blink::WebNavigationPolicyNewForegroundTab, false); RenderViewImpl* new_view = RenderViewImpl::FromWebView(new_web_view); policy = new_view->decidePolicyForNavigation( new_web_view->mainFrame(), &state, popup_request, - WebKit::WebNavigationTypeLinkClicked, - WebKit::WebNavigationPolicyNewForegroundTab, + blink::WebNavigationTypeLinkClicked, + blink::WebNavigationPolicyNewForegroundTab, false); - EXPECT_EQ(WebKit::WebNavigationPolicyIgnore, policy); + EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy); // Clean up after the new view so we don't leak it. new_view->Close(); @@ -1006,7 +1068,7 @@ TEST_F(RenderViewImplTest, ImeComposition) { case IME_SETCOMPOSITION: view()->OnImeSetComposition( WideToUTF16Hack(ime_message->ime_string), - std::vector<WebKit::WebCompositionUnderline>(), + std::vector<blink::WebCompositionUnderline>(), ime_message->selection_start, ime_message->selection_end); break; @@ -1020,8 +1082,8 @@ TEST_F(RenderViewImplTest, ImeComposition) { case IME_CANCELCOMPOSITION: view()->OnImeSetComposition( - string16(), - std::vector<WebKit::WebCompositionUnderline>(), + base::string16(), + std::vector<blink::WebCompositionUnderline>(), 0, 0); break; } @@ -1065,8 +1127,8 @@ TEST_F(RenderViewImplTest, OnSetTextDirection) { WebTextDirection direction; const wchar_t* expected_result; } kTextDirection[] = { - { WebKit::WebTextDirectionRightToLeft, L"\x000A" L"rtl,rtl" }, - { WebKit::WebTextDirectionLeftToRight, L"\x000A" L"ltr,ltr" }, + { blink::WebTextDirectionRightToLeft, L"\x000A" L"rtl,rtl" }, + { blink::WebTextDirectionLeftToRight, L"\x000A" L"ltr,ltr" }, }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTextDirection); ++i) { // Set the text direction of the <textarea> element. @@ -1208,7 +1270,7 @@ TEST_F(RenderViewImplTest, MAYBE_OnHandleKeyboardEvent) { // driver is installed in a PC and the driver can assign a Unicode // charcter for the given tuple (key-code and modifiers). int key_code = kKeyCodes[k]; - string16 char_code; + base::string16 char_code; if (SendKeyEvent(layout, key_code, modifiers, &char_code) < 0) continue; @@ -1455,7 +1517,7 @@ TEST_F(RenderViewImplTest, MAYBE_InsertCharacters) { // driver is installed in a PC and the driver can assign a Unicode // charcter for the given tuple (layout, key-code, and modifiers). int key_code = kKeyCodes[k]; - string16 char_code; + base::string16 char_code; if (SendKeyEvent(layout, key_code, modifiers, &char_code) < 0) continue; } @@ -1522,7 +1584,7 @@ TEST_F(RenderViewImplTest, DidFailProvisionalLoadWithErrorForCancellation) { // Regression test for http://crbug.com/41562 TEST_F(RenderViewImplTest, UpdateTargetURLWithInvalidURL) { const GURL invalid_gurl("http://"); - view()->setMouseOverURL(WebKit::WebURL(invalid_gurl)); + view()->setMouseOverURL(blink::WebURL(invalid_gurl)); EXPECT_EQ(invalid_gurl, view()->target_url_); } @@ -1711,9 +1773,9 @@ TEST_F(RenderViewImplTest, ContextMenu) { TEST_F(RenderViewImplTest, TestBackForward) { LoadHTML("<div id=pagename>Page A</div>"); - WebKit::WebHistoryItem page_a_item = GetMainFrame()->currentHistoryItem(); + blink::WebHistoryItem page_a_item = GetMainFrame()->currentHistoryItem(); int was_page_a = -1; - string16 check_page_a = + base::string16 check_page_a = ASCIIToUTF16( "Number(document.getElementById('pagename').innerHTML == 'Page A')"); EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a, &was_page_a)); @@ -1721,7 +1783,7 @@ TEST_F(RenderViewImplTest, TestBackForward) { LoadHTML("<div id=pagename>Page B</div>"); int was_page_b = -1; - string16 check_page_b = + base::string16 check_page_b = ASCIIToUTF16( "Number(document.getElementById('pagename').innerHTML == 'Page B')"); EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b)); @@ -1729,13 +1791,13 @@ TEST_F(RenderViewImplTest, TestBackForward) { LoadHTML("<div id=pagename>Page C</div>"); int was_page_c = -1; - string16 check_page_c = + base::string16 check_page_c = ASCIIToUTF16( "Number(document.getElementById('pagename').innerHTML == 'Page C')"); EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_c, &was_page_c)); EXPECT_EQ(1, was_page_b); - WebKit::WebHistoryItem forward_item = GetMainFrame()->currentHistoryItem(); + blink::WebHistoryItem forward_item = GetMainFrame()->currentHistoryItem(); GoBack(GetMainFrame()->previousHistoryItem()); EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b)); EXPECT_EQ(1, was_page_b); @@ -1760,17 +1822,24 @@ TEST_F(RenderViewImplTest, TestBackForward) { #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA) TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) { + +#if defined(OS_WIN) + // http://crbug.com/304193 + if (base::win::GetVersion() < base::win::VERSION_VISTA) + return; +#endif + LoadHTML("<textarea id=\"test\"></textarea>"); ExecuteJavaScript("document.getElementById('test').focus();"); - const string16 empty_string = UTF8ToUTF16(""); - const std::vector<WebKit::WebCompositionUnderline> empty_underline; + const base::string16 empty_string = UTF8ToUTF16(""); + const std::vector<blink::WebCompositionUnderline> empty_underline; std::vector<gfx::Rect> bounds; view()->OnSetFocus(true); view()->OnSetInputMethodActive(true); // ASCII composition - const string16 ascii_composition = UTF8ToUTF16("aiueo"); + const base::string16 ascii_composition = UTF8ToUTF16("aiueo"); view()->OnImeSetComposition(ascii_composition, empty_underline, 0, 0); view()->GetCompositionCharacterBounds(&bounds); ASSERT_EQ(ascii_composition.size(), bounds.size()); @@ -1780,7 +1849,7 @@ TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) { empty_string, gfx::Range::InvalidRange(), false); // Non surrogate pair unicode character. - const string16 unicode_composition = UTF8ToUTF16( + const base::string16 unicode_composition = UTF8ToUTF16( "\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A"); view()->OnImeSetComposition(unicode_composition, empty_underline, 0, 0); view()->GetCompositionCharacterBounds(&bounds); @@ -1791,7 +1860,7 @@ TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) { empty_string, gfx::Range::InvalidRange(), false); // Surrogate pair character. - const string16 surrogate_pair_char = UTF8ToUTF16("\xF0\xA0\xAE\x9F"); + const base::string16 surrogate_pair_char = UTF8ToUTF16("\xF0\xA0\xAE\x9F"); view()->OnImeSetComposition(surrogate_pair_char, empty_underline, 0, @@ -1804,7 +1873,7 @@ TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) { empty_string, gfx::Range::InvalidRange(), false); // Mixed string. - const string16 surrogate_pair_mixed_composition = + const base::string16 surrogate_pair_mixed_composition = surrogate_pair_char + UTF8ToUTF16("\xE3\x81\x82") + surrogate_pair_char + UTF8ToUTF16("b") + surrogate_pair_char; const size_t utf16_length = 8UL; @@ -1866,9 +1935,9 @@ TEST_F(RenderViewImplTest, SetEditableSelectionAndComposition) { "</html>"); ExecuteJavaScript("document.getElementById('test1').focus();"); view()->OnSetEditableSelectionOffsets(4, 8); - const std::vector<WebKit::WebCompositionUnderline> empty_underline; + const std::vector<blink::WebCompositionUnderline> empty_underline; view()->OnSetCompositionFromExistingText(7, 10, empty_underline); - WebKit::WebTextInputInfo info = view()->webview()->textInputInfo(); + blink::WebTextInputInfo info = view()->webview()->textInputInfo(); EXPECT_EQ(4, info.selectionStart); EXPECT_EQ(8, info.selectionEnd); EXPECT_EQ(7, info.compositionStart); @@ -1892,7 +1961,7 @@ TEST_F(RenderViewImplTest, OnExtendSelectionAndDelete) { ExecuteJavaScript("document.getElementById('test1').focus();"); view()->OnSetEditableSelectionOffsets(10, 10); view()->OnExtendSelectionAndDelete(3, 4); - WebKit::WebTextInputInfo info = view()->webview()->textInputInfo(); + blink::WebTextInputInfo info = view()->webview()->textInputInfo(); EXPECT_EQ("abcdefgopqrstuvwxyz", info.value); EXPECT_EQ(7, info.selectionStart); EXPECT_EQ(7, info.selectionEnd); @@ -1943,13 +2012,45 @@ TEST_F(RenderViewImplTest, GetSSLStatusOfFrame) { SSLStatus ssl_status = view()->GetSSLStatusOfFrame(frame); EXPECT_FALSE(net::IsCertStatusError(ssl_status.cert_status)); - const_cast<WebKit::WebURLResponse&>(frame->dataSource()->response()). + const_cast<blink::WebURLResponse&>(frame->dataSource()->response()). setSecurityInfo( - SerializeSecurityInfo(0, net::CERT_STATUS_ALL_ERRORS, 0, 0)); + SerializeSecurityInfo(0, net::CERT_STATUS_ALL_ERRORS, 0, 0, + SignedCertificateTimestampIDStatusList())); ssl_status = view()->GetSSLStatusOfFrame(frame); EXPECT_TRUE(net::IsCertStatusError(ssl_status.cert_status)); } +TEST_F(RenderViewImplTest, MessageOrderInDidChangeSelection) { + view()->OnSetInputMethodActive(true); + view()->set_send_content_state_immediately(true); + LoadHTML("<textarea id=\"test\"></textarea>"); + + view()->handling_input_event_ = true; + ExecuteJavaScript("document.getElementById('test').focus();"); + + bool is_input_type_called = false; + bool is_selection_called = false; + size_t last_input_type = 0; + size_t last_selection = 0; + + for (size_t i = 0; i < render_thread_->sink().message_count(); ++i) { + const uint32 type = render_thread_->sink().GetMessageAt(i)->type(); + if (type == ViewHostMsg_TextInputTypeChanged::ID) { + is_input_type_called = true; + last_input_type = i; + } else if (type == ViewHostMsg_SelectionChanged::ID) { + is_selection_called = true; + last_selection = i; + } + } + + EXPECT_TRUE(is_input_type_called); + EXPECT_TRUE(is_selection_called); + + // InputTypeChange shold be called earlier than SelectionChanged. + EXPECT_LT(last_input_type, last_selection); +} + class SuppressErrorPageTest : public RenderViewTest { public: virtual void SetUp() OVERRIDE { @@ -1969,11 +2070,12 @@ class SuppressErrorPageTest : public RenderViewTest { } virtual void GetNavigationErrorStrings( - WebKit::WebFrame* frame, - const WebKit::WebURLRequest& failed_request, - const WebKit::WebURLError& error, + blink::WebFrame* frame, + const blink::WebURLRequest& failed_request, + const blink::WebURLError& error, + const std::string& accept_languages, std::string* error_html, - string16* error_description) OVERRIDE { + base::string16* error_description) OVERRIDE { if (error_html) *error_html = "A suffusion of yellow."; } @@ -1982,7 +2084,14 @@ class SuppressErrorPageTest : public RenderViewTest { TestContentRendererClient client_; }; -TEST_F(SuppressErrorPageTest, Suppresses) { +#if defined(OS_ANDROID) +// Crashing on Android: http://crbug.com/311341 +#define MAYBE_Suppresses DISABLED_Suppresses +#else +#define MAYBE_Suppresses Suppresses +#endif + +TEST_F(SuppressErrorPageTest, MAYBE_Suppresses) { WebURLError error; error.domain = WebString::fromUTF8(net::kErrorDomain); error.reason = net::ERR_FILE_NOT_FOUND; @@ -2003,7 +2112,14 @@ TEST_F(SuppressErrorPageTest, Suppresses) { EXPECT_EQ("", UTF16ToASCII(web_frame->contentAsText(kMaxOutputCharacters))); } -TEST_F(SuppressErrorPageTest, DoesNotSuppress) { +#if defined(OS_ANDROID) +// Crashing on Android: http://crbug.com/311341 +#define MAYBE_DoesNotSuppress DISABLED_DoesNotSuppress +#else +#define MAYBE_DoesNotSuppress DoesNotSuppress +#endif + +TEST_F(SuppressErrorPageTest, MAYBE_DoesNotSuppress) { WebURLError error; error.domain = WebString::fromUTF8(net::kErrorDomain); error.reason = net::ERR_FILE_NOT_FOUND; @@ -2026,4 +2142,42 @@ TEST_F(SuppressErrorPageTest, DoesNotSuppress) { UTF16ToASCII(web_frame->contentAsText(kMaxOutputCharacters))); } +// Tests if IME API's candidatewindow* events sent from browser are handled +// in renderer. +TEST_F(RenderViewImplTest, SendCandidateWindowEvents) { + // Sends an HTML with an <input> element and scripts to the renderer. + // The script handles all 3 of candidatewindow* events for an + // InputMethodContext object and once it received 'show', 'update', 'hide' + // should appear in the result div. + LoadHTML("<input id='test'>" + "<div id='result'>Result: </div>" + "<script>" + "window.onload = function() {" + " var result = document.getElementById('result');" + " var test = document.getElementById('test');" + " test.focus();" + " var context = test.inputMethodContext;" + " if (context) {" + " context.oncandidatewindowshow = function() {" + " result.innerText += 'show'; };" + " context.oncandidatewindowupdate = function(){" + " result.innerText += 'update'; };" + " context.oncandidatewindowhide = function(){" + " result.innerText += 'hide'; };" + " }" + "};" + "</script>"); + + // Fire candidatewindow events. + view()->OnCandidateWindowShown(); + view()->OnCandidateWindowUpdated(); + view()->OnCandidateWindowHidden(); + + // Retrieve the content and check if it is expected. + const int kMaxOutputCharacters = 50; + std::string output = UTF16ToUTF8( + GetMainFrame()->contentAsText(kMaxOutputCharacters)); + EXPECT_EQ(output, "\nResult:showupdatehide"); +} + } // namespace content diff --git a/chromium/content/renderer/render_view_browsertest_mac.mm b/chromium/content/renderer/render_view_browsertest_mac.mm index d025ca8647f..f0959e06e1b 100644 --- a/chromium/content/renderer/render_view_browsertest_mac.mm +++ b/chromium/content/renderer/render_view_browsertest_mac.mm @@ -50,37 +50,32 @@ TEST_F(RenderViewTest, MacTestCmdUp) { // a single long line). #define HTML(s) #s const char* kRawHtml = HTML( - <html> - <head><title></title> - <script type='text/javascript' language='javascript'> - function OnKeyEvent(ev) { - var result = document.getElementById(ev.type); - result.innerText = (ev.which || ev.keyCode) + ',' + - ev.shiftKey + ',' + - ev.ctrlKey + ',' + - ev.metaKey + ',' + - ev.altKey; - return %s; /* Replace with "return true;" when testing in an html file. */ - } - function OnScroll(ev) { - var result = document.getElementById("scroll"); - result.innerText = window.pageYOffset; - return true; - } - </script> - <style type="text/css"> - p { border-bottom:5000px solid black; } /* enforce vertical scroll bar */ + <!DOCTYPE html> + <style> + /* Add a vertical scrollbar */ + body { height: 10128px; } </style> - </head> - <body - onscroll='return OnScroll(event);' - onkeydown='return OnKeyEvent(event);'> - <div id='keydown' contenteditable='true'> </div> - <div id='scroll' contenteditable='true'> </div> + <div id='keydown'></div> + <div id='scroll'></div> + <script> + var allowKeyEvents = true; + var scroll = document.getElementById('scroll'); + var result = document.getElementById('keydown'); + onkeydown = function(event) { + result.textContent = + event.keyCode + ',' + + event.shiftKey + ',' + + event.ctrlKey + ',' + + event.metaKey + ',' + + event.altKey; + return allowKeyEvents; + } + </script> + <!-- + TODO(esprehn): For some strange reason we need a non-empty document for + scrolling to work. This is not the case in a real browser only in the test. + --> <p>p1 - <p>p2 - </body> - </html> ); #undef HTML @@ -91,58 +86,54 @@ TEST_F(RenderViewTest, MacTestCmdUp) { view->OnUpdateWebPreferences(prefs); const int kMaxOutputCharacters = 1024; - string16 output; - char htmlBuffer[2048]; + base::string16 output; NSEvent* arrowDownKeyDown = CmdDeadKeyEvent(NSKeyDown, kVK_DownArrow); NSEvent* arrowUpKeyDown = CmdDeadKeyEvent(NSKeyDown, kVK_UpArrow); // First test when javascript does not eat keypresses -- should scroll. - sprintf(htmlBuffer, kRawHtml, "true"); view->set_send_content_state_immediately(true); - LoadHTML(htmlBuffer); + LoadHTML(kRawHtml); render_thread_->sink().ClearMessages(); - const char* kArrowDownScrollDown = - "40,false,false,true,false\n10128\np1\n\np2"; + const char* kArrowDownScrollDown = "40,false,false,true,false\n10144\np1"; view->OnSetEditCommandsForNextKeyEvent( EditCommands(1, EditCommand("moveToEndOfDocument", ""))); SendNativeKeyEvent(NativeWebKeyboardEvent(arrowDownKeyDown)); ProcessPendingMessages(); + ExecuteJavaScript("scroll.textContent = window.pageYOffset"); output = GetMainFrame()->contentAsText(kMaxOutputCharacters); EXPECT_EQ(kArrowDownScrollDown, UTF16ToASCII(output)); - const char* kArrowUpScrollUp = - "38,false,false,true,false\n0\np1\n\np2"; + const char* kArrowUpScrollUp = "38,false,false,true,false\n0\np1"; view->OnSetEditCommandsForNextKeyEvent( EditCommands(1, EditCommand("moveToBeginningOfDocument", ""))); SendNativeKeyEvent(NativeWebKeyboardEvent(arrowUpKeyDown)); ProcessPendingMessages(); + ExecuteJavaScript("scroll.textContent = window.pageYOffset"); output = GetMainFrame()->contentAsText(kMaxOutputCharacters); EXPECT_EQ(kArrowUpScrollUp, UTF16ToASCII(output)); + // Now let javascript eat the key events -- no scrolling should happen. + // Set a scroll position slightly down the page to ensure that it does not + // move. + ExecuteJavaScript("allowKeyEvents = false; window.scrollTo(0, 100)"); - // Now let javascript eat the key events -- no scrolling should happen - sprintf(htmlBuffer, kRawHtml, "false"); - view->set_send_content_state_immediately(true); - LoadHTML(htmlBuffer); - render_thread_->sink().ClearMessages(); - - const char* kArrowDownNoScroll = - "40,false,false,true,false\np1\n\np2"; + const char* kArrowDownNoScroll = "40,false,false,true,false\n100\np1"; view->OnSetEditCommandsForNextKeyEvent( EditCommands(1, EditCommand("moveToEndOfDocument", ""))); SendNativeKeyEvent(NativeWebKeyboardEvent(arrowDownKeyDown)); ProcessPendingMessages(); + ExecuteJavaScript("scroll.textContent = window.pageYOffset"); output = GetMainFrame()->contentAsText(kMaxOutputCharacters); EXPECT_EQ(kArrowDownNoScroll, UTF16ToASCII(output)); - const char* kArrowUpNoScroll = - "38,false,false,true,false\np1\n\np2"; + const char* kArrowUpNoScroll = "38,false,false,true,false\n100\np1"; view->OnSetEditCommandsForNextKeyEvent( EditCommands(1, EditCommand("moveToBeginningOfDocument", ""))); SendNativeKeyEvent(NativeWebKeyboardEvent(arrowUpKeyDown)); ProcessPendingMessages(); + ExecuteJavaScript("scroll.textContent = window.pageYOffset"); output = GetMainFrame()->contentAsText(kMaxOutputCharacters); EXPECT_EQ(kArrowUpNoScroll, UTF16ToASCII(output)); } diff --git a/chromium/content/renderer/render_view_impl.cc b/chromium/content/renderer/render_view_impl.cc index 6efebffe5f9..134281769ca 100644 --- a/chromium/content/renderer/render_view_impl.cc +++ b/chromium/content/renderer/render_view_impl.cc @@ -15,7 +15,7 @@ #include "base/debug/alias.h" #include "base/debug/trace_event.h" #include "base/files/file_path.h" -#include "base/i18n/char_iterator.h" +#include "base/i18n/rtl.h" #include "base/json/json_writer.h" #include "base/lazy_instance.h" #include "base/memory/scoped_ptr.h" @@ -23,6 +23,7 @@ #include "base/metrics/histogram.h" #include "base/path_service.h" #include "base/process/kill.h" +#include "base/process/process.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" @@ -30,6 +31,7 @@ #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" +#include "cc/base/switches.h" #include "content/child/appcache/appcache_dispatcher.h" #include "content/child/appcache/web_application_cache_host_impl.h" #include "content/child/child_thread.h" @@ -75,7 +77,6 @@ #include "content/renderer/browser_plugin/browser_plugin_manager.h" #include "content/renderer/browser_plugin/browser_plugin_manager_impl.h" #include "content/renderer/context_menu_params_builder.h" -#include "content/renderer/device_orientation_dispatcher.h" #include "content/renderer/devtools/devtools_agent.h" #include "content/renderer/disambiguation_popup_helper.h" #include "content/renderer/dom_automation_controller.h" @@ -84,11 +85,11 @@ #include "content/renderer/external_popup_menu.h" #include "content/renderer/fetchers/alt_error_page_resource_fetcher.h" #include "content/renderer/geolocation_dispatcher.h" -#include "content/renderer/gpu/input_handler_manager.h" #include "content/renderer/gpu/render_widget_compositor.h" #include "content/renderer/idle_user_detector.h" #include "content/renderer/image_loading_helper.h" #include "content/renderer/ime_event_guard.h" +#include "content/renderer/input/input_handler_manager.h" #include "content/renderer/input_tag_speech_dispatcher.h" #include "content/renderer/internal_document_state_data.h" #include "content/renderer/java/java_bridge_dispatcher.h" @@ -112,10 +113,11 @@ #include "content/renderer/render_view_impl_params.h" #include "content/renderer/render_view_mouse_lock_dispatcher.h" #include "content/renderer/render_widget_fullscreen_pepper.h" -#include "content/renderer/renderer_date_time_picker.h" #include "content/renderer/renderer_webapplicationcachehost_impl.h" #include "content/renderer/renderer_webcolorchooser_impl.h" +#include "content/renderer/resizing_mode_selector.h" #include "content/renderer/savable_resources.h" +#include "content/renderer/shared_worker_repository.h" #include "content/renderer/speech_recognition_dispatcher.h" #include "content/renderer/stats_collection_controller.h" #include "content/renderer/stats_collection_observer.h" @@ -144,6 +146,7 @@ #include "third_party/WebKit/public/platform/WebRect.h" #include "third_party/WebKit/public/platform/WebSize.h" #include "third_party/WebKit/public/platform/WebSocketStreamHandle.h" +#include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURL.h" #include "third_party/WebKit/public/platform/WebURLError.h" @@ -152,6 +155,7 @@ #include "third_party/WebKit/public/platform/WebVector.h" #include "third_party/WebKit/public/web/WebAXObject.h" #include "third_party/WebKit/public/web/WebColorName.h" +#include "third_party/WebKit/public/web/WebColorSuggestion.h" #include "third_party/WebKit/public/web/WebDOMEvent.h" #include "third_party/WebKit/public/web/WebDOMMessageEvent.h" #include "third_party/WebKit/public/web/WebDataSource.h" @@ -178,7 +182,6 @@ #include "third_party/WebKit/public/web/WebPluginAction.h" #include "third_party/WebKit/public/web/WebPluginContainer.h" #include "third_party/WebKit/public/web/WebPluginDocument.h" -#include "third_party/WebKit/public/web/WebPluginParams.h" #include "third_party/WebKit/public/web/WebRange.h" #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" #include "third_party/WebKit/public/web/WebScriptSource.h" @@ -187,13 +190,13 @@ #include "third_party/WebKit/public/web/WebSecurityPolicy.h" #include "third_party/WebKit/public/web/WebSerializedScriptValue.h" #include "third_party/WebKit/public/web/WebSettings.h" -#include "third_party/WebKit/public/web/WebStorageQuotaCallbacks.h" #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" #include "third_party/WebKit/public/web/WebUserMediaClient.h" #include "third_party/WebKit/public/web/WebView.h" #include "third_party/WebKit/public/web/WebWindowFeatures.h" #include "third_party/WebKit/public/web/default/WebRenderTheme.h" #include "ui/base/ui_base_switches_util.h" +#include "ui/events/latency_info.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/point.h" #include "ui/gfx/rect.h" @@ -216,7 +219,6 @@ #include "content/renderer/media/android/renderer_media_player_manager.h" #include "content/renderer/media/android/stream_texture_factory_android_impl.h" #include "content/renderer/media/android/webmediaplayer_android.h" -#include "content/renderer/media/android/webmediaplayer_proxy_android.h" #include "skia/ext/platform_canvas.h" #include "third_party/WebKit/public/platform/WebFloatPoint.h" #include "third_party/WebKit/public/platform/WebFloatRect.h" @@ -240,116 +242,109 @@ #if defined(ENABLE_PLUGINS) #include "content/renderer/npapi/webplugin_delegate_proxy.h" -#include "content/renderer/npapi/webplugin_impl.h" -#include "content/renderer/pepper/pepper_browser_connection.h" #include "content/renderer/pepper/pepper_plugin_instance_impl.h" #include "content/renderer/pepper/pepper_plugin_registry.h" -#include "content/renderer/pepper/pepper_webplugin_impl.h" -#include "content/renderer/pepper/plugin_module.h" #endif #if defined(ENABLE_WEBRTC) #include "content/renderer/media/rtc_peer_connection_handler.h" #endif -using WebKit::WebAXObject; -using WebKit::WebApplicationCacheHost; -using WebKit::WebApplicationCacheHostClient; -using WebKit::WebCString; -using WebKit::WebColor; -using WebKit::WebColorName; -using WebKit::WebConsoleMessage; -using WebKit::WebContextMenuData; -using WebKit::WebCookieJar; -using WebKit::WebData; -using WebKit::WebDataSource; -using WebKit::WebDocument; -using WebKit::WebDOMEvent; -using WebKit::WebDOMMessageEvent; -using WebKit::WebDragData; -using WebKit::WebDragOperation; -using WebKit::WebDragOperationsMask; -using WebKit::WebEditingAction; -using WebKit::WebElement; -using WebKit::WebExternalPopupMenu; -using WebKit::WebExternalPopupMenuClient; -using WebKit::WebFileChooserCompletion; -using WebKit::WebFindOptions; -using WebKit::WebFormControlElement; -using WebKit::WebFormElement; -using WebKit::WebFrame; -using WebKit::WebGestureEvent; -using WebKit::WebHistoryItem; -using WebKit::WebHTTPBody; -using WebKit::WebIconURL; -using WebKit::WebImage; -using WebKit::WebInputElement; -using WebKit::WebInputEvent; -using WebKit::WebMediaPlayer; -using WebKit::WebMediaPlayerAction; -using WebKit::WebMediaPlayerClient; -using WebKit::WebMouseEvent; -using WebKit::WebNavigationPolicy; -using WebKit::WebNavigationType; -using WebKit::WebNode; -using WebKit::WebPageSerializer; -using WebKit::WebPageSerializerClient; -using WebKit::WebPeerConnection00Handler; -using WebKit::WebPeerConnection00HandlerClient; -using WebKit::WebPeerConnectionHandler; -using WebKit::WebPeerConnectionHandlerClient; -using WebKit::WebPluginAction; -using WebKit::WebPluginContainer; -using WebKit::WebPluginDocument; -using WebKit::WebPluginParams; -using WebKit::WebPoint; -using WebKit::WebPopupMenuInfo; -using WebKit::WebRange; -using WebKit::WebRect; -using WebKit::WebReferrerPolicy; -using WebKit::WebRuntimeFeatures; -using WebKit::WebScriptSource; -using WebKit::WebSearchableFormData; -using WebKit::WebSecurityOrigin; -using WebKit::WebSecurityPolicy; -using WebKit::WebSerializedScriptValue; -using WebKit::WebSettings; -using WebKit::WebSharedWorker; -using WebKit::WebSize; -using WebKit::WebSocketStreamHandle; -using WebKit::WebStorageNamespace; -using WebKit::WebStorageQuotaCallbacks; -using WebKit::WebStorageQuotaError; -using WebKit::WebStorageQuotaType; -using WebKit::WebString; -using WebKit::WebTextAffinity; -using WebKit::WebTextDirection; -using WebKit::WebTouchEvent; -using WebKit::WebURL; -using WebKit::WebURLError; -using WebKit::WebURLRequest; -using WebKit::WebURLResponse; -using WebKit::WebUserGestureIndicator; -using WebKit::WebVector; -using WebKit::WebView; -using WebKit::WebWidget; -using WebKit::WebWindowFeatures; +using blink::WebAXObject; +using blink::WebApplicationCacheHost; +using blink::WebApplicationCacheHostClient; +using blink::WebCString; +using blink::WebColor; +using blink::WebColorName; +using blink::WebConsoleMessage; +using blink::WebContextMenuData; +using blink::WebCookieJar; +using blink::WebData; +using blink::WebDataSource; +using blink::WebDocument; +using blink::WebDOMEvent; +using blink::WebDOMMessageEvent; +using blink::WebDragData; +using blink::WebDragOperation; +using blink::WebDragOperationsMask; +using blink::WebElement; +using blink::WebExternalPopupMenu; +using blink::WebExternalPopupMenuClient; +using blink::WebFileChooserCompletion; +using blink::WebFindOptions; +using blink::WebFormControlElement; +using blink::WebFormElement; +using blink::WebFrame; +using blink::WebGestureEvent; +using blink::WebHistoryItem; +using blink::WebHTTPBody; +using blink::WebIconURL; +using blink::WebImage; +using blink::WebInputElement; +using blink::WebInputEvent; +using blink::WebMediaPlayer; +using blink::WebMediaPlayerAction; +using blink::WebMediaPlayerClient; +using blink::WebMouseEvent; +using blink::WebNavigationPolicy; +using blink::WebNavigationType; +using blink::WebNode; +using blink::WebPageSerializer; +using blink::WebPageSerializerClient; +using blink::WebPeerConnection00Handler; +using blink::WebPeerConnection00HandlerClient; +using blink::WebPeerConnectionHandler; +using blink::WebPeerConnectionHandlerClient; +using blink::WebPluginAction; +using blink::WebPluginContainer; +using blink::WebPluginDocument; +using blink::WebPoint; +using blink::WebPopupMenuInfo; +using blink::WebRange; +using blink::WebRect; +using blink::WebReferrerPolicy; +using blink::WebRuntimeFeatures; +using blink::WebScriptSource; +using blink::WebSearchableFormData; +using blink::WebSecurityOrigin; +using blink::WebSecurityPolicy; +using blink::WebSerializedScriptValue; +using blink::WebSettings; +using blink::WebSize; +using blink::WebSocketStreamHandle; +using blink::WebStorageNamespace; +using blink::WebStorageQuotaCallbacks; +using blink::WebStorageQuotaError; +using blink::WebStorageQuotaType; +using blink::WebString; +using blink::WebTextAffinity; +using blink::WebTextDirection; +using blink::WebTouchEvent; +using blink::WebURL; +using blink::WebURLError; +using blink::WebURLRequest; +using blink::WebURLResponse; +using blink::WebUserGestureIndicator; +using blink::WebVector; +using blink::WebView; +using blink::WebWidget; +using blink::WebWindowFeatures; using base::Time; using base::TimeDelta; using webkit_glue::WebURLResponseExtraDataImpl; #if defined(OS_ANDROID) -using WebKit::WebContentDetectionResult; -using WebKit::WebFloatPoint; -using WebKit::WebFloatRect; -using WebKit::WebHitTestResult; +using blink::WebContentDetectionResult; +using blink::WebFloatPoint; +using blink::WebFloatRect; +using blink::WebHitTestResult; #endif namespace content { //----------------------------------------------------------------------------- -typedef std::map<WebKit::WebView*, RenderViewImpl*> ViewMap; +typedef std::map<blink::WebView*, RenderViewImpl*> ViewMap; static base::LazyInstance<ViewMap> g_view_map = LAZY_INSTANCE_INITIALIZER; typedef std::map<int32, RenderViewImpl*> RoutingIDViewMap; static base::LazyInstance<RoutingIDViewMap> g_routing_id_view_map = @@ -363,19 +358,17 @@ static base::LazyInstance<RoutingIDViewMap> g_routing_id_view_map = // foreground renderer. This means there is a small window of time from which // content state is modified and not sent to session restore, but this is // better than having to wake up all renderers during shutdown. -static const int kDelaySecondsForContentStateSyncHidden = 5; -static const int kDelaySecondsForContentStateSync = 1; +const int kDelaySecondsForContentStateSyncHidden = 5; +const int kDelaySecondsForContentStateSync = 1; -static const size_t kExtraCharsBeforeAndAfterSelection = 100; +const size_t kExtraCharsBeforeAndAfterSelection = 100; -static const float kScalingIncrement = 0.1f; - -static const float kScalingIncrementForGesture = 0.01f; +const float kScalingIncrementForGesture = 0.01f; #if defined(OS_ANDROID) // Delay between tapping in content and launching the associated android intent. // Used to allow users see what has been recognized as content. -static const size_t kContentIntentDelayMilliseconds = 700; +const size_t kContentIntentDelayMilliseconds = 700; #endif static RenderViewImpl* (*g_create_render_view_impl)(RenderViewImplParams*) = @@ -521,13 +514,13 @@ static bool IsNonLocalTopLevelNavigation(const GURL& url, if (!url.SchemeIs(kHttpScheme) && !url.SchemeIs(kHttpsScheme)) return false; - if (type != WebKit::WebNavigationTypeReload && - type != WebKit::WebNavigationTypeBackForward && !is_form_post) { + if (type != blink::WebNavigationTypeReload && + type != blink::WebNavigationTypeBackForward && !is_form_post) { // The opener relationship between the new window and the parent allows the // new window to script the parent and vice versa. This is not allowed if // the origins of the two domains are different. This can be treated as a // top level navigation and routed back to the host. - WebKit::WebFrame* opener = frame->opener(); + blink::WebFrame* opener = frame->opener(); if (!opener) return true; @@ -537,11 +530,11 @@ static bool IsNonLocalTopLevelNavigation(const GURL& url, return false; } -static void NotifyTimezoneChange(WebKit::WebFrame* frame) { +static void NotifyTimezoneChange(blink::WebFrame* frame) { v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); v8::Context::Scope context_scope(frame->mainWorldScriptContext()); - v8::Date::DateTimeConfigurationChangeNotification(); - WebKit::WebFrame* child = frame->firstChild(); + v8::Date::DateTimeConfigurationChangeNotification(v8::Isolate::GetCurrent()); + blink::WebFrame* child = frame->firstChild(); for (; child; child = child->nextSibling()) NotifyTimezoneChange(child); } @@ -549,19 +542,19 @@ static void NotifyTimezoneChange(WebKit::WebFrame* frame) { static WindowOpenDisposition NavigationPolicyToDisposition( WebNavigationPolicy policy) { switch (policy) { - case WebKit::WebNavigationPolicyIgnore: + case blink::WebNavigationPolicyIgnore: return IGNORE_ACTION; - case WebKit::WebNavigationPolicyDownload: + case blink::WebNavigationPolicyDownload: return SAVE_TO_DISK; - case WebKit::WebNavigationPolicyCurrentTab: + case blink::WebNavigationPolicyCurrentTab: return CURRENT_TAB; - case WebKit::WebNavigationPolicyNewBackgroundTab: + case blink::WebNavigationPolicyNewBackgroundTab: return NEW_BACKGROUND_TAB; - case WebKit::WebNavigationPolicyNewForegroundTab: + case blink::WebNavigationPolicyNewForegroundTab: return NEW_FOREGROUND_TAB; - case WebKit::WebNavigationPolicyNewWindow: + case blink::WebNavigationPolicyNewWindow: return NEW_WINDOW; - case WebKit::WebNavigationPolicyNewPopup: + case blink::WebNavigationPolicyNewPopup: return NEW_POPUP; default: NOTREACHED() << "Unexpected WebNavigationPolicy"; @@ -599,12 +592,61 @@ static bool ShouldUseAcceleratedCompositingForOverflowScroll( float device_scale_factor) { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(switches::kDisableAcceleratedOverflowScroll)) + return false; + if (command_line.HasSwitch(switches::kEnableAcceleratedOverflowScroll)) return true; return DeviceScaleEnsuresTextQuality(device_scale_factor); } +static bool ShouldUseAcceleratedCompositingForScrollableFrames( + float device_scale_factor) { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + + if (command_line.HasSwitch(switches::kDisableAcceleratedScrollableFrames)) + return false; + + if (command_line.HasSwitch(switches::kEnableAcceleratedScrollableFrames)) + return true; + + if (!cc::switches::IsLCDTextEnabled()) + return true; + + return DeviceScaleEnsuresTextQuality(device_scale_factor); +} + +static bool ShouldUseCompositedScrollingForFrames( + float device_scale_factor) { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + + if (command_line.HasSwitch(switches::kDisableCompositedScrollingForFrames)) + return false; + + if (command_line.HasSwitch(switches::kEnableCompositedScrollingForFrames)) + return true; + + if (!cc::switches::IsLCDTextEnabled()) + return true; + + return DeviceScaleEnsuresTextQuality(device_scale_factor); +} + +static bool ShouldUseUniversalAcceleratedCompositingForOverflowScroll() { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + + if (command_line.HasSwitch( + switches::kDisableUniversalAcceleratedOverflowScroll)) + return false; + + if (command_line.HasSwitch( + switches::kEnableUniversalAcceleratedOverflowScroll)) + return true; + + return false; +} + static bool ShouldUseTransitionCompositing(float device_scale_factor) { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); @@ -632,15 +674,15 @@ static bool ShouldUseAcceleratedFixedRootBackground(float device_scale_factor) { return DeviceScaleEnsuresTextQuality(device_scale_factor); } -static FaviconURL::IconType ToFaviconType(WebKit::WebIconURL::Type type) { +static FaviconURL::IconType ToFaviconType(blink::WebIconURL::Type type) { switch (type) { - case WebKit::WebIconURL::TypeFavicon: + case blink::WebIconURL::TypeFavicon: return FaviconURL::FAVICON; - case WebKit::WebIconURL::TypeTouch: + case blink::WebIconURL::TypeTouch: return FaviconURL::TOUCH_ICON; - case WebKit::WebIconURL::TypeTouchPrecomposed: + case blink::WebIconURL::TypeTouchPrecomposed: return FaviconURL::TOUCH_PRECOMPOSED_ICON; - case WebKit::WebIconURL::TypeInvalid: + case blink::WebIconURL::TypeInvalid: return FaviconURL::INVALID_ICON; } return FaviconURL::INVALID_ICON; @@ -661,7 +703,7 @@ namespace { class WebWidgetLockTarget : public MouseLockDispatcher::LockTarget { public: - explicit WebWidgetLockTarget(WebKit::WebWidget* webwidget) + explicit WebWidgetLockTarget(blink::WebWidget* webwidget) : webwidget_(webwidget) {} virtual void OnLockMouseACK(bool succeeded) OVERRIDE { @@ -676,13 +718,13 @@ class WebWidgetLockTarget : public MouseLockDispatcher::LockTarget { } virtual bool HandleMouseLockedInputEvent( - const WebKit::WebMouseEvent &event) OVERRIDE { + const blink::WebMouseEvent &event) OVERRIDE { // The WebWidget handles mouse lock in WebKit's handleInputEvent(). return false; } private: - WebKit::WebWidget* webwidget_; + blink::WebWidget* webwidget_; }; int64 ExtractPostId(const WebHistoryItem& item) { @@ -772,7 +814,7 @@ WebDragData DropDataToWebDragData(const DropData& drop_data) { } // namespace RenderViewImpl::RenderViewImpl(RenderViewImplParams* params) - : RenderWidget(WebKit::WebPopupTypeNone, + : RenderWidget(blink::WebPopupTypeNone, params->screen_info, params->swapped_out, params->hidden), @@ -784,6 +826,7 @@ RenderViewImpl::RenderViewImpl(RenderViewImplParams* params) navigation_gesture_(NavigationGestureUnknown), opened_by_user_gesture_(true), opener_suppressed_(false), + suppress_dialogs_until_swap_out_(false), page_id_(-1), last_page_id_sent_to_browser_(-1), next_page_id_(params->next_page_id), @@ -804,7 +847,6 @@ RenderViewImpl::RenderViewImpl(RenderViewImplParams* params) geolocation_dispatcher_(NULL), input_tag_speech_dispatcher_(NULL), speech_recognition_dispatcher_(NULL), - device_orientation_dispatcher_(NULL), media_stream_dispatcher_(NULL), browser_plugin_manager_(NULL), media_stream_client_(NULL), @@ -813,12 +855,11 @@ RenderViewImpl::RenderViewImpl(RenderViewImplParams* params) devtools_agent_(NULL), accessibility_mode_(AccessibilityModeOff), renderer_accessibility_(NULL), - java_bridge_dispatcher_(NULL), mouse_lock_dispatcher_(NULL), #if defined(OS_ANDROID) body_background_color_(SK_ColorWHITE), expected_content_intent_id_(0), - media_player_proxy_(NULL), + media_player_manager_(NULL), #endif #if defined(OS_WIN) focused_plugin_id_(-1), @@ -837,9 +878,6 @@ RenderViewImpl::RenderViewImpl(RenderViewImplParams* params) } void RenderViewImpl::Initialize(RenderViewImplParams* params) { - RenderFrameImpl* main_frame = RenderFrameImpl::Create( - this, params->main_frame_routing_id); - main_render_frame_.reset(main_frame); routing_id_ = params->routing_id; surface_id_ = params->surface_id; if (params->opener_id != MSG_ROUTING_NONE && params->is_renderer_created) @@ -898,13 +936,24 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) { ShouldUseFixedPositionCompositing(device_scale_factor_)); webview()->settings()->setAcceleratedCompositingForOverflowScrollEnabled( ShouldUseAcceleratedCompositingForOverflowScroll(device_scale_factor_)); + webview()->settings()->setCompositorDrivenAcceleratedScrollingEnabled( + ShouldUseUniversalAcceleratedCompositingForOverflowScroll()); webview()->settings()->setAcceleratedCompositingForTransitionEnabled( ShouldUseTransitionCompositing(device_scale_factor_)); webview()->settings()->setAcceleratedCompositingForFixedRootBackgroundEnabled( ShouldUseAcceleratedFixedRootBackground(device_scale_factor_)); + webview()->settings()->setAcceleratedCompositingForScrollableFramesEnabled( + ShouldUseAcceleratedCompositingForScrollableFrames(device_scale_factor_)); + webview()->settings()->setCompositedScrollingForFramesEnabled( + ShouldUseCompositedScrollingForFrames(device_scale_factor_)); ApplyWebPreferences(webkit_preferences_, webview()); - webview()->initializeMainFrame(main_render_frame_.get()); + + main_render_frame_.reset( + RenderFrameImpl::Create(this, params->main_frame_routing_id)); + // The main frame WebFrame object is closed by + // RenderViewImpl::frameDetached(). + webview()->setMainFrame(WebFrame::create(main_render_frame_.get())); if (switches::IsTouchDragDropEnabled()) webview()->settings()->setTouchDragDropEnabled(true); @@ -927,8 +976,11 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) { new TextInputClientObserver(this); #endif // defined(OS_MACOSX) + new SharedWorkerRepository(this); + #if defined(OS_ANDROID) - media_player_manager_.reset(new RendererMediaPlayerManager()); + media_player_manager_ = new RendererMediaPlayerManager(this); + new JavaBridgeDispatcher(this); #endif // The next group of objects all implement RenderViewObserver, so are deleted @@ -952,10 +1004,6 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) { ProcessViewLayoutFlags(command_line); -#if defined(ENABLE_PLUGINS) - new PepperBrowserConnection(this); -#endif - GetContentClient()->renderer()->RenderViewCreated(this); // If we have an opener_id but we weren't created by a renderer, then @@ -1015,7 +1063,7 @@ RenderViewImpl* RenderViewImpl::FromWebView(WebView* webview) { } /*static*/ -RenderView* RenderView::FromWebView(WebKit::WebView* webview) { +RenderView* RenderView::FromWebView(blink::WebView* webview) { return RenderViewImpl::FromWebView(webview); } @@ -1049,12 +1097,12 @@ RenderViewImpl* RenderViewImpl::Create( int32 main_frame_routing_id, int32 surface_id, int64 session_storage_namespace_id, - const string16& frame_name, + const base::string16& frame_name, bool is_renderer_created, bool swapped_out, bool hidden, int32 next_page_id, - const WebKit::WebScreenInfo& screen_info, + const blink::WebScreenInfo& screen_info, AccessibilityMode accessibility_mode, bool allow_partial_swap) { DCHECK(routing_id != MSG_ROUTING_NONE); @@ -1099,120 +1147,11 @@ void RenderViewImpl::RemoveObserver(RenderViewObserver* observer) { observers_.RemoveObserver(observer); } -WebKit::WebView* RenderViewImpl::webview() const { - return static_cast<WebKit::WebView*>(webwidget()); +blink::WebView* RenderViewImpl::webview() const { + return static_cast<blink::WebView*>(webwidget()); } #if defined(ENABLE_PLUGINS) -void RenderViewImpl::PepperInstanceCreated(PepperPluginInstanceImpl* instance) { - active_pepper_instances_.insert(instance); -} - -void RenderViewImpl::PepperInstanceDeleted(PepperPluginInstanceImpl* instance) { - active_pepper_instances_.erase(instance); - - if (pepper_last_mouse_event_target_ == instance) - pepper_last_mouse_event_target_ = NULL; - if (focused_pepper_plugin_ == instance) - PepperFocusChanged(instance, false); -} - -void RenderViewImpl::PepperDidChangeCursor( - PepperPluginInstanceImpl* instance, - const WebKit::WebCursorInfo& cursor) { - // Update the cursor appearance immediately if the requesting plugin is the - // one which receives the last mouse event. Otherwise, the new cursor won't be - // picked up until the plugin gets the next input event. That is bad if, e.g., - // the plugin would like to set an invisible cursor when there isn't any user - // input for a while. - if (instance == pepper_last_mouse_event_target_) - didChangeCursor(cursor); -} - -void RenderViewImpl::PepperDidReceiveMouseEvent( - PepperPluginInstanceImpl* instance) { - pepper_last_mouse_event_target_ = instance; -} - -void RenderViewImpl::PepperFocusChanged(PepperPluginInstanceImpl* instance, - bool focused) { - if (focused) - focused_pepper_plugin_ = instance; - else if (focused_pepper_plugin_ == instance) - focused_pepper_plugin_ = NULL; - - UpdateTextInputType(); - UpdateSelectionBounds(); -} - -void RenderViewImpl::PepperTextInputTypeChanged( - PepperPluginInstanceImpl* instance) { - if (instance != focused_pepper_plugin_) - return; - - UpdateTextInputType(); - if (renderer_accessibility_) - renderer_accessibility_->FocusedNodeChanged(WebNode()); -} - -void RenderViewImpl::PepperCaretPositionChanged( - PepperPluginInstanceImpl* instance) { - if (instance != focused_pepper_plugin_) - return; - UpdateSelectionBounds(); -} - -void RenderViewImpl::PepperCancelComposition( - PepperPluginInstanceImpl* instance) { - if (instance != focused_pepper_plugin_) - return; - Send(new ViewHostMsg_ImeCancelComposition(routing_id()));; -#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA) - UpdateCompositionInfo(true); -#endif -} - -void RenderViewImpl::PepperSelectionChanged( - PepperPluginInstanceImpl* instance) { - if (instance != focused_pepper_plugin_) - return; - SyncSelectionIfRequired(); -} - -RenderWidgetFullscreenPepper* RenderViewImpl::CreatePepperFullscreenContainer( - PepperPluginInstanceImpl* plugin) { - GURL active_url; - if (webview() && webview()->mainFrame()) - active_url = GURL(webview()->mainFrame()->document().url()); - RenderWidgetFullscreenPepper* widget = RenderWidgetFullscreenPepper::Create( - routing_id_, plugin, active_url, screen_info_); - widget->show(WebKit::WebNavigationPolicyIgnore); - return widget; -} - -void RenderViewImpl::PepperPluginCreated(RendererPpapiHost* host) { - FOR_EACH_OBSERVER(RenderViewObserver, observers_, - DidCreatePepperPlugin(host)); -} - -bool RenderViewImpl::GetPepperCaretBounds(gfx::Rect* rect) { - if (!focused_pepper_plugin_) - return false; - *rect = focused_pepper_plugin_->GetCaretBounds(); - return true; -} - -bool RenderViewImpl::IsPepperAcceptingCompositionEvents() const { - if (!focused_pepper_plugin_) - return false; - return focused_pepper_plugin_->IsPluginAcceptingCompositionEvents(); -} - -void RenderViewImpl::PluginCrashed(const base::FilePath& plugin_path, - base::ProcessId plugin_pid) { - Send(new ViewHostMsg_CrashedPlugin(routing_id_, plugin_path, plugin_pid)); -} - void RenderViewImpl::RegisterPluginDelegate(WebPluginDelegateProxy* delegate) { plugin_delegates_.insert(delegate); // If the renderer is visible, set initial visibility and focus state. @@ -1234,32 +1173,6 @@ void RenderViewImpl::UnregisterPluginDelegate( plugin_delegates_.erase(delegate); } -bool RenderViewImpl::GetPluginInfo(const GURL& url, - const GURL& page_url, - const std::string& mime_type, - WebPluginInfo* plugin_info, - std::string* actual_mime_type) { - bool found = false; - Send(new ViewHostMsg_GetPluginInfo( - routing_id_, url, page_url, mime_type, &found, plugin_info, - actual_mime_type)); - return found; -} - -void RenderViewImpl::SimulateImeSetComposition( - const string16& text, - const std::vector<WebKit::WebCompositionUnderline>& underlines, - int selection_start, - int selection_end) { - OnImeSetComposition(text, underlines, selection_start, selection_end); -} - -void RenderViewImpl::SimulateImeConfirmComposition( - const string16& text, - const gfx::Range& replacement_range) { - OnImeConfirmComposition(text, replacement_range, false); -} - #if defined(OS_WIN) void RenderViewImpl::PluginFocusChanged(bool focused, int plugin_id) { if (focused) @@ -1286,7 +1199,7 @@ void RenderViewImpl::StartPluginIme() { #endif // ENABLE_PLUGINS void RenderViewImpl::TransferActiveWheelFlingAnimation( - const WebKit::WebActiveWheelFlingParameters& params) { + const blink::WebActiveWheelFlingParameters& params) { if (webview()) webview()->transferActiveWheelFlingAnimation(params); } @@ -1368,6 +1281,8 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) { OnEnumerateDirectoryResponse) IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse) IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnShouldClose) + IPC_MESSAGE_HANDLER(ViewMsg_SuppressDialogsUntilSwapOut, + OnSuppressDialogsUntilSwapOut) IPC_MESSAGE_HANDLER(ViewMsg_SwapOut, OnSwapOut) IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage) IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged) @@ -1399,11 +1314,12 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewMsg_SetHistoryLengthAndPrune, OnSetHistoryLengthAndPrune) IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode) -#if defined(OS_ANDROID) - IPC_MESSAGE_HANDLER(JavaBridgeMsg_Init, OnJavaBridgeInit) -#endif IPC_MESSAGE_HANDLER(ViewMsg_SetAccessibilityMode, OnSetAccessibilityMode) IPC_MESSAGE_HANDLER(ViewMsg_DisownOpener, OnDisownOpener) + IPC_MESSAGE_HANDLER(ViewMsg_ReleaseDisambiguationPopupDIB, + OnReleaseDisambiguationPopupDIB) + IPC_MESSAGE_HANDLER(ViewMsg_WindowSnapshotCompleted, + OnWindowSnapshotCompleted) #if defined(OS_ANDROID) IPC_MESSAGE_HANDLER(InputMsg_ActivateNearestFindResult, OnActivateNearestFindResult) @@ -1414,6 +1330,7 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewMsg_UpdateTopControlsState, OnUpdateTopControlsState) IPC_MESSAGE_HANDLER(ViewMsg_PauseVideo, OnPauseVideo) + IPC_MESSAGE_HANDLER(ViewMsg_ExtractSmartClipData, OnExtractSmartClipData) #elif defined(OS_MACOSX) IPC_MESSAGE_HANDLER(InputMsg_CopyToFindPboard, OnCopyToFindPboard) IPC_MESSAGE_HANDLER(ViewMsg_PluginImeCompositionCompleted, @@ -1423,10 +1340,8 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewMsg_SetWindowVisibility, OnSetWindowVisibility) IPC_MESSAGE_HANDLER(ViewMsg_WindowFrameChanged, OnWindowFrameChanged) #endif - IPC_MESSAGE_HANDLER(ViewMsg_ReleaseDisambiguationPopupDIB, - OnReleaseDisambiguationPopupDIB) - IPC_MESSAGE_HANDLER(ViewMsg_WindowSnapshotCompleted, - OnWindowSnapshotCompleted) + // Adding a new message? Add platform independent ones first, then put the + // platform specific ones at the end. // Have the super handle all other messages. IPC_MESSAGE_UNHANDLED(handled = RenderWidget::OnMessageReceived(message)) @@ -1581,10 +1496,13 @@ void RenderViewImpl::OnNavigate(const ViewMsg_Navigate_Params& params) { // Set post data. WebHTTPBody http_body; http_body.initialize(); - http_body.appendData(WebData( - reinterpret_cast<const char*>( - ¶ms.browser_initiated_post_data.front()), - params.browser_initiated_post_data.size())); + const char* data = NULL; + if (params.browser_initiated_post_data.size()) { + data = reinterpret_cast<const char*>( + ¶ms.browser_initiated_post_data.front()); + } + http_body.appendData( + WebData(data, params.browser_initiated_post_data.size())); request.setHTTPBody(http_body); } @@ -1652,7 +1570,7 @@ void RenderViewImpl::OnStop() { if (webview()) { WebFrame* main_frame = webview()->mainFrame(); // Stop the alt error page fetcher. If we let it continue it may complete - // and cause RenderViewHostManager to swap to this RenderView, even though + // and cause RenderFrameHostManager to swap to this RenderView, even though // it may no longer be active. StopAltErrorPageFetcher(main_frame->provisionalDataSource()); StopAltErrorPageFetcher(main_frame->dataSource()); @@ -1728,7 +1646,7 @@ void RenderViewImpl::OnMoveCaret(const gfx::Point& point) { Send(new ViewHostMsg_MoveCaret_ACK(routing_id_)); - webview()->focusedFrame()->moveCaretSelectionTowardsWindowPoint(point); + webview()->focusedFrame()->moveCaretSelection(point); } void RenderViewImpl::OnPaste() { @@ -1757,7 +1675,7 @@ void RenderViewImpl::OnRedo() { GetFocusedNode()); } -void RenderViewImpl::OnReplace(const string16& text) { +void RenderViewImpl::OnReplace(const base::string16& text) { if (!webview()) return; @@ -1768,7 +1686,7 @@ void RenderViewImpl::OnReplace(const string16& text) { frame->replaceSelection(text); } -void RenderViewImpl::OnReplaceMisspelling(const string16& text) { +void RenderViewImpl::OnReplaceMisspelling(const base::string16& text) { if (!webview()) return; @@ -1781,7 +1699,7 @@ void RenderViewImpl::OnReplaceMisspelling(const string16& text) { void RenderViewImpl::OnScrollFocusedEditableNodeIntoRect( const gfx::Rect& rect) { - WebKit::WebNode node = GetFocusedNode(); + blink::WebNode node = GetFocusedNode(); if (!node.isNull()) { if (IsEditableNode(node)) { webview()->saveScrollAndScaleState(); @@ -1841,7 +1759,7 @@ void RenderViewImpl::OnCopyToFindPboard() { // than the |OnCopy()| case. WebFrame* frame = webview()->focusedFrame(); if (frame->hasSelection()) { - string16 selection = frame->selectionAsText(); + base::string16 selection = frame->selectionAsText(); RenderThread::Get()->Send( new ClipboardHostMsg_FindPboardWriteStringAsync(selection)); } @@ -1865,7 +1783,7 @@ void RenderViewImpl::OnSetEditableSelectionOffsets(int start, int end) { void RenderViewImpl::OnSetCompositionFromExistingText( int start, int end, - const std::vector<WebKit::WebCompositionUnderline>& underlines) { + const std::vector<blink::WebCompositionUnderline>& underlines) { if (!ShouldHandleImeEvent()) return; ImeEventGuard guard(this); @@ -1955,6 +1873,7 @@ void RenderViewImpl::UpdateURL(WebFrame* frame) { params.post_id = -1; params.page_id = page_id_; params.frame_id = frame->identifier(); + params.frame_unique_name = frame->uniqueName(); params.socket_address.set_host(response.remoteIPAddress().utf8()); params.socket_address.set_port(response.remotePort()); WebURLResponseExtraDataImpl* extra_data = GetExtraDataFromResponse(response); @@ -2050,7 +1969,7 @@ void RenderViewImpl::UpdateURL(WebFrame* frame) { params.referrer = GetReferrerFromRequest(frame, original_request); } - string16 method = request.httpMethod(); + base::string16 method = request.httpMethod(); if (EqualsASCII(method, "POST")) { params.is_post = true; params.post_id = ExtractPostId(item); @@ -2059,8 +1978,13 @@ void RenderViewImpl::UpdateURL(WebFrame* frame) { // Send the user agent override back. params.is_overriding_user_agent = internal_data->is_overriding_user_agent(); - // Track the URL of the original request. - params.original_request_url = original_request.url(); + // Track the URL of the original request. We use the first entry of the + // redirect chain if it exists because the chain may have started in another + // process. + if (params.redirects.size() > 0) + params.original_request_url = params.redirects.at(0); + else + params.original_request_url = original_request.url(); params.history_list_was_cleared = navigation_state->history_list_was_cleared(); @@ -2068,7 +1992,7 @@ void RenderViewImpl::UpdateURL(WebFrame* frame) { // Save some histogram data so we can compute the average memory used per // page load of the glyphs. UMA_HISTOGRAM_COUNTS_10000("Memory.GlyphPagesPerLoad", - WebKit::WebGlyphCache::pageCount()); + blink::WebGlyphCache::pageCount()); // This message needs to be sent before any of allowScripts(), // allowImages(), allowPlugins() is called for the new page, so that when @@ -2102,7 +2026,7 @@ void RenderViewImpl::UpdateURL(WebFrame* frame) { // Tell the embedding application that the title of the active page has changed void RenderViewImpl::UpdateTitle(WebFrame* frame, - const string16& title, + const base::string16& title, WebTextDirection title_direction) { // Ignore all but top level navigations. if (frame->parent()) @@ -2111,7 +2035,7 @@ void RenderViewImpl::UpdateTitle(WebFrame* frame, base::debug::TraceLog::GetInstance()->UpdateProcessLabel( routing_id_, UTF16ToUTF8(title)); - string16 shortened_title = title.substr(0, kMaxTitleChars); + base::string16 shortened_title = title.substr(0, kMaxTitleChars); Send(new ViewHostMsg_UpdateTitle(routing_id_, page_id_, shortened_title, title_direction)); } @@ -2166,7 +2090,19 @@ void RenderViewImpl::OpenURL(WebFrame* frame, params.frame_id = frame->identifier(); WebDataSource* ds = frame->provisionalDataSource(); if (ds) { - params.should_replace_current_entry = ds->replacesCurrentHistoryItem(); + DocumentState* document_state = DocumentState::FromDataSource(ds); + NavigationState* navigation_state = document_state->navigation_state(); + if (navigation_state->is_content_initiated()) { + params.should_replace_current_entry = ds->replacesCurrentHistoryItem(); + } else { + // This is necessary to preserve the should_replace_current_entry value on + // cross-process redirects, in the event it was set by a previous process. + // + // TODO(davidben): Avoid this awkward duplication of state. See comment on + // NavigationState::should_replace_current_entry(). + params.should_replace_current_entry = + navigation_state->should_replace_current_entry(); + } } else { params.should_replace_current_entry = false; } @@ -2174,10 +2110,10 @@ void RenderViewImpl::OpenURL(WebFrame* frame, if (GetContentClient()->renderer()->AllowPopup()) params.user_gesture = true; - if (policy == WebKit::WebNavigationPolicyNewBackgroundTab || - policy == WebKit::WebNavigationPolicyNewForegroundTab || - policy == WebKit::WebNavigationPolicyNewWindow || - policy == WebKit::WebNavigationPolicyNewPopup) { + if (policy == blink::WebNavigationPolicyNewBackgroundTab || + policy == blink::WebNavigationPolicyNewForegroundTab || + policy == blink::WebNavigationPolicyNewWindow || + policy == blink::WebNavigationPolicyNewPopup) { WebUserGestureIndicator::consumeUserGesture(); } @@ -2199,7 +2135,8 @@ void RenderViewImpl::LoadNavigationErrorPage( error_html = &html; } else { GetContentClient()->renderer()->GetNavigationErrorStrings( - frame, failed_request, error, &alt_html, NULL); + frame, failed_request, error, renderer_preferences_.accept_languages, + &alt_html, NULL); error_html = &alt_html; } @@ -2210,12 +2147,17 @@ void RenderViewImpl::LoadNavigationErrorPage( } bool RenderViewImpl::RunJavaScriptMessage(JavaScriptMessageType type, - const string16& message, - const string16& default_value, + const base::string16& message, + const base::string16& default_value, const GURL& frame_url, - string16* result) { + base::string16* result) { + // Don't allow further dialogs if we are waiting to swap out, since the + // PageGroupLoadDeferrer in our stack prevents it. + if (suppress_dialogs_until_swap_out_) + return false; + bool success = false; - string16 result_temp; + base::string16 result_temp; if (!result) result = &result_temp; @@ -2239,25 +2181,45 @@ bool RenderViewImpl::SendAndRunNestedMessageLoop(IPC::SyncMessage* message) { void RenderViewImpl::GetWindowSnapshot(const WindowSnapshotCallback& callback) { int id = next_snapshot_id_++; pending_snapshots_.insert(std::make_pair(id, callback)); - Send(new ViewHostMsg_GetWindowSnapshot(routing_id_, id)); + ui::LatencyInfo latency_info; + latency_info.AddLatencyNumber(ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT, + GetLatencyComponentId(), + id); + scoped_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor; + if (RenderWidgetCompositor* rwc = compositor()) { + latency_info_swap_promise_monitor = + rwc->CreateLatencyInfoSwapPromiseMonitor(&latency_info).Pass(); + } else { + latency_info_.MergeWith(latency_info); + } + ScheduleCompositeWithForcedRedraw(); } void RenderViewImpl::OnWindowSnapshotCompleted(const int snapshot_id, const gfx::Size& size, const std::vector<unsigned char>& png) { - PendingSnapshotMap::iterator it = pending_snapshots_.find(snapshot_id); - DCHECK(it != pending_snapshots_.end()); - it->second.Run(size, png); - pending_snapshots_.erase(it); + + // Any pending snapshots with a lower ID than the one received are considered + // to be implicitly complete, and returned the same snapshot data. + PendingSnapshotMap::iterator it = pending_snapshots_.begin(); + while(it != pending_snapshots_.end()) { + if (it->first <= snapshot_id) { + it->second.Run(size, png); + pending_snapshots_.erase(it++); + } else { + ++it; + } + } } -// WebKit::WebViewClient ------------------------------------------------------ +// blink::WebViewClient ------------------------------------------------------ WebView* RenderViewImpl::createView( WebFrame* creator, const WebURLRequest& request, const WebWindowFeatures& features, const WebString& frame_name, - WebNavigationPolicy policy) { + WebNavigationPolicy policy, + bool suppress_opener) { ViewHostMsg_CreateWindow_Params params; params.opener_id = routing_id_; params.user_gesture = WebUserGestureIndicator::isProcessingUserGesture(); @@ -2274,7 +2236,7 @@ WebView* RenderViewImpl::createView( if (!security_url.is_valid()) security_url = GURL(); params.opener_security_origin = security_url; - params.opener_suppressed = creator->willSuppressOpenerInNewFrame(); + params.opener_suppressed = suppress_opener; params.disposition = NavigationPolicyToDisposition(policy); if (!request.isNull()) { params.target_url = request.url(); @@ -2282,6 +2244,9 @@ WebView* RenderViewImpl::createView( } params.features = features; + for (size_t i = 0; i < features.additionalFeatures.size(); ++i) + params.additional_features.push_back(features.additionalFeatures[i]); + int32 routing_id = MSG_ROUTING_NONE; int32 main_frame_routing_id = MSG_ROUTING_NONE; int32 surface_id = 0; @@ -2325,7 +2290,7 @@ WebView* RenderViewImpl::createView( main_frame_routing_id, surface_id, cloned_session_storage_namespace_id, - string16(), // WebCore will take care of setting the correct name. + base::string16(), // WebCore will take care of setting the correct name. true, // is_renderer_created false, // swapped_out params.disposition == NEW_BACKGROUND_TAB, // hidden @@ -2345,9 +2310,13 @@ WebView* RenderViewImpl::createView( return view->webview(); } -WebWidget* RenderViewImpl::createPopupMenu(WebKit::WebPopupType popup_type) { +WebWidget* RenderViewImpl::createPopupMenu(blink::WebPopupType popup_type) { RenderWidget* widget = RenderWidget::Create(routing_id_, popup_type, screen_info_); + if (screen_metrics_emulator_) { + widget->SetPopupOriginAdjustmentsForEmulation( + screen_metrics_emulator_.get()); + } return widget->webwidget(); } @@ -2364,6 +2333,10 @@ WebExternalPopupMenu* RenderViewImpl::createExternalPopupMenu( return NULL; external_popup_menu_.reset( new ExternalPopupMenu(this, popup_menu_info, popup_menu_client)); + if (screen_metrics_emulator_) { + SetExternalPopupOriginAdjustmentsForEmulation( + external_popup_menu_.get(), screen_metrics_emulator_.get()); + } return external_popup_menu_.get(); } @@ -2387,6 +2360,7 @@ void RenderViewImpl::didAddMessageToConsole( log_severity = logging::LOG_VERBOSE; break; case WebConsoleMessage::LevelLog: + case WebConsoleMessage::LevelInfo: log_severity = logging::LOG_INFO; break; case WebConsoleMessage::LevelWarning: @@ -2422,7 +2396,7 @@ void RenderViewImpl::printPage(WebFrame* frame) { PrintPage(frame, handling_input_event_)); } -WebKit::WebNotificationPresenter* RenderViewImpl::notificationPresenter() { +blink::WebNotificationPresenter* RenderViewImpl::notificationPresenter() { return notification_provider_; } @@ -2438,7 +2412,7 @@ bool RenderViewImpl::enumerateChosenDirectory( } void RenderViewImpl::initializeHelperPluginWebFrame( - WebKit::WebHelperPlugin* plugin) { + blink::WebHelperPlugin* plugin) { plugin->initializeFrame(main_render_frame_.get()); } @@ -2495,8 +2469,13 @@ void RenderViewImpl::didChangeSelection(bool is_empty_selection) { if (is_empty_selection) selection_text_.clear(); - SyncSelectionIfRequired(); + // UpdateTextInputType should be called before SyncSelectionIfRequired. + // UpdateTextInputType may send TextInputTypeChanged to notify the focus + // was changed, and SyncSelectionIfRequired may send SelectionChanged + // to notify the selection was changed. Focus change should be notified + // before selection change. UpdateTextInputType(); + SyncSelectionIfRequired(); #if defined(OS_ANDROID) UpdateTextInputState(false, true); #endif @@ -2508,7 +2487,7 @@ void RenderViewImpl::didExecuteCommand(const WebString& command_name) { StartsWithASCII(name, "Insert", true) || StartsWithASCII(name, "Delete", true)) return; - RenderThreadImpl::current()->RecordUserMetrics(name); + RenderThreadImpl::current()->RecordComputedAction(name); } bool RenderViewImpl::handleCurrentKeyboardEvent() { @@ -2537,17 +2516,22 @@ bool RenderViewImpl::handleCurrentKeyboardEvent() { return did_execute_command; } -WebKit::WebColorChooser* RenderViewImpl::createColorChooser( - WebKit::WebColorChooserClient* client, - const WebKit::WebColor& initial_color) { +blink::WebColorChooser* RenderViewImpl::createColorChooser( + blink::WebColorChooserClient* client, + const blink::WebColor& initial_color, + const blink::WebVector<blink::WebColorSuggestion>& suggestions) { RendererWebColorChooserImpl* color_chooser = new RendererWebColorChooserImpl(this, client); - color_chooser->Open(static_cast<SkColor>(initial_color)); + std::vector<content::ColorSuggestion> color_suggestions; + for (size_t i = 0; i < suggestions.size(); i++) { + color_suggestions.push_back(content::ColorSuggestion(suggestions[i])); + } + color_chooser->Open(static_cast<SkColor>(initial_color), color_suggestions); return color_chooser; } bool RenderViewImpl::runFileChooser( - const WebKit::WebFileChooserParams& params, + const blink::WebFileChooserParams& params, WebFileChooserCompletion* chooser_completion) { // Do not open the file dialog in a hidden RenderView. if (is_hidden()) @@ -2578,7 +2562,7 @@ void RenderViewImpl::runModalAlertDialog(WebFrame* frame, const WebString& message) { RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_ALERT, message, - string16(), + base::string16(), frame->document().url(), NULL); } @@ -2587,7 +2571,7 @@ bool RenderViewImpl::runModalConfirmDialog(WebFrame* frame, const WebString& message) { return RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_CONFIRM, message, - string16(), + base::string16(), frame->document().url(), NULL); } @@ -2596,7 +2580,7 @@ bool RenderViewImpl::runModalPromptDialog(WebFrame* frame, const WebString& message, const WebString& default_value, WebString* actual_value) { - string16 result; + base::string16 result; bool ok = RunJavaScriptMessage(JAVASCRIPT_MESSAGE_TYPE_PROMPT, message, default_value, @@ -2612,7 +2596,7 @@ bool RenderViewImpl::runModalBeforeUnloadDialog( bool is_reload = false; WebDataSource* ds = frame->provisionalDataSource(); if (ds) - is_reload = (ds->navigationType() == WebKit::WebNavigationTypeReload); + is_reload = (ds->navigationType() == blink::WebNavigationTypeReload); return runModalBeforeUnloadDialog(frame, is_reload, message); } @@ -2624,16 +2608,56 @@ bool RenderViewImpl::runModalBeforeUnloadDialog( if (is_swapped_out_) return true; + // Don't allow further dialogs if we are waiting to swap out, since the + // PageGroupLoadDeferrer in our stack prevents it. + if (suppress_dialogs_until_swap_out_) + return false; + bool success = false; // This is an ignored return value, but is included so we can accept the same // response as RunJavaScriptMessage. - string16 ignored_result; + base::string16 ignored_result; SendAndRunNestedMessageLoop(new ViewHostMsg_RunBeforeUnloadConfirm( routing_id_, frame->document().url(), message, is_reload, &success, &ignored_result)); return success; } +void RenderViewImpl::showValidationMessage( + const blink::WebRect& anchor_in_root_view, + const blink::WebString& main_text, + const blink::WebString& sub_text, + blink::WebTextDirection hint) { + base::string16 wrapped_main_text = main_text; + base::string16 wrapped_sub_text = sub_text; + if (hint == blink::WebTextDirectionLeftToRight) { + wrapped_main_text = + base::i18n::GetDisplayStringInLTRDirectionality(wrapped_main_text); + if (!wrapped_sub_text.empty()) { + wrapped_sub_text = + base::i18n::GetDisplayStringInLTRDirectionality(wrapped_sub_text); + } + } else if (hint == blink::WebTextDirectionRightToLeft + && !base::i18n::IsRTL()) { + base::i18n::WrapStringWithRTLFormatting(&wrapped_main_text); + if (!wrapped_sub_text.empty()) { + base::i18n::WrapStringWithRTLFormatting(&wrapped_sub_text); + } + } + Send(new ViewHostMsg_ShowValidationMessage( + routing_id(), anchor_in_root_view, wrapped_main_text, wrapped_sub_text)); +} + +void RenderViewImpl::hideValidationMessage() { + Send(new ViewHostMsg_HideValidationMessage(routing_id())); +} + +void RenderViewImpl::moveValidationMessage( + const blink::WebRect& anchor_in_root_view) { + Send(new ViewHostMsg_MoveValidationMessage(routing_id(), + anchor_in_root_view)); +} + void RenderViewImpl::showContextMenu( WebFrame* frame, const WebContextMenuData& data) { ContextMenuParams params = ContextMenuParamsBuilder::Build(data); @@ -2642,6 +2666,7 @@ void RenderViewImpl::showContextMenu( params.x = touch_editing_context_menu_location_.x(); params.y = touch_editing_context_menu_location_.y(); } + OnShowHostContextMenu(¶ms); // Plugins, e.g. PDF, don't currently update the render view when their // selected text changes, but the context menu params do contain the updated @@ -2671,7 +2696,7 @@ void RenderViewImpl::showContextMenu( // in the context menu. // TODO(jcivelli): http://crbug.com/45160 This prevents us from saving large // data encoded images. We should have a way to save them. - if (params.src_url.spec().size() > kMaxURLChars) + if (params.src_url.spec().size() > GetMaxURLChars()) params.src_url = GURL(); context_menu_node_ = data.node; @@ -2711,9 +2736,9 @@ void RenderViewImpl::UpdateTargetURL(const GURL& url, pending_target_url_ = latest_url; target_url_status_ = TARGET_PENDING; } else { - // URLs larger than |kMaxURLChars| cannot be sent through IPC - + // URLs larger than |MaxURLChars()| cannot be sent through IPC - // see |ParamTraits<GURL>|. - if (latest_url.possibly_invalid_spec().size() > kMaxURLChars) + if (latest_url.possibly_invalid_spec().size() > GetMaxURLChars()) latest_url = GURL(); Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_, latest_url)); target_url_ = latest_url; @@ -2728,6 +2753,12 @@ gfx::RectF RenderViewImpl::ClientRectToPhysicalWindowRect( return window_rect; } +int64 RenderViewImpl::GetLatencyComponentId() { + // Note: this must match the logic in RenderWidgetHostImpl. + return GetRoutingID() | (static_cast<int64>( + RenderThreadImpl::current()->renderer_process_id()) << 32); +} + void RenderViewImpl::StartNavStateSyncTimerIfNecessary() { // No need to update state if no page has committed yet. if (page_id_ == -1) @@ -2831,7 +2862,7 @@ int RenderViewImpl::historyForwardListCount() { } void RenderViewImpl::postAccessibilityEvent( - const WebAXObject& obj, WebKit::WebAXEvent event) { + const WebAXObject& obj, blink::WebAXEvent event) { if (renderer_accessibility_) { renderer_accessibility_->HandleWebAccessibilityEvent(obj, event); } @@ -2844,7 +2875,7 @@ void RenderViewImpl::didUpdateInspectorSetting(const WebString& key, value.utf8())); } -// WebKit::WebWidgetClient ---------------------------------------------------- +// blink::WebWidgetClient ---------------------------------------------------- void RenderViewImpl::didFocus() { // TODO(jcivelli): when https://bugs.webkit.org/show_bug.cgi?id=33389 is fixed @@ -2888,8 +2919,8 @@ void RenderViewImpl::show(WebNavigationPolicy policy) { // We exempt background tabs for compat with older versions of Chrome. // TODO(darin): This seems bogus. These should have a user gesture, so // we probably don't need this check. - if (policy != WebKit::WebNavigationPolicyNewBackgroundTab) - policy = WebKit::WebNavigationPolicyNewPopup; + if (policy != blink::WebNavigationPolicyNewBackgroundTab) + policy = blink::WebNavigationPolicyNewPopup; } // NOTE: initial_pos_ may still have its default values at this point, but @@ -2904,6 +2935,11 @@ void RenderViewImpl::show(WebNavigationPolicy policy) { void RenderViewImpl::runModal() { DCHECK(did_show_) << "should already have shown the view"; + // Don't allow further dialogs if we are waiting to swap out, since the + // PageGroupLoadDeferrer in our stack prevents it. + if (suppress_dialogs_until_swap_out_) + return; + // We must keep WebKit's shared timer running in this case in order to allow // showModalDialog to function properly. // @@ -2959,8 +2995,15 @@ void RenderViewImpl::didHandleGestureEvent( const WebGestureEvent& event, bool event_cancelled) { RenderWidget::didHandleGestureEvent(event, event_cancelled); - FOR_EACH_OBSERVER(RenderViewObserver, observers_, - DidHandleGestureEvent(event)); + + if (event.type != blink::WebGestureEvent::GestureTap) + return; + + blink::WebTextInputType text_input_type = + GetWebView()->textInputInfo().type; + + Send(new ViewHostMsg_FocusedNodeTouched( + routing_id(), text_input_type != blink::WebTextInputTypeNone)); } void RenderViewImpl::initializeLayerTreeView() { @@ -2971,112 +3014,47 @@ void RenderViewImpl::initializeLayerTreeView() { webview()->devToolsAgent()->setLayerTreeId(rwc->GetLayerTreeId()); } -// WebKit::WebFrameClient ----------------------------------------------------- +// blink::WebFrameClient ----------------------------------------------------- WebMediaPlayer* RenderViewImpl::createMediaPlayer( - WebFrame* frame, const WebKit::WebURL& url, WebMediaPlayerClient* client) { + WebFrame* frame, const blink::WebURL& url, WebMediaPlayerClient* client) { + NOTREACHED(); + return NULL; +} + +blink::WebMediaPlayer* RenderViewImpl::CreateMediaPlayer( + RenderFrame* render_frame, + blink::WebFrame* frame, + const blink::WebURL& url, + blink::WebMediaPlayerClient* client) { FOR_EACH_OBSERVER( RenderViewObserver, observers_, WillCreateMediaPlayer(frame, client)); - const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); -#if defined(ENABLE_WEBRTC) - if (!InitializeMediaStreamClient()) - return NULL; - -#if !defined(GOOGLE_TV) - if (media_stream_client_->IsMediaStream(url)) { -#if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL) - bool found_neon = - (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0; - UMA_HISTOGRAM_BOOLEAN("Platform.WebRtcNEONFound", found_neon); -#endif // defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL) - return new WebMediaPlayerMS( - frame, client, AsWeakPtr(), media_stream_client_, new RenderMediaLog()); - } -#endif // !defined(GOOGLE_TV) -#endif // defined(ENABLE_WEBRTC) + WebMediaPlayer* player = CreateWebMediaPlayerForMediaStream(frame, url, + client); + if (player) + return player; #if defined(OS_ANDROID) - GpuChannelHost* gpu_channel_host = - RenderThreadImpl::current()->EstablishGpuChannelSync( - CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE); - if (!gpu_channel_host) { - LOG(ERROR) << "Failed to establish GPU channel for media player"; - return NULL; - } - - scoped_refptr<cc::ContextProvider> context_provider = - RenderThreadImpl::current()->OffscreenContextProviderForMainThread(); - scoped_ptr<StreamTextureFactory> stream_texture_factory; - if (UsingSynchronousRendererCompositor()) { - SynchronousCompositorFactory* factory = - SynchronousCompositorFactory::GetInstance(); - stream_texture_factory = factory->CreateStreamTextureFactory(routing_id_); - } else { - if (!context_provider.get()) { - LOG(ERROR) << "Failed to get context3d for media player"; - return NULL; - } - - stream_texture_factory.reset(new StreamTextureFactoryImpl( - context_provider->Context3d(), gpu_channel_host, routing_id_)); - } - - if (!media_player_proxy_) { - media_player_proxy_ = new WebMediaPlayerProxyAndroid( - this, media_player_manager_.get()); - } - - scoped_ptr<WebMediaPlayerAndroid> web_media_player_android( - new WebMediaPlayerAndroid( - frame, - client, - AsWeakPtr(), - media_player_manager_.get(), - media_player_proxy_, - stream_texture_factory.release(), - RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy(), - new RenderMediaLog())); -#if defined(ENABLE_WEBRTC) && defined(GOOGLE_TV) - if (media_stream_client_->IsMediaStream(url)) { - RTCVideoDecoderFactoryTv* factory = RenderThreadImpl::current() - ->GetMediaStreamDependencyFactory()->decoder_factory_tv(); - // |media_stream_client| and |factory| outlives |web_media_player_android|. - if (!factory->AcquireDemuxer() || - !web_media_player_android->InjectMediaStream( - media_stream_client_, - factory, - base::Bind( - base::IgnoreResult(&RTCVideoDecoderFactoryTv::ReleaseDemuxer), - base::Unretained(factory)))) { - LOG(ERROR) << "Failed to inject media stream."; - return NULL; - } - } -#endif // defined(ENABLE_WEBRTC) && defined(GOOGLE_TV) - return web_media_player_android.release(); -#endif // defined(OS_ANDROID) - + return CreateAndroidWebMediaPlayer(frame, url, client); +#else scoped_refptr<media::AudioRendererSink> sink; - if (!cmd_line->HasSwitch(switches::kDisableAudio)) { + if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableAudio)) { sink = RenderThreadImpl::current()->GetAudioRendererMixerManager()-> CreateInput(routing_id_); DVLOG(1) << "Using AudioRendererMixerManager-provided sink: " << sink.get(); } - scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories = - RenderThreadImpl::current()->GetGpuFactories( - RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy()); - WebMediaPlayerParams params( RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy(), base::Bind(&ContentRendererClient::DeferMediaLoad, base::Unretained(GetContentClient()->renderer()), - static_cast<RenderView*>(this)), + static_cast<RenderFrame*>(render_frame)), sink, - gpu_factories, + RenderThreadImpl::current()->GetGpuFactories(), new RenderMediaLog()); - return new WebMediaPlayerImpl(frame, client, AsWeakPtr(), params); + return new WebMediaPlayerImpl(this, frame, client, AsWeakPtr(), params); +#endif // defined(OS_ANDROID) } WebCookieJar* RenderViewImpl::cookieJar(WebFrame* frame) { @@ -3090,7 +3068,7 @@ void RenderViewImpl::didAccessInitialDocument(WebFrame* frame) { Send(new ViewHostMsg_DidAccessInitialDocument(routing_id_)); } -void RenderViewImpl::didDisownOpener(WebKit::WebFrame* frame) { +void RenderViewImpl::didDisownOpener(blink::WebFrame* frame) { // We only need to notify the browser if the active, top-level frame clears // its opener. We can ignore cases where a swapped out frame clears its // opener after hearing about it from the browser, and the browser does not @@ -3110,6 +3088,15 @@ void RenderViewImpl::willClose(WebFrame* frame) { FOR_EACH_OBSERVER(RenderViewObserver, observers_, FrameWillClose(frame)); } +void RenderViewImpl::didMatchCSS( + WebFrame* frame, + const WebVector<WebString>& newly_matching_selectors, + const WebVector<WebString>& stopped_matching_selectors) { + FOR_EACH_OBSERVER( + RenderViewObserver, observers_, + DidMatchCSS(frame, newly_matching_selectors, stopped_matching_selectors)); +} + void RenderViewImpl::Repaint(const gfx::Size& size) { OnRepaint(size); } @@ -3125,7 +3112,7 @@ void RenderViewImpl::ClearEditCommands() { edit_commands_.clear(); } -SSLStatus RenderViewImpl::GetSSLStatusOfFrame(WebKit::WebFrame* frame) const { +SSLStatus RenderViewImpl::GetSSLStatusOfFrame(blink::WebFrame* frame) const { std::string security_info; if (frame && frame->dataSource()) security_info = frame->dataSource()->response().securityInfo(); @@ -3135,20 +3122,35 @@ SSLStatus RenderViewImpl::GetSSLStatusOfFrame(WebKit::WebFrame* frame) const { &ssl_status.cert_id, &ssl_status.cert_status, &ssl_status.security_bits, - &ssl_status.connection_status); + &ssl_status.connection_status, + &ssl_status.signed_certificate_timestamp_ids); return ssl_status; } +const std::string& RenderViewImpl::GetAcceptLanguages() const { + return renderer_preferences_.accept_languages; +} + WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation( WebFrame* frame, WebDataSource::ExtraData* extraData, const WebURLRequest& request, WebNavigationType type, WebNavigationPolicy default_policy, bool is_redirect) { +#ifdef OS_ANDROID + // The handlenavigation API is deprecated and will be removed once + // crbug.com/325351 is resolved. if (request.url() != GURL(kSwappedOutURL) && - GetContentClient()->renderer()->HandleNavigation(frame, request, type, - default_policy, - is_redirect)) { - return WebKit::WebNavigationPolicyIgnore; + GetContentClient()->renderer()->HandleNavigation( + this, + static_cast<DocumentState*>(extraData), + opener_id_, + frame, + request, + type, + default_policy, + is_redirect)) { + return blink::WebNavigationPolicyIgnore; } +#endif Referrer referrer(GetReferrerFromRequest(frame, request)); @@ -3163,12 +3165,12 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation( // fixing http://crbug.com/101395. if (frame->parent() == NULL) { OpenURL(frame, request.url(), referrer, default_policy); - return WebKit::WebNavigationPolicyIgnore; // Suppress the load here. + return blink::WebNavigationPolicyIgnore; // Suppress the load here. } // We should otherwise ignore in-process iframe navigations, if they // arrive just after we are swapped out. - return WebKit::WebNavigationPolicyIgnore; + return blink::WebNavigationPolicyIgnore; } // Allow kSwappedOutURL to complete. @@ -3207,22 +3209,23 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation( net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES); if (!same_domain_or_host || frame_url.scheme() != url.scheme()) { OpenURL(frame, url, referrer, default_policy); - return WebKit::WebNavigationPolicyIgnore; + return blink::WebNavigationPolicyIgnore; } } // If the browser is interested, then give it a chance to look at the request. if (is_content_initiated) { - bool is_form_post = ((type == WebKit::WebNavigationTypeFormSubmitted) || - (type == WebKit::WebNavigationTypeFormResubmitted)) && + bool is_form_post = ((type == blink::WebNavigationTypeFormSubmitted) || + (type == blink::WebNavigationTypeFormResubmitted)) && EqualsASCII(request.httpMethod(), "POST"); bool browser_handles_request = renderer_preferences_.browser_handles_non_local_top_level_requests && IsNonLocalTopLevelNavigation(url, frame, type, is_form_post); if (!browser_handles_request) { - browser_handles_request = - renderer_preferences_.browser_handles_all_top_level_requests && - IsTopLevelNavigation(frame); + browser_handles_request = IsTopLevelNavigation(frame) && + (renderer_preferences_.browser_handles_all_top_level_requests || + (renderer_preferences_.browser_handles_all_top_level_link_clicks && + type == blink::WebNavigationTypeLinkClicked)); } if (browser_handles_request) { @@ -3231,7 +3234,7 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation( page_id_ = -1; last_page_id_sent_to_browser_ = -1; OpenURL(frame, url, referrer, default_policy); - return WebKit::WebNavigationPolicyIgnore; // Suppress the load here. + return blink::WebNavigationPolicyIgnore; // Suppress the load here. } } @@ -3273,7 +3276,7 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation( (cumulative_bindings & BINDINGS_POLICY_WEB_UI) || url.SchemeIs(kViewSourceScheme) || (frame->isViewSourceModeEnabled() && - type != WebKit::WebNavigationTypeReload); + type != blink::WebNavigationTypeReload); if (!should_fork && url.SchemeIs(chrome::kFileScheme)) { // Fork non-file to file opens. Check the opener URL if this is the @@ -3295,7 +3298,7 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation( if (should_fork) { OpenURL( frame, url, send_referrer ? referrer : Referrer(), default_policy); - return WebKit::WebNavigationPolicyIgnore; // Suppress the load here. + return blink::WebNavigationPolicyIgnore; // Suppress the load here. } } @@ -3327,14 +3330,14 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation( // Must not have issued the request from this page. is_content_initiated && // Must be targeted at the current tab. - default_policy == WebKit::WebNavigationPolicyCurrentTab && + default_policy == blink::WebNavigationPolicyCurrentTab && // Must be a JavaScript navigation, which appears as "other". - type == WebKit::WebNavigationTypeOther; + type == blink::WebNavigationTypeOther; if (is_fork) { // Open the URL via the browser, not via WebKit. OpenURL(frame, url, Referrer(), default_policy); - return WebKit::WebNavigationPolicyIgnore; + return blink::WebNavigationPolicyIgnore; } return default_policy; @@ -3348,8 +3351,8 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation( request, type, default_policy, is_redirect); } -void RenderViewImpl::willSendSubmitEvent(WebKit::WebFrame* frame, - const WebKit::WebFormElement& form) { +void RenderViewImpl::willSendSubmitEvent(blink::WebFrame* frame, + const blink::WebFormElement& form) { FOR_EACH_OBSERVER( RenderViewObserver, observers_, WillSendSubmitEvent(frame, form)); } @@ -3363,6 +3366,15 @@ void RenderViewImpl::willSubmitForm(WebFrame* frame, void RenderViewImpl::didCreateDataSource(WebFrame* frame, WebDataSource* ds) { bool content_initiated = !pending_navigation_params_.get(); + // Make sure any previous redirect URLs end up in our new data source. + if (pending_navigation_params_.get()) { + for (std::vector<GURL>::const_iterator i = + pending_navigation_params_->redirects.begin(); + i != pending_navigation_params_->redirects.end(); ++i) { + ds->appendRedirect(*i); + } + } + DocumentState* document_state = DocumentState::FromDataSource(ds); if (!document_state) { document_state = new DocumentState; @@ -3492,6 +3504,8 @@ NavigationState* RenderViewImpl::CreateNavigationStateFromPending() { params.pending_history_list_offset, params.should_clear_history_list, params.transition); + navigation_state->set_should_replace_current_entry( + params.should_replace_current_entry); navigation_state->set_transferred_request_child_id( params.transferred_request_child_id); navigation_state->set_transferred_request_request_id( @@ -3506,11 +3520,8 @@ NavigationState* RenderViewImpl::CreateNavigationStateFromPending() { void RenderViewImpl::ProcessViewLayoutFlags(const CommandLine& command_line) { bool enable_viewport = - command_line.HasSwitch(switches::kEnableViewport); - bool enable_fixed_layout = - command_line.HasSwitch(switches::kEnableFixedLayout); - - webview()->enableFixedLayoutMode(enable_fixed_layout || enable_viewport); + command_line.HasSwitch(switches::kEnableViewport) || + command_line.HasSwitch(switches::kEnableViewportMeta); // If viewport tag is enabled, then the WebKit side will take care // of setting the fixed layout size and page scale limits. @@ -3520,65 +3531,13 @@ void RenderViewImpl::ProcessViewLayoutFlags(const CommandLine& command_line) { // When navigating to a new page, reset the page scale factor to be 1.0. webview()->setInitialPageScaleOverride(1.f); - if (enable_fixed_layout) { - std::string str = - command_line.GetSwitchValueASCII(switches::kEnableFixedLayout); - std::vector<std::string> tokens; - base::SplitString(str, ',', &tokens); - if (tokens.size() == 2) { - int width, height; - if (base::StringToInt(tokens[0], &width) && - base::StringToInt(tokens[1], &height)) - webview()->setFixedLayoutSize(WebSize(width, height)); - } - } float maxPageScaleFactor = command_line.HasSwitch(switches::kEnablePinch) ? 4.f : 1.f ; webview()->setPageScaleFactorLimits(1, maxPageScaleFactor); } +// TODO(nasko): Remove this method once WebTestProxy in Blink is fixed. void RenderViewImpl::didStartProvisionalLoad(WebFrame* frame) { - WebDataSource* ds = frame->provisionalDataSource(); - - // In fast/loader/stop-provisional-loads.html, we abort the load before this - // callback is invoked. - if (!ds) - return; - - DocumentState* document_state = DocumentState::FromDataSource(ds); - - // We should only navigate to swappedout:// when is_swapped_out_ is true. - CHECK((ds->request().url() != GURL(kSwappedOutURL)) || - is_swapped_out_) << "Heard swappedout:// when not swapped out."; - - // Update the request time if WebKit has better knowledge of it. - if (document_state->request_time().is_null()) { - double event_time = ds->triggeringEventTime(); - if (event_time != 0.0) - document_state->set_request_time(Time::FromDoubleT(event_time)); - } - - // Start time is only set after request time. - document_state->set_start_load_time(Time::Now()); - - bool is_top_most = !frame->parent(); - if (is_top_most) { - navigation_gesture_ = WebUserGestureIndicator::isProcessingUserGesture() ? - NavigationGestureUser : NavigationGestureAuto; - } else if (frame->parent()->isLoading()) { - // Take note of AUTO_SUBFRAME loads here, so that we can know how to - // load an error page. See didFailProvisionalLoad. - document_state->navigation_state()->set_transition_type( - PAGE_TRANSITION_AUTO_SUBFRAME); - } - - FOR_EACH_OBSERVER( - RenderViewObserver, observers_, DidStartProvisionalLoad(frame)); - - Send(new ViewHostMsg_DidStartProvisionalLoadForFrame( - routing_id_, frame->identifier(), - frame->parent() ? frame->parent()->identifier() : -1, - is_top_most, ds->request().url())); } void RenderViewImpl::didReceiveServerRedirectForProvisionalLoad( @@ -3622,12 +3581,14 @@ void RenderViewImpl::didFailProvisionalLoad(WebFrame* frame, ViewHostMsg_DidFailProvisionalLoadWithError_Params params; params.frame_id = frame->identifier(); + params.frame_unique_name = frame->uniqueName(); params.is_main_frame = !frame->parent(); params.error_code = error.reason; GetContentClient()->renderer()->GetNavigationErrorStrings( frame, failed_request, error, + renderer_preferences_.accept_languages, NULL, ¶ms.error_description); params.url = error.unreachableURL; @@ -3671,6 +3632,8 @@ void RenderViewImpl::didFailProvisionalLoad(WebFrame* frame, // AUTO_SUBFRAME loads should always be treated as loads that do not advance // the page id. // + // TODO(davidben): This should also take the failed navigation's replacement + // state into account, if a location.replace() failed. bool replace = navigation_state->pending_page_id() != -1 || PageTransitionCoreTypeIs(navigation_state->transition_type(), @@ -3690,6 +3653,7 @@ void RenderViewImpl::didFailProvisionalLoad(WebFrame* frame, navigation_state->transition_type(); pending_navigation_params_->request_time = document_state->request_time(); + pending_navigation_params_->should_replace_current_entry = replace; } // Provide the user with a more helpful error page? @@ -3808,14 +3772,8 @@ void RenderViewImpl::didClearWindowObject(WebFrame* frame) { "domAutomationController"); } - if (enabled_bindings_ & BINDINGS_POLICY_STATS_COLLECTION) { - if (!stats_collection_controller_.get()) - stats_collection_controller_.reset(new StatsCollectionController()); - stats_collection_controller_->set_message_sender( - static_cast<RenderView*>(this)); - stats_collection_controller_->BindToJavascript(frame, - "statsCollectionController"); - } + if (enabled_bindings_ & BINDINGS_POLICY_STATS_COLLECTION) + StatsCollectionController::Install(frame); } void RenderViewImpl::didCreateDocumentElement(WebFrame* frame) { @@ -3877,11 +3835,12 @@ void RenderViewImpl::didFailLoad(WebFrame* frame, const WebURLError& error) { FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidFailLoad(frame, error)); const WebURLRequest& failed_request = ds->request(); - string16 error_description; + base::string16 error_description; GetContentClient()->renderer()->GetNavigationErrorStrings( frame, failed_request, error, + renderer_preferences_.accept_languages, NULL, &error_description); Send(new ViewHostMsg_DidFailLoadWithError(routing_id_, @@ -4134,7 +4093,7 @@ void RenderViewImpl::didChangeScrollOffset(WebFrame* frame) { RenderViewObserver, observers_, DidChangeScrollOffset(frame)); } -void RenderViewImpl::willInsertBody(WebKit::WebFrame* frame) { +void RenderViewImpl::willInsertBody(blink::WebFrame* frame) { NOTREACHED(); } @@ -4178,11 +4137,11 @@ void RenderViewImpl::SendFindReply(int request_id, // static bool RenderViewImpl::ShouldUpdateSelectionTextFromContextMenuParams( - const string16& selection_text, + const base::string16& selection_text, size_t selection_text_offset, const gfx::Range& selection_range, const ContextMenuParams& params) { - string16 trimmed_selection_text; + base::string16 trimmed_selection_text; if (!selection_text.empty() && !selection_range.is_empty()) { const int start = selection_range.GetMin() - selection_text_offset; const size_t length = selection_range.length(); @@ -4191,7 +4150,7 @@ bool RenderViewImpl::ShouldUpdateSelectionTextFromContextMenuParams( &trimmed_selection_text); } } - string16 trimmed_params_text; + base::string16 trimmed_params_text; TrimWhitespace(params.selection_text, TRIM_ALL, &trimmed_params_text); return trimmed_params_text != trimmed_selection_text; } @@ -4199,17 +4158,13 @@ bool RenderViewImpl::ShouldUpdateSelectionTextFromContextMenuParams( void RenderViewImpl::reportFindInPageMatchCount(int request_id, int count, bool final_update) { - // TODO(jam): switch PepperPluginInstanceImpl to take a RenderFrame - main_render_frame_->reportFindInPageMatchCount( - request_id, count, final_update); + NOTREACHED(); } void RenderViewImpl::reportFindInPageSelection(int request_id, int active_match_ordinal, const WebRect& selection_rect) { - // TODO(jam): switch PepperPluginInstanceImpl to take a RenderFrame - main_render_frame_->reportFindInPageSelection( - request_id, active_match_ordinal, selection_rect); + NOTREACHED(); } void RenderViewImpl::requestStorageQuota( @@ -4221,10 +4176,10 @@ void RenderViewImpl::requestStorageQuota( } bool RenderViewImpl::willCheckAndDispatchMessageEvent( - WebKit::WebFrame* sourceFrame, - WebKit::WebFrame* targetFrame, - WebKit::WebSecurityOrigin target_origin, - WebKit::WebDOMMessageEvent event) { + blink::WebFrame* sourceFrame, + blink::WebFrame* targetFrame, + blink::WebSecurityOrigin target_origin, + blink::WebDOMMessageEvent event) { if (!is_swapped_out_) return false; @@ -4234,6 +4189,20 @@ bool RenderViewImpl::willCheckAndDispatchMessageEvent( if (!target_origin.isNull()) params.target_origin = target_origin.toString(); + blink::WebMessagePortChannelArray channels = event.releaseChannels(); + if (!channels.isEmpty()) { + std::vector<int> message_port_ids(channels.size()); + // Extract the port IDs from the channel array. + for (size_t i = 0; i < channels.size(); ++i) { + WebMessagePortChannelImpl* webchannel = + static_cast<WebMessagePortChannelImpl*>(channels[i]); + message_port_ids[i] = webchannel->message_port_id(); + webchannel->QueueMessages(); + DCHECK_NE(message_port_ids[i], MSG_ROUTING_NONE); + } + params.message_port_ids = message_port_ids; + } + // Include the routing ID for the source frame (if one exists), which the // browser process will translate into the routing ID for the equivalent // frame in the target process. @@ -4254,24 +4223,24 @@ void RenderViewImpl::willOpenSocketStream( } void RenderViewImpl::willStartUsingPeerConnectionHandler( - WebKit::WebFrame* frame, WebKit::WebRTCPeerConnectionHandler* handler) { + blink::WebFrame* frame, blink::WebRTCPeerConnectionHandler* handler) { NOTREACHED(); } -WebKit::WebString RenderViewImpl::acceptLanguages() { +blink::WebString RenderViewImpl::acceptLanguages() { return WebString::fromUTF8(renderer_preferences_.accept_languages); } -WebKit::WebString RenderViewImpl::userAgentOverride( - WebKit::WebFrame* frame, - const WebKit::WebURL& url) { +blink::WebString RenderViewImpl::userAgentOverride( + blink::WebFrame* frame, + const blink::WebURL& url) { NOTREACHED(); - return WebKit::WebString(); + return blink::WebString(); } WebString RenderViewImpl::doNotTrackValue(WebFrame* frame) { NOTREACHED(); - return WebKit::WebString(); + return blink::WebString(); } bool RenderViewImpl::allowWebGL(WebFrame* frame, bool default_value) { @@ -4280,12 +4249,12 @@ bool RenderViewImpl::allowWebGL(WebFrame* frame, bool default_value) { } void RenderViewImpl::didLoseWebGLContext( - WebKit::WebFrame* frame, + blink::WebFrame* frame, int arb_robustness_status_code) { NOTREACHED(); } -// WebKit::WebPageSerializerClient implementation ------------------------------ +// blink::WebPageSerializerClient implementation ------------------------------ void RenderViewImpl::didSerializeDataForFrame( const WebURL& frame_url, @@ -4304,6 +4273,10 @@ bool RenderViewImpl::Send(IPC::Message* message) { return RenderWidget::Send(message); } +RenderFrame* RenderViewImpl::GetMainRenderFrame() { + return main_render_frame_.get(); +} + int RenderViewImpl::GetRoutingID() const { return routing_id_; } @@ -4324,11 +4297,11 @@ void RenderViewImpl::SetWebkitPreferences(const WebPreferences& preferences) { OnUpdateWebPreferences(preferences); } -WebKit::WebView* RenderViewImpl::GetWebView() { +blink::WebView* RenderViewImpl::GetWebView() { return webview(); } -WebKit::WebNode RenderViewImpl::GetFocusedNode() const { +blink::WebNode RenderViewImpl::GetFocusedNode() const { if (!webview()) return WebNode(); WebFrame* focused_frame = webview()->focusedFrame(); @@ -4341,7 +4314,7 @@ WebKit::WebNode RenderViewImpl::GetFocusedNode() const { return WebNode(); } -WebKit::WebNode RenderViewImpl::GetContextMenuNode() const { +blink::WebNode RenderViewImpl::GetContextMenuNode() const { return context_menu_node_; } @@ -4370,27 +4343,8 @@ bool RenderViewImpl::IsEditableNode(const WebNode& node) const { return false; } -WebKit::WebPlugin* RenderViewImpl::CreatePlugin( - WebKit::WebFrame* frame, - const WebPluginInfo& info, - const WebKit::WebPluginParams& params) { -#if defined(ENABLE_PLUGINS) - bool pepper_plugin_was_registered = false; - scoped_refptr<PluginModule> pepper_module(PluginModule::Create( - this, info, &pepper_plugin_was_registered)); - if (pepper_plugin_was_registered) { - if (pepper_module.get()) - return new PepperWebPluginImpl(pepper_module.get(), params, AsWeakPtr()); - } - - return new WebPluginImpl(frame, params, info.path, AsWeakPtr()); -#else - return NULL; -#endif -} - -void RenderViewImpl::EvaluateScript(const string16& frame_xpath, - const string16& jscript, +void RenderViewImpl::EvaluateScript(const base::string16& frame_xpath, + const base::string16& jscript, int id, bool notify_result) { v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); @@ -4447,22 +4401,15 @@ void RenderViewImpl::CancelContextMenu(int request_id) { pending_context_menus_.Remove(request_id); } -WebKit::WebPageVisibilityState RenderViewImpl::GetVisibilityState() const { +blink::WebPageVisibilityState RenderViewImpl::GetVisibilityState() const { return visibilityState(); } -void RenderViewImpl::RunModalAlertDialog(WebKit::WebFrame* frame, - const WebKit::WebString& message) { +void RenderViewImpl::RunModalAlertDialog(blink::WebFrame* frame, + const blink::WebString& message) { return runModalAlertDialog(frame, message); } -void RenderViewImpl::LoadURLExternally( - WebKit::WebFrame* frame, - const WebKit::WebURLRequest& request, - WebKit::WebNavigationPolicy policy) { - main_render_frame_->loadURLExternally(frame, request, policy); -} - void RenderViewImpl::DidStartLoading() { didStartLoading(); } @@ -4471,7 +4418,7 @@ void RenderViewImpl::DidStopLoading() { didStopLoading(); } -void RenderViewImpl::DidPlay(WebKit::WebMediaPlayer* player) { +void RenderViewImpl::DidPlay(blink::WebMediaPlayer* player) { Send(new ViewHostMsg_MediaNotification(routing_id_, reinterpret_cast<int64>(player), player->hasVideo(), @@ -4479,7 +4426,7 @@ void RenderViewImpl::DidPlay(WebKit::WebMediaPlayer* player) { true)); } -void RenderViewImpl::DidPause(WebKit::WebMediaPlayer* player) { +void RenderViewImpl::DidPause(blink::WebMediaPlayer* player) { Send(new ViewHostMsg_MediaNotification(routing_id_, reinterpret_cast<int64>(player), player->hasVideo(), @@ -4487,7 +4434,7 @@ void RenderViewImpl::DidPause(WebKit::WebMediaPlayer* player) { false)); } -void RenderViewImpl::PlayerGone(WebKit::WebMediaPlayer* player) { +void RenderViewImpl::PlayerGone(blink::WebMediaPlayer* player) { DidPause(player); } @@ -4504,7 +4451,7 @@ void RenderViewImpl::SyncSelectionIfRequired() { if (!frame) return; - string16 text; + base::string16 text; size_t offset; gfx::Range range; #if defined(ENABLE_PLUGINS) @@ -4521,7 +4468,7 @@ void RenderViewImpl::SyncSelectionIfRequired() { range = gfx::Range(location, location + length); - if (webview()->textInputInfo().type != WebKit::WebTextInputTypeNone) { + if (webview()->textInputInfo().type != blink::WebTextInputTypeNone) { // If current focused element is editable, we will send 100 more chars // before and after selection. It is for input method surrounding text // feature. @@ -4580,6 +4527,8 @@ GURL RenderViewImpl::GetAlternateErrorPageURL(const GURL& failed_url, remove_params.ClearQuery(); remove_params.ClearRef(); const GURL url_to_send = failed_url.ReplaceComponents(remove_params); + // TODO(yuusuke): change to net::FormatUrl when link doctor + // becomes unicode-capable. std::string spec_to_send = url_to_send.spec(); // Notify link doctor of the url truncation by sending of "?" at the end. if (failed_url.has_query()) @@ -4615,7 +4564,7 @@ GURL RenderViewImpl::GetAlternateErrorPageURL(const GURL& failed_url, return url; } -GURL RenderViewImpl::GetLoadingUrl(WebKit::WebFrame* frame) const { +GURL RenderViewImpl::GetLoadingUrl(blink::WebFrame* frame) const { WebDataSource* ds = frame->dataSource(); if (ds->hasUnreachableURL()) return ds->unreachableURL(); @@ -4624,12 +4573,12 @@ GURL RenderViewImpl::GetLoadingUrl(WebKit::WebFrame* frame) const { return request.url(); } -WebKit::WebPlugin* RenderViewImpl::GetWebPluginFromPluginDocument() { +blink::WebPlugin* RenderViewImpl::GetWebPluginFromPluginDocument() { return webview()->mainFrame()->document().to<WebPluginDocument>().plugin(); } void RenderViewImpl::OnFind(int request_id, - const string16& search_text, + const base::string16& search_text, const WebFindOptions& options) { WebFrame* main_frame = webview()->mainFrame(); @@ -4915,7 +4864,7 @@ void RenderViewImpl::OnResetPageEncodingToDefault() { webview()->setPageEncoding(no_encoding); } -WebFrame* RenderViewImpl::GetChildFrame(const string16& xpath) const { +WebFrame* RenderViewImpl::GetChildFrame(const base::string16& xpath) const { if (xpath.empty()) return webview()->mainFrame(); @@ -4924,11 +4873,11 @@ WebFrame* RenderViewImpl::GetChildFrame(const string16& xpath) const { // Example, /html/body/table/tbody/tr/td/iframe\n/frameset/frame[0] // should break into 2 xpaths // /html/body/table/tbody/tr/td/iframe & /frameset/frame[0] - std::vector<string16> xpaths; + std::vector<base::string16> xpaths; base::SplitString(xpath, '\n', &xpaths); WebFrame* frame = webview()->mainFrame(); - for (std::vector<string16>::const_iterator i = xpaths.begin(); + for (std::vector<base::string16>::const_iterator i = xpaths.begin(); frame && i != xpaths.end(); ++i) { frame = frame->findChildByExpression(*i); } @@ -4936,8 +4885,8 @@ WebFrame* RenderViewImpl::GetChildFrame(const string16& xpath) const { return frame; } -void RenderViewImpl::OnScriptEvalRequest(const string16& frame_xpath, - const string16& jscript, +void RenderViewImpl::OnScriptEvalRequest(const base::string16& frame_xpath, + const base::string16& jscript, int id, bool notify_result) { TRACE_EVENT_INSTANT0("test_tracing", "OnScriptEvalRequest", @@ -4958,6 +4907,18 @@ void RenderViewImpl::OnPostMessageEvent( source_frame = source_view->webview()->mainFrame(); } + // If the message contained MessagePorts, create the corresponding endpoints. + DCHECK_EQ(params.message_port_ids.size(), params.new_routing_ids.size()); + blink::WebMessagePortChannelArray channels(params.message_port_ids.size()); + for (size_t i = 0; + i < params.message_port_ids.size() && i < params.new_routing_ids.size(); + ++i) { + channels[i] = + new WebMessagePortChannelImpl(params.new_routing_ids[i], + params.message_port_ids[i], + base::MessageLoopProxy::current().get()); + } + // Create an event with the message. The final parameter to initMessageEvent // is the last event ID, which is not used with postMessage. WebDOMEvent event = frame->document().createEvent("MessageEvent"); @@ -4966,7 +4927,7 @@ void RenderViewImpl::OnPostMessageEvent( // |canBubble| and |cancellable| are always false false, false, WebSerializedScriptValue::fromString(params.data), - params.source_origin, source_frame, ""); + params.source_origin, source_frame, "", channels); // We must pass in the target_origin to do the security check on this side, // since it may have changed since the original postMessage call was made. @@ -4978,7 +4939,7 @@ void RenderViewImpl::OnPostMessageEvent( frame->dispatchMessageEventWithOriginCheck(target_origin, msg_event); } -void RenderViewImpl::OnCSSInsertRequest(const string16& frame_xpath, +void RenderViewImpl::OnCSSInsertRequest(const base::string16& frame_xpath, const std::string& css) { WebFrame* frame = GetChildFrame(frame_xpath); if (!frame) @@ -5182,9 +5143,9 @@ void RenderViewImpl::OnSetRendererPrefs( #if defined(USE_DEFAULT_RENDER_THEME) || defined(TOOLKIT_GTK) if (renderer_prefs.use_custom_colors) { - WebColorName name = WebKit::WebColorWebkitFocusRingColor; - WebKit::setNamedColors(&name, &renderer_prefs.focus_ring_color, 1); - WebKit::setCaretBlinkInterval(renderer_prefs.caret_blink_interval); + WebColorName name = blink::WebColorWebkitFocusRingColor; + blink::setNamedColors(&name, &renderer_prefs.focus_ring_color, 1); + blink::setCaretBlinkInterval(renderer_prefs.caret_blink_interval); #if defined(TOOLKIT_GTK) ui::NativeTheme::instance()->SetScrollbarColors( renderer_prefs.thumb_inactive_color, @@ -5193,12 +5154,6 @@ void RenderViewImpl::OnSetRendererPrefs( #endif // defined(TOOLKIT_GTK) if (webview()) { -#if defined(TOOLKIT_GTK) - webview()->setScrollbarColors( - renderer_prefs.thumb_inactive_color, - renderer_prefs.thumb_active_color, - renderer_prefs.track_color); -#endif // defined(TOOLKIT_GTK) webview()->setSelectionColors( renderer_prefs.active_selection_bg_color, renderer_prefs.active_selection_fg_color, @@ -5232,6 +5187,7 @@ void RenderViewImpl::OnMediaPlayerActionAt(const gfx::Point& location, } void RenderViewImpl::OnOrientationChangeEvent(int orientation) { + // Screen has rotated. 0 = default (portrait), 90 = one turn right, and so on. FOR_EACH_OBSERVER(RenderViewObserver, observers_, OrientationChangeEvent(orientation)); @@ -5249,7 +5205,7 @@ void RenderViewImpl::OnGetAllSavableResourceLinksForCurrentPage( // Prepare list to storage all savable resource links. std::vector<GURL> resources_list; std::vector<GURL> referrer_urls_list; - std::vector<WebKit::WebReferrerPolicy> referrer_policies_list; + std::vector<blink::WebReferrerPolicy> referrer_policies_list; std::vector<GURL> frames_list; SavableResourcesResult result(&resources_list, &referrer_urls_list, @@ -5311,6 +5267,11 @@ void RenderViewImpl::OnShouldClose() { before_unload_end_time)); } +void RenderViewImpl::OnSuppressDialogsUntilSwapOut() { + // Don't show any more dialogs until we finish OnSwapOut. + suppress_dialogs_until_swap_out_ = true; +} + void RenderViewImpl::OnSwapOut() { // Only run unload if we're not swapped out yet, but send the ack either way. if (!is_swapped_out_) { @@ -5341,13 +5302,16 @@ void RenderViewImpl::OnSwapOut() { // Let WebKit know that this view is hidden so it can drop resources and // stop compositing. - webview()->setVisibilityState(WebKit::WebPageVisibilityStateHidden, false); + webview()->setVisibilityState(blink::WebPageVisibilityStateHidden, false); } + // It is now safe to show modal dialogs again. + suppress_dialogs_until_swap_out_ = false; + Send(new ViewHostMsg_SwapOut_ACK(routing_id_)); } -void RenderViewImpl::NavigateToSwappedOutURL(WebKit::WebFrame* frame) { +void RenderViewImpl::NavigateToSwappedOutURL(blink::WebFrame* frame) { // We use loadRequest instead of loadHTMLString because the former commits // synchronously. Otherwise a new navigation can interrupt the navigation // to kSwappedOutURL. If that happens to be to the page we had been @@ -5464,57 +5428,15 @@ void RenderViewImpl::OnResize(const ViewMsg_Resize_Params& params) { RenderWidget::OnResize(params); } -void RenderViewImpl::WillInitiatePaint() { -#if defined(ENABLE_PLUGINS) - // Notify all of our instances that we started painting. This is used for - // internal bookkeeping only, so we know that the set can not change under - // us. - for (PepperPluginSet::iterator i = active_pepper_instances_.begin(); - i != active_pepper_instances_.end(); ++i) - (*i)->ViewWillInitiatePaint(); -#endif -} - void RenderViewImpl::DidInitiatePaint() { #if defined(ENABLE_PLUGINS) - // Notify all instances that we painted. The same caveats apply as for - // ViewFlushedPaint regarding instances closing themselves, so we take - // similar precautions. - PepperPluginSet plugins = active_pepper_instances_; - for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) { - if (active_pepper_instances_.find(*i) != active_pepper_instances_.end()) - (*i)->ViewInitiatedPaint(); - } + main_render_frame_->DidInitiatePaint(); #endif } void RenderViewImpl::DidFlushPaint() { #if defined(ENABLE_PLUGINS) - // Notify all instances that we flushed. This will call into the plugin, and - // we it may ask to close itself as a result. This will, in turn, modify our - // set, possibly invalidating the iterator. So we iterate on a copy that - // won't change out from under us. - PepperPluginSet plugins = active_pepper_instances_; - for (PepperPluginSet::iterator i = plugins.begin(); i != plugins.end(); ++i) { - // The copy above makes sure our iterator is never invalid if some plugins - // are destroyed. But some plugin may decide to close all of its views in - // response to a paint in one of them, so we need to make sure each one is - // still "current" before using it. - // - // It's possible that a plugin was destroyed, but another one was created - // with the same address. In this case, we'll call ViewFlushedPaint on that - // new plugin. But that's OK for this particular case since we're just - // notifying all of our instances that the view flushed, and the new one is - // one of our instances. - // - // What about the case where a new one is created in a callback at a new - // address and we don't issue the callback? We're still OK since this - // callback is used for flush callbacks and we could not have possibly - // started a new paint (ViewWillInitiatePaint) for the new plugin while - // processing a previous paint for an existing one. - if (active_pepper_instances_.find(*i) != active_pepper_instances_.end()) - (*i)->ViewFlushedPaint(); - } + main_render_frame_->DidFlushPaint(); #endif // If the RenderWidget is closing down then early-exit, otherwise we'll crash. @@ -5558,16 +5480,8 @@ PepperPluginInstanceImpl* RenderViewImpl::GetBitmapForOptimizedPluginPaint( gfx::Rect* clip, float* scale_factor) { #if defined(ENABLE_PLUGINS) - for (PepperPluginSet::iterator i = active_pepper_instances_.begin(); - i != active_pepper_instances_.end(); ++i) { - PepperPluginInstanceImpl* instance = *i; - // In Flash fullscreen , the plugin contents should be painted onto the - // fullscreen widget instead of the web page. - if (!instance->FlashIsFullscreenOrPending() && - instance->GetBitmapForOptimizedPluginPaint(paint_bounds, dib, location, - clip, scale_factor)) - return *i; - } + return main_render_frame_->GetBitmapForOptimizedPluginPaint( + paint_bounds, dib, location, clip, scale_factor); #endif return NULL; } @@ -5644,7 +5558,7 @@ void RenderViewImpl::OnWindowFrameChanged(const gfx::Rect& window_frame, #endif } -void RenderViewImpl::OnPluginImeCompositionCompleted(const string16& text, +void RenderViewImpl::OnPluginImeCompositionCompleted(const base::string16& text, int plugin_id) { // WebPluginDelegateProxy is responsible for figuring out if this event // applies to it or not, so inform all the delegates. @@ -5668,7 +5582,7 @@ void RenderViewImpl::DidHandleKeyEvent() { ClearEditCommands(); } -bool RenderViewImpl::WillHandleMouseEvent(const WebKit::WebMouseEvent& event) { +bool RenderViewImpl::WillHandleMouseEvent(const blink::WebMouseEvent& event) { context_menu_source_type_ = ui::MENU_SOURCE_MOUSE; possible_drag_event_info_.event_source = ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE; @@ -5676,14 +5590,7 @@ bool RenderViewImpl::WillHandleMouseEvent(const WebKit::WebMouseEvent& event) { gfx::Point(event.globalX, event.globalY); #if defined(ENABLE_PLUGINS) - // This method is called for every mouse event that the render view receives. - // And then the mouse event is forwarded to WebKit, which dispatches it to the - // event target. Potentially a Pepper plugin will receive the event. - // In order to tell whether a plugin gets the last mouse event and which it - // is, we set |pepper_last_mouse_event_target_| to NULL here. If a plugin gets - // the event, it will notify us via DidReceiveMouseEvent() and set itself as - // |pepper_last_mouse_event_target_|. - pepper_last_mouse_event_target_ = NULL; + main_render_frame_->WillHandleMouseEvent(event); #endif // If the mouse is locked, only the current owner of the mouse lock can @@ -5691,13 +5598,13 @@ bool RenderViewImpl::WillHandleMouseEvent(const WebKit::WebMouseEvent& event) { return mouse_lock_dispatcher_->WillHandleMouseEvent(event); } -bool RenderViewImpl::WillHandleKeyEvent(const WebKit::WebKeyboardEvent& event) { +bool RenderViewImpl::WillHandleKeyEvent(const blink::WebKeyboardEvent& event) { context_menu_source_type_ = ui::MENU_SOURCE_KEYBOARD; return false; } bool RenderViewImpl::WillHandleGestureEvent( - const WebKit::WebGestureEvent& event) { + const blink::WebGestureEvent& event) { context_menu_source_type_ = ui::MENU_SOURCE_TOUCH; possible_drag_event_info_.event_source = ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH; @@ -5732,10 +5639,7 @@ void RenderViewImpl::OnWasHidden() { webview()->setVisibilityState(visibilityState(), false); #if defined(ENABLE_PLUGINS) - // Inform PPAPI plugins that their page is no longer visible. - for (PepperPluginSet::iterator i = active_pepper_instances_.begin(); - i != active_pepper_instances_.end(); ++i) - (*i)->PageVisibilityChanged(false); + main_render_frame_->PageVisibilityChanged(false); #if defined(OS_MACOSX) // Inform NPAPI plugins that their container is no longer visible. @@ -5760,10 +5664,7 @@ void RenderViewImpl::OnWasShown(bool needs_repainting) { webview()->setVisibilityState(visibilityState(), false); #if defined(ENABLE_PLUGINS) - // Inform PPAPI plugins that their page is visible. - for (PepperPluginSet::iterator i = active_pepper_instances_.begin(); - i != active_pepper_instances_.end(); ++i) - (*i)->PageVisibilityChanged(true); + main_render_frame_->PageVisibilityChanged(true); #if defined(OS_MACOSX) // Inform NPAPI plugins that their container is now visible. @@ -5806,10 +5707,7 @@ void RenderViewImpl::OnSetFocus(bool enable) { (*plugin_it)->SetContentAreaFocus(enable); } } - // Notify all Pepper plugins. - for (PepperPluginSet::iterator i = active_pepper_instances_.begin(); - i != active_pepper_instances_.end(); ++i) - (*i)->SetContentAreaFocus(enable); + main_render_frame_->OnSetFocus(enable); #endif // Notify all BrowserPlugins of the RenderView's focus state. if (browser_plugin_manager_.get()) @@ -5817,35 +5715,14 @@ void RenderViewImpl::OnSetFocus(bool enable) { } void RenderViewImpl::OnImeSetComposition( - const string16& text, - const std::vector<WebKit::WebCompositionUnderline>& underlines, + const base::string16& text, + const std::vector<blink::WebCompositionUnderline>& underlines, int selection_start, int selection_end) { #if defined(ENABLE_PLUGINS) if (focused_pepper_plugin_) { - // When a PPAPI plugin has focus, we bypass WebKit. - if (!IsPepperAcceptingCompositionEvents()) { - pepper_composition_text_ = text; - } else { - // TODO(kinaba) currently all composition events are sent directly to - // plugins. Use DOM event mechanism after WebKit is made aware about - // plugins that support composition. - // The code below mimics the behavior of WebCore::Editor::setComposition. - - // Empty -> nonempty: composition started. - if (pepper_composition_text_.empty() && !text.empty()) - focused_pepper_plugin_->HandleCompositionStart(string16()); - // Nonempty -> empty: composition canceled. - if (!pepper_composition_text_.empty() && text.empty()) - focused_pepper_plugin_->HandleCompositionEnd(string16()); - pepper_composition_text_ = text; - // Nonempty: composition is ongoing. - if (!pepper_composition_text_.empty()) { - focused_pepper_plugin_->HandleCompositionUpdate( - pepper_composition_text_, underlines, selection_start, - selection_end); - } - } + focused_pepper_plugin_->render_frame()->OnImeSetComposition( + text, underlines, selection_start, selection_end); return; } @@ -5882,49 +5759,13 @@ void RenderViewImpl::OnImeSetComposition( } void RenderViewImpl::OnImeConfirmComposition( - const string16& text, + const base::string16& text, const gfx::Range& replacement_range, bool keep_selection) { #if defined(ENABLE_PLUGINS) if (focused_pepper_plugin_) { - // When a PPAPI plugin has focus, we bypass WebKit. - // Here, text.empty() has a special meaning. It means to commit the last - // update of composition text (see - // RenderWidgetHost::ImeConfirmComposition()). - const string16& last_text = text.empty() ? pepper_composition_text_ : text; - - // last_text is empty only when both text and pepper_composition_text_ is. - // Ignore it. - if (last_text.empty()) - return; - - if (!IsPepperAcceptingCompositionEvents()) { - base::i18n::UTF16CharIterator iterator(&last_text); - int32 i = 0; - while (iterator.Advance()) { - WebKit::WebKeyboardEvent char_event; - char_event.type = WebKit::WebInputEvent::Char; - char_event.timeStampSeconds = base::Time::Now().ToDoubleT(); - char_event.modifiers = 0; - char_event.windowsKeyCode = last_text[i]; - char_event.nativeKeyCode = last_text[i]; - - const int32 char_start = i; - for (; i < iterator.array_pos(); ++i) { - char_event.text[i - char_start] = last_text[i]; - char_event.unmodifiedText[i - char_start] = last_text[i]; - } - - if (webwidget()) - webwidget()->handleInputEvent(char_event); - } - } else { - // Mimics the order of events sent by WebKit. - // See WebCore::Editor::setComposition() for the corresponding code. - focused_pepper_plugin_->HandleCompositionEnd(last_text); - focused_pepper_plugin_->HandleTextInput(last_text); - } - pepper_composition_text_.clear(); + focused_pepper_plugin_->render_frame()->OnImeConfirmComposition( + text, replacement_range, keep_selection); return; } #if defined(OS_WIN) @@ -5970,6 +5811,11 @@ void RenderViewImpl::SetDeviceScaleFactor(float device_scale_factor) { webview()->settings()-> setAcceleratedCompositingForFixedRootBackgroundEnabled( ShouldUseAcceleratedFixedRootBackground(device_scale_factor_)); + webview()->settings()->setAcceleratedCompositingForScrollableFramesEnabled( + ShouldUseAcceleratedCompositingForScrollableFrames( + device_scale_factor_)); + webview()->settings()->setCompositedScrollingForFramesEnabled( + ShouldUseCompositedScrollingForFrames(device_scale_factor_)); } if (auto_resize_mode_) AutoResizeCompositor(); @@ -6023,12 +5869,12 @@ void RenderViewImpl::GetCompositionCharacterBounds( if (character_count == 0) return; - WebKit::WebFrame* frame = webview()->focusedFrame(); + blink::WebFrame* frame = webview()->focusedFrame(); if (!frame) return; bounds->reserve(character_count); - WebKit::WebRect webrect; + blink::WebRect webrect; for (size_t i = 0; i < character_count; ++i) { if (!frame->firstRectForCharacterRange(start_offset + i, 1, webrect)) { DLOG(ERROR) << "Could not retrieve character rectangle at " << i; @@ -6052,17 +5898,17 @@ void RenderViewImpl::GetCompositionRange(gfx::Range* range) { bool RenderViewImpl::CanComposeInline() { #if defined(ENABLE_PLUGINS) if (focused_pepper_plugin_) - return IsPepperAcceptingCompositionEvents(); + return focused_pepper_plugin_->IsPluginAcceptingCompositionEvents(); #endif return true; } -void RenderViewImpl::InstrumentWillBeginFrame() { +void RenderViewImpl::InstrumentWillBeginFrame(int frame_id) { if (!webview()) return; if (!webview()->devToolsAgent()) return; - webview()->devToolsAgent()->didBeginFrame(); + webview()->devToolsAgent()->didBeginFrame(frame_id); } void RenderViewImpl::InstrumentDidBeginFrame() { @@ -6094,6 +5940,18 @@ bool RenderViewImpl::AllowPartialSwap() const { return allow_partial_swap_; } +void RenderViewImpl::SetScreenMetricsEmulationParameters( + float device_scale_factor, + const gfx::Point& root_layer_offset, + float root_layer_scale) { + if (webview()) { + webview()->setCompositorDeviceScaleFactorOverride(device_scale_factor); + webview()->setRootLayerTransform( + blink::WebSize(root_layer_offset.x(), root_layer_offset.y()), + root_layer_scale); + } +} + bool RenderViewImpl::ScheduleFileChooser( const FileChooserParams& params, WebFileChooserCompletion* completion) { @@ -6119,14 +5977,14 @@ bool RenderViewImpl::ScheduleFileChooser( return true; } -WebKit::WebGeolocationClient* RenderViewImpl::geolocationClient() { +blink::WebGeolocationClient* RenderViewImpl::geolocationClient() { if (!geolocation_dispatcher_) geolocation_dispatcher_ = new GeolocationDispatcher(this); return geolocation_dispatcher_; } -WebKit::WebSpeechInputController* RenderViewImpl::speechInputController( - WebKit::WebSpeechInputListener* listener) { +blink::WebSpeechInputController* RenderViewImpl::speechInputController( + blink::WebSpeechInputListener* listener) { #if defined(ENABLE_INPUT_SPEECH) if (!input_tag_speech_dispatcher_) input_tag_speech_dispatcher_ = @@ -6135,18 +5993,12 @@ WebKit::WebSpeechInputController* RenderViewImpl::speechInputController( return input_tag_speech_dispatcher_; } -WebKit::WebSpeechRecognizer* RenderViewImpl::speechRecognizer() { +blink::WebSpeechRecognizer* RenderViewImpl::speechRecognizer() { if (!speech_recognition_dispatcher_) speech_recognition_dispatcher_ = new SpeechRecognitionDispatcher(this); return speech_recognition_dispatcher_; } -WebKit::WebDeviceOrientationClient* RenderViewImpl::deviceOrientationClient() { - if (!device_orientation_dispatcher_) - device_orientation_dispatcher_ = new DeviceOrientationDispatcher(this); - return device_orientation_dispatcher_; -} - void RenderViewImpl::zoomLimitsChanged(double minimum_level, double maximum_level) { // For now, don't remember plugin zoom values. We don't want to mix them with @@ -6201,19 +6053,20 @@ void RenderViewImpl::registerProtocolHandler(const WebString& scheme, user_gesture)); } -WebKit::WebPageVisibilityState RenderViewImpl::visibilityState() const { - WebKit::WebPageVisibilityState current_state = is_hidden() ? - WebKit::WebPageVisibilityStateHidden : - WebKit::WebPageVisibilityStateVisible; - WebKit::WebPageVisibilityState override_state = current_state; +blink::WebPageVisibilityState RenderViewImpl::visibilityState() const { + blink::WebPageVisibilityState current_state = is_hidden() ? + blink::WebPageVisibilityStateHidden : + blink::WebPageVisibilityStateVisible; + blink::WebPageVisibilityState override_state = current_state; + // TODO(jam): move this method to WebFrameClient. if (GetContentClient()->renderer()-> - ShouldOverridePageVisibilityState(this, + ShouldOverridePageVisibilityState(main_render_frame_.get(), &override_state)) return override_state; return current_state; } -WebKit::WebUserMediaClient* RenderViewImpl::userMediaClient() { +blink::WebUserMediaClient* RenderViewImpl::userMediaClient() { // This can happen in tests, in which case it's OK to return NULL. if (!InitializeMediaStreamClient()) return NULL; @@ -6221,7 +6074,7 @@ WebKit::WebUserMediaClient* RenderViewImpl::userMediaClient() { return web_user_media_client_; } -WebKit::WebMIDIClient* RenderViewImpl::webMIDIClient() { +blink::WebMIDIClient* RenderViewImpl::webMIDIClient() { if (!midi_dispatcher_) midi_dispatcher_ = new MIDIDispatcher(this); return midi_dispatcher_; @@ -6234,6 +6087,30 @@ void RenderViewImpl::draggableRegionsChanged() { DraggableRegionsChanged(webview()->mainFrame())); } +WebMediaPlayer* RenderViewImpl::CreateWebMediaPlayerForMediaStream( + WebFrame* frame, + const blink::WebURL& url, + WebMediaPlayerClient* client) { +#if defined(ENABLE_WEBRTC) + if (!InitializeMediaStreamClient()) { + LOG(ERROR) << "Failed to initialize MediaStreamClient"; + return NULL; + } +#if !defined(GOOGLE_TV) + if (media_stream_client_->IsMediaStream(url)) { +#if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL) + bool found_neon = + (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0; + UMA_HISTOGRAM_BOOLEAN("Platform.WebRtcNEONFound", found_neon); +#endif // defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL) + return new WebMediaPlayerMS(frame, client, AsWeakPtr(), + media_stream_client_, new RenderMediaLog()); + } +#endif // !defined(GOOGLE_TV) +#endif // defined(ENABLE_WEBRTC) + return NULL; +} + #if defined(OS_ANDROID) WebContentDetectionResult RenderViewImpl::detectContentAround( const WebHitTestResult& touch_hit) { @@ -6282,13 +6159,82 @@ void RenderViewImpl::LaunchAndroidContentIntent(const GURL& intent, } bool RenderViewImpl::openDateTimeChooser( - const WebKit::WebDateTimeChooserParams& params, - WebKit::WebDateTimeChooserCompletion* completion) { + const blink::WebDateTimeChooserParams& params, + blink::WebDateTimeChooserCompletion* completion) { + // JavaScript may try to open a date time chooser while one is already open. + if (date_time_picker_client_) + return false; date_time_picker_client_.reset( new RendererDateTimePicker(this, params, completion)); return date_time_picker_client_->Open(); } +#if defined(OS_ANDROID) +void RenderViewImpl::DismissDateTimeDialog() { + DCHECK(date_time_picker_client_); + date_time_picker_client_.reset(NULL); +} +#endif + +WebMediaPlayer* RenderViewImpl::CreateAndroidWebMediaPlayer( + WebFrame* frame, + const blink::WebURL& url, + WebMediaPlayerClient* client) { + GpuChannelHost* gpu_channel_host = + RenderThreadImpl::current()->EstablishGpuChannelSync( + CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE); + if (!gpu_channel_host) { + LOG(ERROR) << "Failed to establish GPU channel for media player"; + return NULL; + } + + scoped_ptr<StreamTextureFactory> stream_texture_factory; + if (UsingSynchronousRendererCompositor()) { + SynchronousCompositorFactory* factory = + SynchronousCompositorFactory::GetInstance(); + stream_texture_factory = factory->CreateStreamTextureFactory(routing_id_); + } else { + scoped_refptr<cc::ContextProvider> context_provider = + RenderThreadImpl::current()->SharedMainThreadContextProvider(); + + if (!context_provider.get()) { + LOG(ERROR) << "Failed to get context3d for media player"; + return NULL; + } + + stream_texture_factory.reset(new StreamTextureFactoryImpl( + context_provider->Context3d(), gpu_channel_host, routing_id_)); + } + + scoped_ptr<WebMediaPlayerAndroid> web_media_player_android( + new WebMediaPlayerAndroid( + frame, + client, + AsWeakPtr(), + media_player_manager_, + stream_texture_factory.release(), + RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy(), + new RenderMediaLog())); +#if defined(ENABLE_WEBRTC) && defined(GOOGLE_TV) + if (media_stream_client_ && media_stream_client_->IsMediaStream(url)) { + RTCVideoDecoderFactoryTv* factory = RenderThreadImpl::current() + ->GetMediaStreamDependencyFactory()->decoder_factory_tv(); + // |media_stream_client| and |factory| outlives |web_media_player_android|. + if (!factory->AcquireDemuxer() || + !web_media_player_android->InjectMediaStream( + media_stream_client_, + factory, + base::Bind( + base::IgnoreResult(&RTCVideoDecoderFactoryTv::ReleaseDemuxer), + base::Unretained(factory)))) { + LOG(ERROR) << "Failed to inject media stream."; + return NULL; + } + } +#endif // defined(ENABLE_WEBRTC) && defined(GOOGLE_TV) + return web_media_player_android.release(); +} + #endif // defined(OS_ANDROID) #if defined(OS_MACOSX) @@ -6354,13 +6300,6 @@ void RenderViewImpl::OnEnableViewSourceMode() { main_frame->enableViewSourceMode(true); } -#if defined(OS_ANDROID) -void RenderViewImpl::OnJavaBridgeInit() { - DCHECK(!java_bridge_dispatcher_); - java_bridge_dispatcher_ = new JavaBridgeDispatcher(this); -} -#endif - void RenderViewImpl::OnDisownOpener() { if (!webview()) return; @@ -6372,7 +6311,7 @@ void RenderViewImpl::OnDisownOpener() { #if defined(OS_ANDROID) bool RenderViewImpl::didTapMultipleTargets( - const WebKit::WebGestureEvent& event, + const blink::WebGestureEvent& event, const WebVector<WebRect>& target_rects) { // Never show a disambiguation popup when accessibility is enabled, // as this interferes with "touch exploration". @@ -6473,6 +6412,18 @@ void RenderViewImpl::SetDeviceScaleFactorForTesting(float factor) { OnResize(params); } +void RenderViewImpl::ForceResizeForTesting(const gfx::Size& new_size) { + gfx::Rect new_position(rootWindowRect().x, + rootWindowRect().y, + new_size.width(), + new_size.height()); + ResizeSynchronously(new_position); +} + +void RenderViewImpl::UseSynchronousResizeModeForTesting(bool enable) { + resizing_mode_selector_->set_is_synchronous_mode(enable); +} + void RenderViewImpl::EnableAutoResizeForTesting(const gfx::Size& min_size, const gfx::Size& max_size) { OnEnableAutoResize(min_size, max_size); @@ -6489,10 +6440,6 @@ void RenderViewImpl::SetMediaStreamClientForTesting( media_stream_client_ = media_stream_client; } -bool RenderViewImpl::IsPluginFullscreenAllowed() { - return renderer_preferences_.plugin_fullscreen_allowed; -} - void RenderViewImpl::OnReleaseDisambiguationPopupDIB( TransportDIB::Handle dib_handle) { TransportDIB* dib = TransportDIB::CreateWithHandle(dib_handle); diff --git a/chromium/content/renderer/render_view_impl.h b/chromium/content/renderer/render_view_impl.h index 2634ce1ebbd..f341ecc08e7 100644 --- a/chromium/content/renderer/render_view_impl.h +++ b/chromium/content/renderer/render_view_impl.h @@ -39,6 +39,7 @@ #include "content/renderer/mouse_lock_dispatcher.h" #include "content/renderer/render_frame_impl.h" #include "content/renderer/render_widget.h" +#include "content/renderer/renderer_date_time_picker.h" #include "content/renderer/renderer_webcookiejar_impl.h" #include "content/renderer/stats_collection_observer.h" #include "ipc/ipc_platform_file.h" @@ -84,7 +85,7 @@ namespace ui { struct SelectedFileInfo; } // namespace ui -namespace WebKit { +namespace blink { class WebApplicationCacheHost; class WebApplicationCacheHostClient; class WebDOMMessageEvent; @@ -111,7 +112,6 @@ class WebTouchEvent; class WebURLRequest; class WebUserMediaClient; struct WebActiveWheelFlingParameters; -struct WebCursorInfo; struct WebDateTimeChooserParams; struct WebFileChooserParams; struct WebFindOptions; @@ -153,11 +153,8 @@ class RenderViewObserver; class RenderViewTest; class RendererAccessibility; class RendererDateTimePicker; -class RendererPpapiHost; class RendererWebColorChooserImpl; -class RenderWidgetFullscreenPepper; class SpeechRecognitionDispatcher; -class StatsCollectionController; class WebPluginDelegateProxy; struct CustomContextMenuContext; struct DropData; @@ -176,9 +173,9 @@ class WebMediaPlayerProxyAndroid; // class CONTENT_EXPORT RenderViewImpl : public RenderWidget, - NON_EXPORTED_BASE(public WebKit::WebViewClient), - NON_EXPORTED_BASE(public WebKit::WebFrameClient), - NON_EXPORTED_BASE(public WebKit::WebPageSerializerClient), + NON_EXPORTED_BASE(public blink::WebViewClient), + NON_EXPORTED_BASE(public blink::WebFrameClient), + NON_EXPORTED_BASE(public blink::WebPageSerializerClient), public RenderView, NON_EXPORTED_BASE(public WebMediaPlayerDelegate), public base::SupportsWeakPtr<RenderViewImpl> { @@ -193,12 +190,12 @@ class CONTENT_EXPORT RenderViewImpl int32 main_frame_routing_id, int32 surface_id, int64 session_storage_namespace_id, - const string16& frame_name, + const base::string16& frame_name, bool is_renderer_created, bool swapped_out, bool hidden, int32 next_page_id, - const WebKit::WebScreenInfo& screen_info, + const blink::WebScreenInfo& screen_info, AccessibilityMode accessibility_mode, bool allow_partial_swap); @@ -208,13 +205,13 @@ class CONTENT_EXPORT RenderViewImpl RenderViewImpl* (*create_render_view_impl)(RenderViewImplParams*)); // Returns the RenderViewImpl containing the given WebView. - static RenderViewImpl* FromWebView(WebKit::WebView* webview); + static RenderViewImpl* FromWebView(blink::WebView* webview); // Returns the RenderViewImpl for the given routing ID. static RenderViewImpl* FromRoutingID(int routing_id); // May return NULL when the view is closing. - WebKit::WebView* webview() const; + blink::WebView* webview() const; int history_list_offset() const { return history_list_offset_; } @@ -222,26 +219,30 @@ class CONTENT_EXPORT RenderViewImpl return webkit_preferences_; } + const RendererPreferences& renderer_preferences() const { + return renderer_preferences_; + } + void set_send_content_state_immediately(bool value) { send_content_state_immediately_ = value; } + RenderFrameImpl* main_render_frame() { return main_render_frame_.get(); } + MediaStreamDispatcher* media_stream_dispatcher() { return media_stream_dispatcher_; } + RendererAccessibility* renderer_accessibility() { + return renderer_accessibility_; + } + MouseLockDispatcher* mouse_lock_dispatcher() { return mouse_lock_dispatcher_; } RendererWebCookieJarImpl* cookie_jar() { return &cookie_jar_; } -#if defined(OS_ANDROID) - RendererMediaPlayerManager* media_player_manager() { - return media_player_manager_.get(); - } -#endif - // Lazily initialize this view's BrowserPluginManager and return it. BrowserPluginManager* GetBrowserPluginManager(); @@ -262,72 +263,34 @@ class CONTENT_EXPORT RenderViewImpl // Returns true if the chooser was successfully scheduled. False means we // didn't schedule anything. bool ScheduleFileChooser(const FileChooserParams& params, - WebKit::WebFileChooserCompletion* completion); + blink::WebFileChooserCompletion* completion); void LoadNavigationErrorPage( - WebKit::WebFrame* frame, - const WebKit::WebURLRequest& failed_request, - const WebKit::WebURLError& error, + blink::WebFrame* frame, + const blink::WebURLRequest& failed_request, + const blink::WebURLError& error, const std::string& html, bool replace); +#if defined(OS_ANDROID) + void DismissDateTimeDialog(); +#endif + // Plugin-related functions -------------------------------------------------- #if defined(ENABLE_PLUGINS) - // Indicates that the given instance has been created. - void PepperInstanceCreated(PepperPluginInstanceImpl* instance); - - // Indicates that the given instance is being destroyed. This is called from - // the destructor, so it's important that the instance is not dereferenced - // from this call. - void PepperInstanceDeleted(PepperPluginInstanceImpl* instance); - - // Notifies that |instance| has changed the cursor. - // This will update the cursor appearance if it is currently over the plugin - // instance. - void PepperDidChangeCursor(PepperPluginInstanceImpl* instance, - const WebKit::WebCursorInfo& cursor); - - // Notifies that |instance| has received a mouse event. - void PepperDidReceiveMouseEvent(PepperPluginInstanceImpl* instance); - - // Notification that the given plugin is focused or unfocused. - void PepperFocusChanged(PepperPluginInstanceImpl* instance, bool focused); - - // Informs the render view that a PPAPI plugin has changed text input status. - void PepperTextInputTypeChanged(PepperPluginInstanceImpl* instance); - void PepperCaretPositionChanged(PepperPluginInstanceImpl* instance); - - // Cancels current composition. - void PepperCancelComposition(PepperPluginInstanceImpl* instance); - - // Informs the render view that a PPAPI plugin has changed selection. - void PepperSelectionChanged(PepperPluginInstanceImpl* instance); - - // Creates a fullscreen container for a pepper plugin instance. - RenderWidgetFullscreenPepper* CreatePepperFullscreenContainer( - PepperPluginInstanceImpl* plugin); - - // Notification that a PPAPI plugin has been created. - void PepperPluginCreated(RendererPpapiHost* host); - - // Retrieves the current caret position if a PPAPI plugin has focus. - bool GetPepperCaretBounds(gfx::Rect* rect); - - bool IsPepperAcceptingCompositionEvents() const; - - // Notification that the given plugin has crashed. - void PluginCrashed(const base::FilePath& plugin_path, - base::ProcessId plugin_pid); - - // Simulates IME events for testing purpose. - void SimulateImeSetComposition( - const string16& text, - const std::vector<WebKit::WebCompositionUnderline>& underlines, - int selection_start, - int selection_end); - void SimulateImeConfirmComposition(const string16& text, - const gfx::Range& replacement_range); + PepperPluginInstanceImpl* focused_pepper_plugin() { + return focused_pepper_plugin_; + } + void set_focused_pepper_plugin(PepperPluginInstanceImpl* plugin) { + focused_pepper_plugin_ = plugin; + } + PepperPluginInstanceImpl* pepper_last_mouse_event_target() { + return pepper_last_mouse_event_target_; + } + void set_pepper_last_mouse_event_target(PepperPluginInstanceImpl* plugin) { + pepper_last_mouse_event_target_ = plugin; + } #if defined(OS_MACOSX) || defined(OS_WIN) // Informs the render view that the given plugin has gained or lost focus. @@ -341,22 +304,10 @@ class CONTENT_EXPORT RenderViewImpl void RegisterPluginDelegate(WebPluginDelegateProxy* delegate); void UnregisterPluginDelegate(WebPluginDelegateProxy* delegate); - - // Helper function to retrieve information about a plugin for a URL and mime - // type. Returns false if no plugin was found. - // |actual_mime_type| is the actual mime type supported by the - // plugin found that match the URL given (one for each item in - // |info|). - bool GetPluginInfo(const GURL& url, - const GURL& page_url, - const std::string& mime_type, - WebPluginInfo* plugin_info, - std::string* actual_mime_type); - #endif // ENABLE_PLUGINS void TransferActiveWheelFlingAnimation( - const WebKit::WebActiveWheelFlingParameters& params); + const blink::WebActiveWheelFlingParameters& params); // Returns true if the focused element is editable text from the perspective // of IME support (also used for on-screen keyboard). Works correctly inside @@ -374,6 +325,19 @@ class CONTENT_EXPORT RenderViewImpl // periodic timer so we don't send too many messages. void SyncNavigationState(); + // Temporary call until all this media code moves to RenderFrame. + // TODO(jam): remove me + blink::WebMediaPlayer* CreateMediaPlayer( + RenderFrame* render_frame, + blink::WebFrame* frame, + const blink::WebURL& url, + blink::WebMediaPlayerClient* client); + // Temporary call until the context menu code moves to RenderFrmae. + // TODO(jam): remove me + int ShowContextMenu(ContextMenuClient* client, + const ContextMenuParams& params); + void CancelContextMenu(int request_id); + // Returns the length of the session history of this RenderView. Note that // this only coincides with the actual length of the session history if this // RenderView is the currently active RenderView of a WebContents. @@ -387,6 +351,11 @@ class CONTENT_EXPORT RenderViewImpl // Change the device scale factor and force the compositor to resize. void SetDeviceScaleFactorForTesting(float factor); + // Used to force the size of a window when running layout tests. + void ForceResizeForTesting(const gfx::Size& new_size); + + void UseSynchronousResizeModeForTesting(bool enable); + // Control autoresize mode. void EnableAutoResizeForTesting(const gfx::Size& min_size, const gfx::Size& max_size); @@ -396,19 +365,16 @@ class CONTENT_EXPORT RenderViewImpl // Must be called before any players are created. void SetMediaStreamClientForTesting(MediaStreamClient* media_stream_client); - // Determines whether plugins are allowed to enter fullscreen mode. - bool IsPluginFullscreenAllowed(); - // IPC::Listener implementation ---------------------------------------------- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; - // WebKit::WebWidgetClient implementation ------------------------------------ + // blink::WebWidgetClient implementation ------------------------------------ // Most methods are handled by RenderWidget. virtual void didFocus(); virtual void didBlur(); - virtual void show(WebKit::WebNavigationPolicy policy); + virtual void show(blink::WebNavigationPolicy policy); virtual void runModal(); virtual bool enterFullScreen(); virtual void exitFullScreen(); @@ -416,287 +382,292 @@ class CONTENT_EXPORT RenderViewImpl virtual void requestPointerUnlock(); virtual bool isPointerLocked(); virtual void didActivateCompositor(int input_handler_identifier); - virtual void didHandleGestureEvent(const WebKit::WebGestureEvent& event, + virtual void didHandleGestureEvent(const blink::WebGestureEvent& event, bool event_cancelled) OVERRIDE; virtual void initializeLayerTreeView() OVERRIDE; - // WebKit::WebViewClient implementation -------------------------------------- - - virtual WebKit::WebView* createView( - WebKit::WebFrame* creator, - const WebKit::WebURLRequest& request, - const WebKit::WebWindowFeatures& features, - const WebKit::WebString& frame_name, - WebKit::WebNavigationPolicy policy); - virtual WebKit::WebWidget* createPopupMenu(WebKit::WebPopupType popup_type); - virtual WebKit::WebExternalPopupMenu* createExternalPopupMenu( - const WebKit::WebPopupMenuInfo& popup_menu_info, - WebKit::WebExternalPopupMenuClient* popup_menu_client); - virtual WebKit::WebStorageNamespace* createSessionStorageNamespace(); + // blink::WebViewClient implementation -------------------------------------- + + virtual blink::WebView* createView( + blink::WebFrame* creator, + const blink::WebURLRequest& request, + const blink::WebWindowFeatures& features, + const blink::WebString& frame_name, + blink::WebNavigationPolicy policy, + bool suppress_opener); + virtual blink::WebWidget* createPopupMenu(blink::WebPopupType popup_type); + virtual blink::WebExternalPopupMenu* createExternalPopupMenu( + const blink::WebPopupMenuInfo& popup_menu_info, + blink::WebExternalPopupMenuClient* popup_menu_client); + virtual blink::WebStorageNamespace* createSessionStorageNamespace(); virtual bool shouldReportDetailedMessageForSource( - const WebKit::WebString& source); + const blink::WebString& source); virtual void didAddMessageToConsole( - const WebKit::WebConsoleMessage& message, - const WebKit::WebString& source_name, + const blink::WebConsoleMessage& message, + const blink::WebString& source_name, unsigned source_line, - const WebKit::WebString& stack_trace); - virtual void printPage(WebKit::WebFrame* frame); - virtual WebKit::WebNotificationPresenter* notificationPresenter(); + const blink::WebString& stack_trace); + virtual void printPage(blink::WebFrame* frame); + virtual blink::WebNotificationPresenter* notificationPresenter(); virtual bool enumerateChosenDirectory( - const WebKit::WebString& path, - WebKit::WebFileChooserCompletion* chooser_completion); - virtual void initializeHelperPluginWebFrame(WebKit::WebHelperPlugin*); + const blink::WebString& path, + blink::WebFileChooserCompletion* chooser_completion); + virtual void initializeHelperPluginWebFrame(blink::WebHelperPlugin*); virtual void didStartLoading(); virtual void didStopLoading(); - virtual void didChangeLoadProgress(WebKit::WebFrame* frame, + virtual void didChangeLoadProgress(blink::WebFrame* frame, double load_progress); virtual void didCancelCompositionOnSelectionChange(); virtual void didChangeSelection(bool is_selection_empty); - virtual void didExecuteCommand(const WebKit::WebString& command_name); + virtual void didExecuteCommand(const blink::WebString& command_name); virtual bool handleCurrentKeyboardEvent(); - virtual WebKit::WebColorChooser* createColorChooser( - WebKit::WebColorChooserClient*, const WebKit::WebColor& initial_color); + virtual blink::WebColorChooser* createColorChooser( + blink::WebColorChooserClient*, + const blink::WebColor& initial_color, + const blink::WebVector<blink::WebColorSuggestion>& suggestions); virtual bool runFileChooser( - const WebKit::WebFileChooserParams& params, - WebKit::WebFileChooserCompletion* chooser_completion); - virtual void runModalAlertDialog(WebKit::WebFrame* frame, - const WebKit::WebString& message); - virtual bool runModalConfirmDialog(WebKit::WebFrame* frame, - const WebKit::WebString& message); - virtual bool runModalPromptDialog(WebKit::WebFrame* frame, - const WebKit::WebString& message, - const WebKit::WebString& default_value, - WebKit::WebString* actual_value); - virtual bool runModalBeforeUnloadDialog(WebKit::WebFrame* frame, + const blink::WebFileChooserParams& params, + blink::WebFileChooserCompletion* chooser_completion); + virtual void runModalAlertDialog(blink::WebFrame* frame, + const blink::WebString& message); + virtual bool runModalConfirmDialog(blink::WebFrame* frame, + const blink::WebString& message); + virtual bool runModalPromptDialog(blink::WebFrame* frame, + const blink::WebString& message, + const blink::WebString& default_value, + blink::WebString* actual_value); + virtual bool runModalBeforeUnloadDialog(blink::WebFrame* frame, bool is_reload, - const WebKit::WebString& message); + const blink::WebString& message); + virtual void showValidationMessage(const blink::WebRect& anchor_in_root_view, + const blink::WebString& main_text, + const blink::WebString& sub_text, + blink::WebTextDirection hint) OVERRIDE; + virtual void hideValidationMessage() OVERRIDE; + virtual void moveValidationMessage( + const blink::WebRect& anchor_in_root_view) OVERRIDE; + // DEPRECATED - virtual bool runModalBeforeUnloadDialog(WebKit::WebFrame* frame, - const WebKit::WebString& message); - virtual void showContextMenu(WebKit::WebFrame* frame, - const WebKit::WebContextMenuData& data); + virtual bool runModalBeforeUnloadDialog(blink::WebFrame* frame, + const blink::WebString& message); + virtual void showContextMenu(blink::WebFrame* frame, + const blink::WebContextMenuData& data); virtual void clearContextMenu(); - virtual void setStatusText(const WebKit::WebString& text); - virtual void setMouseOverURL(const WebKit::WebURL& url); - virtual void setKeyboardFocusURL(const WebKit::WebURL& url); - virtual void startDragging(WebKit::WebFrame* frame, - const WebKit::WebDragData& data, - WebKit::WebDragOperationsMask mask, - const WebKit::WebImage& image, - const WebKit::WebPoint& imageOffset); + virtual void setStatusText(const blink::WebString& text); + virtual void setMouseOverURL(const blink::WebURL& url); + virtual void setKeyboardFocusURL(const blink::WebURL& url); + virtual void startDragging(blink::WebFrame* frame, + const blink::WebDragData& data, + blink::WebDragOperationsMask mask, + const blink::WebImage& image, + const blink::WebPoint& imageOffset); virtual bool acceptsLoadDrops(); virtual void focusNext(); virtual void focusPrevious(); - virtual void focusedNodeChanged(const WebKit::WebNode& node); + virtual void focusedNodeChanged(const blink::WebNode& node); virtual void numberOfWheelEventHandlersChanged(unsigned num_handlers); virtual void didUpdateLayout(); #if defined(OS_ANDROID) virtual bool didTapMultipleTargets( - const WebKit::WebGestureEvent& event, - const WebKit::WebVector<WebKit::WebRect>& target_rects); + const blink::WebGestureEvent& event, + const blink::WebVector<blink::WebRect>& target_rects); #endif virtual void navigateBackForwardSoon(int offset); virtual int historyBackListCount(); virtual int historyForwardListCount(); virtual void postAccessibilityEvent( - const WebKit::WebAXObject& obj, WebKit::WebAXEvent event); - virtual void didUpdateInspectorSetting(const WebKit::WebString& key, - const WebKit::WebString& value); - virtual WebKit::WebGeolocationClient* geolocationClient(); - virtual WebKit::WebSpeechInputController* speechInputController( - WebKit::WebSpeechInputListener* listener); - virtual WebKit::WebSpeechRecognizer* speechRecognizer(); - virtual WebKit::WebDeviceOrientationClient* deviceOrientationClient(); + const blink::WebAXObject& obj, blink::WebAXEvent event); + virtual void didUpdateInspectorSetting(const blink::WebString& key, + const blink::WebString& value); + virtual blink::WebGeolocationClient* geolocationClient(); + virtual blink::WebSpeechInputController* speechInputController( + blink::WebSpeechInputListener* listener); + virtual blink::WebSpeechRecognizer* speechRecognizer(); virtual void zoomLimitsChanged(double minimum_level, double maximum_level); virtual void zoomLevelChanged(); virtual double zoomLevelToZoomFactor(double zoom_level) const; virtual double zoomFactorToZoomLevel(double factor) const; - virtual void registerProtocolHandler(const WebKit::WebString& scheme, - const WebKit::WebString& base_url, - const WebKit::WebString& url, - const WebKit::WebString& title); - virtual WebKit::WebPageVisibilityState visibilityState() const; - virtual WebKit::WebUserMediaClient* userMediaClient(); - virtual WebKit::WebMIDIClient* webMIDIClient(); + virtual void registerProtocolHandler(const blink::WebString& scheme, + const blink::WebString& base_url, + const blink::WebString& url, + const blink::WebString& title); + virtual blink::WebPageVisibilityState visibilityState() const; + virtual blink::WebUserMediaClient* userMediaClient(); + virtual blink::WebMIDIClient* webMIDIClient(); virtual void draggableRegionsChanged(); #if defined(OS_ANDROID) - virtual void scheduleContentIntent(const WebKit::WebURL& intent); + virtual void scheduleContentIntent(const blink::WebURL& intent); virtual void cancelScheduledContentIntents(); - virtual WebKit::WebContentDetectionResult detectContentAround( - const WebKit::WebHitTestResult& touch_hit); + virtual blink::WebContentDetectionResult detectContentAround( + const blink::WebHitTestResult& touch_hit); // Only used on Android since all other platforms implement // date and time input fields using MULTIPLE_FIELDS_UI - virtual bool openDateTimeChooser(const WebKit::WebDateTimeChooserParams&, - WebKit::WebDateTimeChooserCompletion*); - virtual void didScrollWithKeyboard(const WebKit::WebSize& delta); + virtual bool openDateTimeChooser(const blink::WebDateTimeChooserParams&, + blink::WebDateTimeChooserCompletion*); + virtual void didScrollWithKeyboard(const blink::WebSize& delta); #endif - // WebKit::WebFrameClient implementation ------------------------------------- - - virtual WebKit::WebMediaPlayer* createMediaPlayer( - WebKit::WebFrame* frame, - const WebKit::WebURL& url, - WebKit::WebMediaPlayerClient* client); - virtual WebKit::WebCookieJar* cookieJar(WebKit::WebFrame* frame); - virtual void didAccessInitialDocument(WebKit::WebFrame* frame); - virtual void didDisownOpener(WebKit::WebFrame* frame); - virtual void frameDetached(WebKit::WebFrame* frame); - virtual void willClose(WebKit::WebFrame* frame); + // blink::WebFrameClient implementation ------------------------------------- + + virtual blink::WebMediaPlayer* createMediaPlayer( + blink::WebFrame* frame, + const blink::WebURL& url, + blink::WebMediaPlayerClient* client); + virtual blink::WebCookieJar* cookieJar(blink::WebFrame* frame); + virtual void didAccessInitialDocument(blink::WebFrame* frame); + virtual void didDisownOpener(blink::WebFrame* frame); + virtual void frameDetached(blink::WebFrame* frame); + virtual void willClose(blink::WebFrame* frame); + virtual void didMatchCSS( + blink::WebFrame* frame, + const blink::WebVector<blink::WebString>& newly_matching_selectors, + const blink::WebVector<blink::WebString>& stopped_matching_selectors); // The WebDataSource::ExtraData* is assumed to be a DocumentState* subclass. - virtual WebKit::WebNavigationPolicy decidePolicyForNavigation( - WebKit::WebFrame* frame, - WebKit::WebDataSource::ExtraData* extraData, - const WebKit::WebURLRequest& request, - WebKit::WebNavigationType type, - WebKit::WebNavigationPolicy default_policy, + virtual blink::WebNavigationPolicy decidePolicyForNavigation( + blink::WebFrame* frame, + blink::WebDataSource::ExtraData* extraData, + const blink::WebURLRequest& request, + blink::WebNavigationType type, + blink::WebNavigationPolicy default_policy, bool is_redirect); // DEPRECATED. - virtual WebKit::WebNavigationPolicy decidePolicyForNavigation( - WebKit::WebFrame* frame, - const WebKit::WebURLRequest& request, - WebKit::WebNavigationType type, - WebKit::WebNavigationPolicy default_policy, + virtual blink::WebNavigationPolicy decidePolicyForNavigation( + blink::WebFrame* frame, + const blink::WebURLRequest& request, + blink::WebNavigationType type, + blink::WebNavigationPolicy default_policy, bool is_redirect); - virtual void willSendSubmitEvent(WebKit::WebFrame* frame, - const WebKit::WebFormElement& form); - virtual void willSubmitForm(WebKit::WebFrame* frame, - const WebKit::WebFormElement& form); - virtual void didCreateDataSource(WebKit::WebFrame* frame, - WebKit::WebDataSource* datasource); - virtual void didStartProvisionalLoad(WebKit::WebFrame* frame); + virtual void willSendSubmitEvent(blink::WebFrame* frame, + const blink::WebFormElement& form); + virtual void willSubmitForm(blink::WebFrame* frame, + const blink::WebFormElement& form); + virtual void didCreateDataSource(blink::WebFrame* frame, + blink::WebDataSource* datasource); + virtual void didStartProvisionalLoad(blink::WebFrame* frame); virtual void didReceiveServerRedirectForProvisionalLoad( - WebKit::WebFrame* frame); - virtual void didFailProvisionalLoad(WebKit::WebFrame* frame, - const WebKit::WebURLError& error); - virtual void didCommitProvisionalLoad(WebKit::WebFrame* frame, + blink::WebFrame* frame); + virtual void didFailProvisionalLoad(blink::WebFrame* frame, + const blink::WebURLError& error); + virtual void didCommitProvisionalLoad(blink::WebFrame* frame, bool is_new_navigation); - virtual void didClearWindowObject(WebKit::WebFrame* frame); - virtual void didCreateDocumentElement(WebKit::WebFrame* frame); - virtual void didReceiveTitle(WebKit::WebFrame* frame, - const WebKit::WebString& title, - WebKit::WebTextDirection direction); - virtual void didChangeIcon(WebKit::WebFrame*, - WebKit::WebIconURL::Type); - virtual void didFinishDocumentLoad(WebKit::WebFrame* frame); - virtual void didHandleOnloadEvents(WebKit::WebFrame* frame); - virtual void didFailLoad(WebKit::WebFrame* frame, - const WebKit::WebURLError& error); - virtual void didFinishLoad(WebKit::WebFrame* frame); - virtual void didNavigateWithinPage(WebKit::WebFrame* frame, + virtual void didClearWindowObject(blink::WebFrame* frame); + virtual void didCreateDocumentElement(blink::WebFrame* frame); + virtual void didReceiveTitle(blink::WebFrame* frame, + const blink::WebString& title, + blink::WebTextDirection direction); + virtual void didChangeIcon(blink::WebFrame*, + blink::WebIconURL::Type); + virtual void didFinishDocumentLoad(blink::WebFrame* frame); + virtual void didHandleOnloadEvents(blink::WebFrame* frame); + virtual void didFailLoad(blink::WebFrame* frame, + const blink::WebURLError& error); + virtual void didFinishLoad(blink::WebFrame* frame); + virtual void didNavigateWithinPage(blink::WebFrame* frame, bool is_new_navigation); - virtual void didUpdateCurrentHistoryItem(WebKit::WebFrame* frame); - virtual void willSendRequest(WebKit::WebFrame* frame, + virtual void didUpdateCurrentHistoryItem(blink::WebFrame* frame); + virtual void willSendRequest(blink::WebFrame* frame, unsigned identifier, - WebKit::WebURLRequest& request, - const WebKit::WebURLResponse& redirect_response); - virtual void didReceiveResponse(WebKit::WebFrame* frame, + blink::WebURLRequest& request, + const blink::WebURLResponse& redirect_response); + virtual void didReceiveResponse(blink::WebFrame* frame, unsigned identifier, - const WebKit::WebURLResponse& response); - virtual void didFinishResourceLoad(WebKit::WebFrame* frame, + const blink::WebURLResponse& response); + virtual void didFinishResourceLoad(blink::WebFrame* frame, unsigned identifier); virtual void didLoadResourceFromMemoryCache( - WebKit::WebFrame* frame, - const WebKit::WebURLRequest& request, - const WebKit::WebURLResponse&); - virtual void didDisplayInsecureContent(WebKit::WebFrame* frame); + blink::WebFrame* frame, + const blink::WebURLRequest& request, + const blink::WebURLResponse&); + virtual void didDisplayInsecureContent(blink::WebFrame* frame); virtual void didRunInsecureContent( - WebKit::WebFrame* frame, - const WebKit::WebSecurityOrigin& origin, - const WebKit::WebURL& target); - virtual void didExhaustMemoryAvailableForScript(WebKit::WebFrame* frame); - virtual void didCreateScriptContext(WebKit::WebFrame* frame, + blink::WebFrame* frame, + const blink::WebSecurityOrigin& origin, + const blink::WebURL& target); + virtual void didExhaustMemoryAvailableForScript(blink::WebFrame* frame); + virtual void didCreateScriptContext(blink::WebFrame* frame, v8::Handle<v8::Context>, int extension_group, int world_id); - virtual void willReleaseScriptContext(WebKit::WebFrame* frame, + virtual void willReleaseScriptContext(blink::WebFrame* frame, v8::Handle<v8::Context>, int world_id); - virtual void didChangeScrollOffset(WebKit::WebFrame* frame); - virtual void willInsertBody(WebKit::WebFrame* frame); - virtual void didFirstVisuallyNonEmptyLayout(WebKit::WebFrame*); - virtual void didChangeContentsSize(WebKit::WebFrame* frame, - const WebKit::WebSize& size); + virtual void didChangeScrollOffset(blink::WebFrame* frame); + virtual void willInsertBody(blink::WebFrame* frame); + virtual void didFirstVisuallyNonEmptyLayout(blink::WebFrame*); + virtual void didChangeContentsSize(blink::WebFrame* frame, + const blink::WebSize& size); virtual void reportFindInPageMatchCount(int request_id, int count, bool final_update); virtual void reportFindInPageSelection(int request_id, int active_match_ordinal, - const WebKit::WebRect& sel); + const blink::WebRect& sel); virtual void requestStorageQuota( - WebKit::WebFrame* frame, - WebKit::WebStorageQuotaType type, + blink::WebFrame* frame, + blink::WebStorageQuotaType type, unsigned long long requested_size, - WebKit::WebStorageQuotaCallbacks* callbacks); + blink::WebStorageQuotaCallbacks* callbacks); virtual void willOpenSocketStream( - WebKit::WebSocketStreamHandle* handle); - virtual void willStartUsingPeerConnectionHandler(WebKit::WebFrame* frame, - WebKit::WebRTCPeerConnectionHandler* handler); + blink::WebSocketStreamHandle* handle); + virtual void willStartUsingPeerConnectionHandler(blink::WebFrame* frame, + blink::WebRTCPeerConnectionHandler* handler); virtual bool willCheckAndDispatchMessageEvent( - WebKit::WebFrame* sourceFrame, - WebKit::WebFrame* targetFrame, - WebKit::WebSecurityOrigin targetOrigin, - WebKit::WebDOMMessageEvent event); - virtual WebKit::WebString acceptLanguages(); - virtual WebKit::WebString userAgentOverride( - WebKit::WebFrame* frame, - const WebKit::WebURL& url); - virtual WebKit::WebString doNotTrackValue(WebKit::WebFrame* frame); - virtual bool allowWebGL(WebKit::WebFrame* frame, bool default_value); + blink::WebFrame* sourceFrame, + blink::WebFrame* targetFrame, + blink::WebSecurityOrigin targetOrigin, + blink::WebDOMMessageEvent event); + virtual blink::WebString acceptLanguages(); + virtual blink::WebString userAgentOverride( + blink::WebFrame* frame, + const blink::WebURL& url); + virtual blink::WebString doNotTrackValue(blink::WebFrame* frame); + virtual bool allowWebGL(blink::WebFrame* frame, bool default_value); virtual void didLoseWebGLContext( - WebKit::WebFrame* frame, + blink::WebFrame* frame, int arb_robustness_status_code); - // WebKit::WebPageSerializerClient implementation ---------------------------- + // blink::WebPageSerializerClient implementation ---------------------------- virtual void didSerializeDataForFrame( - const WebKit::WebURL& frame_url, - const WebKit::WebCString& data, + const blink::WebURL& frame_url, + const blink::WebCString& data, PageSerializationStatus status) OVERRIDE; // RenderView implementation ------------------------------------------------- virtual bool Send(IPC::Message* message) OVERRIDE; + virtual RenderFrame* GetMainRenderFrame() OVERRIDE; virtual int GetRoutingID() const OVERRIDE; virtual int GetPageId() const OVERRIDE; virtual gfx::Size GetSize() const OVERRIDE; virtual WebPreferences& GetWebkitPreferences() OVERRIDE; virtual void SetWebkitPreferences(const WebPreferences& preferences) OVERRIDE; - virtual WebKit::WebView* GetWebView() OVERRIDE; - virtual WebKit::WebNode GetFocusedNode() const OVERRIDE; - virtual WebKit::WebNode GetContextMenuNode() const OVERRIDE; - virtual bool IsEditableNode(const WebKit::WebNode& node) const OVERRIDE; - virtual WebKit::WebPlugin* CreatePlugin( - WebKit::WebFrame* frame, - const WebPluginInfo& info, - const WebKit::WebPluginParams& params) OVERRIDE; - virtual void EvaluateScript(const string16& frame_xpath, - const string16& jscript, + virtual blink::WebView* GetWebView() OVERRIDE; + virtual blink::WebNode GetFocusedNode() const OVERRIDE; + virtual blink::WebNode GetContextMenuNode() const OVERRIDE; + virtual bool IsEditableNode(const blink::WebNode& node) const OVERRIDE; + virtual void EvaluateScript(const base::string16& frame_xpath, + const base::string16& jscript, int id, bool notify_result) OVERRIDE; virtual bool ShouldDisplayScrollbars(int width, int height) const OVERRIDE; virtual int GetEnabledBindings() const OVERRIDE; virtual bool GetContentStateImmediately() const OVERRIDE; virtual float GetFilteredTimePerFrame() const OVERRIDE; - virtual int ShowContextMenu(ContextMenuClient* client, - const ContextMenuParams& params) OVERRIDE; - virtual void CancelContextMenu(int request_id) OVERRIDE; - virtual WebKit::WebPageVisibilityState GetVisibilityState() const OVERRIDE; - virtual void RunModalAlertDialog(WebKit::WebFrame* frame, - const WebKit::WebString& message) OVERRIDE; - virtual void LoadURLExternally( - WebKit::WebFrame* frame, - const WebKit::WebURLRequest& request, - WebKit::WebNavigationPolicy policy) OVERRIDE; + virtual blink::WebPageVisibilityState GetVisibilityState() const OVERRIDE; + virtual void RunModalAlertDialog(blink::WebFrame* frame, + const blink::WebString& message) OVERRIDE; virtual void DidStartLoading() OVERRIDE; virtual void DidStopLoading() OVERRIDE; virtual void Repaint(const gfx::Size& size) OVERRIDE; virtual void SetEditCommandForNextKeyEvent(const std::string& name, const std::string& value) OVERRIDE; virtual void ClearEditCommands() OVERRIDE; - virtual SSLStatus GetSSLStatusOfFrame(WebKit::WebFrame* frame) const OVERRIDE; + virtual SSLStatus GetSSLStatusOfFrame(blink::WebFrame* frame) const OVERRIDE; + virtual const std::string& GetAcceptLanguages() const OVERRIDE; #if defined(OS_ANDROID) virtual void UpdateTopControlsState(TopControlsState constraints, TopControlsState current, @@ -705,9 +676,9 @@ class CONTENT_EXPORT RenderViewImpl // WebMediaPlayerDelegate implementation ----------------------- - virtual void DidPlay(WebKit::WebMediaPlayer* player) OVERRIDE; - virtual void DidPause(WebKit::WebMediaPlayer* player) OVERRIDE; - virtual void PlayerGone(WebKit::WebMediaPlayer* player) OVERRIDE; + virtual void DidPlay(blink::WebMediaPlayer* player) OVERRIDE; + virtual void DidPause(blink::WebMediaPlayer* player) OVERRIDE; + virtual void PlayerGone(blink::WebMediaPlayer* player) OVERRIDE; // Please do not add your stuff randomly to the end here. If there is an // appropriate section, add it there. If not, there are some random functions @@ -722,7 +693,6 @@ class CONTENT_EXPORT RenderViewImpl // RenderWidget overrides: virtual void Close() OVERRIDE; virtual void OnResize(const ViewMsg_Resize_Params& params) OVERRIDE; - virtual void WillInitiatePaint() OVERRIDE; virtual void DidInitiatePaint() OVERRIDE; virtual void DidFlushPaint() OVERRIDE; virtual PepperPluginInstanceImpl* GetBitmapForOptimizedPluginPaint( @@ -734,13 +704,13 @@ class CONTENT_EXPORT RenderViewImpl virtual gfx::Vector2d GetScrollOffset() OVERRIDE; virtual void DidHandleKeyEvent() OVERRIDE; virtual bool WillHandleMouseEvent( - const WebKit::WebMouseEvent& event) OVERRIDE; + const blink::WebMouseEvent& event) OVERRIDE; virtual bool WillHandleKeyEvent( - const WebKit::WebKeyboardEvent& event) OVERRIDE; + const blink::WebKeyboardEvent& event) OVERRIDE; virtual bool WillHandleGestureEvent( - const WebKit::WebGestureEvent& event) OVERRIDE; - virtual void DidHandleMouseEvent(const WebKit::WebMouseEvent& event) OVERRIDE; - virtual void DidHandleTouchEvent(const WebKit::WebTouchEvent& event) OVERRIDE; + const blink::WebGestureEvent& event) OVERRIDE; + virtual void DidHandleMouseEvent(const blink::WebMouseEvent& event) OVERRIDE; + virtual void DidHandleTouchEvent(const blink::WebTouchEvent& event) OVERRIDE; virtual bool HasTouchEventHandlersAt(const gfx::Point& point) const OVERRIDE; virtual void OnSetFocus(bool enable) OVERRIDE; virtual void OnWasHidden() OVERRIDE; @@ -748,11 +718,11 @@ class CONTENT_EXPORT RenderViewImpl virtual GURL GetURLForGraphicsContext3D() OVERRIDE; virtual bool ForceCompositingModeEnabled() OVERRIDE; virtual void OnImeSetComposition( - const string16& text, - const std::vector<WebKit::WebCompositionUnderline>& underlines, + const base::string16& text, + const std::vector<blink::WebCompositionUnderline>& underlines, int selection_start, int selection_end) OVERRIDE; - virtual void OnImeConfirmComposition(const string16& text, + virtual void OnImeConfirmComposition(const base::string16& text, const gfx::Range& replacement_range, bool keep_selection) OVERRIDE; virtual void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE; @@ -765,7 +735,7 @@ class CONTENT_EXPORT RenderViewImpl #endif virtual bool CanComposeInline() OVERRIDE; virtual void DidCommitCompositorFrame() OVERRIDE; - virtual void InstrumentWillBeginFrame() OVERRIDE; + virtual void InstrumentWillBeginFrame(int frame_id) OVERRIDE; virtual void InstrumentDidBeginFrame() OVERRIDE; virtual void InstrumentDidCancelFrame() OVERRIDE; virtual void InstrumentWillComposite() OVERRIDE; @@ -775,6 +745,10 @@ class CONTENT_EXPORT RenderViewImpl explicit RenderViewImpl(RenderViewImplParams* params); void Initialize(RenderViewImplParams* params); + virtual void SetScreenMetricsEmulationParameters( + float device_scale_factor, + const gfx::Point& root_layer_offset, + float root_layer_scale) OVERRIDE; // Do not delete directly. This class is reference counted. virtual ~RenderViewImpl(); @@ -822,6 +796,8 @@ class CONTENT_EXPORT RenderViewImpl FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, GetCompositionCharacterBoundsTest); FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnNavigationHttpPost); + FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, + DecideNavigationPolicyHandlesAllTopLevel); #if defined(OS_MACOSX) FRIEND_TEST_ALL_PREFIXES(RenderViewTest, MacTestCmdUp); #endif @@ -832,6 +808,9 @@ class CONTENT_EXPORT RenderViewImpl ShouldUpdateSelectionTextFromContextMenuParams); FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, BasicRenderFrame); FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, TextInputTypeWithPepper); + FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, + MessageOrderInDidChangeSelection); + FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, SendCandidateWindowEvents); FRIEND_TEST_ALL_PREFIXES(SuppressErrorPageTest, Suppresses); FRIEND_TEST_ALL_PREFIXES(SuppressErrorPageTest, DoesNotSuppress); @@ -843,22 +822,22 @@ class CONTENT_EXPORT RenderViewImpl CONNECTION_ERROR, }; - static WebKit::WebReferrerPolicy GetReferrerPolicyFromRequest( - WebKit::WebFrame* frame, - const WebKit::WebURLRequest& request); + static blink::WebReferrerPolicy GetReferrerPolicyFromRequest( + blink::WebFrame* frame, + const blink::WebURLRequest& request); static Referrer GetReferrerFromRequest( - WebKit::WebFrame* frame, - const WebKit::WebURLRequest& request); + blink::WebFrame* frame, + const blink::WebURLRequest& request); static webkit_glue::WebURLResponseExtraDataImpl* GetExtraDataFromResponse( - const WebKit::WebURLResponse& response); + const blink::WebURLResponse& response); - void UpdateURL(WebKit::WebFrame* frame); - void UpdateTitle(WebKit::WebFrame* frame, const string16& title, - WebKit::WebTextDirection title_direction); - void UpdateSessionHistory(WebKit::WebFrame* frame); - void SendUpdateState(const WebKit::WebHistoryItem& item); + void UpdateURL(blink::WebFrame* frame); + void UpdateTitle(blink::WebFrame* frame, const base::string16& title, + blink::WebTextDirection title_direction); + void UpdateSessionHistory(blink::WebFrame* frame); + void SendUpdateState(const blink::WebHistoryItem& item); // Update current main frame's encoding and send it to browser window. // Since we want to let users see the right encoding info from menu @@ -873,25 +852,25 @@ class CONTENT_EXPORT RenderViewImpl // c) function:DidFinishDocumentLoadForFrame. When this function is // called, that means we have got whole html page. In here we should // finally get right encoding of page. - void UpdateEncoding(WebKit::WebFrame* frame, + void UpdateEncoding(blink::WebFrame* frame, const std::string& encoding_name); - void OpenURL(WebKit::WebFrame* frame, + void OpenURL(blink::WebFrame* frame, const GURL& url, const Referrer& referrer, - WebKit::WebNavigationPolicy policy); + blink::WebNavigationPolicy policy); bool RunJavaScriptMessage(JavaScriptMessageType type, - const string16& message, - const string16& default_value, + const base::string16& message, + const base::string16& default_value, const GURL& frame_url, - string16* result); + base::string16* result); // Sends a message and runs a nested message loop. bool SendAndRunNestedMessageLoop(IPC::SyncMessage* message); // Called when the "pinned to left/right edge" state needs to be updated. - void UpdateScrollState(WebKit::WebFrame* frame); + void UpdateScrollState(blink::WebFrame* frame); // IPC message handlers ------------------------------------------------------ // @@ -906,15 +885,14 @@ class CONTENT_EXPORT RenderViewImpl void OnPaste(); void OnPasteAndMatchStyle(); void OnRedo(); - void OnReplace(const string16& text); - void OnReplaceMisspelling(const string16& text); + void OnReplace(const base::string16& text); + void OnReplaceMisspelling(const base::string16& text); void OnScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect); void OnSelectAll(); void OnSelectRange(const gfx::Point& start, const gfx::Point& end); void OnSetEditCommandsForNextKeyEvent(const EditCommands& edit_commands); void OnUndo(); void OnUnselect(); - void OnAllowBindings(int enabled_bindings_flags); void OnAllowScriptToClose(bool script_can_close); void OnCancelDownload(int32 download_id); @@ -923,7 +901,7 @@ class CONTENT_EXPORT RenderViewImpl void OnContextMenuClosed(const CustomContextMenuContext& custom_context); void OnShowContextMenu(const gfx::Point& location); void OnCopyImageAt(int x, int y); - void OnCSSInsertRequest(const string16& frame_xpath, + void OnCSSInsertRequest(const base::string16& frame_xpath, const std::string& css); void OnCustomContextMenuAction(const CustomContextMenuContext& custom_context, unsigned action); @@ -934,7 +912,7 @@ class CONTENT_EXPORT RenderViewImpl void OnDragSourceEndedOrMoved(const gfx::Point& client_point, const gfx::Point& screen_point, bool ended, - WebKit::WebDragOperation drag_operation); + blink::WebDragOperation drag_operation); void OnDragSourceSystemDragEnded(); void OnDragTargetDrop(const gfx::Point& client_pt, const gfx::Point& screen_pt, @@ -942,12 +920,12 @@ class CONTENT_EXPORT RenderViewImpl void OnDragTargetDragEnter(const DropData& drop_data, const gfx::Point& client_pt, const gfx::Point& screen_pt, - WebKit::WebDragOperationsMask operations_allowed, + blink::WebDragOperationsMask operations_allowed, int key_modifiers); void OnDragTargetDragLeave(); void OnDragTargetDragOver(const gfx::Point& client_pt, const gfx::Point& screen_pt, - WebKit::WebDragOperationsMask operations_allowed, + blink::WebDragOperationsMask operations_allowed, int key_modifiers); void OnEnablePreferredSizeChangedMode(); void OnEnableAutoResize(const gfx::Size& min_size, const gfx::Size& max_size); @@ -957,28 +935,27 @@ class CONTENT_EXPORT RenderViewImpl void OnExtendSelectionAndDelete(int before, int after); void OnFileChooserResponse( const std::vector<ui::SelectedFileInfo>& files); - void OnFind(int request_id, const string16&, const WebKit::WebFindOptions&); + void OnFind(int request_id, + const base::string16&, + const blink::WebFindOptions&); void OnGetAllSavableResourceLinksForCurrentPage(const GURL& page_url); void OnGetSerializedHtmlDataForCurrentPageWithLocalLinks( const std::vector<GURL>& links, const std::vector<base::FilePath>& local_paths, const base::FilePath& local_directory_name); void OnMediaPlayerActionAt(const gfx::Point& location, - const WebKit::WebMediaPlayerAction& action); - - // Screen has rotated. 0 = default (portrait), 90 = one turn right, and so on. + const blink::WebMediaPlayerAction& action); void OnOrientationChangeEvent(int orientation); - void OnPluginActionAt(const gfx::Point& location, - const WebKit::WebPluginAction& action); + const blink::WebPluginAction& action); void OnMoveOrResizeStarted(); void OnNavigate(const ViewMsg_Navigate_Params& params); void OnPostMessageEvent(const ViewMsg_PostMessage_Params& params); void OnReleaseDisambiguationPopupDIB(TransportDIB::Handle dib_handle); void OnReloadFrame(); void OnResetPageEncodingToDefault(); - void OnScriptEvalRequest(const string16& frame_xpath, - const string16& jscript, + void OnScriptEvalRequest(const base::string16& frame_xpath, + const base::string16& jscript, int id, bool notify_result); void OnSetAccessibilityMode(AccessibilityMode new_mode); @@ -987,7 +964,7 @@ class CONTENT_EXPORT RenderViewImpl void OnSetBackground(const SkBitmap& background); void OnSetCompositionFromExistingText( int start, int end, - const std::vector<WebKit::WebCompositionUnderline>& underlines); + const std::vector<blink::WebCompositionUnderline>& underlines); void OnExitFullscreen(); void OnSetEditableSelectionOffsets(int start, int end); void OnSetHistoryLengthAndPrune(int history_length, int32 minimum_page_id); @@ -1000,21 +977,18 @@ class CONTENT_EXPORT RenderViewImpl void OnShouldClose(); void OnStop(); void OnStopFinding(StopFindAction action); + void OnSuppressDialogsUntilSwapOut(); void OnSwapOut(); void OnThemeChanged(); void OnUpdateTargetURLAck(); void OnUpdateTimezone(); void OnUpdateWebPreferences(const WebPreferences& prefs); - void OnZoom(PageZoom zoom); void OnZoomFactor(PageZoom zoom, int zoom_center_x, int zoom_center_y); - void OnEnableViewSourceMode(); - - void OnJavaBridgeInit(); - void OnDisownOpener(); - + void OnWindowSnapshotCompleted(const int snapshot_id, + const gfx::Size& size, const std::vector<unsigned char>& png); #if defined(OS_ANDROID) void OnActivateNearestFindResult(int request_id, float x, float y); void OnFindMatchRects(int current_version); @@ -1025,10 +999,11 @@ class CONTENT_EXPORT RenderViewImpl bool enable_showing, bool animate); void OnPauseVideo(); - + void OnExtractSmartClipData(const gfx::Rect& rect); #elif defined(OS_MACOSX) void OnCopyToFindPboard(); - void OnPluginImeCompositionCompleted(const string16& text, int plugin_id); + void OnPluginImeCompositionCompleted(const base::string16& text, + int plugin_id); void OnSelectPopupMenuItem(int selected_index); void OnSetInLiveResize(bool in_live_resize); void OnSetWindowVisibility(bool visible); @@ -1036,10 +1011,6 @@ class CONTENT_EXPORT RenderViewImpl const gfx::Rect& view_frame); #endif - void OnWindowSnapshotCompleted(const int snapshot_id, - const gfx::Size& size, const std::vector<unsigned char>& png); - - // Adding a new message handler? Please add it in alphabetical order above // and put it in the same position in the .cc file. @@ -1047,9 +1018,9 @@ class CONTENT_EXPORT RenderViewImpl void ZoomFactorHelper(PageZoom zoom, int zoom_center_x, int zoom_center_y, float scaling_increment); - void AltErrorPageFinished(WebKit::WebFrame* frame, - const WebKit::WebURLRequest& original_request, - const WebKit::WebURLError& original_error, + void AltErrorPageFinished(blink::WebFrame* frame, + const blink::WebURLRequest& original_request, + const blink::WebURLError& original_error, const std::string& html); // Check whether the preferred size has changed. @@ -1078,25 +1049,25 @@ class CONTENT_EXPORT RenderViewImpl ErrorPageType error_type); // Locates a sub frame with given xpath - WebKit::WebFrame* GetChildFrame(const string16& frame_xpath) const; + blink::WebFrame* GetChildFrame(const base::string16& frame_xpath) const; // Returns the URL being loaded by the given frame's request. - GURL GetLoadingUrl(WebKit::WebFrame* frame) const; + GURL GetLoadingUrl(blink::WebFrame* frame) const; // Should only be called if this object wraps a PluginDocument. - WebKit::WebPlugin* GetWebPluginFromPluginDocument(); + blink::WebPlugin* GetWebPluginFromPluginDocument(); // Returns true if the |params| navigation is to an entry that has been // cropped due to a recent navigation the browser did not know about. bool IsBackForwardToStaleEntry(const ViewMsg_Navigate_Params& params, bool is_reload); - bool MaybeLoadAlternateErrorPage(WebKit::WebFrame* frame, - const WebKit::WebURLError& error, + bool MaybeLoadAlternateErrorPage(blink::WebFrame* frame, + const blink::WebURLError& error, bool replace); // Make this RenderView show an empty, unscriptable page. - void NavigateToSwappedOutURL(WebKit::WebFrame* frame); + void NavigateToSwappedOutURL(blink::WebFrame* frame); // If we initiated a navigation, this function will populate |document_state| // with the navigation information saved in OnNavigate(). @@ -1113,20 +1084,30 @@ class CONTENT_EXPORT RenderViewImpl #if defined(OS_ANDROID) // Launch an Android content intent with the given URL. void LaunchAndroidContentIntent(const GURL& intent_url, size_t request_id); + + blink::WebMediaPlayer* CreateAndroidWebMediaPlayer( + blink::WebFrame* frame, + const blink::WebURL& url, + blink::WebMediaPlayerClient* client); #endif + blink::WebMediaPlayer* CreateWebMediaPlayerForMediaStream( + blink::WebFrame* frame, + const blink::WebURL& url, + blink::WebMediaPlayerClient* client); + // Sends a reply to the current find operation handling if it was a // synchronous find request. void SendFindReply(int request_id, int match_count, int ordinal, - const WebKit::WebRect& selection_rect, + const blink::WebRect& selection_rect, bool final_status_update); // Returns whether |params.selection_text| should be synchronized to the // browser before bringing up the context menu. Static for testing. static bool ShouldUpdateSelectionTextFromContextMenuParams( - const string16& selection_text, + const base::string16& selection_text, size_t selection_text_offset, const gfx::Range& selection_range, const ContextMenuParams& params); @@ -1161,6 +1142,31 @@ class CONTENT_EXPORT RenderViewImpl gfx::RectF ClientRectToPhysicalWindowRect(const gfx::RectF& rect) const; + // Helper for LatencyInfo construction. + int64 GetLatencyComponentId(); + + // RenderFrameImpl accessible state ------------------------------------------ + // The following section is the set of methods that RenderFrameImpl needs + // to access RenderViewImpl state. The set of state variables are page-level + // specific, so they don't belong in RenderFrameImpl and should remain in + // this object. + ObserverList<RenderViewObserver>& observers() { + return observers_; + } + + // TODO(nasko): Remove this method when we move to frame proxy objects, since + // the concept of swapped out will be eliminated. + void set_is_swapped_out(bool swapped_out) { + is_swapped_out_ = swapped_out; + } + + NavigationGesture navigation_gesture() { + return navigation_gesture_; + } + void set_navigation_gesture(NavigationGesture gesture) { + navigation_gesture_ = gesture; + } + // --------------------------------------------------------------------------- // ADDING NEW FUNCTIONS? Please keep private functions alphabetized and put // it in the same order in the .cc file as it was in the header. @@ -1215,6 +1221,11 @@ class CONTENT_EXPORT RenderViewImpl // decidePolicyForNavigation for details. bool opener_suppressed_; + // Whether we must stop creating nested message loops for modal dialogs until + // OnSwapOut is called. This is necessary because modal dialogs have a + // PageGroupLoadDeferrer on the stack that interferes with swapping out. + bool suppress_dialogs_until_swap_out_; + // Holds state pertaining to a navigation that we initiated. This is held by // the WebDataSource::ExtraData attribute. We use pending_navigation_state_ // as a temporary holder for the state until the WebDataSource corresponding @@ -1296,7 +1307,7 @@ class CONTENT_EXPORT RenderViewImpl // portion of this string that is the actual selected text starts at index // |selection_range_.GetMin() - selection_text_offset_| and has length // |selection_range_.length()|. - string16 selection_text_; + base::string16 selection_text_; // The offset corresponding to the start of |selection_text_| in the document. size_t selection_text_offset_; // Range over the document corresponding to the actual selected text (which @@ -1375,7 +1386,7 @@ class CONTENT_EXPORT RenderViewImpl // MediaStreamClient attached to this view; lazily initialized. MediaStreamClient* media_stream_client_; - WebKit::WebUserMediaClient* web_user_media_client_; + blink::WebUserMediaClient* web_user_media_client_; // MIDIClient attached to this view; lazily initialized. MIDIDispatcher* midi_dispatcher_; @@ -1389,9 +1400,6 @@ class CONTENT_EXPORT RenderViewImpl // AccessibilityModeOff. RendererAccessibility* renderer_accessibility_; - // Java Bridge dispatcher attached to this view; lazily initialized. - JavaBridgeDispatcher* java_bridge_dispatcher_; - // Mouse Lock dispatcher attached to this view. MouseLockDispatcher* mouse_lock_dispatcher_; @@ -1411,12 +1419,9 @@ class CONTENT_EXPORT RenderViewImpl typedef std::vector< linked_ptr<ContentDetector> > ContentDetectorList; ContentDetectorList content_detectors_; - // Proxy class for WebMediaPlayer to communicate with the real media player - // objects in browser process. - WebMediaPlayerProxyAndroid* media_player_proxy_; - - // The media player manager for managing all the media players on this view. - scoped_ptr<RendererMediaPlayerManager> media_player_manager_; + // The media player manager for managing all the media players on this view + // for communicating with the real media player objects in browser process. + RendererMediaPlayerManager* media_player_manager_; // A date/time picker object for date and time related input elements. scoped_ptr<RendererDateTimePicker> date_time_picker_client_; @@ -1435,20 +1440,18 @@ class CONTENT_EXPORT RenderViewImpl #endif #if defined(ENABLE_PLUGINS) - typedef std::set<PepperPluginInstanceImpl*> PepperPluginSet; - PepperPluginSet active_pepper_instances_; + // TODO(jam): these belong on RenderFrame, once the browser knows which frame + // is focused and sends the IPCs which use these to the correct frame. Until + // then, we must store these on RenderView as that's the one place that knows + // about all the RenderFrames for a page. // Whether or not the focus is on a PPAPI plugin PepperPluginInstanceImpl* focused_pepper_plugin_; - // Current text input composition text. Empty if no composition is in - // progress. - string16 pepper_composition_text_; - // The plugin instance that received the last mouse event. It is set to NULL // if the last mouse event went to elements other than Pepper plugins. - // |pepper_last_mouse_event_target_| is not owned by this class. We can know - // about when it is destroyed via InstanceDeleted(). + // |pepper_last_mouse_event_target_| is not owned by this class. We depend on + // the RenderFrameImpl to NULL it out when it destructs. PepperPluginInstanceImpl* pepper_last_mouse_event_target_; #endif @@ -1462,7 +1465,7 @@ class CONTENT_EXPORT RenderViewImpl std::deque< linked_ptr<PendingFileChooser> > file_chooser_completions_; // The current directory enumeration callback - std::map<int, WebKit::WebFileChooserCompletion*> enumeration_completions_; + std::map<int, blink::WebFileChooserCompletion*> enumeration_completions_; int enumeration_completion_id_; // Reports load progress to the browser. @@ -1481,7 +1484,7 @@ class CONTENT_EXPORT RenderViewImpl scoped_ptr<ExternalPopupMenu> external_popup_menu_; // The node that the context menu was pressed over. - WebKit::WebNode context_menu_node_; + blink::WebNode context_menu_node_; // All the registered observers. We expect this list to be small, so vector // is fine. @@ -1507,10 +1510,6 @@ class CONTENT_EXPORT RenderViewImpl // DOM automation bindings are enabled. scoped_ptr<DomAutomationController> dom_automation_controller_; - // Allows JS to read out a variety of internal various metrics. The JS object - // is only exposed when the stats collection bindings are enabled. - scoped_ptr<StatsCollectionController> stats_collection_controller_; - // This field stores drag/drop related info for the event that is currently // being handled. If the current event results in starting a drag/drop // session, this info is sent to the browser along with other drag/drop info. diff --git a/chromium/content/renderer/render_view_impl_android.cc b/chromium/content/renderer/render_view_impl_android.cc index 18f41a29ac6..679da548f91 100644 --- a/chromium/content/renderer/render_view_impl_android.cc +++ b/chromium/content/renderer/render_view_impl_android.cc @@ -7,7 +7,9 @@ #include "base/command_line.h" #include "base/message_loop/message_loop.h" #include "cc/trees/layer_tree_host.h" +#include "content/common/view_messages.h" #include "content/renderer/gpu/render_widget_compositor.h" +#include "third_party/WebKit/public/web/WebView.h" namespace content { @@ -51,7 +53,7 @@ void RenderViewImpl::UpdateTopControlsState(TopControlsState constraints, top_controls_constraints_ = constraints_cc; } -void RenderViewImpl::didScrollWithKeyboard(const WebKit::WebSize& delta) { +void RenderViewImpl::didScrollWithKeyboard(const blink::WebSize& delta) { if (delta.height == 0) return; if (compositor_) { @@ -62,4 +64,9 @@ void RenderViewImpl::didScrollWithKeyboard(const WebKit::WebSize& delta) { } } +void RenderViewImpl::OnExtractSmartClipData(const gfx::Rect& rect) { + Send(new ViewHostMsg_SmartClipDataExtracted( + routing_id_, webview()->getSmartClipData(rect))); +} + } // namespace content diff --git a/chromium/content/renderer/render_view_impl_params.cc b/chromium/content/renderer/render_view_impl_params.cc index 44c8353090b..0e77ea41aaa 100644 --- a/chromium/content/renderer/render_view_impl_params.cc +++ b/chromium/content/renderer/render_view_impl_params.cc @@ -14,12 +14,12 @@ RenderViewImplParams::RenderViewImplParams( int32 main_frame_routing_id, int32 surface_id, int64 session_storage_namespace_id, - const string16& frame_name, + const base::string16& frame_name, bool is_renderer_created, bool swapped_out, bool hidden, int32 next_page_id, - const WebKit::WebScreenInfo& screen_info, + const blink::WebScreenInfo& screen_info, AccessibilityMode accessibility_mode, bool allow_partial_swap) : opener_id(opener_id), diff --git a/chromium/content/renderer/render_view_impl_params.h b/chromium/content/renderer/render_view_impl_params.h index 07a4f41b494..5993f308999 100644 --- a/chromium/content/renderer/render_view_impl_params.h +++ b/chromium/content/renderer/render_view_impl_params.h @@ -13,7 +13,7 @@ struct WebPreferences; -namespace WebKit { +namespace blink { struct WebScreenInfo; } @@ -30,12 +30,12 @@ struct CONTENT_EXPORT RenderViewImplParams { int32 main_frame_routing_id, int32 surface_id, int64 session_storage_namespace_id, - const string16& frame_name, + const base::string16& frame_name, bool is_renderer_created, bool swapped_out, bool hidden, int32 next_page_id, - const WebKit::WebScreenInfo& screen_info, + const blink::WebScreenInfo& screen_info, AccessibilityMode accessibility_mode, bool allow_partial_swap); ~RenderViewImplParams(); @@ -47,12 +47,12 @@ struct CONTENT_EXPORT RenderViewImplParams { int32 main_frame_routing_id; int32 surface_id; int64 session_storage_namespace_id; - const string16& frame_name; + const base::string16& frame_name; bool is_renderer_created; bool swapped_out; bool hidden; int32 next_page_id; - const WebKit::WebScreenInfo& screen_info; + const blink::WebScreenInfo& screen_info; AccessibilityMode accessibility_mode; bool allow_partial_swap; }; diff --git a/chromium/content/renderer/render_view_linux.cc b/chromium/content/renderer/render_view_linux.cc index 01218adc97f..41f558c2085 100644 --- a/chromium/content/renderer/render_view_linux.cc +++ b/chromium/content/renderer/render_view_linux.cc @@ -7,7 +7,7 @@ #include "content/public/common/renderer_preferences.h" #include "third_party/WebKit/public/web/linux/WebFontRendering.h" -using WebKit::WebFontRendering; +using blink::WebFontRendering; namespace content { diff --git a/chromium/content/renderer/render_view_mouse_lock_dispatcher.cc b/chromium/content/renderer/render_view_mouse_lock_dispatcher.cc index 41d21b7bfc5..25b4ccc4ff2 100644 --- a/chromium/content/renderer/render_view_mouse_lock_dispatcher.cc +++ b/chromium/content/renderer/render_view_mouse_lock_dispatcher.cc @@ -11,7 +11,7 @@ #include "third_party/WebKit/public/web/WebView.h" #include "third_party/WebKit/public/web/WebWidget.h" -using WebKit::WebUserGestureIndicator; +using blink::WebUserGestureIndicator; namespace content { diff --git a/chromium/content/renderer/render_widget.cc b/chromium/content/renderer/render_widget.cc index dc4a9025a13..852e94e1c8b 100644 --- a/chromium/content/renderer/render_widget.cc +++ b/chromium/content/renderer/render_widget.cc @@ -16,44 +16,49 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "cc/base/switches.h" +#include "cc/debug/benchmark_instrumentation.h" #include "cc/output/output_surface.h" #include "cc/trees/layer_tree_host.h" #include "content/child/npapi/webplugin.h" #include "content/common/gpu/client/context_provider_command_buffer.h" #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" +#include "content/common/gpu/gpu_process_launch_causes.h" +#include "content/common/input/synthetic_gesture_packet.h" +#include "content/common/input/web_input_event_traits.h" #include "content/common/input_messages.h" #include "content/common/swapped_out_messages.h" #include "content/common/view_messages.h" #include "content/public/common/content_switches.h" #include "content/renderer/cursor_utils.h" +#include "content/renderer/external_popup_menu.h" #include "content/renderer/gpu/compositor_output_surface.h" #include "content/renderer/gpu/compositor_software_output_device.h" #include "content/renderer/gpu/delegated_compositor_output_surface.h" -#include "content/renderer/gpu/input_handler_manager.h" #include "content/renderer/gpu/mailbox_output_surface.h" #include "content/renderer/gpu/render_widget_compositor.h" #include "content/renderer/ime_event_guard.h" +#include "content/renderer/input/input_handler_manager.h" #include "content/renderer/pepper/pepper_plugin_instance_impl.h" #include "content/renderer/render_process.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/renderer_webkitplatformsupport_impl.h" +#include "content/renderer/resizing_mode_selector.h" #include "ipc/ipc_sync_message.h" #include "skia/ext/platform_canvas.h" +#include "third_party/WebKit/public/platform/WebCursorInfo.h" #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" -#include "third_party/WebKit/public/platform/WebPoint.h" #include "third_party/WebKit/public/platform/WebRect.h" +#include "third_party/WebKit/public/platform/WebScreenInfo.h" #include "third_party/WebKit/public/platform/WebSize.h" #include "third_party/WebKit/public/platform/WebString.h" -#include "third_party/WebKit/public/web/WebCursorInfo.h" #include "third_party/WebKit/public/web/WebHelperPlugin.h" #include "third_party/WebKit/public/web/WebPagePopup.h" #include "third_party/WebKit/public/web/WebPopupMenu.h" #include "third_party/WebKit/public/web/WebPopupMenuInfo.h" #include "third_party/WebKit/public/web/WebRange.h" -#include "third_party/WebKit/public/web/WebScreenInfo.h" #include "third_party/skia/include/core/SkShader.h" #include "ui/base/ui_base_switches.h" -#include "ui/gfx/point.h" +#include "ui/gfx/frame_time.h" #include "ui/gfx/rect_conversions.h" #include "ui/gfx/size_conversions.h" #include "ui/gfx/skia_util.h" @@ -74,72 +79,29 @@ #include "third_party/WebKit/public/web/WebWidget.h" -using WebKit::WebCompositionUnderline; -using WebKit::WebCursorInfo; -using WebKit::WebGestureEvent; -using WebKit::WebInputEvent; -using WebKit::WebKeyboardEvent; -using WebKit::WebMouseEvent; -using WebKit::WebNavigationPolicy; -using WebKit::WebPagePopup; -using WebKit::WebPoint; -using WebKit::WebPopupMenu; -using WebKit::WebPopupMenuInfo; -using WebKit::WebPopupType; -using WebKit::WebRange; -using WebKit::WebRect; -using WebKit::WebScreenInfo; -using WebKit::WebSize; -using WebKit::WebTextDirection; -using WebKit::WebTouchEvent; -using WebKit::WebVector; -using WebKit::WebWidget; +using blink::WebCompositionUnderline; +using blink::WebCursorInfo; +using blink::WebGestureEvent; +using blink::WebInputEvent; +using blink::WebKeyboardEvent; +using blink::WebMouseEvent; +using blink::WebMouseWheelEvent; +using blink::WebNavigationPolicy; +using blink::WebPagePopup; +using blink::WebPopupMenu; +using blink::WebPopupMenuInfo; +using blink::WebPopupType; +using blink::WebRange; +using blink::WebRect; +using blink::WebScreenInfo; +using blink::WebSize; +using blink::WebTextDirection; +using blink::WebTouchEvent; +using blink::WebTouchPoint; +using blink::WebVector; +using blink::WebWidget; namespace { -const char* GetEventName(WebInputEvent::Type type) { -#define CASE_TYPE(t) case WebInputEvent::t: return #t - switch(type) { - CASE_TYPE(Undefined); - CASE_TYPE(MouseDown); - CASE_TYPE(MouseUp); - CASE_TYPE(MouseMove); - CASE_TYPE(MouseEnter); - CASE_TYPE(MouseLeave); - CASE_TYPE(ContextMenu); - CASE_TYPE(MouseWheel); - CASE_TYPE(RawKeyDown); - CASE_TYPE(KeyDown); - CASE_TYPE(KeyUp); - CASE_TYPE(Char); - CASE_TYPE(GestureScrollBegin); - CASE_TYPE(GestureScrollEnd); - CASE_TYPE(GestureScrollUpdate); - CASE_TYPE(GestureFlingStart); - CASE_TYPE(GestureFlingCancel); - CASE_TYPE(GestureTap); - CASE_TYPE(GestureTapUnconfirmed); - CASE_TYPE(GestureTapDown); - CASE_TYPE(GestureTapCancel); - CASE_TYPE(GestureDoubleTap); - CASE_TYPE(GestureTwoFingerTap); - CASE_TYPE(GestureLongPress); - CASE_TYPE(GestureLongTap); - CASE_TYPE(GesturePinchBegin); - CASE_TYPE(GesturePinchEnd); - CASE_TYPE(GesturePinchUpdate); - CASE_TYPE(TouchStart); - CASE_TYPE(TouchMove); - CASE_TYPE(TouchEnd); - CASE_TYPE(TouchCancel); - default: - // Must include default to let WebKit::WebInputEvent add new event types - // before they're added here. - DLOG(WARNING) << "Unhandled WebInputEvent type in GetEventName.\n"; - break; - } -#undef CASE_TYPE - return ""; -} typedef std::map<std::string, ui::TextInputMode> TextInputModeMap; @@ -148,47 +110,229 @@ class TextInputModeMapSingleton { static TextInputModeMapSingleton* GetInstance() { return Singleton<TextInputModeMapSingleton>::get(); } - TextInputModeMapSingleton() - : map() { - map["verbatim"] = ui::TEXT_INPUT_MODE_VERBATIM; - map["latin"] = ui::TEXT_INPUT_MODE_LATIN; - map["latin-name"] = ui::TEXT_INPUT_MODE_LATIN_NAME; - map["latin-prose"] = ui::TEXT_INPUT_MODE_LATIN_PROSE; - map["full-width-latin"] = ui::TEXT_INPUT_MODE_FULL_WIDTH_LATIN; - map["kana"] = ui::TEXT_INPUT_MODE_KANA; - map["katakana"] = ui::TEXT_INPUT_MODE_KATAKANA; - map["numeric"] = ui::TEXT_INPUT_MODE_NUMERIC; - map["tel"] = ui::TEXT_INPUT_MODE_TEL; - map["email"] = ui::TEXT_INPUT_MODE_EMAIL; - map["url"] = ui::TEXT_INPUT_MODE_URL; - } - TextInputModeMap& Map() { - return map; - } + TextInputModeMapSingleton() { + map_["verbatim"] = ui::TEXT_INPUT_MODE_VERBATIM; + map_["latin"] = ui::TEXT_INPUT_MODE_LATIN; + map_["latin-name"] = ui::TEXT_INPUT_MODE_LATIN_NAME; + map_["latin-prose"] = ui::TEXT_INPUT_MODE_LATIN_PROSE; + map_["full-width-latin"] = ui::TEXT_INPUT_MODE_FULL_WIDTH_LATIN; + map_["kana"] = ui::TEXT_INPUT_MODE_KANA; + map_["katakana"] = ui::TEXT_INPUT_MODE_KATAKANA; + map_["numeric"] = ui::TEXT_INPUT_MODE_NUMERIC; + map_["tel"] = ui::TEXT_INPUT_MODE_TEL; + map_["email"] = ui::TEXT_INPUT_MODE_EMAIL; + map_["url"] = ui::TEXT_INPUT_MODE_URL; + } + const TextInputModeMap& map() const { return map_; } private: - TextInputModeMap map; + TextInputModeMap map_; friend struct DefaultSingletonTraits<TextInputModeMapSingleton>; DISALLOW_COPY_AND_ASSIGN(TextInputModeMapSingleton); }; -ui::TextInputMode ConvertInputMode( - const WebKit::WebString& input_mode) { +ui::TextInputMode ConvertInputMode(const blink::WebString& input_mode) { static TextInputModeMapSingleton* singleton = TextInputModeMapSingleton::GetInstance(); - TextInputModeMap::iterator it = singleton->Map().find(input_mode.utf8()); - if (it == singleton->Map().end()) + TextInputModeMap::const_iterator it = + singleton->map().find(input_mode.utf8()); + if (it == singleton->map().end()) return ui::TEXT_INPUT_MODE_DEFAULT; return it->second; } +// TODO(brianderson): Replace the hard-coded threshold with a fraction of +// the BeginMainFrame interval. +// 4166us will allow 1/4 of a 60Hz interval or 1/2 of a 120Hz interval to +// be spent in input hanlders before input starts getting throttled. +const int kInputHandlingTimeThrottlingThresholdMicroseconds = 4166; + } // namespace namespace content { -RenderWidget::RenderWidget(WebKit::WebPopupType popup_type, - const WebKit::WebScreenInfo& screen_info, +// RenderWidget::ScreenMetricsEmulator ---------------------------------------- + +class RenderWidget::ScreenMetricsEmulator { + public: + ScreenMetricsEmulator( + RenderWidget* widget, + const gfx::Rect& device_rect, + const gfx::Rect& widget_rect, + float device_scale_factor, + bool fit_to_view); + virtual ~ScreenMetricsEmulator(); + + float scale() { return scale_; } + gfx::Point offset() { return offset_; } + gfx::Rect widget_rect() const { return widget_rect_; } + gfx::Rect original_screen_rect() const { return original_view_screen_rect_; } + + void ChangeEmulationParams( + const gfx::Rect& device_rect, + const gfx::Rect& widget_rect, + float device_scale_factor, + bool fit_to_view); + + // The following methods alter handlers' behavior for messages related to + // widget size and position. + void OnResizeMessage(const ViewMsg_Resize_Params& params); + void OnUpdateScreenRectsMessage(const gfx::Rect& view_screen_rect, + const gfx::Rect& window_screen_rect); + void OnShowContextMenu(ContextMenuParams* params); + + private: + void Apply(float overdraw_bottom_height, + gfx::Rect resizer_rect, bool is_fullscreen); + + RenderWidget* widget_; + + // Parameters as passed by RenderWidget::EnableScreenMetricsEmulation. + gfx::Rect device_rect_; + gfx::Rect widget_rect_; + float device_scale_factor_; + bool fit_to_view_; + + // The computed scale and offset used to fit widget into browser window. + float scale_; + gfx::Point offset_; + + // Original values to restore back after emulation ends. + gfx::Size original_size_; + gfx::Size original_physical_backing_size_; + blink::WebScreenInfo original_screen_info_; + gfx::Rect original_view_screen_rect_; + gfx::Rect original_window_screen_rect_; +}; + +RenderWidget::ScreenMetricsEmulator::ScreenMetricsEmulator( + RenderWidget* widget, + const gfx::Rect& device_rect, + const gfx::Rect& widget_rect, + float device_scale_factor, + bool fit_to_view) + : widget_(widget), + device_rect_(device_rect), + widget_rect_(widget_rect), + device_scale_factor_(device_scale_factor), + fit_to_view_(fit_to_view), + scale_(1.f) { + original_size_ = widget_->size_; + original_physical_backing_size_ = widget_->physical_backing_size_; + original_screen_info_ = widget_->screen_info_; + original_view_screen_rect_ = widget_->view_screen_rect_; + original_window_screen_rect_ = widget_->window_screen_rect_; + Apply(widget_->overdraw_bottom_height_, + widget_->resizer_rect_, widget_->is_fullscreen_); +} + +RenderWidget::ScreenMetricsEmulator::~ScreenMetricsEmulator() { + widget_->screen_info_ = original_screen_info_; + + widget_->SetDeviceScaleFactor(original_screen_info_.deviceScaleFactor); + widget_->SetScreenMetricsEmulationParameters(0.f, gfx::Point(), 1.f); + widget_->view_screen_rect_ = original_view_screen_rect_; + widget_->window_screen_rect_ = original_window_screen_rect_; + widget_->Resize(original_size_, original_physical_backing_size_, + widget_->overdraw_bottom_height_, widget_->resizer_rect_, + widget_->is_fullscreen_, NO_RESIZE_ACK); +} + +void RenderWidget::ScreenMetricsEmulator::ChangeEmulationParams( + const gfx::Rect& device_rect, + const gfx::Rect& widget_rect, + float device_scale_factor, + bool fit_to_view) { + device_rect_ = device_rect; + widget_rect_ = widget_rect; + device_scale_factor_ = device_scale_factor; + fit_to_view_ = fit_to_view; + Apply(widget_->overdraw_bottom_height_, + widget_->resizer_rect_, widget_->is_fullscreen_); +} + +void RenderWidget::ScreenMetricsEmulator::Apply( + float overdraw_bottom_height, gfx::Rect resizer_rect, bool is_fullscreen) { + if (fit_to_view_) { + DCHECK(!original_size_.IsEmpty()); + + int width_with_gutter = + std::max(original_size_.width() - 2 * device_rect_.x(), 1); + int height_with_gutter = + std::max(original_size_.height() - 2 * device_rect_.y(), 1); + float width_ratio = + static_cast<float>(widget_rect_.width()) / width_with_gutter; + float height_ratio = + static_cast<float>(widget_rect_.height()) / height_with_gutter; + float ratio = std::max(1.0f, std::max(width_ratio, height_ratio)); + scale_ = 1.f / ratio; + } else { + scale_ = 1.f; + } + + // Center emulated view inside available view space. + offset_.set_x((original_size_.width() - scale_ * widget_rect_.width()) / 2); + offset_.set_y((original_size_.height() - scale_ * widget_rect_.height()) / 2); + + widget_->screen_info_.rect = gfx::Rect(device_rect_.size()); + widget_->screen_info_.availableRect = gfx::Rect(device_rect_.size()); + widget_->screen_info_.deviceScaleFactor = device_scale_factor_; + + // Pass three emulation parameters to the blink side: + // - we keep the real device scale factor in compositor to produce sharp image + // even when emulating different scale factor; + // - in order to fit into view, WebView applies offset and scale to the + // root layer. + widget_->SetScreenMetricsEmulationParameters( + original_screen_info_.deviceScaleFactor, offset_, scale_); + + widget_->SetDeviceScaleFactor(device_scale_factor_); + widget_->view_screen_rect_ = widget_rect_; + widget_->window_screen_rect_ = widget_->screen_info_.availableRect; + + gfx::Size physical_backing_size = gfx::ToCeiledSize(gfx::ScaleSize( + original_size_, original_screen_info_.deviceScaleFactor)); + widget_->Resize(widget_rect_.size(), physical_backing_size, + overdraw_bottom_height, resizer_rect, is_fullscreen, NO_RESIZE_ACK); +} + +void RenderWidget::ScreenMetricsEmulator::OnResizeMessage( + const ViewMsg_Resize_Params& params) { + bool need_ack = params.new_size != original_size_ && + !params.new_size.IsEmpty() && !params.physical_backing_size.IsEmpty(); + original_size_ = params.new_size; + original_physical_backing_size_ = params.physical_backing_size; + original_screen_info_ = params.screen_info; + Apply(params.overdraw_bottom_height, params.resizer_rect, + params.is_fullscreen); + + if (need_ack) { + widget_->set_next_paint_is_resize_ack(); + if (widget_->compositor_) + widget_->compositor_->SetNeedsRedrawRect(gfx::Rect(widget_->size_)); + } +} + +void RenderWidget::ScreenMetricsEmulator::OnUpdateScreenRectsMessage( + const gfx::Rect& view_screen_rect, + const gfx::Rect& window_screen_rect) { + original_view_screen_rect_ = view_screen_rect; + original_window_screen_rect_ = window_screen_rect; +} + +void RenderWidget::ScreenMetricsEmulator::OnShowContextMenu( + ContextMenuParams* params) { + params->x *= scale_; + params->x += offset_.x(); + params->y *= scale_; + params->y += offset_.y(); +} + +// RenderWidget --------------------------------------------------------------- + +RenderWidget::RenderWidget(blink::WebPopupType popup_type, + const blink::WebScreenInfo& screen_info, bool swapped_out, bool hidden) : routing_id_(MSG_ROUTING_NONE), @@ -212,6 +356,7 @@ RenderWidget::RenderWidget(WebKit::WebPopupType popup_type, has_focus_(false), handling_input_event_(false), handling_ime_event_(false), + handling_touchstart_event_(false), closing_(false), is_swapped_out_(swapped_out), input_method_is_active_(false), @@ -232,7 +377,8 @@ RenderWidget::RenderWidget(WebKit::WebPopupType popup_type, #if defined(OS_ANDROID) outstanding_ime_acks_(0), #endif - weak_ptr_factory_(this) { + popup_origin_scale_for_emulation_(0.f), + resizing_mode_selector_(new ResizingModeSelector()) { if (!swapped_out) RenderProcess::current()->AddRefProcess(); DCHECK(RenderThread::Get()); @@ -266,8 +412,8 @@ RenderWidget::~RenderWidget() { // static RenderWidget* RenderWidget::Create(int32 opener_id, - WebKit::WebPopupType popup_type, - const WebKit::WebScreenInfo& screen_info) { + blink::WebPopupType popup_type, + const blink::WebScreenInfo& screen_info) { DCHECK(opener_id != MSG_ROUTING_NONE); scoped_refptr<RenderWidget> widget( new RenderWidget(popup_type, screen_info, false, false)); @@ -280,15 +426,15 @@ RenderWidget* RenderWidget::Create(int32 opener_id, // static WebWidget* RenderWidget::CreateWebWidget(RenderWidget* render_widget) { switch (render_widget->popup_type_) { - case WebKit::WebPopupTypeNone: // Nothing to create. + case blink::WebPopupTypeNone: // Nothing to create. break; - case WebKit::WebPopupTypeSelect: - case WebKit::WebPopupTypeSuggestion: + case blink::WebPopupTypeSelect: + case blink::WebPopupTypeSuggestion: return WebPopupMenu::create(render_widget); - case WebKit::WebPopupTypePage: + case blink::WebPopupTypePage: return WebPagePopup::create(render_widget); - case WebKit::WebPopupTypeHelperPlugin: - return WebKit::WebHelperPlugin::create(render_widget); + case blink::WebPopupTypeHelperPlugin: + return blink::WebHelperPlugin::create(render_widget); default: NOTREACHED(); } @@ -370,6 +516,63 @@ bool RenderWidget::UsingSynchronousRendererCompositor() const { #endif } +void RenderWidget::EnableScreenMetricsEmulation( + const gfx::Rect& device_rect, + const gfx::Rect& widget_rect, + float device_scale_factor, + bool fit_to_view) { + if (!screen_metrics_emulator_) { + screen_metrics_emulator_.reset(new ScreenMetricsEmulator(this, + device_rect, widget_rect, device_scale_factor, fit_to_view)); + } else { + screen_metrics_emulator_->ChangeEmulationParams(device_rect, + widget_rect, device_scale_factor, fit_to_view); + } +} + +void RenderWidget::DisableScreenMetricsEmulation() { + screen_metrics_emulator_.reset(); +} + +void RenderWidget::SetPopupOriginAdjustmentsForEmulation( + ScreenMetricsEmulator* emulator) { + popup_origin_scale_for_emulation_ = emulator->scale(); + popup_view_origin_for_emulation_ = emulator->widget_rect().origin(); + popup_screen_origin_for_emulation_ = gfx::Point( + emulator->original_screen_rect().origin().x() + emulator->offset().x(), + emulator->original_screen_rect().origin().y() + emulator->offset().y()); +} + +void RenderWidget::SetScreenMetricsEmulationParameters( + float device_scale_factor, + const gfx::Point& root_layer_offset, + float root_layer_scale) { + // This is only supported in RenderView. + NOTREACHED(); +} + +void RenderWidget::SetExternalPopupOriginAdjustmentsForEmulation( + ExternalPopupMenu* popup, ScreenMetricsEmulator* emulator) { + popup->SetOriginScaleAndOffsetForEmulation( + emulator->scale(), emulator->offset()); +} + +void RenderWidget::OnShowHostContextMenu(ContextMenuParams* params) { + if (screen_metrics_emulator_) + screen_metrics_emulator_->OnShowContextMenu(params); +} + +void RenderWidget::ScheduleCompositeWithForcedRedraw() { + if (compositor_) { + // Regardless of whether threaded compositing is enabled, always + // use this mechanism to force the compositor to redraw. However, + // the invalidation code path below is still needed for the + // non-threaded case. + compositor_->SetNeedsForcedRedraw(); + } + scheduleComposite(); +} + bool RenderWidget::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(RenderWidget, message) @@ -378,6 +581,8 @@ bool RenderWidget::OnMessageReceived(const IPC::Message& message) { OnCursorVisibilityChange) IPC_MESSAGE_HANDLER(InputMsg_MouseCaptureLost, OnMouseCaptureLost) IPC_MESSAGE_HANDLER(InputMsg_SetFocus, OnSetFocus) + IPC_MESSAGE_HANDLER(InputMsg_SyntheticGestureCompleted, + OnSyntheticGestureCompleted) IPC_MESSAGE_HANDLER(ViewMsg_Close, OnClose) IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck) IPC_MESSAGE_HANDLER(ViewMsg_Resize, OnResize) @@ -386,20 +591,20 @@ bool RenderWidget::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewMsg_WasShown, OnWasShown) IPC_MESSAGE_HANDLER(ViewMsg_WasSwappedOut, OnWasSwappedOut) IPC_MESSAGE_HANDLER(ViewMsg_UpdateRect_ACK, OnUpdateRectAck) - IPC_MESSAGE_HANDLER(ViewMsg_SwapBuffers_ACK, - OnViewContextSwapBuffersComplete) + IPC_MESSAGE_HANDLER(ViewMsg_SwapBuffers_ACK, OnSwapBuffersComplete) IPC_MESSAGE_HANDLER(ViewMsg_SetInputMethodActive, OnSetInputMethodActive) + IPC_MESSAGE_HANDLER(ViewMsg_CandidateWindowShown, OnCandidateWindowShown) + IPC_MESSAGE_HANDLER(ViewMsg_CandidateWindowUpdated, + OnCandidateWindowUpdated) + IPC_MESSAGE_HANDLER(ViewMsg_CandidateWindowHidden, OnCandidateWindowHidden) IPC_MESSAGE_HANDLER(ViewMsg_ImeSetComposition, OnImeSetComposition) IPC_MESSAGE_HANDLER(ViewMsg_ImeConfirmComposition, OnImeConfirmComposition) IPC_MESSAGE_HANDLER(ViewMsg_PaintAtSize, OnPaintAtSize) IPC_MESSAGE_HANDLER(ViewMsg_Repaint, OnRepaint) - IPC_MESSAGE_HANDLER(ViewMsg_SyntheticGestureCompleted, - OnSyntheticGestureCompleted) IPC_MESSAGE_HANDLER(ViewMsg_SetTextDirection, OnSetTextDirection) IPC_MESSAGE_HANDLER(ViewMsg_Move_ACK, OnRequestMoveAck) IPC_MESSAGE_HANDLER(ViewMsg_UpdateScreenRects, OnUpdateScreenRects) #if defined(OS_ANDROID) - IPC_MESSAGE_HANDLER(ViewMsg_ImeBatchStateChanged, OnImeBatchStateChanged) IPC_MESSAGE_HANDLER(ViewMsg_ShowImeIfNeeded, OnShowImeIfNeeded) IPC_MESSAGE_HANDLER(ViewMsg_ImeEventAck, OnImeEventAck) #endif @@ -434,8 +639,7 @@ void RenderWidget::Resize(const gfx::Size& new_size, const gfx::Rect& resizer_rect, bool is_fullscreen, ResizeAck resize_ack) { - if (!RenderThreadImpl::current() || // Will be NULL during unit tests. - !RenderThreadImpl::current()->layout_test_mode()) { + if (resizing_mode_selector_->NeverUsesSynchronousResize()) { // A resize ack shouldn't be requested if we have not ACK'd the previous // one. DCHECK(resize_ack != SEND_RESIZE_ACK || !next_paint_is_resize_ack()); @@ -474,14 +678,12 @@ void RenderWidget::Resize(const gfx::Size& new_size, // send an ACK if we are resized to a non-empty rect. webwidget_->resize(new_size); - if (!RenderThreadImpl::current() || // Will be NULL during unit tests. - !RenderThreadImpl::current()->layout_test_mode()) { + if (resizing_mode_selector_->NeverUsesSynchronousResize()) { // Resize should have caused an invalidation of the entire view. DCHECK(new_size.IsEmpty() || is_accelerated_compositing_active_ || paint_aggregator_.HasPendingUpdate()); } - } else if (!RenderThreadImpl::current() || // Will be NULL during unit tests. - !RenderThreadImpl::current()->layout_test_mode()) { + } else if (!resizing_mode_selector_->is_synchronous_mode()) { resize_ack = NO_RESIZE_ACK; } @@ -503,6 +705,15 @@ void RenderWidget::Resize(const gfx::Size& new_size, DCHECK(resize_ack != SEND_RESIZE_ACK || next_paint_is_resize_ack()); } +void RenderWidget::ResizeSynchronously(const gfx::Rect& new_position) { + Resize(new_position.size(), new_position.size(), overdraw_bottom_height_, + gfx::Rect(), is_fullscreen_, NO_RESIZE_ACK); + view_screen_rect_ = new_position; + window_screen_rect_ = new_position; + if (!did_show_) + initial_pos_ = new_position; +} + void RenderWidget::OnClose() { if (closing_) return; @@ -533,6 +744,14 @@ void RenderWidget::OnCreatingNewAck() { } void RenderWidget::OnResize(const ViewMsg_Resize_Params& params) { + if (resizing_mode_selector_->ShouldAbortOnResize(this, params)) + return; + + if (screen_metrics_emulator_) { + screen_metrics_emulator_->OnResizeMessage(params); + return; + } + screen_info_ = params.screen_info; SetDeviceScaleFactor(screen_info_.deviceScaleFactor); Resize(params.new_size, params.physical_backing_size, @@ -586,6 +805,8 @@ void RenderWidget::OnWasShown(bool needs_repainting) { if (!is_accelerated_compositing_active_) { didInvalidateRect(gfx::Rect(size_.width(), size_.height())); } else { + if (compositor_) + compositor_->SetNeedsForcedRedraw(); scheduleComposite(); } } @@ -667,7 +888,7 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) { // be optimized to resolve directly into the IOSurface shared between the // GPU and browser processes. For these reasons and to avoid platform // disparities we explicitly disable antialiasing. - WebKit::WebGraphicsContext3D::Attributes attributes; + blink::WebGraphicsContext3D::Attributes attributes; attributes.antialias = false; attributes.shareResources = true; attributes.noAutomaticFlushes = true; @@ -675,9 +896,6 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) { attributes.stencil = false; const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - if (command_line.HasSwitch(cc::switches::kForceDirectLayerDrawing)) - attributes.stencil = true; - scoped_refptr<ContextProviderCommandBuffer> context_provider; if (!fallback) { context_provider = ContextProviderCommandBuffer::Create( @@ -736,7 +954,7 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) { use_swap_compositor_frame_message)); } -void RenderWidget::OnViewContextSwapBuffersAborted() { +void RenderWidget::OnSwapBuffersAborted() { TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersAborted"); while (!updates_pending_swap_.empty()) { ViewHostMsg_UpdateRect* msg = updates_pending_swap_.front(); @@ -752,7 +970,7 @@ void RenderWidget::OnViewContextSwapBuffersAborted() { scheduleComposite(); } -void RenderWidget::OnViewContextSwapBuffersPosted() { +void RenderWidget::OnSwapBuffersPosted() { TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersPosted"); if (using_asynchronous_swapbuffers_) { @@ -769,7 +987,7 @@ void RenderWidget::OnViewContextSwapBuffersPosted() { } } -void RenderWidget::OnViewContextSwapBuffersComplete() { +void RenderWidget::OnSwapBuffersComplete() { TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersComplete"); // Notify subclasses that composited rendering was flushed to the screen. @@ -819,8 +1037,8 @@ void RenderWidget::OnViewContextSwapBuffersComplete() { DoDeferredUpdateAndSendInputAck(); } -void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event, - const ui::LatencyInfo& latency_info, +void RenderWidget::OnHandleInputEvent(const blink::WebInputEvent* input_event, + ui::LatencyInfo latency_info, bool is_keyboard_shortcut) { handling_input_event_ = true; if (!input_event) { @@ -828,14 +1046,23 @@ void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event, return; } - const char* const event_name = GetEventName(input_event->type); + base::TimeTicks start_time; + if (base::TimeTicks::IsHighResNowFastAndReliable()) + start_time = base::TimeTicks::HighResNow(); + + const char* const event_name = + WebInputEventTraits::GetName(input_event->type); TRACE_EVENT1("renderer", "RenderWidget::OnHandleInputEvent", "event", event_name); - if (compositor_) - compositor_->SetLatencyInfo(latency_info); - else + scoped_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor; + + if (compositor_) { + latency_info_swap_promise_monitor = + compositor_->CreateLatencyInfoSwapPromiseMonitor(&latency_info).Pass(); + } else { latency_info_.MergeWith(latency_info); + } base::TimeDelta now = base::TimeDelta::FromInternalValue( base::TimeTicks::Now().ToInternalValue()); @@ -878,6 +1105,9 @@ void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event, input_event->type == WebInputEvent::GestureLongPress) resetInputMethod(); + if (input_event->type == WebInputEvent::TouchStart) + handling_touchstart_event_ = true; + bool processed = prevent_default; if (input_event->type != WebInputEvent::Char || !suppress_next_char_events_) { suppress_next_char_events_ = false; @@ -885,6 +1115,8 @@ void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event, processed = webwidget_->handleInputEvent(*input_event); } + handling_touchstart_event_ = false; + // If this RawKeyDown event corresponds to a browser keyboard shortcut and // it's not processed by webkit, then we need to suppress the upcoming Char // events. @@ -896,41 +1128,66 @@ void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event, if (!processed && input_event->type == WebInputEvent::TouchStart) { const WebTouchEvent& touch_event = *static_cast<const WebTouchEvent*>(input_event); - ack_result = HasTouchEventHandlersAt(touch_event.touches[0].position) ? - INPUT_EVENT_ACK_STATE_NOT_CONSUMED : - INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; + // Hit-test for all the pressed touch points. If there is a touch-handler + // for any of the touch points, then the renderer should continue to receive + // touch events. + ack_result = INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; + for (size_t i = 0; i < touch_event.touchesLength; ++i) { + if (touch_event.touches[i].state == WebTouchPoint::StatePressed && + HasTouchEventHandlersAt(touch_event.touches[i].position)) { + ack_result = INPUT_EVENT_ACK_STATE_NOT_CONSUMED; + break; + } + } } - IPC::Message* response = - new InputHostMsg_HandleInputEvent_ACK(routing_id_, - input_event->type, - ack_result, - latency_info); - bool event_type_gets_rate_limited = + bool event_type_can_be_rate_limited = input_event->type == WebInputEvent::MouseMove || input_event->type == WebInputEvent::MouseWheel || - WebInputEvent::isTouchEventType(input_event->type); + input_event->type == WebInputEvent::TouchMove; bool frame_pending = paint_aggregator_.HasPendingUpdate(); if (is_accelerated_compositing_active_) { frame_pending = compositor_ && - compositor_->commitRequested(); - } - - if (event_type_gets_rate_limited && frame_pending && !is_hidden_) { - // We want to rate limit the input events in this case, so we'll wait for - // painting to finish before ACKing this message. - if (pending_input_event_ack_) { - // As two different kinds of events could cause us to postpone an ack - // we send it now, if we have one pending. The Browser should never - // send us the same kind of event we are delaying the ack for. - Send(pending_input_event_ack_.release()); + compositor_->BeginMainFrameRequested(); + } + + // If we don't have a fast and accurate HighResNow, we assume the input + // handlers are heavy and rate limit them. + bool rate_limiting_wanted = true; + if (base::TimeTicks::IsHighResNowFastAndReliable()) { + base::TimeTicks end_time = base::TimeTicks::HighResNow(); + total_input_handling_time_this_frame_ += (end_time - start_time); + rate_limiting_wanted = + total_input_handling_time_this_frame_.InMicroseconds() > + kInputHandlingTimeThrottlingThresholdMicroseconds; + } + + if (!WebInputEventTraits::IgnoresAckDisposition(input_event->type)) { + scoped_ptr<IPC::Message> response( + new InputHostMsg_HandleInputEvent_ACK(routing_id_, + input_event->type, + ack_result, + latency_info)); + if (rate_limiting_wanted && event_type_can_be_rate_limited && + frame_pending && !is_hidden_) { + // We want to rate limit the input events in this case, so we'll wait for + // painting to finish before ACKing this message. + TRACE_EVENT_INSTANT0("renderer", + "RenderWidget::OnHandleInputEvent ack throttled", + TRACE_EVENT_SCOPE_THREAD); + if (pending_input_event_ack_) { + // As two different kinds of events could cause us to postpone an ack + // we send it now, if we have one pending. The Browser should never + // send us the same kind of event we are delaying the ack for. + Send(pending_input_event_ack_.release()); + } + pending_input_event_ack_ = response.Pass(); + if (compositor_) + compositor_->NotifyInputThrottledUntilCommit(); + } else { + Send(response.release()); } - pending_input_event_ack_.reset(response); - if (compositor_) - compositor_->NotifyInputThrottledUntilCommit(); - } else { - Send(response); } #if defined(OS_ANDROID) @@ -1175,11 +1432,15 @@ void RenderWidget::InvalidationCallback() { DoDeferredUpdateAndSendInputAck(); } -void RenderWidget::DoDeferredUpdateAndSendInputAck() { - DoDeferredUpdate(); - +void RenderWidget::FlushPendingInputEventAck() { if (pending_input_event_ack_) Send(pending_input_event_ack_.release()); + total_input_handling_time_this_frame_ = base::TimeDelta(); +} + +void RenderWidget::DoDeferredUpdateAndSendInputAck() { + DoDeferredUpdate(); + FlushPendingInputEventAck(); } void RenderWidget::DoDeferredUpdate() { @@ -1212,8 +1473,8 @@ void RenderWidget::DoDeferredUpdate() { } // Tracking of frame rate jitter - base::TimeTicks frame_begin_ticks = base::TimeTicks::Now(); - InstrumentWillBeginFrame(); + base::TimeTicks frame_begin_ticks = gfx::FrameTime::Now(); + InstrumentWillBeginFrame(0); AnimateIfNeeded(); // Layout may generate more invalidation. It may also enable the @@ -1271,9 +1532,9 @@ void RenderWidget::DoDeferredUpdate() { last_do_deferred_update_time_ = frame_begin_ticks; if (!is_accelerated_compositing_active_) { - legacy_software_mode_stats_->IncrementAnimationFrameCount(); - legacy_software_mode_stats_->IncrementScreenFrameCount(1, true); - legacy_software_mode_stats_->IssueTraceEventForMainThreadStats(); + legacy_software_mode_stats_->IncrementFrameCount(1, true); + cc::BenchmarkInstrumentation::IssueMainThreadRenderingStatsEvent( + legacy_software_mode_stats_->main_thread_rendering_stats()); legacy_software_mode_stats_->AccumulateAndClearMainThreadStats(); } @@ -1285,9 +1546,6 @@ void RenderWidget::DoDeferredUpdate() { gfx::Rect scroll_damage = update.GetScrollDamage(); gfx::Rect bounds = gfx::UnionRects(update.GetPaintBounds(), scroll_damage); - // Notify derived classes that we're about to initiate a paint. - WillInitiatePaint(); - // A plugin may be able to do an optimized paint. First check this, in which // case we can skip all of the bitmap generation and regular paint code. // This optimization allows PPAPI plugins that declare themselves on top of @@ -1404,8 +1662,7 @@ void RenderWidget::DoDeferredUpdate() { // UpdateReply message so we can receive another input event before the // UpdateRect_ACK on platforms where the UpdateRect_ACK is sent from within // the UpdateRect IPC message handler. - if (pending_input_event_ack_) - Send(pending_input_event_ack_.release()); + FlushPendingInputEventAck(); // If Composite() called SwapBuffers, pending_update_params_ will be reset (in // OnSwapBuffersPosted), meaning a message has been added to the @@ -1518,7 +1775,7 @@ void RenderWidget::didAutoResize(const WebSize& new_size) { // with invalid damage rects. paint_aggregator_.ClearPendingUpdate(); - if (RenderThreadImpl::current()->layout_test_mode()) { + if (resizing_mode_selector_->is_synchronous_mode()) { WebRect new_pos(rootWindowRect().x, rootWindowRect().y, new_size.width, @@ -1529,7 +1786,7 @@ void RenderWidget::didAutoResize(const WebSize& new_size) { AutoResizeCompositor(); - if (!RenderThreadImpl::current()->layout_test_mode()) + if (!resizing_mode_selector_->is_synchronous_mode()) need_update_rect_for_auto_resize_ = true; } } @@ -1598,7 +1855,7 @@ void RenderWidget::initializeLayerTreeView() { compositor_->setSurfaceReady(); } -WebKit::WebLayerTreeView* RenderWidget::layerTreeView() { +blink::WebLayerTreeView* RenderWidget::layerTreeView() { return compositor_.get(); } @@ -1620,14 +1877,11 @@ void RenderWidget::willBeginCompositorFrame() { UpdateTextInputState(false, true); #endif UpdateSelectionBounds(); - - WillInitiatePaint(); } void RenderWidget::didBecomeReadyForAdditionalInput() { TRACE_EVENT0("renderer", "RenderWidget::didBecomeReadyForAdditionalInput"); - if (pending_input_event_ack_) - Send(pending_input_event_ack_.release()); + FlushPendingInputEventAck(); } void RenderWidget::DidCommitCompositorFrame() { @@ -1674,7 +1928,7 @@ void RenderWidget::didCompleteSwapBuffers() { void RenderWidget::scheduleComposite() { if (RenderThreadImpl::current()->compositor_message_loop_proxy().get() && compositor_) { - compositor_->setNeedsRedraw(); + compositor_->setNeedsAnimate(); } else { // TODO(nduca): replace with something a little less hacky. The reason this // hack is still used is because the Invalidate-DoDeferredUpdate loop @@ -1732,14 +1986,6 @@ void RenderWidget::show(WebNavigationPolicy) { SetPendingWindowRect(initial_pos_); } -void RenderWidget::didProgrammaticallyScroll( - const WebKit::WebPoint& scroll_point) { - if (!compositor_) - return; - Send(new ViewHostMsg_DidProgrammaticallyScroll( - routing_id_, gfx::Vector2d(scroll_point.x, scroll_point.y))); -} - void RenderWidget::didFocus() { } @@ -1771,6 +2017,19 @@ void RenderWidget::closeWidgetSoon() { FROM_HERE, base::Bind(&RenderWidget::DoDeferredClose, this)); } +void RenderWidget::QueueSyntheticGesture( + scoped_ptr<SyntheticGestureParams> gesture_params, + const SyntheticGestureCompletionCallback& callback) { + DCHECK(!callback.is_null()); + + pending_synthetic_gesture_callbacks_.push(callback); + + SyntheticGesturePacket gesture_packet; + gesture_packet.set_gesture_params(gesture_params.Pass()); + + Send(new InputHostMsg_QueueSyntheticGesture(routing_id_, gesture_packet)); +} + void RenderWidget::Close() { if (webwidget_) { webwidget_->willCloseLayerTreeView(); @@ -1787,25 +2046,30 @@ WebRect RenderWidget::windowRect() { return view_screen_rect_; } -void RenderWidget::setToolTipText(const WebKit::WebString& text, +void RenderWidget::setToolTipText(const blink::WebString& text, WebTextDirection hint) { Send(new ViewHostMsg_SetTooltipText(routing_id_, text, hint)); } -void RenderWidget::setWindowRect(const WebRect& pos) { - if (did_show_) { - if (!RenderThreadImpl::current()->layout_test_mode()) { +void RenderWidget::setWindowRect(const WebRect& rect) { + WebRect pos = rect; + if (popup_origin_scale_for_emulation_) { + float scale = popup_origin_scale_for_emulation_; + pos.x = popup_screen_origin_for_emulation_.x() + + (pos.x - popup_view_origin_for_emulation_.x()) * scale; + pos.y = popup_screen_origin_for_emulation_.y() + + (pos.y - popup_view_origin_for_emulation_.y()) * scale; + } + + if (!resizing_mode_selector_->is_synchronous_mode()) { + if (did_show_) { Send(new ViewHostMsg_RequestMove(routing_id_, pos)); SetPendingWindowRect(pos); } else { - WebSize new_size(pos.width, pos.height); - Resize(new_size, new_size, overdraw_bottom_height_, - WebRect(), is_fullscreen_, NO_RESIZE_ACK); - view_screen_rect_ = pos; - window_screen_rect_ = pos; + initial_pos_ = pos; } } else { - initial_pos_ = pos; + ResizeSynchronously(pos); } } @@ -1838,8 +2102,20 @@ void RenderWidget::OnSetInputMethodActive(bool is_active) { input_method_is_active_ = is_active; } +void RenderWidget::OnCandidateWindowShown() { + webwidget_->didShowCandidateWindow(); +} + +void RenderWidget::OnCandidateWindowUpdated() { + webwidget_->didUpdateCandidateWindow(); +} + +void RenderWidget::OnCandidateWindowHidden() { + webwidget_->didHideCandidateWindow(); +} + void RenderWidget::OnImeSetComposition( - const string16& text, + const base::string16& text, const std::vector<WebCompositionUnderline>& underlines, int selection_start, int selection_end) { if (!ShouldHandleImeEvent()) @@ -1858,7 +2134,7 @@ void RenderWidget::OnImeSetComposition( #endif } -void RenderWidget::OnImeConfirmComposition(const string16& text, +void RenderWidget::OnImeConfirmComposition(const base::string16& text, const gfx::Range& replacement_range, bool keep_selection) { if (!ShouldHandleImeEvent()) @@ -2022,7 +2298,10 @@ void RenderWidget::OnRepaint(gfx::Size size_to_paint) { } void RenderWidget::OnSyntheticGestureCompleted() { - pending_synthetic_gesture_.Run(); + DCHECK(!pending_synthetic_gesture_callbacks_.empty()); + + pending_synthetic_gesture_callbacks_.front().Run(); + pending_synthetic_gesture_callbacks_.pop(); } void RenderWidget::OnSetTextDirection(WebTextDirection direction) { @@ -2033,16 +2312,17 @@ void RenderWidget::OnSetTextDirection(WebTextDirection direction) { void RenderWidget::OnUpdateScreenRects(const gfx::Rect& view_screen_rect, const gfx::Rect& window_screen_rect) { - view_screen_rect_ = view_screen_rect; - window_screen_rect_ = window_screen_rect; + if (screen_metrics_emulator_) { + screen_metrics_emulator_->OnUpdateScreenRectsMessage( + view_screen_rect, window_screen_rect); + } else { + view_screen_rect_ = view_screen_rect; + window_screen_rect_ = window_screen_rect; + } Send(new ViewHostMsg_UpdateScreenRects_ACK(routing_id())); } #if defined(OS_ANDROID) -void RenderWidget::OnImeBatchStateChanged(bool is_begin) { - Send(new ViewHostMsg_ImeBatchStateChanged_ACK(routing_id(), is_begin)); -} - void RenderWidget::OnShowImeIfNeeded() { UpdateTextInputState(true, true); } @@ -2182,8 +2462,16 @@ void RenderWidget::FinishHandlingImeEvent() { } void RenderWidget::UpdateTextInputType() { + // On Windows, not only an IME but also an on-screen keyboard relies on the + // latest TextInputType to optimize its layout and functionality. Thus + // |input_method_is_active_| is no longer an appropriate condition to suppress + // TextInputTypeChanged IPC on Windows. + // TODO(yukawa, yoichio): Consider to stop checking |input_method_is_active_| + // on other platforms as well as Windows if the overhead is acceptable. +#if !defined(OS_WIN) if (!input_method_is_active_) return; +#endif ui::TextInputType new_type = GetTextInputType(); if (IsDateTimeInput(new_type)) @@ -2191,7 +2479,7 @@ void RenderWidget::UpdateTextInputType() { bool new_can_compose_inline = CanComposeInline(); - WebKit::WebTextInputInfo new_info; + blink::WebTextInputInfo new_info; if (webwidget_) new_info = webwidget_->textInputInfo(); const ui::TextInputMode new_mode = ConvertInputMode(new_info.inputMode); @@ -2220,7 +2508,7 @@ void RenderWidget::UpdateTextInputState(bool show_ime_if_needed, if (IsDateTimeInput(new_type)) return; // Not considered as a text input field in WebKit/Chromium. - WebKit::WebTextInputInfo new_info; + blink::WebTextInputInfo new_info; if (webwidget_) new_info = webwidget_->textInputInfo(); @@ -2281,47 +2569,47 @@ void RenderWidget::UpdateSelectionBounds() { #endif } -// Check WebKit::WebTextInputType and ui::TextInputType is kept in sync. -COMPILE_ASSERT(int(WebKit::WebTextInputTypeNone) == \ +// Check blink::WebTextInputType and ui::TextInputType is kept in sync. +COMPILE_ASSERT(int(blink::WebTextInputTypeNone) == \ int(ui::TEXT_INPUT_TYPE_NONE), mismatching_enums); -COMPILE_ASSERT(int(WebKit::WebTextInputTypeText) == \ +COMPILE_ASSERT(int(blink::WebTextInputTypeText) == \ int(ui::TEXT_INPUT_TYPE_TEXT), mismatching_enums); -COMPILE_ASSERT(int(WebKit::WebTextInputTypePassword) == \ +COMPILE_ASSERT(int(blink::WebTextInputTypePassword) == \ int(ui::TEXT_INPUT_TYPE_PASSWORD), mismatching_enums); -COMPILE_ASSERT(int(WebKit::WebTextInputTypeSearch) == \ +COMPILE_ASSERT(int(blink::WebTextInputTypeSearch) == \ int(ui::TEXT_INPUT_TYPE_SEARCH), mismatching_enums); -COMPILE_ASSERT(int(WebKit::WebTextInputTypeEmail) == \ +COMPILE_ASSERT(int(blink::WebTextInputTypeEmail) == \ int(ui::TEXT_INPUT_TYPE_EMAIL), mismatching_enums); -COMPILE_ASSERT(int(WebKit::WebTextInputTypeNumber) == \ +COMPILE_ASSERT(int(blink::WebTextInputTypeNumber) == \ int(ui::TEXT_INPUT_TYPE_NUMBER), mismatching_enums); -COMPILE_ASSERT(int(WebKit::WebTextInputTypeTelephone) == \ +COMPILE_ASSERT(int(blink::WebTextInputTypeTelephone) == \ int(ui::TEXT_INPUT_TYPE_TELEPHONE), mismatching_enums); -COMPILE_ASSERT(int(WebKit::WebTextInputTypeURL) == \ +COMPILE_ASSERT(int(blink::WebTextInputTypeURL) == \ int(ui::TEXT_INPUT_TYPE_URL), mismatching_enums); -COMPILE_ASSERT(int(WebKit::WebTextInputTypeDate) == \ +COMPILE_ASSERT(int(blink::WebTextInputTypeDate) == \ int(ui::TEXT_INPUT_TYPE_DATE), mismatching_enum); -COMPILE_ASSERT(int(WebKit::WebTextInputTypeDateTime) == \ +COMPILE_ASSERT(int(blink::WebTextInputTypeDateTime) == \ int(ui::TEXT_INPUT_TYPE_DATE_TIME), mismatching_enum); -COMPILE_ASSERT(int(WebKit::WebTextInputTypeDateTimeLocal) == \ +COMPILE_ASSERT(int(blink::WebTextInputTypeDateTimeLocal) == \ int(ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL), mismatching_enum); -COMPILE_ASSERT(int(WebKit::WebTextInputTypeMonth) == \ +COMPILE_ASSERT(int(blink::WebTextInputTypeMonth) == \ int(ui::TEXT_INPUT_TYPE_MONTH), mismatching_enum); -COMPILE_ASSERT(int(WebKit::WebTextInputTypeTime) == \ +COMPILE_ASSERT(int(blink::WebTextInputTypeTime) == \ int(ui::TEXT_INPUT_TYPE_TIME), mismatching_enum); -COMPILE_ASSERT(int(WebKit::WebTextInputTypeWeek) == \ +COMPILE_ASSERT(int(blink::WebTextInputTypeWeek) == \ int(ui::TEXT_INPUT_TYPE_WEEK), mismatching_enum); -COMPILE_ASSERT(int(WebKit::WebTextInputTypeTextArea) == \ +COMPILE_ASSERT(int(blink::WebTextInputTypeTextArea) == \ int(ui::TEXT_INPUT_TYPE_TEXT_AREA), mismatching_enums); -COMPILE_ASSERT(int(WebKit::WebTextInputTypeContentEditable) == \ +COMPILE_ASSERT(int(blink::WebTextInputTypeContentEditable) == \ int(ui::TEXT_INPUT_TYPE_CONTENT_EDITABLE), mismatching_enums); -COMPILE_ASSERT(int(WebKit::WebTextInputTypeDateTimeField) == \ +COMPILE_ASSERT(int(blink::WebTextInputTypeDateTimeField) == \ int(ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD), mismatching_enums); ui::TextInputType RenderWidget::WebKitToUiTextInputType( - WebKit::WebTextInputType type) { + blink::WebTextInputType type) { // Check the type is in the range representable by ui::TextInputType. DCHECK_LE(type, static_cast<int>(ui::TEXT_INPUT_TYPE_MAX)) << - "WebKit::WebTextInputType and ui::TextInputType not synchronized"; + "blink::WebTextInputType and ui::TextInputType not synchronized"; return static_cast<ui::TextInputType>(type); } @@ -2456,7 +2744,7 @@ void RenderWidget::CleanupWindowInPluginMoves(gfx::PluginWindowHandle window) { } void RenderWidget::GetRenderingStats( - WebKit::WebRenderingStatsImpl& stats) const { + blink::WebRenderingStatsImpl& stats) const { if (compositor_) compositor_->GetRenderingStats(&stats.rendering_stats); @@ -2485,52 +2773,16 @@ void RenderWidget::GetBrowserRenderingStats(BrowserRenderingStats* stats) { *stats = browser_rendering_stats_; } -void RenderWidget::BeginSmoothScroll( - bool down, - const SyntheticGestureCompletionCallback& callback, - int pixels_to_scroll, - int mouse_event_x, - int mouse_event_y) { - DCHECK(!callback.is_null()); - - ViewHostMsg_BeginSmoothScroll_Params params; - params.scroll_down = down; - params.pixels_to_scroll = pixels_to_scroll; - params.mouse_event_x = mouse_event_x; - params.mouse_event_y = mouse_event_y; - - Send(new ViewHostMsg_BeginSmoothScroll(routing_id_, params)); - pending_synthetic_gesture_ = callback; -} - -void RenderWidget::BeginPinch( - bool zoom_in, - int pixels_to_move, - int anchor_x, - int anchor_y, - const SyntheticGestureCompletionCallback& callback) { - DCHECK(!callback.is_null()); - - ViewHostMsg_BeginPinch_Params params; - params.zoom_in = zoom_in; - params.pixels_to_move = pixels_to_move; - params.anchor_x = anchor_x; - params.anchor_y = anchor_y; - - Send(new ViewHostMsg_BeginPinch(routing_id_, params)); - pending_synthetic_gesture_ = callback; -} - -bool RenderWidget::WillHandleMouseEvent(const WebKit::WebMouseEvent& event) { +bool RenderWidget::WillHandleMouseEvent(const blink::WebMouseEvent& event) { return false; } -bool RenderWidget::WillHandleKeyEvent(const WebKit::WebKeyboardEvent& event) { +bool RenderWidget::WillHandleKeyEvent(const blink::WebKeyboardEvent& event) { return false; } bool RenderWidget::WillHandleGestureEvent( - const WebKit::WebGestureEvent& event) { + const blink::WebGestureEvent& event) { return false; } @@ -2538,25 +2790,50 @@ void RenderWidget::hasTouchEventHandlers(bool has_handlers) { Send(new ViewHostMsg_HasTouchEventHandlers(routing_id_, has_handlers)); } +void RenderWidget::setTouchAction( + blink::WebTouchAction web_touch_action) { + + // Ignore setTouchAction calls that result from synthetic touch events (eg. + // when blink is emulating touch with mouse). + if (!handling_touchstart_event_) + return; + + content::TouchAction content_touch_action; + switch(web_touch_action) { + case blink::WebTouchActionNone: + content_touch_action = content::TOUCH_ACTION_NONE; + break; + case blink::WebTouchActionAuto: + content_touch_action = content::TOUCH_ACTION_AUTO; + break; + default: + NOTREACHED(); + } + Send(new InputHostMsg_SetTouchAction(routing_id_, content_touch_action)); +} + bool RenderWidget::HasTouchEventHandlersAt(const gfx::Point& point) const { return true; } scoped_ptr<WebGraphicsContext3DCommandBufferImpl> RenderWidget::CreateGraphicsContext3D( - const WebKit::WebGraphicsContext3D::Attributes& attributes) { + const blink::WebGraphicsContext3D::Attributes& attributes) { if (!webwidget_) return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>(); if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableGpuCompositing)) return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>(); - scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context( - new WebGraphicsContext3DCommandBufferImpl( - surface_id(), - GetURLForGraphicsContext3D(), - RenderThreadImpl::current(), - weak_ptr_factory_.GetWeakPtr())); + if (!RenderThreadImpl::current()) + return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>(); + CauseForGpuLaunch cause = + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE; + scoped_refptr<GpuChannelHost> gpu_channel_host( + RenderThreadImpl::current()->EstablishGpuChannelSync(cause)); + if (!gpu_channel_host) + return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>(); + WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits; #if defined(OS_ANDROID) // If we raster too fast we become upload bound, and pending // uploads consume memory. For maximum upload throughput, we would @@ -2576,22 +2853,18 @@ RenderWidget::CreateGraphicsContext3D( static const size_t kBytesPerMegabyte = 1024 * 1024; // We keep the MappedMemoryReclaimLimit the same as the upload limit // to avoid unnecessarily stalling the compositor thread. - const size_t mapped_memory_reclaim_limit = + limits.mapped_memory_reclaim_limit = max_transfer_buffer_usage_mb * kBytesPerMegabyte; -#else - const size_t mapped_memory_reclaim_limit = - WebGraphicsContext3DCommandBufferImpl::kNoLimit; #endif - if (!context->Initialize( + + scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context( + new WebGraphicsContext3DCommandBufferImpl( + surface_id(), + GetURLForGraphicsContext3D(), + gpu_channel_host.get(), attributes, false /* bind generates resources */, - CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE, - kDefaultCommandBufferSize, - kDefaultStartTransferBufferSize, - kDefaultMinTransferBufferSize, - kDefaultMaxTransferBufferSize, - mapped_memory_reclaim_limit)) - return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>(); + limits)); return context.Pass(); } diff --git a/chromium/content/renderer/render_widget.h b/chromium/content/renderer/render_widget.h index d43934766c7..043d3aa3f01 100644 --- a/chromium/content/renderer/render_widget.h +++ b/chromium/content/renderer/render_widget.h @@ -12,13 +12,13 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "cc/debug/rendering_stats_instrumentation.h" #include "content/common/browser_rendering_stats.h" #include "content/common/content_export.h" #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" +#include "content/common/input/synthetic_gesture_params.h" #include "content/renderer/paint_aggregator.h" #include "ipc/ipc_listener.h" #include "ipc/ipc_sender.h" @@ -27,6 +27,7 @@ #include "third_party/WebKit/public/web/WebPopupType.h" #include "third_party/WebKit/public/web/WebTextDirection.h" #include "third_party/WebKit/public/web/WebTextInputInfo.h" +#include "third_party/WebKit/public/web/WebTouchAction.h" #include "third_party/WebKit/public/web/WebWidget.h" #include "third_party/WebKit/public/web/WebWidgetClient.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -48,13 +49,12 @@ namespace IPC { class SyncMessage; } -namespace WebKit { +namespace blink { class WebGestureEvent; class WebInputEvent; class WebKeyboardEvent; class WebMouseEvent; class WebTouchEvent; -struct WebPoint; struct WebRenderingStatsImpl; } @@ -65,9 +65,12 @@ class Range; } namespace content { +class ExternalPopupMenu; class PepperPluginInstanceImpl; class RenderWidgetCompositor; class RenderWidgetTest; +class ResizingModeSelector; +struct ContextMenuParams; struct GpuRenderingStats; struct WebPluginGeometry; @@ -76,18 +79,17 @@ struct WebPluginGeometry; class CONTENT_EXPORT RenderWidget : public IPC::Listener, public IPC::Sender, - NON_EXPORTED_BASE(virtual public WebKit::WebWidgetClient), - NON_EXPORTED_BASE(public WebGraphicsContext3DSwapBuffersClient), + NON_EXPORTED_BASE(virtual public blink::WebWidgetClient), public base::RefCounted<RenderWidget> { public: // Creates a new RenderWidget. The opener_id is the routing ID of the // RenderView that this widget lives inside. static RenderWidget* Create(int32 opener_id, - WebKit::WebPopupType popup_type, - const WebKit::WebScreenInfo& screen_info); + blink::WebPopupType popup_type, + const blink::WebScreenInfo& screen_info); // Creates a WebWidget based on the popup type. - static WebKit::WebWidget* CreateWebWidget(RenderWidget* render_widget); + static blink::WebWidget* CreateWebWidget(RenderWidget* render_widget); // The compositing surface assigned by the RenderWidgetHost // (or RenderViewHost). Will be gfx::kNullPluginWindow if not assigned yet, @@ -104,7 +106,7 @@ class CONTENT_EXPORT RenderWidget } // May return NULL when the window is closing. - WebKit::WebWidget* webwidget() const { return webwidget_; } + blink::WebWidget* webwidget() const { return webwidget_; } gfx::Size size() const { return size_; } bool has_focus() const { return has_focus_; } @@ -117,17 +119,17 @@ class CONTENT_EXPORT RenderWidget // IPC::Sender virtual bool Send(IPC::Message* msg) OVERRIDE; - // WebKit::WebWidgetClient + // blink::WebWidgetClient virtual void suppressCompositorScheduling(bool enable); virtual void willBeginCompositorFrame(); - virtual void didInvalidateRect(const WebKit::WebRect&); + virtual void didInvalidateRect(const blink::WebRect&); virtual void didScrollRect(int dx, int dy, - const WebKit::WebRect& clipRect); - virtual void didAutoResize(const WebKit::WebSize& new_size); + const blink::WebRect& clipRect); + virtual void didAutoResize(const blink::WebSize& new_size); virtual void didActivateCompositor(int input_handler_identifier); virtual void didDeactivateCompositor(); virtual void initializeLayerTreeView(); - virtual WebKit::WebLayerTreeView* layerTreeView(); + virtual blink::WebLayerTreeView* layerTreeView(); virtual void didBecomeReadyForAdditionalInput(); virtual void didCommitAndDrawCompositorFrame(); virtual void didCompleteSwapBuffers(); @@ -135,21 +137,20 @@ class CONTENT_EXPORT RenderWidget virtual void scheduleAnimation(); virtual void didFocus(); virtual void didBlur(); - virtual void didChangeCursor(const WebKit::WebCursorInfo&); + virtual void didChangeCursor(const blink::WebCursorInfo&); virtual void closeWidgetSoon(); - virtual void show(WebKit::WebNavigationPolicy); + virtual void show(blink::WebNavigationPolicy); virtual void runModal() {} - virtual void didProgrammaticallyScroll(const WebKit::WebPoint& scroll_point); - virtual WebKit::WebRect windowRect(); - virtual void setToolTipText(const WebKit::WebString& text, - WebKit::WebTextDirection hint); - virtual void setWindowRect(const WebKit::WebRect&); - virtual WebKit::WebRect windowResizerRect(); - virtual WebKit::WebRect rootWindowRect(); - virtual WebKit::WebScreenInfo screenInfo(); + virtual blink::WebRect windowRect(); + virtual void setToolTipText(const blink::WebString& text, + blink::WebTextDirection hint); + virtual void setWindowRect(const blink::WebRect&); + virtual blink::WebRect windowResizerRect(); + virtual blink::WebRect rootWindowRect(); + virtual blink::WebScreenInfo screenInfo(); virtual float deviceScaleFactor(); virtual void resetInputMethod(); - virtual void didHandleGestureEvent(const WebKit::WebGestureEvent& event, + virtual void didHandleGestureEvent(const blink::WebGestureEvent& event, bool event_cancelled); // Called when a plugin is moved. These events are queued up and sent with @@ -162,7 +163,7 @@ class CONTENT_EXPORT RenderWidget // Fills in a WebRenderingStatsImpl struct containing information about // rendering, e.g. count of frames rendered, time spent painting. - void GetRenderingStats(WebKit::WebRenderingStatsImpl&) const; + void GetRenderingStats(blink::WebRenderingStatsImpl&) const; // Fills in a GpuRenderingStats struct containing information about // GPU rendering, e.g. count of texture uploads performed, time spent @@ -179,25 +180,11 @@ class CONTENT_EXPORT RenderWidget // Callback for use with synthetic gestures (e.g. BeginSmoothScroll). typedef base::Callback<void()> SyntheticGestureCompletionCallback; - // Directs the host to begin a smooth scroll. This scroll should have the same - // performance characteristics as a user-initiated scroll. Returns an ID of - // the scroll gesture. |mouse_event_x| and |mouse_event_y| are expected to be - // in local DIP coordinates. - void BeginSmoothScroll(bool scroll_down, - const SyntheticGestureCompletionCallback& callback, - int pixels_to_scroll, - int mouse_event_x, - int mouse_event_y); - - // Directs the host to begin a pinch gesture. This gesture should have the - // same performance characteristics as a user-initiated pinch. - // |pixels_to_move|, |anchor_x| and |anchor_y| are expected to be in local - // DIP coordinates. - void BeginPinch(bool zoom_in, - int pixels_to_move, - int anchor_x, - int anchor_y, - const SyntheticGestureCompletionCallback& callback); + // Send a synthetic gesture to the browser to be queued to the synthetic + // gesture controller. + void QueueSyntheticGesture( + scoped_ptr<SyntheticGestureParams> gesture_params, + const SyntheticGestureCompletionCallback& callback); // Close the underlying WebWidget. virtual void Close(); @@ -213,7 +200,7 @@ class CONTENT_EXPORT RenderWidget void StartHandlingImeEvent(); void FinishHandlingImeEvent(); - virtual void InstrumentWillBeginFrame() {} + virtual void InstrumentWillBeginFrame(int frame_id) {} virtual void InstrumentDidBeginFrame() {} virtual void InstrumentDidCancelFrame() {} virtual void InstrumentWillComposite() {} @@ -223,6 +210,46 @@ class CONTENT_EXPORT RenderWidget bool is_swapped_out() { return is_swapped_out_; } + // ScreenMetricsEmulator class manages screen emulation inside a render + // widget. This includes resizing, placing view on the screen at desired + // position, changing device scale factor, and scaling down the whole + // widget if required to fit into the browser window. + class ScreenMetricsEmulator; + + // Emulates screen and widget metrics. Supplied values override everything + // coming from host. + void EnableScreenMetricsEmulation( + const gfx::Rect& device_rect, + const gfx::Rect& widget_rect, + float device_scale_factor, + bool fit_to_view); + void DisableScreenMetricsEmulation(); + void SetPopupOriginAdjustmentsForEmulation(ScreenMetricsEmulator* emulator); + + void ScheduleCompositeWithForcedRedraw(); + + // Called by the compositor in single-threaded mode when a swap is posted, + // completes or is aborted. + void OnSwapBuffersPosted(); + void OnSwapBuffersComplete(); + void OnSwapBuffersAborted(); + + // Checks if the text input state and compose inline mode have been changed. + // If they are changed, the new value will be sent to the browser process. + void UpdateTextInputType(); + + // Checks if the selection bounds have been changed. If they are changed, + // the new value will be sent to the browser process. + void UpdateSelectionBounds(); + + +#if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA) + // Checks if the composition range or composition character bounds have been + // changed. If they are changed, the new value will be sent to the browser + // process. + void UpdateCompositionInfo(bool should_update_range); +#endif + protected: // Friend RefCounted so that the dtor can be non-public. Using this class // without ref-counting is an error. @@ -235,8 +262,8 @@ class CONTENT_EXPORT RenderWidget NO_RESIZE_ACK, }; - RenderWidget(WebKit::WebPopupType popup_type, - const WebKit::WebScreenInfo& screen_info, + RenderWidget(blink::WebPopupType popup_type, + const blink::WebScreenInfo& screen_info, bool swapped_out, bool hidden); @@ -248,7 +275,7 @@ class CONTENT_EXPORT RenderWidget // Called by Init and subclasses to perform initialization. bool DoInit(int32 opener_id, - WebKit::WebWidget* web_widget, + blink::WebWidget* web_widget, IPC::SyncMessage* create_widget_message); // Finishes creation of a pending view started with Init. @@ -273,10 +300,11 @@ class CONTENT_EXPORT RenderWidget void AnimationCallback(); void AnimateIfNeeded(); void InvalidationCallback(); + void FlushPendingInputEventAck(); void DoDeferredUpdateAndSendInputAck(); void DoDeferredUpdate(); void DoDeferredClose(); - void DoDeferredSetWindowRect(const WebKit::WebRect& pos); + void DoDeferredSetWindowRect(const blink::WebRect& pos); virtual void Composite(base::TimeTicks frame_begin_time); // Set the background of the render widget to a bitmap. The bitmap will be @@ -291,10 +319,19 @@ class CONTENT_EXPORT RenderWidget const gfx::Rect& resizer_rect, bool is_fullscreen, ResizeAck resize_ack); + // Used to force the size of a window when running layout tests. + void ResizeSynchronously(const gfx::Rect& new_position); + virtual void SetScreenMetricsEmulationParameters( + float device_scale_factor, + const gfx::Point& root_layer_offset, + float root_layer_scale); + void SetExternalPopupOriginAdjustmentsForEmulation( + ExternalPopupMenu* popup, ScreenMetricsEmulator* emulator); + virtual void OnShowHostContextMenu(ContextMenuParams* params); // RenderWidget IPC message handlers - void OnHandleInputEvent(const WebKit::WebInputEvent* event, - const ui::LatencyInfo& latency_info, + void OnHandleInputEvent(const blink::WebInputEvent* event, + ui::LatencyInfo latency_info, bool keyboard_shortcut); void OnCursorVisibilityChange(bool is_visible); void OnMouseCaptureLost(); @@ -311,12 +348,15 @@ class CONTENT_EXPORT RenderWidget void OnUpdateVideoAck(int32 video_id); void OnRequestMoveAck(); void OnSetInputMethodActive(bool is_active); + void OnCandidateWindowShown(); + void OnCandidateWindowUpdated(); + void OnCandidateWindowHidden(); virtual void OnImeSetComposition( - const string16& text, - const std::vector<WebKit::WebCompositionUnderline>& underlines, + const base::string16& text, + const std::vector<blink::WebCompositionUnderline>& underlines, int selection_start, int selection_end); - virtual void OnImeConfirmComposition(const string16& text, + virtual void OnImeConfirmComposition(const base::string16& text, const gfx::Range& replacement_range, bool keep_selection); void OnPaintAtSize(const TransportDIB::Handle& dib_id, @@ -325,12 +365,11 @@ class CONTENT_EXPORT RenderWidget const gfx::Size& desired_size); void OnRepaint(gfx::Size size_to_paint); void OnSyntheticGestureCompleted(); - void OnSetTextDirection(WebKit::WebTextDirection direction); + void OnSetTextDirection(blink::WebTextDirection direction); void OnGetFPS(); void OnUpdateScreenRects(const gfx::Rect& view_screen_rect, const gfx::Rect& window_screen_rect); #if defined(OS_ANDROID) - void OnImeBatchStateChanged(bool is_begin); void OnShowImeIfNeeded(); // Whenever an IME event that needs an acknowledgement is sent to the browser, @@ -356,13 +395,11 @@ class CONTENT_EXPORT RenderWidget virtual void SetDeviceScaleFactor(float device_scale_factor); // Override points to notify derived classes that a paint has happened. - // WillInitiatePaint happens when we're about to generate a new bitmap and - // send it to the browser. DidInitiatePaint happens when that has completed, - // and subsequent rendering won't affect the painted content. DidFlushPaint - // happens once we've received the ACK that the screen has been updated. - // For a given paint operation, these overrides will always be called in the - // order WillInitiatePaint, DidInitiatePaint, DidFlushPaint. - virtual void WillInitiatePaint() {} + // DidInitiatePaint happens when that has completed, and subsequent rendering + // won't affect the painted content. DidFlushPaint happens once we've received + // the ACK that the screen has been updated. For a given paint operation, + // these overrides will always be called in the order DidInitiatePaint, + // DidFlushPaint. virtual void DidInitiatePaint() {} virtual void DidFlushPaint() {} @@ -376,14 +413,6 @@ class CONTENT_EXPORT RenderWidget virtual bool ForceCompositingModeEnabled(); - // WebGraphicsContext3DSwapBuffersClient implementation. - - // Called by a GraphicsContext associated with this view when swapbuffers - // is posted, completes or is aborted. - virtual void OnViewContextSwapBuffersPosted() OVERRIDE; - virtual void OnViewContextSwapBuffersComplete() OVERRIDE; - virtual void OnViewContextSwapBuffersAborted() OVERRIDE; - // Detects if a suitable opaque plugin covers the given paint bounds with no // compositing necessary. // @@ -419,10 +448,6 @@ class CONTENT_EXPORT RenderWidget void set_next_paint_is_restore_ack(); void set_next_paint_is_repaint_ack(); - // Checks if the text input state and compose inline mode have been changed. - // If they are changed, the new value will be sent to the browser process. - void UpdateTextInputType(); - #if defined(OS_ANDROID) // |show_ime_if_needed| should be true iff the update may cause the ime to be // displayed, e.g. after a tap on an input field on mobile. @@ -433,23 +458,14 @@ class CONTENT_EXPORT RenderWidget void UpdateTextInputState(bool show_ime_if_needed, bool send_ime_ack); #endif - // Checks if the selection bounds have been changed. If they are changed, - // the new value will be sent to the browser process. - virtual void UpdateSelectionBounds(); - // Override point to obtain that the current input method state and caret // position. virtual ui::TextInputType GetTextInputType(); virtual void GetSelectionBounds(gfx::Rect* start, gfx::Rect* end); virtual ui::TextInputType WebKitToUiTextInputType( - WebKit::WebTextInputType type); + blink::WebTextInputType type); #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA) - // Checks if the composition range or composition character bounds have been - // changed. If they are changed, the new value will be sent to the browser - // process. - void UpdateCompositionInfo(bool should_update_range); - // Override point to obtain that the current composition character bounds. // In the case of surrogate pairs, the character is treated as two characters: // the bounds for first character is actual one, and the bounds for second @@ -482,7 +498,7 @@ class CONTENT_EXPORT RenderWidget // been processed by the browser. So we maintain a pending window rect // size. If JS code sets the WindowRect, and then immediately calls // GetWindowRect() we'll use this pending window rect as the size. - void SetPendingWindowRect(const WebKit::WebRect& r); + void SetPendingWindowRect(const blink::WebRect& r); // Called by OnHandleInputEvent() to notify subclasses that a key event was // just handled. @@ -492,27 +508,27 @@ class CONTENT_EXPORT RenderWidget // about to be handled. // Returns true if no further handling is needed. In that case, the event // won't be sent to WebKit or trigger DidHandleMouseEvent(). - virtual bool WillHandleMouseEvent(const WebKit::WebMouseEvent& event); + virtual bool WillHandleMouseEvent(const blink::WebMouseEvent& event); // Called by OnHandleInputEvent() to notify subclasses that a key event is // about to be handled. // Returns true if no further handling is needed. In that case, the event // won't be sent to WebKit or trigger DidHandleKeyEvent(). - virtual bool WillHandleKeyEvent(const WebKit::WebKeyboardEvent& event); + virtual bool WillHandleKeyEvent(const blink::WebKeyboardEvent& event); // Called by OnHandleInputEvent() to notify subclasses that a gesture event is // about to be handled. // Returns true if no further handling is needed. In that case, the event // won't be sent to WebKit. - virtual bool WillHandleGestureEvent(const WebKit::WebGestureEvent& event); + virtual bool WillHandleGestureEvent(const blink::WebGestureEvent& event); // Called by OnHandleInputEvent() to notify subclasses that a mouse event was // just handled. - virtual void DidHandleMouseEvent(const WebKit::WebMouseEvent& event) {} + virtual void DidHandleMouseEvent(const blink::WebMouseEvent& event) {} // Called by OnHandleInputEvent() to notify subclasses that a touch event was // just handled. - virtual void DidHandleTouchEvent(const WebKit::WebTouchEvent& event) {} + virtual void DidHandleTouchEvent(const blink::WebTouchEvent& event) {} // Check whether the WebWidget has any touch event handlers registered // at the given point. @@ -521,9 +537,12 @@ class CONTENT_EXPORT RenderWidget // Check whether the WebWidget has any touch event handlers registered. virtual void hasTouchEventHandlers(bool has_handlers); + // Tell the browser about the actions permitted for a new touch point. + virtual void setTouchAction(blink::WebTouchAction touch_action); + // Creates a 3D context associated with this view. scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateGraphicsContext3D( - const WebKit::WebGraphicsContext3D::Attributes& attributes); + const blink::WebGraphicsContext3D::Attributes& attributes); bool OnSnapshotHelper(const gfx::Rect& src_subrect, SkBitmap* bitmap); @@ -534,7 +553,7 @@ class CONTENT_EXPORT RenderWidget int32 surface_id_; // We are responsible for destroying this object via its Close method. - WebKit::WebWidget* webwidget_; + blink::WebWidget* webwidget_; // This is lazily constructed and must not outlive webwidget_. scoped_ptr<RenderWidgetCompositor> compositor_; @@ -633,6 +652,9 @@ class CONTENT_EXPORT RenderWidget // Are we currently handling an ime event? bool handling_ime_event_; + // Are we currently handling a touchstart event? + bool handling_touchstart_event_; + // True if we have requested this widget be closed. No more messages will // be sent, except for a Close. bool closing_; @@ -646,7 +668,7 @@ class CONTENT_EXPORT RenderWidget bool input_method_is_active_; // Stores information about the current text input. - WebKit::WebTextInputInfo text_input_info_; + blink::WebTextInputInfo text_input_info_; // Stores the current text input type of |webwidget_|. ui::TextInputType text_input_type_; @@ -668,7 +690,7 @@ class CONTENT_EXPORT RenderWidget gfx::Range composition_range_; // The kind of popup this widget represents, NONE if not a popup. - WebKit::WebPopupType popup_type_; + blink::WebPopupType popup_type_; // Holds all the needed plugin window moves for a scroll. typedef std::vector<WebPluginGeometry> WebPluginGeometryVector; @@ -680,7 +702,7 @@ class CONTENT_EXPORT RenderWidget // While we are waiting for the browser to update window sizes, we track the // pending size temporarily. int pending_window_rect_count_; - WebKit::WebRect pending_window_rect_; + blink::WebRect pending_window_rect_; // The screen rects of the view and the window that contains it. gfx::Rect view_screen_rect_; @@ -688,6 +710,9 @@ class CONTENT_EXPORT RenderWidget scoped_ptr<IPC::Message> pending_input_event_ack_; + // The time spent in input handlers this frame. Used to throttle input acks. + base::TimeDelta total_input_handling_time_this_frame_; + // Indicates if the next sequence of Char events should be suppressed or not. bool suppress_next_char_events_; @@ -723,15 +748,17 @@ class CONTENT_EXPORT RenderWidget std::deque<ViewHostMsg_UpdateRect*> updates_pending_swap_; // Properties of the screen hosting this RenderWidget instance. - WebKit::WebScreenInfo screen_info_; + blink::WebScreenInfo screen_info_; // The device scale factor. This value is computed from the DPI entries in // |screen_info_| on some platforms, and defaults to 1 on other platforms. float device_scale_factor_; - // State associated with the synthetic gestures function - // (e.g. BeginSmoothScroll). - SyntheticGestureCompletionCallback pending_synthetic_gesture_; + // State associated with synthetic gestures. Synthetic gestures are processed + // in-order, so a queue is sufficient to identify the correct state for a + // completed gesture. + std::queue<SyntheticGestureCompletionCallback> + pending_synthetic_gesture_callbacks_; // Specified whether the compositor will run in its own thread. bool is_threaded_compositing_enabled_; @@ -753,7 +780,15 @@ class CONTENT_EXPORT RenderWidget int outstanding_ime_acks_; #endif - base::WeakPtrFactory<RenderWidget> weak_ptr_factory_; + scoped_ptr<ScreenMetricsEmulator> screen_metrics_emulator_; + + // Popups may be displaced when screen metrics emulation is enabled. + // These values are used to properly adjust popup position. + gfx::Point popup_view_origin_for_emulation_; + gfx::Point popup_screen_origin_for_emulation_; + float popup_origin_scale_for_emulation_; + + scoped_ptr<ResizingModeSelector> resizing_mode_selector_; DISALLOW_COPY_AND_ASSIGN(RenderWidget); }; diff --git a/chromium/content/renderer/render_widget_fullscreen.cc b/chromium/content/renderer/render_widget_fullscreen.cc index 5798285de6c..d6650aeb267 100644 --- a/chromium/content/renderer/render_widget_fullscreen.cc +++ b/chromium/content/renderer/render_widget_fullscreen.cc @@ -7,11 +7,11 @@ #include "content/common/view_messages.h" #include "third_party/WebKit/public/web/WebWidget.h" -using WebKit::WebWidget; +using blink::WebWidget; namespace content { -void RenderWidgetFullscreen::show(WebKit::WebNavigationPolicy) { +void RenderWidgetFullscreen::show(blink::WebNavigationPolicy) { DCHECK(!did_show_) << "received extraneous Show call"; DCHECK_NE(MSG_ROUTING_NONE, routing_id_); DCHECK_NE(MSG_ROUTING_NONE, opener_id_); @@ -24,8 +24,8 @@ void RenderWidgetFullscreen::show(WebKit::WebNavigationPolicy) { } RenderWidgetFullscreen::RenderWidgetFullscreen( - const WebKit::WebScreenInfo& screen_info) - : RenderWidget(WebKit::WebPopupTypeNone, screen_info, false, false) { + const blink::WebScreenInfo& screen_info) + : RenderWidget(blink::WebPopupTypeNone, screen_info, false, false) { } RenderWidgetFullscreen::~RenderWidgetFullscreen() {} diff --git a/chromium/content/renderer/render_widget_fullscreen.h b/chromium/content/renderer/render_widget_fullscreen.h index 9978fd2bf84..4b65b887809 100644 --- a/chromium/content/renderer/render_widget_fullscreen.h +++ b/chromium/content/renderer/render_widget_fullscreen.h @@ -14,13 +14,13 @@ namespace content { // TODO(boliu): Override non-supported methods with no-op? eg setWindowRect(). class RenderWidgetFullscreen : public RenderWidget { public: - virtual void show(WebKit::WebNavigationPolicy); + virtual void show(blink::WebNavigationPolicy); protected: - RenderWidgetFullscreen(const WebKit::WebScreenInfo& screen_info); + RenderWidgetFullscreen(const blink::WebScreenInfo& screen_info); virtual ~RenderWidgetFullscreen(); - virtual WebKit::WebWidget* CreateWebWidget(); + virtual blink::WebWidget* CreateWebWidget(); bool Init(int32 opener_id); }; diff --git a/chromium/content/renderer/render_widget_fullscreen_pepper.cc b/chromium/content/renderer/render_widget_fullscreen_pepper.cc index 751268ea4c4..dc222523bb8 100644 --- a/chromium/content/renderer/render_widget_fullscreen_pepper.cc +++ b/chromium/content/renderer/render_widget_fullscreen_pepper.cc @@ -19,38 +19,35 @@ #include "gpu/command_buffer/client/gles2_implementation.h" #include "skia/ext/platform_canvas.h" #include "third_party/WebKit/public/platform/WebCanvas.h" +#include "third_party/WebKit/public/platform/WebCursorInfo.h" #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" #include "third_party/WebKit/public/platform/WebLayer.h" #include "third_party/WebKit/public/platform/WebSize.h" -#include "third_party/WebKit/public/web/WebCursorInfo.h" #include "third_party/WebKit/public/web/WebWidget.h" #include "ui/gfx/size_conversions.h" #include "ui/gl/gpu_preference.h" -using WebKit::WebCanvas; -using WebKit::WebCompositionUnderline; -using WebKit::WebCursorInfo; -using WebKit::WebGestureEvent; -using WebKit::WebInputEvent; -using WebKit::WebMouseEvent; -using WebKit::WebMouseWheelEvent; -using WebKit::WebPoint; -using WebKit::WebRect; -using WebKit::WebSize; -using WebKit::WebString; -using WebKit::WebTextDirection; -using WebKit::WebTextInputType; -using WebKit::WebVector; -using WebKit::WebWidget; -using WebKit::WGC3Dintptr; +using blink::WebCanvas; +using blink::WebCompositionUnderline; +using blink::WebCursorInfo; +using blink::WebGestureEvent; +using blink::WebInputEvent; +using blink::WebMouseEvent; +using blink::WebMouseWheelEvent; +using blink::WebPoint; +using blink::WebRect; +using blink::WebSize; +using blink::WebString; +using blink::WebTextDirection; +using blink::WebTextInputType; +using blink::WebVector; +using blink::WebWidget; +using blink::WGC3Dintptr; namespace content { namespace { -// See third_party/WebKit/Source/WebCore/dom/WheelEvent.h. -const float kTickDivisor = 120.0f; - class FullscreenMouseLockDispatcher : public MouseLockDispatcher { public: explicit FullscreenMouseLockDispatcher(RenderWidgetFullscreenPepper* widget); @@ -312,7 +309,7 @@ class PepperWidget : public WebWidget { } virtual WebTextInputType textInputType() { - return WebKit::WebTextInputTypeNone; + return blink::WebTextInputTypeNone; } virtual WebRect caretOrSelectionBounds() { @@ -348,7 +345,7 @@ RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create( int32 opener_id, PepperPluginInstanceImpl* plugin, const GURL& active_url, - const WebKit::WebScreenInfo& screen_info) { + const blink::WebScreenInfo& screen_info) { DCHECK_NE(MSG_ROUTING_NONE, opener_id); scoped_refptr<RenderWidgetFullscreenPepper> widget( new RenderWidgetFullscreenPepper(plugin, active_url, screen_info)); @@ -360,7 +357,7 @@ RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create( RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper( PepperPluginInstanceImpl* plugin, const GURL& active_url, - const WebKit::WebScreenInfo& screen_info) + const blink::WebScreenInfo& screen_info) : RenderWidgetFullscreen(screen_info), active_url_(active_url), plugin_(plugin), @@ -376,12 +373,12 @@ void RenderWidgetFullscreenPepper::Invalidate() { InvalidateRect(gfx::Rect(size_.width(), size_.height())); } -void RenderWidgetFullscreenPepper::InvalidateRect(const WebKit::WebRect& rect) { +void RenderWidgetFullscreenPepper::InvalidateRect(const blink::WebRect& rect) { didInvalidateRect(rect); } void RenderWidgetFullscreenPepper::ScrollRect( - int dx, int dy, const WebKit::WebRect& rect) { + int dx, int dy, const blink::WebRect& rect) { didScrollRect(dx, dy, rect); } @@ -400,19 +397,20 @@ void RenderWidgetFullscreenPepper::Destroy() { } void RenderWidgetFullscreenPepper::DidChangeCursor( - const WebKit::WebCursorInfo& cursor) { + const blink::WebCursorInfo& cursor) { didChangeCursor(cursor); } -void RenderWidgetFullscreenPepper::SetLayer(WebKit::WebLayer* layer) { +void RenderWidgetFullscreenPepper::SetLayer(blink::WebLayer* layer) { layer_ = layer; bool compositing = !!layer_; if (compositing != is_accelerated_compositing_active_) { if (compositing) { - initializeLayerTreeView(); + if (!layerTreeView()) + initializeLayerTreeView(); if (!layerTreeView()) return; - layer_->setBounds(WebKit::WebSize(size())); + layer_->setBounds(blink::WebSize(size())); layer_->setDrawsContent(true); compositor_->setDeviceScaleFactor(device_scale_factor_); compositor_->setRootLayer(*layer_); @@ -440,11 +438,6 @@ bool RenderWidgetFullscreenPepper::OnMessageReceived(const IPC::Message& msg) { return RenderWidgetFullscreen::OnMessageReceived(msg); } -void RenderWidgetFullscreenPepper::WillInitiatePaint() { - if (plugin_) - plugin_->ViewWillInitiatePaint(); -} - void RenderWidgetFullscreenPepper::DidInitiatePaint() { if (plugin_) plugin_->ViewInitiatedPaint(); @@ -482,7 +475,7 @@ PepperPluginInstanceImpl* void RenderWidgetFullscreenPepper::OnResize( const ViewMsg_Resize_Params& params) { if (layer_) - layer_->setBounds(WebKit::WebSize(params.new_size)); + layer_->setBounds(blink::WebSize(params.new_size)); RenderWidget::OnResize(params); } diff --git a/chromium/content/renderer/render_widget_fullscreen_pepper.h b/chromium/content/renderer/render_widget_fullscreen_pepper.h index 29980e8ab74..5e2952cbd3c 100644 --- a/chromium/content/renderer/render_widget_fullscreen_pepper.h +++ b/chromium/content/renderer/render_widget_fullscreen_pepper.h @@ -11,7 +11,7 @@ #include "content/renderer/render_widget_fullscreen.h" #include "third_party/WebKit/public/web/WebWidget.h" -namespace WebKit { +namespace blink { class WebLayer; } @@ -28,15 +28,15 @@ class RenderWidgetFullscreenPepper : public RenderWidgetFullscreen, int32 opener_id, PepperPluginInstanceImpl* plugin, const GURL& active_url, - const WebKit::WebScreenInfo& screen_info); + const blink::WebScreenInfo& screen_info); // pepper::FullscreenContainer API. virtual void Invalidate() OVERRIDE; - virtual void InvalidateRect(const WebKit::WebRect& rect) OVERRIDE; - virtual void ScrollRect(int dx, int dy, const WebKit::WebRect& rect) OVERRIDE; + virtual void InvalidateRect(const blink::WebRect& rect) OVERRIDE; + virtual void ScrollRect(int dx, int dy, const blink::WebRect& rect) OVERRIDE; virtual void Destroy() OVERRIDE; - virtual void DidChangeCursor(const WebKit::WebCursorInfo& cursor) OVERRIDE; - virtual void SetLayer(WebKit::WebLayer* layer) OVERRIDE; + virtual void DidChangeCursor(const blink::WebCursorInfo& cursor) OVERRIDE; + virtual void SetLayer(blink::WebLayer* layer) OVERRIDE; // IPC::Listener implementation. This overrides the implementation // in RenderWidgetFullscreen. @@ -54,11 +54,10 @@ class RenderWidgetFullscreenPepper : public RenderWidgetFullscreen, protected: RenderWidgetFullscreenPepper(PepperPluginInstanceImpl* plugin, const GURL& active_url, - const WebKit::WebScreenInfo& screen_info); + const blink::WebScreenInfo& screen_info); virtual ~RenderWidgetFullscreenPepper(); // RenderWidget API. - virtual void WillInitiatePaint() OVERRIDE; virtual void DidInitiatePaint() OVERRIDE; virtual void DidFlushPaint() OVERRIDE; virtual void Close() OVERRIDE; @@ -71,7 +70,7 @@ class RenderWidgetFullscreenPepper : public RenderWidgetFullscreen, virtual void OnResize(const ViewMsg_Resize_Params& params) OVERRIDE; // RenderWidgetFullscreen API. - virtual WebKit::WebWidget* CreateWebWidget() OVERRIDE; + virtual blink::WebWidget* CreateWebWidget() OVERRIDE; // RenderWidget overrides. virtual GURL GetURLForGraphicsContext3D() OVERRIDE; @@ -84,7 +83,7 @@ class RenderWidgetFullscreenPepper : public RenderWidgetFullscreen, // The plugin instance this widget wraps. PepperPluginInstanceImpl* plugin_; - WebKit::WebLayer* layer_; + blink::WebLayer* layer_; scoped_ptr<MouseLockDispatcher> mouse_lock_dispatcher_; diff --git a/chromium/content/renderer/render_widget_unittest.cc b/chromium/content/renderer/render_widget_unittest.cc new file mode 100644 index 00000000000..1af4fafd7f9 --- /dev/null +++ b/chromium/content/renderer/render_widget_unittest.cc @@ -0,0 +1,146 @@ +// 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/renderer/render_widget.h" + +#include <vector> + +#include "content/common/input/synthetic_web_input_event_builders.h" +#include "content/common/input_messages.h" +#include "content/public/test/mock_render_thread.h" +#include "content/test/mock_render_process.h" +#include "ipc/ipc_test_sink.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/gfx/rect.h" + +namespace content { + +class RenderWidgetUnittest : public testing::Test { + public: + RenderWidgetUnittest() {} + virtual ~RenderWidgetUnittest() {} + + private: + MockRenderProcess render_process_; + MockRenderThread render_thread_; + + DISALLOW_COPY_AND_ASSIGN(RenderWidgetUnittest); +}; + +class TouchableRenderWidget : public RenderWidget { + public: + TouchableRenderWidget() : RenderWidget(blink::WebPopupTypeNone, + blink::WebScreenInfo(), + false, + false) {} + + void SetTouchRegion(const std::vector<gfx::Rect>& rects) { + rects_ = rects; + } + + void SendInputEvent(const blink::WebInputEvent& event) { + OnHandleInputEvent(&event, ui::LatencyInfo(), false); + } + + IPC::TestSink* sink() { return &sink_; } + + protected: + virtual ~TouchableRenderWidget() {} + + // Overridden from RenderWidget: + virtual bool HasTouchEventHandlersAt(const gfx::Point& point) const OVERRIDE { + for (std::vector<gfx::Rect>::const_iterator iter = rects_.begin(); + iter != rects_.end(); ++iter) { + if ((*iter).Contains(point)) + return true; + } + return false; + } + + virtual bool Send(IPC::Message* msg) OVERRIDE { + sink_.OnMessageReceived(*msg); + delete msg; + return true; + } + + private: + std::vector<gfx::Rect> rects_; + IPC::TestSink sink_; + + DISALLOW_COPY_AND_ASSIGN(TouchableRenderWidget); +}; + +TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) { + scoped_refptr<TouchableRenderWidget> widget = new TouchableRenderWidget(); + + blink::WebInputEvent::Type type; + InputEventAckState ack_state; + ui::LatencyInfo latency; + + SyntheticWebTouchEvent touch; + touch.PressPoint(10, 10); + + widget->SendInputEvent(touch); + ASSERT_EQ(1u, widget->sink()->message_count()); + + // Since there's currently no touch-event handling region, the response should + // be 'no consumer exists'. + const IPC::Message* message = widget->sink()->GetMessageAt(0); + EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type()); + InputHostMsg_HandleInputEvent_ACK::Read(message, &type, &ack_state, &latency); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state); + widget->sink()->ClearMessages(); + + std::vector<gfx::Rect> rects; + rects.push_back(gfx::Rect(0, 0, 20, 20)); + rects.push_back(gfx::Rect(25, 0, 10, 10)); + widget->SetTouchRegion(rects); + + widget->SendInputEvent(touch); + ASSERT_EQ(1u, widget->sink()->message_count()); + message = widget->sink()->GetMessageAt(0); + EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type()); + InputHostMsg_HandleInputEvent_ACK::Read(message, &type, &ack_state, &latency); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state); + widget->sink()->ClearMessages(); +} + +TEST_F(RenderWidgetUnittest, TouchHitTestMultiplePoints) { + scoped_refptr<TouchableRenderWidget> widget = new TouchableRenderWidget(); + std::vector<gfx::Rect> rects; + rects.push_back(gfx::Rect(0, 0, 20, 20)); + rects.push_back(gfx::Rect(25, 0, 10, 10)); + widget->SetTouchRegion(rects); + + blink::WebInputEvent::Type type; + InputEventAckState ack_state; + ui::LatencyInfo latency; + + SyntheticWebTouchEvent touch; + touch.PressPoint(25, 25); + + widget->SendInputEvent(touch); + ASSERT_EQ(1u, widget->sink()->message_count()); + + // Since there's currently no touch-event handling region, the response should + // be 'no consumer exists'. + const IPC::Message* message = widget->sink()->GetMessageAt(0); + EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type()); + InputHostMsg_HandleInputEvent_ACK::Read(message, &type, &ack_state, &latency); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state); + widget->sink()->ClearMessages(); + + // Press a second touch point. This time, on a touch-handling region. + touch.PressPoint(10, 10); + widget->SendInputEvent(touch); + ASSERT_EQ(1u, widget->sink()->message_count()); + message = widget->sink()->GetMessageAt(0); + EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type()); + InputHostMsg_HandleInputEvent_ACK::Read(message, &type, &ack_state, &latency); + EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state); + widget->sink()->ClearMessages(); +} + +} // namespace content diff --git a/chromium/content/renderer/renderer_clipboard_client.cc b/chromium/content/renderer/renderer_clipboard_client.cc index 9df9508be90..9c47463bddd 100644 --- a/chromium/content/renderer/renderer_clipboard_client.cc +++ b/chromium/content/renderer/renderer_clipboard_client.cc @@ -100,69 +100,65 @@ ui::Clipboard* RendererClipboardClient::GetClipboard() { return NULL; } -uint64 RendererClipboardClient::GetSequenceNumber( - ui::Clipboard::Buffer buffer) { +uint64 RendererClipboardClient::GetSequenceNumber(ui::ClipboardType type) { uint64 sequence_number = 0; RenderThreadImpl::current()->Send( - new ClipboardHostMsg_GetSequenceNumber(buffer, - &sequence_number)); + new ClipboardHostMsg_GetSequenceNumber(type, &sequence_number)); return sequence_number; } bool RendererClipboardClient::IsFormatAvailable( const ui::Clipboard::FormatType& format, - ui::Clipboard::Buffer buffer) { + ui::ClipboardType type) { bool result; RenderThreadImpl::current()->Send( - new ClipboardHostMsg_IsFormatAvailable(format, buffer, &result)); + new ClipboardHostMsg_IsFormatAvailable(format, type, &result)); return result; } -void RendererClipboardClient::Clear(ui::Clipboard::Buffer buffer) { - RenderThreadImpl::current()->Send(new ClipboardHostMsg_Clear(buffer)); +void RendererClipboardClient::Clear(ui::ClipboardType type) { + RenderThreadImpl::current()->Send(new ClipboardHostMsg_Clear(type)); } void RendererClipboardClient::ReadAvailableTypes( - ui::Clipboard::Buffer buffer, - std::vector<string16>* types, + ui::ClipboardType type, + std::vector<base::string16>* types, bool* contains_filenames) { RenderThreadImpl::current()->Send(new ClipboardHostMsg_ReadAvailableTypes( - buffer, types, contains_filenames)); + type, types, contains_filenames)); } -void RendererClipboardClient::ReadText(ui::Clipboard::Buffer buffer, - string16* result) { +void RendererClipboardClient::ReadText(ui::ClipboardType type, + base::string16* result) { RenderThreadImpl::current()->Send( - new ClipboardHostMsg_ReadText(buffer, result)); + new ClipboardHostMsg_ReadText(type, result)); } -void RendererClipboardClient::ReadAsciiText(ui::Clipboard::Buffer buffer, +void RendererClipboardClient::ReadAsciiText(ui::ClipboardType type, std::string* result) { RenderThreadImpl::current()->Send( - new ClipboardHostMsg_ReadAsciiText(buffer, result)); + new ClipboardHostMsg_ReadAsciiText(type, result)); } -void RendererClipboardClient::ReadHTML(ui::Clipboard::Buffer buffer, - string16* markup, +void RendererClipboardClient::ReadHTML(ui::ClipboardType type, + base::string16* markup, GURL* url, uint32* fragment_start, uint32* fragment_end) { - RenderThreadImpl::current()->Send( - new ClipboardHostMsg_ReadHTML(buffer, markup, url, fragment_start, - fragment_end)); + RenderThreadImpl::current()->Send(new ClipboardHostMsg_ReadHTML( + type, markup, url, fragment_start, fragment_end)); } -void RendererClipboardClient::ReadRTF(ui::Clipboard::Buffer buffer, +void RendererClipboardClient::ReadRTF(ui::ClipboardType type, std::string* result) { - RenderThreadImpl::current()->Send( - new ClipboardHostMsg_ReadRTF(buffer, result)); + RenderThreadImpl::current()->Send(new ClipboardHostMsg_ReadRTF(type, result)); } -void RendererClipboardClient::ReadImage(ui::Clipboard::Buffer buffer, +void RendererClipboardClient::ReadImage(ui::ClipboardType type, std::string* data) { base::SharedMemoryHandle image_handle; uint32 image_size; RenderThreadImpl::current()->Send( - new ClipboardHostMsg_ReadImage(buffer, &image_handle, &image_size)); + new ClipboardHostMsg_ReadImage(type, &image_handle, &image_size)); if (base::SharedMemory::IsHandleValid(image_handle)) { base::SharedMemory buffer(image_handle, true); buffer.Map(image_size); @@ -170,11 +166,11 @@ void RendererClipboardClient::ReadImage(ui::Clipboard::Buffer buffer, } } -void RendererClipboardClient::ReadCustomData(ui::Clipboard::Buffer buffer, - const string16& type, - string16* data) { +void RendererClipboardClient::ReadCustomData(ui::ClipboardType clipboard_type, + const base::string16& type, + base::string16* data) { RenderThreadImpl::current()->Send( - new ClipboardHostMsg_ReadCustomData(buffer, type, data)); + new ClipboardHostMsg_ReadCustomData(clipboard_type, type, data)); } void RendererClipboardClient::ReadData(const ui::Clipboard::FormatType& format, diff --git a/chromium/content/renderer/renderer_clipboard_client.h b/chromium/content/renderer/renderer_clipboard_client.h index 888f1160c0e..96d05b2621a 100644 --- a/chromium/content/renderer/renderer_clipboard_client.h +++ b/chromium/content/renderer/renderer_clipboard_client.h @@ -17,27 +17,27 @@ class RendererClipboardClient : public ClipboardClient { virtual ~RendererClipboardClient(); virtual ui::Clipboard* GetClipboard() OVERRIDE; - virtual uint64 GetSequenceNumber(ui::Clipboard::Buffer buffer) OVERRIDE; + virtual uint64 GetSequenceNumber(ui::ClipboardType type) OVERRIDE; virtual bool IsFormatAvailable(const ui::Clipboard::FormatType& format, - ui::Clipboard::Buffer buffer) OVERRIDE; - virtual void Clear(ui::Clipboard::Buffer buffer) OVERRIDE; - virtual void ReadAvailableTypes(ui::Clipboard::Buffer buffer, - std::vector<string16>* types, + ui::ClipboardType type) OVERRIDE; + virtual void Clear(ui::ClipboardType type) OVERRIDE; + virtual void ReadAvailableTypes(ui::ClipboardType type, + std::vector<base::string16>* types, bool* contains_filenames) OVERRIDE; - virtual void ReadText(ui::Clipboard::Buffer buffer, - string16* result) OVERRIDE; - virtual void ReadAsciiText(ui::Clipboard::Buffer buffer, + virtual void ReadText(ui::ClipboardType type, + base::string16* result) OVERRIDE; + virtual void ReadAsciiText(ui::ClipboardType type, std::string* result) OVERRIDE; - virtual void ReadHTML(ui::Clipboard::Buffer buffer, string16* markup, - GURL* url, uint32* fragment_start, + virtual void ReadHTML(ui::ClipboardType type, + base::string16* markup, + GURL* url, + uint32* fragment_start, uint32* fragment_end) OVERRIDE; - virtual void ReadRTF(ui::Clipboard::Buffer buffer, - std::string* result) OVERRIDE; - virtual void ReadImage(ui::Clipboard::Buffer buffer, - std::string* data) OVERRIDE; - virtual void ReadCustomData(ui::Clipboard::Buffer buffer, - const string16& type, - string16* data) OVERRIDE; + virtual void ReadRTF(ui::ClipboardType type, std::string* result) OVERRIDE; + virtual void ReadImage(ui::ClipboardType type, std::string* data) OVERRIDE; + virtual void ReadCustomData(ui::ClipboardType clipboard_type, + const base::string16& type, + base::string16* data) OVERRIDE; virtual void ReadData(const ui::Clipboard::FormatType& format, std::string* data) OVERRIDE; virtual WriteContext* CreateWriteContext() OVERRIDE; diff --git a/chromium/content/renderer/renderer_date_time_picker.cc b/chromium/content/renderer/renderer_date_time_picker.cc index 86d268ac913..592e2491451 100644 --- a/chromium/content/renderer/renderer_date_time_picker.cc +++ b/chromium/content/renderer/renderer_date_time_picker.cc @@ -6,48 +6,66 @@ #include "base/strings/string_util.h" #include "content/common/view_messages.h" -#include "content/renderer/date_time_formatter.h" +#include "content/renderer/date_time_suggestion_builder.h" #include "content/renderer/render_view_impl.h" - #include "third_party/WebKit/public/web/WebDateTimeChooserCompletion.h" #include "third_party/WebKit/public/web/WebDateTimeChooserParams.h" #include "third_party/WebKit/public/web/WebDateTimeInputType.h" +#include "ui/base/ime/text_input_type.h" -using WebKit::WebString; +using blink::WebString; namespace content { +static ui::TextInputType ToTextInputType(int type) { + switch (type) { + case blink::WebDateTimeInputTypeDate: + return ui::TEXT_INPUT_TYPE_DATE; + break; + case blink::WebDateTimeInputTypeDateTime: + return ui::TEXT_INPUT_TYPE_DATE_TIME; + break; + case blink::WebDateTimeInputTypeDateTimeLocal: + return ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL; + break; + case blink::WebDateTimeInputTypeMonth: + return ui::TEXT_INPUT_TYPE_MONTH; + break; + case blink::WebDateTimeInputTypeTime: + return ui::TEXT_INPUT_TYPE_TIME; + break; + case blink::WebDateTimeInputTypeWeek: + return ui::TEXT_INPUT_TYPE_WEEK; + break; + case blink::WebDateTimeInputTypeNone: + default: + return ui::TEXT_INPUT_TYPE_NONE; + } +} + RendererDateTimePicker::RendererDateTimePicker( RenderViewImpl* sender, - const WebKit::WebDateTimeChooserParams& params, - WebKit::WebDateTimeChooserCompletion* completion) + const blink::WebDateTimeChooserParams& params, + blink::WebDateTimeChooserCompletion* completion) : RenderViewObserver(sender), chooser_params_(params), - chooser_completion_(completion){ + chooser_completion_(completion) { } RendererDateTimePicker::~RendererDateTimePicker() { } bool RendererDateTimePicker::Open() { - DateTimeFormatter parser(chooser_params_); ViewHostMsg_DateTimeDialogValue_Params message; - message.dialog_type = parser.GetType(); - if (message.dialog_type == ui::TEXT_INPUT_TYPE_WEEK) { - message.year = parser.GetWeekYear(); - message.week = parser.GetWeek(); - } else { - message.year = parser.GetYear(); - message.month = parser.GetMonth(); - message.day = parser.GetDay(); - message.hour = parser.GetHour(); - message.minute = parser.GetMinute(); - message.second = parser.GetSecond(); - message.milli = parser.GetMilli(); - } + message.dialog_type = ToTextInputType(chooser_params_.type); + message.dialog_value = chooser_params_.doubleValue; message.minimum = chooser_params_.minimum; message.maximum = chooser_params_.maximum; message.step = chooser_params_.step; + for (size_t i = 0; i < chooser_params_.suggestions.size(); i++) { + message.suggestions.push_back( + DateTimeSuggestionBuilder::Build(chooser_params_.suggestions[i])); + } Send(new ViewHostMsg_OpenDateTimeDialog(routing_id(), message)); return true; } @@ -63,28 +81,20 @@ bool RendererDateTimePicker::OnMessageReceived( return handled; } -void RendererDateTimePicker::OnReplaceDateTime( - const ViewHostMsg_DateTimeDialogValue_Params& value) { - - DateTimeFormatter formatter(static_cast<ui::TextInputType>(value.dialog_type), - value.year, - value.month, - value.day, - value.hour, - value.minute, - value.second, - value.milli, - value.year, - value.week); - +void RendererDateTimePicker::OnReplaceDateTime(double value) { if (chooser_completion_) - chooser_completion_->didChooseValue(WebString::fromUTF8( - formatter.GetFormattedValue().c_str())); + chooser_completion_->didChooseValue(value); +#if defined(OS_ANDROID) + static_cast<RenderViewImpl*>(render_view())->DismissDateTimeDialog(); +#endif } void RendererDateTimePicker::OnCancel() { if (chooser_completion_) chooser_completion_->didCancelChooser(); +#if defined(OS_ANDROID) + static_cast<RenderViewImpl*>(render_view())->DismissDateTimeDialog(); +#endif } } // namespace content diff --git a/chromium/content/renderer/renderer_date_time_picker.h b/chromium/content/renderer/renderer_date_time_picker.h index d7292b7e37c..7a780c7826d 100644 --- a/chromium/content/renderer/renderer_date_time_picker.h +++ b/chromium/content/renderer/renderer_date_time_picker.h @@ -11,9 +11,9 @@ struct ViewHostMsg_DateTimeDialogValue_Params; -namespace WebKit { +namespace blink { class WebDateTimeChooserCompletion; -} // namespace WebKit +} // namespace blink namespace content { class RenderViewImpl; @@ -22,21 +22,21 @@ class RendererDateTimePicker : public RenderViewObserver { public: RendererDateTimePicker( RenderViewImpl* sender, - const WebKit::WebDateTimeChooserParams& params, - WebKit::WebDateTimeChooserCompletion* completion); + const blink::WebDateTimeChooserParams& params, + blink::WebDateTimeChooserCompletion* completion); virtual ~RendererDateTimePicker(); bool Open(); private: - void OnReplaceDateTime(const ViewHostMsg_DateTimeDialogValue_Params& value); + void OnReplaceDateTime(double value); void OnCancel(); // RenderViewObserver virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - WebKit::WebDateTimeChooserParams chooser_params_; - WebKit::WebDateTimeChooserCompletion* chooser_completion_; // Not owned by us + blink::WebDateTimeChooserParams chooser_params_; + blink::WebDateTimeChooserCompletion* chooser_completion_; // Not owned by us DISALLOW_COPY_AND_ASSIGN(RendererDateTimePicker); }; diff --git a/chromium/content/renderer/renderer_main.cc b/chromium/content/renderer/renderer_main.cc index 1c33cf340a0..f0c16d27815 100644 --- a/chromium/content/renderer/renderer_main.cc +++ b/chromium/content/renderer/renderer_main.cc @@ -32,7 +32,6 @@ #include "content/renderer/renderer_main_platform_delegate.h" #include "ui/base/ui_base_switches.h" #include "webkit/child/webkit_child_helpers.h" -#include "webkit/glue/webkit_glue.h" #if defined(OS_ANDROID) #include "base/android/sys_utils.h" @@ -160,7 +159,7 @@ int RendererMain(const MainFunctionParams& parameters) { RendererMessageLoopObserver task_observer; #if defined(OS_MACOSX) // As long as we use Cocoa in the renderer (for the forseeable future as of - // now; see http://crbug.com/13890 for info) we need to have a UI loop. + // now; see http://crbug.com/306348 for info) we need to have a UI loop. base::MessageLoop main_message_loop(base::MessageLoop::TYPE_UI); #else // The main message loop of the renderer services doesn't have IO or UI tasks, diff --git a/chromium/content/renderer/renderer_main_platform_delegate_linux.cc b/chromium/content/renderer/renderer_main_platform_delegate_linux.cc index e473ad895f3..bc9deec23a8 100644 --- a/chromium/content/renderer/renderer_main_platform_delegate_linux.cc +++ b/chromium/content/renderer/renderer_main_platform_delegate_linux.cc @@ -10,7 +10,7 @@ #include "base/command_line.h" #include "base/file_util.h" #include "base/logging.h" -#include "content/common/sandbox_linux.h" +#include "content/common/sandbox_linux/sandbox_linux.h" #include "content/public/common/content_switches.h" #include "content/public/common/sandbox_init.h" @@ -69,7 +69,7 @@ void RendererMainPlatformDelegate::RunSandboxTests(bool no_sandbox) { // Here, we test that the status of SeccompBpf in the renderer is consistent // with what LinuxSandbox::GetStatus() said we would do. class LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); - if (linux_sandbox->GetStatus() & kSandboxLinuxSeccompBpf) { + if (linux_sandbox->GetStatus() & kSandboxLinuxSeccompBPF) { CHECK(linux_sandbox->seccomp_bpf_started()); } diff --git a/chromium/content/renderer/renderer_main_platform_delegate_mac.mm b/chromium/content/renderer/renderer_main_platform_delegate_mac.mm index e7cf9ffa4cd..9f6172e71e1 100644 --- a/chromium/content/renderer/renderer_main_platform_delegate_mac.mm +++ b/chromium/content/renderer/renderer_main_platform_delegate_mac.mm @@ -101,7 +101,7 @@ static void LogTestMessage(std::string message, bool is_error) { if (is_error) LOG(ERROR) << message; else - LOG(INFO) << message; + VLOG(0) << message; } bool RendererMainPlatformDelegate::InitSandboxTests(bool no_sandbox) { @@ -127,7 +127,7 @@ bool RendererMainPlatformDelegate::InitSandboxTests(bool no_sandbox) { } bool RendererMainPlatformDelegate::EnableSandbox() { - // http://openradar.appspot.com/radar?id=1156410 is fixed on OS X 10.9+. + // rdar://9251340 http://openradar.me/9251340 // See http://crbug.com/31225 and http://crbug.com/152566 // To check if this is broken: // 1. Enable Multi language input (simplified chinese) @@ -140,8 +140,8 @@ bool RendererMainPlatformDelegate::EnableSandbox() { // and then kill that pid to make it go away.) // // Chinese Handwriting was introduced in 10.6 and is confirmed broken on - // 10.6, 10.7, and 10.8. It's reportedly fixed on 10.9. - bool needs_ime_hack = !base::mac::IsOSLaterThanMountainLion_DontCallThis(); + // 10.6, 10.7, and 10.8. It's fixed on 10.9. + bool needs_ime_hack = base::mac::IsOSMountainLionOrEarlier(); if (needs_ime_hack) { mach_error_t err = mach_override_ptr( diff --git a/chromium/content/renderer/renderer_main_platform_delegate_win.cc b/chromium/content/renderer/renderer_main_platform_delegate_win.cc index c4b46163cbc..e425c5ab77f 100644 --- a/chromium/content/renderer/renderer_main_platform_delegate_win.cc +++ b/chromium/content/renderer/renderer_main_platform_delegate_win.cc @@ -38,8 +38,9 @@ void SkiaPreCacheFontCharacters(const LOGFONT& logfont, unsigned int text_length) { RenderThreadImpl* render_thread_impl = RenderThreadImpl::current(); if (render_thread_impl) { - render_thread_impl->PreCacheFontCharacters(logfont, - string16(text, text_length)); + render_thread_impl->PreCacheFontCharacters( + logfont, + base::string16(text, text_length)); } } diff --git a/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc b/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc index 42b281c10db..8aeee8a960e 100644 --- a/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc +++ b/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc @@ -11,8 +11,8 @@ #include "third_party/WebKit/public/web/WebView.h" using appcache::AppCacheBackend; -using WebKit::WebApplicationCacheHostClient; -using WebKit::WebConsoleMessage; +using blink::WebApplicationCacheHostClient; +using blink::WebConsoleMessage; namespace content { @@ -34,10 +34,10 @@ void RendererWebApplicationCacheHostImpl::OnLogMessage( !render_view->webview()->mainFrame()) return; - WebKit::WebFrame* frame = render_view->webview()->mainFrame(); + blink::WebFrame* frame = render_view->webview()->mainFrame(); frame->addMessageToConsole(WebConsoleMessage( static_cast<WebConsoleMessage::Level>(log_level), - WebKit::WebString::fromUTF8(message.c_str()))); + blink::WebString::fromUTF8(message.c_str()))); } void RendererWebApplicationCacheHostImpl::OnContentBlocked( diff --git a/chromium/content/renderer/renderer_webapplicationcachehost_impl.h b/chromium/content/renderer/renderer_webapplicationcachehost_impl.h index 06120398cfc..16fd17c2115 100644 --- a/chromium/content/renderer/renderer_webapplicationcachehost_impl.h +++ b/chromium/content/renderer/renderer_webapplicationcachehost_impl.h @@ -14,7 +14,7 @@ class RendererWebApplicationCacheHostImpl : public WebApplicationCacheHostImpl { public: RendererWebApplicationCacheHostImpl( RenderViewImpl* render_view, - WebKit::WebApplicationCacheHostClient* client, + blink::WebApplicationCacheHostClient* client, appcache::AppCacheBackend* backend); // WebApplicationCacheHostImpl: diff --git a/chromium/content/renderer/renderer_webcolorchooser_impl.cc b/chromium/content/renderer/renderer_webcolorchooser_impl.cc index 337ec7e6212..5cfbd7397d2 100644 --- a/chromium/content/renderer/renderer_webcolorchooser_impl.cc +++ b/chromium/content/renderer/renderer_webcolorchooser_impl.cc @@ -16,7 +16,7 @@ static int GenerateColorChooserIdentifier() { RendererWebColorChooserImpl::RendererWebColorChooserImpl( RenderViewImpl* render_view, - WebKit::WebColorChooserClient* client) + blink::WebColorChooserClient* client) : RenderViewObserver(render_view), identifier_(GenerateColorChooserIdentifier()), client_(client) { @@ -38,7 +38,7 @@ bool RendererWebColorChooserImpl::OnMessageReceived( return handled; } -void RendererWebColorChooserImpl::setSelectedColor(WebKit::WebColor color) { +void RendererWebColorChooserImpl::setSelectedColor(blink::WebColor color) { Send(new ViewHostMsg_SetSelectedColorInColorChooser(routing_id(), identifier_, static_cast<SkColor>(color))); } @@ -47,16 +47,20 @@ void RendererWebColorChooserImpl::endChooser() { Send(new ViewHostMsg_EndColorChooser(routing_id(), identifier_)); } -void RendererWebColorChooserImpl::Open(SkColor initial_color) { - Send(new ViewHostMsg_OpenColorChooser(routing_id(), identifier_, - initial_color)); +void RendererWebColorChooserImpl::Open( + SkColor initial_color, + const std::vector<content::ColorSuggestion>& suggestions) { + Send(new ViewHostMsg_OpenColorChooser(routing_id(), + identifier_, + initial_color, + suggestions)); } void RendererWebColorChooserImpl::OnDidChooseColorResponse(int color_chooser_id, SkColor color) { DCHECK(identifier_ == color_chooser_id); - client_->didChooseColor(static_cast<WebKit::WebColor>(color)); + client_->didChooseColor(static_cast<blink::WebColor>(color)); } void RendererWebColorChooserImpl::OnDidEndColorChooser(int color_chooser_id) { diff --git a/chromium/content/renderer/renderer_webcolorchooser_impl.h b/chromium/content/renderer/renderer_webcolorchooser_impl.h index bd8f235528a..d7534788738 100644 --- a/chromium/content/renderer/renderer_webcolorchooser_impl.h +++ b/chromium/content/renderer/renderer_webcolorchooser_impl.h @@ -5,32 +5,36 @@ #ifndef CONTENT_RENDERER_RENDERER_WEBCOLORCHOOSER_IMPL_H_ #define CONTENT_RENDERER_RENDERER_WEBCOLORCHOOSER_IMPL_H_ +#include <vector> + #include "base/compiler_specific.h" +#include "content/public/common/color_suggestion.h" #include "content/public/renderer/render_view_observer.h" #include "third_party/WebKit/public/web/WebColorChooser.h" #include "third_party/WebKit/public/web/WebColorChooserClient.h" #include "third_party/skia/include/core/SkColor.h" -namespace WebKit { +namespace blink { class WebFrame; } namespace content { class RenderViewImpl; -class RendererWebColorChooserImpl : public WebKit::WebColorChooser, +class RendererWebColorChooserImpl : public blink::WebColorChooser, public RenderViewObserver { public: explicit RendererWebColorChooserImpl(RenderViewImpl* sender, - WebKit::WebColorChooserClient*); + blink::WebColorChooserClient*); virtual ~RendererWebColorChooserImpl(); - virtual void setSelectedColor(const WebKit::WebColor); + virtual void setSelectedColor(const blink::WebColor); virtual void endChooser(); - void Open(SkColor initial_color); + void Open(SkColor initial_color, + const std::vector<content::ColorSuggestion>& suggestions); - WebKit::WebColorChooserClient* client() { return client_; } + blink::WebColorChooserClient* client() { return client_; } private: // RenderViewObserver implementation. @@ -40,7 +44,7 @@ class RendererWebColorChooserImpl : public WebKit::WebColorChooser, void OnDidEndColorChooser(int color_chooser_id); int identifier_; - WebKit::WebColorChooserClient* client_; + blink::WebColorChooserClient* client_; DISALLOW_COPY_AND_ASSIGN(RendererWebColorChooserImpl); }; diff --git a/chromium/content/renderer/renderer_webcookiejar_impl.cc b/chromium/content/renderer/renderer_webcookiejar_impl.cc index c9e6934e714..c74f16ac701 100644 --- a/chromium/content/renderer/renderer_webcookiejar_impl.cc +++ b/chromium/content/renderer/renderer_webcookiejar_impl.cc @@ -11,10 +11,10 @@ #include "content/renderer/render_view_impl.h" #include "third_party/WebKit/public/platform/WebCookie.h" -using WebKit::WebCookie; -using WebKit::WebString; -using WebKit::WebURL; -using WebKit::WebVector; +using blink::WebCookie; +using blink::WebString; +using blink::WebURL; +using blink::WebVector; namespace content { @@ -22,23 +22,15 @@ void RendererWebCookieJarImpl::setCookie( const WebURL& url, const WebURL& first_party_for_cookies, const WebString& value) { std::string value_utf8 = UTF16ToUTF8(value); - if (!GetContentClient()->renderer()->HandleSetCookieRequest( - sender_, url, first_party_for_cookies, value_utf8)) { - sender_->Send(new ViewHostMsg_SetCookie( - MSG_ROUTING_NONE, url, first_party_for_cookies, value_utf8)); - } + sender_->Send(new ViewHostMsg_SetCookie( + MSG_ROUTING_NONE, url, first_party_for_cookies, value_utf8)); } WebString RendererWebCookieJarImpl::cookies( const WebURL& url, const WebURL& first_party_for_cookies) { std::string value_utf8; - - if (!GetContentClient()->renderer()->HandleGetCookieRequest( - sender_, url, first_party_for_cookies, &value_utf8)) { - // NOTE: This may pump events (see RenderThread::Send). - sender_->Send(new ViewHostMsg_GetCookies( - MSG_ROUTING_NONE, url, first_party_for_cookies, &value_utf8)); - } + sender_->Send(new ViewHostMsg_GetCookies( + MSG_ROUTING_NONE, url, first_party_for_cookies, &value_utf8)); return WebString::fromUTF8(value_utf8); } diff --git a/chromium/content/renderer/renderer_webcookiejar_impl.h b/chromium/content/renderer/renderer_webcookiejar_impl.h index 4820bc487f0..a6451af3509 100644 --- a/chromium/content/renderer/renderer_webcookiejar_impl.h +++ b/chromium/content/renderer/renderer_webcookiejar_impl.h @@ -12,7 +12,7 @@ namespace content { class RenderViewImpl; -class RendererWebCookieJarImpl : public WebKit::WebCookieJar { +class RendererWebCookieJarImpl : public blink::WebCookieJar { public: explicit RendererWebCookieJarImpl(RenderViewImpl* sender) : sender_(sender) { @@ -20,21 +20,21 @@ class RendererWebCookieJarImpl : public WebKit::WebCookieJar { virtual ~RendererWebCookieJarImpl() {} private: - // WebKit::WebCookieJar methods: + // blink::WebCookieJar methods: virtual void setCookie( - const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies, - const WebKit::WebString& value); - virtual WebKit::WebString cookies( - const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies); - virtual WebKit::WebString cookieRequestHeaderFieldValue( - const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies); + const blink::WebURL& url, const blink::WebURL& first_party_for_cookies, + const blink::WebString& value); + virtual blink::WebString cookies( + const blink::WebURL& url, const blink::WebURL& first_party_for_cookies); + virtual blink::WebString cookieRequestHeaderFieldValue( + const blink::WebURL& url, const blink::WebURL& first_party_for_cookies); virtual void rawCookies( - const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies, - WebKit::WebVector<WebKit::WebCookie>& cookies); + const blink::WebURL& url, const blink::WebURL& first_party_for_cookies, + blink::WebVector<blink::WebCookie>& cookies); virtual void deleteCookie( - const WebKit::WebURL& url, const WebKit::WebString& cookie_name); + const blink::WebURL& url, const blink::WebString& cookie_name); virtual bool cookiesEnabled( - const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies); + const blink::WebURL& url, const blink::WebURL& first_party_for_cookies); RenderViewImpl* sender_; }; diff --git a/chromium/content/renderer/renderer_webkitplatformsupport_impl.cc b/chromium/content/renderer/renderer_webkitplatformsupport_impl.cc index 25ca5d13968..6013a05d052 100644 --- a/chromium/content/renderer/renderer_webkitplatformsupport_impl.cc +++ b/chromium/content/renderer/renderer_webkitplatformsupport_impl.cc @@ -16,16 +16,19 @@ #include "base/strings/utf_string_conversions.h" #include "content/child/database_util.h" #include "content/child/fileapi/webfilesystem_impl.h" -#include "content/child/indexed_db/proxy_webidbfactory_impl.h" +#include "content/child/indexed_db/webidbfactory_impl.h" #include "content/child/npapi/npobject_util.h" #include "content/child/quota_dispatcher.h" #include "content/child/quota_message_filter.h" #include "content/child/thread_safe_sender.h" +#include "content/child/web_database_observer_impl.h" #include "content/child/webblobregistry_impl.h" #include "content/child/webmessageportchannel_impl.h" #include "content/common/file_utilities_messages.h" #include "content/common/gpu/client/context_provider_command_buffer.h" +#include "content/common/gpu/client/gpu_channel_host.h" #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" +#include "content/common/gpu/gpu_process_launch_causes.h" #include "content/common/mime_registry_messages.h" #include "content/common/view_messages.h" #include "content/public/common/content_switches.h" @@ -44,8 +47,8 @@ #include "content/renderer/render_thread_impl.h" #include "content/renderer/renderer_clipboard_client.h" #include "content/renderer/webclipboard_impl.h" -#include "content/renderer/webcrypto_impl.h" -#include "content/renderer/websharedworkerrepository_impl.h" +#include "content/renderer/webcrypto/webcrypto_impl.h" +#include "content/renderer/webpublicsuffixlist_impl.h" #include "gpu/config/gpu_info.h" #include "ipc/ipc_sync_message_filter.h" #include "media/audio/audio_output_device.h" @@ -65,6 +68,7 @@ #include "third_party/WebKit/public/platform/WebVector.h" #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" +#include "ui/gfx/color_profile.h" #include "url/gurl.h" #include "webkit/common/gpu/webgraphicscontext3d_provider_impl.h" #include "webkit/common/quota/quota_types.h" @@ -102,33 +106,34 @@ #include "content/renderer/media/android/audio_decoder_android.h" #endif -using WebKit::WebAudioDevice; -using WebKit::WebBlobRegistry; -using WebKit::WebFileInfo; -using WebKit::WebFileSystem; -using WebKit::WebFrame; -using WebKit::WebGamepads; -using WebKit::WebIDBFactory; -using WebKit::WebMIDIAccessor; -using WebKit::Platform; -using WebKit::WebMediaStreamCenter; -using WebKit::WebMediaStreamCenterClient; -using WebKit::WebMimeRegistry; -using WebKit::WebRTCPeerConnectionHandler; -using WebKit::WebRTCPeerConnectionHandlerClient; -using WebKit::WebStorageNamespace; -using WebKit::WebString; -using WebKit::WebURL; -using WebKit::WebVector; +using blink::Platform; +using blink::WebAudioDevice; +using blink::WebBlobRegistry; +using blink::WebDatabaseObserver; +using blink::WebFileInfo; +using blink::WebFileSystem; +using blink::WebFrame; +using blink::WebGamepads; +using blink::WebIDBFactory; +using blink::WebMIDIAccessor; +using blink::WebMediaStreamCenter; +using blink::WebMediaStreamCenterClient; +using blink::WebMimeRegistry; +using blink::WebRTCPeerConnectionHandler; +using blink::WebRTCPeerConnectionHandlerClient; +using blink::WebStorageNamespace; +using blink::WebString; +using blink::WebURL; +using blink::WebVector; namespace content { static bool g_sandbox_enabled = true; base::LazyInstance<WebGamepads>::Leaky g_test_gamepads = LAZY_INSTANCE_INITIALIZER; -base::LazyInstance<WebKit::WebDeviceMotionData>::Leaky +base::LazyInstance<blink::WebDeviceMotionData>::Leaky g_test_device_motion_data = LAZY_INSTANCE_INITIALIZER; -base::LazyInstance<WebKit::WebDeviceOrientationData>::Leaky +base::LazyInstance<blink::WebDeviceOrientationData>::Leaky g_test_device_orientation_data = LAZY_INSTANCE_INITIALIZER; //------------------------------------------------------------------------------ @@ -136,20 +141,16 @@ base::LazyInstance<WebKit::WebDeviceOrientationData>::Leaky class RendererWebKitPlatformSupportImpl::MimeRegistry : public webkit_glue::SimpleWebMimeRegistryImpl { public: - // TODO(ddorwin): Remove after http://webk.it/82983 lands. - virtual WebKit::WebMimeRegistry::SupportsType supportsMediaMIMEType( - const WebKit::WebString& mime_type, - const WebKit::WebString& codecs); - virtual WebKit::WebMimeRegistry::SupportsType supportsMediaMIMEType( - const WebKit::WebString& mime_type, - const WebKit::WebString& codecs, - const WebKit::WebString& key_system); - virtual bool supportsMediaSourceMIMEType(const WebKit::WebString& mime_type, - const WebKit::WebString& codecs); - virtual WebKit::WebString mimeTypeForExtension( - const WebKit::WebString& file_extension); - virtual WebKit::WebString mimeTypeFromFile( - const WebKit::WebString& file_path); + virtual blink::WebMimeRegistry::SupportsType supportsMediaMIMEType( + const blink::WebString& mime_type, + const blink::WebString& codecs, + const blink::WebString& key_system); + virtual bool supportsMediaSourceMIMEType(const blink::WebString& mime_type, + const blink::WebString& codecs); + virtual blink::WebString mimeTypeForExtension( + const blink::WebString& file_extension); + virtual blink::WebString mimeTypeFromFile( + const blink::WebString& file_path); }; class RendererWebKitPlatformSupportImpl::FileUtilities @@ -170,7 +171,7 @@ class RendererWebKitPlatformSupportImpl::SandboxSupport { }; #else class RendererWebKitPlatformSupportImpl::SandboxSupport - : public WebKit::WebSandboxSupport { + : public blink::WebSandboxSupport { public: virtual ~SandboxSupport() {} @@ -183,18 +184,18 @@ class RendererWebKitPlatformSupportImpl::SandboxSupport uint32* font_id); #elif defined(OS_POSIX) virtual void getFontFamilyForCharacter( - WebKit::WebUChar32 character, + blink::WebUChar32 character, const char* preferred_locale, - WebKit::WebFontFamily* family); + blink::WebFontFamily* family); virtual void getRenderStyleForStrike( - const char* family, int sizeAndStyle, WebKit::WebFontRenderStyle* out); + const char* family, int sizeAndStyle, blink::WebFontRenderStyle* out); private: // WebKit likes to ask us for the correct font family to use for a set of // unicode code points. It needs this information frequently so we cache it // here. base::Lock unicode_font_families_mutex_; - std::map<int32_t, WebKit::WebFontFamily> unicode_font_families_; + std::map<int32_t, blink::WebFontFamily> unicode_font_families_; #endif }; #endif // defined(OS_ANDROID) @@ -207,7 +208,6 @@ RendererWebKitPlatformSupportImpl::RendererWebKitPlatformSupportImpl() mime_registry_(new RendererWebKitPlatformSupportImpl::MimeRegistry), sudden_termination_disables_(0), plugin_refresh_allowed_(true), - shared_worker_repository_(new WebSharedWorkerRepositoryImpl), child_thread_loop_(base::MessageLoopProxy::current()) { if (g_sandbox_enabled && sandboxEnabled()) { sandbox_support_.reset( @@ -221,6 +221,10 @@ RendererWebKitPlatformSupportImpl::RendererWebKitPlatformSupportImpl() sync_message_filter_ = ChildThread::current()->sync_message_filter(); thread_safe_sender_ = ChildThread::current()->thread_safe_sender(); quota_message_filter_ = ChildThread::current()->quota_message_filter(); + blob_registry_.reset(new WebBlobRegistryImpl(thread_safe_sender_)); + web_idb_factory_.reset(new WebIDBFactoryImpl(thread_safe_sender_)); + web_database_observer_impl_.reset( + new WebDatabaseObserverImpl(sync_message_filter_)); } } @@ -230,19 +234,19 @@ RendererWebKitPlatformSupportImpl::~RendererWebKitPlatformSupportImpl() { //------------------------------------------------------------------------------ -WebKit::WebClipboard* RendererWebKitPlatformSupportImpl::clipboard() { - WebKit::WebClipboard* clipboard = +blink::WebClipboard* RendererWebKitPlatformSupportImpl::clipboard() { + blink::WebClipboard* clipboard = GetContentClient()->renderer()->OverrideWebClipboard(); if (clipboard) return clipboard; return clipboard_.get(); } -WebKit::WebMimeRegistry* RendererWebKitPlatformSupportImpl::mimeRegistry() { +blink::WebMimeRegistry* RendererWebKitPlatformSupportImpl::mimeRegistry() { return mime_registry_.get(); } -WebKit::WebFileUtilities* +blink::WebFileUtilities* RendererWebKitPlatformSupportImpl::fileUtilities() { if (!file_utilities_) { file_utilities_.reset(new FileUtilities(thread_safe_sender_.get())); @@ -251,7 +255,7 @@ RendererWebKitPlatformSupportImpl::fileUtilities() { return file_utilities_.get(); } -WebKit::WebSandboxSupport* RendererWebKitPlatformSupportImpl::sandboxSupport() { +blink::WebSandboxSupport* RendererWebKitPlatformSupportImpl::sandboxSupport() { #if defined(OS_ANDROID) // WebKit doesn't use WebSandboxSupport on android. return NULL; @@ -260,13 +264,13 @@ WebKit::WebSandboxSupport* RendererWebKitPlatformSupportImpl::sandboxSupport() { #endif } -WebKit::WebCookieJar* RendererWebKitPlatformSupportImpl::cookieJar() { +blink::WebCookieJar* RendererWebKitPlatformSupportImpl::cookieJar() { NOTREACHED() << "Use WebFrameClient::cookieJar() instead!"; return NULL; } -WebKit::WebThemeEngine* RendererWebKitPlatformSupportImpl::themeEngine() { - WebKit::WebThemeEngine* theme_engine = +blink::WebThemeEngine* RendererWebKitPlatformSupportImpl::themeEngine() { + blink::WebThemeEngine* theme_engine = GetContentClient()->renderer()->OverrideThemeEngine(); if (theme_engine) return theme_engine; @@ -295,12 +299,12 @@ bool RendererWebKitPlatformSupportImpl::isLinkVisited( return GetContentClient()->renderer()->IsLinkVisited(link_hash); } -WebKit::WebMessagePortChannel* +blink::WebMessagePortChannel* RendererWebKitPlatformSupportImpl::createMessagePortChannel() { return new WebMessagePortChannelImpl(child_thread_loop_.get()); } -WebKit::WebPrescientNetworking* +blink::WebPrescientNetworking* RendererWebKitPlatformSupportImpl::prescientNetworking() { return GetContentClient()->renderer()->GetPrescientNetworking(); } @@ -318,7 +322,7 @@ RendererWebKitPlatformSupportImpl::CheckPreparsedJsCachingEnabled() const { } void RendererWebKitPlatformSupportImpl::cacheMetadata( - const WebKit::WebURL& url, + const blink::WebURL& url, double response_time, const char* data, size_t size) { @@ -366,9 +370,6 @@ RendererWebKitPlatformSupportImpl::createLocalStorageNamespace() { //------------------------------------------------------------------------------ WebIDBFactory* RendererWebKitPlatformSupportImpl::idbFactory() { - if (!web_idb_factory_) - web_idb_factory_.reset( - new RendererWebIDBFactoryImpl(thread_safe_sender_.get())); return web_idb_factory_.get(); } @@ -383,13 +384,6 @@ WebFileSystem* RendererWebKitPlatformSupportImpl::fileSystem() { WebMimeRegistry::SupportsType RendererWebKitPlatformSupportImpl::MimeRegistry::supportsMediaMIMEType( const WebString& mime_type, - const WebString& codecs) { - return supportsMediaMIMEType(mime_type, codecs, WebString()); -} - -WebMimeRegistry::SupportsType -RendererWebKitPlatformSupportImpl::MimeRegistry::supportsMediaMIMEType( - const WebString& mime_type, const WebString& codecs, const WebString& key_system) { const std::string mime_type_ascii = ToASCIIOrEmpty(mime_type); @@ -439,7 +433,7 @@ RendererWebKitPlatformSupportImpl::MimeRegistry::supportsMediaMIMEType( bool RendererWebKitPlatformSupportImpl::MimeRegistry::supportsMediaSourceMIMEType( - const WebKit::WebString& mime_type, + const blink::WebString& mime_type, const WebString& codecs) { const std::string mime_type_ascii = ToASCIIOrEmpty(mime_type); std::vector<std::string> parsed_codec_ids; @@ -557,11 +551,11 @@ bool RendererWebKitPlatformSupportImpl::SandboxSupport::loadFont( void RendererWebKitPlatformSupportImpl::SandboxSupport::getFontFamilyForCharacter( - WebKit::WebUChar32 character, + blink::WebUChar32 character, const char* preferred_locale, - WebKit::WebFontFamily* family) { + blink::WebFontFamily* family) { base::AutoLock lock(unicode_font_families_mutex_); - const std::map<int32_t, WebKit::WebFontFamily>::const_iterator iter = + const std::map<int32_t, blink::WebFontFamily>::const_iterator iter = unicode_font_families_.find(character); if (iter != unicode_font_families_.end()) { family->name = iter->second.name; @@ -576,7 +570,7 @@ RendererWebKitPlatformSupportImpl::SandboxSupport::getFontFamilyForCharacter( void RendererWebKitPlatformSupportImpl::SandboxSupport::getRenderStyleForStrike( - const char* family, int sizeAndStyle, WebKit::WebFontRenderStyle* out) { + const char* family, int sizeAndStyle, blink::WebFontRenderStyle* out) { GetRenderStyleForStrike(family, sizeAndStyle, out); } @@ -615,22 +609,6 @@ long long RendererWebKitPlatformSupportImpl::databaseGetSpaceAvailableForOrigin( sync_message_filter_.get()); } -WebKit::WebSharedWorkerRepository* -RendererWebKitPlatformSupportImpl::sharedWorkerRepository() { -#if !defined(OS_ANDROID) - if (!CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableSharedWorkers)) { - return shared_worker_repository_.get(); - } else { - return NULL; - } -#else - // Shared workers are unsupported on Android. Returning NULL will prevent the - // window.SharedWorker constructor from being exposed. http://crbug.com/154571 - return NULL; -#endif -} - bool RendererWebKitPlatformSupportImpl::canAccelerate2dCanvas() { RenderThreadImpl* thread = RenderThreadImpl::current(); GpuChannelHost* host = thread->EstablishGpuChannelSync( @@ -638,11 +616,7 @@ bool RendererWebKitPlatformSupportImpl::canAccelerate2dCanvas() { if (!host) return false; - const gpu::GPUInfo& gpu_info = host->gpu_info(); - if (gpu_info.can_lose_context || gpu_info.software_rendering) - return false; - - return true; + return host->gpu_info().SupportsAccelerated2dCanvas(); } bool RendererWebKitPlatformSupportImpl::isThreadedCompositingEnabled() { @@ -664,6 +638,10 @@ unsigned RendererWebKitPlatformSupportImpl::audioHardwareOutputChannels() { return thread->GetAudioHardwareConfig()->GetOutputChannels(); } +WebDatabaseObserver* RendererWebKitPlatformSupportImpl::databaseObserver() { + return web_database_observer_impl_.get(); +} + // TODO(crogers): remove deprecated API as soon as WebKit calls new API. WebAudioDevice* RendererWebKitPlatformSupportImpl::createAudioDevice( @@ -694,9 +672,9 @@ RendererWebKitPlatformSupportImpl::createAudioDevice( unsigned channels, double sample_rate, WebAudioDevice::RenderCallback* callback, - const WebKit::WebString& input_device_id) { + const blink::WebString& input_device_id) { // Use a mock for testing. - WebKit::WebAudioDevice* mock_device = + blink::WebAudioDevice* mock_device = GetContentClient()->renderer()->OverrideCreateAudioDevice(sample_rate); if (mock_device) return mock_device; @@ -748,14 +726,15 @@ RendererWebKitPlatformSupportImpl::createAudioDevice( media::AudioParameters params( media::AudioParameters::AUDIO_PCM_LOW_LATENCY, layout, input_channels, - static_cast<int>(sample_rate), 16, buffer_size); + static_cast<int>(sample_rate), 16, buffer_size, + media::AudioParameters::NO_EFFECTS); return new RendererWebAudioDeviceImpl(params, callback, session_id); } #if defined(OS_ANDROID) bool RendererWebKitPlatformSupportImpl::loadAudioResource( - WebKit::WebAudioBus* destination_bus, const char* audio_file_data, + blink::WebAudioBus* destination_bus, const char* audio_file_data, size_t data_size, double sample_rate) { return DecodeAudioFileData(destination_bus, audio_file_data, @@ -765,7 +744,7 @@ bool RendererWebKitPlatformSupportImpl::loadAudioResource( } #else bool RendererWebKitPlatformSupportImpl::loadAudioResource( - WebKit::WebAudioBus* destination_bus, const char* audio_file_data, + blink::WebAudioBus* destination_bus, const char* audio_file_data, size_t data_size, double sample_rate) { return DecodeAudioFileData( destination_bus, audio_file_data, data_size, sample_rate); @@ -774,18 +753,18 @@ bool RendererWebKitPlatformSupportImpl::loadAudioResource( //------------------------------------------------------------------------------ -WebKit::WebContentDecryptionModule* +blink::WebContentDecryptionModule* RendererWebKitPlatformSupportImpl::createContentDecryptionModule( - const WebKit::WebString& key_system) { + const blink::WebString& key_system) { return WebContentDecryptionModuleImpl::Create(key_system); } //------------------------------------------------------------------------------ -WebKit::WebMIDIAccessor* +blink::WebMIDIAccessor* RendererWebKitPlatformSupportImpl::createMIDIAccessor( - WebKit::WebMIDIAccessorClient* client) { - WebKit::WebMIDIAccessor* accessor = + blink::WebMIDIAccessorClient* client) { + blink::WebMIDIAccessor* accessor = GetContentClient()->renderer()->OverrideCreateMIDIAccessor(client); if (accessor) return accessor; @@ -795,7 +774,7 @@ RendererWebKitPlatformSupportImpl::createMIDIAccessor( void RendererWebKitPlatformSupportImpl::getPluginList( bool refresh, - WebKit::WebPluginListBuilder* builder) { + blink::WebPluginListBuilder* builder) { #if defined(ENABLE_PLUGINS) std::vector<WebPluginInfo> plugins; if (!plugin_refresh_allowed_) @@ -826,11 +805,18 @@ void RendererWebKitPlatformSupportImpl::getPluginList( //------------------------------------------------------------------------------ -WebKit::WebString +blink::WebPublicSuffixList* +RendererWebKitPlatformSupportImpl::publicSuffixList() { + return &public_suffix_list_; +} + +//------------------------------------------------------------------------------ + +blink::WebString RendererWebKitPlatformSupportImpl::signedPublicKeyAndChallengeString( unsigned key_size_index, - const WebKit::WebString& challenge, - const WebKit::WebURL& url) { + const blink::WebString& challenge, + const blink::WebURL& url) { std::string signed_public_key; RenderThread::Get()->Send(new ViewHostMsg_Keygen( static_cast<uint32>(key_size_index), @@ -844,18 +830,23 @@ RendererWebKitPlatformSupportImpl::signedPublicKeyAndChallengeString( void RendererWebKitPlatformSupportImpl::screenColorProfile( WebVector<char>* to_profile) { +#if defined(OS_WIN) + // On Windows screen color profile is only available in the browser. std::vector<char> profile; RenderThread::Get()->Send( new ViewHostMsg_GetMonitorColorProfile(&profile)); *to_profile = profile; +#else + // On other platforms color profile can be obtained directly. + gfx::ColorProfile profile; + *to_profile = profile.profile(); +#endif } //------------------------------------------------------------------------------ WebBlobRegistry* RendererWebKitPlatformSupportImpl::blobRegistry() { - // thread_safe_sender_ can be NULL when running some tests. - if (!blob_registry_.get() && thread_safe_sender_.get()) - blob_registry_.reset(new WebBlobRegistryImpl(thread_safe_sender_.get())); + // blob_registry_ can be NULL when running some tests. return blob_registry_.get(); } @@ -869,8 +860,8 @@ void RendererWebKitPlatformSupportImpl::sampleGamepads(WebGamepads& gamepads) { } } -WebKit::WebString RendererWebKitPlatformSupportImpl::userAgent( - const WebKit::WebURL& url) { +blink::WebString RendererWebKitPlatformSupportImpl::userAgent( + const blink::WebURL& url) { return WebKitPlatformSupportImpl::userAgent(url); } @@ -927,9 +918,9 @@ void RendererWebKitPlatformSupportImpl::SetMockGamepadsForTesting( //------------------------------------------------------------------------------ -WebKit::WebSpeechSynthesizer* +blink::WebSpeechSynthesizer* RendererWebKitPlatformSupportImpl::createSpeechSynthesizer( - WebKit::WebSpeechSynthesizerClient* client) { + blink::WebSpeechSynthesizerClient* client) { return GetContentClient()->renderer()->OverrideSpeechSynthesizer(client); } @@ -944,49 +935,65 @@ bool RendererWebKitPlatformSupportImpl::processMemorySizesInBytes( //------------------------------------------------------------------------------ -WebKit::WebGraphicsContext3D* +blink::WebGraphicsContext3D* RendererWebKitPlatformSupportImpl::createOffscreenGraphicsContext3D( - const WebKit::WebGraphicsContext3D::Attributes& attributes) { + const blink::WebGraphicsContext3D::Attributes& attributes) { + if (!RenderThreadImpl::current()) + return NULL; + + scoped_refptr<GpuChannelHost> gpu_channel_host( + RenderThreadImpl::current()->EstablishGpuChannelSync( + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)); + + WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits; + + CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kWebGLCommandBufferSizeKb)) { + std::string size_string = command_line->GetSwitchValueASCII( + switches::kWebGLCommandBufferSizeKb); + size_t buffer_size_kb; + if (base::StringToSizeT(size_string, &buffer_size_kb)) { + limits.command_buffer_size = buffer_size_kb * 1024; + } + } + return WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( - RenderThreadImpl::current(), + gpu_channel_host.get(), attributes, - GURL(attributes.topDocumentURL)); + GURL(attributes.topDocumentURL), + limits); } //------------------------------------------------------------------------------ -WebKit::WebGraphicsContext3DProvider* RendererWebKitPlatformSupportImpl:: +blink::WebGraphicsContext3DProvider* RendererWebKitPlatformSupportImpl:: createSharedOffscreenGraphicsContext3DProvider() { - if (!shared_offscreen_context_.get() || - shared_offscreen_context_->DestroyedOnMainThread()) { - shared_offscreen_context_ = - RenderThreadImpl::current()->OffscreenContextProviderForMainThread(); - } - if (!shared_offscreen_context_.get()) + scoped_refptr<cc::ContextProvider> provider = + RenderThreadImpl::current()->SharedMainThreadContextProvider(); + if (!provider) return NULL; - return new webkit::gpu::WebGraphicsContext3DProviderImpl( - shared_offscreen_context_); + return new webkit::gpu::WebGraphicsContext3DProviderImpl(provider); } //------------------------------------------------------------------------------ -WebKit::WebCompositorSupport* +blink::WebCompositorSupport* RendererWebKitPlatformSupportImpl::compositorSupport() { return &compositor_support_; } //------------------------------------------------------------------------------ -WebKit::WebString RendererWebKitPlatformSupportImpl::convertIDNToUnicode( - const WebKit::WebString& host, - const WebKit::WebString& languages) { +blink::WebString RendererWebKitPlatformSupportImpl::convertIDNToUnicode( + const blink::WebString& host, + const blink::WebString& languages) { return net::IDNToUnicode(host.utf8(), languages.utf8()); } //------------------------------------------------------------------------------ void RendererWebKitPlatformSupportImpl::setDeviceMotionListener( - WebKit::WebDeviceMotionListener* listener) { + blink::WebDeviceMotionListener* listener) { if (g_test_device_motion_data == 0) { if (!device_motion_event_pump_) { device_motion_event_pump_.reset(new DeviceMotionEventPump); @@ -997,7 +1004,7 @@ void RendererWebKitPlatformSupportImpl::setDeviceMotionListener( // Testing mode: just echo the test data to the listener. base::MessageLoopProxy::current()->PostTask( FROM_HERE, - base::Bind(&WebKit::WebDeviceMotionListener::didChangeDeviceMotion, + base::Bind(&blink::WebDeviceMotionListener::didChangeDeviceMotion, base::Unretained(listener), g_test_device_motion_data.Get())); } @@ -1005,14 +1012,14 @@ void RendererWebKitPlatformSupportImpl::setDeviceMotionListener( // static void RendererWebKitPlatformSupportImpl::SetMockDeviceMotionDataForTesting( - const WebKit::WebDeviceMotionData& data) { + const blink::WebDeviceMotionData& data) { g_test_device_motion_data.Get() = data; } //------------------------------------------------------------------------------ void RendererWebKitPlatformSupportImpl::setDeviceOrientationListener( - WebKit::WebDeviceOrientationListener* listener) { + blink::WebDeviceOrientationListener* listener) { if (g_test_device_orientation_data == 0) { if (!device_orientation_event_pump_) { device_orientation_event_pump_.reset(new DeviceOrientationEventPump); @@ -1024,7 +1031,7 @@ void RendererWebKitPlatformSupportImpl::setDeviceOrientationListener( base::MessageLoopProxy::current()->PostTask( FROM_HERE, base::Bind( - &WebKit::WebDeviceOrientationListener::didChangeDeviceOrientation, + &blink::WebDeviceOrientationListener::didChangeDeviceOrientation, base::Unretained(listener), g_test_device_orientation_data.Get())); } @@ -1032,19 +1039,13 @@ void RendererWebKitPlatformSupportImpl::setDeviceOrientationListener( // static void RendererWebKitPlatformSupportImpl::SetMockDeviceOrientationDataForTesting( - const WebKit::WebDeviceOrientationData& data) { + const blink::WebDeviceOrientationData& data) { g_test_device_orientation_data.Get() = data; } //------------------------------------------------------------------------------ -WebKit::WebCrypto* RendererWebKitPlatformSupportImpl::crypto() { - // Use a mock implementation for testing in-progress work. - WebKit::WebCrypto* crypto = - GetContentClient()->renderer()->OverrideWebCrypto(); - if (crypto) - return crypto; - +blink::WebCrypto* RendererWebKitPlatformSupportImpl::crypto() { if (!web_crypto_) web_crypto_.reset(new WebCryptoImpl()); return web_crypto_.get(); @@ -1053,7 +1054,6 @@ WebKit::WebCrypto* RendererWebKitPlatformSupportImpl::crypto() { //------------------------------------------------------------------------------ -#if defined(OS_ANDROID) void RendererWebKitPlatformSupportImpl::vibrate(unsigned int milliseconds) { RenderThread::Get()->Send( new ViewHostMsg_Vibrate(base::checked_numeric_cast<int64>(milliseconds))); @@ -1062,14 +1062,13 @@ void RendererWebKitPlatformSupportImpl::vibrate(unsigned int milliseconds) { void RendererWebKitPlatformSupportImpl::cancelVibration() { RenderThread::Get()->Send(new ViewHostMsg_CancelVibration()); } -#endif // defined(OS_ANDROID) //------------------------------------------------------------------------------ void RendererWebKitPlatformSupportImpl::queryStorageUsageAndQuota( - const WebKit::WebURL& storage_partition, - WebKit::WebStorageQuotaType type, - WebKit::WebStorageQuotaCallbacks* callbacks) { + const blink::WebURL& storage_partition, + blink::WebStorageQuotaType type, + blink::WebStorageQuotaCallbacks* callbacks) { if (!thread_safe_sender_.get() || !quota_message_filter_.get()) return; QuotaDispatcher::ThreadSpecificInstance( diff --git a/chromium/content/renderer/renderer_webkitplatformsupport_impl.h b/chromium/content/renderer/renderer_webkitplatformsupport_impl.h index 1ec2a6c89a1..ca772948a8d 100644 --- a/chromium/content/renderer/renderer_webkitplatformsupport_impl.h +++ b/chromium/content/renderer/renderer_webkitplatformsupport_impl.h @@ -10,7 +10,7 @@ #include "base/platform_file.h" #include "content/child/webkitplatformsupport_impl.h" #include "content/common/content_export.h" -#include "third_party/WebKit/public/web/WebSharedWorkerRepository.h" +#include "content/renderer/webpublicsuffixlist_impl.h" #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" #include "third_party/WebKit/public/platform/WebIDBFactory.h" #include "webkit/renderer/compositor_bindings/web_compositor_support_impl.h" @@ -27,7 +27,7 @@ namespace IPC { class SyncMessageFilter; } -namespace WebKit { +namespace blink { class WebDeviceMotionData; class WebDeviceOrientationData; class WebGraphicsContext3DProvider; @@ -41,8 +41,8 @@ class RendererClipboardClient; class ThreadSafeSender; class WebClipboardImpl; class WebCryptoImpl; +class WebDatabaseObserverImpl; class WebFileSystemImpl; -class WebSharedWorkerRepositoryImpl; class CONTENT_EXPORT RendererWebKitPlatformSupportImpl : public WebKitPlatformSupportImpl { @@ -54,104 +54,102 @@ class CONTENT_EXPORT RendererWebKitPlatformSupportImpl plugin_refresh_allowed_ = plugin_refresh_allowed; } // Platform methods: - virtual WebKit::WebClipboard* clipboard(); - virtual WebKit::WebMimeRegistry* mimeRegistry(); - virtual WebKit::WebFileUtilities* fileUtilities(); - virtual WebKit::WebSandboxSupport* sandboxSupport(); - virtual WebKit::WebCookieJar* cookieJar(); - virtual WebKit::WebThemeEngine* themeEngine(); - virtual WebKit::WebSpeechSynthesizer* createSpeechSynthesizer( - WebKit::WebSpeechSynthesizerClient* client); + virtual blink::WebClipboard* clipboard(); + virtual blink::WebMimeRegistry* mimeRegistry(); + virtual blink::WebFileUtilities* fileUtilities(); + virtual blink::WebSandboxSupport* sandboxSupport(); + virtual blink::WebCookieJar* cookieJar(); + virtual blink::WebThemeEngine* themeEngine(); + virtual blink::WebSpeechSynthesizer* createSpeechSynthesizer( + blink::WebSpeechSynthesizerClient* client); virtual bool sandboxEnabled(); virtual unsigned long long visitedLinkHash( const char* canonicalURL, size_t length); virtual bool isLinkVisited(unsigned long long linkHash); - virtual WebKit::WebMessagePortChannel* createMessagePortChannel(); - virtual WebKit::WebPrescientNetworking* prescientNetworking(); + virtual blink::WebMessagePortChannel* createMessagePortChannel(); + virtual blink::WebPrescientNetworking* prescientNetworking(); virtual void cacheMetadata( - const WebKit::WebURL&, double, const char*, size_t); - virtual WebKit::WebString defaultLocale(); + const blink::WebURL&, double, const char*, size_t); + virtual blink::WebString defaultLocale(); virtual void suddenTerminationChanged(bool enabled); - virtual WebKit::WebStorageNamespace* createLocalStorageNamespace(); - virtual WebKit::Platform::FileHandle databaseOpenFile( - const WebKit::WebString& vfs_file_name, int desired_flags); - virtual int databaseDeleteFile(const WebKit::WebString& vfs_file_name, + virtual blink::WebStorageNamespace* createLocalStorageNamespace(); + virtual blink::Platform::FileHandle databaseOpenFile( + const blink::WebString& vfs_file_name, int desired_flags); + virtual int databaseDeleteFile(const blink::WebString& vfs_file_name, bool sync_dir); virtual long databaseGetFileAttributes( - const WebKit::WebString& vfs_file_name); + const blink::WebString& vfs_file_name); virtual long long databaseGetFileSize( - const WebKit::WebString& vfs_file_name); + const blink::WebString& vfs_file_name); virtual long long databaseGetSpaceAvailableForOrigin( - const WebKit::WebString& origin_identifier); - virtual WebKit::WebString signedPublicKeyAndChallengeString( + const blink::WebString& origin_identifier); + virtual blink::WebString signedPublicKeyAndChallengeString( unsigned key_size_index, - const WebKit::WebString& challenge, - const WebKit::WebURL& url); + const blink::WebString& challenge, + const blink::WebURL& url); virtual void getPluginList(bool refresh, - WebKit::WebPluginListBuilder* builder); - virtual void screenColorProfile(WebKit::WebVector<char>* to_profile); - virtual WebKit::WebIDBFactory* idbFactory(); - virtual WebKit::WebFileSystem* fileSystem(); - virtual WebKit::WebSharedWorkerRepository* sharedWorkerRepository(); + blink::WebPluginListBuilder* builder); + virtual blink::WebPublicSuffixList* publicSuffixList(); + virtual void screenColorProfile(blink::WebVector<char>* to_profile); + virtual blink::WebIDBFactory* idbFactory(); + virtual blink::WebFileSystem* fileSystem(); virtual bool canAccelerate2dCanvas(); virtual bool isThreadedCompositingEnabled(); virtual double audioHardwareSampleRate(); virtual size_t audioHardwareBufferSize(); virtual unsigned audioHardwareOutputChannels(); + virtual blink::WebDatabaseObserver* databaseObserver(); // TODO(crogers): remove deprecated API as soon as WebKit calls new API. - virtual WebKit::WebAudioDevice* createAudioDevice( + virtual blink::WebAudioDevice* createAudioDevice( size_t buffer_size, unsigned channels, double sample_rate, - WebKit::WebAudioDevice::RenderCallback* callback); + blink::WebAudioDevice::RenderCallback* callback); // TODO(crogers): remove deprecated API as soon as WebKit calls new API. - virtual WebKit::WebAudioDevice* createAudioDevice( + virtual blink::WebAudioDevice* createAudioDevice( size_t buffer_size, unsigned input_channels, unsigned channels, - double sample_rate, WebKit::WebAudioDevice::RenderCallback* callback); + double sample_rate, blink::WebAudioDevice::RenderCallback* callback); - virtual WebKit::WebAudioDevice* createAudioDevice( + virtual blink::WebAudioDevice* createAudioDevice( size_t buffer_size, unsigned input_channels, unsigned channels, - double sample_rate, WebKit::WebAudioDevice::RenderCallback* callback, - const WebKit::WebString& input_device_id); + double sample_rate, blink::WebAudioDevice::RenderCallback* callback, + const blink::WebString& input_device_id); virtual bool loadAudioResource( - WebKit::WebAudioBus* destination_bus, const char* audio_file_data, + blink::WebAudioBus* destination_bus, const char* audio_file_data, size_t data_size, double sample_rate); - virtual WebKit::WebContentDecryptionModule* createContentDecryptionModule( - const WebKit::WebString& key_system); - virtual WebKit::WebMIDIAccessor* - createMIDIAccessor(WebKit::WebMIDIAccessorClient* client); - - virtual WebKit::WebBlobRegistry* blobRegistry(); - virtual void sampleGamepads(WebKit::WebGamepads&); - virtual WebKit::WebString userAgent(const WebKit::WebURL& url); - virtual WebKit::WebRTCPeerConnectionHandler* createRTCPeerConnectionHandler( - WebKit::WebRTCPeerConnectionHandlerClient* client); - virtual WebKit::WebMediaStreamCenter* createMediaStreamCenter( - WebKit::WebMediaStreamCenterClient* client); + virtual blink::WebContentDecryptionModule* createContentDecryptionModule( + const blink::WebString& key_system); + virtual blink::WebMIDIAccessor* + createMIDIAccessor(blink::WebMIDIAccessorClient* client); + + virtual blink::WebBlobRegistry* blobRegistry(); + virtual void sampleGamepads(blink::WebGamepads&); + virtual blink::WebString userAgent(const blink::WebURL& url); + virtual blink::WebRTCPeerConnectionHandler* createRTCPeerConnectionHandler( + blink::WebRTCPeerConnectionHandlerClient* client); + virtual blink::WebMediaStreamCenter* createMediaStreamCenter( + blink::WebMediaStreamCenterClient* client); virtual bool processMemorySizesInBytes( size_t* private_bytes, size_t* shared_bytes); - virtual WebKit::WebGraphicsContext3D* createOffscreenGraphicsContext3D( - const WebKit::WebGraphicsContext3D::Attributes& attributes); - virtual WebKit::WebGraphicsContext3DProvider* + virtual blink::WebGraphicsContext3D* createOffscreenGraphicsContext3D( + const blink::WebGraphicsContext3D::Attributes& attributes); + virtual blink::WebGraphicsContext3DProvider* createSharedOffscreenGraphicsContext3DProvider(); - virtual WebKit::WebCompositorSupport* compositorSupport(); - virtual WebKit::WebString convertIDNToUnicode( - const WebKit::WebString& host, const WebKit::WebString& languages); + virtual blink::WebCompositorSupport* compositorSupport(); + virtual blink::WebString convertIDNToUnicode( + const blink::WebString& host, const blink::WebString& languages); virtual void setDeviceMotionListener( - WebKit::WebDeviceMotionListener* listener) OVERRIDE; + blink::WebDeviceMotionListener* listener) OVERRIDE; virtual void setDeviceOrientationListener( - WebKit::WebDeviceOrientationListener* listener) OVERRIDE; - virtual WebKit::WebCrypto* crypto() OVERRIDE; + blink::WebDeviceOrientationListener* listener) OVERRIDE; + virtual blink::WebCrypto* crypto() OVERRIDE; virtual void queryStorageUsageAndQuota( - const WebKit::WebURL& storage_partition, - WebKit::WebStorageQuotaType, - WebKit::WebStorageQuotaCallbacks*) OVERRIDE; - -#if defined(OS_ANDROID) + const blink::WebURL& storage_partition, + blink::WebStorageQuotaType, + blink::WebStorageQuotaCallbacks*) OVERRIDE; virtual void vibrate(unsigned int milliseconds); virtual void cancelVibration(); -#endif // defined(OS_ANDROID) // Disables the WebSandboxSupport implementation for testing. // Tests that do not set up a full sandbox environment should call @@ -163,14 +161,18 @@ class CONTENT_EXPORT RendererWebKitPlatformSupportImpl static bool SetSandboxEnabledForTesting(bool enable); // Set WebGamepads to return when sampleGamepads() is invoked. - static void SetMockGamepadsForTesting(const WebKit::WebGamepads& pads); + static void SetMockGamepadsForTesting(const blink::WebGamepads& pads); // Set WebDeviceMotionData to return when setDeviceMotionListener is invoked. static void SetMockDeviceMotionDataForTesting( - const WebKit::WebDeviceMotionData& data); + const blink::WebDeviceMotionData& data); // Set WebDeviceOrientationData to return when setDeviceOrientationListener // is invoked. static void SetMockDeviceOrientationDataForTesting( - const WebKit::WebDeviceOrientationData& data); + const blink::WebDeviceOrientationData& data); + + WebDatabaseObserverImpl* web_database_observer_impl() { + return web_database_observer_impl_.get(); + } private: bool CheckPreparsedJsCachingEnabled() const; @@ -196,15 +198,11 @@ class CONTENT_EXPORT RendererWebKitPlatformSupportImpl // If true, then a GetPlugins call is allowed to rescan the disk. bool plugin_refresh_allowed_; - // Implementation of the WebSharedWorkerRepository APIs (provides an interface - // to WorkerService on the browser thread. - scoped_ptr<WebSharedWorkerRepositoryImpl> shared_worker_repository_; - - scoped_ptr<WebKit::WebIDBFactory> web_idb_factory_; + scoped_ptr<blink::WebIDBFactory> web_idb_factory_; - scoped_ptr<WebFileSystemImpl> web_file_system_; + scoped_ptr<blink::WebBlobRegistry> blob_registry_; - scoped_ptr<WebKit::WebBlobRegistry> blob_registry_; + WebPublicSuffixListImpl public_suffix_list_; scoped_ptr<DeviceMotionEventPump> device_motion_event_pump_; scoped_ptr<DeviceOrientationEventPump> device_orientation_event_pump_; @@ -214,7 +212,7 @@ class CONTENT_EXPORT RendererWebKitPlatformSupportImpl scoped_refptr<ThreadSafeSender> thread_safe_sender_; scoped_refptr<QuotaMessageFilter> quota_message_filter_; - scoped_refptr<cc::ContextProvider> shared_offscreen_context_; + scoped_ptr<WebDatabaseObserverImpl> web_database_observer_impl_; webkit::WebCompositorSupportImpl compositor_support_; diff --git a/chromium/content/renderer/resizing_mode_selector.cc b/chromium/content/renderer/resizing_mode_selector.cc new file mode 100644 index 00000000000..d51b4570627 --- /dev/null +++ b/chromium/content/renderer/resizing_mode_selector.cc @@ -0,0 +1,38 @@ +// 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/renderer/resizing_mode_selector.h" + +#include "content/common/view_messages.h" +#include "content/renderer/render_thread_impl.h" +#include "content/renderer/render_widget.h" +#include "third_party/WebKit/public/platform/WebScreenInfo.h" + +namespace content { + +ResizingModeSelector::ResizingModeSelector() : is_synchronous_mode_(false) {} + +bool ResizingModeSelector::NeverUsesSynchronousResize() const { + return !RenderThreadImpl::current() || // can be NULL when in unit tests + !RenderThreadImpl::current()->layout_test_mode(); +} + +bool ResizingModeSelector::ShouldAbortOnResize( + RenderWidget* widget, + const ViewMsg_Resize_Params& params) { + return is_synchronous_mode_ && + params.is_fullscreen == widget->is_fullscreen() && + params.screen_info.deviceScaleFactor == + widget->screenInfo().deviceScaleFactor; +} + +void ResizingModeSelector::set_is_synchronous_mode(bool mode) { + is_synchronous_mode_ = mode; +} + +bool ResizingModeSelector::is_synchronous_mode() const { + return is_synchronous_mode_; +} + +} // namespace content diff --git a/chromium/content/renderer/resizing_mode_selector.h b/chromium/content/renderer/resizing_mode_selector.h new file mode 100644 index 00000000000..ac657e294cd --- /dev/null +++ b/chromium/content/renderer/resizing_mode_selector.h @@ -0,0 +1,43 @@ +// 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_RENDERER_RESIZING_MODE_SELECTOR_H_ +#define CONTENT_RENDERER_RESIZING_MODE_SELECTOR_H_ + +#include "base/basictypes.h" + +struct ViewMsg_Resize_Params; + +namespace content { + +class RenderWidget; + +// Enables switching between two modes of resizing: +// 1) The "normal" (asynchronous) resizing, which involves sending messages to +// and receiving them from host; and +// 2) The synchronous mode, which short-circuits the resizing logic to operate +// strictly inside renderer. +// The latter is necessary to support a handful of layout tests that were +// written with the expectation of a synchronous resize, and we're going to +// eventually rewrite or remove all of them. See http://crbug.com/309760 for +// details. +class ResizingModeSelector { + public: + ResizingModeSelector(); + bool NeverUsesSynchronousResize() const; + bool ShouldAbortOnResize(RenderWidget* widget, + const ViewMsg_Resize_Params& params); + + void set_is_synchronous_mode(bool mode); + bool is_synchronous_mode() const; + + private: + bool is_synchronous_mode_; + + DISALLOW_COPY_AND_ASSIGN(ResizingModeSelector); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_RESIZING_MODE_SELECTOR_H_ diff --git a/chromium/content/renderer/resource_fetcher_browsertest.cc b/chromium/content/renderer/resource_fetcher_browsertest.cc index 573fe4d2b79..a9498cb0823 100644 --- a/chromium/content/renderer/resource_fetcher_browsertest.cc +++ b/chromium/content/renderer/resource_fetcher_browsertest.cc @@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/fetchers/resource_fetcher.h" +#include "content/public/renderer/resource_fetcher.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/command_line.h" #include "base/message_loop/message_loop.h" +#include "base/time/time.h" #include "base/timer/timer.h" #include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" @@ -20,9 +21,9 @@ #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebView.h" -using WebKit::WebFrame; -using WebKit::WebURLRequest; -using WebKit::WebURLResponse; +using blink::WebFrame; +using blink::WebURLRequest; +using blink::WebURLResponse; namespace content { @@ -108,10 +109,13 @@ class EvilFetcherDelegate : public FetcherDelegate { virtual void OnURLFetchComplete(const WebURLResponse& response, const std::string& data) OVERRIDE { + FetcherDelegate::OnURLFetchComplete(response, data); + // Destroy the ResourceFetcher here. We are testing that upon returning - // to the ResourceFetcher that it does not crash. + // to the ResourceFetcher that it does not crash. This must be done after + // calling FetcherDelegate::OnURLFetchComplete, since deleting the fetcher + // invalidates |response| and |data|. fetcher_.reset(); - FetcherDelegate::OnURLFetchComplete(response, data); } private: @@ -138,7 +142,7 @@ class ResourceFetcherTests : public ContentBrowserTest { WebFrame* frame = GetRenderView()->GetWebView()->mainFrame(); scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); - scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher( + scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create( url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback())); delegate->WaitForResponse(); @@ -153,7 +157,7 @@ class ResourceFetcherTests : public ContentBrowserTest { WebFrame* frame = GetRenderView()->GetWebView()->mainFrame(); scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); - scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher( + scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create( url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback())); delegate->WaitForResponse(); @@ -169,7 +173,7 @@ class ResourceFetcherTests : public ContentBrowserTest { // Try to fetch a page on a site that doesn't exist. GURL url("http://localhost:1339/doesnotexist"); scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); - scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher( + scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create( url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback())); delegate->WaitForResponse(); @@ -186,9 +190,10 @@ class ResourceFetcherTests : public ContentBrowserTest { WebFrame* frame = GetRenderView()->GetWebView()->mainFrame(); scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); - scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout( + scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create( url, frame, WebURLRequest::TargetIsMainFrame, - 0, delegate->NewCallback())); + delegate->NewCallback())); + fetcher->SetTimeout(base::TimeDelta()); delegate->WaitForResponse(); @@ -204,9 +209,10 @@ class ResourceFetcherTests : public ContentBrowserTest { WebFrame* frame = GetRenderView()->GetWebView()->mainFrame(); scoped_ptr<EvilFetcherDelegate> delegate(new EvilFetcherDelegate); - scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout( + scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create( url, frame, WebURLRequest::TargetIsMainFrame, - 0, delegate->NewCallback())); + delegate->NewCallback())); + fetcher->SetTimeout(base::TimeDelta()); delegate->SetFetcher(fetcher.release()); delegate->WaitForResponse(); diff --git a/chromium/content/renderer/resources/media/mediaplayer_remote_playback.png b/chromium/content/renderer/resources/media/mediaplayer_remote_playback.png Binary files differnew file mode 100644 index 00000000000..6916ce6dd67 --- /dev/null +++ b/chromium/content/renderer/resources/media/mediaplayer_remote_playback.png diff --git a/chromium/content/renderer/sad_plugin.cc b/chromium/content/renderer/sad_plugin.cc index a30788cf105..52d613d5d4f 100644 --- a/chromium/content/renderer/sad_plugin.cc +++ b/chromium/content/renderer/sad_plugin.cc @@ -13,7 +13,7 @@ namespace content { -void PaintSadPlugin(WebKit::WebCanvas* webcanvas, +void PaintSadPlugin(blink::WebCanvas* webcanvas, const gfx::Rect& plugin_rect, const SkBitmap& sad_plugin_bitmap) { const int width = plugin_rect.width(); diff --git a/chromium/content/renderer/sad_plugin.h b/chromium/content/renderer/sad_plugin.h index 827d705568b..4148c0ae086 100644 --- a/chromium/content/renderer/sad_plugin.h +++ b/chromium/content/renderer/sad_plugin.h @@ -17,7 +17,7 @@ namespace content { // Paints the sad plugin to the given canvas for the given plugin bounds. This // is used by both the NPAPI and the PPAPI out-of-process plugin impls. -void PaintSadPlugin(WebKit::WebCanvas* canvas, +void PaintSadPlugin(blink::WebCanvas* canvas, const gfx::Rect& plugin_rect, const SkBitmap& sad_plugin_bitmap); diff --git a/chromium/content/renderer/savable_resources.cc b/chromium/content/renderer/savable_resources.cc index f1b2fde4474..5e5e0478008 100644 --- a/chromium/content/renderer/savable_resources.cc +++ b/chromium/content/renderer/savable_resources.cc @@ -20,16 +20,16 @@ #include "third_party/WebKit/public/web/WebNodeList.h" #include "third_party/WebKit/public/web/WebView.h" -using WebKit::WebDocument; -using WebKit::WebElement; -using WebKit::WebFrame; -using WebKit::WebInputElement; -using WebKit::WebNode; -using WebKit::WebNodeCollection; -using WebKit::WebNodeList; -using WebKit::WebString; -using WebKit::WebVector; -using WebKit::WebView; +using blink::WebDocument; +using blink::WebElement; +using blink::WebFrame; +using blink::WebInputElement; +using blink::WebNode; +using blink::WebNodeCollection; +using blink::WebNodeList; +using blink::WebString; +using blink::WebVector; +using blink::WebView; namespace content { namespace { @@ -97,7 +97,7 @@ void GetSavableResourceLinkForElement( result->resources_list->push_back(u); // Insert referrer for above new resource link. result->referrer_urls_list->push_back(GURL()); - result->referrer_policies_list->push_back(WebKit::WebReferrerPolicyDefault); + result->referrer_policies_list->push_back(blink::WebReferrerPolicyDefault); } // Get all savable resource links from current WebFrameImpl object pointer. diff --git a/chromium/content/renderer/savable_resources.h b/chromium/content/renderer/savable_resources.h index 52b51144cd7..94326927b4a 100644 --- a/chromium/content/renderer/savable_resources.h +++ b/chromium/content/renderer/savable_resources.h @@ -12,7 +12,7 @@ #include "third_party/WebKit/public/platform/WebReferrerPolicy.h" #include "url/gurl.h" -namespace WebKit { +namespace blink { class WebElement; class WebString; class WebView; @@ -32,7 +32,7 @@ struct SavableResourcesResult { // it matched with links one by one. std::vector<GURL>* referrer_urls_list; // and the corresponding referrer policies. - std::vector<WebKit::WebReferrerPolicy>* referrer_policies_list; + std::vector<blink::WebReferrerPolicy>* referrer_policies_list; // vector which contains all savable links of main frame and sub frames. std::vector<GURL>* frames_list; @@ -40,7 +40,7 @@ struct SavableResourcesResult { SavableResourcesResult( std::vector<GURL>* resources_list, std::vector<GURL>* referrer_urls_list, - std::vector<WebKit::WebReferrerPolicy>* referrer_policies_list, + std::vector<blink::WebReferrerPolicy>* referrer_policies_list, std::vector<GURL>* frames_list) : resources_list(resources_list), referrer_urls_list(referrer_urls_list), @@ -56,7 +56,7 @@ struct SavableResourcesResult { // will send those links to embedder. Return value indicates whether we get // all saved resource links successfully. CONTENT_EXPORT bool GetAllSavableResourceLinksForCurrentPage( - WebKit::WebView* view, + blink::WebView* view, const GURL& page_url, SavableResourcesResult* savable_resources_result, const char** savable_schemes); @@ -66,8 +66,8 @@ CONTENT_EXPORT bool GetAllSavableResourceLinksForCurrentPage( // the value in "href". For BODY, TABLE, TR, TD, returns the value in // "background". For BLOCKQUOTE, Q, DEL, INS, returns the value in "cite" // attribute. Otherwise returns a null WebString. -CONTENT_EXPORT WebKit::WebString GetSubResourceLinkFromElement( - const WebKit::WebElement& element); +CONTENT_EXPORT blink::WebString GetSubResourceLinkFromElement( + const blink::WebElement& element); } // namespace content diff --git a/chromium/content/renderer/savable_resources_browsertest.cc b/chromium/content/renderer/savable_resources_browsertest.cc index a7ad83ac266..5f7a0ca4805 100644 --- a/chromium/content/renderer/savable_resources_browsertest.cc +++ b/chromium/content/renderer/savable_resources_browsertest.cc @@ -53,7 +53,7 @@ class SavableResourcesTest : public ContentBrowserTest { // Get all savable resource links for the page. std::vector<GURL> resources_list; std::vector<GURL> referrer_urls_list; - std::vector<WebKit::WebReferrerPolicy> referrer_policies_list; + std::vector<blink::WebReferrerPolicy> referrer_policies_list; std::vector<GURL> frames_list; SavableResourcesResult result(&resources_list, &referrer_urls_list, diff --git a/chromium/content/renderer/scoped_clipboard_writer_glue.cc b/chromium/content/renderer/scoped_clipboard_writer_glue.cc index 4403952b3a4..37790375303 100644 --- a/chromium/content/renderer/scoped_clipboard_writer_glue.cc +++ b/chromium/content/renderer/scoped_clipboard_writer_glue.cc @@ -9,7 +9,7 @@ namespace content { ScopedClipboardWriterGlue::ScopedClipboardWriterGlue(ClipboardClient* client) : ui::ScopedClipboardWriter(client->GetClipboard(), - ui::Clipboard::BUFFER_STANDARD), + ui::CLIPBOARD_TYPE_COPY_PASTE), context_(client->CreateWriteContext()) { // We should never have an instance where both are set. DCHECK((clipboard_ && !context_.get()) || @@ -27,7 +27,7 @@ void ScopedClipboardWriterGlue::WriteBitmapFromPixels(const void* pixels, if (context_) { context_->WriteBitmapFromPixels(&objects_, pixels, size); } else { - ScopedClipboardWriter::WriteBitmapFromPixels(pixels, size); + NOTREACHED(); } } diff --git a/chromium/content/renderer/service_worker/OWNERS b/chromium/content/renderer/service_worker/OWNERS new file mode 100644 index 00000000000..633b8a4fd96 --- /dev/null +++ b/chromium/content/renderer/service_worker/OWNERS @@ -0,0 +1,3 @@ +alecflett@chromium.org +kinuko@chromium.org +michaeln@chromium.org diff --git a/chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc b/chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc new file mode 100644 index 00000000000..0aa4ab2d820 --- /dev/null +++ b/chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc @@ -0,0 +1,94 @@ +// 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/renderer/service_worker/embedded_worker_dispatcher.h" + +#include "base/memory/scoped_ptr.h" +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" +#include "content/child/child_process.h" +#include "content/child/scoped_child_process_reference.h" +#include "content/child/thread_safe_sender.h" +#include "content/common/service_worker_messages.h" +#include "content/renderer/render_thread_impl.h" +#include "content/renderer/service_worker/service_worker_context_client.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/platform/WebURL.h" +#include "third_party/WebKit/public/web/WebEmbeddedWorker.h" +#include "third_party/WebKit/public/web/WebEmbeddedWorkerStartData.h" +#include "webkit/child/worker_task_runner.h" +#include "webkit/common/user_agent/user_agent.h" + +namespace content { + +// A thin wrapper of WebEmbeddedWorker which also adds and releases process +// references automatically. +class EmbeddedWorkerDispatcher::WorkerWrapper { + public: + explicit WorkerWrapper(blink::WebEmbeddedWorker* worker) : worker_(worker) {} + ~WorkerWrapper() {} + + blink::WebEmbeddedWorker* worker() { return worker_.get(); } + + private: + ScopedChildProcessReference process_ref_; + scoped_ptr<blink::WebEmbeddedWorker> worker_; +}; + +EmbeddedWorkerDispatcher::EmbeddedWorkerDispatcher() : weak_factory_(this) {} + +EmbeddedWorkerDispatcher::~EmbeddedWorkerDispatcher() {} + +bool EmbeddedWorkerDispatcher::OnMessageReceived( + const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerDispatcher, message) + IPC_MESSAGE_HANDLER(ServiceWorkerMsg_StartWorker, OnStartWorker) + IPC_MESSAGE_HANDLER(ServiceWorkerMsg_TerminateWorker, OnTerminateWorker) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void EmbeddedWorkerDispatcher::WorkerContextDestroyed( + int embedded_worker_id) { + workers_.Remove(embedded_worker_id); +} + +void EmbeddedWorkerDispatcher::OnStartWorker( + int embedded_worker_id, + int64 service_worker_version_id, + const GURL& script_url) { + DCHECK(!workers_.Lookup(embedded_worker_id)); + scoped_ptr<WorkerWrapper> wrapper(new WorkerWrapper( + blink::WebEmbeddedWorker::create( + new ServiceWorkerContextClient( + embedded_worker_id, + service_worker_version_id, + script_url), + NULL))); + + blink::WebEmbeddedWorkerStartData start_data; + start_data.scriptURL = script_url; + start_data.userAgent = + base::UTF8ToUTF16(webkit_glue::GetUserAgent(script_url)); + + wrapper->worker()->startWorkerContext(start_data); + workers_.AddWithID(wrapper.release(), embedded_worker_id); +} + +void EmbeddedWorkerDispatcher::OnTerminateWorker(int embedded_worker_id) { + WorkerWrapper* wrapper = workers_.Lookup(embedded_worker_id); + if (!wrapper) { + LOG(WARNING) << "Got OnTerminateWorker for nonexistent worker"; + return; + } + + // This should eventually call WorkerContextDestroyed. (We may need to post + // a delayed task to forcibly abort the worker context if we find it + // necessary) + wrapper->worker()->terminateWorkerContext(); +} + +} // namespace content diff --git a/chromium/content/renderer/service_worker/embedded_worker_dispatcher.h b/chromium/content/renderer/service_worker/embedded_worker_dispatcher.h new file mode 100644 index 00000000000..d4dd6626c5a --- /dev/null +++ b/chromium/content/renderer/service_worker/embedded_worker_dispatcher.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_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_DISPATCHER_H_ +#define CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_DISPATCHER_H_ + +#include "base/basictypes.h" +#include "base/id_map.h" +#include "base/memory/weak_ptr.h" +#include "ipc/ipc_listener.h" + +struct ServiceWorkerMsg_StartWorker_Params; +class GURL; + +namespace WebKit { +class WebEmbeddedWorker; +} + +namespace content { + +// A tiny dispatcher which handles embedded worker start/stop messages. +class EmbeddedWorkerDispatcher : public IPC::Listener { + public: + EmbeddedWorkerDispatcher(); + virtual ~EmbeddedWorkerDispatcher(); + + // IPC::Listener overrides. + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + void WorkerContextDestroyed(int embedded_worker_id); + + private: + class WorkerWrapper; + + void OnStartWorker(int embedded_worker_id, + int64 service_worker_version_id, + const GURL& script_url); + void OnTerminateWorker(int embedded_worker_id); + + IDMap<WorkerWrapper, IDMapOwnPointer> workers_; + base::WeakPtrFactory<EmbeddedWorkerDispatcher> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerDispatcher); +}; + +} // namespace content + +#endif // CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_DISPATCHER_H_ diff --git a/chromium/content/renderer/service_worker/service_worker_context_client.cc b/chromium/content/renderer/service_worker/service_worker_context_client.cc new file mode 100644 index 00000000000..412ed674800 --- /dev/null +++ b/chromium/content/renderer/service_worker/service_worker_context_client.cc @@ -0,0 +1,98 @@ +// 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/renderer/service_worker/service_worker_context_client.h" + +#include "base/lazy_instance.h" +#include "base/message_loop/message_loop_proxy.h" +#include "base/pickle.h" +#include "base/threading/thread_local.h" +#include "content/child/thread_safe_sender.h" +#include "content/renderer/render_thread_impl.h" +#include "content/renderer/service_worker/embedded_worker_dispatcher.h" +#include "ipc/ipc_message_macros.h" +#include "third_party/WebKit/public/platform/WebString.h" +#include "webkit/child/worker_task_runner.h" + +using webkit_glue::WorkerTaskRunner; + +namespace content { + +namespace { + +// For now client must be a per-thread instance. +// TODO(kinuko): This needs to be refactored when we start using thread pool +// or having multiple clients per one thread. +base::LazyInstance<base::ThreadLocalPointer<ServiceWorkerContextClient> >:: + Leaky g_worker_client_tls = LAZY_INSTANCE_INITIALIZER; + +void CallWorkerContextDestroyedOnMainThread(int embedded_worker_id) { + if (!RenderThreadImpl::current() || + !RenderThreadImpl::current()->embedded_worker_dispatcher()) + return; + RenderThreadImpl::current()->embedded_worker_dispatcher()-> + WorkerContextDestroyed(embedded_worker_id); +} + +} // namespace + +ServiceWorkerContextClient* +ServiceWorkerContextClient::ThreadSpecificInstance() { + return g_worker_client_tls.Pointer()->Get(); +} + +ServiceWorkerContextClient::ServiceWorkerContextClient( + int embedded_worker_id, + int64 service_worker_version_id, + const GURL& script_url) + : embedded_worker_id_(embedded_worker_id), + service_worker_version_id_(service_worker_version_id), + script_url_(script_url), + sender_(ChildThread::current()->thread_safe_sender()), + main_thread_proxy_(base::MessageLoopProxy::current()), + proxy_(NULL) { +} + +ServiceWorkerContextClient::~ServiceWorkerContextClient() { + DCHECK(g_worker_client_tls.Pointer()->Get() != NULL); + g_worker_client_tls.Pointer()->Set(NULL); +} + +bool ServiceWorkerContextClient::OnMessageReceived( + const IPC::Message& msg) { + NOTIMPLEMENTED(); + return false; +} + +void ServiceWorkerContextClient::workerContextFailedToStart() +{ + DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); + DCHECK(!proxy_); + + RenderThreadImpl::current()->embedded_worker_dispatcher()-> + WorkerContextDestroyed(embedded_worker_id_); +} + +void ServiceWorkerContextClient::workerContextStarted( + blink::WebServiceWorkerContextProxy* proxy) { + DCHECK_NE(0, WorkerTaskRunner::Instance()->CurrentWorkerId()); + DCHECK(g_worker_client_tls.Pointer()->Get() == NULL); + g_worker_client_tls.Pointer()->Set(this); + proxy_ = proxy; + + // TODO(kinuko): Send WorkerStarted message to the browser with the + // current thread ID so that the browser can start sending embedded worker + // messages directly to this client. +} + +void ServiceWorkerContextClient::workerContextDestroyed() { + DCHECK_NE(0, WorkerTaskRunner::Instance()->CurrentWorkerId()); + proxy_ = NULL; + main_thread_proxy_->PostTask( + FROM_HERE, + base::Bind(&CallWorkerContextDestroyedOnMainThread, + embedded_worker_id_)); +} + +} // namespace content diff --git a/chromium/content/renderer/service_worker/service_worker_context_client.h b/chromium/content/renderer/service_worker/service_worker_context_client.h new file mode 100644 index 00000000000..e59cc62a84a --- /dev/null +++ b/chromium/content/renderer/service_worker/service_worker_context_client.h @@ -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. + +#ifndef CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_CLIENT_H_ +#define CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_CLIENT_H_ + +#include "base/memory/ref_counted.h" +#include "base/strings/string16.h" +#include "ipc/ipc_listener.h" +#include "third_party/WebKit/public/web/WebServiceWorkerContextClient.h" +#include "url/gurl.h" + +namespace base { +class MessageLoopProxy; +} + +namespace content { + +class ThreadSafeSender; + +// This class provides access to/from an embedded worker's WorkerGlobalScope. +// All methods other than the constructor (it's created on the main thread) +// are called on the worker thread. +class ServiceWorkerContextClient + : public blink::WebServiceWorkerContextClient { + public: + // Returns a thread-specific client instance. This does NOT create a + // new instance. + static ServiceWorkerContextClient* ThreadSpecificInstance(); + + ServiceWorkerContextClient(int embedded_worker_id, + int64 service_worker_version_id, + const GURL& script_url); + + virtual ~ServiceWorkerContextClient(); + + bool OnMessageReceived(const IPC::Message& msg); + + // WebServiceWorkerContextClient overrides. + virtual void workerContextFailedToStart(); + virtual void workerContextStarted(blink::WebServiceWorkerContextProxy* proxy); + virtual void workerContextDestroyed(); + + // TODO: Implement DevTools related method overrides. + + int embedded_worker_id() const { return embedded_worker_id_; } + + private: + const int embedded_worker_id_; + const int64 service_worker_version_id_; + const GURL script_url_; + scoped_refptr<ThreadSafeSender> sender_; + scoped_refptr<base::MessageLoopProxy> main_thread_proxy_; + + blink::WebServiceWorkerContextProxy* proxy_; + + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextClient); +}; + +} // namespace content + +#endif // CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_CLIENT_H_ diff --git a/chromium/content/renderer/shared_worker_repository.cc b/chromium/content/renderer/shared_worker_repository.cc new file mode 100644 index 00000000000..1ccc9e82002 --- /dev/null +++ b/chromium/content/renderer/shared_worker_repository.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/renderer/shared_worker_repository.h" + +#include "content/child/child_thread.h" +#include "content/common/view_messages.h" +#include "content/renderer/render_view_impl.h" +#include "content/renderer/websharedworker_proxy.h" +#include "third_party/WebKit/public/web/WebView.h" + +namespace content { + +SharedWorkerRepository::SharedWorkerRepository(RenderViewImpl* render_view) + : RenderViewObserver(render_view) { + render_view->GetWebView()->setSharedWorkerRepositoryClient(this); +} + +SharedWorkerRepository::~SharedWorkerRepository() {} + +blink::WebSharedWorkerConnector* +SharedWorkerRepository::createSharedWorkerConnector( + const blink::WebURL& url, + const blink::WebString& name, + DocumentID document_id) { + int route_id = MSG_ROUTING_NONE; + bool exists = false; + bool url_mismatch = false; + ViewHostMsg_CreateWorker_Params params; + params.url = url; + params.name = name; + params.document_id = document_id; + params.render_view_route_id = render_view()->GetRoutingID(); + params.route_id = MSG_ROUTING_NONE; + params.script_resource_appcache_id = 0; + Send(new ViewHostMsg_LookupSharedWorker( + params, &exists, &route_id, &url_mismatch)); + if (url_mismatch) + return NULL; + documents_with_workers_.insert(document_id); + return new WebSharedWorkerProxy(ChildThread::current(), + document_id, + exists, + route_id, + render_view()->GetRoutingID()); +} + +void SharedWorkerRepository::documentDetached(DocumentID document) { + std::set<DocumentID>::iterator iter = documents_with_workers_.find(document); + if (iter != documents_with_workers_.end()) { + // Notify the browser process that the document has shut down. + Send(new ViewHostMsg_DocumentDetached(document)); + documents_with_workers_.erase(iter); + } +} + +} // namespace content diff --git a/chromium/content/renderer/shared_worker_repository.h b/chromium/content/renderer/shared_worker_repository.h new file mode 100644 index 00000000000..ce3b53c4978 --- /dev/null +++ b/chromium/content/renderer/shared_worker_repository.h @@ -0,0 +1,39 @@ +// 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_RENDERER_SHARED_WORKER_REPOSITORY_H_ +#define CONTENT_RENDERER_SHARED_WORKER_REPOSITORY_H_ + +#include <set> + +#include "base/basictypes.h" +#include "content/public/renderer/render_view_observer.h" +#include "third_party/WebKit/public/web/WebSharedWorkerRepositoryClient.h" + +namespace content { + +class RenderViewImpl; + +class SharedWorkerRepository : public RenderViewObserver, + public blink::WebSharedWorkerRepositoryClient { + public: + explicit SharedWorkerRepository(RenderViewImpl* render_view); + virtual ~SharedWorkerRepository(); + + // WebSharedWorkerRepositoryClient overrides. + virtual blink::WebSharedWorkerConnector* createSharedWorkerConnector( + const blink::WebURL& url, + const blink::WebString& name, + DocumentID document_id) OVERRIDE; + virtual void documentDetached(DocumentID document_id) OVERRIDE; + + private: + std::set<DocumentID> documents_with_workers_; + + DISALLOW_COPY_AND_ASSIGN(SharedWorkerRepository); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_SHARED_WORKER_REPOSITORY_H_ diff --git a/chromium/content/renderer/skia_benchmarking_extension.cc b/chromium/content/renderer/skia_benchmarking_extension.cc index 3890e985c9d..d19dd62c854 100644 --- a/chromium/content/renderer/skia_benchmarking_extension.cc +++ b/chromium/content/renderer/skia_benchmarking_extension.cc @@ -24,28 +24,31 @@ #include "ui/gfx/skia_util.h" #include "v8/include/v8.h" -using WebKit::WebFrame; +using blink::WebFrame; namespace { const char kSkiaBenchmarkingExtensionName[] = "v8/SkiaBenchmarking"; -static scoped_ptr<base::Value> ParsePictureArg(v8::Handle<v8::Value> arg) { +static scoped_ptr<base::Value> ParsePictureArg(v8::Isolate* isolate, + v8::Handle<v8::Value> arg) { scoped_ptr<content::V8ValueConverter> converter( content::V8ValueConverter::create()); return scoped_ptr<base::Value>( - converter->FromV8Value(arg, v8::Context::GetCurrent())); + converter->FromV8Value(arg, isolate->GetCurrentContext())); } -static scoped_refptr<cc::Picture> ParsePictureStr(v8::Handle<v8::Value> arg) { - scoped_ptr<base::Value> picture_value = ParsePictureArg(arg); +static scoped_refptr<cc::Picture> ParsePictureStr(v8::Isolate* isolate, + v8::Handle<v8::Value> arg) { + scoped_ptr<base::Value> picture_value = ParsePictureArg(isolate, arg); if (!picture_value) return NULL; return cc::Picture::CreateFromSkpValue(picture_value.get()); } -static scoped_refptr<cc::Picture> ParsePictureHash(v8::Handle<v8::Value> arg) { - scoped_ptr<base::Value> picture_value = ParsePictureArg(arg); +static scoped_refptr<cc::Picture> ParsePictureHash(v8::Isolate* isolate, + v8::Handle<v8::Value> arg) { + scoped_ptr<base::Value> picture_value = ParsePictureArg(isolate, arg); if (!picture_value) return NULL; return cc::Picture::CreateFromValue(picture_value.get()); @@ -118,16 +121,17 @@ class SkiaBenchmarkingWrapper : public v8::Extension { content::SkiaBenchmarkingExtension::InitSkGraphics(); } - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( + virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate( + v8::Isolate* isolate, v8::Handle<v8::String> name) OVERRIDE { - if (name->Equals(v8::String::New("Rasterize"))) - return v8::FunctionTemplate::New(Rasterize); - if (name->Equals(v8::String::New("GetOps"))) - return v8::FunctionTemplate::New(GetOps); - if (name->Equals(v8::String::New("GetOpTimings"))) - return v8::FunctionTemplate::New(GetOpTimings); - if (name->Equals(v8::String::New("GetInfo"))) - return v8::FunctionTemplate::New(GetInfo); + if (name->Equals(v8::String::NewFromUtf8(isolate, "Rasterize"))) + return v8::FunctionTemplate::New(isolate, Rasterize); + if (name->Equals(v8::String::NewFromUtf8(isolate, "GetOps"))) + return v8::FunctionTemplate::New(isolate, GetOps); + if (name->Equals(v8::String::NewFromUtf8(isolate, "GetOpTimings"))) + return v8::FunctionTemplate::New(isolate, GetOpTimings); + if (name->Equals(v8::String::NewFromUtf8(isolate, "GetInfo"))) + return v8::FunctionTemplate::New(isolate, GetInfo); return v8::Handle<v8::FunctionTemplate>(); } @@ -136,7 +140,8 @@ class SkiaBenchmarkingWrapper : public v8::Extension { if (args.Length() < 1) return; - scoped_refptr<cc::Picture> picture = ParsePictureHash(args[0]); + v8::Isolate* isolate = args.GetIsolate(); + scoped_refptr<cc::Picture> picture = ParsePictureHash(isolate, args[0]); if (!picture.get()) return; @@ -149,7 +154,7 @@ class SkiaBenchmarkingWrapper : public v8::Extension { scoped_ptr<content::V8ValueConverter> converter( content::V8ValueConverter::create()); scoped_ptr<base::Value> params_value( - converter->FromV8Value(args[1], v8::Context::GetCurrent())); + converter->FromV8Value(args[1], isolate->GetCurrentContext())); const base::DictionaryValue* params_dict = NULL; if (params_value.get() && params_value->GetAsDictionary(¶ms_dict)) { @@ -195,13 +200,15 @@ class SkiaBenchmarkingWrapper : public v8::Extension { // Raster the requested command subset into the bitmap-backed canvas. int last_index = debug_canvas.getSize() - 1; - debug_canvas.setOverdrawViz(overdraw); - debug_canvas.drawTo(&canvas, stop_index < 0 - ? last_index - : std::min(last_index, stop_index)); + if (last_index >= 0) { + debug_canvas.setOverdrawViz(overdraw); + debug_canvas.drawTo(&canvas, stop_index < 0 + ? last_index + : std::min(last_index, stop_index)); + } - WebKit::WebArrayBuffer buffer = - WebKit::WebArrayBuffer::create(bitmap.getSize(), 1); + blink::WebArrayBuffer buffer = + blink::WebArrayBuffer::create(bitmap.getSize(), 1); uint32* packed_pixels = reinterpret_cast<uint32*>(bitmap.getPixels()); uint8* buffer_pixels = reinterpret_cast<uint8*>(buffer.data()); // Swizzle from native Skia format to RGBA as we copy out. @@ -214,11 +221,11 @@ class SkiaBenchmarkingWrapper : public v8::Extension { } v8::Handle<v8::Object> result = v8::Object::New(); - result->Set(v8::String::New("width"), + result->Set(v8::String::NewFromUtf8(isolate, "width"), v8::Number::New(snapped_clip.width())); - result->Set(v8::String::New("height"), + result->Set(v8::String::NewFromUtf8(isolate, "height"), v8::Number::New(snapped_clip.height())); - result->Set(v8::String::New("data"), buffer.toV8Value()); + result->Set(v8::String::NewFromUtf8(isolate, "data"), buffer.toV8Value()); args.GetReturnValue().Set(result); } @@ -227,7 +234,8 @@ class SkiaBenchmarkingWrapper : public v8::Extension { if (args.Length() != 1) return; - scoped_refptr<cc::Picture> picture = ParsePictureHash(args[0]); + v8::Isolate* isolate = args.GetIsolate(); + scoped_refptr<cc::Picture> picture = ParsePictureHash(isolate, args[0]); if (!picture.get()) return; @@ -235,25 +243,27 @@ class SkiaBenchmarkingWrapper : public v8::Extension { SkDebugCanvas canvas(bounds.width(), bounds.height()); picture->Replay(&canvas); - v8::Local<v8::Array> result = v8::Array::New(canvas.getSize()); + v8::Local<v8::Array> result = v8::Array::New(isolate, canvas.getSize()); for (int i = 0; i < canvas.getSize(); ++i) { DrawType cmd_type = canvas.getDrawCommandAt(i)->getType(); v8::Handle<v8::Object> cmd = v8::Object::New(); - cmd->Set(v8::String::New("cmd_type"), v8::Integer::New(cmd_type)); - cmd->Set(v8::String::New("cmd_string"), v8::String::New( - SkDrawCommand::GetCommandString(cmd_type))); + cmd->Set(v8::String::NewFromUtf8(isolate, "cmd_type"), + v8::Integer::New(isolate, cmd_type)); + cmd->Set(v8::String::NewFromUtf8(isolate, "cmd_string"), + v8::String::NewFromUtf8( + isolate, SkDrawCommand::GetCommandString(cmd_type))); SkTDArray<SkString*>* info = canvas.getCommandInfo(i); DCHECK(info); - v8::Local<v8::Array> v8_info = v8::Array::New(info->count()); + v8::Local<v8::Array> v8_info = v8::Array::New(isolate, info->count()); for (int j = 0; j < info->count(); ++j) { const SkString* info_str = (*info)[j]; DCHECK(info_str); - v8_info->Set(j, v8::String::New(info_str->c_str())); + v8_info->Set(j, v8::String::NewFromUtf8(isolate, info_str->c_str())); } - cmd->Set(v8::String::New("info"), v8_info); + cmd->Set(v8::String::NewFromUtf8(isolate, "info"), v8_info); result->Set(i, cmd); } @@ -265,7 +275,8 @@ class SkiaBenchmarkingWrapper : public v8::Extension { if (args.Length() != 1) return; - scoped_refptr<cc::Picture> picture = ParsePictureHash(args[0]); + v8::Isolate* isolate = args.GetIsolate(); + scoped_refptr<cc::Picture> picture = ParsePictureHash(isolate, args[0]); if (!picture.get()) return; @@ -287,14 +298,14 @@ class SkiaBenchmarkingWrapper : public v8::Extension { picture->Replay(&benchmarking_canvas); v8::Local<v8::Array> op_times = - v8::Array::New(benchmarking_canvas.CommandCount()); + v8::Array::New(isolate, benchmarking_canvas.CommandCount()); for (size_t i = 0; i < benchmarking_canvas.CommandCount(); ++i) op_times->Set(i, v8::Number::New(benchmarking_canvas.GetTime(i))); - v8::Handle<v8::Object> result = v8::Object::New(); - result->Set(v8::String::New("total_time"), + v8::Handle<v8::Object> result = v8::Object::New(isolate); + result->Set(v8::String::NewFromUtf8(isolate, "total_time"), v8::Number::New(total_time.InMillisecondsF())); - result->Set(v8::String::New("cmd_times"), op_times); + result->Set(v8::String::NewFromUtf8(isolate, "cmd_times"), op_times); args.GetReturnValue().Set(result); } @@ -303,14 +314,15 @@ class SkiaBenchmarkingWrapper : public v8::Extension { if (args.Length() != 1) return; - scoped_refptr<cc::Picture> picture = ParsePictureStr(args[0]); + v8::Isolate* isolate = args.GetIsolate(); + scoped_refptr<cc::Picture> picture = ParsePictureStr(isolate, args[0]); if (!picture.get()) return; - v8::Handle<v8::Object> result = v8::Object::New(); - result->Set(v8::String::New("width"), + v8::Handle<v8::Object> result = v8::Object::New(isolate); + result->Set(v8::String::NewFromUtf8(isolate, "width"), v8::Number::New(picture->LayerRect().width())); - result->Set(v8::String::New("height"), + result->Set(v8::String::NewFromUtf8(isolate, "height"), v8::Number::New(picture->LayerRect().height())); args.GetReturnValue().Set(result); diff --git a/chromium/content/renderer/speech_recognition_dispatcher.cc b/chromium/content/renderer/speech_recognition_dispatcher.cc index cf7c2fec286..1ac22371017 100644 --- a/chromium/content/renderer/speech_recognition_dispatcher.cc +++ b/chromium/content/renderer/speech_recognition_dispatcher.cc @@ -15,13 +15,13 @@ #include "third_party/WebKit/public/web/WebSpeechRecognitionResult.h" #include "third_party/WebKit/public/web/WebSpeechRecognizerClient.h" -using WebKit::WebVector; -using WebKit::WebString; -using WebKit::WebSpeechGrammar; -using WebKit::WebSpeechRecognitionHandle; -using WebKit::WebSpeechRecognitionResult; -using WebKit::WebSpeechRecognitionParams; -using WebKit::WebSpeechRecognizerClient; +using blink::WebVector; +using blink::WebString; +using blink::WebSpeechGrammar; +using blink::WebSpeechRecognitionHandle; +using blink::WebSpeechRecognitionResult; +using blink::WebSpeechRecognitionParams; +using blink::WebSpeechRecognizerClient; namespace content { diff --git a/chromium/content/renderer/speech_recognition_dispatcher.h b/chromium/content/renderer/speech_recognition_dispatcher.h index bffb0c8a1a9..297f174da12 100644 --- a/chromium/content/renderer/speech_recognition_dispatcher.h +++ b/chromium/content/renderer/speech_recognition_dispatcher.h @@ -23,7 +23,7 @@ struct SpeechRecognitionResult; // scripted JS speech APIs. It's the complement of // SpeechRecognitionDispatcherHost (owned by RenderViewHost). class SpeechRecognitionDispatcher : public RenderViewObserver, - public WebKit::WebSpeechRecognizer { + public blink::WebSpeechRecognizer { public: explicit SpeechRecognitionDispatcher(RenderViewImpl* render_view); virtual ~SpeechRecognitionDispatcher(); @@ -32,14 +32,14 @@ class SpeechRecognitionDispatcher : public RenderViewObserver, // RenderViewObserver implementation. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - // WebKit::WebSpeechRecognizer implementation. - virtual void start(const WebKit::WebSpeechRecognitionHandle&, - const WebKit::WebSpeechRecognitionParams&, - WebKit::WebSpeechRecognizerClient*) OVERRIDE; - virtual void stop(const WebKit::WebSpeechRecognitionHandle&, - WebKit::WebSpeechRecognizerClient*) OVERRIDE; - virtual void abort(const WebKit::WebSpeechRecognitionHandle&, - WebKit::WebSpeechRecognizerClient*) OVERRIDE; + // blink::WebSpeechRecognizer implementation. + virtual void start(const blink::WebSpeechRecognitionHandle&, + const blink::WebSpeechRecognitionParams&, + blink::WebSpeechRecognizerClient*) OVERRIDE; + virtual void stop(const blink::WebSpeechRecognitionHandle&, + blink::WebSpeechRecognizerClient*) OVERRIDE; + virtual void abort(const blink::WebSpeechRecognitionHandle&, + blink::WebSpeechRecognizerClient*) OVERRIDE; void OnRecognitionStarted(int request_id); void OnAudioStarted(int request_id); @@ -51,14 +51,14 @@ class SpeechRecognitionDispatcher : public RenderViewObserver, void OnResultsRetrieved(int request_id, const SpeechRecognitionResults& result); - int GetOrCreateIDForHandle(const WebKit::WebSpeechRecognitionHandle& handle); - bool HandleExists(const WebKit::WebSpeechRecognitionHandle& handle); - const WebKit::WebSpeechRecognitionHandle& GetHandleFromID(int handle_id); + int GetOrCreateIDForHandle(const blink::WebSpeechRecognitionHandle& handle); + bool HandleExists(const blink::WebSpeechRecognitionHandle& handle); + const blink::WebSpeechRecognitionHandle& GetHandleFromID(int handle_id); // The WebKit client class that we use to send events back to the JS world. - WebKit::WebSpeechRecognizerClient* recognizer_client_; + blink::WebSpeechRecognizerClient* recognizer_client_; - typedef std::map<int, WebKit::WebSpeechRecognitionHandle> HandleMap; + typedef std::map<int, blink::WebSpeechRecognitionHandle> HandleMap; HandleMap handle_map_; int next_id_; diff --git a/chromium/content/renderer/stats_collection_controller.cc b/chromium/content/renderer/stats_collection_controller.cc index f82a8c4fd56..af86c9ea0ef 100644 --- a/chromium/content/renderer/stats_collection_controller.cc +++ b/chromium/content/renderer/stats_collection_controller.cc @@ -4,30 +4,29 @@ #include "content/renderer/stats_collection_controller.h" -#include "base/bind.h" -#include "base/bind_helpers.h" #include "base/json/json_writer.h" #include "base/metrics/histogram.h" #include "base/metrics/statistics_recorder.h" #include "base/strings/string_util.h" #include "content/common/child_process_messages.h" #include "content/renderer/render_view_impl.h" +#include "gin/handle.h" +#include "gin/object_template_builder.h" +#include "gin/per_isolate_data.h" #include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebKit.h" #include "third_party/WebKit/public/web/WebView.h" -using webkit_glue::CppArgumentList; -using webkit_glue::CppVariant; - namespace content { namespace { bool CurrentRenderViewImpl(RenderViewImpl** out) { - WebKit::WebFrame* web_frame = WebKit::WebFrame::frameForCurrentContext(); + blink::WebFrame* web_frame = blink::WebFrame::frameForCurrentContext(); if (!web_frame) return false; - WebKit::WebView* web_view = web_frame->view(); + blink::WebView* web_view = web_frame->view(); if (!web_view) return false; @@ -50,110 +49,114 @@ bool CurrentRenderViewImpl(RenderViewImpl** out) { // either value may be null if a web contents hasn't fully loaded. // load_start_ms is represented as milliseconds since system boot. void ConvertLoadTimeToJSON( - const base::TimeTicks& load_start_time, - const base::TimeTicks& load_stop_time, + const base::Time& load_start_time, + const base::Time& load_stop_time, std::string *result) { base::DictionaryValue item; if (load_start_time.is_null()) { - item.Set("load_start_ms", base::Value::CreateNullValue()); + item.Set("load_start_ms", base::Value::CreateNullValue()); } else { - // This code relies on an implementation detail of TimeTicks::Now() - that - // its return value happens to coincide with the system uptime value in - // microseconds, on Win/Mac/iOS/Linux/ChromeOS and Android. See comments - // in base::SysInfo::Uptime(). item.SetDouble("load_start_ms", load_start_time.ToInternalValue() / 1000); } if (load_start_time.is_null() || load_stop_time.is_null()) { item.Set("load_duration_ms", base::Value::CreateNullValue()); } else { item.SetDouble("load_duration_ms", - (load_stop_time - load_start_time).InMilliseconds()); + (load_stop_time - load_start_time).InMillisecondsF()); } base::JSONWriter::Write(&item, result); } } // namespace -StatsCollectionController::StatsCollectionController() - : sender_(NULL) { - BindCallback("getHistogram", - base::Bind(&StatsCollectionController::GetHistogram, - base::Unretained(this))); - BindCallback("getBrowserHistogram", - base::Bind(&StatsCollectionController::GetBrowserHistogram, - base::Unretained(this))); - BindCallback("tabLoadTiming", - base::Bind( - &StatsCollectionController::GetTabLoadTiming, - base::Unretained(this))); -} - -void StatsCollectionController::GetHistogram(const CppArgumentList& args, - CppVariant* result) { - if (args.size() != 1) { - result->SetNull(); +// static +gin::WrapperInfo StatsCollectionController::kWrapperInfo = { + gin::kEmbedderNativeGin +}; + +// static +void StatsCollectionController::Install(blink::WebFrame* frame) { + v8::Isolate* isolate = blink::mainThreadIsolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle<v8::Context> context = frame->mainWorldScriptContext(); + if (context.IsEmpty()) return; + + v8::Context::Scope context_scope(context); + + gin::PerIsolateData* data = gin::PerIsolateData::From(isolate); + if (data->GetObjectTemplate(&StatsCollectionController::kWrapperInfo) + .IsEmpty()) { + v8::Handle<v8::ObjectTemplate> templ = + gin::ObjectTemplateBuilder(isolate) + .SetMethod("getHistogram", &StatsCollectionController::GetHistogram) + .SetMethod("getBrowserHistogram", + &StatsCollectionController::GetBrowserHistogram) + .SetMethod("tabLoadTiming", + &StatsCollectionController::GetTabLoadTiming) + .Build(); + templ->SetInternalFieldCount(gin::kNumberOfInternalFields); + data->SetObjectTemplate(&StatsCollectionController::kWrapperInfo, templ); } + + gin::Handle<StatsCollectionController> controller = + gin::CreateHandle(isolate, new StatsCollectionController()); + v8::Handle<v8::Object> global = context->Global(); + global->Set(gin::StringToV8(isolate, "statsCollectionController"), + controller.ToV8()); +} + +StatsCollectionController::StatsCollectionController() {} + +StatsCollectionController::~StatsCollectionController() {} + +std::string StatsCollectionController::GetHistogram( + const std::string& histogram_name) { base::HistogramBase* histogram = - base::StatisticsRecorder::FindHistogram(args[0].ToString()); + base::StatisticsRecorder::FindHistogram(histogram_name); std::string output; if (!histogram) { output = "{}"; } else { histogram->WriteJSON(&output); } - result->Set(output); + return output; } -void StatsCollectionController::GetBrowserHistogram(const CppArgumentList& args, - CppVariant* result) { - if (args.size() != 1) { - result->SetNull(); - return; - } - - if (!sender_) { +std::string StatsCollectionController::GetBrowserHistogram( + const std::string& histogram_name) { + RenderViewImpl *render_view_impl = NULL; + if (!CurrentRenderViewImpl(&render_view_impl)) { NOTREACHED(); - result->SetNull(); - return; + return std::string(); } std::string histogram_json; - sender_->Send(new ChildProcessHostMsg_GetBrowserHistogram( - args[0].ToString(), &histogram_json)); - result->Set(histogram_json); + render_view_impl->Send(new ChildProcessHostMsg_GetBrowserHistogram( + histogram_name, &histogram_json)); + return histogram_json; } -void StatsCollectionController::GetTabLoadTiming( - const CppArgumentList& args, - CppVariant* result) { - if (!sender_) { - NOTREACHED(); - result->SetNull(); - return; - } - +std::string StatsCollectionController::GetTabLoadTiming() { RenderViewImpl *render_view_impl = NULL; if (!CurrentRenderViewImpl(&render_view_impl)) { NOTREACHED(); - result->SetNull(); - return; + return std::string(); } StatsCollectionObserver* observer = render_view_impl->GetStatsCollectionObserver(); if (!observer) { NOTREACHED(); - result->SetNull(); - return; + return std::string(); } std::string tab_timing_json; ConvertLoadTimeToJSON( observer->load_start_time(), observer->load_stop_time(), &tab_timing_json); - result->Set(tab_timing_json); + return tab_timing_json; } } // namespace content diff --git a/chromium/content/renderer/stats_collection_controller.h b/chromium/content/renderer/stats_collection_controller.h index 63175d830a9..c122972e41f 100644 --- a/chromium/content/renderer/stats_collection_controller.h +++ b/chromium/content/renderer/stats_collection_controller.h @@ -5,8 +5,12 @@ #ifndef CONTENT_RENDERER_STATS_COLLECTION_CONTROLLER_H_ #define CONTENT_RENDERER_STATS_COLLECTION_CONTROLLER_H_ -#include "ipc/ipc_sender.h" -#include "webkit/renderer/cpp_bound_class.h" +#include "base/basictypes.h" +#include "gin/wrappable.h" + +namespace blink { +class WebFrame; +} namespace content { @@ -14,28 +18,28 @@ namespace content { // functionality to read out statistics from the browser. // Its use must be enabled specifically via the // --enable-stats-collection-bindings command line flag. -class StatsCollectionController : public webkit_glue::CppBoundClass { +class StatsCollectionController + : public gin::Wrappable<StatsCollectionController> { public: - StatsCollectionController(); + static gin::WrapperInfo kWrapperInfo; - void set_message_sender(IPC::Sender* sender) { - sender_ = sender; - } + static void Install(blink::WebFrame* frame); + + private: + StatsCollectionController(); + virtual ~StatsCollectionController(); // Retrieves a histogram and returns a JSON representation of it. - void GetHistogram(const webkit_glue::CppArgumentList& args, - webkit_glue::CppVariant* result); + std::string GetHistogram(const std::string& histogram_name); // Retrieves a histogram from the browser process and returns a JSON // representation of it. - void GetBrowserHistogram(const webkit_glue::CppArgumentList& args, - webkit_glue::CppVariant* result); + std::string GetBrowserHistogram(const std::string& histogram_name); // Returns JSON representation of tab timing information for the current tab. - void GetTabLoadTiming(const webkit_glue::CppArgumentList& args, - webkit_glue::CppVariant* result); - private: - IPC::Sender* sender_; + std::string GetTabLoadTiming(); + + DISALLOW_COPY_AND_ASSIGN(StatsCollectionController); }; } // namespace content diff --git a/chromium/content/renderer/stats_collection_observer.cc b/chromium/content/renderer/stats_collection_observer.cc index 00211ff781d..4c4b911ec8c 100644 --- a/chromium/content/renderer/stats_collection_observer.cc +++ b/chromium/content/renderer/stats_collection_observer.cc @@ -18,12 +18,12 @@ StatsCollectionObserver::~StatsCollectionObserver() { void StatsCollectionObserver::DidStartLoading() { DCHECK(start_time_.is_null()); - start_time_ = base::TimeTicks::Now(); + start_time_ = base::Time::Now(); } void StatsCollectionObserver::DidStopLoading() { DCHECK(stop_time_.is_null()); - stop_time_ = base::TimeTicks::Now(); + stop_time_ = base::Time::Now(); // Stop observing so we don't get called again. RenderViewImpl* impl = static_cast<RenderViewImpl*>(render_view()); diff --git a/chromium/content/renderer/stats_collection_observer.h b/chromium/content/renderer/stats_collection_observer.h index 298226f07b8..2717fd943c5 100644 --- a/chromium/content/renderer/stats_collection_observer.h +++ b/chromium/content/renderer/stats_collection_observer.h @@ -25,12 +25,12 @@ class StatsCollectionObserver : public RenderViewObserver { // Timing for the page load start and stop. These functions may return // a null time value under various circumstances. - const base::TimeTicks& load_start_time() { return start_time_; } - const base::TimeTicks& load_stop_time() { return stop_time_; } + const base::Time& load_start_time() { return start_time_; } + const base::Time& load_stop_time() { return stop_time_; } private: - base::TimeTicks start_time_; - base::TimeTicks stop_time_; + base::Time start_time_; + base::Time stop_time_; DISALLOW_COPY_AND_ASSIGN(StatsCollectionObserver); }; diff --git a/chromium/content/renderer/text_input_client_observer.cc b/chromium/content/renderer/text_input_client_observer.cc index cec5e1ab76f..5ce95ff6093 100644 --- a/chromium/content/renderer/text_input_client_observer.cc +++ b/chromium/content/renderer/text_input_client_observer.cc @@ -6,6 +6,7 @@ #include "base/memory/scoped_ptr.h" #include "content/common/text_input_client_messages.h" +#include "content/renderer/pepper/pepper_plugin_instance_impl.h" #include "content/renderer/render_view_impl.h" #include "third_party/WebKit/public/platform/WebPoint.h" #include "third_party/WebKit/public/platform/WebRect.h" @@ -38,12 +39,12 @@ bool TextInputClientObserver::OnMessageReceived(const IPC::Message& message) { return handled; } -WebKit::WebView* TextInputClientObserver::webview() { +blink::WebView* TextInputClientObserver::webview() { return render_view()->GetWebView(); } void TextInputClientObserver::OnCharacterIndexForPoint(gfx::Point point) { - WebKit::WebPoint web_point(point); + blink::WebPoint web_point(point); size_t index = webview()->focusedFrame()->characterIndexForPoint(web_point); Send(new TextInputClientReplyMsg_GotCharacterIndexForPoint(routing_id(), index)); @@ -52,12 +53,14 @@ void TextInputClientObserver::OnCharacterIndexForPoint(gfx::Point point) { void TextInputClientObserver::OnFirstRectForCharacterRange(gfx::Range range) { gfx::Rect rect; #if defined(ENABLE_PLUGINS) - if (!render_view_impl_->GetPepperCaretBounds(&rect)) + if (render_view_impl_->focused_pepper_plugin()) { + rect = render_view_impl_->focused_pepper_plugin()->GetCaretBounds(); + } else #endif { - WebKit::WebFrame* frame = webview()->focusedFrame(); + blink::WebFrame* frame = webview()->focusedFrame(); if (frame) { - WebKit::WebRect web_rect; + blink::WebRect web_rect; frame->firstRectForCharacterRange(range.start(), range.length(), web_rect); rect = web_rect; @@ -69,9 +72,9 @@ void TextInputClientObserver::OnFirstRectForCharacterRange(gfx::Range range) { void TextInputClientObserver::OnStringForRange(gfx::Range range) { #if defined(OS_MACOSX) NSAttributedString* string = nil; - WebKit::WebFrame* frame = webview()->focusedFrame(); + blink::WebFrame* frame = webview()->focusedFrame(); if (frame) { - string = WebKit::WebSubstringUtil::attributedSubstringInRange( + string = blink::WebSubstringUtil::attributedSubstringInRange( frame, range.start(), range.length()); } scoped_ptr<const mac::AttributedStringCoder::EncodedString> encoded( diff --git a/chromium/content/renderer/text_input_client_observer.h b/chromium/content/renderer/text_input_client_observer.h index 4c8b9a6ba63..cd674188917 100644 --- a/chromium/content/renderer/text_input_client_observer.h +++ b/chromium/content/renderer/text_input_client_observer.h @@ -11,7 +11,7 @@ #include "ui/gfx/point.h" #include "ui/gfx/range/range.h" -namespace WebKit { +namespace blink { class WebView; } @@ -32,7 +32,7 @@ class TextInputClientObserver : public RenderViewObserver { private: // Returns the WebView of the RenderView. - WebKit::WebView* webview(); + blink::WebView* webview(); // IPC Message handlers: void OnCharacterIndexForPoint(gfx::Point point); diff --git a/chromium/content/renderer/v8_value_converter_impl.cc b/chromium/content/renderer/v8_value_converter_impl.cc index ab2a6330442..0244c338e6b 100644 --- a/chromium/content/renderer/v8_value_converter_impl.cc +++ b/chromium/content/renderer/v8_value_converter_impl.cc @@ -115,8 +115,8 @@ void V8ValueConverterImpl::SetStrategy(Strategy* strategy) { v8::Handle<v8::Value> V8ValueConverterImpl::ToV8Value( const base::Value* value, v8::Handle<v8::Context> context) const { v8::Context::Scope context_scope(context); - v8::HandleScope handle_scope(context->GetIsolate()); - return handle_scope.Close(ToV8ValueImpl(value)); + v8::EscapableHandleScope handle_scope(context->GetIsolate()); + return handle_scope.Escape(ToV8ValueImpl(context->GetIsolate(), value)); } Value* V8ValueConverterImpl::FromV8Value( @@ -125,64 +125,68 @@ Value* V8ValueConverterImpl::FromV8Value( v8::Context::Scope context_scope(context); v8::HandleScope handle_scope(context->GetIsolate()); FromV8ValueState state(avoid_identity_hash_for_testing_); - return FromV8ValueImpl(val, &state); + return FromV8ValueImpl(val, &state, context->GetIsolate()); } -v8::Handle<v8::Value> V8ValueConverterImpl::ToV8ValueImpl( - const base::Value* value) const { +v8::Local<v8::Value> V8ValueConverterImpl::ToV8ValueImpl( + v8::Isolate* isolate, + const base::Value* value) const { CHECK(value); switch (value->GetType()) { case base::Value::TYPE_NULL: - return v8::Null(); + return v8::Null(isolate); case base::Value::TYPE_BOOLEAN: { bool val = false; CHECK(value->GetAsBoolean(&val)); - return v8::Boolean::New(val); + return v8::Boolean::New(isolate, val); } case base::Value::TYPE_INTEGER: { int val = 0; CHECK(value->GetAsInteger(&val)); - return v8::Integer::New(val); + return v8::Integer::New(isolate, val); } case base::Value::TYPE_DOUBLE: { double val = 0.0; CHECK(value->GetAsDouble(&val)); - return v8::Number::New(val); + return v8::Number::New(isolate, val); } case base::Value::TYPE_STRING: { std::string val; CHECK(value->GetAsString(&val)); - return v8::String::New(val.c_str(), val.length()); + return v8::String::NewFromUtf8( + isolate, val.c_str(), v8::String::kNormalString, val.length()); } case base::Value::TYPE_LIST: - return ToV8Array(static_cast<const base::ListValue*>(value)); + return ToV8Array(isolate, static_cast<const base::ListValue*>(value)); case base::Value::TYPE_DICTIONARY: - return ToV8Object(static_cast<const base::DictionaryValue*>(value)); + return ToV8Object(isolate, + static_cast<const base::DictionaryValue*>(value)); case base::Value::TYPE_BINARY: return ToArrayBuffer(static_cast<const base::BinaryValue*>(value)); default: LOG(ERROR) << "Unexpected value type: " << value->GetType(); - return v8::Null(); + return v8::Null(isolate); } } v8::Handle<v8::Value> V8ValueConverterImpl::ToV8Array( + v8::Isolate* isolate, const base::ListValue* val) const { - v8::Handle<v8::Array> result(v8::Array::New(val->GetSize())); + v8::Handle<v8::Array> result(v8::Array::New(isolate, val->GetSize())); for (size_t i = 0; i < val->GetSize(); ++i) { const base::Value* child = NULL; CHECK(val->Get(i, &child)); - v8::Handle<v8::Value> child_v8 = ToV8ValueImpl(child); + v8::Handle<v8::Value> child_v8 = ToV8ValueImpl(isolate, child); CHECK(!child_v8.IsEmpty()); v8::TryCatch try_catch; @@ -195,17 +199,21 @@ v8::Handle<v8::Value> V8ValueConverterImpl::ToV8Array( } v8::Handle<v8::Value> V8ValueConverterImpl::ToV8Object( + v8::Isolate* isolate, const base::DictionaryValue* val) const { v8::Handle<v8::Object> result(v8::Object::New()); for (base::DictionaryValue::Iterator iter(*val); !iter.IsAtEnd(); iter.Advance()) { const std::string& key = iter.key(); - v8::Handle<v8::Value> child_v8 = ToV8ValueImpl(&iter.value()); + v8::Handle<v8::Value> child_v8 = ToV8ValueImpl(isolate, &iter.value()); CHECK(!child_v8.IsEmpty()); v8::TryCatch try_catch; - result->Set(v8::String::New(key.c_str(), key.length()), child_v8); + result->Set( + v8::String::NewFromUtf8( + isolate, key.c_str(), v8::String::kNormalString, key.length()), + child_v8); if (try_catch.HasCaught()) { LOG(ERROR) << "Setter for property " << key.c_str() << " threw an " << "exception."; @@ -217,15 +225,16 @@ v8::Handle<v8::Value> V8ValueConverterImpl::ToV8Object( v8::Handle<v8::Value> V8ValueConverterImpl::ToArrayBuffer( const base::BinaryValue* value) const { - WebKit::WebArrayBuffer buffer = - WebKit::WebArrayBuffer::create(value->GetSize(), 1); + blink::WebArrayBuffer buffer = + blink::WebArrayBuffer::create(value->GetSize(), 1); memcpy(buffer.data(), value->GetBuffer(), value->GetSize()); return buffer.toV8Value(); } Value* V8ValueConverterImpl::FromV8ValueImpl( v8::Handle<v8::Value> val, - FromV8ValueState* state) const { + FromV8ValueState* state, + v8::Isolate* isolate) const { CHECK(!val.IsEmpty()); FromV8ValueState::Level state_level(state); @@ -261,27 +270,27 @@ Value* V8ValueConverterImpl::FromV8ValueImpl( if (!date_allowed_) // JSON.stringify would convert this to a string, but an object is more // consistent within this class. - return FromV8Object(val->ToObject(), state); + return FromV8Object(val->ToObject(), state, isolate); v8::Date* date = v8::Date::Cast(*val); - return new base::FundamentalValue(date->NumberValue() / 1000.0); + return new base::FundamentalValue(date->ValueOf() / 1000.0); } if (val->IsRegExp()) { if (!reg_exp_allowed_) // JSON.stringify converts to an object. - return FromV8Object(val->ToObject(), state); + return FromV8Object(val->ToObject(), state, isolate); return new base::StringValue(*v8::String::Utf8Value(val->ToString())); } // v8::Value doesn't have a ToArray() method for some reason. if (val->IsArray()) - return FromV8Array(val.As<v8::Array>(), state); + return FromV8Array(val.As<v8::Array>(), state, isolate); if (val->IsFunction()) { if (!function_allowed_) // JSON.stringify refuses to convert function(){}. return NULL; - return FromV8Object(val->ToObject(), state); + return FromV8Object(val->ToObject(), state, isolate); } if (val->IsObject()) { @@ -289,7 +298,7 @@ Value* V8ValueConverterImpl::FromV8ValueImpl( if (binary_value) { return binary_value; } else { - return FromV8Object(val->ToObject(), state); + return FromV8Object(val->ToObject(), state, isolate); } } @@ -299,7 +308,8 @@ Value* V8ValueConverterImpl::FromV8ValueImpl( base::Value* V8ValueConverterImpl::FromV8Array( v8::Handle<v8::Array> val, - FromV8ValueState* state) const { + FromV8ValueState* state, + v8::Isolate* isolate) const { if (!state->UpdateAndCheckUniqueness(val)) return base::Value::CreateNullValue(); @@ -307,12 +317,12 @@ base::Value* V8ValueConverterImpl::FromV8Array( // If val was created in a different context than our current one, change to // that context, but change back after val is converted. if (!val->CreationContext().IsEmpty() && - val->CreationContext() != v8::Context::GetCurrent()) + val->CreationContext() != isolate->GetCurrentContext()) scope.reset(new v8::Context::Scope(val->CreationContext())); if (strategy_) { Value* out = NULL; - if (strategy_->FromV8Array(val, &out)) + if (strategy_->FromV8Array(val, &out, isolate)) return out; } @@ -324,13 +334,13 @@ base::Value* V8ValueConverterImpl::FromV8Array( v8::Handle<v8::Value> child_v8 = val->Get(i); if (try_catch.HasCaught()) { LOG(ERROR) << "Getter for index " << i << " threw an exception."; - child_v8 = v8::Null(); + child_v8 = v8::Null(isolate); } if (!val->HasRealIndexedProperty(i)) continue; - base::Value* child = FromV8ValueImpl(child_v8, state); + base::Value* child = FromV8ValueImpl(child_v8, state, isolate); if (child) result->Append(child); else @@ -346,14 +356,14 @@ base::BinaryValue* V8ValueConverterImpl::FromV8Buffer( char* data = NULL; size_t length = 0; - scoped_ptr<WebKit::WebArrayBuffer> array_buffer( - WebKit::WebArrayBuffer::createFromV8Value(val)); - scoped_ptr<WebKit::WebArrayBufferView> view; + scoped_ptr<blink::WebArrayBuffer> array_buffer( + blink::WebArrayBuffer::createFromV8Value(val)); + scoped_ptr<blink::WebArrayBufferView> view; if (array_buffer) { data = reinterpret_cast<char*>(array_buffer->data()); length = array_buffer->byteLength(); } else { - view.reset(WebKit::WebArrayBufferView::createFromV8Value(val)); + view.reset(blink::WebArrayBufferView::createFromV8Value(val)); if (view) { data = reinterpret_cast<char*>(view->baseAddress()) + view->byteOffset(); length = view->byteLength(); @@ -368,7 +378,8 @@ base::BinaryValue* V8ValueConverterImpl::FromV8Buffer( base::Value* V8ValueConverterImpl::FromV8Object( v8::Handle<v8::Object> val, - FromV8ValueState* state) const { + FromV8ValueState* state, + v8::Isolate* isolate) const { if (!state->UpdateAndCheckUniqueness(val)) return base::Value::CreateNullValue(); @@ -376,12 +387,12 @@ base::Value* V8ValueConverterImpl::FromV8Object( // If val was created in a different context than our current one, change to // that context, but change back after val is converted. if (!val->CreationContext().IsEmpty() && - val->CreationContext() != v8::Context::GetCurrent()) + val->CreationContext() != isolate->GetCurrentContext()) scope.reset(new v8::Context::Scope(val->CreationContext())); if (strategy_) { Value* out = NULL; - if (strategy_->FromV8Object(val, &out)) + if (strategy_->FromV8Object(val, &out, isolate)) return out; } @@ -407,7 +418,7 @@ base::Value* V8ValueConverterImpl::FromV8Object( // Extend this test to cover more types as necessary and if sensible. if (!key->IsString() && !key->IsNumber()) { - NOTREACHED() << "Key \"" << *v8::String::AsciiValue(key) << "\" " + NOTREACHED() << "Key \"" << *v8::String::Utf8Value(key) << "\" " "is neither a string nor a number"; continue; } @@ -420,10 +431,10 @@ base::Value* V8ValueConverterImpl::FromV8Object( if (try_catch.HasCaught()) { LOG(WARNING) << "Getter for property " << *name_utf8 << " threw an exception."; - child_v8 = v8::Null(); + child_v8 = v8::Null(isolate); } - scoped_ptr<base::Value> child(FromV8ValueImpl(child_v8, state)); + scoped_ptr<base::Value> child(FromV8ValueImpl(child_v8, state, isolate)); if (!child) // JSON.stringify skips properties whose values don't serialize, for // example undefined and functions. Emulate that behavior. diff --git a/chromium/content/renderer/v8_value_converter_impl.h b/chromium/content/renderer/v8_value_converter_impl.h index 20331648fab..b64b8d8f5e6 100644 --- a/chromium/content/renderer/v8_value_converter_impl.h +++ b/chromium/content/renderer/v8_value_converter_impl.h @@ -43,16 +43,21 @@ class CONTENT_EXPORT V8ValueConverterImpl : public V8ValueConverter { class FromV8ValueState; - v8::Handle<v8::Value> ToV8ValueImpl(const base::Value* value) const; - v8::Handle<v8::Value> ToV8Array(const base::ListValue* list) const; + v8::Local<v8::Value> ToV8ValueImpl(v8::Isolate* isolate, + const base::Value* value) const; + v8::Handle<v8::Value> ToV8Array(v8::Isolate* isolate, + const base::ListValue* list) const; v8::Handle<v8::Value> ToV8Object( + v8::Isolate* isolate, const base::DictionaryValue* dictionary) const; v8::Handle<v8::Value> ToArrayBuffer(const base::BinaryValue* value) const; base::Value* FromV8ValueImpl(v8::Handle<v8::Value> value, - FromV8ValueState* state) const; + FromV8ValueState* state, + v8::Isolate* isolate) const; base::Value* FromV8Array(v8::Handle<v8::Array> array, - FromV8ValueState* state) const; + FromV8ValueState* state, + v8::Isolate* isolate) const; // This will convert objects of type ArrayBuffer or any of the // ArrayBufferView subclasses. The return value will be NULL if |value| is @@ -60,7 +65,8 @@ class CONTENT_EXPORT V8ValueConverterImpl : public V8ValueConverter { base::BinaryValue* FromV8Buffer(v8::Handle<v8::Value> value) const; base::Value* FromV8Object(v8::Handle<v8::Object> object, - FromV8ValueState* state) const; + FromV8ValueState* state, + v8::Isolate* isolate) const; // If true, we will convert Date JavaScript objects to doubles. bool date_allowed_; diff --git a/chromium/content/renderer/v8_value_converter_impl_unittest.cc b/chromium/content/renderer/v8_value_converter_impl_unittest.cc index f762f934545..392dd0b0f13 100644 --- a/chromium/content/renderer/v8_value_converter_impl_unittest.cc +++ b/chromium/content/renderer/v8_value_converter_impl_unittest.cc @@ -58,7 +58,7 @@ class V8ValueConverterImplTest : public testing::Test { } virtual void TearDown() { - context_.Dispose(); + context_.Reset(); } std::string GetString(base::DictionaryValue* value, const std::string& key) { @@ -72,7 +72,8 @@ class V8ValueConverterImplTest : public testing::Test { std::string GetString(v8::Handle<v8::Object> value, const std::string& key) { v8::Handle<v8::String> temp = - value->Get(v8::String::New(key.c_str())).As<v8::String>(); + value->Get(v8::String::NewFromUtf8(isolate_, key.c_str())) + .As<v8::String>(); if (temp.IsEmpty()) { ADD_FAILURE(); return std::string(); @@ -110,7 +111,8 @@ class V8ValueConverterImplTest : public testing::Test { } bool IsNull(v8::Handle<v8::Object> value, const std::string& key) { - v8::Handle<v8::Value> child = value->Get(v8::String::New(key.c_str())); + v8::Handle<v8::Value> child = + value->Get(v8::String::NewFromUtf8(isolate_, key.c_str())); if (child.IsEmpty()) { ADD_FAILURE(); return false; @@ -153,7 +155,7 @@ class V8ValueConverterImplTest : public testing::Test { } v8::Handle<v8::Object> object(v8::Object::New()); - object->Set(v8::String::New("test"), val); + object->Set(v8::String::NewFromUtf8(isolate_, "test"), val); scoped_ptr<base::DictionaryValue> dictionary( static_cast<base::DictionaryValue*>( converter.FromV8Value(object, context))); @@ -168,7 +170,7 @@ class V8ValueConverterImplTest : public testing::Test { EXPECT_FALSE(dictionary->HasKey("test")); } - v8::Handle<v8::Array> array(v8::Array::New()); + v8::Handle<v8::Array> array(v8::Array::New(isolate_)); array->Set(0, val); scoped_ptr<base::ListValue> list( static_cast<base::ListValue*>(converter.FromV8Value(array, context))); @@ -216,9 +218,9 @@ TEST_F(V8ValueConverterImplTest, BasicRoundTrip) { "}"); v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); V8ValueConverterImpl converter; v8::Handle<v8::Object> v8_object = @@ -227,21 +229,34 @@ TEST_F(V8ValueConverterImplTest, BasicRoundTrip) { EXPECT_EQ(static_cast<const base::DictionaryValue&>(*original_root).size(), v8_object->GetPropertyNames()->Length()); - EXPECT_TRUE(v8_object->Get(v8::String::New("null"))->IsNull()); - EXPECT_TRUE(v8_object->Get(v8::String::New("true"))->IsTrue()); - EXPECT_TRUE(v8_object->Get(v8::String::New("false"))->IsFalse()); - EXPECT_TRUE(v8_object->Get(v8::String::New("positive-int"))->IsInt32()); - EXPECT_TRUE(v8_object->Get(v8::String::New("negative-int"))->IsInt32()); - EXPECT_TRUE(v8_object->Get(v8::String::New("zero"))->IsInt32()); - EXPECT_TRUE(v8_object->Get(v8::String::New("double"))->IsNumber()); EXPECT_TRUE( - v8_object->Get(v8::String::New("big-integral-double"))->IsNumber()); - EXPECT_TRUE(v8_object->Get(v8::String::New("string"))->IsString()); - EXPECT_TRUE(v8_object->Get(v8::String::New("empty-string"))->IsString()); - EXPECT_TRUE(v8_object->Get(v8::String::New("dictionary"))->IsObject()); - EXPECT_TRUE(v8_object->Get(v8::String::New("empty-dictionary"))->IsObject()); - EXPECT_TRUE(v8_object->Get(v8::String::New("list"))->IsArray()); - EXPECT_TRUE(v8_object->Get(v8::String::New("empty-list"))->IsArray()); + v8_object->Get(v8::String::NewFromUtf8(isolate_, "null"))->IsNull()); + EXPECT_TRUE( + v8_object->Get(v8::String::NewFromUtf8(isolate_, "true"))->IsTrue()); + EXPECT_TRUE( + v8_object->Get(v8::String::NewFromUtf8(isolate_, "false"))->IsFalse()); + EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(isolate_, "positive-int")) + ->IsInt32()); + EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(isolate_, "negative-int")) + ->IsInt32()); + EXPECT_TRUE( + v8_object->Get(v8::String::NewFromUtf8(isolate_, "zero"))->IsInt32()); + EXPECT_TRUE( + v8_object->Get(v8::String::NewFromUtf8(isolate_, "double"))->IsNumber()); + EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8( + isolate_, "big-integral-double"))->IsNumber()); + EXPECT_TRUE( + v8_object->Get(v8::String::NewFromUtf8(isolate_, "string"))->IsString()); + EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(isolate_, "empty-string")) + ->IsString()); + EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(isolate_, "dictionary")) + ->IsObject()); + EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8( + isolate_, "empty-dictionary"))->IsObject()); + EXPECT_TRUE( + v8_object->Get(v8::String::NewFromUtf8(isolate_, "list"))->IsArray()); + EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(isolate_, "empty-list")) + ->IsArray()); scoped_ptr<base::Value> new_root(converter.FromV8Value(v8_object, context)); EXPECT_NE(original_root.get(), new_root.get()); @@ -253,9 +268,9 @@ TEST_F(V8ValueConverterImplTest, KeysWithDots) { base::test::ParseJson("{ \"foo.bar\": \"baz\" }"); v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); V8ValueConverterImpl converter; scoped_ptr<base::Value> copy( @@ -267,9 +282,9 @@ TEST_F(V8ValueConverterImplTest, KeysWithDots) { TEST_F(V8ValueConverterImplTest, ObjectExceptions) { v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); // Set up objects to throw when reading or writing 'foo'. const char* source = @@ -278,11 +293,13 @@ TEST_F(V8ValueConverterImplTest, ObjectExceptions) { "Object.prototype.__defineGetter__('foo', " " function() { throw new Error('muah!'); });"; - v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); + v8::Handle<v8::Script> script( + v8::Script::New(v8::String::NewFromUtf8(isolate_, source))); script->Run(); - v8::Handle<v8::Object> object(v8::Object::New()); - object->Set(v8::String::New("bar"), v8::String::New("bar")); + v8::Handle<v8::Object> object(v8::Object::New(isolate_)); + object->Set(v8::String::NewFromUtf8(isolate_, "bar"), + v8::String::NewFromUtf8(isolate_, "bar")); // Converting from v8 value should replace the foo property with null. V8ValueConverterImpl converter; @@ -307,9 +324,9 @@ TEST_F(V8ValueConverterImplTest, ObjectExceptions) { TEST_F(V8ValueConverterImplTest, ArrayExceptions) { v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); const char* source = "(function() {" "var arr = [];" @@ -321,7 +338,8 @@ TEST_F(V8ValueConverterImplTest, ArrayExceptions) { "return arr;" "})();"; - v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); + v8::Handle<v8::Script> script( + v8::Script::New(v8::String::NewFromUtf8(isolate_, source))); v8::Handle<v8::Array> array = script->Run().As<v8::Array>(); ASSERT_FALSE(array.IsEmpty()); @@ -346,18 +364,20 @@ TEST_F(V8ValueConverterImplTest, ArrayExceptions) { TEST_F(V8ValueConverterImplTest, WeirdTypes) { v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); + v8::Local<v8::Context> context = + v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); - v8::Handle<v8::RegExp> regex( - v8::RegExp::New(v8::String::New("."), v8::RegExp::kNone)); + v8::Handle<v8::RegExp> regex(v8::RegExp::New( + v8::String::NewFromUtf8(isolate_, "."), v8::RegExp::kNone)); V8ValueConverterImpl converter; TestWeirdType(converter, - v8::Undefined(), + v8::Undefined(isolate_), base::Value::TYPE_NULL, // Arbitrary type, result is NULL. scoped_ptr<base::Value>()); TestWeirdType(converter, - v8::Date::New(1000), + v8::Date::New(isolate_, 1000), base::Value::TYPE_DICTIONARY, scoped_ptr<base::Value>(new base::DictionaryValue())); TestWeirdType(converter, @@ -367,7 +387,7 @@ TEST_F(V8ValueConverterImplTest, WeirdTypes) { converter.SetDateAllowed(true); TestWeirdType(converter, - v8::Date::New(1000), + v8::Date::New(isolate_, 1000), base::Value::TYPE_DOUBLE, scoped_ptr<base::Value>(new base::FundamentalValue(1.0))); @@ -380,16 +400,17 @@ TEST_F(V8ValueConverterImplTest, WeirdTypes) { TEST_F(V8ValueConverterImplTest, Prototype) { v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); const char* source = "(function() {" "Object.prototype.foo = 'foo';" "return {};" "})();"; - v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); + v8::Handle<v8::Script> script( + v8::Script::New(v8::String::NewFromUtf8(isolate_, source))); v8::Handle<v8::Object> object = script->Run().As<v8::Object>(); ASSERT_FALSE(object.IsEmpty()); @@ -403,15 +424,16 @@ TEST_F(V8ValueConverterImplTest, Prototype) { TEST_F(V8ValueConverterImplTest, StripNullFromObjects) { v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); const char* source = "(function() {" "return { foo: undefined, bar: null };" "})();"; - v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); + v8::Handle<v8::Script> script( + v8::Script::New(v8::String::NewFromUtf8(isolate_, source))); v8::Handle<v8::Object> object = script->Run().As<v8::Object>(); ASSERT_FALSE(object.IsEmpty()); @@ -427,16 +449,17 @@ TEST_F(V8ValueConverterImplTest, StripNullFromObjects) { TEST_F(V8ValueConverterImplTest, RecursiveObjects) { v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); V8ValueConverterImpl converter; v8::Handle<v8::Object> object = v8::Object::New().As<v8::Object>(); ASSERT_FALSE(object.IsEmpty()); - object->Set(v8::String::New("foo"), v8::String::New("bar")); - object->Set(v8::String::New("obj"), object); + object->Set(v8::String::NewFromUtf8(isolate_, "foo"), + v8::String::NewFromUtf8(isolate_, "bar")); + object->Set(v8::String::NewFromUtf8(isolate_, "obj"), object); scoped_ptr<base::DictionaryValue> object_result( static_cast<base::DictionaryValue*>( @@ -445,9 +468,9 @@ TEST_F(V8ValueConverterImplTest, RecursiveObjects) { EXPECT_EQ(2u, object_result->size()); EXPECT_TRUE(IsNull(object_result.get(), "obj")); - v8::Handle<v8::Array> array = v8::Array::New().As<v8::Array>(); + v8::Handle<v8::Array> array = v8::Array::New(isolate_).As<v8::Array>(); ASSERT_FALSE(array.IsEmpty()); - array->Set(0, v8::String::New("1")); + array->Set(0, v8::String::NewFromUtf8(isolate_, "1")); array->Set(1, array); scoped_ptr<base::ListValue> list_result( @@ -459,9 +482,9 @@ TEST_F(V8ValueConverterImplTest, RecursiveObjects) { TEST_F(V8ValueConverterImplTest, WeirdProperties) { v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); const char* source = "(function() {" "return {" @@ -474,7 +497,8 @@ TEST_F(V8ValueConverterImplTest, WeirdProperties) { "};" "})();"; - v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); + v8::Handle<v8::Script> script( + v8::Script::New(v8::String::NewFromUtf8(isolate_, source))); v8::Handle<v8::Object> object = script->Run().As<v8::Object>(); ASSERT_FALSE(object.IsEmpty()); @@ -496,9 +520,9 @@ TEST_F(V8ValueConverterImplTest, WeirdProperties) { TEST_F(V8ValueConverterImplTest, ArrayGetters) { v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); const char* source = "(function() {" "var a = [0];" @@ -506,7 +530,8 @@ TEST_F(V8ValueConverterImplTest, ArrayGetters) { "return a;" "})();"; - v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); + v8::Handle<v8::Script> script( + v8::Script::New(v8::String::NewFromUtf8(isolate_, source))); v8::Handle<v8::Array> array = script->Run().As<v8::Array>(); ASSERT_FALSE(array.IsEmpty()); @@ -519,16 +544,17 @@ TEST_F(V8ValueConverterImplTest, ArrayGetters) { TEST_F(V8ValueConverterImplTest, UndefinedValueBehavior) { v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); v8::Handle<v8::Object> object; { const char* source = "(function() {" "return { foo: undefined, bar: null, baz: function(){} };" "})();"; - v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); + v8::Handle<v8::Script> script( + v8::Script::New(v8::String::NewFromUtf8(isolate_, source))); object = script->Run().As<v8::Object>(); ASSERT_FALSE(object.IsEmpty()); } @@ -538,7 +564,8 @@ TEST_F(V8ValueConverterImplTest, UndefinedValueBehavior) { const char* source = "(function() {" "return [ undefined, null, function(){} ];" "})();"; - v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); + v8::Handle<v8::Script> script( + v8::Script::New(v8::String::NewFromUtf8(isolate_, source))); array = script->Run().As<v8::Array>(); ASSERT_FALSE(array.IsEmpty()); } @@ -558,9 +585,9 @@ TEST_F(V8ValueConverterImplTest, UndefinedValueBehavior) { TEST_F(V8ValueConverterImplTest, ObjectsWithClashingIdentityHash) { v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); V8ValueConverterImpl converter; // We check that the converter checks identity correctly by disabling the @@ -568,11 +595,11 @@ TEST_F(V8ValueConverterImplTest, ObjectsWithClashingIdentityHash) { ScopedAvoidIdentityHashForTesting scoped_hash_avoider(&converter); // Create the v8::Object to be converted. - v8::Handle<v8::Array> root(v8::Array::New(4)); - root->Set(0, v8::Handle<v8::Object>(v8::Object::New())); - root->Set(1, v8::Handle<v8::Object>(v8::Object::New())); - root->Set(2, v8::Handle<v8::Object>(v8::Array::New(0))); - root->Set(3, v8::Handle<v8::Object>(v8::Array::New(0))); + v8::Handle<v8::Array> root(v8::Array::New(isolate_, 4)); + root->Set(0, v8::Handle<v8::Object>(v8::Object::New(isolate_))); + root->Set(1, v8::Handle<v8::Object>(v8::Object::New(isolate_))); + root->Set(2, v8::Handle<v8::Object>(v8::Array::New(isolate_, 0))); + root->Set(3, v8::Handle<v8::Object>(v8::Array::New(isolate_, 0))); // The expected base::Value result. scoped_ptr<base::Value> expected = base::test::ParseJson("[{},{},[],[]]"); @@ -587,13 +614,13 @@ TEST_F(V8ValueConverterImplTest, ObjectsWithClashingIdentityHash) { TEST_F(V8ValueConverterImplTest, DetectCycles) { v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); V8ValueConverterImpl converter; // Create a recursive array. - v8::Handle<v8::Array> recursive_array(v8::Array::New(1)); + v8::Handle<v8::Array> recursive_array(v8::Array::New(isolate_, 1)); recursive_array->Set(0, recursive_array); // The first repetition should be trimmed and replaced by a null value. @@ -611,8 +638,10 @@ TEST_F(V8ValueConverterImplTest, DetectCycles) { const std::string key("key"); v8::Handle<v8::Object> recursive_object(v8::Object::New()); v8::TryCatch try_catch; - recursive_object->Set(v8::String::New(key.c_str(), key.length()), - recursive_object); + recursive_object->Set( + v8::String::NewFromUtf8( + isolate_, key.c_str(), v8::String::kNormalString, key.length()), + recursive_object); ASSERT_FALSE(try_catch.HasCaught()); // The first repetition should be trimmed and replaced by a null value. @@ -629,9 +658,9 @@ TEST_F(V8ValueConverterImplTest, DetectCycles) { TEST_F(V8ValueConverterImplTest, MaxRecursionDepth) { v8::HandleScope handle_scope(isolate_); - v8::Context::Scope context_scope(isolate_, context_); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_); + v8::Context::Scope context_scope(context); // Must larger than kMaxRecursionDepth in v8_value_converter_impl.cc. int kDepth = 1000; @@ -642,7 +671,7 @@ TEST_F(V8ValueConverterImplTest, MaxRecursionDepth) { v8::Local<v8::Object> leaf = deep_object; for (int i = 0; i < kDepth; ++i) { v8::Local<v8::Object> new_object = v8::Object::New(); - leaf->Set(v8::String::New(kKey), new_object); + leaf->Set(v8::String::NewFromUtf8(isolate_, kKey), new_object); leaf = new_object; } diff --git a/chromium/content/renderer/web_preferences.cc b/chromium/content/renderer/web_preferences.cc index ce14ce13e01..5a94512667e 100644 --- a/chromium/content/renderer/web_preferences.cc +++ b/chromium/content/renderer/web_preferences.cc @@ -16,18 +16,18 @@ #include "third_party/icu/source/common/unicode/uscript.h" #include "webkit/common/webpreferences.h" -using WebKit::WebNetworkStateNotifier; -using WebKit::WebRuntimeFeatures; -using WebKit::WebSettings; -using WebKit::WebString; -using WebKit::WebURL; -using WebKit::WebView; +using blink::WebNetworkStateNotifier; +using blink::WebRuntimeFeatures; +using blink::WebSettings; +using blink::WebString; +using blink::WebURL; +using blink::WebView; namespace content { namespace { -typedef void (*SetFontFamilyWrapper)(WebKit::WebSettings*, +typedef void (*SetFontFamilyWrapper)(blink::WebSettings*, const base::string16&, UScriptCode); @@ -146,14 +146,10 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) { settings->setUsesEncodingDetector(prefs.uses_universal_detector); settings->setTextAreasAreResizable(prefs.text_areas_are_resizable); settings->setAllowScriptsToCloseWindows(prefs.allow_scripts_to_close_windows); - if (prefs.user_style_sheet_enabled) - settings->setUserStyleSheetLocation(prefs.user_style_sheet_location); - else - settings->setUserStyleSheetLocation(WebURL()); - settings->setAuthorAndUserStylesEnabled(prefs.author_and_user_styles_enabled); settings->setDownloadableBinaryFontsEnabled(prefs.remote_fonts_enabled); settings->setJavaScriptCanAccessClipboard( prefs.javascript_can_access_clipboard); + WebRuntimeFeatures::enableXSLT(prefs.xslt_enabled); settings->setXSSAuditorEnabled(prefs.xss_auditor_enabled); settings->setDNSPrefetchingEnabled(prefs.dns_prefetching_enabled); settings->setLocalStorageEnabled(prefs.local_storage_enabled); @@ -216,6 +212,8 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) { // Uses the mock theme engine for scrollbars. settings->setMockScrollbarsEnabled(prefs.mock_scrollbars_enabled); + settings->setLayerSquashingEnabled(prefs.layer_squashing_enabled); + settings->setThreadedHTMLParser(prefs.threaded_html_parser); // Display visualization of what has changed on the screen using an @@ -236,6 +234,11 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) { settings->setAntialiased2dCanvasEnabled( !prefs.antialiased_2d_canvas_disabled); + // Set MSAA sample count for 2d canvas if requested on the command line (or + // default value if not). + settings->setAccelerated2dCanvasMSAASampleCount( + prefs.accelerated_2d_canvas_msaa_sample_count); + // Enable gpu-accelerated filters if requested on the command line. settings->setAcceleratedFiltersEnabled(prefs.accelerated_filters_enabled); @@ -285,15 +288,16 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) { prefs.allow_running_insecure_content); settings->setPasswordEchoEnabled(prefs.password_echo_enabled); settings->setShouldPrintBackgrounds(prefs.should_print_backgrounds); + settings->setShouldClearDocumentBackground( + prefs.should_clear_document_background); settings->setEnableScrollAnimator(prefs.enable_scroll_animator); settings->setVisualWordMovementEnabled(prefs.visual_word_movement_enabled); - settings->setCSSStickyPositionEnabled(prefs.css_sticky_position_enabled); - settings->setExperimentalCSSCustomFilterEnabled(prefs.css_shaders_enabled); settings->setRegionBasedColumnsEnabled(prefs.region_based_columns_enabled); WebRuntimeFeatures::enableLazyLayout(prefs.lazy_layout_enabled); WebRuntimeFeatures::enableTouch(prefs.touch_enabled); + settings->setMaxTouchPoints(prefs.pointer_events_max_touch_points); settings->setDeviceSupportsTouch(prefs.device_supports_touch); settings->setDeviceSupportsMouse(prefs.device_supports_mouse); settings->setEnableTouchAdjustment(prefs.touch_adjustment_enabled); @@ -313,8 +317,10 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) { settings->setSupportsMultipleWindows(prefs.supports_multiple_windows); settings->setViewportEnabled(prefs.viewport_enabled); - settings->setInitializeAtMinimumPageScale( - prefs.initialize_at_minimum_page_scale); + settings->setLoadWithOverviewMode(prefs.initialize_at_minimum_page_scale); + settings->setViewportMetaEnabled(prefs.viewport_meta_enabled); + settings->setMainFrameResizesAreOrientationChanges( + prefs.main_frame_resizes_are_orientation_changes); settings->setSmartInsertDeleteEnabled(prefs.smart_insert_delete_enabled); @@ -325,7 +331,8 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) { #if defined(OS_ANDROID) settings->setAllowCustomScrollbarInMainFrame(false); settings->setTextAutosizingEnabled(prefs.text_autosizing_enabled); - settings->setTextAutosizingFontScaleFactor(prefs.font_scale_factor); + settings->setAccessibilityFontScaleFactor(prefs.font_scale_factor); + settings->setDeviceScaleAdjustment(prefs.device_scale_adjustment); web_view->setIgnoreViewportTagScaleLimits(prefs.force_enable_zoom); settings->setAutoZoomFocusedNodeToLegibleScale(true); settings->setDoubleTapToZoomEnabled(prefs.double_tap_to_zoom_enabled); @@ -343,8 +350,20 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) { settings->setUseWideViewport(prefs.use_wide_viewport); settings->setViewportMetaLayoutSizeQuirk( prefs.viewport_meta_layout_size_quirk); + settings->setViewportMetaMergeContentQuirk( + prefs.viewport_meta_merge_content_quirk); + settings->setViewportMetaNonUserScalableQuirk( + prefs.viewport_meta_non_user_scalable_quirk); settings->setViewportMetaZeroValuesQuirk( prefs.viewport_meta_zero_values_quirk); + settings->setClobberUserAgentInitialScaleQuirk( + prefs.clobber_user_agent_initial_scale_quirk); + settings->setIgnoreMainFrameOverflowHiddenQuirk( + prefs.ignore_main_frame_overflow_hidden_quirk); + settings->setReportScreenSizeInPhysicalPixelsQuirk( + prefs.report_screen_size_in_physical_pixels_quirk); + settings->setMainFrameClipsContent(false); + settings->setShrinksStandaloneImagesToFit(false); #endif WebNetworkStateNotifier::setOnLine(prefs.is_online); @@ -356,6 +375,7 @@ void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) { settings->setPinchOverlayScrollbarThickness( prefs.pinch_overlay_scrollbar_thickness); settings->setUseSolidColorScrollbars(prefs.use_solid_color_scrollbars); + settings->setCompositorTouchHitTesting(prefs.compositor_touch_hit_testing); } } // namespace content diff --git a/chromium/content/renderer/web_ui_extension.cc b/chromium/content/renderer/web_ui_extension.cc index 9616dbb76a2..f887e9d765e 100644 --- a/chromium/content/renderer/web_ui_extension.cc +++ b/chromium/content/renderer/web_ui_extension.cc @@ -48,13 +48,14 @@ class WebUIExtensionWrapper : public v8::Extension { WebUIExtensionWrapper(); virtual ~WebUIExtensionWrapper(); - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( + virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate( + v8::Isolate* isolate, v8::Handle<v8::String> name) OVERRIDE; static void Send(const v8::FunctionCallbackInfo<v8::Value>& args); static void GetVariableValue(const v8::FunctionCallbackInfo<v8::Value>& args); private: - static bool ShouldRespondToRequest(WebKit::WebFrame** frame_ptr, + static bool ShouldRespondToRequest(blink::WebFrame** frame_ptr, RenderView** render_view_ptr); DISALLOW_COPY_AND_ASSIGN(WebUIExtensionWrapper); @@ -65,20 +66,21 @@ WebUIExtensionWrapper::WebUIExtensionWrapper() WebUIExtensionWrapper::~WebUIExtensionWrapper() {} -v8::Handle<v8::FunctionTemplate> WebUIExtensionWrapper::GetNativeFunction( - v8::Handle<v8::String> name) { - if (name->Equals(v8::String::New("Send"))) - return v8::FunctionTemplate::New(Send); - if (name->Equals(v8::String::New("GetVariableValue"))) - return v8::FunctionTemplate::New(GetVariableValue); +v8::Handle<v8::FunctionTemplate> +WebUIExtensionWrapper::GetNativeFunctionTemplate(v8::Isolate* isolate, + v8::Handle<v8::String> name) { + if (name->Equals(v8::String::NewFromUtf8(isolate, "Send"))) + return v8::FunctionTemplate::New(isolate, Send); + if (name->Equals(v8::String::NewFromUtf8(isolate, "GetVariableValue"))) + return v8::FunctionTemplate::New(isolate, GetVariableValue); return v8::Handle<v8::FunctionTemplate>(); } // static bool WebUIExtensionWrapper::ShouldRespondToRequest( - WebKit::WebFrame** frame_ptr, + blink::WebFrame** frame_ptr, RenderView** render_view_ptr) { - WebKit::WebFrame* frame = WebKit::WebFrame::frameForCurrentContext(); + blink::WebFrame* frame = blink::WebFrame::frameForCurrentContext(); if (!frame || !frame->view()) return false; @@ -104,7 +106,7 @@ bool WebUIExtensionWrapper::ShouldRespondToRequest( // static void WebUIExtensionWrapper::Send( const v8::FunctionCallbackInfo<v8::Value>& args) { - WebKit::WebFrame* frame; + blink::WebFrame* frame; RenderView* render_view; if (!ShouldRespondToRequest(&frame, &render_view)) return; @@ -145,7 +147,7 @@ void WebUIExtensionWrapper::Send( // static void WebUIExtensionWrapper::GetVariableValue( const v8::FunctionCallbackInfo<v8::Value>& args) { - WebKit::WebFrame* frame; + blink::WebFrame* frame; RenderView* render_view; if (!ShouldRespondToRequest(&frame, &render_view)) return; @@ -155,7 +157,10 @@ void WebUIExtensionWrapper::GetVariableValue( std::string key = *v8::String::Utf8Value(args[0]->ToString()); std::string value = WebUIExtensionData::Get(render_view)->GetValue(key); - args.GetReturnValue().Set(v8::String::New(value.c_str(), value.length())); + args.GetReturnValue().Set(v8::String::NewFromUtf8(args.GetIsolate(), + value.c_str(), + v8::String::kNormalString, + value.length())); } // static diff --git a/chromium/content/renderer/webclipboard_impl.cc b/chromium/content/renderer/webclipboard_impl.cc index 9ab29d1d892..c1ee0a71230 100644 --- a/chromium/content/renderer/webclipboard_impl.cc +++ b/chromium/content/renderer/webclipboard_impl.cc @@ -9,6 +9,7 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "content/public/common/drop_data.h" +#include "content/renderer/clipboard_utils.h" #include "content/renderer/drop_data_builder.h" #include "content/renderer/scoped_clipboard_writer_glue.h" #include "third_party/WebKit/public/platform/WebData.h" @@ -22,16 +23,14 @@ #include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/custom_data_helper.h" #include "url/gurl.h" -#include "webkit/glue/webkit_glue.h" -#include "webkit/renderer/clipboard_utils.h" -using WebKit::WebClipboard; -using WebKit::WebData; -using WebKit::WebDragData; -using WebKit::WebImage; -using WebKit::WebString; -using WebKit::WebURL; -using WebKit::WebVector; +using blink::WebClipboard; +using blink::WebData; +using blink::WebDragData; +using blink::WebImage; +using blink::WebString; +using blink::WebURL; +using blink::WebVector; namespace content { @@ -42,40 +41,36 @@ WebClipboardImpl::WebClipboardImpl(ClipboardClient* client) WebClipboardImpl::~WebClipboardImpl() { } -uint64 WebClipboardImpl::getSequenceNumber() { - return sequenceNumber(BufferStandard); -} - uint64 WebClipboardImpl::sequenceNumber(Buffer buffer) { - ui::Clipboard::Buffer buffer_type; - if (!ConvertBufferType(buffer, &buffer_type)) + ui::ClipboardType clipboard_type; + if (!ConvertBufferType(buffer, &clipboard_type)) return 0; - return client_->GetSequenceNumber(buffer_type); + return client_->GetSequenceNumber(clipboard_type); } bool WebClipboardImpl::isFormatAvailable(Format format, Buffer buffer) { - ui::Clipboard::Buffer buffer_type = ui::Clipboard::BUFFER_STANDARD; + ui::ClipboardType clipboard_type = ui::CLIPBOARD_TYPE_COPY_PASTE; - if (!ConvertBufferType(buffer, &buffer_type)) + if (!ConvertBufferType(buffer, &clipboard_type)) return false; switch (format) { case FormatPlainText: return client_->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(), - buffer_type) || + clipboard_type) || client_->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(), - buffer_type); + clipboard_type); case FormatHTML: return client_->IsFormatAvailable(ui::Clipboard::GetHtmlFormatType(), - buffer_type); + clipboard_type); case FormatSmartPaste: return client_->IsFormatAvailable( - ui::Clipboard::GetWebKitSmartPasteFormatType(), buffer_type); + ui::Clipboard::GetWebKitSmartPasteFormatType(), clipboard_type); case FormatBookmark: #if defined(OS_WIN) || defined(OS_MACOSX) return client_->IsFormatAvailable(ui::Clipboard::GetUrlWFormatType(), - buffer_type); + clipboard_type); #endif default: NOTREACHED(); @@ -86,31 +81,31 @@ bool WebClipboardImpl::isFormatAvailable(Format format, Buffer buffer) { WebVector<WebString> WebClipboardImpl::readAvailableTypes( Buffer buffer, bool* contains_filenames) { - ui::Clipboard::Buffer buffer_type; + ui::ClipboardType clipboard_type; std::vector<base::string16> types; - if (ConvertBufferType(buffer, &buffer_type)) { - client_->ReadAvailableTypes(buffer_type, &types, contains_filenames); + if (ConvertBufferType(buffer, &clipboard_type)) { + client_->ReadAvailableTypes(clipboard_type, &types, contains_filenames); } return types; } WebString WebClipboardImpl::readPlainText(Buffer buffer) { - ui::Clipboard::Buffer buffer_type; - if (!ConvertBufferType(buffer, &buffer_type)) + ui::ClipboardType clipboard_type; + if (!ConvertBufferType(buffer, &clipboard_type)) return WebString(); if (client_->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(), - buffer_type)) { + clipboard_type)) { base::string16 text; - client_->ReadText(buffer_type, &text); + client_->ReadText(clipboard_type, &text); if (!text.empty()) return text; } if (client_->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(), - buffer_type)) { + clipboard_type)) { std::string text; - client_->ReadAsciiText(buffer_type, &text); + client_->ReadAsciiText(clipboard_type, &text); if (!text.empty()) return ASCIIToUTF16(text); } @@ -121,13 +116,13 @@ WebString WebClipboardImpl::readPlainText(Buffer buffer) { WebString WebClipboardImpl::readHTML(Buffer buffer, WebURL* source_url, unsigned* fragment_start, unsigned* fragment_end) { - ui::Clipboard::Buffer buffer_type; - if (!ConvertBufferType(buffer, &buffer_type)) + ui::ClipboardType clipboard_type; + if (!ConvertBufferType(buffer, &clipboard_type)) return WebString(); base::string16 html_stdstr; GURL gurl; - client_->ReadHTML(buffer_type, &html_stdstr, &gurl, + client_->ReadHTML(clipboard_type, &html_stdstr, &gurl, static_cast<uint32*>(fragment_start), static_cast<uint32*>(fragment_end)); *source_url = gurl; @@ -135,26 +130,31 @@ WebString WebClipboardImpl::readHTML(Buffer buffer, WebURL* source_url, } WebData WebClipboardImpl::readImage(Buffer buffer) { - ui::Clipboard::Buffer buffer_type; - if (!ConvertBufferType(buffer, &buffer_type)) + ui::ClipboardType clipboard_type; + if (!ConvertBufferType(buffer, &clipboard_type)) return WebData(); std::string png_data; - client_->ReadImage(buffer_type, &png_data); + client_->ReadImage(clipboard_type, &png_data); return WebData(png_data); } WebString WebClipboardImpl::readCustomData(Buffer buffer, const WebString& type) { - ui::Clipboard::Buffer buffer_type; - if (!ConvertBufferType(buffer, &buffer_type)) + ui::ClipboardType clipboard_type; + if (!ConvertBufferType(buffer, &clipboard_type)) return WebString(); base::string16 data; - client_->ReadCustomData(buffer_type, type, &data); + client_->ReadCustomData(clipboard_type, type, &data); return data; } +void WebClipboardImpl::writePlainText(const WebString& plain_text) { + ScopedClipboardWriterGlue scw(client_); + scw.WriteText(plain_text); +} + void WebClipboardImpl::writeHTML( const WebString& html_text, const WebURL& source_url, const WebString& plain_text, bool write_smart_paste) { @@ -166,22 +166,9 @@ void WebClipboardImpl::writeHTML( scw.WriteWebSmartPaste(); } -void WebClipboardImpl::writePlainText(const WebString& plain_text) { - ScopedClipboardWriterGlue scw(client_); - scw.WriteText(plain_text); -} - -void WebClipboardImpl::writeURL(const WebURL& url, const WebString& title) { - ScopedClipboardWriterGlue scw(client_); - - scw.WriteBookmark(title, url.spec()); - scw.WriteHTML(UTF8ToUTF16(webkit_clipboard::URLToMarkup(url, title)), - std::string()); - scw.WriteText(UTF8ToUTF16(std::string(url.spec()))); -} - -void WebClipboardImpl::writeImage( - const WebImage& image, const WebURL& url, const WebString& title) { +void WebClipboardImpl::writeImage(const WebImage& image, + const WebURL& url, + const WebString& title) { ScopedClipboardWriterGlue scw(client_); if (!image.isNull()) { @@ -200,8 +187,7 @@ void WebClipboardImpl::writeImage( // We also don't want to write HTML on a Mac, since Mail.app prefers to use // the image markup over attaching the actual image. See // http://crbug.com/33016 for details. - scw.WriteHTML(UTF8ToUTF16(webkit_clipboard::URLToImageMarkup(url, title)), - std::string()); + scw.WriteHTML(UTF8ToUTF16(URLToImageMarkup(url, title)), std::string()); #endif } } @@ -228,8 +214,8 @@ void WebClipboardImpl::writeDataObject(const WebDragData& data) { } bool WebClipboardImpl::ConvertBufferType(Buffer buffer, - ui::Clipboard::Buffer* result) { - *result = ui::Clipboard::BUFFER_STANDARD; + ui::ClipboardType* result) { + *result = ui::CLIPBOARD_TYPE_COPY_PASTE; switch (buffer) { case BufferStandard: break; @@ -240,7 +226,7 @@ bool WebClipboardImpl::ConvertBufferType(Buffer buffer, // but not the X selection clipboad. return false; #else - *result = ui::Clipboard::BUFFER_SELECTION; + *result = ui::CLIPBOARD_TYPE_SELECTION; break; #endif #endif @@ -252,4 +238,3 @@ bool WebClipboardImpl::ConvertBufferType(Buffer buffer, } } // namespace content - diff --git a/chromium/content/renderer/webclipboard_impl.h b/chromium/content/renderer/webclipboard_impl.h index e5a12aa47bd..477f53b08fb 100644 --- a/chromium/content/renderer/webclipboard_impl.h +++ b/chromium/content/renderer/webclipboard_impl.h @@ -15,48 +15,43 @@ namespace content { class ClipboardClient; -class WebClipboardImpl : public WebKit::WebClipboard { +class WebClipboardImpl : public blink::WebClipboard { public: explicit WebClipboardImpl(ClipboardClient* client); virtual ~WebClipboardImpl(); // WebClipboard methods: - virtual uint64 getSequenceNumber(); virtual uint64 sequenceNumber(Buffer buffer); virtual bool isFormatAvailable(Format format, Buffer buffer); - virtual WebKit::WebVector<WebKit::WebString> readAvailableTypes( + virtual blink::WebVector<blink::WebString> readAvailableTypes( Buffer buffer, bool* contains_filenames); - virtual WebKit::WebString readPlainText(Buffer buffer); - virtual WebKit::WebString readHTML( + virtual blink::WebString readPlainText(Buffer buffer); + virtual blink::WebString readHTML( Buffer buffer, - WebKit::WebURL* source_url, + blink::WebURL* source_url, unsigned* fragment_start, unsigned* fragment_end); - virtual WebKit::WebData readImage(Buffer buffer); - virtual WebKit::WebString readCustomData( - Buffer buffer, const WebKit::WebString& type); + virtual blink::WebData readImage(Buffer buffer); + virtual blink::WebString readCustomData( + Buffer buffer, const blink::WebString& type); + virtual void writePlainText(const blink::WebString& plain_text); virtual void writeHTML( - const WebKit::WebString& html_text, - const WebKit::WebURL& source_url, - const WebKit::WebString& plain_text, + const blink::WebString& html_text, + const blink::WebURL& source_url, + const blink::WebString& plain_text, bool write_smart_paste); - virtual void writePlainText(const WebKit::WebString& plain_text); - virtual void writeURL( - const WebKit::WebURL& url, - const WebKit::WebString& title); virtual void writeImage( - const WebKit::WebImage& image, - const WebKit::WebURL& source_url, - const WebKit::WebString& title); - virtual void writeDataObject(const WebKit::WebDragData& data); + const blink::WebImage& image, + const blink::WebURL& source_url, + const blink::WebString& title); + virtual void writeDataObject(const blink::WebDragData& data); private: - bool ConvertBufferType(Buffer, ui::Clipboard::Buffer*); + bool ConvertBufferType(Buffer, ui::ClipboardType*); ClipboardClient* client_; }; } // namespace content #endif // CONTENT_RENDERER_WEBCLIPBOARD_IMPL_H_ - diff --git a/chromium/content/renderer/webcrypto/OWNERS b/chromium/content/renderer/webcrypto/OWNERS new file mode 100644 index 00000000000..6b60858e6e8 --- /dev/null +++ b/chromium/content/renderer/webcrypto/OWNERS @@ -0,0 +1,2 @@ +eroman@chromium.org +rsleevi@chromium.org diff --git a/chromium/content/renderer/webcrypto/webcrypto_impl.cc b/chromium/content/renderer/webcrypto/webcrypto_impl.cc new file mode 100644 index 00000000000..4e343ba873a --- /dev/null +++ b/chromium/content/renderer/webcrypto/webcrypto_impl.cc @@ -0,0 +1,631 @@ +// Copyright (c) 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/renderer/webcrypto/webcrypto_impl.h" + +#include <algorithm> +#include <functional> +#include <map> +#include "base/json/json_reader.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_piece.h" +#include "base/values.h" +#include "content/renderer/webcrypto/webcrypto_util.h" +#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" +#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" +#include "third_party/WebKit/public/platform/WebCryptoKey.h" + +namespace content { + +namespace { + +bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) { + // TODO(padolph): include all other asymmetric algorithms once they are + // defined, e.g. EC and DH. + return (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || + algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || + algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep); +} + +// Binds a specific key length value to a compatible factory function. +typedef blink::WebCryptoAlgorithm (*AlgFactoryFuncWithOneShortArg)( + unsigned short); +template <AlgFactoryFuncWithOneShortArg func, unsigned short key_length> +blink::WebCryptoAlgorithm BindAlgFactoryWithKeyLen() { + return func(key_length); +} + +// Binds a WebCryptoAlgorithmId value to a compatible factory function. +typedef blink::WebCryptoAlgorithm (*AlgFactoryFuncWithWebCryptoAlgIdArg)( + blink::WebCryptoAlgorithmId); +template <AlgFactoryFuncWithWebCryptoAlgIdArg func, + blink::WebCryptoAlgorithmId algorithm_id> +blink::WebCryptoAlgorithm BindAlgFactoryAlgorithmId() { + return func(algorithm_id); +} + +// Defines a map between a JWK 'alg' string ID and a corresponding Web Crypto +// factory function. +typedef blink::WebCryptoAlgorithm (*AlgFactoryFuncNoArgs)(); +typedef std::map<std::string, AlgFactoryFuncNoArgs> JwkAlgFactoryMap; + +class JwkAlgorithmFactoryMap { + public: + JwkAlgorithmFactoryMap() { + map_["HS256"] = + &BindAlgFactoryWithKeyLen<webcrypto::CreateHmacAlgorithmByHashOutputLen, + 256>; + map_["HS384"] = + &BindAlgFactoryWithKeyLen<webcrypto::CreateHmacAlgorithmByHashOutputLen, + 384>; + map_["HS512"] = + &BindAlgFactoryWithKeyLen<webcrypto::CreateHmacAlgorithmByHashOutputLen, + 512>; + map_["RS256"] = + &BindAlgFactoryAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, + blink::WebCryptoAlgorithmIdSha256>; + map_["RS384"] = + &BindAlgFactoryAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, + blink::WebCryptoAlgorithmIdSha384>; + map_["RS512"] = + &BindAlgFactoryAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, + blink::WebCryptoAlgorithmIdSha512>; + map_["RSA1_5"] = + &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm, + blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5>; + map_["RSA-OAEP"] = + &BindAlgFactoryAlgorithmId<webcrypto::CreateRsaOaepAlgorithm, + blink::WebCryptoAlgorithmIdSha1>; + // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 128 yet + map_["A128KW"] = &blink::WebCryptoAlgorithm::createNull; + // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 256 yet + map_["A256KW"] = &blink::WebCryptoAlgorithm::createNull; + map_["A128GCM"] = + &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm, + blink::WebCryptoAlgorithmIdAesGcm>; + map_["A256GCM"] = + &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm, + blink::WebCryptoAlgorithmIdAesGcm>; + map_["A128CBC"] = + &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm, + blink::WebCryptoAlgorithmIdAesCbc>; + map_["A192CBC"] = + &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm, + blink::WebCryptoAlgorithmIdAesCbc>; + map_["A256CBC"] = + &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm, + blink::WebCryptoAlgorithmIdAesCbc>; + } + + blink::WebCryptoAlgorithm CreateAlgorithmFromName(const std::string& alg_id) + const { + const JwkAlgFactoryMap::const_iterator pos = map_.find(alg_id); + if (pos == map_.end()) + return blink::WebCryptoAlgorithm::createNull(); + return pos->second(); + } + + private: + JwkAlgFactoryMap map_; +}; + +base::LazyInstance<JwkAlgorithmFactoryMap> jwk_alg_factory = + LAZY_INSTANCE_INITIALIZER; + +bool WebCryptoAlgorithmsConsistent(const blink::WebCryptoAlgorithm& alg1, + const blink::WebCryptoAlgorithm& alg2) { + DCHECK(!alg1.isNull()); + DCHECK(!alg2.isNull()); + if (alg1.id() != alg2.id()) + return false; + switch (alg1.id()) { + case blink::WebCryptoAlgorithmIdHmac: + case blink::WebCryptoAlgorithmIdRsaOaep: + case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: + if (WebCryptoAlgorithmsConsistent( + webcrypto::GetInnerHashAlgorithm(alg1), + webcrypto::GetInnerHashAlgorithm(alg2))) { + return true; + } + break; + case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: + case blink::WebCryptoAlgorithmIdSha1: + case blink::WebCryptoAlgorithmIdSha224: + case blink::WebCryptoAlgorithmIdSha256: + case blink::WebCryptoAlgorithmIdSha384: + case blink::WebCryptoAlgorithmIdSha512: + case blink::WebCryptoAlgorithmIdAesCbc: + case blink::WebCryptoAlgorithmIdAesGcm: + case blink::WebCryptoAlgorithmIdAesCtr: + return true; + default: + NOTREACHED(); // Not a supported algorithm. + break; + } + return false; +} + +bool GetDecodedUrl64ValueByKey( + const base::DictionaryValue& dict, + const std::string& key, + std::string* decoded) { + std::string value_url64; + if (!dict.GetString(key, &value_url64) || + !webcrypto::Base64DecodeUrlSafe(value_url64, decoded) || + !decoded->size()) { + return false; + } + return true; +} + +} // namespace + +WebCryptoImpl::WebCryptoImpl() { + Init(); +} + +void WebCryptoImpl::encrypt( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebCryptoResult result) { + DCHECK(!algorithm.isNull()); + blink::WebArrayBuffer buffer; + if (!EncryptInternal(algorithm, key, data, data_size, &buffer)) { + result.completeWithError(); + } else { + result.completeWithBuffer(buffer); + } +} + +void WebCryptoImpl::decrypt( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebCryptoResult result) { + DCHECK(!algorithm.isNull()); + blink::WebArrayBuffer buffer; + if (!DecryptInternal(algorithm, key, data, data_size, &buffer)) { + result.completeWithError(); + } else { + result.completeWithBuffer(buffer); + } +} + +void WebCryptoImpl::digest( + const blink::WebCryptoAlgorithm& algorithm, + const unsigned char* data, + unsigned data_size, + blink::WebCryptoResult result) { + DCHECK(!algorithm.isNull()); + blink::WebArrayBuffer buffer; + if (!DigestInternal(algorithm, data, data_size, &buffer)) { + result.completeWithError(); + } else { + result.completeWithBuffer(buffer); + } +} + +void WebCryptoImpl::generateKey( + const blink::WebCryptoAlgorithm& algorithm, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoResult result) { + DCHECK(!algorithm.isNull()); + if (IsAlgorithmAsymmetric(algorithm)) { + blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); + blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); + if (!GenerateKeyPairInternal( + algorithm, extractable, usage_mask, &public_key, &private_key)) { + result.completeWithError(); + } else { + DCHECK(public_key.handle()); + DCHECK(private_key.handle()); + DCHECK_EQ(algorithm.id(), public_key.algorithm().id()); + DCHECK_EQ(algorithm.id(), private_key.algorithm().id()); + DCHECK_EQ(true, public_key.extractable()); + DCHECK_EQ(extractable, private_key.extractable()); + DCHECK_EQ(usage_mask, public_key.usages()); + DCHECK_EQ(usage_mask, private_key.usages()); + result.completeWithKeyPair(public_key, private_key); + } + } else { + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + if (!GenerateKeyInternal(algorithm, extractable, usage_mask, &key)) { + result.completeWithError(); + } else { + DCHECK(key.handle()); + DCHECK_EQ(algorithm.id(), key.algorithm().id()); + DCHECK_EQ(extractable, key.extractable()); + DCHECK_EQ(usage_mask, key.usages()); + result.completeWithKey(key); + } + } +} + +void WebCryptoImpl::importKey( + blink::WebCryptoKeyFormat format, + const unsigned char* key_data, + unsigned key_data_size, + const blink::WebCryptoAlgorithm& algorithm_or_null, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoResult result) { + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + if (format == blink::WebCryptoKeyFormatJwk) { + if (!ImportKeyJwk(key_data, + key_data_size, + algorithm_or_null, + extractable, + usage_mask, + &key)) { + result.completeWithError(); + return; + } + } else { + if (!ImportKeyInternal(format, + key_data, + key_data_size, + algorithm_or_null, + extractable, + usage_mask, + &key)) { + result.completeWithError(); + return; + } + } + DCHECK(key.handle()); + DCHECK(!key.algorithm().isNull()); + DCHECK_EQ(extractable, key.extractable()); + result.completeWithKey(key); +} + +void WebCryptoImpl::exportKey( + blink::WebCryptoKeyFormat format, + const blink::WebCryptoKey& key, + blink::WebCryptoResult result) { + blink::WebArrayBuffer buffer; + if (!ExportKeyInternal(format, key, &buffer)) { + result.completeWithError(); + return; + } + result.completeWithBuffer(buffer); +} + +void WebCryptoImpl::sign( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebCryptoResult result) { + DCHECK(!algorithm.isNull()); + blink::WebArrayBuffer buffer; + if (!SignInternal(algorithm, key, data, data_size, &buffer)) { + result.completeWithError(); + } else { + result.completeWithBuffer(buffer); + } +} + +void WebCryptoImpl::verifySignature( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* signature, + unsigned signature_size, + const unsigned char* data, + unsigned data_size, + blink::WebCryptoResult result) { + DCHECK(!algorithm.isNull()); + bool signature_match = false; + if (!VerifySignatureInternal(algorithm, + key, + signature, + signature_size, + data, + data_size, + &signature_match)) { + result.completeWithError(); + } else { + result.completeWithBoolean(signature_match); + } +} + +bool WebCryptoImpl::ImportKeyJwk( + const unsigned char* key_data, + unsigned key_data_size, + const blink::WebCryptoAlgorithm& algorithm_or_null, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* key) { + + // The goal of this method is to extract key material and meta data from the + // incoming JWK, combine them with the input parameters, and ultimately import + // a Web Crypto Key. + // + // JSON Web Key Format (JWK) + // http://tools.ietf.org/html/draft-ietf-jose-json-web-key-16 + // TODO(padolph): Not all possible values are handled by this code right now + // + // A JWK is a simple JSON dictionary with the following entries + // - "kty" (Key Type) Parameter, REQUIRED + // - <kty-specific parameters, see below>, REQUIRED + // - "use" (Key Use) Parameter, OPTIONAL + // - "alg" (Algorithm) Parameter, OPTIONAL + // - "extractable" (Key Exportability), OPTIONAL [NOTE: not yet part of JOSE, + // see https://www.w3.org/Bugs/Public/show_bug.cgi?id=23796] + // (all other entries are ignored) + // + // OPTIONAL here means that this code does not require the entry to be present + // in the incoming JWK, because the method input parameters contain similar + // information. If the optional JWK entry is present, it will be validated + // against the corresponding input parameter for consistency and combined with + // it according to rules defined below. A special case is that the method + // input parameter 'algorithm' is also optional. If it is null, the JWK 'alg' + // value (if present) is used as a fallback. + // + // Input 'key_data' contains the JWK. To build a Web Crypto Key, the JWK + // values are parsed out and combined with the method input parameters to + // build a Web Crypto Key: + // Web Crypto Key type <-- (deduced) + // Web Crypto Key extractable <-- JWK extractable + input extractable + // Web Crypto Key algorithm <-- JWK alg + input algorithm + // Web Crypto Key keyUsage <-- JWK use + input usage_mask + // Web Crypto Key keying material <-- kty-specific parameters + // + // Values for each JWK entry are case-sensitive and defined in + // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16. + // Note that not all values specified by JOSE are handled by this code. Only + // handled values are listed. + // - kty (Key Type) + // +-------+--------------------------------------------------------------+ + // | "RSA" | RSA [RFC3447] | + // | "oct" | Octet sequence (used to represent symmetric keys) | + // +-------+--------------------------------------------------------------+ + // - use (Key Use) + // +-------+--------------------------------------------------------------+ + // | "enc" | encrypt and decrypt operations | + // | "sig" | sign and verify (MAC) operations | + // | "wrap"| key wrap and unwrap [not yet part of JOSE] | + // +-------+--------------------------------------------------------------+ + // - extractable (Key Exportability) + // +-------+--------------------------------------------------------------+ + // | true | Key may be exported from the trusted environment | + // | false | Key cannot exit the trusted environment | + // +-------+--------------------------------------------------------------+ + // - alg (Algorithm) + // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16 + // +--------------+-------------------------------------------------------+ + // | Digital Signature or MAC Algorithm | + // +--------------+-------------------------------------------------------+ + // | "HS256" | HMAC using SHA-256 hash algorithm | + // | "HS384" | HMAC using SHA-384 hash algorithm | + // | "HS512" | HMAC using SHA-512 hash algorithm | + // | "RS256" | RSASSA using SHA-256 hash algorithm | + // | "RS384" | RSASSA using SHA-384 hash algorithm | + // | "RS512" | RSASSA using SHA-512 hash algorithm | + // +--------------+-------------------------------------------------------| + // | Key Management Algorithm | + // +--------------+-------------------------------------------------------+ + // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] | + // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding | + // | | (OAEP) [RFC3447], with the default parameters | + // | | specified by RFC3447 in Section A.2.1 | + // | "A128KW" | Advanced Encryption Standard (AES) Key Wrap Algorithm | + // | | [RFC3394] using 128 bit keys | + // | "A256KW" | AES Key Wrap Algorithm using 256 bit keys | + // | "A128GCM" | AES in Galois/Counter Mode (GCM) [NIST.800-38D] using | + // | | 128 bit keys | + // | "A256GCM" | AES GCM using 256 bit keys | + // | "A128CBC" | AES in Cipher Block Chaining Mode (CBC) with PKCS #5 | + // | | padding [NIST.800-38A] [not yet part of JOSE, see | + // | | https://www.w3.org/Bugs/Public/show_bug.cgi?id=23796 | + // | "A192CBC" | AES CBC using 192 bit keys [not yet part of JOSE] | + // | "A256CBC" | AES CBC using 256 bit keys [not yet part of JOSE] | + // +--------------+-------------------------------------------------------+ + // + // kty-specific parameters + // The value of kty determines the type and content of the keying material + // carried in the JWK to be imported. Currently only two possibilities are + // supported: a raw key or an RSA public key. RSA private keys are not + // supported because typical applications seldom need to import a private key, + // and the large number of JWK parameters required to describe one. + // - kty == "oct" (symmetric or other raw key) + // +-------+--------------------------------------------------------------+ + // | "k" | Contains the value of the symmetric (or other single-valued) | + // | | key. It is represented as the base64url encoding of the | + // | | octet sequence containing the key value. | + // +-------+--------------------------------------------------------------+ + // - kty == "RSA" (RSA public key) + // +-------+--------------------------------------------------------------+ + // | "n" | Contains the modulus value for the RSA public key. It is | + // | | represented as the base64url encoding of the value's | + // | | unsigned big endian representation as an octet sequence. | + // +-------+--------------------------------------------------------------+ + // | "e" | Contains the exponent value for the RSA public key. It is | + // | | represented as the base64url encoding of the value's | + // | | unsigned big endian representation as an octet sequence. | + // +-------+--------------------------------------------------------------+ + // + // Consistency and conflict resolution + // The 'algorithm_or_null', 'extractable', and 'usage_mask' input parameters + // may be different than the corresponding values inside the JWK. The Web + // Crypto spec says that if a JWK value is present but is inconsistent with + // the input value, it is an error and the operation must fail. If no + // inconsistency is found, the input and JWK values are combined as follows: + // + // algorithm + // If an algorithm is provided by both the input parameter and the JWK, + // consistency between the two is based only on algorithm ID's (including an + // inner hash algorithm if present). In this case if the consistency + // check is passed, the input algorithm is used. If only one of either the + // input algorithm and JWK alg is provided, it is used as the final + // algorithm. + // + // extractable + // If the JWK extractable is true but the input parameter is false, make the + // Web Crypto Key non-extractable. Conversely, if the JWK extractable is + // false but the input parameter is true, it is an inconsistency. If both + // are true or both are false, use that value. + // + // usage_mask + // The input usage_mask must be a strict subset of the interpreted JWK use + // value, else it is judged inconsistent. In all cases the input usage_mask + // is used as the final usage_mask. + // + + if (!key_data_size) + return false; + DCHECK(key); + + // Parse the incoming JWK JSON. + base::StringPiece json_string(reinterpret_cast<const char*>(key_data), + key_data_size); + scoped_ptr<base::Value> value(base::JSONReader::Read(json_string)); + // Note, bare pointer dict_value is ok since it points into scoped value. + base::DictionaryValue* dict_value = NULL; + if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value) + return false; + + // JWK "kty". Exit early if this required JWK parameter is missing. + std::string jwk_kty_value; + if (!dict_value->GetString("kty", &jwk_kty_value)) + return false; + + // JWK "extractable" (optional) --> extractable parameter + { + bool jwk_extractable_value; + if (dict_value->GetBoolean("extractable", &jwk_extractable_value)) { + if (!jwk_extractable_value && extractable) + return false; + extractable = extractable && jwk_extractable_value; + } + } + + // JWK "alg" (optional) --> algorithm parameter + // Note: input algorithm is also optional, so we have six cases to handle. + // 1. JWK alg present but unrecognized: error + // 2. JWK alg valid AND input algorithm isNull: use JWK value + // 3. JWK alg valid AND input algorithm specified, but JWK value + // inconsistent with input: error + // 4. JWK alg valid AND input algorithm specified, both consistent: use + // input value (because it has potentially more details) + // 5. JWK alg missing AND input algorithm isNull: error + // 6. JWK alg missing AND input algorithm specified: use input value + blink::WebCryptoAlgorithm algorithm = blink::WebCryptoAlgorithm::createNull(); + std::string jwk_alg_value; + if (dict_value->GetString("alg", &jwk_alg_value)) { + // JWK alg present + + // TODO(padolph): Validate alg vs kty. For example kty="RSA" implies alg can + // only be from the RSA family. + + const blink::WebCryptoAlgorithm jwk_algorithm = + jwk_alg_factory.Get().CreateAlgorithmFromName(jwk_alg_value); + if (jwk_algorithm.isNull()) { + // JWK alg unrecognized + return false; // case 1 + } + // JWK alg valid + if (algorithm_or_null.isNull()) { + // input algorithm not specified + algorithm = jwk_algorithm; // case 2 + } else { + // input algorithm specified + if (!WebCryptoAlgorithmsConsistent(jwk_algorithm, algorithm_or_null)) + return false; // case 3 + algorithm = algorithm_or_null; // case 4 + } + } else { + // JWK alg missing + if (algorithm_or_null.isNull()) + return false; // case 5 + algorithm = algorithm_or_null; // case 6 + } + DCHECK(!algorithm.isNull()); + + // JWK "use" (optional) --> usage_mask parameter + std::string jwk_use_value; + if (dict_value->GetString("use", &jwk_use_value)) { + blink::WebCryptoKeyUsageMask jwk_usage_mask = 0; + if (jwk_use_value == "enc") { + jwk_usage_mask = + blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt; + } else if (jwk_use_value == "sig") { + jwk_usage_mask = + blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify; + } else if (jwk_use_value == "wrap") { + jwk_usage_mask = + blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey; + } else { + return false; + } + if ((jwk_usage_mask & usage_mask) != usage_mask) { + // A usage_mask must be a subset of jwk_usage_mask. + return false; + } + } + + // JWK keying material --> ImportKeyInternal() + if (jwk_kty_value == "oct") { + + std::string jwk_k_value; + if (!GetDecodedUrl64ValueByKey(*dict_value, "k", &jwk_k_value)) + return false; + + // TODO(padolph): Some JWK alg ID's embed information about the key length + // in the alg ID string. For example "A128" implies the JWK carries 128 bits + // of key material, and "HS512" implies the JWK carries _at least_ 512 bits + // of key material. For such keys validate the actual key length against the + // value in the ID. + + return ImportKeyInternal(blink::WebCryptoKeyFormatRaw, + reinterpret_cast<const uint8*>(jwk_k_value.data()), + jwk_k_value.size(), + algorithm, + extractable, + usage_mask, + key); + } else if (jwk_kty_value == "RSA") { + + // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry + // in the JWK, while an RSA private key must have those, plus at least a "d" + // (private exponent) entry. + // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18, + // section 6.3. + + // RSA private key import is not currently supported, so fail here if a "d" + // entry is found. + // TODO(padolph): Support RSA private key import. + if (dict_value->HasKey("d")) + return false; + + std::string jwk_n_value; + if (!GetDecodedUrl64ValueByKey(*dict_value, "n", &jwk_n_value)) + return false; + std::string jwk_e_value; + if (!GetDecodedUrl64ValueByKey(*dict_value, "e", &jwk_e_value)) + return false; + + return ImportRsaPublicKeyInternal( + reinterpret_cast<const uint8*>(jwk_n_value.data()), + jwk_n_value.size(), + reinterpret_cast<const uint8*>(jwk_e_value.data()), + jwk_e_value.size(), + algorithm, + extractable, + usage_mask, + key); + + } else { + return false; + } + + return true; +} + +} // namespace content diff --git a/chromium/content/renderer/webcrypto/webcrypto_impl.h b/chromium/content/renderer/webcrypto/webcrypto_impl.h new file mode 100644 index 00000000000..6537d429b6f --- /dev/null +++ b/chromium/content/renderer/webcrypto/webcrypto_impl.h @@ -0,0 +1,153 @@ +// Copyright (c) 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_RENDERER_WEBCRYPTO_WEBCRYPTO_IMPL_H_ +#define CONTENT_RENDERER_WEBCRYPTO_WEBCRYPTO_IMPL_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "content/common/content_export.h" +#include "third_party/WebKit/public/platform/WebCrypto.h" + +namespace content { + +class CONTENT_EXPORT WebCryptoImpl + : NON_EXPORTED_BASE(public blink::WebCrypto) { + public: + WebCryptoImpl(); + + virtual void encrypt( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebCryptoResult result); + virtual void decrypt( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebCryptoResult result); + virtual void digest( + const blink::WebCryptoAlgorithm& algorithm, + const unsigned char* data, + unsigned data_size, + blink::WebCryptoResult result); + virtual void generateKey( + const blink::WebCryptoAlgorithm& algorithm, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoResult result); + virtual void importKey( + blink::WebCryptoKeyFormat format, + const unsigned char* key_data, + unsigned key_data_size, + const blink::WebCryptoAlgorithm& algorithm_or_null, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoResult result); + virtual void exportKey( + blink::WebCryptoKeyFormat format, + const blink::WebCryptoKey& key, + blink::WebCryptoResult result); + virtual void sign( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebCryptoResult result); + virtual void verifySignature( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* signature, + unsigned signature_size, + const unsigned char* data, + unsigned data_size, + blink::WebCryptoResult result); + + + protected: + friend class WebCryptoImplTest; + + void Init(); + + bool EncryptInternal( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebArrayBuffer* buffer); + bool DecryptInternal( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebArrayBuffer* buffer); + bool DigestInternal( + const blink::WebCryptoAlgorithm& algorithm, + const unsigned char* data, + unsigned data_size, + blink::WebArrayBuffer* buffer); + bool GenerateKeyInternal( + const blink::WebCryptoAlgorithm& algorithm, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* key); + bool GenerateKeyPairInternal( + const blink::WebCryptoAlgorithm& algorithm, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* public_key, + blink::WebCryptoKey* private_key); + bool ImportKeyInternal( + blink::WebCryptoKeyFormat format, + const unsigned char* key_data, + unsigned key_data_size, + const blink::WebCryptoAlgorithm& algorithm_or_null, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* key); + bool ExportKeyInternal( + blink::WebCryptoKeyFormat format, + const blink::WebCryptoKey& key, + blink::WebArrayBuffer* buffer); + bool SignInternal( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebArrayBuffer* buffer); + bool VerifySignatureInternal( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* signature, + unsigned signature_size, + const unsigned char* data, + unsigned data_size, + bool* signature_match); + + bool ImportKeyJwk( + const unsigned char* key_data, + unsigned key_data_size, + const blink::WebCryptoAlgorithm& algorithm_or_null, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* key); + bool ImportRsaPublicKeyInternal( + const unsigned char* modulus_data, + unsigned modulus_size, + const unsigned char* exponent_data, + unsigned exponent_size, + const blink::WebCryptoAlgorithm& algorithm, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* key); + + private: + DISALLOW_COPY_AND_ASSIGN(WebCryptoImpl); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_WEBCRYPTO_WEBCRYPTO_IMPL_H_ diff --git a/chromium/content/renderer/webcrypto/webcrypto_impl_nss.cc b/chromium/content/renderer/webcrypto/webcrypto_impl_nss.cc new file mode 100644 index 00000000000..105bfbe9f89 --- /dev/null +++ b/chromium/content/renderer/webcrypto/webcrypto_impl_nss.cc @@ -0,0 +1,1013 @@ +// 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/renderer/webcrypto/webcrypto_impl.h" + +#include <cryptohi.h> +#include <pk11pub.h> +#include <sechash.h> + +#include <vector> + +#include "base/logging.h" +#include "content/renderer/webcrypto/webcrypto_util.h" +#include "crypto/nss_util.h" +#include "crypto/scoped_nss_types.h" +#include "crypto/secure_util.h" +#include "third_party/WebKit/public/platform/WebArrayBuffer.h" +#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" +#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" + +namespace content { + +namespace { + +class SymKeyHandle : public blink::WebCryptoKeyHandle { + public: + explicit SymKeyHandle(crypto::ScopedPK11SymKey key) : key_(key.Pass()) {} + + PK11SymKey* key() { return key_.get(); } + + private: + crypto::ScopedPK11SymKey key_; + + DISALLOW_COPY_AND_ASSIGN(SymKeyHandle); +}; + +class PublicKeyHandle : public blink::WebCryptoKeyHandle { + public: + explicit PublicKeyHandle(crypto::ScopedSECKEYPublicKey key) + : key_(key.Pass()) {} + + SECKEYPublicKey* key() { return key_.get(); } + + private: + crypto::ScopedSECKEYPublicKey key_; + + DISALLOW_COPY_AND_ASSIGN(PublicKeyHandle); +}; + +class PrivateKeyHandle : public blink::WebCryptoKeyHandle { + public: + explicit PrivateKeyHandle(crypto::ScopedSECKEYPrivateKey key) + : key_(key.Pass()) {} + + SECKEYPrivateKey* key() { return key_.get(); } + + private: + crypto::ScopedSECKEYPrivateKey key_; + + DISALLOW_COPY_AND_ASSIGN(PrivateKeyHandle); +}; + +HASH_HashType WebCryptoAlgorithmToNSSHashType( + const blink::WebCryptoAlgorithm& algorithm) { + switch (algorithm.id()) { + case blink::WebCryptoAlgorithmIdSha1: + return HASH_AlgSHA1; + case blink::WebCryptoAlgorithmIdSha224: + return HASH_AlgSHA224; + case blink::WebCryptoAlgorithmIdSha256: + return HASH_AlgSHA256; + case blink::WebCryptoAlgorithmIdSha384: + return HASH_AlgSHA384; + case blink::WebCryptoAlgorithmIdSha512: + return HASH_AlgSHA512; + default: + // Not a digest algorithm. + return HASH_AlgNULL; + } +} + +CK_MECHANISM_TYPE WebCryptoAlgorithmToHMACMechanism( + const blink::WebCryptoAlgorithm& algorithm) { + switch (algorithm.id()) { + case blink::WebCryptoAlgorithmIdSha1: + return CKM_SHA_1_HMAC; + case blink::WebCryptoAlgorithmIdSha256: + return CKM_SHA256_HMAC; + default: + // Not a supported algorithm. + return CKM_INVALID_MECHANISM; + } +} + +bool AesCbcEncryptDecrypt( + CK_ATTRIBUTE_TYPE operation, + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebArrayBuffer* buffer) { + DCHECK_EQ(blink::WebCryptoAlgorithmIdAesCbc, algorithm.id()); + DCHECK_EQ(algorithm.id(), key.algorithm().id()); + DCHECK_EQ(blink::WebCryptoKeyTypeSecret, key.type()); + DCHECK(operation == CKA_ENCRYPT || operation == CKA_DECRYPT); + + SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); + + const blink::WebCryptoAesCbcParams* params = algorithm.aesCbcParams(); + if (params->iv().size() != AES_BLOCK_SIZE) + return false; + + SECItem iv_item; + iv_item.type = siBuffer; + iv_item.data = const_cast<unsigned char*>(params->iv().data()); + iv_item.len = params->iv().size(); + + crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); + if (!param) + return false; + + crypto::ScopedPK11Context context(PK11_CreateContextBySymKey( + CKM_AES_CBC_PAD, operation, sym_key->key(), param.get())); + + if (!context.get()) + return false; + + // Oddly PK11_CipherOp takes input and output lengths as "int" rather than + // "unsigned". Do some checks now to avoid integer overflowing. + if (data_size >= INT_MAX - AES_BLOCK_SIZE) { + // TODO(eroman): Handle this by chunking the input fed into NSS. Right now + // it doesn't make much difference since the one-shot API would end up + // blowing out the memory and crashing anyway. However a newer version of + // the spec allows for a sequence<CryptoData> so this will be relevant. + return false; + } + + // PK11_CipherOp does an invalid memory access when given empty decryption + // input, or input which is not a multiple of the block size. See also + // https://bugzilla.mozilla.com/show_bug.cgi?id=921687. + if (operation == CKA_DECRYPT && + (data_size == 0 || (data_size % AES_BLOCK_SIZE != 0))) { + return false; + } + + // TODO(eroman): Refine the output buffer size. It can be computed exactly for + // encryption, and can be smaller for decryption. + unsigned output_max_len = data_size + AES_BLOCK_SIZE; + CHECK_GT(output_max_len, data_size); + + *buffer = blink::WebArrayBuffer::create(output_max_len, 1); + + unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); + + int output_len; + if (SECSuccess != PK11_CipherOp(context.get(), + buffer_data, + &output_len, + buffer->byteLength(), + data, + data_size)) { + return false; + } + + unsigned int final_output_chunk_len; + if (SECSuccess != PK11_DigestFinal(context.get(), + buffer_data + output_len, + &final_output_chunk_len, + output_max_len - output_len)) { + return false; + } + + webcrypto::ShrinkBuffer(buffer, final_output_chunk_len + output_len); + return true; +} + +CK_MECHANISM_TYPE HmacAlgorithmToGenMechanism( + const blink::WebCryptoAlgorithm& algorithm) { + DCHECK_EQ(algorithm.id(), blink::WebCryptoAlgorithmIdHmac); + const blink::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams(); + DCHECK(params); + switch (params->hash().id()) { + case blink::WebCryptoAlgorithmIdSha1: + return CKM_SHA_1_HMAC; + case blink::WebCryptoAlgorithmIdSha256: + return CKM_SHA256_HMAC; + default: + return CKM_INVALID_MECHANISM; + } +} + +CK_MECHANISM_TYPE WebCryptoAlgorithmToGenMechanism( + const blink::WebCryptoAlgorithm& algorithm) { + switch (algorithm.id()) { + case blink::WebCryptoAlgorithmIdAesCbc: + return CKM_AES_KEY_GEN; + case blink::WebCryptoAlgorithmIdHmac: + return HmacAlgorithmToGenMechanism(algorithm); + default: + return CKM_INVALID_MECHANISM; + } +} + +unsigned int WebCryptoHmacAlgorithmToBlockSize( + const blink::WebCryptoAlgorithm& algorithm) { + DCHECK_EQ(algorithm.id(), blink::WebCryptoAlgorithmIdHmac); + const blink::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams(); + DCHECK(params); + switch (params->hash().id()) { + case blink::WebCryptoAlgorithmIdSha1: + return 512; + case blink::WebCryptoAlgorithmIdSha256: + return 512; + default: + return 0; + } +} + +// Converts a (big-endian) WebCrypto BigInteger, with or without leading zeros, +// to unsigned long. +bool BigIntegerToLong(const uint8* data, + unsigned data_size, + unsigned long* result) { + // TODO(padolph): Is it correct to say that empty data is an error, or does it + // mean value 0? See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23655 + if (data_size == 0) + return false; + + *result = 0; + for (size_t i = 0; i < data_size; ++i) { + size_t reverse_i = data_size - i - 1; + + if (reverse_i >= sizeof(unsigned long) && data[i]) + return false; // Too large for a long. + + *result |= data[i] << 8 * reverse_i; + } + return true; +} + +bool IsAlgorithmRsa(const blink::WebCryptoAlgorithm& algorithm) { + return algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || + algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep || + algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; +} + +bool ImportKeyInternalRaw( + const unsigned char* key_data, + unsigned key_data_size, + const blink::WebCryptoAlgorithm& algorithm, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* key) { + + DCHECK(!algorithm.isNull()); + + blink::WebCryptoKeyType type; + switch (algorithm.id()) { + case blink::WebCryptoAlgorithmIdHmac: + case blink::WebCryptoAlgorithmIdAesCbc: + type = blink::WebCryptoKeyTypeSecret; + break; + // TODO(bryaneyler): Support more key types. + default: + return false; + } + + // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys. + // Currently only supporting symmetric. + CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; + // Flags are verified at the Blink layer; here the flags are set to all + // possible operations for this key type. + CK_FLAGS flags = 0; + + switch (algorithm.id()) { + case blink::WebCryptoAlgorithmIdHmac: { + const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); + if (!params) { + return false; + } + + mechanism = WebCryptoAlgorithmToHMACMechanism(params->hash()); + if (mechanism == CKM_INVALID_MECHANISM) { + return false; + } + + flags |= CKF_SIGN | CKF_VERIFY; + + break; + } + case blink::WebCryptoAlgorithmIdAesCbc: { + mechanism = CKM_AES_CBC; + flags |= CKF_ENCRYPT | CKF_DECRYPT; + break; + } + default: + return false; + } + + DCHECK_NE(CKM_INVALID_MECHANISM, mechanism); + DCHECK_NE(0ul, flags); + + SECItem key_item = { + siBuffer, + const_cast<unsigned char*>(key_data), + key_data_size + }; + + crypto::ScopedPK11SymKey pk11_sym_key( + PK11_ImportSymKeyWithFlags(PK11_GetInternalSlot(), + mechanism, + PK11_OriginUnwrap, + CKA_FLAGS_ONLY, + &key_item, + flags, + false, + NULL)); + if (!pk11_sym_key.get()) { + return false; + } + + *key = blink::WebCryptoKey::create(new SymKeyHandle(pk11_sym_key.Pass()), + type, extractable, algorithm, usage_mask); + return true; +} + +bool ExportKeyInternalRaw( + const blink::WebCryptoKey& key, + blink::WebArrayBuffer* buffer) { + + DCHECK(key.handle()); + DCHECK(buffer); + + if (key.type() != blink::WebCryptoKeyTypeSecret || !key.extractable()) + return false; + + SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); + + if (PK11_ExtractKeyValue(sym_key->key()) != SECSuccess) + return false; + + const SECItem* key_data = PK11_GetKeyData(sym_key->key()); + if (!key_data) + return false; + + *buffer = webcrypto::CreateArrayBuffer(key_data->data, key_data->len); + + return true; +} + +typedef scoped_ptr<CERTSubjectPublicKeyInfo, + crypto::NSSDestroyer<CERTSubjectPublicKeyInfo, + SECKEY_DestroySubjectPublicKeyInfo> > + ScopedCERTSubjectPublicKeyInfo; + +// Validates an NSS KeyType against a WebCrypto algorithm. Some NSS KeyTypes +// contain enough information to fabricate a Web Crypto algorithm, which is +// returned if the input algorithm isNull(). This function indicates failure by +// returning a Null algorithm. +blink::WebCryptoAlgorithm ResolveNssKeyTypeWithInputAlgorithm( + KeyType key_type, + const blink::WebCryptoAlgorithm& algorithm_or_null) { + switch (key_type) { + case rsaKey: + // NSS's rsaKey KeyType maps to keys with SEC_OID_PKCS1_RSA_ENCRYPTION and + // according to RFCs 4055/5756 this can be used for both encryption and + // signatures. However, this is not specific enough to build a compatible + // Web Crypto algorithm, since in Web Crypto, RSA encryption and signature + // algorithms are distinct. So if the input algorithm isNull() here, we + // have to fail. + if (!algorithm_or_null.isNull() && IsAlgorithmRsa(algorithm_or_null)) + return algorithm_or_null; + break; + case dsaKey: + case ecKey: + case rsaPssKey: + case rsaOaepKey: + // TODO(padolph): Handle other key types. + break; + default: + break; + } + return blink::WebCryptoAlgorithm::createNull(); +} + +bool ImportKeyInternalSpki( + const unsigned char* key_data, + unsigned key_data_size, + const blink::WebCryptoAlgorithm& algorithm_or_null, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* key) { + + DCHECK(key); + + if (!key_data_size) + return false; + DCHECK(key_data); + + // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject + // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. + SECItem spki_item = {siBuffer, const_cast<uint8*>(key_data), key_data_size}; + const ScopedCERTSubjectPublicKeyInfo spki( + SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); + if (!spki) + return false; + + crypto::ScopedSECKEYPublicKey sec_public_key( + SECKEY_ExtractPublicKey(spki.get())); + if (!sec_public_key) + return false; + + const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); + blink::WebCryptoAlgorithm algorithm = + ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); + if (algorithm.isNull()) + return false; + + *key = blink::WebCryptoKey::create( + new PublicKeyHandle(sec_public_key.Pass()), + blink::WebCryptoKeyTypePublic, + extractable, + algorithm, + usage_mask); + + return true; +} + +bool ExportKeyInternalSpki( + const blink::WebCryptoKey& key, + blink::WebArrayBuffer* buffer) { + + DCHECK(key.handle()); + DCHECK(buffer); + + if (key.type() != blink::WebCryptoKeyTypePublic || !key.extractable()) + return false; + + PublicKeyHandle* const pub_key = + reinterpret_cast<PublicKeyHandle*>(key.handle()); + + const crypto::ScopedSECItem spki_der( + SECKEY_EncodeDERSubjectPublicKeyInfo(pub_key->key())); + if (!spki_der) + return false; + + DCHECK(spki_der->data); + DCHECK(spki_der->len); + + *buffer = webcrypto::CreateArrayBuffer(spki_der->data, spki_der->len); + + return true; +} + +bool ImportKeyInternalPkcs8( + const unsigned char* key_data, + unsigned key_data_size, + const blink::WebCryptoAlgorithm& algorithm_or_null, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* key) { + + DCHECK(key); + + if (!key_data_size) + return false; + DCHECK(key_data); + + // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8 + // private key info object. + SECItem pki_der = {siBuffer, const_cast<uint8*>(key_data), key_data_size}; + + SECKEYPrivateKey* seckey_private_key = NULL; + if (PK11_ImportDERPrivateKeyInfoAndReturnKey( + PK11_GetInternalSlot(), + &pki_der, + NULL, // nickname + NULL, // publicValue + false, // isPerm + false, // isPrivate + KU_ALL, // usage + &seckey_private_key, + NULL) != SECSuccess) { + return false; + } + DCHECK(seckey_private_key); + crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); + + const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); + blink::WebCryptoAlgorithm algorithm = + ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null); + if (algorithm.isNull()) + return false; + + *key = blink::WebCryptoKey::create( + new PrivateKeyHandle(private_key.Pass()), + blink::WebCryptoKeyTypePrivate, + extractable, + algorithm, + usage_mask); + + return true; +} + +} // namespace + +void WebCryptoImpl::Init() { + crypto::EnsureNSSInit(); +} + +bool WebCryptoImpl::EncryptInternal( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebArrayBuffer* buffer) { + + DCHECK_EQ(algorithm.id(), key.algorithm().id()); + DCHECK(key.handle()); + DCHECK(buffer); + + if (algorithm.id() == blink::WebCryptoAlgorithmIdAesCbc) { + return AesCbcEncryptDecrypt( + CKA_ENCRYPT, algorithm, key, data, data_size, buffer); + } else if (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5) { + + // RSAES encryption does not support empty input + if (!data_size) + return false; + DCHECK(data); + + if (key.type() != blink::WebCryptoKeyTypePublic) + return false; + + PublicKeyHandle* const public_key = + reinterpret_cast<PublicKeyHandle*>(key.handle()); + + const unsigned encrypted_length_bytes = + SECKEY_PublicKeyStrength(public_key->key()); + + // RSAES can operate on messages up to a length of k - 11, where k is the + // octet length of the RSA modulus. + if (encrypted_length_bytes < 11 || encrypted_length_bytes - 11 < data_size) + return false; + + *buffer = blink::WebArrayBuffer::create(encrypted_length_bytes, 1); + unsigned char* const buffer_data = + reinterpret_cast<unsigned char*>(buffer->data()); + + if (PK11_PubEncryptPKCS1(public_key->key(), + buffer_data, + const_cast<unsigned char*>(data), + data_size, + NULL) != SECSuccess) { + return false; + } + return true; + } + + return false; +} + +bool WebCryptoImpl::DecryptInternal( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebArrayBuffer* buffer) { + + DCHECK_EQ(algorithm.id(), key.algorithm().id()); + DCHECK(key.handle()); + DCHECK(buffer); + + if (algorithm.id() == blink::WebCryptoAlgorithmIdAesCbc) { + return AesCbcEncryptDecrypt( + CKA_DECRYPT, algorithm, key, data, data_size, buffer); + } else if (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5) { + + // RSAES decryption does not support empty input + if (!data_size) + return false; + DCHECK(data); + + if (key.type() != blink::WebCryptoKeyTypePrivate) + return false; + + PrivateKeyHandle* const private_key = + reinterpret_cast<PrivateKeyHandle*>(key.handle()); + + const int modulus_length_bytes = + PK11_GetPrivateModulusLen(private_key->key()); + if (modulus_length_bytes <= 0) + return false; + const unsigned max_output_length_bytes = modulus_length_bytes; + + *buffer = blink::WebArrayBuffer::create(max_output_length_bytes, 1); + unsigned char* const buffer_data = + reinterpret_cast<unsigned char*>(buffer->data()); + + unsigned output_length_bytes = 0; + if (PK11_PrivDecryptPKCS1(private_key->key(), + buffer_data, + &output_length_bytes, + max_output_length_bytes, + const_cast<unsigned char*>(data), + data_size) != SECSuccess) { + return false; + } + DCHECK_LE(output_length_bytes, max_output_length_bytes); + webcrypto::ShrinkBuffer(buffer, output_length_bytes); + return true; + } + + return false; +} + +bool WebCryptoImpl::DigestInternal( + const blink::WebCryptoAlgorithm& algorithm, + const unsigned char* data, + unsigned data_size, + blink::WebArrayBuffer* buffer) { + HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); + if (hash_type == HASH_AlgNULL) { + return false; + } + + HASHContext* context = HASH_Create(hash_type); + if (!context) { + return false; + } + + HASH_Begin(context); + + HASH_Update(context, data, data_size); + + unsigned hash_result_length = HASH_ResultLenContext(context); + DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX)); + + *buffer = blink::WebArrayBuffer::create(hash_result_length, 1); + + unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data()); + + unsigned result_length = 0; + HASH_End(context, digest, &result_length, hash_result_length); + + HASH_Destroy(context); + + return result_length == hash_result_length; +} + +bool WebCryptoImpl::GenerateKeyInternal( + const blink::WebCryptoAlgorithm& algorithm, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* key) { + + CK_MECHANISM_TYPE mech = WebCryptoAlgorithmToGenMechanism(algorithm); + unsigned int keylen_bytes = 0; + blink::WebCryptoKeyType key_type = blink::WebCryptoKeyTypeSecret; + + if (mech == CKM_INVALID_MECHANISM) { + return false; + } + + switch (algorithm.id()) { + case blink::WebCryptoAlgorithmIdAesCbc: { + const blink::WebCryptoAesKeyGenParams* params = + algorithm.aesKeyGenParams(); + DCHECK(params); + keylen_bytes = params->length() / 8; + if (params->length() % 8) + return false; + key_type = blink::WebCryptoKeyTypeSecret; + break; + } + case blink::WebCryptoAlgorithmIdHmac: { + const blink::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams(); + DCHECK(params); + if (!params->getLength(keylen_bytes)) { + keylen_bytes = WebCryptoHmacAlgorithmToBlockSize(algorithm) / 8; + } + + key_type = blink::WebCryptoKeyTypeSecret; + break; + } + + default: { + return false; + } + } + + if (keylen_bytes == 0) { + return false; + } + + crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); + if (!slot) { + return false; + } + + crypto::ScopedPK11SymKey pk11_key( + PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL)); + + if (!pk11_key) { + return false; + } + + *key = blink::WebCryptoKey::create( + new SymKeyHandle(pk11_key.Pass()), + key_type, extractable, algorithm, usage_mask); + return true; +} + +bool WebCryptoImpl::GenerateKeyPairInternal( + const blink::WebCryptoAlgorithm& algorithm, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* public_key, + blink::WebCryptoKey* private_key) { + + // TODO(padolph): Handle other asymmetric algorithm key generation. + switch (algorithm.id()) { + case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: + case blink::WebCryptoAlgorithmIdRsaOaep: + case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: { + const blink::WebCryptoRsaKeyGenParams* const params = + algorithm.rsaKeyGenParams(); + DCHECK(params); + + crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); + unsigned long public_exponent; + if (!slot || !params->modulusLength() || + !BigIntegerToLong(params->publicExponent().data(), + params->publicExponent().size(), + &public_exponent) || + !public_exponent) { + return false; + } + + PK11RSAGenParams rsa_gen_params; + rsa_gen_params.keySizeInBits = params->modulusLength(); + rsa_gen_params.pe = public_exponent; + + // Flags are verified at the Blink layer; here the flags are set to all + // possible operations for the given key type. + CK_FLAGS operation_flags; + switch (algorithm.id()) { + case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: + case blink::WebCryptoAlgorithmIdRsaOaep: + operation_flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP; + break; + case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: + operation_flags = CKF_SIGN | CKF_VERIFY; + break; + default: + NOTREACHED(); + return false; + } + const CK_FLAGS operation_flags_mask = CKF_ENCRYPT | CKF_DECRYPT | + CKF_SIGN | CKF_VERIFY | CKF_WRAP | + CKF_UNWRAP; + const PK11AttrFlags attribute_flags = 0; // Default all PK11_ATTR_ flags. + + // Note: NSS does not generate an sec_public_key if the call below fails, + // so there is no danger of a leaked sec_public_key. + SECKEYPublicKey* sec_public_key; + crypto::ScopedSECKEYPrivateKey scoped_sec_private_key( + PK11_GenerateKeyPairWithOpFlags(slot.get(), + CKM_RSA_PKCS_KEY_PAIR_GEN, + &rsa_gen_params, + &sec_public_key, + attribute_flags, + operation_flags, + operation_flags_mask, + NULL)); + if (!private_key) { + return false; + } + + *public_key = blink::WebCryptoKey::create( + new PublicKeyHandle(crypto::ScopedSECKEYPublicKey(sec_public_key)), + blink::WebCryptoKeyTypePublic, + true, + algorithm, + usage_mask); + *private_key = blink::WebCryptoKey::create( + new PrivateKeyHandle(scoped_sec_private_key.Pass()), + blink::WebCryptoKeyTypePrivate, + extractable, + algorithm, + usage_mask); + + return true; + } + default: + return false; + } +} + +bool WebCryptoImpl::ImportKeyInternal( + blink::WebCryptoKeyFormat format, + const unsigned char* key_data, + unsigned key_data_size, + const blink::WebCryptoAlgorithm& algorithm_or_null, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* key) { + + switch (format) { + case blink::WebCryptoKeyFormatRaw: + // A 'raw'-formatted key import requires an input algorithm. + if (algorithm_or_null.isNull()) + return false; + return ImportKeyInternalRaw(key_data, + key_data_size, + algorithm_or_null, + extractable, + usage_mask, + key); + case blink::WebCryptoKeyFormatSpki: + return ImportKeyInternalSpki(key_data, + key_data_size, + algorithm_or_null, + extractable, + usage_mask, + key); + case blink::WebCryptoKeyFormatPkcs8: + return ImportKeyInternalPkcs8(key_data, + key_data_size, + algorithm_or_null, + extractable, + usage_mask, + key); + default: + // NOTE: blink::WebCryptoKeyFormatJwk is handled one level above. + return false; + } +} + +bool WebCryptoImpl::ExportKeyInternal( + blink::WebCryptoKeyFormat format, + const blink::WebCryptoKey& key, + blink::WebArrayBuffer* buffer) { + switch (format) { + case blink::WebCryptoKeyFormatRaw: + return ExportKeyInternalRaw(key, buffer); + case blink::WebCryptoKeyFormatSpki: + return ExportKeyInternalSpki(key, buffer); + case blink::WebCryptoKeyFormatPkcs8: + // TODO(padolph): Implement pkcs8 export + return false; + default: + return false; + } +} + +bool WebCryptoImpl::SignInternal( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebArrayBuffer* buffer) { + blink::WebArrayBuffer result; + + switch (algorithm.id()) { + case blink::WebCryptoAlgorithmIdHmac: { + const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); + if (!params) { + return false; + } + + SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); + + DCHECK_EQ(PK11_GetMechanism(sym_key->key()), + WebCryptoAlgorithmToHMACMechanism(params->hash())); + DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign); + + SECItem param_item = { siBuffer, NULL, 0 }; + SECItem data_item = { + siBuffer, + const_cast<unsigned char*>(data), + data_size + }; + // First call is to figure out the length. + SECItem signature_item = { siBuffer, NULL, 0 }; + + if (PK11_SignWithSymKey(sym_key->key(), + PK11_GetMechanism(sym_key->key()), + ¶m_item, + &signature_item, + &data_item) != SECSuccess) { + NOTREACHED(); + return false; + } + + DCHECK_NE(0u, signature_item.len); + + result = blink::WebArrayBuffer::create(signature_item.len, 1); + signature_item.data = reinterpret_cast<unsigned char*>(result.data()); + + if (PK11_SignWithSymKey(sym_key->key(), + PK11_GetMechanism(sym_key->key()), + ¶m_item, + &signature_item, + &data_item) != SECSuccess) { + NOTREACHED(); + return false; + } + + DCHECK_EQ(result.byteLength(), signature_item.len); + + break; + } + default: + return false; + } + + *buffer = result; + return true; +} + +bool WebCryptoImpl::VerifySignatureInternal( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* signature, + unsigned signature_size, + const unsigned char* data, + unsigned data_size, + bool* signature_match) { + switch (algorithm.id()) { + case blink::WebCryptoAlgorithmIdHmac: { + blink::WebArrayBuffer result; + if (!SignInternal(algorithm, key, data, data_size, &result)) { + return false; + } + + // Handling of truncated signatures is underspecified in the WebCrypto + // spec, so here we fail verification if a truncated signature is being + // verified. + // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 + *signature_match = + result.byteLength() == signature_size && + crypto::SecureMemEqual(result.data(), signature, signature_size); + + break; + } + default: + return false; + } + + return true; +} + +bool WebCryptoImpl::ImportRsaPublicKeyInternal( + const unsigned char* modulus_data, + unsigned modulus_size, + const unsigned char* exponent_data, + unsigned exponent_size, + const blink::WebCryptoAlgorithm& algorithm, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* key) { + + if (!modulus_size || !exponent_size) + return false; + DCHECK(modulus_data); + DCHECK(exponent_data); + + // NSS does not provide a way to create an RSA public key directly from the + // modulus and exponent values, but it can import an DER-encoded ASN.1 blob + // with these values and create the public key from that. The code below + // follows the recommendation described in + // https://developer.mozilla.org/en-US/docs/NSS/NSS_Tech_Notes/nss_tech_note7 + + // Pack the input values into a struct compatible with NSS ASN.1 encoding, and + // set up an ASN.1 encoder template for it. + struct RsaPublicKeyData { + SECItem modulus; + SECItem exponent; + }; + const RsaPublicKeyData pubkey_in = { + {siUnsignedInteger, const_cast<unsigned char*>(modulus_data), + modulus_size}, + {siUnsignedInteger, const_cast<unsigned char*>(exponent_data), + exponent_size}}; + const SEC_ASN1Template rsa_public_key_template[] = { + {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RsaPublicKeyData)}, + {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, modulus), }, + {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, exponent), }, + {0, }}; + + // DER-encode the public key. + crypto::ScopedSECItem pubkey_der(SEC_ASN1EncodeItem( + NULL, NULL, &pubkey_in, rsa_public_key_template)); + if (!pubkey_der) + return false; + + // Import the DER-encoded public key to create an RSA SECKEYPublicKey. + crypto::ScopedSECKEYPublicKey pubkey( + SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA)); + if (!pubkey) + return false; + + *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()), + blink::WebCryptoKeyTypePublic, + extractable, + algorithm, + usage_mask); + return true; +} + +} // namespace content diff --git a/chromium/content/renderer/webcrypto/webcrypto_impl_openssl.cc b/chromium/content/renderer/webcrypto/webcrypto_impl_openssl.cc new file mode 100644 index 00000000000..9faf51da7be --- /dev/null +++ b/chromium/content/renderer/webcrypto/webcrypto_impl_openssl.cc @@ -0,0 +1,539 @@ +// 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/renderer/webcrypto/webcrypto_impl.h" + +#include <vector> +#include <openssl/aes.h> +#include <openssl/evp.h> +#include <openssl/hmac.h> +#include <openssl/sha.h> +#include <openssl/evp.h> +#include <openssl/rand.h> + +#include "base/logging.h" +#include "content/renderer/webcrypto/webcrypto_util.h" +#include "crypto/openssl_util.h" +#include "crypto/secure_util.h" +#include "third_party/WebKit/public/platform/WebArrayBuffer.h" +#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" +#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" + +namespace content { + +namespace { + +class SymKeyHandle : public blink::WebCryptoKeyHandle { + public: + SymKeyHandle(const unsigned char* key_data, unsigned key_data_size) + : key_(key_data, key_data + key_data_size) {} + + const std::vector<unsigned char>& key() const { return key_; } + + private: + const std::vector<unsigned char> key_; + + DISALLOW_COPY_AND_ASSIGN(SymKeyHandle); +}; + +const EVP_CIPHER* GetAESCipherByKeyLength(unsigned key_length_bytes) { + // OpenSSL supports AES CBC ciphers for only 3 key lengths: 128, 192, 256 bits + switch (key_length_bytes) { + case 16: + return EVP_aes_128_cbc(); + case 24: + return EVP_aes_192_cbc(); + case 32: + return EVP_aes_256_cbc(); + default: + return NULL; + } +} + +unsigned WebCryptoHmacParamsToBlockSize( + const blink::WebCryptoHmacKeyParams* params) { + DCHECK(params); + switch (params->hash().id()) { + case blink::WebCryptoAlgorithmIdSha1: + return SHA_DIGEST_LENGTH / 8; + case blink::WebCryptoAlgorithmIdSha224: + return SHA224_DIGEST_LENGTH / 8; + case blink::WebCryptoAlgorithmIdSha256: + return SHA256_DIGEST_LENGTH / 8; + case blink::WebCryptoAlgorithmIdSha384: + return SHA384_DIGEST_LENGTH / 8; + case blink::WebCryptoAlgorithmIdSha512: + return SHA512_DIGEST_LENGTH / 8; + default: + return 0; + } +} + +// OpenSSL constants for EVP_CipherInit_ex(), do not change +enum CipherOperation { + kDoDecrypt = 0, + kDoEncrypt = 1 +}; + +bool AesCbcEncryptDecrypt(CipherOperation cipher_operation, + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebArrayBuffer* buffer) { + + // TODO(padolph): Handle other encrypt operations and then remove this gate + if (algorithm.id() != blink::WebCryptoAlgorithmIdAesCbc) + return false; + + DCHECK_EQ(algorithm.id(), key.algorithm().id()); + DCHECK_EQ(blink::WebCryptoKeyTypeSecret, key.type()); + + if (data_size >= INT_MAX - AES_BLOCK_SIZE) { + // TODO(padolph): Handle this by chunking the input fed into OpenSSL. Right + // now it doesn't make much difference since the one-shot API would end up + // blowing out the memory and crashing anyway. However a newer version of + // the spec allows for a sequence<CryptoData> so this will be relevant. + return false; + } + + // Note: PKCS padding is enabled by default + crypto::ScopedOpenSSL<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free> context( + EVP_CIPHER_CTX_new()); + + if (!context.get()) + return false; + + SymKeyHandle* const sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); + + const EVP_CIPHER* const cipher = + GetAESCipherByKeyLength(sym_key->key().size()); + DCHECK(cipher); + + const blink::WebCryptoAesCbcParams* const params = algorithm.aesCbcParams(); + if (params->iv().size() != AES_BLOCK_SIZE) + return false; + + if (!EVP_CipherInit_ex(context.get(), + cipher, + NULL, + &sym_key->key()[0], + params->iv().data(), + cipher_operation)) { + return false; + } + + // According to the openssl docs, the amount of data written may be as large + // as (data_size + cipher_block_size - 1), constrained to a multiple of + // cipher_block_size. + unsigned output_max_len = data_size + AES_BLOCK_SIZE - 1; + const unsigned remainder = output_max_len % AES_BLOCK_SIZE; + if (remainder != 0) + output_max_len += AES_BLOCK_SIZE - remainder; + DCHECK_GT(output_max_len, data_size); + + *buffer = blink::WebArrayBuffer::create(output_max_len, 1); + + unsigned char* const buffer_data = + reinterpret_cast<unsigned char*>(buffer->data()); + + int output_len = 0; + if (!EVP_CipherUpdate( + context.get(), buffer_data, &output_len, data, data_size)) + return false; + int final_output_chunk_len = 0; + if (!EVP_CipherFinal_ex( + context.get(), buffer_data + output_len, &final_output_chunk_len)) + return false; + + const unsigned final_output_len = + static_cast<unsigned>(output_len) + + static_cast<unsigned>(final_output_chunk_len); + DCHECK_LE(final_output_len, output_max_len); + + webcrypto::ShrinkBuffer(buffer, final_output_len); + + return true; +} + +bool ExportKeyInternalRaw( + const blink::WebCryptoKey& key, + blink::WebArrayBuffer* buffer) { + + DCHECK(key.handle()); + DCHECK(buffer); + + if (key.type() != blink::WebCryptoKeyTypeSecret || !key.extractable()) + return false; + + const SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); + + *buffer = webcrypto::CreateArrayBuffer( + webcrypto::Uint8VectorStart(sym_key->key()), sym_key->key().size()); + + return true; +} + +} // namespace + +void WebCryptoImpl::Init() { crypto::EnsureOpenSSLInit(); } + +bool WebCryptoImpl::EncryptInternal(const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebArrayBuffer* buffer) { + if (algorithm.id() == blink::WebCryptoAlgorithmIdAesCbc) { + return AesCbcEncryptDecrypt( + kDoEncrypt, algorithm, key, data, data_size, buffer); + } + + return false; +} + +bool WebCryptoImpl::DecryptInternal(const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebArrayBuffer* buffer) { + if (algorithm.id() == blink::WebCryptoAlgorithmIdAesCbc) { + return AesCbcEncryptDecrypt( + kDoDecrypt, algorithm, key, data, data_size, buffer); + } + + return false; +} + +bool WebCryptoImpl::DigestInternal(const blink::WebCryptoAlgorithm& algorithm, + const unsigned char* data, + unsigned data_size, + blink::WebArrayBuffer* buffer) { + + crypto::OpenSSLErrStackTracer(FROM_HERE); + + const EVP_MD* digest_algorithm; + switch (algorithm.id()) { + case blink::WebCryptoAlgorithmIdSha1: + digest_algorithm = EVP_sha1(); + break; + case blink::WebCryptoAlgorithmIdSha224: + digest_algorithm = EVP_sha224(); + break; + case blink::WebCryptoAlgorithmIdSha256: + digest_algorithm = EVP_sha256(); + break; + case blink::WebCryptoAlgorithmIdSha384: + digest_algorithm = EVP_sha384(); + break; + case blink::WebCryptoAlgorithmIdSha512: + digest_algorithm = EVP_sha512(); + break; + default: + // Not a digest algorithm. + return false; + } + + crypto::ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_destroy> digest_context( + EVP_MD_CTX_create()); + if (!digest_context.get()) { + return false; + } + + if (!EVP_DigestInit_ex(digest_context.get(), digest_algorithm, NULL) || + !EVP_DigestUpdate(digest_context.get(), data, data_size)) { + return false; + } + + const int hash_expected_size = EVP_MD_CTX_size(digest_context.get()); + if (hash_expected_size <= 0) { + return false; + } + DCHECK_LE(hash_expected_size, EVP_MAX_MD_SIZE); + + *buffer = blink::WebArrayBuffer::create(hash_expected_size, 1); + unsigned char* const hash_buffer = + reinterpret_cast<unsigned char* const>(buffer->data()); + + unsigned hash_size = 0; + if (!EVP_DigestFinal_ex(digest_context.get(), hash_buffer, &hash_size) || + static_cast<int>(hash_size) != hash_expected_size) { + buffer->reset(); + return false; + } + + return true; +} + +bool WebCryptoImpl::GenerateKeyInternal( + const blink::WebCryptoAlgorithm& algorithm, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* key) { + + unsigned keylen_bytes = 0; + blink::WebCryptoKeyType key_type; + switch (algorithm.id()) { + case blink::WebCryptoAlgorithmIdAesCbc: { + const blink::WebCryptoAesKeyGenParams* params = + algorithm.aesKeyGenParams(); + DCHECK(params); + if (params->length() % 8) + return false; + keylen_bytes = params->length() / 8; + if (!GetAESCipherByKeyLength(keylen_bytes)) { + return false; + } + key_type = blink::WebCryptoKeyTypeSecret; + break; + } + case blink::WebCryptoAlgorithmIdHmac: { + const blink::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams(); + DCHECK(params); + if (!params->getLength(keylen_bytes)) { + keylen_bytes = WebCryptoHmacParamsToBlockSize(params); + } + key_type = blink::WebCryptoKeyTypeSecret; + break; + } + + default: { return false; } + } + + if (keylen_bytes == 0) { + return false; + } + + crypto::OpenSSLErrStackTracer(FROM_HERE); + + std::vector<unsigned char> random_bytes(keylen_bytes, 0); + if (!(RAND_bytes(&random_bytes[0], keylen_bytes))) { + return false; + } + + *key = blink::WebCryptoKey::create( + new SymKeyHandle(&random_bytes[0], random_bytes.size()), + key_type, extractable, algorithm, usage_mask); + + return true; +} + +bool WebCryptoImpl::GenerateKeyPairInternal( + const blink::WebCryptoAlgorithm& algorithm, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* public_key, + blink::WebCryptoKey* private_key) { + // TODO(padolph): Placeholder for OpenSSL implementation. + // Issue http://crbug.com/267888. + return false; +} + +bool WebCryptoImpl::ImportKeyInternal( + blink::WebCryptoKeyFormat format, + const unsigned char* key_data, + unsigned key_data_size, + const blink::WebCryptoAlgorithm& algorithm_or_null, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* key) { + // TODO(eroman): Currently expects algorithm to always be specified, as it is + // required for raw format. + if (algorithm_or_null.isNull()) + return false; + const blink::WebCryptoAlgorithm& algorithm = algorithm_or_null; + + // TODO(padolph): Support all relevant alg types and then remove this gate. + if (algorithm.id() != blink::WebCryptoAlgorithmIdHmac && + algorithm.id() != blink::WebCryptoAlgorithmIdAesCbc) { + return false; + } + + // TODO(padolph): Need to split handling for symmetric (raw format) and + // asymmetric (spki or pkcs8 format) keys. + // Currently only supporting symmetric. + + // Symmetric keys are always type secret + blink::WebCryptoKeyType type = blink::WebCryptoKeyTypeSecret; + + const unsigned char* raw_key_data; + unsigned raw_key_data_size; + switch (format) { + case blink::WebCryptoKeyFormatRaw: + raw_key_data = key_data; + raw_key_data_size = key_data_size; + // The NSS implementation fails when importing a raw AES key with a length + // incompatible with AES. The line below is to match this behavior. + if (algorithm.id() == blink::WebCryptoAlgorithmIdAesCbc && + !GetAESCipherByKeyLength(raw_key_data_size)) { + return false; + } + break; + case blink::WebCryptoKeyFormatJwk: + // TODO(padolph): Handle jwk format; need simple JSON parser. + // break; + return false; + default: + return false; + } + + *key = blink::WebCryptoKey::create( + new SymKeyHandle(raw_key_data, raw_key_data_size), + type, extractable, algorithm, usage_mask); + + return true; +} + +bool WebCryptoImpl::ExportKeyInternal( + blink::WebCryptoKeyFormat format, + const blink::WebCryptoKey& key, + blink::WebArrayBuffer* buffer) { + switch (format) { + case blink::WebCryptoKeyFormatRaw: + return ExportKeyInternalRaw(key, buffer); + case blink::WebCryptoKeyFormatSpki: + // TODO(padolph): Implement spki export + return false; + case blink::WebCryptoKeyFormatPkcs8: + // TODO(padolph): Implement pkcs8 export + return false; + default: + return false; + } + return false; +} + +bool WebCryptoImpl::SignInternal( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebArrayBuffer* buffer) { + + blink::WebArrayBuffer result; + + switch (algorithm.id()) { + case blink::WebCryptoAlgorithmIdHmac: { + + DCHECK_EQ(key.algorithm().id(), blink::WebCryptoAlgorithmIdHmac); + DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign); + + const blink::WebCryptoHmacParams* const params = algorithm.hmacParams(); + if (!params) + return false; + + const EVP_MD* evp_sha = 0; + unsigned int hmac_expected_length = 0; + // Note that HMAC length is determined by the hash used. + switch (params->hash().id()) { + case blink::WebCryptoAlgorithmIdSha1: + evp_sha = EVP_sha1(); + hmac_expected_length = SHA_DIGEST_LENGTH; + break; + case blink::WebCryptoAlgorithmIdSha224: + evp_sha = EVP_sha224(); + hmac_expected_length = SHA224_DIGEST_LENGTH; + break; + case blink::WebCryptoAlgorithmIdSha256: + evp_sha = EVP_sha256(); + hmac_expected_length = SHA256_DIGEST_LENGTH; + break; + case blink::WebCryptoAlgorithmIdSha384: + evp_sha = EVP_sha384(); + hmac_expected_length = SHA384_DIGEST_LENGTH; + break; + case blink::WebCryptoAlgorithmIdSha512: + evp_sha = EVP_sha512(); + hmac_expected_length = SHA512_DIGEST_LENGTH; + break; + default: + // Not a digest algorithm. + return false; + } + + SymKeyHandle* const sym_key = + reinterpret_cast<SymKeyHandle*>(key.handle()); + const std::vector<unsigned char>& raw_key = sym_key->key(); + + // OpenSSL wierdness here. + // First, HMAC() needs a void* for the key data, so make one up front as a + // cosmetic to avoid a cast. Second, OpenSSL does not like a NULL key, + // which will result if the raw_key vector is empty; an entirely valid + // case. Handle this specific case by pointing to an empty array. + const unsigned char null_key[] = {}; + const void* const raw_key_voidp = raw_key.size() ? &raw_key[0] : null_key; + + result = blink::WebArrayBuffer::create(hmac_expected_length, 1); + crypto::ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> hmac_result( + reinterpret_cast<unsigned char*>(result.data()), + hmac_expected_length); + + crypto::OpenSSLErrStackTracer(FROM_HERE); + + unsigned int hmac_actual_length; + unsigned char* const success = HMAC(evp_sha, + raw_key_voidp, + raw_key.size(), + data, + data_size, + hmac_result.safe_buffer(), + &hmac_actual_length); + if (!success || hmac_actual_length != hmac_expected_length) + return false; + + break; + } + default: + return false; + } + + *buffer = result; + return true; +} + +bool WebCryptoImpl::VerifySignatureInternal( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* signature, + unsigned signature_size, + const unsigned char* data, + unsigned data_size, + bool* signature_match) { + switch (algorithm.id()) { + case blink::WebCryptoAlgorithmIdHmac: { + blink::WebArrayBuffer result; + if (!SignInternal(algorithm, key, data, data_size, &result)) { + return false; + } + + // Handling of truncated signatures is underspecified in the WebCrypto + // spec, so here we fail verification if a truncated signature is being + // verified. + // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 + *signature_match = + result.byteLength() == signature_size && + crypto::SecureMemEqual(result.data(), signature, signature_size); + + break; + } + default: + return false; + } + return true; +} + +bool WebCryptoImpl::ImportRsaPublicKeyInternal( + const unsigned char* modulus_data, + unsigned modulus_size, + const unsigned char* exponent_data, + unsigned exponent_size, + const blink::WebCryptoAlgorithm& algorithm, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* key) { + // TODO(padolph): Placeholder for OpenSSL implementation. + // Issue http://crbug.com/267888. + return false; +} + +} // namespace content diff --git a/chromium/content/renderer/webcrypto/webcrypto_impl_unittest.cc b/chromium/content/renderer/webcrypto/webcrypto_impl_unittest.cc new file mode 100644 index 00000000000..8abe36fe443 --- /dev/null +++ b/chromium/content/renderer/webcrypto/webcrypto_impl_unittest.cc @@ -0,0 +1,1641 @@ +// 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/renderer/webcrypto/webcrypto_impl.h" + +#include <algorithm> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/json/json_writer.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/strings/string_number_conversions.h" +#include "content/public/renderer/content_renderer_client.h" +#include "content/renderer/renderer_webkitplatformsupport_impl.h" +#include "content/renderer/webcrypto/webcrypto_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/public/platform/WebArrayBuffer.h" +#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" +#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" +#include "third_party/WebKit/public/platform/WebCryptoKey.h" + +namespace content { + +namespace { + +std::vector<uint8> HexStringToBytes(const std::string& hex) { + std::vector<uint8> bytes; + base::HexStringToBytes(hex, &bytes); + return bytes; +} + +void ExpectArrayBufferMatchesHex(const std::string& expected_hex, + const blink::WebArrayBuffer& array_buffer) { + EXPECT_STRCASEEQ( + expected_hex.c_str(), + base::HexEncode(array_buffer.data(), array_buffer.byteLength()).c_str()); +} + +std::vector<uint8> MakeJsonVector(const std::string& json_string) { + return std::vector<uint8>(json_string.begin(), json_string.end()); +} + +std::vector<uint8> MakeJsonVector(const base::DictionaryValue& dict) { + std::string json; + base::JSONWriter::Write(&dict, &json); + return MakeJsonVector(json); +} + +// Helper for ImportJwkFailures and ImportJwkOctFailures. Restores the JWK JSON +// dictionary to a good state +void RestoreJwkOctDictionary(base::DictionaryValue* dict) { + dict->Clear(); + dict->SetString("kty", "oct"); + dict->SetString("alg", "A128CBC"); + dict->SetString("use", "enc"); + dict->SetBoolean("extractable", false); + dict->SetString("k", "GADWrMRHwQfoNaXU5fZvTg=="); +} + +#if !defined(USE_OPENSSL) + +// Helper for ImportJwkRsaFailures. Restores the JWK JSON +// dictionary to a good state +void RestoreJwkRsaDictionary(base::DictionaryValue* dict) { + dict->Clear(); + dict->SetString("kty", "RSA"); + dict->SetString("alg", "RSA1_5"); + dict->SetString("use", "enc"); + dict->SetBoolean("extractable", false); + dict->SetString("n", + "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk" + "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm" + "e7PUJHYW1PW6ENTP0ibeiNOfFvs"); + dict->SetString("e", "AQAB"); +} + +blink::WebCryptoAlgorithm CreateRsaKeyGenAlgorithm( + blink::WebCryptoAlgorithmId algorithm_id, + unsigned modulus_length, + const std::vector<uint8>& public_exponent) { + DCHECK(algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || + algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || + algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep); + return blink::WebCryptoAlgorithm::adoptParamsAndCreate( + algorithm_id, + new blink::WebCryptoRsaKeyGenParams( + modulus_length, + webcrypto::Uint8VectorStart(public_exponent), + public_exponent.size())); +} + +// Determines if two ArrayBuffers have identical content. +bool ArrayBuffersEqual( + const blink::WebArrayBuffer& a, + const blink::WebArrayBuffer& b) { + return a.byteLength() == b.byteLength() && + memcmp(a.data(), b.data(), a.byteLength()) == 0; +} + +// Given a vector of WebArrayBuffers, determines if there are any copies. +bool CopiesExist(std::vector<blink::WebArrayBuffer> bufs) { + for (size_t i = 0; i < bufs.size(); ++i) { + for (size_t j = i + 1; j < bufs.size(); ++j) { + if (ArrayBuffersEqual(bufs[i], bufs[j])) + return true; + } + } + return false; +} + +#endif // #if !defined(USE_OPENSSL) + +} // namespace + +class WebCryptoImplTest : public testing::Test { + protected: + blink::WebCryptoKey ImportSecretKeyFromRawHexString( + const std::string& key_hex, + const blink::WebCryptoAlgorithm& algorithm, + blink::WebCryptoKeyUsageMask usage) { + std::vector<uint8> key_raw = HexStringToBytes(key_hex); + + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + bool extractable = true; + EXPECT_TRUE(crypto_.ImportKeyInternal(blink::WebCryptoKeyFormatRaw, + webcrypto::Uint8VectorStart(key_raw), + key_raw.size(), + algorithm, + extractable, + usage, + &key)); + + EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); + EXPECT_FALSE(key.isNull()); + EXPECT_TRUE(key.handle()); + return key; + } + + // Forwarding methods to gain access to protected methods of + // WebCryptoImpl. + + bool DigestInternal( + const blink::WebCryptoAlgorithm& algorithm, + const std::vector<uint8>& data, + blink::WebArrayBuffer* buffer) { + return crypto_.DigestInternal( + algorithm, webcrypto::Uint8VectorStart(data), data.size(), buffer); + } + + bool GenerateKeyInternal( + const blink::WebCryptoAlgorithm& algorithm, + blink::WebCryptoKey* key) { + bool extractable = true; + blink::WebCryptoKeyUsageMask usage_mask = 0; + return crypto_.GenerateKeyInternal(algorithm, extractable, usage_mask, key); + } + + bool GenerateKeyPairInternal( + const blink::WebCryptoAlgorithm& algorithm, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* public_key, + blink::WebCryptoKey* private_key) { + return crypto_.GenerateKeyPairInternal( + algorithm, extractable, usage_mask, public_key, private_key); + } + + bool ImportKeyInternal( + blink::WebCryptoKeyFormat format, + const std::vector<uint8>& key_data, + const blink::WebCryptoAlgorithm& algorithm, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* key) { + return crypto_.ImportKeyInternal(format, + webcrypto::Uint8VectorStart(key_data), + key_data.size(), + algorithm, + extractable, + usage_mask, + key); + } + + bool ExportKeyInternal( + blink::WebCryptoKeyFormat format, + const blink::WebCryptoKey& key, + blink::WebArrayBuffer* buffer) { + return crypto_.ExportKeyInternal(format, key, buffer); + } + + bool SignInternal( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const std::vector<uint8>& data, + blink::WebArrayBuffer* buffer) { + return crypto_.SignInternal( + algorithm, key, webcrypto::Uint8VectorStart(data), data.size(), buffer); + } + + bool VerifySignatureInternal( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* signature, + unsigned signature_size, + const std::vector<uint8>& data, + bool* signature_match) { + return crypto_.VerifySignatureInternal(algorithm, + key, + signature, + signature_size, + webcrypto::Uint8VectorStart(data), + data.size(), + signature_match); + } + + bool EncryptInternal( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebArrayBuffer* buffer) { + return crypto_.EncryptInternal(algorithm, key, data, data_size, buffer); + } + + bool EncryptInternal( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const std::vector<uint8>& data, + blink::WebArrayBuffer* buffer) { + return crypto_.EncryptInternal( + algorithm, key, webcrypto::Uint8VectorStart(data), data.size(), buffer); + } + + bool DecryptInternal( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const unsigned char* data, + unsigned data_size, + blink::WebArrayBuffer* buffer) { + return crypto_.DecryptInternal(algorithm, key, data, data_size, buffer); + } + + bool DecryptInternal( + const blink::WebCryptoAlgorithm& algorithm, + const blink::WebCryptoKey& key, + const std::vector<uint8>& data, + blink::WebArrayBuffer* buffer) { + return crypto_.DecryptInternal( + algorithm, key, webcrypto::Uint8VectorStart(data), data.size(), buffer); + } + + bool ImportKeyJwk( + const std::vector<uint8>& key_data, + const blink::WebCryptoAlgorithm& algorithm, + bool extractable, + blink::WebCryptoKeyUsageMask usage_mask, + blink::WebCryptoKey* key) { + return crypto_.ImportKeyJwk(webcrypto::Uint8VectorStart(key_data), + key_data.size(), + algorithm, + extractable, + usage_mask, + key); + } + + private: + WebCryptoImpl crypto_; +}; + +TEST_F(WebCryptoImplTest, DigestSampleSets) { + // The results are stored here in hex format for readability. + // + // TODO(bryaneyler): Eventually, all these sample test sets should be replaced + // with the sets here: http://csrc.nist.gov/groups/STM/cavp/index.html#03 + // + // Results were generated using the command sha{1,224,256,384,512}sum. + struct TestCase { + blink::WebCryptoAlgorithmId algorithm; + const std::string hex_input; + const char* hex_result; + }; + + const TestCase kTests[] = { + { blink::WebCryptoAlgorithmIdSha1, "", + "da39a3ee5e6b4b0d3255bfef95601890afd80709" + }, + { blink::WebCryptoAlgorithmIdSha224, "", + "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f" + }, + { blink::WebCryptoAlgorithmIdSha256, "", + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { blink::WebCryptoAlgorithmIdSha384, "", + "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274e" + "debfe76f65fbd51ad2f14898b95b" + }, + { blink::WebCryptoAlgorithmIdSha512, "", + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0" + "d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", + }, + { blink::WebCryptoAlgorithmIdSha1, "00", + "5ba93c9db0cff93f52b521d7420e43f6eda2784f", + }, + { blink::WebCryptoAlgorithmIdSha224, "00", + "fff9292b4201617bdc4d3053fce02734166a683d7d858a7f5f59b073", + }, + { blink::WebCryptoAlgorithmIdSha256, "00", + "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", + }, + { blink::WebCryptoAlgorithmIdSha384, "00", + "bec021b4f368e3069134e012c2b4307083d3a9bdd206e24e5f0d86e13d6636655933" + "ec2b413465966817a9c208a11717", + }, + { blink::WebCryptoAlgorithmIdSha512, "00", + "b8244d028981d693af7b456af8efa4cad63d282e19ff14942c246e50d9351d22704a" + "802a71c3580b6370de4ceb293c324a8423342557d4e5c38438f0e36910ee", + }, + { blink::WebCryptoAlgorithmIdSha1, "000102030405", + "868460d98d09d8bbb93d7b6cdd15cc7fbec676b9", + }, + { blink::WebCryptoAlgorithmIdSha224, "000102030405", + "7d92e7f1cad1818ed1d13ab41f04ebabfe1fef6bb4cbeebac34c29bc", + }, + { blink::WebCryptoAlgorithmIdSha256, "000102030405", + "17e88db187afd62c16e5debf3e6527cd006bc012bc90b51a810cd80c2d511f43", + }, + { blink::WebCryptoAlgorithmIdSha384, "000102030405", + "79f4738706fce9650ac60266675c3cd07298b09923850d525604d040e6e448adc7dc" + "22780d7e1b95bfeaa86a678e4552", + }, + { blink::WebCryptoAlgorithmIdSha512, "000102030405", + "2f3831bccc94cf061bcfa5f8c23c1429d26e3bc6b76edad93d9025cb91c903af6cf9" + "c935dc37193c04c2c66e7d9de17c358284418218afea2160147aaa912f4c", + }, + }; + + for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests); + ++test_index) { + SCOPED_TRACE(test_index); + const TestCase& test = kTests[test_index]; + + blink::WebCryptoAlgorithm algorithm = + webcrypto::CreateAlgorithm(test.algorithm); + std::vector<uint8> input = HexStringToBytes(test.hex_input); + + blink::WebArrayBuffer output; + ASSERT_TRUE(DigestInternal(algorithm, input, &output)); + ExpectArrayBufferMatchesHex(test.hex_result, output); + } +} + +TEST_F(WebCryptoImplTest, HMACSampleSets) { + struct TestCase { + blink::WebCryptoAlgorithmId algorithm; + const char* key; + const char* message; + const char* mac; + }; + + const TestCase kTests[] = { + // Empty sets. Result generated via OpenSSL commandline tool. These + // particular results are also posted on the Wikipedia page examples: + // http://en.wikipedia.org/wiki/Hash-based_message_authentication_code + { + blink::WebCryptoAlgorithmIdSha1, + "", + "", + // openssl dgst -sha1 -hmac "" < /dev/null + "fbdb1d1b18aa6c08324b7d64b71fb76370690e1d", + }, + { + blink::WebCryptoAlgorithmIdSha256, + "", + "", + // openssl dgst -sha256 -hmac "" < /dev/null + "b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad", + }, + // For this data, see http://csrc.nist.gov/groups/STM/cavp/index.html#07 + // Download: + // http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip + // L=20 set 45 + { + blink::WebCryptoAlgorithmIdSha1, + // key + "59785928d72516e31272", + // message + "a3ce8899df1022e8d2d539b47bf0e309c66f84095e21438ec355bf119ce5fdcb4e73a6" + "19cdf36f25b369d8c38ff419997f0c59830108223606e31223483fd39edeaa4d3f0d21" + "198862d239c9fd26074130ff6c86493f5227ab895c8f244bd42c7afce5d147a20a5907" + "98c68e708e964902d124dadecdbda9dbd0051ed710e9bf", + // mac + "3c8162589aafaee024fc9a5ca50dd2336fe3eb28", + }, + // L=20 set 299 + { + blink::WebCryptoAlgorithmIdSha1, + // key + "ceb9aedf8d6efcf0ae52bea0fa99a9e26ae81bacea0cff4d5eecf201e3bca3c3577480" + "621b818fd717ba99d6ff958ea3d59b2527b019c343bb199e648090225867d994607962" + "f5866aa62930d75b58f6", + // message + "99958aa459604657c7bf6e4cdfcc8785f0abf06ffe636b5b64ecd931bd8a4563055924" + "21fc28dbcccb8a82acea2be8e54161d7a78e0399a6067ebaca3f2510274dc9f92f2c8a" + "e4265eec13d7d42e9f8612d7bc258f913ecb5a3a5c610339b49fb90e9037b02d684fc6" + "0da835657cb24eab352750c8b463b1a8494660d36c3ab2", + // mac + "4ac41ab89f625c60125ed65ffa958c6b490ea670", + }, + // L=32, set 30 + { + blink::WebCryptoAlgorithmIdSha256, + // key + "9779d9120642797f1747025d5b22b7ac607cab08e1758f2f3a46c8be1e25c53b8c6a8f" + "58ffefa176", + // message + "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a" + "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92" + "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f" + "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e", + // mac + "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b", + }, + // L=32, set 224 + { + blink::WebCryptoAlgorithmIdSha256, + // key + "4b7ab133efe99e02fc89a28409ee187d579e774f4cba6fc223e13504e3511bef8d4f63" + "8b9aca55d4a43b8fbd64cf9d74dcc8c9e8d52034898c70264ea911a3fd70813fa73b08" + "3371289b", + // message + "138efc832c64513d11b9873c6fd4d8a65dbf367092a826ddd587d141b401580b798c69" + "025ad510cff05fcfbceb6cf0bb03201aaa32e423d5200925bddfadd418d8e30e18050e" + "b4f0618eb9959d9f78c1157d4b3e02cd5961f138afd57459939917d9144c95d8e6a94c" + "8f6d4eef3418c17b1ef0b46c2a7188305d9811dccb3d99", + // mac + "4f1ee7cb36c58803a8721d4ac8c4cf8cae5d8832392eed2a96dc59694252801b", + }, + }; + + for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests); + ++test_index) { + SCOPED_TRACE(test_index); + const TestCase& test = kTests[test_index]; + + blink::WebCryptoAlgorithm algorithm = + webcrypto::CreateHmacAlgorithmByHashId(test.algorithm); + + blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( + test.key, algorithm, blink::WebCryptoKeyUsageSign); + + // Verify exported raw key is identical to the imported data + blink::WebArrayBuffer raw_key; + EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key)); + ExpectArrayBufferMatchesHex(test.key, raw_key); + + std::vector<uint8> message_raw = HexStringToBytes(test.message); + + blink::WebArrayBuffer output; + + ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); + + ExpectArrayBufferMatchesHex(test.mac, output); + + bool signature_match = false; + EXPECT_TRUE(VerifySignatureInternal( + algorithm, + key, + static_cast<const unsigned char*>(output.data()), + output.byteLength(), + message_raw, + &signature_match)); + EXPECT_TRUE(signature_match); + + // Ensure truncated signature does not verify by passing one less byte. + EXPECT_TRUE(VerifySignatureInternal( + algorithm, + key, + static_cast<const unsigned char*>(output.data()), + output.byteLength() - 1, + message_raw, + &signature_match)); + EXPECT_FALSE(signature_match); + + // Ensure extra long signature does not cause issues and fails. + const unsigned char kLongSignature[1024] = { 0 }; + EXPECT_TRUE(VerifySignatureInternal( + algorithm, + key, + kLongSignature, + sizeof(kLongSignature), + message_raw, + &signature_match)); + EXPECT_FALSE(signature_match); + } +} + +#if !defined(USE_OPENSSL) + +TEST_F(WebCryptoImplTest, AesCbcFailures) { + const std::string key_hex = "2b7e151628aed2a6abf7158809cf4f3c"; + blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( + key_hex, + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), + blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); + + // Verify exported raw key is identical to the imported data + blink::WebArrayBuffer raw_key; + EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key)); + ExpectArrayBufferMatchesHex(key_hex, raw_key); + + blink::WebArrayBuffer output; + + // Use an invalid |iv| (fewer than 16 bytes) + { + std::vector<uint8> input(32); + std::vector<uint8> iv; + EXPECT_FALSE(EncryptInternal( + webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output)); + EXPECT_FALSE(DecryptInternal( + webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output)); + } + + // Use an invalid |iv| (more than 16 bytes) + { + std::vector<uint8> input(32); + std::vector<uint8> iv(17); + EXPECT_FALSE(EncryptInternal( + webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output)); + EXPECT_FALSE(DecryptInternal( + webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output)); + } + + // Give an input that is too large (would cause integer overflow when + // narrowing to an int). + { + std::vector<uint8> iv(16); + + // Pretend the input is large. Don't pass data pointer as NULL in case that + // is special cased; the implementation shouldn't actually dereference the + // data. + const unsigned char* input = &iv[0]; + unsigned input_len = INT_MAX - 3; + + EXPECT_FALSE(EncryptInternal( + webcrypto::CreateAesCbcAlgorithm(iv), key, input, input_len, &output)); + EXPECT_FALSE(DecryptInternal( + webcrypto::CreateAesCbcAlgorithm(iv), key, input, input_len, &output)); + } + + // Fail importing the key (too few bytes specified) + { + std::vector<uint8> key_raw(1); + std::vector<uint8> iv(16); + + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw, + key_raw, + webcrypto::CreateAesCbcAlgorithm(iv), + true, + blink::WebCryptoKeyUsageEncrypt, + &key)); + } + + // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret + // keys). + EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output)); + EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatPkcs8, key, &output)); +} + +TEST_F(WebCryptoImplTest, AesCbcSampleSets) { + struct TestCase { + const char* key; + const char* iv; + const char* plain_text; + const char* cipher_text; + }; + + TestCase kTests[] = { + // F.2.1 (CBC-AES128.Encrypt) + // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + { + // key + "2b7e151628aed2a6abf7158809cf4f3c", + + // iv + "000102030405060708090a0b0c0d0e0f", + + // plain_text + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710", + + // cipher_text + "7649abac8119b246cee98e9b12e9197d" + "5086cb9b507219ee95db113a917678b2" + "73bed6b8e3c1743b7116e69e22229516" + "3ff1caa1681fac09120eca307586e1a7" + // Padding block: encryption of {0x10, 0x10, ... 0x10}) (not given by the + // NIST test vector) + "8cb82807230e1321d3fae00d18cc2012" + }, + + // F.2.6 CBC-AES256.Decrypt [*] + // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + // + // [*] Truncated 3 bytes off the plain text, so block 4 differs from the + // NIST vector. + { + // key + "603deb1015ca71be2b73aef0857d7781" + "1f352c073b6108d72d9810a30914dff4", + + // iv + "000102030405060708090a0b0c0d0e0f", + + // plain_text + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + // Truncated this last block to make it more interesting. + "f69f2445df4f9b17ad2b417be6", + + // cipher_text + "f58c4c04d6e5f1ba779eabfb5f7bfbd6" + "9cfc4e967edb808d679f777bc6702c7d" + "39f23369a9d9bacfa530e26304231461" + // This block differs from source vector (due to truncation) + "c9aaf02a6a54e9e242ccbf48c59daca6" + }, + + // Taken from encryptor_unittest.cc (EncryptorTest.EmptyEncrypt()) + { + // key + "3132383d5369787465656e4279746573", + + // iv + "5377656574205369787465656e204956", + + // plain_text + "", + + // cipher_text + "8518b8878d34e7185e300d0fcc426396" + }, + }; + + for (size_t index = 0; index < ARRAYSIZE_UNSAFE(kTests); index++) { + SCOPED_TRACE(index); + const TestCase& test = kTests[index]; + + blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( + test.key, + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), + blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); + + // Verify exported raw key is identical to the imported data + blink::WebArrayBuffer raw_key; + EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key)); + ExpectArrayBufferMatchesHex(test.key, raw_key); + + std::vector<uint8> plain_text = HexStringToBytes(test.plain_text); + std::vector<uint8> iv = HexStringToBytes(test.iv); + + blink::WebArrayBuffer output; + + // Test encryption. + EXPECT_TRUE(EncryptInternal(webcrypto::CreateAesCbcAlgorithm(iv), + key, + plain_text, + &output)); + ExpectArrayBufferMatchesHex(test.cipher_text, output); + + // Test decryption. + std::vector<uint8> cipher_text = HexStringToBytes(test.cipher_text); + EXPECT_TRUE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv), + key, + cipher_text, + &output)); + ExpectArrayBufferMatchesHex(test.plain_text, output); + + const unsigned kAesCbcBlockSize = 16; + + // Decrypt with a padding error by stripping the last block. This also ends + // up testing decryption over empty cipher text. + if (cipher_text.size() >= kAesCbcBlockSize) { + EXPECT_FALSE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv), + key, + &cipher_text[0], + cipher_text.size() - kAesCbcBlockSize, + &output)); + } + + // Decrypt cipher text which is not a multiple of block size by stripping + // a few bytes off the cipher text. + if (cipher_text.size() > 3) { + EXPECT_FALSE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv), + key, + &cipher_text[0], + cipher_text.size() - 3, + &output)); + } + } +} + +TEST_F(WebCryptoImplTest, GenerateKeyAes) { + // Generate a small sample of AES keys. + std::vector<blink::WebArrayBuffer> keys; + blink::WebArrayBuffer key_bytes; + for (int i = 0; i < 16; ++i) { + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + ASSERT_TRUE( + GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(128), &key)); + EXPECT_TRUE(key.handle()); + EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); + ASSERT_TRUE( + ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &key_bytes)); + keys.push_back(key_bytes); + } + // Ensure all entries in the key sample set are unique. This is a simplistic + // estimate of whether the generated keys appear random. + EXPECT_FALSE(CopiesExist(keys)); +} + +TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) { + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + EXPECT_FALSE( + GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(0), &key)); + EXPECT_FALSE( + GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(0), &key)); + EXPECT_FALSE( + GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(129), &key)); +} + +TEST_F(WebCryptoImplTest, GenerateKeyHmac) { + // Generate a small sample of HMAC keys. + std::vector<blink::WebArrayBuffer> keys; + for (int i = 0; i < 16; ++i) { + blink::WebArrayBuffer key_bytes; + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + blink::WebCryptoAlgorithm algorithm = webcrypto::CreateHmacKeyGenAlgorithm( + blink::WebCryptoAlgorithmIdSha1, 128); + ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); + EXPECT_FALSE(key.isNull()); + EXPECT_TRUE(key.handle()); + EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); + } + // Ensure all entries in the key sample set are unique. This is a simplistic + // estimate of whether the generated keys appear random. + EXPECT_FALSE(CopiesExist(keys)); +} + +TEST_F(WebCryptoImplTest, GenerateKeyHmacNoLength) { + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + blink::WebCryptoAlgorithm algorithm = + webcrypto::CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1, 0); + ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); + EXPECT_TRUE(key.handle()); + EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); +} + +TEST_F(WebCryptoImplTest, ImportSecretKeyNoAlgorithm) { + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + + // This fails because the algorithm is null. + EXPECT_FALSE(ImportKeyInternal( + blink::WebCryptoKeyFormatRaw, + HexStringToBytes("00000000000000000000"), + blink::WebCryptoAlgorithm::createNull(), + true, + blink::WebCryptoKeyUsageEncrypt, + &key)); +} + +#endif //#if !defined(USE_OPENSSL) + +TEST_F(WebCryptoImplTest, ImportJwkFailures) { + + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + blink::WebCryptoAlgorithm algorithm = + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc); + blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt; + + // Baseline pass: each test below breaks a single item, so we start with a + // passing case to make sure each failure is caused by the isolated break. + // Each breaking subtest below resets the dictionary to this passing case when + // complete. + base::DictionaryValue dict; + RestoreJwkOctDictionary(&dict); + EXPECT_TRUE(ImportKeyJwk( + MakeJsonVector(dict), algorithm, false, usage_mask, &key)); + + // Fail on empty JSON. + EXPECT_FALSE(ImportKeyJwk( + MakeJsonVector(""), algorithm, false, usage_mask, &key)); + + // Fail on invalid JSON. + const std::vector<uint8> bad_json_vec = MakeJsonVector( + "{" + "\"kty\" : \"oct\"," + "\"alg\" : \"HS256\"," + "\"use\" : " + ); + EXPECT_FALSE(ImportKeyJwk(bad_json_vec, algorithm, false, usage_mask, &key)); + + // Fail on JWK alg present but unrecognized. + dict.SetString("alg", "A127CBC"); + EXPECT_FALSE(ImportKeyJwk( + MakeJsonVector(dict), algorithm, false, usage_mask, &key)); + RestoreJwkOctDictionary(&dict); + + // Fail on both JWK and input algorithm missing. + dict.Remove("alg", NULL); + EXPECT_FALSE(ImportKeyJwk(MakeJsonVector(dict), + blink::WebCryptoAlgorithm::createNull(), + false, + usage_mask, + &key)); + RestoreJwkOctDictionary(&dict); + + // Fail on invalid kty. + dict.SetString("kty", "foo"); + EXPECT_FALSE(ImportKeyJwk( + MakeJsonVector(dict), algorithm, false, usage_mask, &key)); + RestoreJwkOctDictionary(&dict); + + // Fail on missing kty. + dict.Remove("kty", NULL); + EXPECT_FALSE(ImportKeyJwk( + MakeJsonVector(dict), algorithm, false, usage_mask, &key)); + RestoreJwkOctDictionary(&dict); + + // Fail on invalid use. + dict.SetString("use", "foo"); + EXPECT_FALSE(ImportKeyJwk( + MakeJsonVector(dict), algorithm, false, usage_mask, &key)); + RestoreJwkOctDictionary(&dict); +} + +TEST_F(WebCryptoImplTest, ImportJwkOctFailures) { + + base::DictionaryValue dict; + RestoreJwkOctDictionary(&dict); + blink::WebCryptoAlgorithm algorithm = + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc); + blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt; + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + + // Baseline pass. + EXPECT_TRUE(ImportKeyJwk( + MakeJsonVector(dict), algorithm, false, usage_mask, &key)); + EXPECT_EQ(algorithm.id(), key.algorithm().id()); + EXPECT_FALSE(key.extractable()); + EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages()); + EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); + + // The following are specific failure cases for when kty = "oct". + + // Fail on missing k. + dict.Remove("k", NULL); + EXPECT_FALSE(ImportKeyJwk( + MakeJsonVector(dict), algorithm, false, usage_mask, &key)); + RestoreJwkOctDictionary(&dict); + + // Fail on bad b64 encoding for k. + dict.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI="); + EXPECT_FALSE(ImportKeyJwk( + MakeJsonVector(dict), algorithm, false, usage_mask, &key)); + RestoreJwkOctDictionary(&dict); + + // Fail on empty k. + dict.SetString("k", ""); + EXPECT_FALSE(ImportKeyJwk( + MakeJsonVector(dict), algorithm, false, usage_mask, &key)); + RestoreJwkOctDictionary(&dict); + + // Fail on k actual length (120 bits) inconsistent with the embedded JWK alg + // value (128) for an AES key. + dict.SetString("k", "AVj42h0Y5aqGtE3yluKL"); + EXPECT_FALSE(ImportKeyJwk( + MakeJsonVector(dict), algorithm, false, usage_mask, &key)); + RestoreJwkOctDictionary(&dict); +} + +#if !defined(USE_OPENSSL) + +TEST_F(WebCryptoImplTest, ImportJwkRsaFailures) { + + base::DictionaryValue dict; + RestoreJwkRsaDictionary(&dict); + blink::WebCryptoAlgorithm algorithm = + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5); + blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt; + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + + // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent) + // entry, while an RSA private key must have those plus at least a "d" + // (private exponent) entry. + // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18, + // section 6.3. + + // Baseline pass. + EXPECT_TRUE(ImportKeyJwk( + MakeJsonVector(dict), algorithm, false, usage_mask, &key)); + EXPECT_EQ(algorithm.id(), key.algorithm().id()); + EXPECT_FALSE(key.extractable()); + EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages()); + EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type()); + + // The following are specific failure cases for when kty = "RSA". + + // Fail if either "n" or "e" is not present or malformed. + const std::string kKtyParmName[] = {"n", "e"}; + for (size_t idx = 0; idx < ARRAYSIZE_UNSAFE(kKtyParmName); ++idx) { + + // Fail on missing parameter. + dict.Remove(kKtyParmName[idx], NULL); + EXPECT_FALSE(ImportKeyJwk( + MakeJsonVector(dict), algorithm, false, usage_mask, &key)); + RestoreJwkRsaDictionary(&dict); + + // Fail on bad b64 parameter encoding. + dict.SetString(kKtyParmName[idx], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0"); + EXPECT_FALSE(ImportKeyJwk( + MakeJsonVector(dict), algorithm, false, usage_mask, &key)); + RestoreJwkRsaDictionary(&dict); + + // Fail on empty parameter. + dict.SetString(kKtyParmName[idx], ""); + EXPECT_FALSE(ImportKeyJwk( + MakeJsonVector(dict), algorithm, false, usage_mask, &key)); + RestoreJwkRsaDictionary(&dict); + } + + // Fail if "d" parameter is present, implying the JWK is a private key, which + // is not supported. + dict.SetString("d", "Qk3f0Dsyt"); + EXPECT_FALSE(ImportKeyJwk( + MakeJsonVector(dict), algorithm, false, usage_mask, &key)); + RestoreJwkRsaDictionary(&dict); +} + +#endif // #if !defined(USE_OPENSSL) + +TEST_F(WebCryptoImplTest, ImportJwkInputConsistency) { + // The Web Crypto spec says that if a JWK value is present, but is + // inconsistent with the input value, the operation must fail. + + // Consistency rules when JWK value is not present: Inputs should be used. + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + bool extractable = false; + blink::WebCryptoAlgorithm algorithm = + webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256); + blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageVerify; + base::DictionaryValue dict; + dict.SetString("kty", "oct"); + dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); + std::vector<uint8> json_vec = MakeJsonVector(dict); + EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key)); + EXPECT_TRUE(key.handle()); + EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); + EXPECT_EQ(extractable, key.extractable()); + EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id()); + EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256, + key.algorithm().hmacParams()->hash().id()); + EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages()); + key = blink::WebCryptoKey::createNull(); + + // Consistency rules when JWK value exists: Fail if inconsistency is found. + + // Pass: All input values are consistent with the JWK values. + dict.Clear(); + dict.SetString("kty", "oct"); + dict.SetString("alg", "HS256"); + dict.SetString("use", "sig"); + dict.SetBoolean("extractable", false); + dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); + json_vec = MakeJsonVector(dict); + EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key)); + + // Extractable cases: + // 1. input=T, JWK=F ==> fail (inconsistent) + // 4. input=F, JWK=F ==> pass, result extractable is F + // 2. input=T, JWK=T ==> pass, result extractable is T + // 3. input=F, JWK=T ==> pass, result extractable is F + EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, true, usage_mask, &key)); + EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); + EXPECT_FALSE(key.extractable()); + dict.SetBoolean("extractable", true); + EXPECT_TRUE( + ImportKeyJwk(MakeJsonVector(dict), algorithm, true, usage_mask, &key)); + EXPECT_TRUE(key.extractable()); + EXPECT_TRUE( + ImportKeyJwk(MakeJsonVector(dict), algorithm, false, usage_mask, &key)); + EXPECT_FALSE(key.extractable()); + dict.SetBoolean("extractable", true); // restore previous value + + // Fail: Input algorithm (AES-CBC) is inconsistent with JWK value + // (HMAC SHA256). + EXPECT_FALSE(ImportKeyJwk( + json_vec, + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), + extractable, + usage_mask, + &key)); + + // Fail: Input algorithm (HMAC SHA1) is inconsistent with JWK value + // (HMAC SHA256). + EXPECT_FALSE(ImportKeyJwk( + json_vec, + webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha1), + extractable, + usage_mask, + &key)); + + // Pass: JWK alg valid but input algorithm isNull: use JWK algorithm value. + EXPECT_TRUE(ImportKeyJwk(json_vec, + blink::WebCryptoAlgorithm::createNull(), + extractable, + usage_mask, + &key)); + EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id()); + + // Pass: JWK alg missing but input algorithm specified: use input value + dict.Remove("alg", NULL); + EXPECT_TRUE(ImportKeyJwk( + MakeJsonVector(dict), + webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256), + extractable, + usage_mask, + &key)); + EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id()); + dict.SetString("alg", "HS256"); + + // Fail: Input usage_mask (encrypt) is not a subset of the JWK value + // (sign|verify) + EXPECT_FALSE(ImportKeyJwk( + json_vec, algorithm, extractable, blink::WebCryptoKeyUsageEncrypt, &key)); + + // Fail: Input usage_mask (encrypt|sign|verify) is not a subset of the JWK + // value (sign|verify) + usage_mask = blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageSign | + blink::WebCryptoKeyUsageVerify; + EXPECT_FALSE( + ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key)); + usage_mask = blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify; + + // TODO(padolph): kty vs alg consistency tests: Depending on the kty value, + // only certain alg values are permitted. For example, when kty = "RSA" alg + // must be of the RSA family, or when kty = "oct" alg must be symmetric + // algorithm. +} + +TEST_F(WebCryptoImplTest, ImportJwkHappy) { + + // This test verifies the happy path of JWK import, including the application + // of the imported key material. + + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + bool extractable = false; + blink::WebCryptoAlgorithm algorithm = + webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256); + blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageSign; + + // Import a symmetric key JWK and HMAC-SHA256 sign() + // Uses the first SHA256 test vector from the HMAC sample set above. + + base::DictionaryValue dict; + dict.SetString("kty", "oct"); + dict.SetString("alg", "HS256"); + dict.SetString("use", "sig"); + dict.SetBoolean("extractable", false); + dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); + std::vector<uint8> json_vec = MakeJsonVector(dict); + + ASSERT_TRUE(ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key)); + + const std::vector<uint8> message_raw = HexStringToBytes( + "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a" + "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92" + "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f" + "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e"); + + blink::WebArrayBuffer output; + + ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); + + const std::string mac_raw = + "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b"; + + ExpectArrayBufferMatchesHex(mac_raw, output); + + // TODO(padolph): Import an RSA public key JWK and use it +} + +#if !defined(USE_OPENSSL) + +TEST_F(WebCryptoImplTest, ImportExportSpki) { + // openssl genrsa -out pair.pem 2048 + // openssl rsa -in pair.pem -out pubkey.der -outform DER -pubout + // xxd -p pubkey.der + const std::string hex_rsa_spki_der = + "30820122300d06092a864886f70d01010105000382010f003082010a0282" + "010100f19e40f94e3780858701577a571cca000cb9795db89ddf8e98ab0e" + "5eecfa47516cb08dc591cae5ab7fa43d6db402e95991d4a2de52e7cd3a66" + "4f58284be2eb4675d5a849a2582c585d2b3c6c225a8f2c53a0414d5dbd06" + "172371cefdf953e9ec3000fc9ad000743023f74e82d12aa93917a2c9b832" + "696085ee0711154cf98a6d098f44cee00ea3b7584236503a5483ba8b6792" + "fee588d1a8f4a0618333c4cb3447d760b43d5a0d9ed6ef79763df670cd8b" + "5eb869a20833f1e3e6d8b88240a5d4335c73fd20487f2a7d112af8692357" + "6425e44a273e5ad2e93d6b50a28e65f9e133958e4f0c7d12e0adc90fedd4" + "f6b6848e7b6900666642a08b520a6534a35d4f0203010001"; + + // Passing case: Import a valid RSA key in SPKI format. + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + ASSERT_TRUE(ImportKeyInternal( + blink::WebCryptoKeyFormatSpki, + HexStringToBytes(hex_rsa_spki_der), + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5), + true, + blink::WebCryptoKeyUsageEncrypt, + &key)); + EXPECT_TRUE(key.handle()); + EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type()); + EXPECT_TRUE(key.extractable()); + EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages()); + + // Failing case: Empty SPKI data + EXPECT_FALSE(ImportKeyInternal( + blink::WebCryptoKeyFormatSpki, + std::vector<uint8>(), + blink::WebCryptoAlgorithm::createNull(), + true, + blink::WebCryptoKeyUsageEncrypt, + &key)); + + // Failing case: Import RSA key with NULL input algorithm. This is not + // allowed because the SPKI ASN.1 format for RSA keys is not specific enough + // to map to a Web Crypto algorithm. + EXPECT_FALSE(ImportKeyInternal( + blink::WebCryptoKeyFormatSpki, + HexStringToBytes(hex_rsa_spki_der), + blink::WebCryptoAlgorithm::createNull(), + true, + blink::WebCryptoKeyUsageEncrypt, + &key)); + + // Failing case: Bad DER encoding. + EXPECT_FALSE(ImportKeyInternal( + blink::WebCryptoKeyFormatSpki, + HexStringToBytes("618333c4cb"), + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5), + true, + blink::WebCryptoKeyUsageEncrypt, + &key)); + + // Failing case: Import RSA key but provide an inconsistent input algorithm. + EXPECT_FALSE(ImportKeyInternal( + blink::WebCryptoKeyFormatSpki, + HexStringToBytes(hex_rsa_spki_der), + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), + true, + blink::WebCryptoKeyUsageEncrypt, + &key)); + + // Passing case: Export a previously imported RSA public key in SPKI format + // and compare to original data. + blink::WebArrayBuffer output; + ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output)); + ExpectArrayBufferMatchesHex(hex_rsa_spki_der, output); + + // Failing case: Try to export a previously imported RSA public key in raw + // format (not allowed for a public key). + EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &output)); + + // Failing case: Try to export a non-extractable key + ASSERT_TRUE(ImportKeyInternal( + blink::WebCryptoKeyFormatSpki, + HexStringToBytes(hex_rsa_spki_der), + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5), + false, + blink::WebCryptoKeyUsageEncrypt, + &key)); + EXPECT_TRUE(key.handle()); + EXPECT_FALSE(key.extractable()); + EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output)); +} + +TEST_F(WebCryptoImplTest, ImportPkcs8) { + + // The following is a DER-encoded PKCS#8 representation of the RSA key from + // Example 1 of NIST's "Test vectors for RSA PKCS#1 v1.5 Signature". + // ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.txt + const std::string hex_rsa_pkcs8_der = + "30820275020100300D06092A864886F70D01010105000482025F3082025B020100028181" + "00A56E4A0E701017589A5187DC7EA841D156F2EC0E36AD52A44DFEB1E61F7AD991D8C510" + "56FFEDB162B4C0F283A12A88A394DFF526AB7291CBB307CEABFCE0B1DFD5CD9508096D5B" + "2B8B6DF5D671EF6377C0921CB23C270A70E2598E6FF89D19F105ACC2D3F0CB35F29280E1" + "386B6F64C4EF22E1E1F20D0CE8CFFB2249BD9A2137020301000102818033A5042A90B27D" + "4F5451CA9BBBD0B44771A101AF884340AEF9885F2A4BBE92E894A724AC3C568C8F97853A" + "D07C0266C8C6A3CA0929F1E8F11231884429FC4D9AE55FEE896A10CE707C3ED7E734E447" + "27A39574501A532683109C2ABACABA283C31B4BD2F53C3EE37E352CEE34F9E503BD80C06" + "22AD79C6DCEE883547C6A3B325024100E7E8942720A877517273A356053EA2A1BC0C94AA" + "72D55C6E86296B2DFC967948C0A72CBCCCA7EACB35706E09A1DF55A1535BD9B3CC34160B" + "3B6DCD3EDA8E6443024100B69DCA1CF7D4D7EC81E75B90FCCA874ABCDE123FD2700180AA" + "90479B6E48DE8D67ED24F9F19D85BA275874F542CD20DC723E6963364A1F9425452B269A" + "6799FD024028FA13938655BE1F8A159CBACA5A72EA190C30089E19CD274A556F36C4F6E1" + "9F554B34C077790427BBDD8DD3EDE2448328F385D81B30E8E43B2FFFA02786197902401A" + "8B38F398FA712049898D7FB79EE0A77668791299CDFA09EFC0E507ACB21ED74301EF5BFD" + "48BE455EAEB6E1678255827580A8E4E8E14151D1510A82A3F2E729024027156ABA4126D2" + "4A81F3A528CBFB27F56886F840A9F6E86E17A44B94FE9319584B8E22FDDE1E5A2E3BD8AA" + "5BA8D8584194EB2190ACF832B847F13A3D24A79F4D"; + + // Passing case: Import a valid RSA key in PKCS#8 format. + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + ASSERT_TRUE(ImportKeyInternal( + blink::WebCryptoKeyFormatPkcs8, + HexStringToBytes(hex_rsa_pkcs8_der), + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5), + true, + blink::WebCryptoKeyUsageSign, + &key)); + EXPECT_TRUE(key.handle()); + EXPECT_EQ(blink::WebCryptoKeyTypePrivate, key.type()); + EXPECT_TRUE(key.extractable()); + EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages()); + + // Failing case: Empty PKCS#8 data + EXPECT_FALSE(ImportKeyInternal( + blink::WebCryptoKeyFormatPkcs8, + std::vector<uint8>(), + blink::WebCryptoAlgorithm::createNull(), + true, + blink::WebCryptoKeyUsageSign, + &key)); + + // Failing case: Import RSA key with NULL input algorithm. This is not + // allowed because the PKCS#8 ASN.1 format for RSA keys is not specific enough + // to map to a Web Crypto algorithm. + EXPECT_FALSE(ImportKeyInternal( + blink::WebCryptoKeyFormatPkcs8, + HexStringToBytes(hex_rsa_pkcs8_der), + blink::WebCryptoAlgorithm::createNull(), + true, + blink::WebCryptoKeyUsageSign, + &key)); + + // Failing case: Bad DER encoding. + EXPECT_FALSE(ImportKeyInternal( + blink::WebCryptoKeyFormatPkcs8, + HexStringToBytes("618333c4cb"), + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5), + true, + blink::WebCryptoKeyUsageSign, + &key)); + + // Failing case: Import RSA key but provide an inconsistent input algorithm. + EXPECT_FALSE(ImportKeyInternal( + blink::WebCryptoKeyFormatPkcs8, + HexStringToBytes(hex_rsa_pkcs8_der), + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), + true, + blink::WebCryptoKeyUsageSign, + &key)); +} + +TEST_F(WebCryptoImplTest, GenerateKeyPairRsa) { + // Note: using unrealistic short key lengths here to avoid bogging down tests. + + // Successful WebCryptoAlgorithmIdRsaEsPkcs1v1_5 key generation. + const unsigned modulus_length = 256; + const std::vector<uint8> public_exponent = HexStringToBytes("010001"); + blink::WebCryptoAlgorithm algorithm = webcrypto::CreateRsaKeyGenAlgorithm( + blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, + modulus_length, + public_exponent); + bool extractable = false; + const blink::WebCryptoKeyUsageMask usage_mask = 0; + blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); + blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); + EXPECT_TRUE(GenerateKeyPairInternal( + algorithm, extractable, usage_mask, &public_key, &private_key)); + EXPECT_FALSE(public_key.isNull()); + EXPECT_FALSE(private_key.isNull()); + EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type()); + EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type()); + EXPECT_EQ(true, public_key.extractable()); + EXPECT_EQ(extractable, private_key.extractable()); + EXPECT_EQ(usage_mask, public_key.usages()); + EXPECT_EQ(usage_mask, private_key.usages()); + + // Fail with bad modulus. + algorithm = webcrypto::CreateRsaKeyGenAlgorithm( + blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, 0, public_exponent); + EXPECT_FALSE(GenerateKeyPairInternal( + algorithm, extractable, usage_mask, &public_key, &private_key)); + + // Fail with bad exponent: larger than unsigned long. + unsigned exponent_length = sizeof(unsigned long) + 1; // NOLINT + const std::vector<uint8> long_exponent(exponent_length, 0x01); + algorithm = webcrypto::CreateRsaKeyGenAlgorithm( + blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, modulus_length, long_exponent); + EXPECT_FALSE(GenerateKeyPairInternal( + algorithm, extractable, usage_mask, &public_key, &private_key)); + + // Fail with bad exponent: empty. + const std::vector<uint8> empty_exponent; + algorithm = webcrypto::CreateRsaKeyGenAlgorithm( + blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, + modulus_length, + empty_exponent); + EXPECT_FALSE(GenerateKeyPairInternal( + algorithm, extractable, usage_mask, &public_key, &private_key)); + + // Fail with bad exponent: all zeros. + std::vector<uint8> exponent_with_leading_zeros(15, 0x00); + algorithm = webcrypto::CreateRsaKeyGenAlgorithm( + blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, + modulus_length, + exponent_with_leading_zeros); + EXPECT_FALSE(GenerateKeyPairInternal( + algorithm, extractable, usage_mask, &public_key, &private_key)); + + // Key generation success using exponent with leading zeros. + exponent_with_leading_zeros.insert(exponent_with_leading_zeros.end(), + public_exponent.begin(), + public_exponent.end()); + algorithm = webcrypto::CreateRsaKeyGenAlgorithm( + blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, + modulus_length, + exponent_with_leading_zeros); + EXPECT_TRUE(GenerateKeyPairInternal( + algorithm, extractable, usage_mask, &public_key, &private_key)); + EXPECT_FALSE(public_key.isNull()); + EXPECT_FALSE(private_key.isNull()); + EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type()); + EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type()); + EXPECT_EQ(true, public_key.extractable()); + EXPECT_EQ(extractable, private_key.extractable()); + EXPECT_EQ(usage_mask, public_key.usages()); + EXPECT_EQ(usage_mask, private_key.usages()); + + // Successful WebCryptoAlgorithmIdRsaOaep key generation. + algorithm = webcrypto::CreateRsaKeyGenAlgorithm( + blink::WebCryptoAlgorithmIdRsaOaep, modulus_length, public_exponent); + EXPECT_TRUE(GenerateKeyPairInternal( + algorithm, extractable, usage_mask, &public_key, &private_key)); + EXPECT_FALSE(public_key.isNull()); + EXPECT_FALSE(private_key.isNull()); + EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type()); + EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type()); + EXPECT_EQ(true, public_key.extractable()); + EXPECT_EQ(extractable, private_key.extractable()); + EXPECT_EQ(usage_mask, public_key.usages()); + EXPECT_EQ(usage_mask, private_key.usages()); + + // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation. + algorithm = webcrypto::CreateRsaKeyGenAlgorithm( + blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, + modulus_length, + public_exponent); + EXPECT_TRUE(GenerateKeyPairInternal( + algorithm, extractable, usage_mask, &public_key, &private_key)); + EXPECT_FALSE(public_key.isNull()); + EXPECT_FALSE(private_key.isNull()); + EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type()); + EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type()); + EXPECT_EQ(true, public_key.extractable()); + EXPECT_EQ(extractable, private_key.extractable()); + EXPECT_EQ(usage_mask, public_key.usages()); + EXPECT_EQ(usage_mask, private_key.usages()); + + // Fail SPKI export of private key. This is an ExportKey test, but do it here + // since it is expensive to generate an RSA key pair and we already have a + // private key here. + blink::WebArrayBuffer output; + EXPECT_FALSE( + ExportKeyInternal(blink::WebCryptoKeyFormatSpki, private_key, &output)); +} + +TEST_F(WebCryptoImplTest, RsaEsRoundTrip) { + // Note: using unrealistic short key length here to avoid bogging down tests. + + // Create a key pair. + const unsigned kModulusLength = 256; + blink::WebCryptoAlgorithm algorithm = + CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, + kModulusLength, + HexStringToBytes("010001")); + const blink::WebCryptoKeyUsageMask usage_mask = + blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt; + blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); + blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); + EXPECT_TRUE(GenerateKeyPairInternal( + algorithm, false, usage_mask, &public_key, &private_key)); + EXPECT_FALSE(public_key.isNull()); + EXPECT_FALSE(private_key.isNull()); + + // Make a maximum-length data message. RSAES can operate on messages up to + // length of k - 11 bytes, where k is the octet length of the RSA modulus. + const unsigned kMaxMsgSizeBytes = kModulusLength / 8 - 11; + // There are two hex chars for each byte. + const unsigned kMsgHexSize = kMaxMsgSizeBytes * 2; + char max_data_hex[kMsgHexSize+1]; + std::fill(&max_data_hex[0], &max_data_hex[0] + kMsgHexSize, 'a'); + max_data_hex[kMsgHexSize] = '\0'; + + // Verify encrypt / decrypt round trip on a few messages. Note that RSA + // encryption does not support empty input. + algorithm = + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5); + const char* const kTestDataHex[] = { + "ff", + "0102030405060708090a0b0c0d0e0f", + max_data_hex + }; + blink::WebArrayBuffer encrypted_data; + blink::WebArrayBuffer decrypted_data; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestDataHex); ++i) { + SCOPED_TRACE(i); + ASSERT_TRUE(EncryptInternal( + algorithm, + public_key, + HexStringToBytes(kTestDataHex[i]), + &encrypted_data)); + EXPECT_EQ(kModulusLength/8, encrypted_data.byteLength()); + ASSERT_TRUE(DecryptInternal( + algorithm, + private_key, + reinterpret_cast<const unsigned char*>(encrypted_data.data()), + encrypted_data.byteLength(), + &decrypted_data)); + ExpectArrayBufferMatchesHex(kTestDataHex[i], decrypted_data); + } +} + +TEST_F(WebCryptoImplTest, RsaEsKnownAnswer) { + // Because the random data in PKCS1.5 padding makes the encryption output non- + // deterministic, we cannot easily do a typical known-answer test for RSA + // encryption / decryption. Instead we will take a known-good encrypted + // message, decrypt it, re-encrypt it, then decrypt again, verifying that the + // original known cleartext is the result. + + // The RSA public and private keys used for this test are produced by the + // openssl command line: + // % openssl genrsa -out pair.pem 1024 + // % openssl rsa -in pair.pem -out spki.der -outform DER -pubout + // % openssl pkcs8 -topk8 -inform PEM -outform DER -in pair.pem -out + // pkcs8.der -nocrypt + // % xxd -p spki.der + // % xxd -p pkcs8.der + const std::string rsa_spki_der_hex = + "30819f300d06092a864886f70d010101050003818d0030818902818100a8" + "d30894b93f376f7822229bfd2483e50da944c4ab803ca31979e0f47e70bf" + "683c687c6b3e80f280a237cea3643fd1f7f10f7cc664dbc2ecd45be53e1c" + "9b15a53c37dbdad846c0f8340c472abc7821e4aa7df185867bf38228ac3e" + "cc1d97d3c8b57e21ea6ba57b2bc3814a436e910ee8ab64a0b7743a927e94" + "4d3420401f7dd50203010001"; + const std::string rsa_pkcs8_der_hex = + "30820276020100300d06092a864886f70d0101010500048202603082025c" + "02010002818100a8d30894b93f376f7822229bfd2483e50da944c4ab803c" + "a31979e0f47e70bf683c687c6b3e80f280a237cea3643fd1f7f10f7cc664" + "dbc2ecd45be53e1c9b15a53c37dbdad846c0f8340c472abc7821e4aa7df1" + "85867bf38228ac3ecc1d97d3c8b57e21ea6ba57b2bc3814a436e910ee8ab" + "64a0b7743a927e944d3420401f7dd5020301000102818100896cdffb50a0" + "691bd00ad9696933243a7c5861a64684e8d74b91aed0d76c28234da9303e" + "8c6ea2f89b141a9d5ea9a4ddd3d8eb9503dcf05ba0b1fd76060b281e3ae4" + "b9d497fb5519bdf1127db8ad412d6a722686c78df3e3002acca960c6b2a2" + "42a83ace5410693c03ce3d74cb9c9a7bacc8e271812920d1f53fee9312ef" + "4eb1024100d09c14418ce92af7cc62f7cdc79836d8c6e3d0d33e7229cc11" + "d732cbac75aa4c56c92e409a3ccbe75d4ce63ac5adca33080690782c6371" + "e3628134c3534ca603024100cf2d3206f6deea2f39b70351c51f85436200" + "5aa8f643e49e22486736d536e040dc30a2b4f9be3ab212a88d1891280874" + "b9a170cdeb22eaf61c27c4b082c7d1470240638411a5b3b307ec6e744802" + "c2d4ba556f8bfe72c7b76e790b89bd91ac13f5c9b51d04138d80b3450c1d" + "4337865601bf96748b36c8f627be719f71ac3c70b441024065ce92cfe34e" + "a58bf173a2b8f3024b4d5282540ac581957db3e11a7f528535ec098808dc" + "a0013ffcb3b88a25716757c86c540e07d2ad8502cdd129118822c30f0240" + "420a4983040e9db46eb29f1315a0d7b41cf60428f7460fce748e9a1a7d22" + "d7390fa328948e7e9d1724401374e99d45eb41474781201378a4330e8e80" + "8ce63551"; + + // Similarly, the cleartext and public key encrypted ciphertext for this test + // are also produced by openssl. Note that since we are using a 1024-bit key, + // the cleartext size must be less than or equal to 117 bytes (modulusLength / + // 8 - 11). + // % openssl rand -out cleartext.bin 64 + // % openssl rsautl -encrypt -inkey spki.der -keyform DER -pubin -in + // cleartext.bin -out ciphertext.bin + // % xxd -p cleartext.bin + // % xxd -p ciphertext.bin + const std::string cleartext_hex = + "ec358ed141c45d7e03d4c6338aebad718e8bcbbf8f8ee6f8d9f4b9ef06d8" + "84739a398c6bcbc688418b2ff64761dc0ccd40e7d52bed03e06946d0957a" + "eef9e822"; + const std::string ciphertext_hex = + "6106441c2b7a4b1a16260ed1ae4fe6135247345dc8e674754bbda6588c6c" + "0d95a3d4d26bb34cdbcbe327723e80343bd7a15cd4c91c3a44e6cb9c6cd6" + "7ad2e8bf41523188d9b36dc364a838642dcbc2c25e85dfb2106ba47578ca" + "3bbf8915055aea4fa7c3cbfdfbcc163f04c234fb6d847f39bab9612ecbee" + "04626e945c3ccf42"; + + // Import the public key. + const blink::WebCryptoAlgorithm algorithm = + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5); + blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); + ASSERT_TRUE(ImportKeyInternal( + blink::WebCryptoKeyFormatSpki, + HexStringToBytes(rsa_spki_der_hex), + algorithm, + true, + blink::WebCryptoKeyUsageEncrypt, + &public_key)); + EXPECT_FALSE(public_key.isNull()); + EXPECT_TRUE(public_key.handle()); + + // Import the private key. + blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); + ASSERT_TRUE(ImportKeyInternal( + blink::WebCryptoKeyFormatPkcs8, + HexStringToBytes(rsa_pkcs8_der_hex), + algorithm, + true, + blink::WebCryptoKeyUsageDecrypt, + &private_key)); + EXPECT_FALSE(private_key.isNull()); + EXPECT_TRUE(private_key.handle()); + + // Decrypt the known-good ciphertext with the private key. As a check we must + // get the known original cleartext. + blink::WebArrayBuffer decrypted_data; + ASSERT_TRUE(DecryptInternal( + algorithm, + private_key, + HexStringToBytes(ciphertext_hex), + &decrypted_data)); + EXPECT_FALSE(decrypted_data.isNull()); + ExpectArrayBufferMatchesHex(cleartext_hex, decrypted_data); + + // Encrypt this decrypted data with the public key. + blink::WebArrayBuffer encrypted_data; + ASSERT_TRUE(EncryptInternal( + algorithm, + public_key, + reinterpret_cast<const unsigned char*>(decrypted_data.data()), + decrypted_data.byteLength(), + &encrypted_data)); + EXPECT_EQ(128u, encrypted_data.byteLength()); + + // Finally, decrypt the newly encrypted result with the private key, and + // compare to the known original cleartext. + decrypted_data.reset(); + ASSERT_TRUE(DecryptInternal( + algorithm, + private_key, + reinterpret_cast<const unsigned char*>(encrypted_data.data()), + encrypted_data.byteLength(), + &decrypted_data)); + EXPECT_FALSE(decrypted_data.isNull()); + ExpectArrayBufferMatchesHex(cleartext_hex, decrypted_data); +} + +TEST_F(WebCryptoImplTest, RsaEsFailures) { + // Note: using unrealistic short key length here to avoid bogging down tests. + + // Create a key pair. + const unsigned kModulusLength = 256; + blink::WebCryptoAlgorithm algorithm = + CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, + kModulusLength, + HexStringToBytes("010001")); + const blink::WebCryptoKeyUsageMask usage_mask = + blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt; + blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); + blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); + EXPECT_TRUE(GenerateKeyPairInternal( + algorithm, false, usage_mask, &public_key, &private_key)); + EXPECT_FALSE(public_key.isNull()); + EXPECT_FALSE(private_key.isNull()); + + // Fail encrypt with a private key. + algorithm = + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5); + blink::WebArrayBuffer encrypted_data; + const std::string message_hex_str("0102030405060708090a0b0c0d0e0f"); + const std::vector<uint8> message_hex(HexStringToBytes(message_hex_str)); + EXPECT_FALSE( + EncryptInternal(algorithm, private_key, message_hex, &encrypted_data)); + + // Fail encrypt with empty message. + EXPECT_FALSE(EncryptInternal( + algorithm, public_key, std::vector<uint8>(), &encrypted_data)); + + // Fail encrypt with message too large. RSAES can operate on messages up to + // length of k - 11 bytes, where k is the octet length of the RSA modulus. + const unsigned kMaxMsgSizeBytes = kModulusLength / 8 - 11; + EXPECT_FALSE(EncryptInternal(algorithm, + public_key, + std::vector<uint8>(kMaxMsgSizeBytes + 1, '0'), + &encrypted_data)); + + // Generate encrypted data. + EXPECT_TRUE( + EncryptInternal(algorithm, public_key, message_hex, &encrypted_data)); + + // Fail decrypt with a public key. + blink::WebArrayBuffer decrypted_data; + EXPECT_FALSE(DecryptInternal( + algorithm, + public_key, + reinterpret_cast<const unsigned char*>(encrypted_data.data()), + encrypted_data.byteLength(), + &decrypted_data)); + + // Corrupt encrypted data; ensure decrypt fails because padding was disrupted. + std::vector<uint8> corrupted_data( + static_cast<uint8*>(encrypted_data.data()), + static_cast<uint8*>(encrypted_data.data()) + encrypted_data.byteLength()); + corrupted_data[corrupted_data.size() / 2] ^= 0x01; + EXPECT_FALSE( + DecryptInternal(algorithm, private_key, corrupted_data, &decrypted_data)); + + // TODO(padolph): Are there other specific data corruption scenarios to + // consider? + + // Do a successful decrypt with good data just for confirmation. + EXPECT_TRUE(DecryptInternal( + algorithm, + private_key, + reinterpret_cast<const unsigned char*>(encrypted_data.data()), + encrypted_data.byteLength(), + &decrypted_data)); + ExpectArrayBufferMatchesHex(message_hex_str, decrypted_data); +} + +#endif // #if !defined(USE_OPENSSL) + +} // namespace content diff --git a/chromium/content/renderer/webcrypto/webcrypto_util.cc b/chromium/content/renderer/webcrypto/webcrypto_util.cc new file mode 100644 index 00000000000..b5a318a1be2 --- /dev/null +++ b/chromium/content/renderer/webcrypto/webcrypto_util.cc @@ -0,0 +1,205 @@ +// 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/renderer/webcrypto/webcrypto_util.h" + +#include "base/base64.h" +#include "base/logging.h" +#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" +#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" + +namespace content { + +namespace webcrypto { + +namespace { + +blink::WebCryptoAlgorithm CreateAesKeyGenAlgorithm( + blink::WebCryptoAlgorithmId aes_alg_id, + unsigned short length) { + return blink::WebCryptoAlgorithm::adoptParamsAndCreate( + aes_alg_id, new blink::WebCryptoAesKeyGenParams(length)); +} + +bool IsHashAlgorithm(blink::WebCryptoAlgorithmId alg_id) { + return alg_id == blink::WebCryptoAlgorithmIdSha1 || + alg_id == blink::WebCryptoAlgorithmIdSha224 || + alg_id == blink::WebCryptoAlgorithmIdSha256 || + alg_id == blink::WebCryptoAlgorithmIdSha384 || + alg_id == blink::WebCryptoAlgorithmIdSha512; +} + +} // namespace + +const uint8* Uint8VectorStart(const std::vector<uint8>& data) { + if (data.empty()) + return NULL; + return &data[0]; +} + +void ShrinkBuffer(blink::WebArrayBuffer* buffer, unsigned new_size) { + DCHECK_LE(new_size, buffer->byteLength()); + + if (new_size == buffer->byteLength()) + return; + + blink::WebArrayBuffer new_buffer = blink::WebArrayBuffer::create(new_size, 1); + DCHECK(!new_buffer.isNull()); + memcpy(new_buffer.data(), buffer->data(), new_size); + *buffer = new_buffer; +} + +blink::WebArrayBuffer CreateArrayBuffer(const uint8* data, unsigned data_size) { + blink::WebArrayBuffer buffer = blink::WebArrayBuffer::create(data_size, 1); + DCHECK(!buffer.isNull()); + if (data_size) // data_size == 0 might mean the data pointer is invalid + memcpy(buffer.data(), data, data_size); + return buffer; +} + +// This function decodes unpadded 'base64url' encoded data, as described in +// RFC4648 (http://www.ietf.org/rfc/rfc4648.txt) Section 5. To do this, first +// change the incoming data to 'base64' encoding by applying the appropriate +// transformation including adding padding if required, and then call a base64 +// decoder. +bool Base64DecodeUrlSafe(const std::string& input, std::string* output) { + std::string base64EncodedText(input); + std::replace(base64EncodedText.begin(), base64EncodedText.end(), '-', '+'); + std::replace(base64EncodedText.begin(), base64EncodedText.end(), '_', '/'); + base64EncodedText.append((4 - base64EncodedText.size() % 4) % 4, '='); + return base::Base64Decode(base64EncodedText, output); +} + +blink::WebCryptoAlgorithm GetInnerHashAlgorithm( + const blink::WebCryptoAlgorithm& algorithm) { + if (algorithm.hmacParams()) + return algorithm.hmacParams()->hash(); + if (algorithm.hmacKeyParams()) + return algorithm.hmacKeyParams()->hash(); + if (algorithm.rsaSsaParams()) + return algorithm.rsaSsaParams()->hash(); + if (algorithm.rsaOaepParams()) + return algorithm.rsaOaepParams()->hash(); + return blink::WebCryptoAlgorithm::createNull(); +} + +blink::WebCryptoAlgorithm CreateAlgorithm(blink::WebCryptoAlgorithmId id) { + return blink::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL); +} + +blink::WebCryptoAlgorithm CreateHmacAlgorithmByHashOutputLen( + unsigned short hash_output_length_bits) { + blink::WebCryptoAlgorithmId hash_id; + switch (hash_output_length_bits) { + case 160: + hash_id = blink::WebCryptoAlgorithmIdSha1; + break; + case 224: + hash_id = blink::WebCryptoAlgorithmIdSha224; + break; + case 256: + hash_id = blink::WebCryptoAlgorithmIdSha256; + break; + case 384: + hash_id = blink::WebCryptoAlgorithmIdSha384; + break; + case 512: + hash_id = blink::WebCryptoAlgorithmIdSha512; + break; + default: + NOTREACHED(); + return blink::WebCryptoAlgorithm::createNull(); + } + return blink::WebCryptoAlgorithm::adoptParamsAndCreate( + blink::WebCryptoAlgorithmIdHmac, + new blink::WebCryptoHmacParams(CreateAlgorithm(hash_id))); +} + +blink::WebCryptoAlgorithm CreateHmacAlgorithmByHashId( + blink::WebCryptoAlgorithmId hash_id) { + DCHECK(IsHashAlgorithm(hash_id)); + return blink::WebCryptoAlgorithm::adoptParamsAndCreate( + blink::WebCryptoAlgorithmIdHmac, + new blink::WebCryptoHmacParams(CreateAlgorithm(hash_id))); +} + +blink::WebCryptoAlgorithm CreateHmacKeyGenAlgorithm( + blink::WebCryptoAlgorithmId hash_id, + unsigned key_length_bytes) { + DCHECK(IsHashAlgorithm(hash_id)); + // key_length_bytes == 0 means unspecified + return blink::WebCryptoAlgorithm::adoptParamsAndCreate( + blink::WebCryptoAlgorithmIdHmac, + new blink::WebCryptoHmacKeyParams( + CreateAlgorithm(hash_id), (key_length_bytes != 0), key_length_bytes)); +} + +blink::WebCryptoAlgorithm CreateRsaSsaAlgorithm( + blink::WebCryptoAlgorithmId hash_id) { + DCHECK(IsHashAlgorithm(hash_id)); + return blink::WebCryptoAlgorithm::adoptParamsAndCreate( + blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, + new blink::WebCryptoRsaSsaParams(CreateAlgorithm(hash_id))); +} + +blink::WebCryptoAlgorithm CreateRsaOaepAlgorithm( + blink::WebCryptoAlgorithmId hash_id) { + DCHECK(IsHashAlgorithm(hash_id)); + return blink::WebCryptoAlgorithm::adoptParamsAndCreate( + blink::WebCryptoAlgorithmIdRsaOaep, + new blink::WebCryptoRsaOaepParams( + CreateAlgorithm(hash_id), false, NULL, 0)); +} + +blink::WebCryptoAlgorithm CreateRsaKeyGenAlgorithm( + blink::WebCryptoAlgorithmId algorithm_id, + unsigned modulus_length, + const std::vector<uint8>& public_exponent) { + DCHECK(algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || + algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || + algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep); + return blink::WebCryptoAlgorithm::adoptParamsAndCreate( + algorithm_id, + new blink::WebCryptoRsaKeyGenParams( + modulus_length, + webcrypto::Uint8VectorStart(public_exponent), + public_exponent.size())); +} + +blink::WebCryptoAlgorithm CreateAesCbcAlgorithm(const std::vector<uint8>& iv) { + return blink::WebCryptoAlgorithm::adoptParamsAndCreate( + blink::WebCryptoAlgorithmIdAesCbc, + new blink::WebCryptoAesCbcParams(Uint8VectorStart(iv), iv.size())); +} + +blink::WebCryptoAlgorithm CreateAesGcmAlgorithm( + const std::vector<uint8>& iv, + const std::vector<uint8>& additional_data, + uint8 tag_length_bytes) { + return blink::WebCryptoAlgorithm::adoptParamsAndCreate( + blink::WebCryptoAlgorithmIdAesCbc, + new blink::WebCryptoAesGcmParams(Uint8VectorStart(iv), + iv.size(), + additional_data.size() != 0, + Uint8VectorStart(additional_data), + additional_data.size(), + tag_length_bytes != 0, + tag_length_bytes)); +} + +blink::WebCryptoAlgorithm CreateAesCbcKeyGenAlgorithm( + unsigned short key_length_bits) { + return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesCbc, + key_length_bits); +} + +blink::WebCryptoAlgorithm CreateAesGcmKeyGenAlgorithm( + unsigned short key_length_bits) { + return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesGcm, + key_length_bits); +} + +} // namespace webcrypto + +} // namespace content diff --git a/chromium/content/renderer/webcrypto/webcrypto_util.h b/chromium/content/renderer/webcrypto/webcrypto_util.h new file mode 100644 index 00000000000..022b3c29fb7 --- /dev/null +++ b/chromium/content/renderer/webcrypto/webcrypto_util.h @@ -0,0 +1,107 @@ +// Copyright (c) 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_RENDERER_WEBCRYPTO_WEBCRYPTO_UTIL_H_ +#define CONTENT_RENDERER_WEBCRYPTO_WEBCRYPTO_UTIL_H_ + +#include <map> +#include <string> +#include <vector> +#include "base/basictypes.h" +#include "content/common/content_export.h" +#include "third_party/WebKit/public/platform/WebArrayBuffer.h" +#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" + +namespace content { + +namespace webcrypto { + +// Returns a pointer to the start of |data|, or NULL if it is empty. This is a +// convenience function for getting the pointer, and should not be used beyond +// the expected lifetime of |data|. +CONTENT_EXPORT const uint8* Uint8VectorStart(const std::vector<uint8>& data); + +// Shrinks a WebArrayBuffer to a new size. +// TODO(eroman): This works by re-allocating a new buffer. It would be better if +// the WebArrayBuffer could just be truncated instead. +void ShrinkBuffer(blink::WebArrayBuffer* buffer, unsigned new_size); + +// Creates a WebArrayBuffer from a uint8 byte array +blink::WebArrayBuffer CreateArrayBuffer(const uint8* data, unsigned data_size); + +// This function decodes unpadded 'base64url' encoded data, as described in +// RFC4648 (http://www.ietf.org/rfc/rfc4648.txt) Section 5. +// In Web Crypto, this type of encoding is only used inside JWK. +bool Base64DecodeUrlSafe(const std::string& input, std::string* output); + +// Returns the "hash" param for an algorithm if it exists, otherwise returns +// a null algorithm. +blink::WebCryptoAlgorithm GetInnerHashAlgorithm( + const blink::WebCryptoAlgorithm& algorithm); + +// Creates a WebCryptoAlgorithm without any parameters. +CONTENT_EXPORT blink::WebCryptoAlgorithm CreateAlgorithm( + blink::WebCryptoAlgorithmId id); + +// Creates an HMAC algorithm whose inner hash algorithm is determined by the +// specified hash output length. It is an error to call this method with an +// unsupported hash output length. +blink::WebCryptoAlgorithm CreateHmacAlgorithmByHashOutputLen( + unsigned short hash_output_length_bits); + +// Creates an HMAC algorithm whose inner hash algorithm is determined by the +// specified algorithm ID. It is an error to call this method with a hash +// algorithm that is not SHA*. +CONTENT_EXPORT blink::WebCryptoAlgorithm CreateHmacAlgorithmByHashId( + blink::WebCryptoAlgorithmId hash_id); + +// Creates an HMAC algorithm whose parameters struct is compatible with key +// generation. It is an error to call this with a hash_id that is not a SHA*. +// The key_length_bytes parameter is optional, with zero meaning unspecified. +CONTENT_EXPORT blink::WebCryptoAlgorithm CreateHmacKeyGenAlgorithm( + blink::WebCryptoAlgorithmId hash_id, + unsigned key_length_bytes); + +// Creates an RSASSA-PKCS1-v1_5 algorithm. It is an error to call this with a +// hash_id that is not a SHA*. +blink::WebCryptoAlgorithm CreateRsaSsaAlgorithm( + blink::WebCryptoAlgorithmId hash_id); + +// Creates an RSA-OAEP algorithm. It is an error to call this with a hash_id +// that is not a SHA*. +blink::WebCryptoAlgorithm CreateRsaOaepAlgorithm( + blink::WebCryptoAlgorithmId hash_id); + +// Creates an RSA algorithm with ID algorithm_id, whose parameters struct is +// compatible with key generation. +CONTENT_EXPORT blink::WebCryptoAlgorithm CreateRsaKeyGenAlgorithm( + blink::WebCryptoAlgorithmId algorithm_id, + unsigned modulus_length, + const std::vector<uint8>& public_exponent); + +// Creates an AES-CBC algorithm. +CONTENT_EXPORT blink::WebCryptoAlgorithm CreateAesCbcAlgorithm( + const std::vector<uint8>& iv); + +// Creates and AES-GCM algorithm. +blink::WebCryptoAlgorithm CreateAesGcmAlgorithm( + const std::vector<uint8>& iv, + const std::vector<uint8>& additional_data, + uint8 tag_length_bytes); + +// Creates an AES-CBC algorithm whose parameters struct is compatible with key +// generation. +CONTENT_EXPORT blink::WebCryptoAlgorithm CreateAesCbcKeyGenAlgorithm( + unsigned short key_length_bits); + +// Creates an AES-GCM algorithm whose parameters struct is compatible with key +// generation. +blink::WebCryptoAlgorithm CreateAesGcmKeyGenAlgorithm( + unsigned short key_length_bits); + +} // namespace webcrypto + +} // namespace content + +#endif // CONTENT_RENDERER_WEBCRYPTO_WEBCRYPTO_UTIL_H_ diff --git a/chromium/content/renderer/webcrypto_impl.cc b/chromium/content/renderer/webcrypto_impl.cc deleted file mode 100644 index b0fc14f5f87..00000000000 --- a/chromium/content/renderer/webcrypto_impl.cc +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 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/renderer/webcrypto_impl.h" - -#include "base/memory/scoped_ptr.h" -#include "third_party/WebKit/public/platform/WebArrayBuffer.h" -#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" -#include "third_party/WebKit/public/platform/WebCryptoKey.h" - -namespace content { - -WebCryptoImpl::WebCryptoImpl() { - Init(); -} - -void WebCryptoImpl::digest( - const WebKit::WebCryptoAlgorithm& algorithm, - const unsigned char* data, - unsigned data_size, - WebKit::WebCryptoResult result) { - WebKit::WebArrayBuffer buffer; - if (!DigestInternal(algorithm, data, data_size, &buffer)) { - result.completeWithError(); - } else { - result.completeWithBuffer(buffer); - } -} - -void WebCryptoImpl::importKey( - WebKit::WebCryptoKeyFormat format, - const unsigned char* key_data, - unsigned key_data_size, - const WebKit::WebCryptoAlgorithm& algorithm, - bool extractable, - WebKit::WebCryptoKeyUsageMask usage_mask, - WebKit::WebCryptoResult result) { - WebKit::WebCryptoKeyType type; - scoped_ptr<WebKit::WebCryptoKeyHandle> handle; - - if (!ImportKeyInternal(format, - key_data, - key_data_size, - algorithm, - usage_mask, - &handle, - &type)) { - result.completeWithError(); - return; - } - - WebKit::WebCryptoKey key( - WebKit::WebCryptoKey::create( - handle.release(), type, extractable, algorithm, usage_mask)); - - result.completeWithKey(key); -} - -void WebCryptoImpl::sign( - const WebKit::WebCryptoAlgorithm& algorithm, - const WebKit::WebCryptoKey& key, - const unsigned char* data, - unsigned data_size, - WebKit::WebCryptoResult result) { - WebKit::WebArrayBuffer buffer; - if (!SignInternal(algorithm, key, data, data_size, &buffer)) { - result.completeWithError(); - } else { - result.completeWithBuffer(buffer); - } -} - -} // namespace content diff --git a/chromium/content/renderer/webcrypto_impl.h b/chromium/content/renderer/webcrypto_impl.h deleted file mode 100644 index 362be613074..00000000000 --- a/chromium/content/renderer/webcrypto_impl.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 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_RENDERER_WEBCRYPTO_IMPL_H_ -#define CONTENT_RENDERER_WEBCRYPTO_IMPL_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "content/common/content_export.h" -#include "third_party/WebKit/public/platform/WebCrypto.h" - -namespace content { - -class CONTENT_EXPORT WebCryptoImpl - : NON_EXPORTED_BASE(public WebKit::WebCrypto) { - public: - WebCryptoImpl(); - - virtual void digest( - const WebKit::WebCryptoAlgorithm& algorithm, - const unsigned char* data, - unsigned data_size, - WebKit::WebCryptoResult result); - virtual void importKey( - WebKit::WebCryptoKeyFormat format, - const unsigned char* key_data, - unsigned key_data_size, - const WebKit::WebCryptoAlgorithm& algorithm, - bool extractable, - WebKit::WebCryptoKeyUsageMask usage_mask, - WebKit::WebCryptoResult result); - virtual void sign( - const WebKit::WebCryptoAlgorithm& algorithm, - const WebKit::WebCryptoKey& key, - const unsigned char* data, - unsigned data_size, - WebKit::WebCryptoResult result); - - protected: - FRIEND_TEST_ALL_PREFIXES(WebCryptoImplTest, DigestSampleSets); - FRIEND_TEST_ALL_PREFIXES(WebCryptoImplTest, HMACSampleSets); - - void Init(); - - bool DigestInternal( - const WebKit::WebCryptoAlgorithm& algorithm, - const unsigned char* data, - unsigned data_size, - WebKit::WebArrayBuffer* buffer); - bool ImportKeyInternal( - WebKit::WebCryptoKeyFormat format, - const unsigned char* key_data, - unsigned key_data_size, - const WebKit::WebCryptoAlgorithm& algorithm, - WebKit::WebCryptoKeyUsageMask usage_mask, - scoped_ptr<WebKit::WebCryptoKeyHandle>* handle, - WebKit::WebCryptoKeyType* type); - bool SignInternal( - const WebKit::WebCryptoAlgorithm& algorithm, - const WebKit::WebCryptoKey& key, - const unsigned char* data, - unsigned data_size, - WebKit::WebArrayBuffer* buffer); - - private: - DISALLOW_COPY_AND_ASSIGN(WebCryptoImpl); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_WEBCRYPTO_IMPL_H_ diff --git a/chromium/content/renderer/webcrypto_impl_nss.cc b/chromium/content/renderer/webcrypto_impl_nss.cc deleted file mode 100644 index caf986fce44..00000000000 --- a/chromium/content/renderer/webcrypto_impl_nss.cc +++ /dev/null @@ -1,252 +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/renderer/webcrypto_impl.h" - -#include <pk11pub.h> -#include <sechash.h> - -#include "base/logging.h" -#include "crypto/nss_util.h" -#include "crypto/scoped_nss_types.h" -#include "third_party/WebKit/public/platform/WebArrayBuffer.h" -#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" -#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" - -namespace content { - -namespace { - -class SymKeyHandle : public WebKit::WebCryptoKeyHandle { - public: - explicit SymKeyHandle(crypto::ScopedPK11SymKey key) { - DCHECK(!key_.get()); - key_ = key.Pass(); - } - - PK11SymKey* key() { return key_.get(); } - - private: - crypto::ScopedPK11SymKey key_; - - DISALLOW_COPY_AND_ASSIGN(SymKeyHandle); -}; - -HASH_HashType WebCryptoAlgorithmToNSSHashType( - const WebKit::WebCryptoAlgorithm& algorithm) { - switch (algorithm.id()) { - case WebKit::WebCryptoAlgorithmIdSha1: - return HASH_AlgSHA1; - case WebKit::WebCryptoAlgorithmIdSha224: - return HASH_AlgSHA224; - case WebKit::WebCryptoAlgorithmIdSha256: - return HASH_AlgSHA256; - case WebKit::WebCryptoAlgorithmIdSha384: - return HASH_AlgSHA384; - case WebKit::WebCryptoAlgorithmIdSha512: - return HASH_AlgSHA512; - default: - // Not a digest algorithm. - return HASH_AlgNULL; - } -} - -CK_MECHANISM_TYPE WebCryptoAlgorithmToHMACMechanism( - const WebKit::WebCryptoAlgorithm& algorithm) { - switch (algorithm.id()) { - case WebKit::WebCryptoAlgorithmIdSha1: - return CKM_SHA_1_HMAC; - case WebKit::WebCryptoAlgorithmIdSha256: - return CKM_SHA256_HMAC; - default: - // Not a supported algorithm. - return CKM_INVALID_MECHANISM; - } -} - -} // namespace - -void WebCryptoImpl::Init() { - crypto::EnsureNSSInit(); -} - -bool WebCryptoImpl::DigestInternal( - const WebKit::WebCryptoAlgorithm& algorithm, - const unsigned char* data, - unsigned data_size, - WebKit::WebArrayBuffer* buffer) { - HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); - if (hash_type == HASH_AlgNULL) { - return false; - } - - HASHContext* context = HASH_Create(hash_type); - if (!context) { - return false; - } - - HASH_Begin(context); - - HASH_Update(context, data, data_size); - - unsigned hash_result_length = HASH_ResultLenContext(context); - DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX)); - - *buffer = WebKit::WebArrayBuffer::create(hash_result_length, 1); - - unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data()); - - unsigned result_length = 0; - HASH_End(context, digest, &result_length, hash_result_length); - - HASH_Destroy(context); - - return result_length == hash_result_length; -} - -bool WebCryptoImpl::ImportKeyInternal( - WebKit::WebCryptoKeyFormat format, - const unsigned char* key_data, - unsigned key_data_size, - const WebKit::WebCryptoAlgorithm& algorithm, - WebKit::WebCryptoKeyUsageMask usage_mask, - scoped_ptr<WebKit::WebCryptoKeyHandle>* handle, - WebKit::WebCryptoKeyType* type) { - switch (algorithm.id()) { - case WebKit::WebCryptoAlgorithmIdHmac: - *type = WebKit::WebCryptoKeyTypeSecret; - break; - // TODO(bryaneyler): Support more key types. - default: - return false; - } - - // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys. - // Currently only supporting symmetric. - CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; - // Flags are verified at the Blink layer; here the flags are set to all - // possible operations for this key type. - CK_FLAGS flags = 0; - - switch(algorithm.id()) { - case WebKit::WebCryptoAlgorithmIdHmac: { - const WebKit::WebCryptoHmacParams* params = algorithm.hmacParams(); - if (!params) { - return false; - } - - mechanism = WebCryptoAlgorithmToHMACMechanism(params->hash()); - if (mechanism == CKM_INVALID_MECHANISM) { - return false; - } - - flags |= CKF_SIGN | CKF_VERIFY; - - break; - } - default: - return false; - } - - DCHECK_NE(CKM_INVALID_MECHANISM, mechanism); - DCHECK_NE(0ul, flags); - - SECItem key_item = { siBuffer, NULL, 0 }; - - switch (format) { - case WebKit::WebCryptoKeyFormatRaw: - key_item.data = const_cast<unsigned char*>(key_data); - key_item.len = key_data_size; - break; - // TODO(bryaneyler): Handle additional formats. - default: - return false; - } - - crypto::ScopedPK11SymKey pk11_sym_key( - PK11_ImportSymKeyWithFlags(PK11_GetInternalSlot(), - mechanism, - PK11_OriginUnwrap, - CKA_FLAGS_ONLY, - &key_item, - flags, - false, - NULL)); - if (!pk11_sym_key.get()) { - NOTREACHED(); - return false; - } - - scoped_ptr<SymKeyHandle> sym_key(new SymKeyHandle(pk11_sym_key.Pass())); - *handle = sym_key.Pass(); - - return true; -} - -bool WebCryptoImpl::SignInternal( - const WebKit::WebCryptoAlgorithm& algorithm, - const WebKit::WebCryptoKey& key, - const unsigned char* data, - unsigned data_size, - WebKit::WebArrayBuffer* buffer) { - WebKit::WebArrayBuffer result; - - switch (algorithm.id()) { - case WebKit::WebCryptoAlgorithmIdHmac: { - const WebKit::WebCryptoHmacParams* params = algorithm.hmacParams(); - if (!params) { - return false; - } - - SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); - - DCHECK_EQ(PK11_GetMechanism(sym_key->key()), - WebCryptoAlgorithmToHMACMechanism(params->hash())); - DCHECK_NE(0, key.usages() & WebKit::WebCryptoKeyUsageSign); - - SECItem param_item = { siBuffer, NULL, 0 }; - SECItem data_item = { - siBuffer, - const_cast<unsigned char*>(data), - data_size - }; - // First call is to figure out the length. - SECItem signature_item = { siBuffer, NULL, 0 }; - - if (PK11_SignWithSymKey(sym_key->key(), - PK11_GetMechanism(sym_key->key()), - ¶m_item, - &signature_item, - &data_item) != SECSuccess) { - NOTREACHED(); - return false; - } - - DCHECK_NE(0u, signature_item.len); - - result = WebKit::WebArrayBuffer::create(signature_item.len, 1); - signature_item.data = reinterpret_cast<unsigned char*>(result.data()); - - if (PK11_SignWithSymKey(sym_key->key(), - PK11_GetMechanism(sym_key->key()), - ¶m_item, - &signature_item, - &data_item) != SECSuccess) { - NOTREACHED(); - return false; - } - - DCHECK_EQ(result.byteLength(), signature_item.len); - - break; - } - default: - return false; - } - - *buffer = result; - return true; -} - -} // namespace content diff --git a/chromium/content/renderer/webcrypto_impl_openssl.cc b/chromium/content/renderer/webcrypto_impl_openssl.cc deleted file mode 100644 index 9aa1a425301..00000000000 --- a/chromium/content/renderer/webcrypto_impl_openssl.cc +++ /dev/null @@ -1,46 +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/renderer/webcrypto_impl.h" - -namespace content { - -void WebCryptoImpl::Init() { -} - -bool WebCryptoImpl::DigestInternal( - const WebKit::WebCryptoAlgorithm& algorithm, - const unsigned char* data, - unsigned data_size, - WebKit::WebArrayBuffer* buffer) { - // TODO(bryaneyler): Placeholder for OpenSSL implementation. - // Issue http://crbug.com/267888. - return false; -} - -bool WebCryptoImpl::ImportKeyInternal( - WebKit::WebCryptoKeyFormat format, - const unsigned char* key_data, - unsigned key_data_size, - const WebKit::WebCryptoAlgorithm& algorithm, - WebKit::WebCryptoKeyUsageMask usage_mask, - scoped_ptr<WebKit::WebCryptoKeyHandle>* handle, - WebKit::WebCryptoKeyType* type) { - // TODO(bryaneyler): Placeholder for OpenSSL implementation. - // Issue http://crbug.com/267888. - return false; -} - -bool WebCryptoImpl::SignInternal( - const WebKit::WebCryptoAlgorithm& algorithm, - const WebKit::WebCryptoKey& key, - const unsigned char* data, - unsigned data_size, - WebKit::WebArrayBuffer* buffer) { - // TODO(bryaneyler): Placeholder for OpenSSL implementation. - // Issue http://crbug.com/267888. - return false; -} - -} // namespace content diff --git a/chromium/content/renderer/webcrypto_impl_unittest.cc b/chromium/content/renderer/webcrypto_impl_unittest.cc deleted file mode 100644 index 8a9a1004b86..00000000000 --- a/chromium/content/renderer/webcrypto_impl_unittest.cc +++ /dev/null @@ -1,277 +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 "webcrypto_impl.h" - -#include "base/basictypes.h" -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/strings/string_number_conversions.h" -#include "content/public/renderer/content_renderer_client.h" -#include "content/renderer/renderer_webkitplatformsupport_impl.h" -#include "content/renderer/webcrypto_impl.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/WebKit/public/platform/WebArrayBuffer.h" -#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" -#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" - -namespace content { - -const WebKit::WebCryptoAlgorithmId kAlgorithmIds[] = { - WebKit::WebCryptoAlgorithmIdSha1, - WebKit::WebCryptoAlgorithmIdSha224, - WebKit::WebCryptoAlgorithmIdSha256, - WebKit::WebCryptoAlgorithmIdSha384, - WebKit::WebCryptoAlgorithmIdSha512 -}; - -class WebCryptoImplTest : public testing::Test, public WebCryptoImpl { -}; - -TEST_F(WebCryptoImplTest, DigestSampleSets) { - // The results are stored here in hex format for readability. - // - // TODO(bryaneyler): Eventually, all these sample test sets should be replaced - // with the sets here: http://csrc.nist.gov/groups/STM/cavp/index.html#03 - struct { - const char* input; - unsigned input_length; - const char* hex_result[arraysize(kAlgorithmIds)]; - } input_set[] = { - { - "", 0, - { - // echo -n "" | sha1sum - "da39a3ee5e6b4b0d3255bfef95601890afd80709", - // echo -n "" | sha224sum - "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", - // echo -n "" | sha256sum - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - // echo -n "" | sha384sum - "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274e" - "debfe76f65fbd51ad2f14898b95b", - // echo -n "" | sha512sum - "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0" - "d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", - }, - }, - { - "\000", 1, - { - // echo -n -e "\000" | sha1sum - "5ba93c9db0cff93f52b521d7420e43f6eda2784f", - // echo -n -e "\000" | sha224sum - "fff9292b4201617bdc4d3053fce02734166a683d7d858a7f5f59b073", - // echo -n -e "\000" | sha256sum - "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", - // echo -n -e "\000" | sha384sum - "bec021b4f368e3069134e012c2b4307083d3a9bdd206e24e5f0d86e13d6636655933" - "ec2b413465966817a9c208a11717", - // echo -n -e "\000" | sha512sum - "b8244d028981d693af7b456af8efa4cad63d282e19ff14942c246e50d9351d22704a" - "802a71c3580b6370de4ceb293c324a8423342557d4e5c38438f0e36910ee", - }, - }, - { - "\000\001\002\003\004\005", 6, - { - // echo -n -e "\000\001\002\003\004\005" | sha1sum - "868460d98d09d8bbb93d7b6cdd15cc7fbec676b9", - // echo -n -e "\000\001\002\003\004\005" | sha224sum - "7d92e7f1cad1818ed1d13ab41f04ebabfe1fef6bb4cbeebac34c29bc", - // echo -n -e "\000\001\002\003\004\005" | sha256sum - "17e88db187afd62c16e5debf3e6527cd006bc012bc90b51a810cd80c2d511f43", - // echo -n -e "\000\001\002\003\004\005" | sha384sum - "79f4738706fce9650ac60266675c3cd07298b09923850d525604d040e6e448adc7dc" - "22780d7e1b95bfeaa86a678e4552", - // echo -n -e "\000\001\002\003\004\005" | sha512sum - "2f3831bccc94cf061bcfa5f8c23c1429d26e3bc6b76edad93d9025cb91c903af6cf9" - "c935dc37193c04c2c66e7d9de17c358284418218afea2160147aaa912f4c", - }, - }, - }; - - for (size_t id_index = 0; id_index < arraysize(kAlgorithmIds); id_index++) { - SCOPED_TRACE(id_index); - - WebKit::WebCryptoAlgorithm algorithm( - WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( - kAlgorithmIds[id_index], NULL)); - - for (size_t set_index = 0; - set_index < ARRAYSIZE_UNSAFE(input_set); - set_index++) { - SCOPED_TRACE(set_index); - - WebKit::WebArrayBuffer array_buffer; - - WebCryptoImpl crypto; - EXPECT_TRUE( - crypto.DigestInternal( - algorithm, - reinterpret_cast<const unsigned char*>( - input_set[set_index].input), - input_set[set_index].input_length, - &array_buffer)); - - // Ignore case, it's checking the hex value. - EXPECT_STRCASEEQ( - input_set[set_index].hex_result[id_index], - base::HexEncode( - array_buffer.data(), array_buffer.byteLength()).c_str()); - } - } -} - -TEST_F(WebCryptoImplTest, HMACSampleSets) { - struct { - WebKit::WebCryptoAlgorithmId algorithm; - const char* key; - const char* message; - const char* mac; - } input_set[] = { - // Empty sets. Result generated via OpenSSL commandline tool. These - // particular results are also posted on the Wikipedia page examples: - // http://en.wikipedia.org/wiki/Hash-based_message_authentication_code - { - WebKit::WebCryptoAlgorithmIdSha1, - "", - "", - // openssl dgst -sha1 -hmac "" < /dev/null - "fbdb1d1b18aa6c08324b7d64b71fb76370690e1d", - }, - { - WebKit::WebCryptoAlgorithmIdSha256, - "", - "", - // openssl dgst -sha256 -hmac "" < /dev/null - "b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad", - }, - // For this data, see http://csrc.nist.gov/groups/STM/cavp/index.html#07 - // Download: - // http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip - // L=20 set 45 - { - WebKit::WebCryptoAlgorithmIdSha1, - // key - "59785928d72516e31272", - // message - "a3ce8899df1022e8d2d539b47bf0e309c66f84095e21438ec355bf119ce5fdcb4e73a6" - "19cdf36f25b369d8c38ff419997f0c59830108223606e31223483fd39edeaa4d3f0d21" - "198862d239c9fd26074130ff6c86493f5227ab895c8f244bd42c7afce5d147a20a5907" - "98c68e708e964902d124dadecdbda9dbd0051ed710e9bf", - // mac - "3c8162589aafaee024fc9a5ca50dd2336fe3eb28", - }, - // L=20 set 299 - { - WebKit::WebCryptoAlgorithmIdSha1, - // key - "ceb9aedf8d6efcf0ae52bea0fa99a9e26ae81bacea0cff4d5eecf201e3bca3c3577480" - "621b818fd717ba99d6ff958ea3d59b2527b019c343bb199e648090225867d994607962" - "f5866aa62930d75b58f6", - // message - "99958aa459604657c7bf6e4cdfcc8785f0abf06ffe636b5b64ecd931bd8a4563055924" - "21fc28dbcccb8a82acea2be8e54161d7a78e0399a6067ebaca3f2510274dc9f92f2c8a" - "e4265eec13d7d42e9f8612d7bc258f913ecb5a3a5c610339b49fb90e9037b02d684fc6" - "0da835657cb24eab352750c8b463b1a8494660d36c3ab2", - // mac - "4ac41ab89f625c60125ed65ffa958c6b490ea670", - }, - // L=32, set 30 - { - WebKit::WebCryptoAlgorithmIdSha256, - // key - "9779d9120642797f1747025d5b22b7ac607cab08e1758f2f3a46c8be1e25c53b8c6a8f" - "58ffefa176", - // message - "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a" - "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92" - "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f" - "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e", - // mac - "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b", - }, - // L=32, set 224 - { - WebKit::WebCryptoAlgorithmIdSha256, - // key - "4b7ab133efe99e02fc89a28409ee187d579e774f4cba6fc223e13504e3511bef8d4f63" - "8b9aca55d4a43b8fbd64cf9d74dcc8c9e8d52034898c70264ea911a3fd70813fa73b08" - "3371289b", - // message - "138efc832c64513d11b9873c6fd4d8a65dbf367092a826ddd587d141b401580b798c69" - "025ad510cff05fcfbceb6cf0bb03201aaa32e423d5200925bddfadd418d8e30e18050e" - "b4f0618eb9959d9f78c1157d4b3e02cd5961f138afd57459939917d9144c95d8e6a94c" - "8f6d4eef3418c17b1ef0b46c2a7188305d9811dccb3d99", - // mac - "4f1ee7cb36c58803a8721d4ac8c4cf8cae5d8832392eed2a96dc59694252801b", - }, - }; - - for (size_t index = 0; index < ARRAYSIZE_UNSAFE(input_set); index++) { - SCOPED_TRACE(index); - - WebKit::WebCryptoAlgorithm hash_algorithm( - WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( - input_set[index].algorithm, NULL)); - - scoped_ptr<WebKit::WebCryptoHmacParams> hmac_params( - new WebKit::WebCryptoHmacParams(hash_algorithm)); - - WebKit::WebCryptoAlgorithm hmac_algorithm( - WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( - WebKit::WebCryptoAlgorithmIdHmac, hmac_params.release())); - - WebKit::WebCryptoKeyType type; - scoped_ptr<WebKit::WebCryptoKeyHandle> handle; - - std::vector<uint8> key_raw; - base::HexStringToBytes(input_set[index].key, &key_raw); - - WebCryptoImpl crypto; - - EXPECT_TRUE( - crypto.ImportKeyInternal( - WebKit::WebCryptoKeyFormatRaw, - key_raw.data(), - key_raw.size(), - hmac_algorithm, - WebKit::WebCryptoKeyUsageSign, - &handle, - &type)); - - EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, type); - ASSERT_TRUE(handle.get()); - - WebKit::WebCryptoKey crypto_key = - WebKit::WebCryptoKey::create( - handle.release(), - type, - false, - hmac_algorithm, - WebKit::WebCryptoKeyUsageSign); - - std::vector<uint8> message_raw; - base::HexStringToBytes(input_set[index].message, &message_raw); - - WebKit::WebArrayBuffer array_buffer; - - EXPECT_TRUE( - crypto.SignInternal( - hmac_algorithm, - crypto_key, - message_raw.data(), - message_raw.size(), - &array_buffer)); - - // Ignore case, it's checking the hex value. - EXPECT_STRCASEEQ( - input_set[index].mac, - base::HexEncode( - array_buffer.data(), array_buffer.byteLength()).c_str()); - } -} - -} // namespace content diff --git a/chromium/content/renderer/webpublicsuffixlist_impl.cc b/chromium/content/renderer/webpublicsuffixlist_impl.cc new file mode 100644 index 00000000000..e1e00c22be2 --- /dev/null +++ b/chromium/content/renderer/webpublicsuffixlist_impl.cc @@ -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. + +#include "content/renderer/webpublicsuffixlist_impl.h" + +#include "net/base/registry_controlled_domains/registry_controlled_domain.h" + +namespace content { + +WebPublicSuffixListImpl::~WebPublicSuffixListImpl() { +} + +size_t WebPublicSuffixListImpl::getPublicSuffixLength( + const blink::WebString& host) { + size_t result = net::registry_controlled_domains::GetRegistryLength( + host.utf8(), + net::registry_controlled_domains::INCLUDE_UNKNOWN_REGISTRIES, + net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); + return result ? result : host.length(); +} + +} // namespace content diff --git a/chromium/content/renderer/webpublicsuffixlist_impl.h b/chromium/content/renderer/webpublicsuffixlist_impl.h new file mode 100644 index 00000000000..65fcc65e39b --- /dev/null +++ b/chromium/content/renderer/webpublicsuffixlist_impl.h @@ -0,0 +1,22 @@ +// 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_RENDERER_WEBPUBLICSUFFIXLIST_IMPL_H_ +#define CONTENT_RENDERER_WEBPUBLICSUFFIXLIST_IMPL_H_ + +#include "base/compiler_specific.h" +#include "third_party/WebKit/public/platform/WebPublicSuffixList.h" + +namespace content { + +class WebPublicSuffixListImpl : public blink::WebPublicSuffixList { + public: + // WebPublicSuffixList methods: + virtual size_t getPublicSuffixLength(const blink::WebString& host); + virtual ~WebPublicSuffixListImpl(); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_WEBPUBLICSUFFIXLIST_IMPL_H_ diff --git a/chromium/content/renderer/websharedworker_proxy.cc b/chromium/content/renderer/websharedworker_proxy.cc index 190a35c59cf..815568ea793 100644 --- a/chromium/content/renderer/websharedworker_proxy.cc +++ b/chromium/content/renderer/websharedworker_proxy.cc @@ -51,11 +51,11 @@ void WebSharedWorkerProxy::Disconnect() { void WebSharedWorkerProxy::CreateWorkerContext( const GURL& script_url, bool is_shared, - const string16& name, - const string16& user_agent, - const string16& source_code, - const string16& content_security_policy, - WebKit::WebContentSecurityPolicyType policy_type, + const base::string16& name, + const base::string16& user_agent, + const base::string16& source_code, + const base::string16& content_security_policy, + blink::WebContentSecurityPolicyType policy_type, int pending_route_id, int64 script_resource_appcache_id) { DCHECK(route_id_ == MSG_ROUTING_NONE); @@ -121,12 +121,12 @@ bool WebSharedWorkerProxy::isStarted() { } void WebSharedWorkerProxy::startWorkerContext( - const WebKit::WebURL& script_url, - const WebKit::WebString& name, - const WebKit::WebString& user_agent, - const WebKit::WebString& source_code, - const WebKit::WebString& content_security_policy, - WebKit::WebContentSecurityPolicyType policy_type, + const blink::WebURL& script_url, + const blink::WebString& name, + const blink::WebString& user_agent, + const blink::WebString& source_code, + const blink::WebString& content_security_policy, + blink::WebContentSecurityPolicyType policy_type, long long script_resource_appcache_id) { DCHECK(!isStarted()); CreateWorkerContext( @@ -134,17 +134,7 @@ void WebSharedWorkerProxy::startWorkerContext( policy_type, pending_route_id_, script_resource_appcache_id); } -void WebSharedWorkerProxy::terminateWorkerContext() { - // This API should only be invoked from worker context. - NOTREACHED(); -} - -void WebSharedWorkerProxy::clientDestroyed() { - // This API should only be invoked from worker context. - NOTREACHED(); -} - -void WebSharedWorkerProxy::connect(WebKit::WebMessagePortChannel* channel, +void WebSharedWorkerProxy::connect(blink::WebMessagePortChannel* channel, ConnectListener* listener) { WebMessagePortChannelImpl* webchannel = static_cast<WebMessagePortChannelImpl*>(channel); diff --git a/chromium/content/renderer/websharedworker_proxy.h b/chromium/content/renderer/websharedworker_proxy.h index 75c7b5505ed..a7335b3d01d 100644 --- a/chromium/content/renderer/websharedworker_proxy.h +++ b/chromium/content/renderer/websharedworker_proxy.h @@ -11,7 +11,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "ipc/ipc_listener.h" -#include "third_party/WebKit/public/web/WebSharedWorker.h" +#include "third_party/WebKit/public/web/WebSharedWorkerConnector.h" #include "url/gurl.h" namespace content { @@ -23,7 +23,7 @@ class ChildThread; // thread. Once the connect event has been sent, all future communication will // happen via the WebMessagePortChannel, and the WebSharedWorker instance will // be freed. -class WebSharedWorkerProxy : public WebKit::WebSharedWorker, +class WebSharedWorkerProxy : public blink::WebSharedWorkerConnector, private IPC::Listener { public: // If the worker not loaded yet, route_id == MSG_ROUTING_NONE @@ -36,21 +36,18 @@ class WebSharedWorkerProxy : public WebKit::WebSharedWorker, // Implementations of WebSharedWorker APIs virtual bool isStarted(); - virtual void connect(WebKit::WebMessagePortChannel* channel, + virtual void connect(blink::WebMessagePortChannel* channel, ConnectListener* listener); virtual void startWorkerContext( - const WebKit::WebURL& script_url, - const WebKit::WebString& name, - const WebKit::WebString& user_agent, - const WebKit::WebString& source_code, - const WebKit::WebString& content_security_policy, - WebKit::WebContentSecurityPolicyType policy_type, + const blink::WebURL& script_url, + const blink::WebString& name, + const blink::WebString& user_agent, + const blink::WebString& source_code, + const blink::WebString& content_security_policy, + blink::WebContentSecurityPolicyType policy_type, long long script_resource_appcache_id); - virtual void terminateWorkerContext(); - virtual void clientDestroyed(); - private: // IPC::Listener implementation. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; @@ -73,11 +70,11 @@ class WebSharedWorkerProxy : public WebKit::WebSharedWorker, void CreateWorkerContext(const GURL& script_url, bool is_shared, - const string16& name, - const string16& user_agent, - const string16& source_code, - const string16& content_security_policy, - WebKit::WebContentSecurityPolicyType policy_type, + const base::string16& name, + const base::string16& user_agent, + const base::string16& source_code, + const base::string16& content_security_policy, + blink::WebContentSecurityPolicyType policy_type, int pending_route_id, int64 script_resource_appcache_id); void OnWorkerCreated(); diff --git a/chromium/content/renderer/websharedworkerrepository_impl.cc b/chromium/content/renderer/websharedworkerrepository_impl.cc deleted file mode 100644 index d914cf7b3f0..00000000000 --- a/chromium/content/renderer/websharedworkerrepository_impl.cc +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2009 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/renderer/websharedworkerrepository_impl.h" - -#include "content/child/child_thread.h" -#include "content/common/view_messages.h" -#include "content/renderer/websharedworker_proxy.h" - -namespace content { - -WebSharedWorkerRepositoryImpl::WebSharedWorkerRepositoryImpl() {} - -WebSharedWorkerRepositoryImpl::~WebSharedWorkerRepositoryImpl() {} - -void WebSharedWorkerRepositoryImpl::addSharedWorker( - WebKit::WebSharedWorker* worker, DocumentID document) { - shared_worker_parents_.insert(document); -} - -void WebSharedWorkerRepositoryImpl::documentDetached(DocumentID document) { - DocumentSet::iterator iter = shared_worker_parents_.find(document); - if (iter != shared_worker_parents_.end()) { - // Notify the browser process that the document has shut down. - ChildThread::current()->Send(new ViewHostMsg_DocumentDetached(document)); - shared_worker_parents_.erase(iter); - } -} - -bool WebSharedWorkerRepositoryImpl::hasSharedWorkers(DocumentID document) { - return shared_worker_parents_.find(document) != shared_worker_parents_.end(); -} - -} // namespace content diff --git a/chromium/content/renderer/websharedworkerrepository_impl.h b/chromium/content/renderer/websharedworkerrepository_impl.h deleted file mode 100644 index ebe2a22dcdb..00000000000 --- a/chromium/content/renderer/websharedworkerrepository_impl.h +++ /dev/null @@ -1,37 +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_RENDERER_WEBSHAREDWORKERREPOSITORY_IMPL_H_ -#define CONTENT_RENDERER_WEBSHAREDWORKERREPOSITORY_IMPL_H_ - -#include "base/containers/hash_tables.h" -#include "third_party/WebKit/public/web/WebSharedWorkerRepository.h" - -namespace WebKit { -class WebSharedWorker; -} - -namespace content { - -class WebSharedWorkerRepositoryImpl : public WebKit::WebSharedWorkerRepository { - public: - WebSharedWorkerRepositoryImpl(); - virtual ~WebSharedWorkerRepositoryImpl(); - - virtual void addSharedWorker(WebKit::WebSharedWorker*, DocumentID document); - virtual void documentDetached(DocumentID document); - - // Returns true if the document has created a SharedWorker (used by the - // WebKit code to determine if the document can be suspended). - virtual bool hasSharedWorkers(DocumentID document); - - private: - // The set of documents that have created a SharedWorker. - typedef base::hash_set<DocumentID> DocumentSet; - DocumentSet shared_worker_parents_; -}; - -} // namespace content - -#endif // CONTENT_RENDERER_WEBSHAREDWORKERREPOSITORY_IMPL_H_ |