Web site exhibits JavaScript error on iPad / iPhone under 3G but not under WiFi - iphone

Connecting to http://www.manage-us.com on an iPad under 3G [used to] result in a JavaScript error which can be seen if the developer console has been enabled. If the same page is accessed using the same iPad under a WiFi connection no error is displayed. [The error has now gone because I applied the fix below!].
Why is this?
I've tried simulating low bandwidth (using dummynet) on Safari on Mac and on the iPad simulator on Mac. This does not reproduce the problem.
I am currently suspecting this is a problem being introduced by my mobile operator in the UK (O2) which is known to modify some content through a proxy cache such as downgrading image files. If you can confirm that you don't experience this problem when connecting by 3G on iPad or iPhone through another mobile operator that would be helpful.

I've investigated this further and discovered that the problem is that the UK mobile operator O2 (the original exclusive iPhone operator for Apple), modifies web content before sending it to iPhones and iPads. Probably before sending it to any device running a mobile browser.
They non-deterministically inline some of the CSS and JavaScript into the main source files of the web pages. This can create errors either because of mistakes in their algorithm or the consequence of stripping white space from source files with syntactic mistakes in the source files which were otherwise benign.
These modifications also strip copyright messages from copyrighted javascript libraries and css libraries and play havoc with delivery optimisations.
For example, imagine if a user is visiting a sequence of pages on your site which all link to jQuery libraries. Instead of letting your mobile browser locally cache the library, O2 inline the library on every page, forcing your phone to load the entire library over and over again for every page.
I've written a blog about the issue here in the hope if drawing a bit more attention to this: http://stuartroebuck.blogspot.com/2010/07/mobile-proxy-cache-content-modification.html
My workaround is to use document.write() to insert the JavaScript library dependencies at load time and prevent O2 from inlining them. This seems to work quite well. e.g.:
<script type="text/javascript">
// <![CDATA[
// Using document.write to load JavaScript dependencies to bypass O2 network inlining of JavaScript.
function loadJS(file){document.write("<" + "script type='text/javascript' src='" + file + "'></" + "script>")}
loadJS("/js/jquery-1.4.2.min.js");
loadJS("/js/myJSLibrary.js");
// ]]>
</script>
Note that, as ever, document.write will not work if the page is served as XHTML.

For anyone needing a solution to this in ASP.NET, this sets the Cache-Control header as per http://stuartroebuck.blogspot.com/2010/08/official-way-to-bypassing-data.html for javascript files using URL Rewrite Module 2.0 http://learn.iis.net/page.aspx/665/url-rewrite-module-20-configuration-reference.
<system.webServer>
<rewrite>
<outboundRules>
<rule name="Compression header" preCondition="Match JS Files">
<match serverVariable="RESPONSE_Cache-Control" pattern="(.*)" />
<action type="Rewrite" value="no-transform" />
</rule>
<preConditions>
<preCondition name="Match JS Files">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="(javascript)$" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
Alternatively can be done using a HttpModule
public class AddHeaderModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.EndRequest += OnEndRequest;
}
void OnEndRequest(object sender, System.EventArgs e)
{
if(HttpContext.Current.Response.ContentType.Contains("javascript"))
HttpContext.Current.Response.Headers.AddHeader("Cache-Control", "no-transform");
}
}
and
<configuration>
<system.web>
<httpModules>
<add name="AddHeaderModule" type="your.namespace.AddHeaderModule" />
</httpModules>
</system.web>
</configuration>

Related

How to diagnose failed validation of Word Add-In when it works on my own setup?

