PDA

View Full Version : [INFOREQ] [Ext.3.1.1] garbageCollector causes SSL unsecure message in IE8



Caius Caesar
1 Dec 2010, 2:52 AM
We have a dialog in our ext-powered website that seems to function normally, but, when running in secure mode (https), after closing the dialog, when the Ext garbageCollector kicks in, the dreaded 'this website contains both secure and unsecure parts' message is shown in IE8.

When disabling Ext garbage collection (not an option for our site), the message does not appear.

I have no clue whatsoever what could cause this behaviour. The dialog is rather complex, but doesn't contain any unsecure elements (I would exprect the message to appear when opening the form).

Can somebody point me in the right direction?

Regards,
Caius

meroy
4 Dec 2010, 12:38 AM
Can you post a testcase by following this thread. Thanks.

http://www.sencha.com/forum/showthread.php?71015-Posting-to-the-Bug-Forum

devtig
6 Dec 2010, 10:37 AM
Caius Caesar, if you want the dev team to try and fix something, you have to post a test case that demonstrates the bug. It's the bit of code that they can copy paste, run in their browser, reproduce the error with and fix if indeed broken.

Caius Caesar
7 Dec 2010, 12:24 AM
I'm pretty sure I replied to the 4 dec request, must have forgotten to actually post it.

Anyway, my problem is solved. The reasen the secure/unsecure message popped up was that i used the icon config option for image buttons. I changed it to iconCls and added the entries to the css.

Seems strange though that perfectly valid image paths caused this problem during garbage collection.

Posting an example is a lot of hassle for me, due to the way our app is set up. The form that caused the problem is part of a big app and needs data from a asp.net server app to function. I will include the code for the form (this is the fixed version, all icon config options have been replaced with iconCls), but it is not a working example.

I suspect that it is reproducable with any form with iconbuttons that use the icon property, though.

Regards,
Caius Caesar



//Ext.namespace("Ext.scanmar");

// Selector

