// ==UserScript== // @name Straight Google // @id straight_google_pokerface // @namespace in.co.tossing.toolkit.google // @description Remove URL redirection from google products // @license GPL v3 or later version // @updateURL http://userscripts.org/scripts/source/121261.meta.js // @include *://www.google.*/*?q=* // @include *://www.google.*/*?tbs=* // @include *://www.google.*/*&q=* // @include *://www.google.*/*#q=* // @include *://www.google.*/ // @include *://encrypted.google.* // @include *://ipv6.google.* // @include *://www.google.*/news* // @include *://news.google.*/* // @include *://plus.google.com/* // @include *://docs.google.com/* // @include *://maps.google.com/* // @include *://www.google.com/maps* // @include *://ditu.google.com/* // @include *://groups.google.com/group/* // @version 1.1 // @author Pokerface - Kevin // ==/UserScript== (function ($$d) { // document URI var $$url = $$d.baseURI; //console.debug('Current URI : '+ $$url); // unsafe window var $$w = null; // get unsafeWindow var injectWindow = (function () { var retry = 0; return function ($var, $func, $testFunc) { if (!$$w) { // load unsafeWindow if (typeof(unsafeWindow) !== "undefined" && typeof(unsafeWindow[$var]) !== "undefined") $$w = unsafeWindow; else if (typeof(window[$var]) !== "undefined") $$w = window; else try { // for Chrome var a = document.createElement("a"); a.setAttribute("onclick", "return window;"); var win = a.onclick(); if (typeof(win[$var]) !== "undefined") $$w = win; } catch (e) {} } if ($$w && (($testFunc && $testFunc($$w)) || !$testFunc)) return $func(); // if window loading is not successful, retry for 12000ms if (++retry<40) setTimeout((function ($v, $f, $t) { return function () { injectWindow($v, $f, $t); }; })($var, $func, $testFunc), 300); } })(); // for each function each($arr, $fun) { if (!$arr) return; //console.debug('each function is called. arr length is '+ $arr.length); for (var i=$arr.length-1; i >=0; i--) $fun.call($arr[i]); } // expand goo.gl shorten url function expand_short_url($url, $callback) { if (!/^(?:https?:\/\/)?goo\.gl\/\w+$/.test($url)) return; var api = "https://www.googleapis.com/urlshortener/v1/url?shortUrl={$url}"; // query Google Shorten URL API console.debug('Straight Google : trying to expand shorten URL ['+ $url +']'); GM_xmlhttpRequest({ method : 'GET', url : api.replace('{$url}', /^https?:\/\//.test($url) ? $url : 'http://'+ $url), onload : (function ($f) { return function (res) { try { eval('var obj = '+ res.responseText); } catch (e) { return; } if (obj.status != "OK") return; console.debug('Straight Google : shorten URL expanded ['+ obj.longUrl +']'); // call back $f(obj.longUrl); }; })($callback), onerror : function (res) { console.debug('Straight Google : fail to expand shorten URL ['+ res.finalUrl +']'); } }); } // fetch Google Redirection Traget function get_google_url($url) { if (!$url) return; var google_url_reg = /^(?:https?:\/\/.+\.google\..+)?\/(?:local_)?url\?(?:(?!url|q)\w+=[^&]*&)*(?:url|q)=((?:https?(?::\/\/|%3A%2F%2F))?[^&]+).*$/i; var mat = $url.match(google_url_reg); var res = mat ? unescape(mat[1] || '') : ''; // fix http:// if (res && !/^https?:\/\//.test(res)) res = "http://"+ res; // default http return res; } function google_url_clean() { var url = get_google_url(this.href); if (url) { this.href = url; console.debug('Redirection of ['+ url +'] is now removed.'); } do_not_track.call(this); // try to expand shorten url expand_short_url(url || this.href, (function (obj) { return function (url) { if (obj) obj.href = url; }; })(this)); return url || ''; } function do_not_track() { // add no follow if (!this.getAttribute("rel")) this.setAttribute("rel", "noreferrer"); } // listen to specific event var listen = (function () { var interval_count=[]; return function ($$dom, $event, $func, $init) { var evt_listener = (function ($$dom, $e, $f, $i) { var id = interval_count.length; return function () { var dom = $$d.querySelectorAll($$dom); if (dom.length > 0) { //console.debug('Event for ['+ $$dom +'] is now binded'); clearInterval(interval_count[id]); delete interval_count[id]; for (var i=0; i<dom.length; i++) { // if the function need initiation if ($i) $f.call(dom[i]); if ($e instanceof Array) each( $e, function () { bindEvent(dom[i], this, $f); } ); else bindEvent(dom[i], $e, $f); } } } })($$dom, $event, $func, $init); interval_count.push(setInterval(evt_listener, 500)); } })(); // shit IE function bindEvent($obj, $evt, $func) { if ($obj.addEventListener) $obj.addEventListener($evt, $func, false); else if ($obj.attachEvent) $obj.attachEvent((/^[a-z]+$/.test($evt) ? "on" : '')+ $evt, $func); } // Main part begin ======================================== // prevent Google Plus redirection : plus.url.google.com if (/:\/\/plus\.google\./.test($$url)) { console.debug('Straight Google [Plus] is now loaded'); function plus_clean() { each( // use 'do not track me' feature $$d.querySelectorAll('a.ot-anchor:not([rel])'), google_url_clean ); } // notification bar if (/\/u\/0\//.test($$url) && $$d.querySelector('#summary-content')) { // plus home page injectWindow("OZ_initData", function () { $$w.OZ_initData["1"][20]=""; console.debug('URL Redirection of Google Plus Notification is now prevented.'); }); listen( // notification stream '#summary-content', "DOMSubtreeModified", plus_clean, true ); } else { // plus home page injectWindow("AF_initDataQueue", function () { for (var i=0, q = $$w.AF_initDataQueue; i<q.length; i++) if (q[i].key=="1") { q[i].data[20]=""; // clear plus.url.google.com console.debug('URL Redirection of Google Plus is now prevented.'); break; } }); // listen to the stream function _bind_stream() { listen( "div.lzqA1d", "DOMNodeInserted", plus_clean ); } // page switch listen( '#gbqn', 'click', _bind_stream, true ); } } // remove google news redirection here else if (/:\/\/news\.google\./.test($$url) || /:\/\/www\.google\..+\/news(\/.*)?/.test($$url)) { console.debug('Straight Google [News] is now loaded'); listen( '.blended-section', "DOMNodeInserted", function () { each( $$d.querySelectorAll('a.article[url]:not(._tracked)'), function () { // fix link to its normal url this.href = this.getAttribute('url'); do_not_track.call(this); console.debug("Redirection of ["+ this.href +"] is now removed."); // cheat google and say "it has been tracked already" this.className += ' _tracked'; } ); }, true ); } // Google Docs else if (/docs\.google\.com\/.+/.test($$url)) { console.debug('Straight Google [Docs] is now loaded'); // Spread Sheet if (/docs\.google\.com\/spreadsheet\/.+/.test($$url)) listen('a.docs-bubble-link[target="_blank"]',['mouseup', 'mouseover'], google_url_clean); // Other products else if (/docs\.google\.com\/(document|presentation|drawings)\/.+/.test($$url)) listen('div.docs-bubble a[target="_blank"]',['mouseup', 'mouseover'], google_url_clean); } // Google Maps else if (/(ditu|maps)\.google\.com/.test($$url) || /www\.google\.com\/maps/.test($$url)) { console.debug('Straight Google [Maps] is now loaded'); listen('.pp-headline-authority-page a[target="_blank"]', 'mouseover', google_url_clean); } // Google Groups else if (/groups\.google\.com\/group\//.test($$url)) { console.debug('Straight Google [Groups] is now loaded'); listen('#inbdy a[target="_blank"]', 'mouseover', google_url_clean); } // Google Search else if (/:\/\/(www|encrypted|ipv6)\.google\..+(\/((search)?(\?|#)|.+&)(q|tbs)=.+)?$/.test($$url)) { console.debug('Straight Google [Search] is now loaded'); // do a deep clean, kill the rwt function injectWindow('rwt', function () { $$w.rwt = function ($_self) { google_url_clean.call($_self); $_self.removeAttribute('onmousedown'); return true; }; }, function (w) { return /google/i.test(''+ w['rwt']); }); // define the elements need to be rebinded after page reloading var _rebind_elements = '#nav, #ms, #bms'; function search_clean() { each( $$d.querySelectorAll('#ires a.l[href][onmousedown]'), function () { google_url_clean.call(this); this.removeAttribute('onmousedown'); console.debug("Click event of link ["+ this.href +"] is now removed."); } ); // image redirection each( $$d.querySelectorAll('#ires a[href^="/url?"]'), google_url_clean ); } // enable google instant var page_clickevent = (function ($c) { var eid = '', interval=null, click_event; function check_eid() { var obj = $$d.querySelector('#rso'); // the interval check runs until the eid is changed if (obj && obj.getAttribute('eid') != eid) { if (interval) clearInterval(interval); interval = null; // do clean job $c(); // rebind the click event listen(_rebind_elements, "click", click_event); } } click_event = function() { var obj = $$d.querySelector('#rso'); // record current eid eid = obj ? obj.getAttribute('eid') : ''; if (!interval) interval = setInterval(check_eid, 500); } return click_event; })(search_clean); // listen to the pagenation listen(_rebind_elements, "click", page_clickevent); var googleinstant = (function ($c) { var eid='', interval=null; function check_eid() { // eid will change when the result is changed var res = $$d.querySelector('#rso'); if (res && res.getAttribute('eid') != eid) { eid = res.getAttribute('eid'); // do the clean $c(); // re-bind event to pagenation listen(_rebind_elements, "click", page_clickevent); } }; return function ($action) { if ($action == 'load') return function () { if (!interval) interval = setInterval(check_eid, 500); } else return function () { if (interval) clearInterval(interval); // clear interval interval = null; // run eid check for once page_clickevent(); } } })(search_clean); // listen to the input box - for Google Instant listen('#lst-ib, #gbqfq', ['focus','keypress'] , googleinstant('load')); listen('#lst-ib, #gbqfq', 'blur', googleinstant('unload')); listen('table[dir="ltr"]', ['click','keypress'], page_clickevent); // input box mointering end // be cool with AutoPager listen("#navcnt", "DOMNodeInserted", search_clean, true); } })(document);
Continue reading...