I'm developing an MS Word Add-In. I've tested it on both Windows and Mac, and it works fine for me. Microsoft requires its own validation of Add-Ins to make sure they work correctly, and my Add-In fails for them even though it works for me with the same version of Windows and Word.
I had a phone call with the Microsoft Validation team, and their only suggestion was that I post a question on Stack Overflow so here goes!
This is the version of Windows and Word that works for me but fails for the MS Validation team:
Windows 10 Pro OS build 18362.295
Word 2016 (Version 1908 in particular)
I submitted a very simple add-in to Microsoft for debugging purposes. This simple add-in has only a single button that just opens a web page in the user's default browser.
This is the relevant portion of the manifest:
<Control xsi:type="Button" id="PB.Home.Button">
<Label resid="PB.Home.Button.Label"/>
<Supertip>
<Title resid="PB.Home.Button.Title"/>
<Description resid="PB.Home.Button.Desc"/>
</Supertip>
<Icon> ... </Icon>
<Action xsi:type="ExecuteFunction">
<FunctionName>navigateToWebPage</FunctionName>
</Action>
</Control>
This is the entirety of FunctionFile.html:
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js" ></script>
<script src="https://appsforoffice.microsoft.com/lib/1/hosted/Office.js" type="text/javascript"></script>
<script src="FunctionFile.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>
This is the entirety of FunctionFile.js:
(function () {
Office.initialize = function (reason) {};
})();
function navigateToWebPage(event) {
window.open('https://www.example.com', '_blank');
event.completed();
}
On my computer, when the button is clicked, a browser tab is opened with the web page, but for the MS Validation team this message appears in the toolbar at the bottom of the Word window
but nothing else happens.
The message "Patent Bots GCP is working on your Examiner Statistics" is generated by Word and not by my add in. "Patent Bots GCP" is the name of the add in and "Examiner Statistics" is the button label (one of the short strings in the manifest).
Any suggestions for how I can find out what is failing for the Microsoft Validation team? They are not able to provide any details about the error other than what I've included here.
I hope a Microsoft engineer sees this and is able to help.
=====
Maybe it is a popup blocker issue? See this: https://www.tek-tips.com/viewthread.cfm?qid=949178
Following up on Ragavan's comment, I did some searching for unexpected behavior of window.open() on IE11 (IE11 is the browser used in MS Word on Windows 10).
I found this other SO question, that noted
In IE on Windows 10 with default settings, if I perform a
window.open() against an external internet site from a page on my
local machine or a server on my local network, I get null.
that question further noted that
Interestingly, if I turn on "Enable Protected Mode" for the Intranet
Zone (so that Protected Mode are the same in the Intranet Zone and
Internet Zone), then the problem goes away.
I suspect this explains why my add in works on my Windows 10 computer, but not on the validation team's Windows 10 VM.
Unfortunately, the solution proposed in the answer there (w = window.open('') followed by w.location = url) does not work in the Word add in.
While this doesn't fix my problem, hopefully it leads the way to a solution...
#gaefan. Just adding my answer too if any one will have the same problem in future.
If anyone trying to open the external site from their add-in using JS window.open will end up in Object Expected aka validation failure error definitely by Microsoft. It depends on various factors like Windows 10 Build version, Office version and the Browser used by Add-ins.
So to publish your add-in successfully in the App source:
Note: This method is a workaround . But in near future If the new edge chromium version is released. Browser used by Add-ins will be changed. Then the workaround can be eliminated.
Use Task Pane add-in approach if your want to open any external site from Add-in.
The reason for recommonding Task-pane add-in is you can make utilize the anchor tag in your HTML like below
<a
href="https://yourcompany.com/"
class="button-config"
target="_blank"
(click)="performOperation()"
>Sign up
</a>
The reason for click event is to trigger any analytics function or trigger logs or add your custom logic
This will definitely open the external site without changing any settings on your browser.
If you want to stick on with command based add-in try adding new Action or Control button to open a external site via anchor tag.
Hope it will help some one. Thanks

GWT: Load different css in host page

