Chrome and It's Handling of %S

Chrome and it's handling of %s

It's a bug.

Did this JavaScript break the console?

As discussed in the comments, there are actually many different ways of constructing a string that causes this issue, and it is not necessary for there to be two percent signs in most cases.

http://example.com/%
http://%%%
http://ab%
http://%ab
http://%zz

However, it's not just the presence of a percent sign that breaks the Chrome console, as when we enter the following well-formed URL, the console continues to work properly and produces a clickable link.

http://ab%20cd

Additionally, the strings http://%, and http://%% will also print properly, since Chrome will not auto-link a URL-link string unless the http:// is followed by at least 3 characters.

From here I hypothesized that the issue must be in the process of linking a URL string in the console, likely in the process of decoding a malformed URL. I remembered that the JavaScript function decodeURI will throw an exception if given a malformed URL, and since Chrome's developer tools are largely written in JavaScript, could this be the issue that is evidently crashing the developer console?

To test this theory, I ran Chrome by the command link, to see if any errors were being logged.

Indeed, the same error you would see if you ran decodeURI on a malformed URL (i.e. decodeURI('http://example.com/%')) was being printed to the console:

[4810:1287:0107/164725:ERROR:CONSOLE(683)] "Uncaught URIError: URI malformed", source: chrome-devtools://devtools/bundled/devtools.js (683)

So, I opened the URL chrome-devtools://devtools/bundled/devtools.js in Chrome, and on line 683, I found the following.

