omega_webext_proxy_script.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. FindProxyForURL = (function () {
  2. var OmegaPac = require('omega-pac');
  3. var options = {};
  4. var state = {};
  5. var activeProfile = null;
  6. var fallbackResult = 'DIRECT';
  7. var pacCache = {};
  8. init();
  9. return FindProxyForURL;
  10. function FindProxyForURL(url, host, details) {
  11. if (!activeProfile) {
  12. warn('Warning: Proxy script not initialized on handling: ' + url);
  13. return fallbackResult;
  14. }
  15. // Moz: Neither path or query is included url regardless of scheme for now.
  16. // This is even more strict than Chromium restricting HTTPS URLs.
  17. // Therefore, it leads to different behavior than the icon and badge.
  18. // https://bugzilla.mozilla.org/show_bug.cgi?id=1337001
  19. var request = OmegaPac.Conditions.requestFromUrl(url);
  20. var profile = activeProfile;
  21. var matchResult, next;
  22. while (profile) {
  23. matchResult = OmegaPac.Profiles.match(profile, request)
  24. if (!matchResult) {
  25. if (profile.profileType === 'DirectProfile') {
  26. return 'DIRECT';
  27. } else if (profile.pacScript) {
  28. return runPacProfile(profile.pacScript);
  29. } else {
  30. warn('Warning: Unsupported profile: ' + profile.profileType);
  31. return fallbackResult;
  32. }
  33. }
  34. if (Array.isArray(matchResult)) {
  35. next = matchResult[0];
  36. // TODO: Maybe also return user/pass if Mozilla supports it or it ends
  37. // up standardized in WebExtensions in the future.
  38. // MOZ: Mozilla has a bug tracked for user/pass in PAC return value.
  39. // https://bugzilla.mozilla.org/show_bug.cgi?id=1319641
  40. if (next.charCodeAt(0) !== 43) {
  41. // MOZ: HTTPS proxies are supported under the prefix PROXY.
  42. // https://dxr.mozilla.org/mozilla-central/source/toolkit/components/extensions/ProxyScriptContext.jsm#180
  43. return next.replace(/HTTPS /g, 'PROXY ');
  44. }
  45. } else if (matchResult.profileName) {
  46. next = OmegaPac.Profiles.nameAsKey(matchResult.profileName)
  47. } else {
  48. return fallbackResult;
  49. }
  50. profile = OmegaPac.Profiles.byKey(next, options)
  51. }
  52. warn('Warning: Cannot find profile: ' + next);
  53. return fallbackResult;
  54. }
  55. function runPacProfile(profile) {
  56. var cached = pacCache[profile.name];
  57. if (!cached || cached.revision !== profile.revision) {
  58. // https://github.com/FelisCatus/SwitchyOmega/issues/390
  59. var body = ';\n' + profile.pacScript + '\n\n/* End of PAC */;'
  60. body += 'return FindProxyForURL';
  61. var func = new Function(body).call(this);
  62. if (typeof func !== 'function') {
  63. warn('Warning: Cannot compile pacScript: ' + profile.name);
  64. func = function() { return fallbackResult; };
  65. }
  66. cached = {func: func, revision: profile.revision}
  67. pacCache[cacheKey] = cached;
  68. }
  69. try {
  70. // Moz: Most scripts probably won't run without global PAC functions.
  71. // Example: dnsDomainIs, shExpMatch, isInNet.
  72. // https://bugzilla.mozilla.org/show_bug.cgi?id=1353510
  73. return cached.func.call(this);
  74. } catch (ex) {
  75. warn('Warning: Error occured in pacScript: ' + profile.name, ex);
  76. return fallbackResult;
  77. }
  78. }
  79. function warn(message, error) {
  80. // We don't have console here and alert is not implemented.
  81. // Throwing and messaging seems to be the only ways to communicate.
  82. // MOZ: alert(): https://bugzilla.mozilla.org/show_bug.cgi?id=1353510
  83. browser.runtime.sendMessage({
  84. event: 'proxyScriptLog',
  85. message: message,
  86. error: error,
  87. level: 'warn',
  88. });
  89. }
  90. function init() {
  91. browser.runtime.sendMessage({event: 'proxyScriptLoaded'});
  92. browser.runtime.onMessage.addListener(function(message) {
  93. if (message.event === 'proxyScriptStateChanged') {
  94. state = message.state;
  95. options = message.options;
  96. if (!state.currentProfileName) {
  97. activeProfile = state.tempProfile;
  98. } else {
  99. activeProfile = OmegaPac.Profiles.byName(state.currentProfileName,
  100. options);
  101. }
  102. }
  103. });
  104. }
  105. })();