I have gwt application based on GWTP. App supports two versions (tablet & desktop) and uses different widget libraries (sencha gxt and sencha touch). These libraries require different css files in host page. Moreother css are in conflict each to other. How I can load different css files in my host page?
I already read about gwt mobilewebapp sample, but they use single html-page and different implementations of components.
You can check the Useragent and decide which CSS File to deliver.
I recommend to use ClientBundles. This deliver only the css styles need, and speed up your page.
In your Entrypoint you just decide which css file you want to deliver:
if(useragent == "desktop") {
YourStyle.getTheme().getMGWTClientBundle().getDesktopCss().ensureInjected();
} else {
YourStyle.getTheme().getMGWTClientBundle().getAppCss().ensureInjected();
}
or you can make a switch inside your css files. But you have to use ClientBundles anyway.
There you can have something like this:
#external gwt-button;
#if user.agent safari {
.gwt-Button {
...
}
}
#external gwt-button is to avoid obfuscation errors. you can also use #external *;
You could also do this on the server side, by using a JSP file as the css source.
Then, in the JSP file, decide which set of properties to send based on the requesting user agent or other.
Another option is to write the host page as a JSP file, and it can include the proper CSS file based on the request.
This is a pretty easy way to go, but you must enable the JSP processor in your web.xml. It also requires your deployed system to have a java compiler on it, which is not the case if you only install the JRE on the webserver.
You have to create two classes which load the css file :
You can do some thing related to type in gwt.xml file
<replace-with
class="com.test.classMobile">
<when-type-is
class="com.Test.classBrowser" />
<when-property-is name="tablet.user.agent" value="ipad" />
</replace-with>
Just try this..I am not sure 100%

Identify Touch/Gesture Capable Devices using GWT

I would like to know if it is possible to identify whether a device is capable of Touch/Gesture Events or not in GWT?
Devices like iPhone supports Multi-Touch Events to a huge extent. Similarly Google Chrome in Desktop also supports TouchEvents. And at present, Windows 8 has been designed with an IE that is responding to TouchEvents.
I am working on an Application where i want to restrict certain features to only Touch/Gesture Capable Devices! Any Solution, please help?
I don't think there's any other way than UA sniffing.
GWT currently does not provide such utility.
Also, till gwt provides us a direct utlity api, it would make sense to write jsni over existing javascript techniques like these stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript .
For windows 8 the msdn document to refer is http://blogs.msdn.com/b/ie/archive/2011/09/20/touch-input-for-ie10-and-metro-style-apps.aspx
I did this with User Agent Check in Deferred Binding. I created a white list so that more devices can be added later.
Here is the Code,
<!-- Definitions for mobile -->
<define-property name="mobile.user.agent" values="android, ios, not_mobile" />
<property-provider name="mobile.user.agent"><![CDATA[
{
var ua = window.navigator.userAgent.toLowerCase();
if (ua.indexOf("android") != -1) { return "android"; }
if (ua.indexOf("iphone") != -1) { return "ios"; }
if (ua.indexOf("ipad") != -1) { return "ios"; }
return 'not_mobile';
}
]]></property-provider>
<!-- Constrain the value for non-webkit browsers -->
<set-property name="mobile.user.agent" value="not_mobile" >
<none> <!-- Actually means NOR, in this case "not safari" -->
<when-property-is name="user.agent" value="safari" />
</none>
</set-property>
Then i defined my classes using the replace-with property in my Module file. Here for example, i have replaced flash player with HTML5 videos for devices like iPad.
<replace-with class="com.example.HTML5Player">
<when-type-is class="com.example.FlashPlayer" />
<any>
<when-property-is name="mobile.user.agent" value="android" />
<when-property-is name="mobile.user.agent" value="ios" />
</any>
</replace-with>

Prevent application from running on a particular browser

