зеркало из https://github.com/mozilla/gecko-dev.git
Merge last green changeset from mozilla-inbound to mozilla-central
This commit is contained in:
Коммит
82f7b47d00
|
@ -355,8 +355,10 @@ let TabView = {
|
|||
if (!tabItem)
|
||||
return;
|
||||
|
||||
// Switch to the new tab
|
||||
// Switch to the new tab, and close the old group if it's now empty.
|
||||
let oldGroupItem = groupItems.getActiveGroupItem();
|
||||
window.gBrowser.selectedTab = tabItem.tab;
|
||||
oldGroupItem.closeIfEmpty();
|
||||
});
|
||||
}
|
||||
}, true);
|
||||
|
|
|
@ -282,6 +282,11 @@ Drag.prototype = {
|
|||
Trenches.hideGuides();
|
||||
this.item.isDragging = false;
|
||||
|
||||
if (this.parent && this.parent != this.item.parent &&
|
||||
this.parent.isEmpty()) {
|
||||
this.parent.close();
|
||||
}
|
||||
|
||||
if (this.parent && this.parent.expanded)
|
||||
this.parent.arrange();
|
||||
|
||||
|
|
|
@ -649,7 +649,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
// Options:
|
||||
// immediately - (bool) if true, no animation will be used
|
||||
close: function GroupItem_close(options) {
|
||||
this.removeAll();
|
||||
this.removeAll({dontClose: true});
|
||||
GroupItems.unregister(this);
|
||||
|
||||
// remove unfreeze event handlers, if item size is frozen
|
||||
|
@ -723,6 +723,21 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
UI.setActive(closestTabItem);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: closeIfEmpty
|
||||
// Closes the group if it's empty, has no title, is closable, and
|
||||
// autoclose is enabled (see pauseAutoclose()). Returns true if the close
|
||||
// occurred and false otherwise.
|
||||
closeIfEmpty: function() {
|
||||
if (!this._children.length && !this.getTitle() &&
|
||||
!GroupItems.getUnclosableGroupItemId() &&
|
||||
!GroupItems._autoclosePaused) {
|
||||
this.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: _unhide
|
||||
// Shows the hidden group.
|
||||
|
@ -996,7 +1011,8 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
item.addSubscriber(this, "close", function() {
|
||||
let count = self._children.length;
|
||||
let dontArrange = self.expanded || !self.shouldStack(count);
|
||||
self.remove(item, {dontArrange: dontArrange});
|
||||
let dontClose = !item.closedManually && gBrowser._numPinnedTabs > 0;
|
||||
self.remove(item, {dontArrange: dontArrange, dontClose: dontClose});
|
||||
|
||||
if (dontArrange)
|
||||
self._freezeItemSize(count);
|
||||
|
@ -1043,6 +1059,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
//
|
||||
// Possible options:
|
||||
// dontArrange - don't rearrange the remaining items
|
||||
// dontClose - don't close the group even if it normally would
|
||||
// immediately - don't animate
|
||||
remove: function GroupItem_remove(a, options) {
|
||||
try {
|
||||
|
@ -1091,7 +1108,15 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
if (typeof item.setResizable == 'function')
|
||||
item.setResizable(true, options.immediately);
|
||||
|
||||
if (!options.dontArrange) {
|
||||
// if a blank tab is selected while restoring a tab the blank tab gets
|
||||
// removed. we need to keep the group alive for the restored tab.
|
||||
if (item.tab._tabViewTabIsRemovedAfterRestore)
|
||||
options.dontClose = true;
|
||||
|
||||
let closed = options.dontClose ? false : this.closeIfEmpty();
|
||||
if (closed)
|
||||
this._makeClosestTabActive();
|
||||
else if (!options.dontArrange) {
|
||||
this.arrange({animate: !options.immediately});
|
||||
this._unfreezeItemSize({dontArrange: true});
|
||||
}
|
||||
|
@ -1706,7 +1731,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
|||
self.arrange();
|
||||
var groupItem = drag.info.item.parent;
|
||||
if (groupItem)
|
||||
groupItem.remove(drag.info.$el);
|
||||
groupItem.remove(drag.info.$el, {dontClose: true});
|
||||
iQ(this.container).removeClass("acceptsDrop");
|
||||
}
|
||||
|
||||
|
@ -1840,6 +1865,7 @@ let GroupItems = {
|
|||
_arrangesPending: [],
|
||||
_removingHiddenGroups: false,
|
||||
_delayedModUpdates: [],
|
||||
_autoclosePaused: false,
|
||||
minGroupHeight: 110,
|
||||
minGroupWidth: 125,
|
||||
|
||||
|
@ -2611,5 +2637,21 @@ let GroupItems = {
|
|||
return new Point(
|
||||
Math.max(size.x, GroupItems.minGroupWidth),
|
||||
Math.max(size.y, GroupItems.minGroupHeight));
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: pauseAutoclose()
|
||||
// Temporarily disable the behavior that closes groups when they become
|
||||
// empty. This is used when entering private browsing, to avoid trashing the
|
||||
// user's groups while private browsing is shuffling things around.
|
||||
pauseAutoclose: function GroupItems_pauseAutoclose() {
|
||||
this._autoclosePaused = true;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: unpauseAutoclose()
|
||||
// Re-enables the auto-close behavior.
|
||||
resumeAutoclose: function GroupItems_resumeAutoclose() {
|
||||
this._autoclosePaused = false;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -179,7 +179,7 @@ Item.prototype = {
|
|||
out: function() {
|
||||
let groupItem = drag.info.item.parent;
|
||||
if (groupItem)
|
||||
groupItem.remove(drag.info.$el);
|
||||
groupItem.remove(drag.info.$el, {dontClose: true});
|
||||
iQ(this.container).removeClass("acceptsDrop");
|
||||
},
|
||||
drop: function(event) {
|
||||
|
|
|
@ -523,9 +523,16 @@ let UI = {
|
|||
|
||||
Storage.saveVisibilityData(gWindow, "true");
|
||||
|
||||
// Close the active group if it was empty. This will happen when the
|
||||
// user returns to Panorama after looking at an app tab, having
|
||||
// closed all other tabs. (If the user is looking at an orphan tab, then
|
||||
// there is no active group for the purposes of this check.)
|
||||
let activeGroupItem = null;
|
||||
if (!UI.getActiveOrphanTab())
|
||||
if (!UI.getActiveOrphanTab()) {
|
||||
activeGroupItem = GroupItems.getActiveGroupItem();
|
||||
if (activeGroupItem && activeGroupItem.closeIfEmpty())
|
||||
activeGroupItem = null;
|
||||
}
|
||||
|
||||
if (zoomOut && currentTab && currentTab._tabViewTabItem) {
|
||||
item = currentTab._tabViewTabItem;
|
||||
|
@ -631,8 +638,10 @@ let UI = {
|
|||
// Pauses the storage activity that conflicts with sessionstore updates and
|
||||
// private browsing mode switches. Calls can be nested.
|
||||
storageBusy: function UI_storageBusy() {
|
||||
if (!this._storageBusyCount)
|
||||
if (!this._storageBusyCount) {
|
||||
TabItems.pauseReconnecting();
|
||||
GroupItems.pauseAutoclose();
|
||||
}
|
||||
|
||||
this._storageBusyCount++;
|
||||
},
|
||||
|
@ -650,6 +659,7 @@ let UI = {
|
|||
|
||||
TabItems.resumeReconnecting();
|
||||
GroupItems._updateTabBar();
|
||||
GroupItems.resumeAutoclose();
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -130,7 +130,4 @@ function test() {
|
|||
is(gBrowser.tabs.length, 1, "sanity check that it matches");
|
||||
is(gBrowser.selectedTab, origTab, "got the orig tab");
|
||||
is(origTab.hidden, false, "and it's not hidden -- visible!");
|
||||
|
||||
if (tabViewWindow)
|
||||
tabViewWindow.GroupItems.groupItems[0].close();
|
||||
}
|
||||
|
|
|
@ -72,6 +72,8 @@ function testGroupSwitch(contentWindow, groupItemOne, groupItemTwo) {
|
|||
"The currently selected tab should be the second tab in the groupItemOne");
|
||||
|
||||
// cleanup.
|
||||
gBrowser.removeTab(groupItemTwo.getChild(0).tab);
|
||||
gBrowser.removeTab(newTabOne);
|
||||
closeGroupItem(groupItemTwo, finish);
|
||||
|
||||
finish();
|
||||
}
|
||||
|
|
|
@ -58,17 +58,15 @@ function onTabViewWindowLoaded() {
|
|||
gBrowser.unpinTab(appXulTab);
|
||||
gBrowser.removeTab(appXulTab);
|
||||
|
||||
ok(!groupItem.getChildren().length, "the second group is empty");
|
||||
ok(groupItem.closeIfEmpty(), "the second group was empty");
|
||||
|
||||
closeGroupItem(groupItem, function () {
|
||||
// Verify ending state
|
||||
is(gBrowser.tabs.length, 1, "we finish with one tab");
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"we finish with one group");
|
||||
ok(!TabView.isVisible(), "we finish with Tab View hidden");
|
||||
|
||||
finish();
|
||||
});
|
||||
// Verify ending state
|
||||
is(gBrowser.tabs.length, 1, "we finish with one tab");
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"we finish with one group");
|
||||
ok(!TabView.isVisible(), "we finish with Tab View hidden");
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
|
|
@ -28,15 +28,12 @@ function test() {
|
|||
EventUtils.synthesizeMouseAtCenter(targetTab, {type: 'mousemove'}, cw);
|
||||
EventUtils.synthesizeMouseAtCenter(targetTab, {type: 'mouseup'}, cw);
|
||||
|
||||
is(cw.GroupItems.groupItems.length, 2, 'there are two groupItems');
|
||||
is(sourceGroup.getChildren().length, 0, 'source group has no tabs');
|
||||
is(targetGroup.getChildren().length, 2, 'target group has two tabs');
|
||||
is(cw.GroupItems.groupItems.length, 1, 'sourceGroup was closed');
|
||||
isnot(cw.GroupItems.groupItems[0], sourceGroup, 'sourceGroup was closed');
|
||||
|
||||
targetGroup.getChild(0).close();
|
||||
|
||||
closeGroupItem(sourceGroup, function () {
|
||||
hideTabView(finish);
|
||||
});
|
||||
hideTabView(finish);
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
|
|
@ -22,13 +22,11 @@ function test() {
|
|||
"Tab width is bigger than tab clip width");
|
||||
is(gBrowser.tabContainer.getAttribute("closebuttons"), "alltabs", "Show button on all tabs.")
|
||||
|
||||
let cw = TabView.getContentWindow();
|
||||
let groupItems = cw.GroupItems.groupItems;
|
||||
is(groupItems.length, 2, "there are two groupItems");
|
||||
|
||||
// clean up and finish
|
||||
newTabs.forEach(function (tab) gBrowser.removeTab(tab));
|
||||
closeGroupItem(groupItems[1], finish);
|
||||
newTabs.forEach(function(tab) {
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -14,11 +14,11 @@ function test() {
|
|||
// make sure the tab one is selected because undoCloseTab() would remove
|
||||
// the selected tab if it's a blank tab.
|
||||
gBrowser.selectedTab = tabOne;
|
||||
showTabView(onTabViewShown);
|
||||
showTabView(onTabViewWindowLoaded);
|
||||
});
|
||||
}
|
||||
|
||||
function onTabViewShown() {
|
||||
function onTabViewWindowLoaded() {
|
||||
let contentWindow = TabView.getContentWindow();
|
||||
let groupItems = contentWindow.GroupItems.groupItems;
|
||||
is(groupItems.length, 1, "There is only one group");
|
||||
|
@ -28,7 +28,8 @@ function onTabViewShown() {
|
|||
ok(TabView.isVisible(), "Tab View is still visible after removing a tab");
|
||||
is(groupItems[0].getChildren().length, 2, "The group has two tab items");
|
||||
|
||||
restoreTab(function (tabTwo) {
|
||||
tabTwo = undoCloseTab(0);
|
||||
whenTabIsReconnected(tabTwo, function() {
|
||||
ok(TabView.isVisible(), "Tab View is still visible after restoring a tab");
|
||||
is(groupItems[0].getChildren().length, 3, "The group still has three tab items");
|
||||
|
||||
|
@ -40,3 +41,18 @@ function onTabViewShown() {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ----------
|
||||
function whenTabIsReconnected(tab, callback) {
|
||||
let tabItem = tab._tabViewTabItem;
|
||||
|
||||
if (tabItem._reconnected) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
tabItem.addSubscriber(tabItem, "reconnected", function () {
|
||||
tabItem.removeSubscriber(tabItem, "reconnected");
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -25,11 +25,12 @@ function test() {
|
|||
is(gBrowser.visibleTabs.length, 1, "The number of visible tabs is 1");
|
||||
is(gBrowser.visibleTabs[0], origTab,
|
||||
"The original tab is the only visible tab");
|
||||
|
||||
let groupItem = newTab._tabViewTabItem.parent;
|
||||
isnot(groupItem.id, newTabGroupItemId,
|
||||
isnot(newTab._tabViewTabItem.parent.id, newTabGroupItemId,
|
||||
"The moved tab item has a new group id");
|
||||
|
||||
closeGroupItem(groupItem, finish);
|
||||
// clean up
|
||||
gBrowser.removeTab(newTab);
|
||||
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -36,14 +36,12 @@ function test() {
|
|||
|
||||
// check state after adding tabItem to targetGroup
|
||||
is(tabItem.parent, targetGroup, 'tabItem changed groups');
|
||||
is(sourceGroup.getChildren().length, 0, 'source group has no children');
|
||||
is(cw.GroupItems.groupItems.length, 1, 'source group was closed automatically');
|
||||
is(targetGroup.getChildren().length, 2, 'target group has now two children');
|
||||
|
||||
// cleanup and finish
|
||||
closeGroupItem(sourceGroup, function () {
|
||||
tabItem.close();
|
||||
hideTabView(finishTest);
|
||||
});
|
||||
tabItem.close();
|
||||
hideTabView(finishTest);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,10 @@ function test() {
|
|||
is(win.gBrowser.visibleTabs.length, 1, "There is one tab displayed");
|
||||
is(cw.GroupItems.groupItems.length, 2, "There are two groups still");
|
||||
|
||||
waitForFocus(finish);
|
||||
showTabView(function () {
|
||||
is(cw.GroupItems.groupItems.length, 1, "There is now only one group");
|
||||
waitForFocus(finish);
|
||||
}, win);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -20,6 +20,23 @@ function test() {
|
|||
return groupItem;
|
||||
}
|
||||
|
||||
let hideGroupItem = function (groupItem, callback) {
|
||||
groupItem.addSubscriber(groupItem, 'groupHidden', function () {
|
||||
groupItem.removeSubscriber(groupItem, 'groupHidden');
|
||||
callback();
|
||||
});
|
||||
groupItem.closeAll();
|
||||
}
|
||||
|
||||
let closeGroupItem = function (groupItem, callback) {
|
||||
afterAllTabsLoaded(function () {
|
||||
hideGroupItem(groupItem, function () {
|
||||
groupItem.closeHidden();
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let tests = [];
|
||||
|
||||
let next = function () {
|
||||
|
@ -197,13 +214,10 @@ function test() {
|
|||
let tabItem = groupItem.getChild(0);
|
||||
groupItem.remove(tabItem);
|
||||
|
||||
closeGroupItem(groupItem, function () {
|
||||
hideTabView(function () {
|
||||
assertNumberOfGroupItems(0);
|
||||
|
||||
hideTabView(function () {
|
||||
createGroupItem().add(tabItem);
|
||||
next();
|
||||
});
|
||||
createGroupItem().add(tabItem);
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -215,17 +229,14 @@ function test() {
|
|||
let tabItem = groupItem.getChild(0);
|
||||
groupItem.remove(tabItem);
|
||||
|
||||
closeGroupItem(groupItem, function () {
|
||||
assertNumberOfGroupItems(0);
|
||||
let newGroupItem = createGroupItem(1);
|
||||
assertNumberOfGroupItems(1);
|
||||
|
||||
closeGroupItem(newGroupItem, function () {
|
||||
assertNumberOfGroupItems(0);
|
||||
|
||||
let newGroupItem = createGroupItem(1);
|
||||
assertNumberOfGroupItems(1);
|
||||
|
||||
closeGroupItem(newGroupItem, function () {
|
||||
assertNumberOfGroupItems(0);
|
||||
createGroupItem().add(tabItem);
|
||||
hideTabView(next);
|
||||
});
|
||||
createGroupItem().add(tabItem);
|
||||
hideTabView(next);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -237,18 +248,15 @@ function test() {
|
|||
let tabItem = groupItem.getChild(0);
|
||||
groupItem.remove(tabItem);
|
||||
|
||||
closeGroupItem(groupItem, function () {
|
||||
assertNumberOfGroupItems(0);
|
||||
assertNumberOfGroupItems(0);
|
||||
let newGroupItem = createGroupItem(1);
|
||||
assertNumberOfGroupItems(1);
|
||||
|
||||
let newGroupItem = createGroupItem(1);
|
||||
assertNumberOfGroupItems(1);
|
||||
|
||||
hideGroupItem(newGroupItem, function () {
|
||||
hideTabView(function () {
|
||||
assertNumberOfGroupItems(0);
|
||||
createGroupItem().add(tabItem);
|
||||
next();
|
||||
});
|
||||
hideGroupItem(newGroupItem, function () {
|
||||
hideTabView(function () {
|
||||
assertNumberOfGroupItems(0);
|
||||
createGroupItem().add(tabItem);
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -39,6 +39,10 @@ function test() {
|
|||
tests.push([tab2, tab1]);
|
||||
tests.push([tab1]);
|
||||
|
||||
// test reordering of empty groups - removes the last tab and causes
|
||||
// the groupItem to close
|
||||
tests.push([]);
|
||||
|
||||
while (tests.length) {
|
||||
let test = tests.shift();
|
||||
|
||||
|
@ -59,7 +63,7 @@ function test() {
|
|||
groupItem.reorderTabsBasedOnTabItemOrder();
|
||||
}
|
||||
|
||||
closeGroupItem(groupItem, testMoveBetweenGroups);
|
||||
testMoveBetweenGroups();
|
||||
}
|
||||
|
||||
let testMoveBetweenGroups = function () {
|
||||
|
|
|
@ -119,8 +119,7 @@ function test() {
|
|||
|
||||
enterAndLeavePrivateBrowsing(function () {
|
||||
assertNumberOfVisibleTabs(2);
|
||||
gBrowser.selectedTab = gBrowser.tabs[0];
|
||||
closeGroupItem(cw.GroupItems.groupItems[1], next);
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -41,6 +41,20 @@ function test() {
|
|||
return createTab('about:blank');
|
||||
}
|
||||
|
||||
let restoreTab = function (callback) {
|
||||
let tab = undoCloseTab(0);
|
||||
|
||||
if (tab._tabViewTabItem._reconnected) {
|
||||
afterAllTabsLoaded(callback);
|
||||
return;
|
||||
}
|
||||
|
||||
tab._tabViewTabItem.addSubscriber(tab, 'reconnected', function () {
|
||||
tab._tabViewTabItem.removeSubscriber(tab, 'reconnected');
|
||||
afterAllTabsLoaded(callback);
|
||||
});
|
||||
}
|
||||
|
||||
let finishTest = function () {
|
||||
prefix = 'finish';
|
||||
assertValidPrerequisites();
|
||||
|
|
|
@ -33,10 +33,13 @@ function test() {
|
|||
ok(!document.getElementById("context_closeTab").disabled, "The 'Close tab' menu item is enabled");
|
||||
ok(!document.getElementById("context_openTabInWindow").disabled, "The 'Move to New Window' menu item is enabled");
|
||||
|
||||
let newTabTwo = gBrowser.selectedTab;
|
||||
gBrowser.selected = originalTab;
|
||||
gBrowser.removeTab(newTabOne);
|
||||
|
||||
closeGroupItem(newGroup, finish);
|
||||
gBrowser.removeTab(newTabOne);
|
||||
gBrowser.removeTab(newTabTwo);
|
||||
|
||||
finish();
|
||||
});
|
||||
let newGroup = contentWindow.GroupItems.newGroup();
|
||||
newGroup.newTab();
|
||||
|
|
|
@ -39,9 +39,7 @@ function test() {
|
|||
synthesizeMiddleMouseDrag(tabContainer, 10);
|
||||
ok(!groupItem.getChild(0), 'tabItem was closed');
|
||||
|
||||
closeGroupItem(groupItem, function () {
|
||||
hideTabView(finish);
|
||||
});
|
||||
hideTabView(finish);
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
|
|
@ -25,25 +25,20 @@ function onTabViewWindowLoaded(win) {
|
|||
|
||||
is(group.getChildren().length, 1, "The group has one child now.");
|
||||
let tab = group.getChild(0);
|
||||
|
||||
function finalize() {
|
||||
is(contentWindow.GroupItems.getActiveGroupItem(), originalGroup,
|
||||
"The original group is active.");
|
||||
is(contentWindow.UI.getActiveTab(), originalTab._tabViewTabItem,
|
||||
"The original tab is active");
|
||||
|
||||
callback();
|
||||
}
|
||||
|
||||
|
||||
function check() {
|
||||
if (groupOrTab == 'group') {
|
||||
group.removeSubscriber(group, "groupHidden", check);
|
||||
group.closeHidden();
|
||||
finalize();
|
||||
} else {
|
||||
} else
|
||||
tab.removeSubscriber(tab, "tabRemoved", check);
|
||||
closeGroupItem(group, finalize);
|
||||
}
|
||||
|
||||
is(contentWindow.GroupItems.getActiveGroupItem(), originalGroup,
|
||||
"The original group is active.");
|
||||
is(contentWindow.UI.getActiveTab(), originalTab._tabViewTabItem,
|
||||
"The original tab is active");
|
||||
|
||||
callback();
|
||||
}
|
||||
|
||||
if (groupOrTab == 'group') {
|
||||
|
@ -63,4 +58,4 @@ function onTabViewWindowLoaded(win) {
|
|||
finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -25,6 +25,20 @@ function test() {
|
|||
return cw.GroupItems.groupItems[index];
|
||||
}
|
||||
|
||||
let restoreTab = function (callback) {
|
||||
let tab = undoCloseTab(0);
|
||||
|
||||
if (tab._tabViewTabItem._reconnected) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
tab._tabViewTabItem.addSubscriber(tab, 'reconnected', function () {
|
||||
tab._tabViewTabItem.removeSubscriber(tab, 'reconnected');
|
||||
afterAllTabsLoaded(callback);
|
||||
});
|
||||
}
|
||||
|
||||
let activateFirstGroupItem = function () {
|
||||
let activeTabItem = getGroupItem(0).getChild(0);
|
||||
cw.GroupItems.updateActiveGroupItemAndTabBar(activeTabItem);
|
||||
|
@ -77,7 +91,9 @@ function test() {
|
|||
assertNumberOfTabsInGroup(groupItem, 2);
|
||||
|
||||
activateFirstGroupItem();
|
||||
closeGroupItem(groupItem, finishTest);
|
||||
gBrowser.removeTab(gBrowser.tabs[1]);
|
||||
gBrowser.removeTab(gBrowser.tabs[1]);
|
||||
finishTest();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
|
|||
};
|
||||
groupTwo.addSubscriber(groupTwo, "close", function() {
|
||||
groupTwo.removeSubscriber(groupTwo, "close");
|
||||
closeGroupItem(groupOne, finish);
|
||||
finish();
|
||||
});
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
gBrowser.selectedTab = originalTab;
|
||||
|
|
|
@ -95,7 +95,7 @@ function testGroupItemWithTabItem(contentWindow) {
|
|||
let endGame = function() {
|
||||
window.removeEventListener("tabviewhidden", endGame, false);
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
closeGroupItem(groupItem, finish);
|
||||
finish();
|
||||
};
|
||||
window.addEventListener("tabviewhidden", endGame, false);
|
||||
|
||||
|
|
|
@ -1244,7 +1244,7 @@ nsWebSocket::Send(const nsAString& aData, PRBool *aRet)
|
|||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
// We need to check if there isn't unpaired surrogates.
|
||||
// Check for unpaired surrogates.
|
||||
PRUint32 i, length = aData.Length();
|
||||
for (i = 0; i < length; ++i) {
|
||||
if (NS_IS_LOW_SURROGATE(aData[i])) {
|
||||
|
|
|
@ -129,15 +129,11 @@ function CreateTestWS(ws_location, ws_protocol)
|
|||
|
||||
function forcegc()
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
Components.utils.forceGC();
|
||||
var wu = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
wu.garbageCollect();
|
||||
SpecialPowers.forceGC();
|
||||
SpecialPowers.gc();
|
||||
setTimeout(function()
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
wu.garbageCollect();
|
||||
SpecialPowers.gc();
|
||||
}, 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,11 +22,8 @@ var params = ["protocol", "resource", "origin", "end"];
|
|||
var results = ["test", "/tests/content/base/test/file_ws_basic_tests", "http://mochi.test:8888", "end"];
|
||||
|
||||
function forcegc(){
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
Components.utils.forceGC();
|
||||
var wu = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
wu.garbageCollect();
|
||||
SpecialPowers.forceGC();
|
||||
SpecialPowers.gc();
|
||||
}
|
||||
|
||||
function finishWSTest() {
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<title>Testcase for bug </title>
|
||||
<style>
|
||||
#ie {
|
||||
border: 5px solid red;
|
||||
}
|
||||
#ie {
|
||||
display: block;
|
||||
}
|
||||
#moz {
|
||||
color: blue;
|
||||
/* display: none; */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p id="foo">foo</p>
|
||||
<p id="ie">ie</p>
|
||||
<p id="moz">moz</p>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -22,7 +22,7 @@ include autofocus/reftest.list
|
|||
== 596455-2b.html 596455-ref-2.html
|
||||
== 610935.html 610935-ref.html
|
||||
== 649134-1.html 649134-ref.html
|
||||
== 649134-2.html 649134-ref.html
|
||||
skip-if(Android) == 649134-2.html 649134-2-ref.html
|
||||
|
||||
== hidden-1a.html hidden-1-ref.html
|
||||
== hidden-1b.html hidden-1-ref.html
|
||||
|
|
|
@ -397,7 +397,6 @@ nsHTMLLinkElement::GetStyleSheetURL(PRBool* aIsInline)
|
|||
*aIsInline = PR_FALSE;
|
||||
nsAutoString href;
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
|
||||
href.Trim(" \t\n\r\f"); // trim HTML5 whitespace
|
||||
if (href.IsEmpty()) {
|
||||
return nsnull;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ DOMCI_DATA(SVGAnimatedIntegerPair, nsSVGIntegerPair::DOMAnimatedIntegerPair)
|
|||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGIntegerPair::DOMAnimatedIntegerPair)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedInteger)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimatedIntegerPair)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimatedInteger)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
/* Implementation */
|
||||
|
|
|
@ -55,7 +55,7 @@ DOMCI_DATA(SVGAnimatedNumberPair, nsSVGNumberPair::DOMAnimatedNumberPair)
|
|||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGNumberPair::DOMAnimatedNumberPair)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedNumber)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimatedNumberPair)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimatedNumber)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
/* Implementation */
|
||||
|
|
|
@ -67,6 +67,7 @@ IPDLDIRS = \
|
|||
netwerk/protocol/ftp \
|
||||
netwerk/protocol/http \
|
||||
netwerk/protocol/wyciwyg \
|
||||
netwerk/protocol/websocket \
|
||||
netwerk/cookie \
|
||||
uriloader/prefetch \
|
||||
$(NULL)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<box xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<label style="margin: 0px 300px;" value="Shadow"/>
|
||||
</box>
|
|
@ -0,0 +1,3 @@
|
|||
<box xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<label style="margin: 0px 300px; text-shadow: blue 4px 10px 2px" value="Shadow"/>
|
||||
</box>
|
|
@ -1649,4 +1649,5 @@ fails-if(layersGPUAccelerated&&cocoaWidget) == 654950-1.html 654950-1-ref.html #
|
|||
== 658952.html 658952-ref.html
|
||||
== 664127-1.xul 664127-1-ref.xul
|
||||
== 660682-1.html 660682-1-ref.html
|
||||
!= 669015-1.xul 669015-1-notref.xul
|
||||
== 668319-1.xul about:blank
|
||||
|
|
|
@ -14,17 +14,20 @@
|
|||
|
||||
div {
|
||||
font-family: DejaVuSansMono;
|
||||
width: 60px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
font-size: 14px;
|
||||
text-overflow: "...";
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
/* We put the text and marker into separate spans, because
|
||||
overflow markers (and their shadows) are drawn separately
|
||||
from the text frame. */
|
||||
span {
|
||||
text-shadow: -0.5em 3px 2px red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
|
||||
a</div>
|
||||
|
||||
<div><span>Hello</span><span>...</span></div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -14,20 +14,24 @@
|
|||
src: url(../fonts/DejaVuSansMono.woff);
|
||||
}
|
||||
|
||||
/* overflow:hidden will clip off some of our text-shadow too.
|
||||
Give us some padding, so we can put the shadow to the left and bottom
|
||||
and beat the overflow clipping. */
|
||||
div {
|
||||
font-family: DejaVuSansMono;
|
||||
width: 60px;
|
||||
width: 5em;
|
||||
padding-left: 1em;
|
||||
padding-bottom: 1em;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
font-size: 14px;
|
||||
text-overflow: "...";
|
||||
text-shadow: 0px 2px 2px red;
|
||||
text-shadow: -0.5em 3px 2px red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
|
||||
a</div>
|
||||
|
||||
<div>HelloKitty</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -13,4 +13,4 @@ HTTP(..) == quirks-line-height.html quirks-line-height-ref.html
|
|||
HTTP(..) == standards-decorations.html standards-decorations-ref.html
|
||||
HTTP(..) == standards-line-height.html standards-line-height-ref.html
|
||||
HTTP(..) == selection.html selection-ref.html
|
||||
HTTP(..) != marker-shadow.html marker-shadow-notref.html
|
||||
HTTP(..) == marker-shadow.html marker-shadow-ref.html
|
||||
|
|
|
@ -88,7 +88,8 @@ function selectText() {
|
|||
addRange(t1.firstChild);
|
||||
var t2 = document.getElementById('t2');
|
||||
addRange(t2.firstChild);
|
||||
document.documentElement.removeAttribute('class');
|
||||
document.body.offsetHeight;
|
||||
setTimeout(function(){document.documentElement.removeAttribute('class')},1000);
|
||||
}
|
||||
</script>
|
||||
</head><body onload="selectText();">
|
||||
|
|
|
@ -86,7 +86,8 @@ function selectText() {
|
|||
for (i = 0; i < divs.length; ++i) {
|
||||
addRange(divs[i]);
|
||||
}
|
||||
document.documentElement.removeAttribute('class');
|
||||
document.body.offsetHeight;
|
||||
setTimeout(function(){document.documentElement.removeAttribute('class')},1000);
|
||||
}
|
||||
</script>
|
||||
</head><body onload="selectText();">
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<script type="text/javascript">
|
||||
|
||||
document.createElementNS("http://www.w3.org/2000/svg", "filter").filterResX;
|
||||
|
||||
</script>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 199 B |
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<script type="text/javascript">
|
||||
|
||||
document.createElementNS("http://www.w3.org/2000/svg", "feGaussianBlur").stdDeviationX;
|
||||
|
||||
</script>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 210 B |
|
@ -113,3 +113,5 @@ load 655025-1.svg
|
|||
load 655025-2.svg
|
||||
load 655025-3.svg
|
||||
load 657077-1.svg
|
||||
load 669025-1.svg
|
||||
load 669025-2.svg
|
||||
|
|
|
@ -347,9 +347,9 @@ public:
|
|||
|
||||
virtual void DisableComponentAlpha() { mDisableSubpixelAA = PR_TRUE; }
|
||||
|
||||
void PaintTextWithOffset(nsRenderingContext* aCtx,
|
||||
nsPoint aOffset,
|
||||
const nscolor* aColor);
|
||||
void PaintTextToContext(nsRenderingContext* aCtx,
|
||||
nsPoint aOffset,
|
||||
const nscolor* aColor);
|
||||
|
||||
PRPackedBool mDisableSubpixelAA;
|
||||
};
|
||||
|
@ -361,7 +361,7 @@ PaintTextShadowCallback(nsRenderingContext* aCtx,
|
|||
void* aData)
|
||||
{
|
||||
reinterpret_cast<nsDisplayXULTextBox*>(aData)->
|
||||
PaintTextWithOffset(aCtx, aShadowOffset, &aShadowColor);
|
||||
PaintTextToContext(aCtx, aShadowOffset, &aShadowColor);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -372,20 +372,21 @@ nsDisplayXULTextBox::Paint(nsDisplayListBuilder* aBuilder,
|
|||
mDisableSubpixelAA);
|
||||
|
||||
// Paint the text shadow before doing any foreground stuff
|
||||
nsRect drawRect = static_cast<nsTextBoxFrame*>(mFrame)->mTextDrawRect;
|
||||
nsRect drawRect = static_cast<nsTextBoxFrame*>(mFrame)->mTextDrawRect +
|
||||
ToReferenceFrame();
|
||||
nsLayoutUtils::PaintTextShadow(mFrame, aCtx,
|
||||
drawRect, mVisibleRect,
|
||||
mFrame->GetStyleColor()->mColor,
|
||||
PaintTextShadowCallback,
|
||||
(void*)this);
|
||||
|
||||
PaintTextWithOffset(aCtx, nsPoint(0, 0), nsnull);
|
||||
PaintTextToContext(aCtx, nsPoint(0, 0), nsnull);
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayXULTextBox::PaintTextWithOffset(nsRenderingContext* aCtx,
|
||||
nsPoint aOffset,
|
||||
const nscolor* aColor)
|
||||
nsDisplayXULTextBox::PaintTextToContext(nsRenderingContext* aCtx,
|
||||
nsPoint aOffset,
|
||||
const nscolor* aColor)
|
||||
{
|
||||
static_cast<nsTextBoxFrame*>(mFrame)->
|
||||
PaintTitle(*aCtx, mVisibleRect, ToReferenceFrame() + aOffset, aColor);
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
diff --git a/media/libvpx/build/make/ads2gas.pl b/media/libvpx/build/make/ads2gas.pl
|
||||
--- a/media/libvpx/build/make/ads2gas.pl
|
||||
+++ b/media/libvpx/build/make/ads2gas.pl
|
||||
@@ -74,17 +74,20 @@ while (<STDIN>)
|
||||
|
||||
# Convert INCLUDE to .INCLUDE "file"
|
||||
s/INCLUDE(\s*)(.*)$/.include $1\"$2\"/;
|
||||
|
||||
# Code directive (ARM vs Thumb)
|
||||
s/CODE([0-9][0-9])/.code $1/;
|
||||
|
||||
# No AREA required
|
||||
- s/^\s*AREA.*$/.text/;
|
||||
+ # But ALIGNs in AREA must be obeyed
|
||||
+ s/^\s*AREA.*ALIGN=([0-9])$/.text\n.p2align $1/;
|
||||
+ # If no ALIGN, strip the AREA and align to 4 bytes
|
||||
+ s/^\s*AREA.*$/.text\n.p2align 2/;
|
||||
|
||||
# DCD to .word
|
||||
# This one is for incoming symbols
|
||||
s/DCD\s+\|(\w*)\|/.long $1/;
|
||||
|
||||
# DCW to .short
|
||||
s/DCW\s+\|(\w*)\|/.short $1/;
|
||||
s/DCW(.*)/.short $1/;
|
|
@ -79,7 +79,10 @@ while (<STDIN>)
|
|||
s/CODE([0-9][0-9])/.code $1/;
|
||||
|
||||
# No AREA required
|
||||
s/^\s*AREA.*$/.text/;
|
||||
# But ALIGNs in AREA must be obeyed
|
||||
s/^\s*AREA.*ALIGN=([0-9])$/.text\n.p2align $1/;
|
||||
# If no ALIGN, strip the AREA and align to 4 bytes
|
||||
s/^\s*AREA.*$/.text\n.p2align 2/;
|
||||
|
||||
# DCD to .word
|
||||
# This one is for incoming symbols
|
||||
|
|
|
@ -326,3 +326,6 @@ patch -p3 < bug640935.patch
|
|||
|
||||
# Patch to avoid text relocations on ARM
|
||||
patch -p3 < bug646815.patch
|
||||
|
||||
# Patch to fix alignment problems with using ARM asm in Thumb mode.
|
||||
patch -p3 < bug666931.patch
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
#include "nsNetStrings.h"
|
||||
#include "nsDNSPrefetch.h"
|
||||
#include "nsAboutProtocolHandler.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
#include "nsNetCID.h"
|
||||
|
||||
|
@ -283,10 +284,47 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsWyciwygProtocolHandler)
|
|||
|
||||
#ifdef NECKO_PROTOCOL_websocket
|
||||
#include "nsWebSocketHandler.h"
|
||||
#include "WebSocketChannelChild.h"
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWebSocketHandler)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWebSocketSSLHandler)
|
||||
static BaseWebSocketChannel*
|
||||
WebSocketHandlerConstructor(bool aSecure)
|
||||
{
|
||||
if (IsNeckoChild()) {
|
||||
return new WebSocketChannelChild(aSecure);
|
||||
}
|
||||
|
||||
if (aSecure) {
|
||||
return new nsWebSocketSSLHandler;
|
||||
} else {
|
||||
return new nsWebSocketHandler;
|
||||
}
|
||||
}
|
||||
|
||||
#define WEB_SOCKET_HANDLER_CONSTRUCTOR(type, secure) \
|
||||
static nsresult \
|
||||
type##Constructor(nsISupports *aOuter, REFNSIID aIID, \
|
||||
void **aResult) \
|
||||
{ \
|
||||
nsresult rv; \
|
||||
\
|
||||
BaseWebSocketChannel * inst; \
|
||||
\
|
||||
*aResult = NULL; \
|
||||
if (NULL != aOuter) { \
|
||||
rv = NS_ERROR_NO_AGGREGATION; \
|
||||
return rv; \
|
||||
} \
|
||||
inst = WebSocketHandlerConstructor(secure); \
|
||||
NS_ADDREF(inst); \
|
||||
rv = inst->QueryInterface(aIID, aResult); \
|
||||
NS_RELEASE(inst); \
|
||||
return rv; \
|
||||
}
|
||||
|
||||
WEB_SOCKET_HANDLER_CONSTRUCTOR(nsWebSocketHandler, false)
|
||||
WEB_SOCKET_HANDLER_CONSTRUCTOR(nsWebSocketSSLHandler, true)
|
||||
#undef WEB_SOCKET_HANDLER_CONSTRUCTOR
|
||||
} // namespace mozilla::net
|
||||
} // namespace mozilla
|
||||
#endif
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIChannel.h"
|
||||
#include "nsISupports.h"
|
||||
#include "mozilla/net/ChannelEventQueue.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -51,7 +51,7 @@ ChannelEventQueue::FlushQueue()
|
|||
// Events flushed could include destruction of channel (and our own
|
||||
// destructor) unless we make sure its refcount doesn't drop to 0 while this
|
||||
// method is running.
|
||||
nsCOMPtr<nsIChannel> kungFuDeathGrip(mOwner);
|
||||
nsCOMPtr<nsISupports> kungFuDeathGrip(mOwner);
|
||||
|
||||
// Prevent flushed events from flushing the queue recursively
|
||||
mFlushing = true;
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#include <nsTArray.h>
|
||||
#include <nsAutoPtr.h>
|
||||
|
||||
class nsIChannel;
|
||||
class nsISupports;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
@ -70,7 +70,7 @@ class AutoEventEnqueuerBase;
|
|||
class ChannelEventQueue
|
||||
{
|
||||
public:
|
||||
ChannelEventQueue(nsIChannel *owner)
|
||||
ChannelEventQueue(nsISupports *owner)
|
||||
: mForced(false)
|
||||
, mSuspended(false)
|
||||
, mFlushing(false)
|
||||
|
@ -116,7 +116,7 @@ class ChannelEventQueue
|
|||
bool mFlushing;
|
||||
|
||||
// Keep ptr to avoid refcount cycle: only grab ref during flushing.
|
||||
nsIChannel *mOwner;
|
||||
nsISupports *mOwner;
|
||||
|
||||
friend class AutoEventEnqueuer;
|
||||
};
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "mozilla/net/CookieServiceChild.h"
|
||||
#include "mozilla/net/WyciwygChannelChild.h"
|
||||
#include "mozilla/net/FTPChannelChild.h"
|
||||
#include "mozilla/net/WebSocketChannelChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
@ -167,5 +168,20 @@ NeckoChild::DeallocPWyciwygChannel(PWyciwygChannelChild* channel)
|
|||
return true;
|
||||
}
|
||||
|
||||
PWebSocketChild*
|
||||
NeckoChild::AllocPWebSocket(PBrowserChild* browser)
|
||||
{
|
||||
NS_NOTREACHED("AllocPWebSocket should not be called");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
bool
|
||||
NeckoChild::DeallocPWebSocket(PWebSocketChild* child)
|
||||
{
|
||||
WebSocketChannelChild* p = static_cast<WebSocketChannelChild*>(child);
|
||||
p->ReleaseIPDLReference();
|
||||
return true;
|
||||
}
|
||||
|
||||
}} // mozilla::net
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@ protected:
|
|||
virtual bool DeallocPWyciwygChannel(PWyciwygChannelChild*);
|
||||
virtual PFTPChannelChild* AllocPFTPChannel();
|
||||
virtual bool DeallocPFTPChannel(PFTPChannelChild*);
|
||||
virtual PWebSocketChild* AllocPWebSocket(PBrowserChild*);
|
||||
virtual bool DeallocPWebSocket(PWebSocketChild*);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -44,9 +44,13 @@
|
|||
#include "mozilla/net/CookieServiceParent.h"
|
||||
#include "mozilla/net/WyciwygChannelParent.h"
|
||||
#include "mozilla/net/FTPChannelParent.h"
|
||||
#include "mozilla/net/WebSocketChannelParent.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
|
||||
#include "nsHTMLDNSPrefetch.h"
|
||||
|
||||
using mozilla::dom::TabParent;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
|
@ -120,6 +124,23 @@ NeckoParent::DeallocPWyciwygChannel(PWyciwygChannelParent* channel)
|
|||
return true;
|
||||
}
|
||||
|
||||
PWebSocketParent*
|
||||
NeckoParent::AllocPWebSocket(PBrowserParent* browser)
|
||||
{
|
||||
TabParent* tabParent = static_cast<TabParent*>(browser);
|
||||
WebSocketChannelParent* p = new WebSocketChannelParent(tabParent);
|
||||
p->AddRef();
|
||||
return p;
|
||||
}
|
||||
|
||||
bool
|
||||
NeckoParent::DeallocPWebSocket(PWebSocketParent* actor)
|
||||
{
|
||||
WebSocketChannelParent* p = static_cast<WebSocketChannelParent*>(actor);
|
||||
p->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
NeckoParent::RecvHTMLDNSPrefetch(const nsString& hostname,
|
||||
const PRUint16& flags)
|
||||
|
|
|
@ -64,6 +64,8 @@ protected:
|
|||
virtual bool DeallocPWyciwygChannel(PWyciwygChannelParent*);
|
||||
virtual PFTPChannelParent* AllocPFTPChannel();
|
||||
virtual bool DeallocPFTPChannel(PFTPChannelParent*);
|
||||
virtual PWebSocketParent* AllocPWebSocket(PBrowserParent* browser);
|
||||
virtual bool DeallocPWebSocket(PWebSocketParent*);
|
||||
virtual bool RecvHTMLDNSPrefetch(const nsString& hostname,
|
||||
const PRUint16& flags);
|
||||
};
|
||||
|
|
|
@ -44,6 +44,7 @@ include protocol PCookieService;
|
|||
include protocol PBrowser;
|
||||
include protocol PWyciwygChannel;
|
||||
include protocol PFTPChannel;
|
||||
include protocol PWebSocket;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
@ -57,6 +58,7 @@ sync protocol PNecko
|
|||
manages PCookieService;
|
||||
manages PWyciwygChannel;
|
||||
manages PFTPChannel;
|
||||
manages PWebSocket;
|
||||
|
||||
parent:
|
||||
__delete__();
|
||||
|
@ -64,6 +66,7 @@ parent:
|
|||
PCookieService();
|
||||
PWyciwygChannel();
|
||||
PFTPChannel();
|
||||
PWebSocket(PBrowser browser);
|
||||
|
||||
HTMLDNSPrefetch(nsString hostname, PRUint16 flags);
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace net {
|
|||
|
||||
FTPChannelChild::FTPChannelChild(nsIURI* uri)
|
||||
: mIPCOpen(false)
|
||||
, mEventQ(this)
|
||||
, mEventQ(static_cast<nsIFTPChannel*>(this))
|
||||
, mCanceled(false)
|
||||
, mSuspendCount(0)
|
||||
, mIsPending(PR_FALSE)
|
||||
|
|
|
@ -66,7 +66,7 @@ HttpChannelChild::HttpChannelChild()
|
|||
, mSendResumeAt(false)
|
||||
, mIPCOpen(false)
|
||||
, mKeptAlive(false)
|
||||
, mEventQ(this)
|
||||
, mEventQ(static_cast<nsIHttpChannel*>(this))
|
||||
{
|
||||
LOG(("Creating HttpChannelChild @%x\n", this));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Josh Matthews <josh@joshmatthews.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "WebSocketLog.h"
|
||||
#include "BaseWebSocketChannel.h"
|
||||
#include "nsWebSocketHandler.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsStandardURL.h"
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
PRLogModuleInfo *webSocketLog = nsnull;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
BaseWebSocketChannel::BaseWebSocketChannel()
|
||||
: mEncrypted(false)
|
||||
{
|
||||
#if defined(PR_LOGGING)
|
||||
if (!webSocketLog)
|
||||
webSocketLog = PR_NewLogModule("nsWebSocket");
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// BaseWebSocketChannel::nsIWebSocketProtocol
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
BaseWebSocketChannel::GetOriginalURI(nsIURI **aOriginalURI)
|
||||
{
|
||||
LOG(("BaseWebSocketChannel::GetOriginalURI() %p\n", this));
|
||||
|
||||
if (!mOriginalURI)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
NS_ADDREF(*aOriginalURI = mOriginalURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BaseWebSocketChannel::GetURI(nsIURI **aURI)
|
||||
{
|
||||
LOG(("BaseWebSocketChannel::GetURI() %p\n", this));
|
||||
|
||||
if (!mOriginalURI)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
if (mURI)
|
||||
NS_ADDREF(*aURI = mURI);
|
||||
else
|
||||
NS_ADDREF(*aURI = mOriginalURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BaseWebSocketChannel::
|
||||
GetNotificationCallbacks(nsIInterfaceRequestor **aNotificationCallbacks)
|
||||
{
|
||||
LOG(("BaseWebSocketChannel::GetNotificationCallbacks() %p\n", this));
|
||||
NS_IF_ADDREF(*aNotificationCallbacks = mCallbacks);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BaseWebSocketChannel::
|
||||
SetNotificationCallbacks(nsIInterfaceRequestor *aNotificationCallbacks)
|
||||
{
|
||||
LOG(("BaseWebSocketChannel::SetNotificationCallbacks() %p\n", this));
|
||||
mCallbacks = aNotificationCallbacks;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BaseWebSocketChannel::GetLoadGroup(nsILoadGroup **aLoadGroup)
|
||||
{
|
||||
LOG(("BaseWebSocketChannel::GetLoadGroup() %p\n", this));
|
||||
NS_IF_ADDREF(*aLoadGroup = mLoadGroup);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BaseWebSocketChannel::SetLoadGroup(nsILoadGroup *aLoadGroup)
|
||||
{
|
||||
LOG(("BaseWebSocketChannel::SetLoadGroup() %p\n", this));
|
||||
mLoadGroup = aLoadGroup;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BaseWebSocketChannel::GetProtocol(nsACString &aProtocol)
|
||||
{
|
||||
LOG(("BaseWebSocketChannel::GetProtocol() %p\n", this));
|
||||
aProtocol = mProtocol;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BaseWebSocketChannel::SetProtocol(const nsACString &aProtocol)
|
||||
{
|
||||
LOG(("BaseWebSocketChannel::SetProtocol() %p\n", this));
|
||||
mProtocol = aProtocol; /* the sub protocol */
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// BaseWebSocketChannel::nsIProtocolHandler
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
BaseWebSocketChannel::GetScheme(nsACString &aScheme)
|
||||
{
|
||||
LOG(("BaseWebSocketHandler::GetScheme() %p\n", this));
|
||||
|
||||
if (mEncrypted)
|
||||
aScheme.AssignLiteral("wss");
|
||||
else
|
||||
aScheme.AssignLiteral("ws");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BaseWebSocketChannel::GetDefaultPort(PRInt32 *aDefaultPort)
|
||||
{
|
||||
LOG(("BaseWebSocketHandler::GetDefaultPort() %p\n", this));
|
||||
|
||||
if (mEncrypted)
|
||||
*aDefaultPort = kDefaultWSSPort;
|
||||
else
|
||||
*aDefaultPort = kDefaultWSPort;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BaseWebSocketChannel::GetProtocolFlags(PRUint32 *aProtocolFlags)
|
||||
{
|
||||
LOG(("BaseWebSocketHandler::GetProtocolFlags() %p\n", this));
|
||||
|
||||
*aProtocolFlags = URI_NORELATIVE | URI_NON_PERSISTABLE | ALLOWS_PROXY |
|
||||
ALLOWS_PROXY_HTTP | URI_DOES_NOT_RETURN_DATA | URI_DANGEROUS_TO_LOAD;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BaseWebSocketChannel::NewURI(const nsACString & aSpec, const char *aOriginCharset,
|
||||
nsIURI *aBaseURI, nsIURI **_retval NS_OUTPARAM)
|
||||
{
|
||||
LOG(("BaseWebSocketHandler::NewURI() %p\n", this));
|
||||
|
||||
PRInt32 port;
|
||||
nsresult rv = GetDefaultPort(&port);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsRefPtr<nsStandardURL> url = new nsStandardURL();
|
||||
rv = url->Init(nsIStandardURL::URLTYPE_AUTHORITY, port, aSpec,
|
||||
aOriginCharset, aBaseURI);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
NS_ADDREF(*_retval = url);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BaseWebSocketChannel::NewChannel(nsIURI *aURI, nsIChannel **_retval NS_OUTPARAM)
|
||||
{
|
||||
LOG(("BaseWebSocketHandler::NewChannel() %p\n", this));
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BaseWebSocketChannel::AllowPort(PRInt32 port, const char *scheme,
|
||||
PRBool *_retval NS_OUTPARAM)
|
||||
{
|
||||
LOG(("BaseWebSocketHandler::AllowPort() %p\n", this));
|
||||
|
||||
// do not override any blacklisted ports
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,94 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Josh Matthews <josh@joshmatthews.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_net_BaseWebSocketChannel_h
|
||||
#define mozilla_net_BaseWebSocketChannel_h
|
||||
|
||||
#include "nsIWebSocketProtocol.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
const static PRInt32 kDefaultWSPort = 80;
|
||||
const static PRInt32 kDefaultWSSPort = 443;
|
||||
|
||||
class BaseWebSocketChannel : public nsIWebSocketProtocol,
|
||||
public nsIProtocolHandler
|
||||
{
|
||||
public:
|
||||
BaseWebSocketChannel();
|
||||
|
||||
NS_DECL_NSIPROTOCOLHANDLER
|
||||
|
||||
NS_IMETHOD QueryInterface(const nsIID & uuid, void **result NS_OUTPARAM) = 0;
|
||||
NS_IMETHOD_(nsrefcnt ) AddRef(void) = 0;
|
||||
NS_IMETHOD_(nsrefcnt ) Release(void) = 0;
|
||||
|
||||
// Partial implementation of nsIWebSocketProtocol
|
||||
//
|
||||
NS_IMETHOD GetOriginalURI(nsIURI **aOriginalURI);
|
||||
NS_IMETHOD GetURI(nsIURI **aURI);
|
||||
NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor **aNotificationCallbacks);
|
||||
NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor *aNotificationCallbacks);
|
||||
NS_IMETHOD GetLoadGroup(nsILoadGroup **aLoadGroup);
|
||||
NS_IMETHOD SetLoadGroup(nsILoadGroup *aLoadGroup);
|
||||
NS_IMETHOD GetProtocol(nsACString &aProtocol);
|
||||
NS_IMETHOD SetProtocol(const nsACString &aProtocol);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIURI> mOriginalURI;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIWebSocketListener> mListener;
|
||||
nsCOMPtr<nsISupports> mContext;
|
||||
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
|
||||
nsCString mProtocol;
|
||||
nsCString mOrigin;
|
||||
|
||||
PRBool mEncrypted;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_net_BaseWebSocketChannel_h
|
|
@ -49,16 +49,30 @@ XPIDL_MODULE = necko_websocket
|
|||
GRE_MODULE = 1
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
EXPORTS_NAMESPACES = mozilla/net
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIWebSocketProtocol.idl \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsWebSocketHandler.cpp
|
||||
nsWebSocketHandler.cpp \
|
||||
WebSocketChannelParent.cpp \
|
||||
WebSocketChannelChild.cpp \
|
||||
BaseWebSocketChannel.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_mozilla/net = \
|
||||
nsWebSocketHandler.h \
|
||||
WebSocketChannelParent.h \
|
||||
WebSocketChannelChild.h \
|
||||
BaseWebSocketChannel.h \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(srcdir)/../../base/src \
|
||||
-I$(topsrcdir)/content/base/src \
|
||||
-I$(topsrcdir)/content/events/src \
|
||||
-I$(topsrcdir)/xpcom/ds \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Josh Matthews <josh@joshmatthews.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
include protocol PNecko;
|
||||
include protocol PBrowser;
|
||||
|
||||
include "mozilla/net/NeckoMessageUtils.h";
|
||||
|
||||
using IPC::URI;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
async protocol PWebSocket
|
||||
{
|
||||
manager PNecko;
|
||||
|
||||
parent:
|
||||
// Forwarded methods corresponding to methods on nsIWebSocketProtocolHandler
|
||||
AsyncOpen(URI aURI, nsCString aOrigin, nsCString aProtocol, bool aSecure);
|
||||
Close();
|
||||
SendMsg(nsCString aMsg);
|
||||
SendBinaryMsg(nsCString aMsg);
|
||||
|
||||
DeleteSelf();
|
||||
|
||||
child:
|
||||
// Forwarded notifications corresponding to the nsIWebSocketListener interface
|
||||
OnStart(nsCString aProtocol);
|
||||
OnStop(nsresult aStatusCode);
|
||||
OnMessageAvailable(nsCString aMsg);
|
||||
OnBinaryMessageAvailable(nsCString aMsg);
|
||||
OnAcknowledge(PRUint32 aSize);
|
||||
OnServerClose();
|
||||
|
||||
// Only sent in the event that AsyncOpen fails
|
||||
AsyncOpenFailed();
|
||||
|
||||
__delete__();
|
||||
|
||||
};
|
||||
|
||||
} //namespace net
|
||||
} //namespace mozilla
|
|
@ -0,0 +1,446 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Josh Matthews <josh@joshmatthews.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "WebSocketLog.h"
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
#include "WebSocketChannelChild.h"
|
||||
#include "nsITabChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
NS_IMPL_ADDREF(WebSocketChannelChild)
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt) WebSocketChannelChild::Release()
|
||||
{
|
||||
NS_PRECONDITION(0 != mRefCnt, "dup release");
|
||||
NS_ASSERT_OWNINGTHREAD(WebSocketChannelChild);
|
||||
--mRefCnt;
|
||||
NS_LOG_RELEASE(this, mRefCnt, "WebSocketChannelChild");
|
||||
|
||||
if (mRefCnt == 1 && mIPCOpen) {
|
||||
SendDeleteSelf();
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
if (mRefCnt == 0) {
|
||||
mRefCnt = 1; /* stabilize */
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(WebSocketChannelChild)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIWebSocketProtocol)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIProtocolHandler)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebSocketProtocol)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
WebSocketChannelChild::WebSocketChannelChild(bool aSecure)
|
||||
: mEventQ(static_cast<nsIWebSocketProtocol*>(this))
|
||||
, mIPCOpen(false)
|
||||
, mCancelled(false)
|
||||
{
|
||||
LOG(("WebSocketChannelChild::WebSocketChannelChild() %p\n", this));
|
||||
BaseWebSocketChannel::mEncrypted = aSecure;
|
||||
}
|
||||
|
||||
WebSocketChannelChild::~WebSocketChannelChild()
|
||||
{
|
||||
LOG(("WebSocketChannelChild::~WebSocketChannelChild() %p\n", this));
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketChannelChild::AddIPDLReference()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(!mIPCOpen, "Attempt to retain more than one IPDL reference");
|
||||
mIPCOpen = true;
|
||||
AddRef();
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketChannelChild::ReleaseIPDLReference()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(mIPCOpen, "Attempt to release nonexistent IPDL reference");
|
||||
mIPCOpen = false;
|
||||
Release();
|
||||
}
|
||||
|
||||
class StartEvent : public ChannelEvent
|
||||
{
|
||||
public:
|
||||
StartEvent(WebSocketChannelChild* aChild,
|
||||
const nsCString& aProtocol)
|
||||
: mChild(aChild)
|
||||
, mProtocol(aProtocol)
|
||||
{}
|
||||
|
||||
void Run()
|
||||
{
|
||||
mChild->OnStart(mProtocol);
|
||||
}
|
||||
private:
|
||||
WebSocketChannelChild* mChild;
|
||||
nsCString mProtocol;
|
||||
};
|
||||
|
||||
bool
|
||||
WebSocketChannelChild::RecvOnStart(const nsCString& aProtocol)
|
||||
{
|
||||
if (mEventQ.ShouldEnqueue()) {
|
||||
mEventQ.Enqueue(new StartEvent(this, aProtocol));
|
||||
} else {
|
||||
OnStart(aProtocol);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketChannelChild::OnStart(const nsCString& aProtocol)
|
||||
{
|
||||
LOG(("WebSocketChannelChild::RecvOnStart() %p\n", this));
|
||||
SetProtocol(aProtocol);
|
||||
if (mListener) {
|
||||
AutoEventEnqueuer ensureSerialDispatch(mEventQ);;
|
||||
mListener->OnStart(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
class StopEvent : public ChannelEvent
|
||||
{
|
||||
public:
|
||||
StopEvent(WebSocketChannelChild* aChild,
|
||||
const nsresult& aStatusCode)
|
||||
: mChild(aChild)
|
||||
, mStatusCode(aStatusCode)
|
||||
{}
|
||||
|
||||
void Run()
|
||||
{
|
||||
mChild->OnStop(mStatusCode);
|
||||
}
|
||||
private:
|
||||
WebSocketChannelChild* mChild;
|
||||
nsresult mStatusCode;
|
||||
};
|
||||
|
||||
bool
|
||||
WebSocketChannelChild::RecvOnStop(const nsresult& aStatusCode)
|
||||
{
|
||||
if (mEventQ.ShouldEnqueue()) {
|
||||
mEventQ.Enqueue(new StopEvent(this, aStatusCode));
|
||||
} else {
|
||||
OnStop(aStatusCode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketChannelChild::OnStop(const nsresult& aStatusCode)
|
||||
{
|
||||
LOG(("WebSocketChannelChild::RecvOnStop() %p\n", this));
|
||||
if (mListener) {
|
||||
AutoEventEnqueuer ensureSerialDispatch(mEventQ);;
|
||||
mListener->OnStop(mContext, aStatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
class MessageEvent : public ChannelEvent
|
||||
{
|
||||
public:
|
||||
MessageEvent(WebSocketChannelChild* aChild,
|
||||
const nsCString& aMessage,
|
||||
bool aBinary)
|
||||
: mChild(aChild)
|
||||
, mMessage(aMessage)
|
||||
, mBinary(aBinary)
|
||||
{}
|
||||
|
||||
void Run()
|
||||
{
|
||||
if (!mBinary) {
|
||||
mChild->OnMessageAvailable(mMessage);
|
||||
} else {
|
||||
mChild->OnBinaryMessageAvailable(mMessage);
|
||||
}
|
||||
}
|
||||
private:
|
||||
WebSocketChannelChild* mChild;
|
||||
nsCString mMessage;
|
||||
bool mBinary;
|
||||
};
|
||||
|
||||
bool
|
||||
WebSocketChannelChild::RecvOnMessageAvailable(const nsCString& aMsg)
|
||||
{
|
||||
if (mEventQ.ShouldEnqueue()) {
|
||||
mEventQ.Enqueue(new MessageEvent(this, aMsg, false));
|
||||
} else {
|
||||
OnMessageAvailable(aMsg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketChannelChild::OnMessageAvailable(const nsCString& aMsg)
|
||||
{
|
||||
LOG(("WebSocketChannelChild::RecvOnMessageAvailable() %p\n", this));
|
||||
if (mListener) {
|
||||
AutoEventEnqueuer ensureSerialDispatch(mEventQ);;
|
||||
mListener->OnMessageAvailable(mContext, aMsg);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
WebSocketChannelChild::RecvOnBinaryMessageAvailable(const nsCString& aMsg)
|
||||
{
|
||||
if (mEventQ.ShouldEnqueue()) {
|
||||
mEventQ.Enqueue(new MessageEvent(this, aMsg, true));
|
||||
} else {
|
||||
OnBinaryMessageAvailable(aMsg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketChannelChild::OnBinaryMessageAvailable(const nsCString& aMsg)
|
||||
{
|
||||
LOG(("WebSocketChannelChild::RecvOnBinaryMessageAvailable() %p\n", this));
|
||||
if (mListener) {
|
||||
AutoEventEnqueuer ensureSerialDispatch(mEventQ);;
|
||||
mListener->OnBinaryMessageAvailable(mContext, aMsg);
|
||||
}
|
||||
}
|
||||
|
||||
class AcknowledgeEvent : public ChannelEvent
|
||||
{
|
||||
public:
|
||||
AcknowledgeEvent(WebSocketChannelChild* aChild,
|
||||
const PRUint32& aSize)
|
||||
: mChild(aChild)
|
||||
, mSize(aSize)
|
||||
{}
|
||||
|
||||
void Run()
|
||||
{
|
||||
mChild->OnAcknowledge(mSize);
|
||||
}
|
||||
private:
|
||||
WebSocketChannelChild* mChild;
|
||||
PRUint32 mSize;
|
||||
};
|
||||
|
||||
bool
|
||||
WebSocketChannelChild::RecvOnAcknowledge(const PRUint32& aSize)
|
||||
{
|
||||
if (mEventQ.ShouldEnqueue()) {
|
||||
mEventQ.Enqueue(new AcknowledgeEvent(this, aSize));
|
||||
} else {
|
||||
OnAcknowledge(aSize);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketChannelChild::OnAcknowledge(const PRUint32& aSize)
|
||||
{
|
||||
LOG(("WebSocketChannelChild::RecvOnAcknowledge() %p\n", this));
|
||||
if (mListener) {
|
||||
AutoEventEnqueuer ensureSerialDispatch(mEventQ);;
|
||||
mListener->OnAcknowledge(mContext, aSize);
|
||||
}
|
||||
}
|
||||
|
||||
class ServerCloseEvent : public ChannelEvent
|
||||
{
|
||||
public:
|
||||
ServerCloseEvent(WebSocketChannelChild* aChild)
|
||||
: mChild(aChild)
|
||||
{}
|
||||
|
||||
void Run()
|
||||
{
|
||||
mChild->OnServerClose();
|
||||
}
|
||||
private:
|
||||
WebSocketChannelChild* mChild;
|
||||
};
|
||||
|
||||
bool
|
||||
WebSocketChannelChild::RecvOnServerClose()
|
||||
{
|
||||
if (mEventQ.ShouldEnqueue()) {
|
||||
mEventQ.Enqueue(new ServerCloseEvent(this));
|
||||
} else {
|
||||
OnServerClose();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketChannelChild::OnServerClose()
|
||||
{
|
||||
LOG(("WebSocketChannelChild::RecvOnServerClose() %p\n", this));
|
||||
if (mListener) {
|
||||
AutoEventEnqueuer ensureSerialDispatch(mEventQ);;
|
||||
mListener->OnServerClose(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
class AsyncOpenFailedEvent : public ChannelEvent
|
||||
{
|
||||
public:
|
||||
AsyncOpenFailedEvent(WebSocketChannelChild* aChild)
|
||||
: mChild(aChild)
|
||||
{}
|
||||
|
||||
void Run()
|
||||
{
|
||||
mChild->AsyncOpenFailed();
|
||||
}
|
||||
private:
|
||||
WebSocketChannelChild* mChild;
|
||||
};
|
||||
|
||||
bool
|
||||
WebSocketChannelChild::RecvAsyncOpenFailed()
|
||||
{
|
||||
if (mEventQ.ShouldEnqueue()) {
|
||||
mEventQ.Enqueue(new AsyncOpenFailedEvent(this));
|
||||
} else {
|
||||
AsyncOpenFailed();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketChannelChild::AsyncOpenFailed()
|
||||
{
|
||||
LOG(("WebSocketChannelChild::RecvAsyncOpenFailed() %p\n", this));
|
||||
mCancelled = true;
|
||||
if (mIPCOpen)
|
||||
SendDeleteSelf();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketChannelChild::AsyncOpen(nsIURI *aURI,
|
||||
const nsACString &aOrigin,
|
||||
nsIWebSocketListener *aListener,
|
||||
nsISupports *aContext)
|
||||
{
|
||||
LOG(("WebSocketChannelChild::AsyncOpen() %p\n", this));
|
||||
|
||||
NS_ABORT_IF_FALSE(aURI && aListener && !mListener,
|
||||
"Invalid state for WebSocketChannelChild::AsyncOpen");
|
||||
|
||||
mozilla::dom::TabChild* tabChild = nsnull;
|
||||
nsCOMPtr<nsITabChild> iTabChild;
|
||||
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
|
||||
NS_GET_IID(nsITabChild),
|
||||
getter_AddRefs(iTabChild));
|
||||
if (iTabChild) {
|
||||
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
|
||||
}
|
||||
|
||||
// Corresponding release in DeallocPWebSocket
|
||||
AddIPDLReference();
|
||||
|
||||
gNeckoChild->SendPWebSocketConstructor(this, tabChild);
|
||||
if (!SendAsyncOpen(aURI, nsCString(aOrigin), mProtocol, mEncrypted))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
mOriginalURI = aURI;
|
||||
mURI = mOriginalURI;
|
||||
mListener = aListener;
|
||||
mContext = aContext;
|
||||
mOrigin = aOrigin;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketChannelChild::Close()
|
||||
{
|
||||
LOG(("WebSocketChannelChild::Close() %p\n", this));
|
||||
|
||||
if (mCancelled)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
if (!mIPCOpen || !SendClose())
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketChannelChild::SendMsg(const nsACString &aMsg)
|
||||
{
|
||||
LOG(("WebSocketChannelChild::SendMsg() %p\n", this));
|
||||
|
||||
if (mCancelled)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
if (!mIPCOpen || !SendSendMsg(nsCString(aMsg)))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketChannelChild::SendBinaryMsg(const nsACString &aMsg)
|
||||
{
|
||||
LOG(("WebSocketChannelChild::SendBinaryMsg() %p\n", this));
|
||||
|
||||
if (mCancelled)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
if (!mIPCOpen || !SendSendBinaryMsg(nsCString(aMsg)))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketChannelChild::GetSecurityInfo(nsISupports **aSecurityInfo)
|
||||
{
|
||||
LOG(("WebSocketChannelChild::GetSecurityInfo() %p\n", this));
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,107 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Josh Matthews <josh@joshmatthews.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_net_WebSocketChannelChild_h
|
||||
#define mozilla_net_WebSocketChannelChild_h
|
||||
|
||||
#include "mozilla/net/PWebSocketChild.h"
|
||||
#include "mozilla/net/ChannelEventQueue.h"
|
||||
#include "mozilla/net/BaseWebSocketChannel.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class WebSocketChannelChild : public BaseWebSocketChannel,
|
||||
public PWebSocketChild
|
||||
{
|
||||
public:
|
||||
WebSocketChannelChild(bool aSecure);
|
||||
~WebSocketChannelChild();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIWebSocketProtocol methods BaseWebSocketChannel didn't implement for us
|
||||
//
|
||||
NS_SCRIPTABLE NS_IMETHOD AsyncOpen(nsIURI *aURI,
|
||||
const nsACString &aOrigin,
|
||||
nsIWebSocketListener *aListener,
|
||||
nsISupports *aContext);
|
||||
NS_SCRIPTABLE NS_IMETHOD Close();
|
||||
NS_SCRIPTABLE NS_IMETHOD SendMsg(const nsACString &aMsg);
|
||||
NS_SCRIPTABLE NS_IMETHOD SendBinaryMsg(const nsACString &aMsg);
|
||||
NS_SCRIPTABLE NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo);
|
||||
|
||||
void AddIPDLReference();
|
||||
void ReleaseIPDLReference();
|
||||
|
||||
private:
|
||||
bool RecvOnStart(const nsCString& aProtocol);
|
||||
bool RecvOnStop(const nsresult& aStatusCode);
|
||||
bool RecvOnMessageAvailable(const nsCString& aMsg);
|
||||
bool RecvOnBinaryMessageAvailable(const nsCString& aMsg);
|
||||
bool RecvOnAcknowledge(const PRUint32& aSize);
|
||||
bool RecvOnServerClose();
|
||||
bool RecvAsyncOpenFailed();
|
||||
|
||||
void OnStart(const nsCString& aProtocol);
|
||||
void OnStop(const nsresult& aStatusCode);
|
||||
void OnMessageAvailable(const nsCString& aMsg);
|
||||
void OnBinaryMessageAvailable(const nsCString& aMsg);
|
||||
void OnAcknowledge(const PRUint32& aSize);
|
||||
void OnServerClose();
|
||||
void AsyncOpenFailed();
|
||||
|
||||
ChannelEventQueue mEventQ;
|
||||
bool mIPCOpen;
|
||||
bool mCancelled;
|
||||
|
||||
friend class StartEvent;
|
||||
friend class StopEvent;
|
||||
friend class MessageEvent;
|
||||
friend class AcknowledgeEvent;
|
||||
friend class ServerCloseEvent;
|
||||
friend class AsyncOpenFailedEvent;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_net_WebSocketChannelChild_h
|
|
@ -0,0 +1,226 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Josh Matthews <josh@joshmatthews.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "WebSocketLog.h"
|
||||
#include "WebSocketChannelParent.h"
|
||||
#include "nsIAuthPromptProvider.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(WebSocketChannelParent,
|
||||
nsIWebSocketListener,
|
||||
nsIInterfaceRequestor)
|
||||
|
||||
WebSocketChannelParent::WebSocketChannelParent(nsIAuthPromptProvider* aAuthProvider)
|
||||
: mAuthProvider(aAuthProvider)
|
||||
, mIPCOpen(true)
|
||||
{
|
||||
#if defined(PR_LOGGING)
|
||||
if (!webSocketLog)
|
||||
webSocketLog = PR_NewLogModule("nsWebSocket");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
WebSocketChannelParent::RecvDeleteSelf()
|
||||
{
|
||||
LOG(("WebSocketChannelParent::RecvDeleteSelf() %p\n", this));
|
||||
mChannel = nsnull;
|
||||
mAuthProvider = nsnull;
|
||||
return mIPCOpen ? Send__delete__(this) : true;
|
||||
}
|
||||
|
||||
bool
|
||||
WebSocketChannelParent::RecvAsyncOpen(const IPC::URI& aURI,
|
||||
const nsCString& aOrigin,
|
||||
const nsCString& aProtocol,
|
||||
const bool& aSecure)
|
||||
{
|
||||
LOG(("WebSocketChannelParent::RecvAsyncOpen() %p\n", this));
|
||||
nsresult rv;
|
||||
if (aSecure) {
|
||||
mChannel =
|
||||
do_CreateInstance("@mozilla.org/network/protocol;1?name=wss", &rv);
|
||||
} else {
|
||||
mChannel =
|
||||
do_CreateInstance("@mozilla.org/network/protocol;1?name=ws", &rv);
|
||||
}
|
||||
if (NS_FAILED(rv))
|
||||
return CancelEarly();
|
||||
|
||||
rv = mChannel->SetNotificationCallbacks(this);
|
||||
if (NS_FAILED(rv))
|
||||
return CancelEarly();
|
||||
|
||||
rv = mChannel->SetProtocol(aProtocol);
|
||||
if (NS_FAILED(rv))
|
||||
return CancelEarly();
|
||||
|
||||
rv = mChannel->AsyncOpen(aURI, aOrigin, this, nsnull);
|
||||
if (NS_FAILED(rv))
|
||||
return CancelEarly();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WebSocketChannelParent::RecvClose()
|
||||
{
|
||||
LOG(("WebSocketChannelParent::RecvClose() %p\n", this));
|
||||
if (mChannel) {
|
||||
nsresult rv = mChannel->Close();
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WebSocketChannelParent::RecvSendMsg(const nsCString& aMsg)
|
||||
{
|
||||
LOG(("WebSocketChannelParent::RecvSendMsg() %p\n", this));
|
||||
if (mChannel) {
|
||||
nsresult rv = mChannel->SendMsg(aMsg);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WebSocketChannelParent::RecvSendBinaryMsg(const nsCString& aMsg)
|
||||
{
|
||||
LOG(("WebSocketChannelParent::RecvSendBinaryMsg() %p\n", this));
|
||||
if (mChannel) {
|
||||
nsresult rv = mChannel->SendBinaryMsg(aMsg);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WebSocketChannelParent::CancelEarly()
|
||||
{
|
||||
LOG(("WebSocketChannelParent::CancelEarly() %p\n", this));
|
||||
return mIPCOpen ? SendAsyncOpenFailed() : true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketChannelParent::GetInterface(const nsIID & iid, void **result NS_OUTPARAM)
|
||||
{
|
||||
LOG(("WebSocketChannelParent::GetInterface() %p\n", this));
|
||||
if (mAuthProvider && iid.Equals(NS_GET_IID(nsIAuthPromptProvider)))
|
||||
return mAuthProvider->GetAuthPrompt(nsIAuthPromptProvider::PROMPT_NORMAL,
|
||||
iid, result);
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketChannelParent::OnStart(nsISupports *aContext)
|
||||
{
|
||||
LOG(("WebSocketChannelParent::OnStart() %p\n", this));
|
||||
nsCAutoString protocol;
|
||||
if (mChannel) {
|
||||
mChannel->GetProtocol(protocol);
|
||||
}
|
||||
if (!mIPCOpen || !SendOnStart(protocol)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketChannelParent::OnStop(nsISupports *aContext, nsresult aStatusCode)
|
||||
{
|
||||
LOG(("WebSocketChannelParent::OnStop() %p\n", this));
|
||||
if (!mIPCOpen || !SendOnStop(aStatusCode)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketChannelParent::OnMessageAvailable(nsISupports *aContext, const nsACString& aMsg)
|
||||
{
|
||||
LOG(("WebSocketChannelParent::OnMessageAvailable() %p\n", this));
|
||||
if (!mIPCOpen || !SendOnMessageAvailable(nsCString(aMsg))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketChannelParent::OnBinaryMessageAvailable(nsISupports *aContext, const nsACString& aMsg)
|
||||
{
|
||||
LOG(("WebSocketChannelParent::OnBinaryMessageAvailable() %p\n", this));
|
||||
if (!mIPCOpen || !SendOnBinaryMessageAvailable(nsCString(aMsg))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketChannelParent::OnAcknowledge(nsISupports *aContext, PRUint32 aSize)
|
||||
{
|
||||
LOG(("WebSocketChannelParent::OnAcknowledge() %p\n", this));
|
||||
if (!mIPCOpen || !SendOnAcknowledge(aSize)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebSocketChannelParent::OnServerClose(nsISupports *aContext)
|
||||
{
|
||||
LOG(("WebSocketChannelParent::OnServerClose() %p\n", this));
|
||||
if (!mIPCOpen || !SendOnServerClose()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
WebSocketChannelParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
LOG(("WebSocketChannelParent::ActorDestroy() %p\n", this));
|
||||
mIPCOpen = false;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,85 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Josh Matthews <josh@joshmatthews.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_net_WebSocketChannelParent_h
|
||||
#define mozilla_net_WebSocketChannelParent_h
|
||||
|
||||
#include "mozilla/net/PWebSocketParent.h"
|
||||
#include "mozilla/net/nsWebSocketHandler.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsIAuthPromptProvider;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class WebSocketChannelParent : public PWebSocketParent,
|
||||
public nsIWebSocketListener,
|
||||
public nsIInterfaceRequestor
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEBSOCKETLISTENER
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
|
||||
WebSocketChannelParent(nsIAuthPromptProvider* aAuthProvider);
|
||||
|
||||
private:
|
||||
bool RecvAsyncOpen(const IPC::URI& aURI,
|
||||
const nsCString& aOrigin,
|
||||
const nsCString& aProtocol,
|
||||
const bool& aSecure);
|
||||
bool RecvClose();
|
||||
bool RecvSendMsg(const nsCString& aMsg);
|
||||
bool RecvSendBinaryMsg(const nsCString& aMsg);
|
||||
bool RecvDeleteSelf();
|
||||
bool CancelEarly();
|
||||
|
||||
void ActorDestroy(ActorDestroyReason why);
|
||||
|
||||
nsCOMPtr<nsIAuthPromptProvider> mAuthProvider;
|
||||
nsCOMPtr<nsIWebSocketProtocol> mChannel;
|
||||
bool mIPCOpen;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_net_WebSocketChannelParent_h
|
|
@ -0,0 +1,62 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Josh Matthews <josh@joshmatthews.net>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef WebSocketLog_h
|
||||
#define WebSocketLog_h
|
||||
|
||||
#ifdef MOZ_LOGGING
|
||||
#define FORCE_PR_LOG
|
||||
#endif
|
||||
|
||||
#if defined(PR_LOG)
|
||||
#error "This file must be #included before any IPDL-generated files or other files that #include prlog.h"
|
||||
#endif
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "prlog.h"
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* webSocketLog;
|
||||
#endif
|
||||
|
||||
#undef LOG
|
||||
#define LOG(args) PR_LOG(webSocketLog, PR_LOG_DEBUG, args)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,40 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Mozilla Firefox.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# The Mozilla Foundation <http://www.mozilla.org/>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Josh Matthews <josh@joshmatthews.net>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
IPDLSRCS = \
|
||||
PWebSocket.ipdl \
|
||||
$(NULL)
|
|
@ -37,6 +37,7 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "WebSocketLog.h"
|
||||
#include "nsWebSocketHandler.h"
|
||||
|
||||
#include "nsISocketTransportService.h"
|
||||
|
@ -69,7 +70,6 @@
|
|||
#include "prmem.h"
|
||||
#include "prnetdb.h"
|
||||
#include "prbit.h"
|
||||
#include "prlog.h"
|
||||
#include "zlib.h"
|
||||
|
||||
extern PRThread *gSocketThread;
|
||||
|
@ -90,11 +90,6 @@ NS_IMPL_THREADSAFE_ISUPPORTS11(nsWebSocketHandler,
|
|||
nsIInterfaceRequestor,
|
||||
nsIChannelEventSink)
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
static PRLogModuleInfo *webSocketLog = nsnull;
|
||||
#endif
|
||||
#define LOG(args) PR_LOG(webSocketLog, PR_LOG_DEBUG, args)
|
||||
|
||||
// Use this fake ptr so the Fin message stays in sequence in the
|
||||
// main transmit queue
|
||||
#define kFinMessage (reinterpret_cast<nsCString *>(0x01))
|
||||
|
@ -490,7 +485,6 @@ static nsWSAdmissionManager *sWebSocketAdmissions = nsnull;
|
|||
// nsWebSocketHandler
|
||||
|
||||
nsWebSocketHandler::nsWebSocketHandler() :
|
||||
mEncrypted(PR_FALSE),
|
||||
mCloseTimeout(20000),
|
||||
mOpenTimeout(20000),
|
||||
mPingTimeout(0),
|
||||
|
@ -522,10 +516,6 @@ nsWebSocketHandler::nsWebSocketHandler() :
|
|||
mDynamicOutput(nsnull)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "not main thread");
|
||||
#if defined(PR_LOGGING)
|
||||
if (!webSocketLog)
|
||||
webSocketLog = PR_NewLogModule("nsWebSocket");
|
||||
#endif
|
||||
|
||||
LOG(("WebSocketHandler::nsWebSocketHandler() %p\n", this));
|
||||
|
||||
|
@ -1894,50 +1884,6 @@ nsWebSocketHandler::Notify(nsITimer *timer)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIWebSocketProtocol
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketHandler::GetOriginalURI(nsIURI **aOriginalURI)
|
||||
{
|
||||
LOG(("WebSocketHandler::GetOriginalURI() %p\n", this));
|
||||
|
||||
if (!mOriginalURI)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
NS_ADDREF(*aOriginalURI = mOriginalURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketHandler::GetURI(nsIURI **aURI)
|
||||
{
|
||||
LOG(("WebSocketHandler::GetURI() %p\n", this));
|
||||
|
||||
if (!mOriginalURI)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
if (mURI)
|
||||
NS_ADDREF(*aURI = mURI);
|
||||
else
|
||||
NS_ADDREF(*aURI = mOriginalURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketHandler::
|
||||
GetNotificationCallbacks(nsIInterfaceRequestor **aNotificationCallbacks)
|
||||
{
|
||||
LOG(("WebSocketHandler::GetNotificationCallbacks() %p\n", this));
|
||||
NS_IF_ADDREF(*aNotificationCallbacks = mCallbacks);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketHandler::
|
||||
SetNotificationCallbacks(nsIInterfaceRequestor *aNotificationCallbacks)
|
||||
{
|
||||
LOG(("WebSocketHandler::SetNotificationCallbacks() %p\n", this));
|
||||
mCallbacks = aNotificationCallbacks;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketHandler::GetSecurityInfo(nsISupports **aSecurityInfo)
|
||||
|
@ -1952,37 +1898,6 @@ nsWebSocketHandler::GetSecurityInfo(nsISupports **aSecurityInfo)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketHandler::GetLoadGroup(nsILoadGroup **aLoadGroup)
|
||||
{
|
||||
LOG(("WebSocketHandler::GetLoadGroup() %p\n", this));
|
||||
NS_IF_ADDREF(*aLoadGroup = mLoadGroup);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketHandler::SetLoadGroup(nsILoadGroup *aLoadGroup)
|
||||
{
|
||||
LOG(("WebSocketHandler::SetLoadGroup() %p\n", this));
|
||||
mLoadGroup = aLoadGroup;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketHandler::GetProtocol(nsACString &aProtocol)
|
||||
{
|
||||
LOG(("WebSocketHandler::GetProtocol() %p\n", this));
|
||||
aProtocol = mProtocol;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketHandler::SetProtocol(const nsACString &aProtocol)
|
||||
{
|
||||
LOG(("WebSocketHandler::SetProtocol() %p\n", this));
|
||||
mProtocol = aProtocol; /* the sub protocol */
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketHandler::AsyncOpen(nsIURI *aURI,
|
||||
|
@ -2664,79 +2579,5 @@ nsWebSocketHandler::OnDataAvailable(nsIRequest *aRequest,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIProtocolHandler
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketHandler::GetScheme(nsACString &aScheme)
|
||||
{
|
||||
LOG(("WebSocketHandler::GetScheme() %p\n", this));
|
||||
|
||||
if (mEncrypted)
|
||||
aScheme.AssignLiteral("wss");
|
||||
else
|
||||
aScheme.AssignLiteral("ws");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketHandler::GetDefaultPort(PRInt32 *aDefaultPort)
|
||||
{
|
||||
LOG(("WebSocketHandler::GetDefaultPort() %p\n", this));
|
||||
|
||||
if (mEncrypted)
|
||||
*aDefaultPort = kDefaultWSSPort;
|
||||
else
|
||||
*aDefaultPort = kDefaultWSPort;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketHandler::GetProtocolFlags(PRUint32 *aProtocolFlags)
|
||||
{
|
||||
LOG(("WebSocketHandler::GetProtocolFlags() %p\n", this));
|
||||
|
||||
*aProtocolFlags = URI_NORELATIVE | URI_NON_PERSISTABLE | ALLOWS_PROXY |
|
||||
ALLOWS_PROXY_HTTP | URI_DOES_NOT_RETURN_DATA | URI_DANGEROUS_TO_LOAD;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketHandler::NewURI(const nsACString & aSpec, const char *aOriginCharset,
|
||||
nsIURI *aBaseURI, nsIURI **_retval NS_OUTPARAM)
|
||||
{
|
||||
LOG(("WebSocketHandler::NewURI() %p\n", this));
|
||||
|
||||
PRInt32 port;
|
||||
nsresult rv = GetDefaultPort(&port);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsRefPtr<nsStandardURL> url = new nsStandardURL();
|
||||
rv = url->Init(nsIStandardURL::URLTYPE_AUTHORITY, port, aSpec,
|
||||
aOriginCharset, aBaseURI);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
NS_ADDREF(*_retval = url);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketHandler::NewChannel(nsIURI *aURI, nsIChannel **_retval NS_OUTPARAM)
|
||||
{
|
||||
LOG(("WebSocketHandler::NewChannel() %p\n", this));
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocketHandler::AllowPort(PRInt32 port, const char *scheme,
|
||||
PRBool *_retval NS_OUTPARAM)
|
||||
{
|
||||
LOG(("WebSocketHandler::AllowPort() %p\n", this));
|
||||
|
||||
// do not override any blacklisted ports
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace mozilla::net
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_net_nsWebSocketHandler_h
|
||||
#define mozilla_net_nsWebSocketHandler_h
|
||||
|
||||
#include "nsIWebSocketProtocol.h"
|
||||
#include "nsIURI.h"
|
||||
|
@ -57,6 +59,7 @@
|
|||
#include "nsIStringStream.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIRandomGenerator.h"
|
||||
#include "BaseWebSocketChannel.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
|
@ -68,10 +71,9 @@ class nsPostMessage;
|
|||
class nsWSAdmissionManager;
|
||||
class nsWSCompression;
|
||||
|
||||
class nsWebSocketHandler : public nsIWebSocketProtocol,
|
||||
class nsWebSocketHandler : public BaseWebSocketChannel,
|
||||
public nsIHttpUpgradeListener,
|
||||
public nsIStreamListener,
|
||||
public nsIProtocolHandler,
|
||||
public nsIInputStreamCallback,
|
||||
public nsIOutputStreamCallback,
|
||||
public nsITimerCallback,
|
||||
|
@ -81,11 +83,9 @@ class nsWebSocketHandler : public nsIWebSocketProtocol,
|
|||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEBSOCKETPROTOCOL
|
||||
NS_DECL_NSIHTTPUPGRADELISTENER
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSIPROTOCOLHANDLER
|
||||
NS_DECL_NSIINPUTSTREAMCALLBACK
|
||||
NS_DECL_NSIOUTPUTSTREAMCALLBACK
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
|
@ -93,6 +93,17 @@ public:
|
|||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
|
||||
// nsIWebSocketProtocol methods BaseWebSocketChannel didn't implement for us
|
||||
//
|
||||
NS_IMETHOD AsyncOpen(nsIURI *aURI,
|
||||
const nsACString &aOrigin,
|
||||
nsIWebSocketListener *aListener,
|
||||
nsISupports *aContext);
|
||||
NS_IMETHOD Close();
|
||||
NS_IMETHOD SendMsg(const nsACString &aMsg);
|
||||
NS_IMETHOD SendBinaryMsg(const nsACString &aMsg);
|
||||
NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo);
|
||||
|
||||
nsWebSocketHandler();
|
||||
static void Shutdown();
|
||||
|
||||
|
@ -109,8 +120,6 @@ public:
|
|||
};
|
||||
|
||||
const static PRUint32 kControlFrameMask = 0x8;
|
||||
const static PRInt32 kDefaultWSPort = 80;
|
||||
const static PRInt32 kDefaultWSSPort = 443;
|
||||
const static PRUint8 kMaskBit = 0x80;
|
||||
const static PRUint8 kFinalFragBit = 0x80;
|
||||
|
||||
|
@ -125,8 +134,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual ~nsWebSocketHandler();
|
||||
PRBool mEncrypted;
|
||||
|
||||
|
||||
private:
|
||||
friend class nsPostMessage;
|
||||
friend class nsWSAdmissionManager;
|
||||
|
@ -196,11 +204,6 @@ private:
|
|||
PRInt32 mBinaryLen;
|
||||
};
|
||||
|
||||
nsCOMPtr<nsIURI> mOriginalURI;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIWebSocketListener> mListener;
|
||||
nsCOMPtr<nsISupports> mContext;
|
||||
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
|
||||
nsCOMPtr<nsIEventTarget> mSocketThread;
|
||||
nsCOMPtr<nsIHttpChannelInternal> mChannel;
|
||||
nsCOMPtr<nsIHttpChannel> mHttpChannel;
|
||||
|
@ -209,8 +212,6 @@ private:
|
|||
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
|
||||
nsCOMPtr<nsIRandomGenerator> mRandomGenerator;
|
||||
|
||||
nsCString mProtocol;
|
||||
nsCString mOrigin;
|
||||
nsCString mHashedSecret;
|
||||
nsCString mAddress;
|
||||
|
||||
|
@ -280,9 +281,11 @@ private:
|
|||
class nsWebSocketSSLHandler : public nsWebSocketHandler
|
||||
{
|
||||
public:
|
||||
nsWebSocketSSLHandler() {nsWebSocketHandler::mEncrypted = PR_TRUE;}
|
||||
nsWebSocketSSLHandler() { BaseWebSocketChannel::mEncrypted = PR_TRUE; }
|
||||
protected:
|
||||
virtual ~nsWebSocketSSLHandler() {}
|
||||
};
|
||||
|
||||
}} // namespace mozilla::net
|
||||
|
||||
#endif // mozilla_net_nsWebSocketHandler_h
|
||||
|
|
|
@ -212,6 +212,10 @@ SpecialPowers.prototype = {
|
|||
this.DOMWindowUtils.garbageCollect();
|
||||
},
|
||||
|
||||
forceGC: function() {
|
||||
Components.utils.forceGC();
|
||||
},
|
||||
|
||||
hasContentProcesses: function() {
|
||||
try {
|
||||
var rt = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
|
||||
|
|
|
@ -208,9 +208,8 @@ TelemetryPing.prototype = {
|
|||
let memReporters = {};
|
||||
while (e.hasMoreElements()) {
|
||||
let mr = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
|
||||
// memReporters[mr.path] = mr.amount;
|
||||
let id = MEM_HISTOGRAMS[mr.path];
|
||||
if (!id) {
|
||||
if (!id || mr.amount == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -224,15 +223,15 @@ TelemetryPing.prototype = {
|
|||
|
||||
// Read mr.amount just once so our arithmetic is consistent.
|
||||
let curVal = mr.amount;
|
||||
let prevVal = this._prevValues[mr.path];
|
||||
if (!prevVal) {
|
||||
if (!(mr.path in this._prevValues)) {
|
||||
// If this is the first time we're reading this reporter, store its
|
||||
// current value but don't report it in the telemetry ping, so we
|
||||
// ignore the effect startup had on the reporter.
|
||||
this._prevValues[mr.path] = curVal;
|
||||
continue;
|
||||
}
|
||||
val = curVal - prevVal;
|
||||
|
||||
val = curVal - this._prevValues[mr.path];
|
||||
this._prevValues[mr.path] = curVal;
|
||||
}
|
||||
else {
|
||||
|
@ -245,9 +244,7 @@ TelemetryPing.prototype = {
|
|||
h = Telemetry.getHistogramById(id);
|
||||
this._histograms[mr.path] = h;
|
||||
}
|
||||
// hack to deal with some memory reporters returning 0
|
||||
if (val)
|
||||
h.add(val);
|
||||
h.add(val);
|
||||
}
|
||||
return memReporters;
|
||||
},
|
||||
|
|
Загрузка…
Ссылка в новой задаче