{var parsedURL=new WebInspector.ParsedURL(decodeURI(url));var origin;var folderPath;var name;if(parsedURL.isValid){origin=parsedURL.scheme+"://"+parsedURL.host;if(parsedURL.port)

As we can see, decodeURI(url) is being called on the URL without any error checking, thus throwing the exception and crashing the developer console.

A real fix for this issue will come from adding error handling to the Chrome console code, but in the meantime, one way to avoid the issue would be to wrap the string in a complex data type like an array to prevent parsing when logging.

var x = "http://example.com/%";
console.log([x]);

Thankfully, the broken console issue does not persist once the tab is closed, and will not affect other tabs.

Update:

Apparently, the issue can persist across tabs and restarts if Preserve Log is checked. Uncheck this if you are having this issue.

Update 2:

As of Chrome 40, this issue is fixed.

Chrome WebDriverException using selenium

You can try as following

driver = webdriver.Chrome(executable_path=r'Path_to_chrome_Driver\\chromedriver.exe')

You are locating chrome browser exe location. Please download chrome driver for selenium Chromedriver. Then enter the chrome driver location.

Note: Make sure you have downloaded the correct chromedriver based on your chrome browser version.

selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PATH error with Headless Chrome

If we analyze the logs it seems the main issue is with in start os.path.basename(self.path) and subsequent error message:

selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PATH

So it's clear from the error that the Python client was unable to locate the chromedriver executable binary.

You need to take care of a couple of things as follows:

  1. chrome_options.binary_location : The parameter points to the chrome.exe not the chromedriver.exe

  2. os.path.abspath("chromedriver") will pick up the file path of chromedriver but won't append chromedriver.exe at the end.

  3. Here is the sample code on my windows-8 system to start google-chrome-headless:

    from selenium import webdriver  
    from selenium.webdriver.chrome.options import Options

    chrome_options = Options()
    chrome_options.add_argument("--headless")
    driver = webdriver.Chrome(chrome_options=chrome_options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
    driver.get("http://www.duo.com")
    print("Chrome Browser Initialized in Headless Mode")
    driver.quit()
    print("Driver Exited")

Update chrome.storage if extension's file changes

With a nudge from Florian in a chat, I came up with the following solution using a second chrome.storage space.

I was already checking to see if a stylesheet exists inside of the user's Chrome storage and loading the stylesheet from the extension's files if it didn't exist. To cause it to auto update upon changes, I now check a second chrome.storage space that holds a version number when checking whether or not to load the stylesheet from Chrome's storage. The basic approach is as follows:

// Helper function that checks whether an object is empty or not
function isEmpty(obj) {
return Object.keys(obj).length === 0;
}

var stylesheetObj = {}, // Keeps track of all stylesheets
stylesheetVersion = 1; // THIS NUMBER MUST BE CHANGED FOR THE STYLESHEETS TO KNOW TO UPDATE

chrome.storage.sync.get('just-read-stylesheets', function (result) {
// Here 'results' is an object with all stylesheets if it exists

// This keeps track of whether or not the user has the latest stylsheet version
var needsUpdate = false;

// Here I get the user's current stylesheet version
chrome.storage.sync.get('stylesheet-version', function (versionResult) {

// If the user has a version of the stylesheets and it is less than the cufrent one, update it
if(isEmpty(versionResult)
|| versionResult['stylesheet-version'] < stylesheetVersion) {

chrome.storage.sync.set({'stylesheet-version': stylesheetVersion});

needsUpdate = true;
}

if(isEmpty(result) // Not found, so we add our default
|| isEmpty(result["just-read-stylesheets"])
|| needsUpdate) { // Update the default stylesheet if it's on a previous version

// Open the default CSS file and save it to our object
var xhr = new XMLHttpRequest();
xhr.open('GET', chrome.extension.getURL('default-styles.css'), true);
// Code to handle successful GET here
}
xhr.send();
return;
}

// Code to do if no load is necessary here
});
});

This makes it so that the only thing that has to be changed to update the stylesheet for users is stylesheetVersion, making sure that it is larger than the previous versions. For example, if I updated the stylesheet and wanted the user's version to auto update, I would change stylesheetVersion from 1 to 1.1.

If you need a more full implementation, you can find the JS file here on GitHub

Do different browsers render decimal percentage sizes differently?

Yes they do.

From my memory:

In Opera, you cannot set the decimal places of the percentage so, if you set 33.3% it uses only 33% (rather annoying) (edit:Opera may have improved on that in current version as it seems)

In Firefox, if you have percentages that add up to 100%, the pixels don't always add up to the 100% of the pixels

e.g. you have a outer div with three columns all with width: 33.33333%. If the outer div has width 100px, the columns will have 33 pixels and the sum is 99 pixels and not 100.
(edit: Firefox does better than I remember. Maybe they improved)

Old IE, I cannot remember IE9 seems to work fine. The bad one of course is IE7, which rounds up (as the IE6, but who cares?). IE8/9 seem to work ok

Chrome works fine

Safari: can't remember


edit

Her one can test for oneself

http://jsfiddle.net/fTpFw/


conclusion

After I played with my fiddle in different browsers I think they all have improved. The only bad implementations (from what I want to achieve) in modern browsers is Opera and Safari. IE7 is a stopper, too. If you don't have to deal with these buggers, you could go ahead and use the percentage widths.

Handling asynchronous JavaScript Chrome Console Errors

Assumed that you have to handle errors with onerror you should handle the onclose as well.
The simplest check is the error code 1000 that means a normal socket close

exampleSocket.onclose = (event) => {
if (event.code != 1000) {
// "Normal closure, meaning that the purpose for which the connection was established has been fulfilled.";
}
}

While a complete handling of error codes is described here, and I'm putting here for your convenience:

     exampleSocket.onclose = (event) => {
if (event.code == 1000)
reason = "Normal closure, meaning that the purpose for which the connection was established has been fulfilled.";
else if(event.code == 1001)
reason = "An endpoint is \"going away\", such as a server going down or a browser having navigated away from a page.";
else if(event.code == 1002)
reason = "An endpoint is terminating the connection due to a protocol error";
else if(event.code == 1003)
reason = "An endpoint is terminating the connection because it has received a type of data it cannot accept (e.g., an endpoint that understands only text data MAY send this if it receives a binary message).";
else if(event.code == 1004)
reason = "Reserved. The specific meaning might be defined in the future.";
else if(event.code == 1005)
reason = "No status code was actually present.";
else if(event.code == 1006)
reason = "The connection was closed abnormally, e.g., without sending or receiving a Close control frame";
else if(event.code == 1007)
reason = "An endpoint is terminating the connection because it has received data within a message that was not consistent with the type of the message (e.g., non-UTF-8 [http://tools.ietf.org/html/rfc3629] data within a text message).";
else if(event.code == 1008)
reason = "An endpoint is terminating the connection because it has received a message that \"violates its policy\". This reason is given either if there is no other sutible reason, or if there is a need to hide specific details about the policy.";
else if(event.code == 1009)
reason = "An endpoint is terminating the connection because it has received a message that is too big for it to process.";
else if(event.code == 1010) // Note that this status code is not used by the server, because it can fail the WebSocket handshake instead.
reason = "An endpoint (client) is terminating the connection because it has expected the server to negotiate one or more extension, but the server didn't return them in the response message of the WebSocket handshake. <br /> Specifically, the extensions that are needed are: " + event.reason;
else if(event.code == 1011)
reason = "A server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request.";
else if(event.code == 1015)
reason = "The connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified).";
else
reason = "Unknown reason";
}

var exampleSocket = new WebSocket("ws://localhost:8080");    exampleSocket.onmessage = function (event) {        var JsonObject = JSON.parse(event.data);        console.log(JsonObject)        exampleSocket.send(event.data);
exampleSocket.onerror = function () { //do nothing } }exampleSocket.onclose = (event) => { if (event.code == 1000) reason = "Normal closure, meaning that the purpose for which the connection was established has been fulfilled."; else if(event.code == 1001) reason = "An endpoint is \"going away\", such as a server going down or a browser having navigated away from a page."; else if(event.code == 1002) reason = "An endpoint is terminating the connection due to a protocol error"; else if(event.code == 1003) reason = "An endpoint is terminating the connection because it has received a type of data it cannot accept (e.g., an endpoint that understands only text data MAY send this if it receives a binary message)."; else if(event.code == 1004) reason = "Reserved. The specific meaning might be defined in the future."; else if(event.code == 1005) reason = "No status code was actually present."; else if(event.code == 1006) reason = "The connection was closed abnormally, e.g., without sending or receiving a Close control frame"; else if(event.code == 1007) reason = "An endpoint is terminating the connection because it has received data within a message that was not consistent with the type of the message (e.g., non-UTF-8 [http://tools.ietf.org/html/rfc3629] data within a text message)."; else if(event.code == 1008) reason = "An endpoint is terminating the connection because it has received a message that \"violates its policy\". This reason is given either if there is no other sutible reason, or if there is a need to hide specific details about the policy."; else if(event.code == 1009) reason = "An endpoint is terminating the connection because it has received a message that is too big for it to process."; else if(event.code == 1010) // Note that this status code is not used by the server, because it can fail the WebSocket handshake instead. reason = "An endpoint (client) is terminating the connection because it has expected the server to negotiate one or more extension, but the server didn't return them in the response message of the WebSocket handshake. <br /> Specifically, the extensions that are needed are: " + event.reason; else if(event.code == 1011) reason = "A server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request."; else if(event.code == 1015) reason = "The connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified)."; else reason = "Unknown reason"; console.error(reason); }


Related Topics



Leave a reply



Submit