مرحبًا دانييلا، لقد جربت هذه التكامل مع ثلاثة مزودي دردشة مختلفين وما زلت أحصل على نفس سياسة محتوى الأمان (CSP) بعد إضافة جميع الروابط التي تمكنت من العثور عليها إلى script-src في سياسة الأمان. هذه الحالة خاصة بـ Tidio، لكن الشيء نفسه حدث مع LiveChat و Pure Chat. هل لديك أي أفكار عما قد يحدث هنا؟
سياسة محتوى الأمان: منعت إعدادات الصفحة تحميل مورد في eval ("script-src"). المصدر: (function injected(eventName, injectedIntoContentWindow)
{
let checkRequest;
/*
* غلاف سياق الإطار
*
* في بعض الحالات القصوى، لن يقوم Chrome بتشغيل نصوص المحتوى داخل الإطارات.
* بدأت المواقع في إساءة استخدام هذه الحقيقة للوصول إلى واجهات برمجة التطبيقات غير المغلفة عبر
* contentWindow الخاص بالإطار (#4586، 5207). لذلك، حتى يقوم Chrome بتشغيل نصوص المحتوى بشكل متسق لجميع الإطارات، يجب علينا الاهتمام بإعادة حقن أغلفتنا عند الوصول إلى contentWindow.
*/
let injectedToString = Function.prototype.toString.bind(injected);
let injectedFrames = new WeakSet();
let injectedFramesAdd = WeakSet.prototype.add.bind(injectedFrames);
let injectedFramesHas = WeakSet.prototype.has.bind(injectedFrames);
function injectIntoContentWindow(contentWindow)
{
if (contentWindow && !injectedFramesHas(contentWindow))
{
injectedFramesAdd(contentWindow);
try
{
contentWindow[eventName] = checkRequest;
contentWindow.eval(
"(" + injectedToString() + ")('" + eventName + "', true);"
);
delete contentWindow[eventName];
}
catch (e) {}
}
}
for (let element of [HTMLFrameElement, HTMLIFrameElement, HTMLObjectElement])
{
let contentDocumentDesc = Object.getOwnPropertyDescriptor(
element.prototype, "contentDocument"
);
let contentWindowDesc = Object.getOwnPropertyDescriptor(
element.prototype, "contentWindow"
);
// يبدو أن contentWindow في HTMLObjectElement.prototype غير موجود
// في إصدارات Chrome القديمة مثل 51.
if (!contentWindowDesc)
continue;
let getContentDocument = Function.prototype.call.bind(
contentDocumentDesc.get
);
let getContentWindow = Function.prototype.call.bind(
contentWindowDesc.get
);
contentWindowDesc.get = function()
{
let contentWindow = getContentWindow(this);
injectIntoContentWindow(contentWindow);
return contentWindow;
};
contentDocumentDesc.get = function()
{
injectIntoContentWindow(getContentWindow(this));
return getContentDocument(this);
};
Object.defineProperty(element.prototype, "contentWindow",
contentWindowDesc);
Object.defineProperty(element.prototype, "contentDocument",
contentDocumentDesc);
}
/*
* غلاف RTCPeerConnection
*
* واجهة webRequest في Chrome لا تسمح بعد بحظر اتصالات WebRTC.
* انظر https://bugs.chromium.org/p/chromium/issues/detail?id=707683
*/
let RealCustomEvent = window.CustomEvent;
// إذا تم حقننا في إطار عبر contentWindow، يمكننا ببساطة
// التقاط نسخة من checkRequest التي تركتها لنا المستند الأصلي. وإلا
// نحتاج إلى إعداده الآن، جنبًا إلى جنب مع دوال معالجة الأحداث.
if (injectedIntoContentWindow)
checkRequest = window[eventName];
else
{
let addEventListener = document.addEventListener.bind(document);
let dispatchEvent = document.dispatchEvent.bind(document);
let removeEventListener = document.removeEventListener.bind(document);
checkRequest = (url, callback) =>
{
let incomingEventName = eventName + "-" + url;
function listener(event)
{
callback(event.detail);
removeEventListener(incomingEventName, listener);
}
addEventListener(incomingEventName, listener);
dispatchEvent(new RealCustomEvent(eventName, {detail: {url}}));
};
}
// يُستدعى فقط قبل كود الصفحة، وليس مقوى.
function copyProperties(src, dest, properties)
{
for (let name of properties)
{
if (Object.prototype.hasOwnProperty.call(src, name))
{
Object.defineProperty(dest, name,
Object.getOwnPropertyDescriptor(src, name));
}
}
}
let RealRTCPeerConnection = window.RTCPeerConnection ||
window.webkitRTCPeerConnection;
لدى Firefox خيار (media.peerconnection.enabled) لتعطيل WebRTC
وفي هذه الحالة يكون RealRTCPeerConnection غير معرف.
if (typeof RealRTCPeerConnection != "undefined")
{
let closeRTCPeerConnection = Function.prototype.call.bind(
RealRTCPeerConnection.prototype.close
);
let RealArray = Array;
let RealString = String;
let {create: createObject, defineProperty} = Object;
let normalizeUrl = url =>
{
if (typeof url != "undefined")
return RealString(url);
};
let safeCopyArray = (originalArray, transform) =>
{
if (originalArray == null || typeof originalArray != "object")
return originalArray;
let safeArray = RealArray(originalArray.length);
for (let i = 0; i < safeArray.length; i++)
{
defineProperty(safeArray, i, {
configurable: false, enumerable: false, writable: false,
value: transform(originalArray[i])
});
}
defineProperty(safeArray, "length", {
configurable: false, enumerable: false, writable: false,
value: safeArray.length
});
return safeArray;
};
// سيكون من الأسهل بكثير استخدام طريقة .getConfiguration للحصول على
// التكوين المعيار والآمن من مثيل RTCPeerConnection.
// للأسف، لم يتم تنفيذها حتى Chrome غير المستقر 59.
// انظر https://www.chromestatus.com/feature/5271355306016768
let protectConfiguration = configuration =>
{
if (configuration == null || typeof configuration != "object")
return configuration;
let iceServers = safeCopyArray(
configuration.iceServers,
iceServer =>
{
let {url, urls} = iceServer;
// RTCPeerConnection لا يتكرر عبر المصفوفات الوهمية لـ urls.
if (typeof urls != "undefined" && !(urls instanceof RealArray))
urls = [urls];
return createObject(iceServer, {
url: {
configurable: false, enumerable: false, writable: false,
value: normalizeUrl(url)
},
urls: {
configurable: false, enumerable: false, writable: false,
value: safeCopyArray(urls, normalizeUrl)
}
});
}
);
return createObject(configuration, {
iceServers: {
configurable: false, enumerable: false, writable: false,
value: iceServers
}
});
};
let checkUrl = (peerconnection, url) =>
{
checkRequest(url, blocked =>
{
if (blocked)
{
// استدعاء .close() يرمي خطأ إذا كان مغلقًا بالفعل.
try
{
closeRTCPeerConnection(peerconnection);
}
catch (e) {}
}
});
};
let checkConfiguration = (peerconnection, configuration) =>
{
if (configuration && configuration.iceServers)
{
for (let i = 0; i < configuration.iceServers.length; i++)
{
let iceServer = configuration.iceServers[i];
if (iceServer)
{
if (iceServer.url)
checkUrl(peerconnection, iceServer.url);
if (iceServer.urls)
{
for (let j = 0; j < iceServer.urls.length; j++)
checkUrl(peerconnection, iceServer.urls[j]);
}
}
}
}
};
// Chrome غير المستقر (تم اختباره مع 59) قد نفذ بالفعل
// setConfiguration، لذا نحتاج إلى تغليفه إذا كان موجودًا أيضًا.
// https://www.chromestatus.com/feature/5596193748942848
if (RealRTCPeerConnection.prototype.setConfiguration)
{
let realSetConfiguration = Function.prototype.call.bind(
RealRTCPeerConnection.prototype.setConfiguration
);
RealRTCPeerConnection.prototype.setConfiguration = function(configuration)
{
configuration = protectConfiguration(configuration);
// استدعاء الطريقة الحقيقية أولاً، للتحقق من التكوين لنا.
// أيضًا، يمكننا ذلك لأن checkRequest غير متزامن على أي حال.
realSetConfiguration(this, configuration);
checkConfiguration(this, configuration);
};
}
let WrappedRTCPeerConnection = function(...args)
{
if (!(this instanceof WrappedRTCPeerConnection))
return RealRTCPeerConnection();
let configuration = protectConfiguration(args[0]);
// بما أن مُنشئ webkitRTCPeerConnection القديم يأخذ حجة ثانية اختيارية
// نحتاج إلى الحرص على تمريرها. ضروري
// لإصدارات Chrome القديمة مثل 51.
let constraints = undefined;
if (args.length > 1)
constraints = args[1];
let peerconnection = new RealRTCPeerConnection(configuration,
constraints);
checkConfiguration(peerconnection, configuration);
return peerconnection;
};
WrappedRTCPeerConnection.prototype = RealRTCPeerConnection.prototype;
let boundWrappedRTCPeerConnection = WrappedRTCPeerConnection.bind();
copyProperties(RealRTCPeerConnection, boundWrappedRTCPeerConnection,
["generateCertificate", "name", "prototype"]);
RealRTCPeerConnection.prototype.constructor = boundWrappedRTCPeerConnection;
if ("RTCPeerConnection" in window)
window.RTCPeerConnection = boundWrappedRTCPeerConnection;
if ("webkitRTCPeerConnection" in window)
window.webkitRTCPeerConnection = boundWrappedRTCPeerConnection;
}
})('abp-request-aic05wltexc', true);. 468b7929-46c3-4249-b516-189e58962157:27:22
سياسة محتوى أمان أخرى:
سياسة محتوى الأمان: منعت إعدادات الصفحة تحميل مورد مضمن ("script-src"). المصدر: try { if (typeof Navigator.prototype.sendBeacon === 'function') { Navigator.prototype.sendBeacon = function(url, data) { return true; }; } } catch (exception) { console.error(exception); }. script.js:517:22
وواحدة أخرى (تمت إضافة الرابط هنا علما)
سياسة محتوى الأمان: منعت إعدادات الصفحة تحميل مورد في https://widget-v4.tidiochat.com//1_23_3/static/js/widget.a6a6e2b4c2401b7c523f.js ("script-src"). xgahvvrt0kwvb7p6crbxuolt4omnin1u.js:1:12450