Ext.scanmar.Selector = Ext.extend(Ext.Window, {

width: 600,
shadow: false,
layout: "fit",
resizable: false,
//closable: false,
modal: true,
buttonAlign: 'left',

initComponent: function () {

Ext.scanmar.Selector.superclass.initComponent.call(this);
this.setTitle("Selector"); // - " + this.dimensions[this.currentDimension][1]);

this.syncLockComponent = this.id;
this.syncLockMode = 2;

this.panelTop = 25;

this.panelHeight = 400;

this.add(

// Add Panel for layout purposes.
new Ext.Panel({
id: this.id + "-layout",
layout: "absolute",
border: false,
height: this.panelHeight + this.panelTop, //400,
//width: 600, not neccessary, causes display problem in IE6

tbar: new Ext.Toolbar({
id: this.id + "-toolbar",
height: this.panelTop,
items: [
this.comboBox = new Ext.form.ComboBox({
id: this.id + "-combo",
selector: this,
//x: 10,
//y: 5,
width: 235,
triggerAction: "all",
value: this.dimensions[this.currentDimension][1],
valueField: "index",
displayField: "text",
mode: "local",
editable: false,
store: new Ext.data.ArrayStore({
fields: ["index", "text"],
data: this.dimensions
})
}),

{ xtype: 'tbspacer', width: 20 }, // add a 20px space

this.freezeCheckBox = new Ext.form.Checkbox({
id: this.id + "-freeze",
selector: this,
//x: 10+235+5,
//y: 5,
width: 235,
boxLabel: "Freeze selection",
value: false,
hidden: true
})
]
}),

items: [

// Right TabPanel.
this.selectedTabPanel = new Ext.TabPanel({
id: this.id + "-selectedtabpanel",
x: 342, //343,
y: -1, //this.panelTop, //-1,
width: 245,
height: this.panelHeight, //402,
layoutOnTabChange: true,
activeTab: 0,
items: [
this.selectedTab = new Ext.Panel({
layout: "absolute",
title: "Selected Items"
})
]
}),

// Left TabPanel.
this.tabPanel = new Ext.TabPanel({
id: this.id + "-tabpanel",
width: 344, //343,
x: -1,
y: -1, //this.panelTop,
height: this.panelHeight, //402,
id: this.id + "-tabs",
activeTab: 0,
layoutOnTabChange: true,
//border: false,
items: [

// Tab Page with (Hierarchical) List.
this.tabList = new Ext.Panel({
id: this.id + "-tablist",
layout: "absolute",
border: false,
title: "All Items",
items: [
this.buttonPanel = new Ext.Panel({
id: this.id + "-buttons",
top: 0,
autoHeight: true,
border: false,
items: [
this.addSelectedButton = new Ext.Button({
selector: this,
tooltip: "Add selected value from All Items to Selected Items.",
width: 40,
cls: "selbutton x-btn-icon",
iconCls: "icon-sel-add",
listeners: {
click: {
fn: this.addSelectedButtonClick
}
}
}),
this.removeSelectedButton = new Ext.Button({
selector: this,
tooltip: "Remove selected value from Selected Items.",
width: 40,
cls: "selbutton x-btn-icon",
iconCls: "icon-sel-remove",
listeners: {
click: {
fn: this.removeSelectedButtonClick
}
}
}),
this.addAllButton = new Ext.Button({
selector: this,
tooltip: "Add all available/expanded values from All Items to Selected Items.",
width: 40,
cls: "selbutton x-btn-icon",
iconCls: "icon-sel-addall",
listeners: {
click: {
fn: this.addAllButtonClick
}
}
}),
this.removeAllButton = new Ext.Button({
selector: this,
tooltip: "Remove all values from Selected Items.",
width: 40,
cls: "selbutton x-btn-icon",
iconCls: "icon-sel-removeall",
style: { overflow: "hidden" },
listeners: {
click: {
fn: this.removeAllButtonClick
}
}
})
]
})
]
}),

// Tab Page for Match Selection.
// Added x-btn-text to cls for IE6 support
this.tabMatch = new Ext.Panel({
id: this.id + "-tabmatch",
title: "Match",
layout: "form",
cls: "selectorMatchPanel", //needed for IE6 hack
style: "padding: 4px",
items: [this.textMatch = new Ext.form.TextField({
width: 228,
fieldLabel: "Selection Pattern",
value: ""
}), this.matchSelectButton = new Ext.Button({
selector: this,
text: "Select",
tooltip: "Select all dimension values matching the selection pattern.",
cls: "selbutton x-btn-text",
minWidth: 75,
//minWidth: 64,
//style: "padding-bottom: 4px",
listeners: {
click: {
fn: this.matchSelectButtonClick
}
}
}), this.matchAddButton = new Ext.Button({
selector: this,
text: "Add",
tooltip: "Add all dimension values matching the selection pattern to the current selection.",
cls: "selbutton x-btn-text",
minWidth: 75,
//minWidth: 64,
listeners: {
click: {
fn: this.matchAddButtonClick
}
}
}), this.matchKeepButton = new Ext.Button({
selector: this,
text: "Keep",
tooltip: "Keep all selected values matching the selection pattern.",
cls: "selbutton x-btn-text",
minWidth: 75,
//minWidth: 64,
listeners: {
click: {
fn: this.matchKeepButtonClick
}
}
}), this.matchRemoveButton = new Ext.Button({
selector: this,
text: "Remove",
tooltip: "Remove all selected values matching the selection pattern.",
cls: "selbutton x-btn-text",
minWidth: 75,
//minWidth: 64,
listeners: {
click: {
fn: this.matchRemoveButtonClick
}
}
}), new Ext.Panel({
border: false,
html: "<br><b>Pattern</b><br>? Any single character<br>* Zero or more characters<br><br>Example:<br>Use J*9? for selecting all months that start with a J in the nineties."
})]
}),

// Tab Page for Sorting.
this.tabSort = new Ext.Panel({
id: this.id + "-tabsort",
title: "Sort",
layout: "form",
style: "padding: 4px",
items: [new Ext.form.FieldSet({
title: "Sort on",
layout: "column",
columns: 1,
autoHeight: true,
items: [new Ext.form.RadioGroup({
id: "rg-sorton",
columns: 1,
items: [
{ id: "rb-sorton1", boxLabel: 'Orginal order', name: 'rb-sorton', inputValue: 1 },
{ id: "rb-sorton2", boxLabel: 'Alphabetically', name: 'rb-sorton', inputValue: 2, checked: true }
]
})]
}), new Ext.form.FieldSet({
title: "Sort order",
layout: "column",
columns: 1,
autoHeight: true,
items: [new Ext.form.RadioGroup({
columns: 1,
items: [
{ id: "rb-sortmode1", boxLabel: 'Ascending', name: 'rb-sortorder', inputValue: 1, checked: true },
{ id: "rb-sortmode2", boxLabel: 'Descending', name: 'rb-sortorder', inputValue: 2 }
]
})]
}), this.sortButton = new Ext.Button({
selector: this,
text: "Sort",
listeners: {
click: {
fn: this.sortButtonClick
}
}
})]
})
]
})
]
})
);

this.okButton = this.addButton({ id: this.id + "-ok", text: "Ok", selector: this }, this.okButtonClick);
this.cancelButton = this.addButton({ id: this.id + "-cancel", text: "Cancel", selector: this }, this.cancelButtonClick);

//KZ201007
this.selectedTab.on("render", function () {
this.selectedTab.body.addListener("click", this.enableButtons, this);
}, this, { single: true });

this.comboBox.on("beforeselect", this.comboBoxBeforeSelect);
this.freezeCheckBox.on("check", this.freezeCheckBoxCheck);

this.on("render", function () {
this.fbar.insert(0, new Ext.Toolbar.Fill());
});

this.loadDimension();

this.doLayout();

this.on("beforehide", function (sender) {
this.cancelButtonClick();
return false;
});

this.on("beforeclose", function (sender) {
this.cancelButtonClick.call(this.cancelButton);
return false;
});

this.on("render", function () {
var km = this.getKeyMap();
if (km) {
// Esc will generate Error status = 0 on the Ajac call in Firefox
km.stopEvent = true;
}

});

this.on("move", function (sender) {
// treenodes disappear after window.move.
sender.treePanel.setVisible(false);
sender.treePanel.setVisible(true);
});


},

cleanUp: function () {

this.removeTreePanel();
this.removeListbox();

this.tabPanel = null;
this.tabList = null;

this.buttonPanel = null;
this.addSelectedButton.selector = null;
this.addSelectedButton = null;
this.removeSelectedButton.selector = null;
this.removeSelectedButton = null;
this.addAllButton.selector = null;
this.addAllButton = null;
this.removeAllButton.selector = null;
this.removeAllButton = null;
this.tabMatch = null;
this.textMatch = null;
this.matchSelectButton.selector = null;
this.matchSelectButton = null;
this.matchAddButton.selector = null;
this.matchAddButton = null;
this.matchKeepButton.selector = null;
this.matchKeepButton = null;
this.matchRemoveButton.selector = null;
this.matchRemoveButton = null;
this.tabSort = null;
this.sortButton.selector = null;
this.sortButton = null;

this.selectedTabPanel = null;

Ext.destroy(this.comboBox);
this.comboBox.selector = null;
this.comboBox = null;
Ext.destroy(this.freezeCheckBox);
this.freezeCheckBox.selector = null;
this.freezeCheckBox = null;
Ext.destroy(this.okButton);
this.okButton.selector = null;
this.okButton = null;
Ext.destroy(this.cancelButton);
this.cancelButton.selector = null;
this.cancelButton = null;
},

onResize: function (adjWidth, adjHeight, rawWidth, rawHeight) {
var h = adjHeight - this.getFrameHeight();
var w = adjWidth - this.getFrameWidth();
Ext.getCmp(this.id + "-buttons").setPosition(w / 2 + 5, 0);
Ext.scanmar.Selector.superclass.onResize.call(this);
},

addSelectedButtonClick: function () {
var nodes = this.selector.treePanel.selModel.selNodes;
for (var i = 0; i < nodes.length; i++) {
var text = nodes[i].text;
var id = parseInt(nodes[i].id.substr(1 + nodes[i].id.lastIndexOf("-")));
//if (this.listBox.store.find("index", id) < 0) {
if (this.selector.listBox.store.findBy(function (record, recordId) { return record.data.index == id }) < 0) {
var record = new Ext.data.Record({ index: id, text: text });
this.selector.listBox.store.add(record);
}
}
this.selector.isDirty = true;
},

removeSelectedButtonClick: function () {
var records = this.selector.listBox.view.getSelectedRecords();
for (var i = 0; i < records.length; i++) {
this.selector.listBox.store.remove(records[i]);
};
this.selector.isDirty = true;
this.selector.enableButtons();
},

addAllButtonClick: function () {
this.selector.treePanel.root.cascade(function (node) {
if (node.parentNode) {
var id = parseInt(node.id.substr(1 + node.id.lastIndexOf("-")));
//if (this.listBox.store.find("index", id) < 0) {
if (this.selector.listBox.store.findBy(function (record, recordId) { return record.data.index == id }) < 0) {
var record = new Ext.data.Record({ index: id, text: node.text });
this.selector.listBox.store.add(record);
}
if (!node.expanded) {
return false;
}
}
}, this);
this.selector.isDirty = true;
},

removeAllButtonClick: function () {
this.selector.listBox.store.removeAll();
this.selector.isDirty = true;
},

matchSelectButtonClick: function () {
this.selector.isDirty = true;
Scanmar.dispatchEvent(this.selector, "Execute", {
id: this.selector.id,
command: "MatchSelect",
arguments: this.selector.textMatch.getValue()
}, {
callbackOnSuccess: this.selector.loadDimensionListBox,
callbackScope: this.selector
});
},

matchAddButtonClick: function () {
this.selector.isDirty = true;
this.selector.applySelection(function () {
Scanmar.dispatchEvent(this.selector, "Execute", {
id: this.selector.id,
command: "MatchAdd",
arguments: this.selector.textMatch.getValue()
}, {
callbackOnSuccess: this.selector.loadDimensionListBox,
callbackScope: this.selector
});
}, this);
},

matchKeepButtonClick: function () {
this.selector.isDirty = true;
this.selector.applySelection(function () {
Scanmar.dispatchEvent(this.selector, "Execute", {
id: this.selector.id,
command: "MatchKeep",
arguments: this.selector.textMatch.getValue()
}, {
callbackOnSuccess: this.selector.loadDimensionListBox,
callbackScope: this.selector
});
}, this);
},

matchRemoveButtonClick: function () {
this.selector.isDirty = true;
this.selector.applySelection(function () {
Scanmar.dispatchEvent(this.selector, "Execute", {
id: this.selector.id,
command: "MatchRemove",
arguments: this.selector.textMatch.getValue()
}, {
callbackOnSuccess: this.selector.loadDimensionListBox,
callbackScope: this.selector
});
}, this);
},

sortButtonClick: function () {
var mode = Ext.getCmp("rb-sorton1").checked ? 0 : 1;
var order = Ext.getCmp("rb-sortmode1").checked ? "ASC" : "DESC";
this.selector.listBox.store.sort(mode, order);
this.selector.isDirty = true;
},

getSelection: function () {
var selection = "";
for (var i = 0; i < this.listBox.store.data.items.length; i++) {
if (selection.length == 0) {
selection = this.listBox.store.data.items[i].data.index;
} else {
selection = selection + "|" + this.listBox.store.data.items[i].data.index;
}
}
return selection;
},

okButtonClick: function () {
if (this.selector.isDirty) {
this.selector.applySelection(function () {
this.selector.doClose();
}, this, true);
} else { this.selector.doClose(); };
},

cancelButtonClick: function () {
this.selector.doClose();
},

applySelection: function (callback, scope, permanent) {
if (this.isDirty) {
Scanmar.dispatchEvent(this, "Execute", {
id: this.id,
command: (permanent ? "ApplySelection_Permanent" : "ApplySelection"),
arguments: this.getSelection() + (permanent ? "|" + this.freezeCheckBox.getValue() : "")
}, {
callbackOnSuccess: callback,
callbackScope: scope
});
if (permanent) {
this.isDirty = false;
}
} else {
if (callback) {
callback.call(scope);
}
}
},


doClose: function () {
this.setDisabled(true); //KZ201007
this.cleanUp();
Scanmar.dispatchEvent(this, "Close", {
"id": this.id
});
},

selectDimension: function (index) {
this.setDisabled(true); //KZ201007
this.currentDimension = index;
this.isDirty = false;
this.removeTreePanel(); //KZ201007
this.removeListbox(); //KZ201007
this.loadDimension();
this.tabList.doLayout();
//this.setTitle("Selector - " + this.dimensions[this.currentDimension][1]);
this.setDisabled(false); //KZ201007
},

freezeCheckBoxCheck: function () {
this.selector.isDirty = true;
},

comboBoxBeforeSelect: function (combo, record, index) {
if (this.selector.currentDimension === index) {
return;
}
if (this.selector.isDirty) {
if (this.selector.okButton.disabled) {

Ext.MessageBox.confirm("Selector", "Switch without changing selection on '" + this.selector.comboBox.getRawValue() + "'?", function (button) {
if (button === "yes") {
this.selector.comboBox.select(index);
this.selector.selectDimension(index);
this.selector.okButton.setDisabled(false);
} else {
return false;
}
}, this);

} else {
var currValue = this.selector.comboBox.getValue();
Ext.Msg.show({
title: "Selector",
msg: "Save selection on '" + this.selector.comboBox.getRawValue() + "'?",
buttons: Ext.Msg.YESNOCANCEL,
fn: function (button) {
switch (button) {
case "yes":
this.selector.applySelection(function () {
this.selector.comboBox.select(index);
this.selector.selectDimension(index);
}, this, true);
break;
case "no":
this.selector.comboBox.select(index);
this.selector.selectDimension(index);
break;
case "cancel":
this.selector.comboBox.setValue(currValue);
break;
};
},
scope: this,
icon: Ext.MessageBox.QUESTION
});

}
} else { this.selector.selectDimension(index); }
},

enableButtons: function () {
if (this.listBox) {
var selcount = this.listBox.view.getSelectionCount();
this.removeSelectedButton.setDisabled(selcount === 0);
}
if (this.treePanel) {
this.addSelectedButton.setDisabled(this.treePanel.selModel.selNodes.length === 0);
}
},

loadDimensionTreePanel: function () {
var ddGroup = "ext-dd-" + ++Scanmar.idSeed;
this.addSelectedButton.setDisabled(true);
this.treePanel = new Ext.tree.TreePanel({
selector: this,
y: -1,
x: -1,
width: 294,
height: 376,
autoScroll: true,
border: true,
legend: "All",
useArrows: true,
// enableDD: true,
ddGroup: ddGroup,
root: new Ext.tree.AsyncTreeNode({
id: "root-node"
}),
rootVisible: false,
selModel: new Ext.tree.MultiSelectionModel(),
animateCollapse: false,
animate: false, //KZ201007 animate kills performance when expanding a large number of items
loader: new Ext.tree.TreeLoader({
dataUrl: "JsonLoader.axd",
requestMethod: "POST",
baseParams: {
id: this.id,
method: "GetAllStatus",
dimension: this.currentDimension
}
})
});

//KZ201007
this.treePanel.on("beforeexpandnode", function (node) {
this.selector.setDisabled(true);
});

this.treePanel.on("expandnode", function (node) {
if (!node.isRoot && node.lastChild) {
//KZ201007: ensureVisible kills performance when expanding a large number of items
if (node.childNodes.length < 500) {
node.lastChild.ensureVisible();
node.ensureVisible();
}
}
this.selector.setDisabled(false); //KZ201007
});

this.treePanel.loader.on("load", function (sender, node, response) {
if (response.responseText.length === 0) {
return;
}
if (Scanmar.App.debugMode) {
Scanmar.App.writeDebugMessage(this.id + " [Ext.tree.TreePanel.wrapped]\n\n" + response.responseText);
};
}, this.treePanel);

this.tabList.insert(0, this.treePanel);
//KZ: passing scope is neccessary for enableButtons to function properly
//this.treePanel.selModel.on("selectionchange", this.enableButtons, null);
this.treePanel.selModel.on("selectionchange", this.enableButtons, this);
/* Double-Click shoud add value.
this.treePanel.on("dblclick", function(node, e) {

}, this);
*/
this.doLayout();
},

loadDimensionListBox: function () {
this.removeSelectedButton.setDisabled(true);
if (this.listBox) {
//KZ201007
this.removeListbox();
}
this.listBox = new Ext.ux.Multiselect({
selector: this,
id: this.id + "-lb",
x: -1,
y: -1,
width: 244,
height: 376,
dataFields: ["index", "text"],
displayField: "text",
valueField: "index",
store: new Ext.data.JsonStore({
autoLoad: true,
baseParams: {
method: "GetSelection",
id: this.id,
dimension: this.currentDimension
},
root: "items",
url: "JsonLoader.axd",
fields: ["index", "text"]
}),
dropGroup: this.treePanel.ddGroup,
dragGroup: this.treePanel.ddGroup
});
this.listBox.on("change", function () {
this.selector.isDirty = true;
this.selector.enableButtons();
}, null);
this.listBox.on("dblclick", this.removeSelectedButtonClick, null);
this.selectedTab.add(this.listBox);
this.listBox.on("render", function (sender) {
// sender.view.tpl = new Ext.XTemplate('<tpl for="."><div class="ux-mselect-item" unselectable=on>{text:htmlEncode}</div></tpl>');
sender.on("beforedestroy", function () {
Ext.dd.ScrollManager.unregister(this.dragZone.el.id)
Ext.dd.ScrollManager.unregister(this.dropZone.el.id)
}, sender.view);
sender.view.on("drop", function () {
this.selector.isDirty = true;
this.selector.enableButtons();
}, sender);
//KZ201007 removed. SelectedTab did get an extra click listener for every new instance of listbox. created 1 click listener on selectedTab on render.
//sender.selector.selectedTab.body.addListener("click", function() {
// this.selector.enableButtons();
//}, sender);
}, null);
this.listBox.store.on("remove", function (store) {
this.okButton.setDisabled(store.getCount() === 0);
}, { okButton: this.okButton });
this.listBox.store.on("load", function (store) {
this.okButton.setDisabled(store.getCount() === 0);
}, { okButton: this.okButton });
this.listBox.store.on("add", function (store) {
this.okButton.setDisabled(false);
}, { okButton: this.okButton });
this.listBox.store.on("clear", function (store) {
this.okButton.setDisabled(true);
}, { okButton: this.okButton });
this.doLayout();
},

loadDimension: function () {
this.loadDimensionTreePanel();
this.loadDimensionListBox();
this.loadFreezeSettings();
},

loadFreezeSettings: function () {
Scanmar.dispatchEvent(this, "Execute", {
id: this.id,
command: "GETFREEZESETTINGS",
arguments: this.currentDimension
}, {
// callbackOnSuccess: this.setFreezeSettings,
callbackScope: this
});
},

setFreezeSettings: function (allowFreeze, frozen) {
this.freezeCheckBox.suspendEvents();
allowFreeze ? this.freezeCheckBox.show() : this.freezeCheckBox.hide();
this.freezeCheckBox.setValue(frozen);
this.freezeCheckBox.resumeEvents();
},

//KZ201007 cleanup and remove
removeTreePanel: function () {
if (this.treePanel) {
if (this.treePanel.selModel) {
this.treePanel.selModel.purgeListeners();
this.treePanel.selModel.tree = null;
this.treePanel.selModel.lastSelNode = null;
this.treePanel.selModel.selNodes = null;
this.treePanel.selModel.selMap = null;
this.treePanel.selModel = null;
}
this.treePanel.loader.purgeListeners();
//Destroy on treepanel with many items is very slow. So remove then first.
if (this.treePanel.root) {
this.treePanel.collapseAll();
this.treePanel.root.removeAll();
}
this.treePanel.selector = null;
this.tabList.remove(this.treePanel, true);
this.treePanel = null;
}
},
//KZ201007 cleanup and remove
removeListbox: function () {
if (this.listBox) {

this.listBox.store.removeAll();
this.listBox.selector = null;
this.selectedTab.remove(this.listBox, true);
this.listBox.store.purgeListeners();
this.listBox.store = null;
this.listBox = null;
}
}
});

Condor
7 Dec 2010, 12:36 AM
Here is the what Microsoft has to say about the issue (KB925014 (http://support.microsoft.com/kb/925014/en-us)).

There are 2 solutions:
1. Don't use inline background images (= don't use the Button 'icon' config option).
2. Replace parentEl.removeChild(childEl) with childEl.outerHTML='' in the Ext base library (and only for IE).

Caius Caesar
7 Dec 2010, 12:45 AM
Thanks, I stick with the iconCls solution.

Wouldn't it be a good idea to implement the second solution in the ext base library?

Btw, Microsoft mentioned IE6 and 7, but I experienced the bug in IE8

Thanks again,

Caius