Block OpenSearch Descriptions

Block sites from adding search engines to Chrome.

当前为 2021-03-17 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Block OpenSearch Descriptions
  3. // @author
  4. // @description Block sites from adding search engines to Chrome.
  5. // @downloadURL
  6. // @grant
  7. // @icon
  8. // @include http*://*
  9. // @require
  10. // @run-at document-start
  11. // @updateURL
  12. // @version 2.0
  13. // @namespace https://gf.qytechs.cn/users/218540
  14. // ==/UserScript==
  15.  
  16. //document.querySelector('[type="application/opensearchdescription+xml"]').remove();
  17. //////////////////////////////////////////////////////////////////////////////
  18. // Code from https://github.com/gregsadetsky/chrome-dont-add-custom-search-engines/blob/master/src/content.js
  19. // OpenSearch - e.g., https://martin-thoma.com/search-engine-autodiscovery/
  20. // Uses CSS4 selectors, Chrome 49+
  21. const DEBUG=false;
  22. let numseen=0, numspoiled=0;
  23. let unspoiled=[];
  24.  
  25. // called when the user clicks an element of the form (any field or button).
  26. // The parameter passed is the event object.
  27. function clickApply(e) {
  28. if(DEBUG) console.info({'form onclick':e});
  29. // remove onclick. One fix only
  30. e.srcElement.form.removeEventListener("click", clickApply);
  31. applyFix(e.srcElement.form);
  32. } //clickApply
  33.  
  34. // add a new <textarea> element
  35. function applyFix(elem) {
  36. var newelem = document.createElement('textarea');
  37. newelem.name = '';
  38. newelem.style.display='none';
  39. elem.appendChild(newelem);
  40. } //applyFix
  41.  
  42. // Add an extra child input to any form that only has one
  43. function spoilFormGet(elem) {
  44. if(DEBUG) {
  45. ++numseen;
  46. unspoiled.push(elem);
  47. }
  48.  
  49. // Check whether the form submits to a HTTP(S) URL.
  50. // A missing or relative action will be resolved against the page URL
  51. // so it must have the same URI scheme which is all we care about
  52. var action = elem.getAttribute('action');
  53. if(!(action && action.indexOf('://') >= 0)) action = location.href;
  54. if(!/^https?:\/\//i.test(action)) return;
  55.  
  56. // Autodetection requires exactly one input of type text or search
  57. // If the type attribute is missing, it defaults to `text`
  58. // Readonly inputs do not count against this total
  59. if(elem.querySelectorAll(':scope input:-webkit-any([type="text" i],[type="search" i],[type*="search" i],[type=""],:not([type])):not([readonly])[name]:not([name=""])').length !== 1) return;
  60.  
  61. // Autodetection also requires no password, file, or textarea elements
  62. if(elem.querySelector(':scope :-webkit-any(input[type="password" i],input[type="file" i],textarea)')) return;
  63.  
  64. // Add a <textarea> - unlike <input>, it doesn't block implicit submission
  65. // per https://www.tjvantoll.com/2013/01/01/enter-should-submit-forms-stop-messing-with-that/
  66.  
  67. // apply the fix now, or place it in onclick. "this" is a parameter passed by foreach(). see below
  68. if (this.now === true) {
  69. // remove onclick placed during first pass
  70. elem.removeEventListener("click", clickApply);
  71. // and instead do it now;
  72. applyFix(elem);
  73. } else {
  74. elem.addEventListener('click', clickApply);
  75. }
  76.  
  77. if(DEBUG) {
  78. console.info({Spoiled: elem});
  79. ++numspoiled;
  80. unspoiled.pop();
  81. }
  82. } //spoilFormGet
  83.  
  84. var debugAutoDetect=0;
  85.  
  86. // move this part of the code here, since it's called multiple times
  87. function autoDetect(now, when_called) {
  88. if(DEBUG) console.log('autoDetect: '+(++debugAutoDetect)+' ('+when_called+')');
  89. document.querySelectorAll('form:-webkit-any([method="get" i],:not([method]))').forEach(spoilFormGet,{now});
  90. if(DEBUG) {
  91. console.log(`Spoiled ${numspoiled}/${numseen}.`+(unspoiled.length?' Unspoiled were:':'') );
  92. if (unspoiled.length) console.log(unspoiled);
  93. }
  94.  
  95. // we reset spoil vars for next call
  96. numseen=0;
  97. numspoiled=0;
  98. unspoiled=[];
  99. } //autoDetect
  100.  
  101. function catchOpenSearch() {
  102. if(DEBUG) console.info('catchOpenSearch called');
  103. // OpenSearch - e.g., https://martin-thoma.com/search-engine-autodiscovery/
  104. // Uses CSS4 selectors, Chrome 49+
  105. document.querySelectorAll('[type="application/opensearchdescription+xml" i]').forEach(
  106. function (it) {
  107. it.removeAttribute('type');
  108. if(DEBUG) console.info({"Spoiled by type removal": it});
  109. }
  110. );
  111.  
  112. // Suggestion service, https://www.chromium.org/tab-to-search
  113. document.querySelectorAll('url[rel="suggestions" i]').forEach(
  114. function (it) {
  115. it.removeAttribute('rel');
  116. if(DEBUG) console.info({"Spoiled by rel removal": it});
  117. }
  118. );
  119. } //catchOpenSearch
  120.  
  121. function onDOMContentLoaded() {
  122. if(DEBUG) console.log('onDOMContentLoaded');
  123.  
  124. catchOpenSearch();
  125.  
  126. // #1 call it now (i.e., DOMContentLoaded) without applying the fix
  127. // #2 call it in 1500 ms and apply the fix
  128. // #3 call when document loaded, and apply the fix.
  129.  
  130. // if <form> is added/modified // dynamically before the document
  131. // is fully loaded, #1 could miss it, but not #2 & #3. Note that #2
  132. // could fire after #3 if the page is fast to load. Once the fix
  133. // is applied, the <form> can't be found by subsequent execution
  134. // of autoDetect, so the fix can only be applied once (#1 is not
  135. // applied but delayed until #2 or #3 fires, or if the user
  136. // clicks).
  137.  
  138. window.addEventListener('load', function() {
  139. if(DEBUG) console.log('onload');
  140. catchOpenSearch();
  141. autoDetect(true,'Load');
  142. } ); // #3
  143. setTimeout(function() { autoDetect(true,'Timer'); } ,1500); // #2
  144. autoDetect(false,'onClick'); // #1
  145.  
  146. } //onDOMContentLoaded
  147.  
  148. (function() {
  149. document.addEventListener('DOMContentLoaded', onDOMContentLoaded);
  150. onDOMContentLoaded();
  151. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址