When I build a GWT application, it runs on all browsers like IE,chrome,firefox etc. provided GWT plugin is installed for that browser.
I want to know how can I prevent a GWT application from running on a particular browser i.e. if I don't want my GWT apps to run on say Firefox, how can I achieve that? What changes I need to do in my code?
Add <set-property name="user.agent" value="ie6,ie8,ie9,safari,opera" /> to your *.gwt.xml file and it will fail to load in Firefox (FYI, Firefox's user.agent token is gecko1_8).
If you don't want to support IE6 and IE7 for instance, you don't need to compile for them, and you can decrease your compilation time by removing the ie6 token from the user.agent value list.

GWT deferred binding

GWT offers javascript files mainly for Fifefox, chrome....., but what happens if another browser is being used such as K Melon or another browser which GWT does not specifically generates the javascript for that browser!!
I have tested for K Melon, it works correctly but i just want to know, how GWT knows which Javascript files to load
This is probably way more information than you wanted.
As far as mechanics go, GWT grabs the user agent from the browser, then uses a mechanism called a "property provider" to classify the browser. So, a property provider sets a property named "user.agent" to one of several predefined classes of browsers.
Here is an XML file which defines constants for all classes of browsers GWT currently knows about:
http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/user/UserAgent.gwt.xml?
At compile time, your app is compiled separately for each class of browser you want to support, and a different batch of JS gets loaded for each type of browser. The beauty of this is that the end user downloads the minimum amount of code needed to run the app, and won't be bloated by having conditional code for IE when you are running Chrome or Firefox.
Its a bit complex, but you can peek at the code that writes out some JavaScript to examine the User Agent string here to determine which class of browser is currently running:
http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/user/rebind/UserAgentPropertyGenerator.java
Once it picks a value for the user.agent property, the various parts of GWT conditionally substitute in code where browser specific logic is needed. Most browsers return a long list of "compatible" user agents. GWT tries to pick the best match from those. You can see that there is a default case - if the user agent string isn't recognized at all it sets the user.agent value to 'unknown' and fires up a warning to alert that the developer needs to manually pick one.
To dive a little deeper, here's the mechanism the compiler uses to pull in browser specific code based on the user.agent property:
(from Window.gwt.xml)
<module>
<inherits name="com.google.gwt.core.Core"/>
<inherits name="com.google.gwt.user.UserAgent"/>
<replace-with class="com.google.gwt.user.client.impl.WindowImplIE">
<when-type-is class="com.google.gwt.user.client.impl.WindowImpl"/>
<any>
<when-property-is name="user.agent" value="ie6"/>
<when-property-is name="user.agent" value="ie8"/>
<when-property-is name="user.agent" value="ie9"/>
</any>
</replace-with>
</module>
You'll notice that if 'webkit' is seen in the user agent, GWT returns the string 'safari' to identify the class of browser. There is no separate class of browser for Chrome. Chrome and Safari are very similar, and pretty closely written to specs, so there's not a lot of special casing for them. But that's not to say that there isn't Chrome specific code in some places. Sometimes a difference in browser will be detected at runtime. Its only done this way when there are just small browser differences. Here's an example of the way a minor difference between Chrome and Safari is handled:
public class HyperlinkImplSafari extends HyperlinkImpl {
private static boolean shiftIsModifier = onChrome();
private static native boolean onChrome() /*-{
return navigator.userAgent.indexOf("Chrome") != -1;
}-*/;
#Override
public boolean handleAsClick(Event event) {
//...
boolean modifiers = alt || ctrl || meta;
if (shiftIsModifier) {
modifiers |= shift;
}
return !modifiers && !middle && !right;
}
}
Check this post out - Google GWT cross-browser support: is it BS?
Even with the big names in browser industry, my experience with GWT apps hasn't been 100% compatibility, but really comes close.
For other browsers, it will look for the engine (most of them are offshoots of webkit or variants of mozilla's offering), if that is recognized, GWT generates the code for it more or less.
Anyways, the user base for such browsers itself is too tiny. In practice, it mostly suffices to test compatibility between IE6 (sigh), IE7, IE8 (yes they behave differently!), Firefox, and nowadays, chrome, safari and IE9.