Bug 766406 - Implement "Request Desktop Site". r=mfinkle

This commit is contained in:
Brian Nicholson 2012-06-22 12:53:40 -07:00
Родитель 3de1510717
Коммит d719f7187f
10 изменённых файлов: 151 добавлений и 13 удалений

Просмотреть файл

@ -574,6 +574,7 @@ abstract public class BrowserApp extends GeckoApp
MenuItem saveAsPDF = aMenu.findItem(R.id.save_as_pdf);
MenuItem charEncoding = aMenu.findItem(R.id.char_encoding);
MenuItem findInPage = aMenu.findItem(R.id.find_in_page);
MenuItem desktopMode = aMenu.findItem(R.id.desktop_mode);
if (tab == null || tab.getURL() == null) {
bookmark.setEnabled(false);
@ -608,6 +609,7 @@ abstract public class BrowserApp extends GeckoApp
}
forward.setEnabled(tab.canDoForward());
desktopMode.setChecked(tab.getDesktopMode());
// Disable share menuitem for about:, chrome:, file:, and resource: URIs
String scheme = Uri.parse(tab.getURL()).getScheme();

Просмотреть файл

@ -698,6 +698,19 @@ abstract public class GeckoApp
case R.id.find_in_page:
mFindInPageBar.show();
return true;
case R.id.desktop_mode:
Tab selectedTab = Tabs.getInstance().getSelectedTab();
if (selectedTab == null)
return true;
JSONObject args = new JSONObject();
try {
args.put("desktopMode", !item.isChecked());
args.put("tabId", selectedTab.getId());
} catch (JSONException e) {
Log.e(LOGTAG, "error building json arguments");
}
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("DesktopMode:Change", args.toString()));
return true;
default:
return super.onOptionsItemSelected(item);
}
@ -1215,6 +1228,20 @@ abstract public class GeckoApp
} else if (event.equals("WebApps:Uninstall")) {
String uniqueURI = message.getString("uniqueURI");
GeckoAppShell.uninstallWebApp(uniqueURI);
} else if (event.equals("DesktopMode:Changed")) {
int tabId = message.getInt("tabId");
boolean desktopMode = message.getBoolean("desktopMode");
final Tab tab = Tabs.getInstance().getTab(tabId);
if (tab == null)
return;
tab.setDesktopMode(desktopMode);
mMainHandler.post(new Runnable() {
public void run() {
if (tab == Tabs.getInstance().getSelectedTab())
invalidateOptionsMenu();
}
});
}
} catch (Exception e) {
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
@ -1890,6 +1917,7 @@ abstract public class GeckoApp
GeckoAppShell.registerGeckoEventListener("WebApps:Open", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("WebApps:Install", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("WebApps:Uninstall", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("DesktopMode:Changed", GeckoApp.mAppContext);
if (SmsManager.getInstance() != null) {
SmsManager.getInstance().start();
@ -2232,6 +2260,7 @@ abstract public class GeckoApp
GeckoAppShell.unregisterGeckoEventListener("WebApps:Open", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("WebApps:Install", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("WebApps:Uninstall", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("DesktopMode:Changed", GeckoApp.mAppContext);
if (mFavicons != null)
mFavicons.close();

Просмотреть файл

@ -69,6 +69,7 @@ public final class Tab {
private int mState;
private ByteBuffer mThumbnailBuffer;
private Bitmap mThumbnailBitmap;
private boolean mDesktopMode;
public static final int STATE_DELAYED = 0;
public static final int STATE_LOADING = 1;
@ -661,4 +662,12 @@ public final class Tab {
int b = Integer.parseInt(matcher.group(3));
return Color.rgb(r, g, b);
}
public void setDesktopMode(boolean enabled) {
mDesktopMode = enabled;
}
public boolean getDesktopMode() {
return mDesktopMode;
}
}

Просмотреть файл

@ -96,6 +96,7 @@
<!ENTITY share_title "Share via">
<!ENTITY save_as_pdf "Save as PDF">
<!ENTITY find_in_page "Find in Page">
<!ENTITY desktop_mode "Request Desktop Site">
<!-- Localization note (find_text, find_prev, find_next, find_close) : These strings are used
as alternate text for accessibility. They are not visible in the UI. -->

Просмотреть файл

@ -36,6 +36,10 @@
<item gecko:id="@+id/find_in_page"
gecko:title="@string/find_in_page" />
<item gecko:id="@+id/desktop_mode"
gecko:title="@string/desktop_mode"
gecko:checkable="true" />
<item gecko:id="@+id/site_settings"
gecko:icon="@drawable/ic_menu_clear_site_settings"
gecko:title="@string/site_settings_title" />

Просмотреть файл

@ -33,6 +33,10 @@
<item gecko:id="@+id/find_in_page"
gecko:title="@string/find_in_page" />
<item gecko:id="@+id/desktop_mode"
gecko:title="@string/desktop_mode"
gecko:checkable="true" />
<item gecko:id="@+id/site_settings"
gecko:icon="@drawable/ic_menu_clear_site_settings"
gecko:title="@string/site_settings_title" />

Просмотреть файл

@ -36,6 +36,10 @@
<item gecko:id="@+id/find_in_page"
gecko:title="@string/find_in_page" />
<item gecko:id="@+id/desktop_mode"
gecko:title="@string/desktop_mode"
gecko:checkable="true" />
<item gecko:id="@+id/site_settings"
gecko:icon="@drawable/ic_menu_clear_site_settings"
gecko:title="@string/site_settings_title" />

Просмотреть файл

@ -32,6 +32,10 @@
<item android:id="@+id/find_in_page"
android:title="@string/find_in_page" />
<item android:id="@+id/desktop_mode"
android:title="@string/desktop_mode"
android:checkable="true" />
<item android:id="@+id/site_settings"
android:title="@string/site_settings_title" />

Просмотреть файл

@ -58,6 +58,7 @@
<string name="share_title">&share_title;</string>
<string name="save_as_pdf">&save_as_pdf;</string>
<string name="find_in_page">&find_in_page;</string>
<string name="desktop_mode">&desktop_mode;</string>
<string name="find_text">&find_text;</string>
<string name="find_prev">&find_prev;</string>

Просмотреть файл

@ -1729,15 +1729,25 @@ var SelectionHandler = {
var UserAgent = {
DESKTOP_UA: null,
init: function ua_init() {
Services.obs.addObserver(this, "DesktopMode:Change", false);
Services.obs.addObserver(this, "http-on-modify-request", false);
// See https://developer.mozilla.org/en/Gecko_user_agent_string_reference
this.DESKTOP_UA = Cc["@mozilla.org/network/protocol;1?name=http"]
.getService(Ci.nsIHttpProtocolHandler).userAgent
.replace(/Android; [a-zA-Z]+/, "X11; Linux x86_64")
.replace(/Gecko\/[0-9\.]+/, "Gecko/20100101");
},
uninit: function ua_uninit() {
Services.obs.removeObserver(this, "DesktopMode:Change");
Services.obs.removeObserver(this, "http-on-modify-request");
},
getRequestLoadContext: function ua_getRequestLoadContext(aRequest) {
_getRequestLoadContext: function ua_getRequestLoadContext(aRequest) {
if (aRequest && aRequest.notificationCallbacks) {
try {
return aRequest.notificationCallbacks.getInterface(Ci.nsILoadContext);
@ -1753,25 +1763,42 @@ var UserAgent = {
return null;
},
getWindowForRequest: function ua_getWindowForRequest(aRequest) {
let loadContext = this.getRequestLoadContext(aRequest);
_getWindowForRequest: function ua_getWindowForRequest(aRequest) {
let loadContext = this._getRequestLoadContext(aRequest);
if (loadContext)
return loadContext.associatedWindow;
return null;
},
observe: function ua_observe(aSubject, aTopic, aData) {
if (!(aSubject instanceof Ci.nsIHttpChannel))
return;
switch (aTopic) {
case "DesktopMode:Change": {
let args = JSON.parse(aData);
let tab = BrowserApp.getTabForId(args.tabId);
if (tab != null)
tab.reloadWithMode(args.desktopMode);
break;
}
case "http-on-modify-request": {
let channel = aSubject.QueryInterface(Ci.nsIHttpChannel);
let channelWindow = this._getWindowForRequest(channel);
let tab = BrowserApp.getTabForWindow(channelWindow);
if (tab == null)
break;
let channel = aSubject.QueryInterface(Ci.nsIHttpChannel);
let channelWindow = this.getWindowForRequest(channel);
if (BrowserApp.getBrowserForWindow(channelWindow)) {
if (channel.URI.host.indexOf("youtube") != -1) {
let ua = Cc["@mozilla.org/network/protocol;1?name=http"].getService(Ci.nsIHttpProtocolHandler).userAgent;
// Send XUL UA to YouTube; temporary hack to make videos play
if (channel.URI.host.indexOf("youtube") != -1) {
let ua = Cc["@mozilla.org/network/protocol;1?name=http"].getService(Ci.nsIHttpProtocolHandler).userAgent;
#expand let version = "__MOZ_APP_VERSION__";
ua += " Fennec/" + version;
channel.setRequestHeader("User-Agent", ua, false);
ua += " Fennec/" + version;
channel.setRequestHeader("User-Agent", ua, false);
}
// Send desktop UA if "Request Desktop Site" is enabled
if (tab.desktopMode && (channel.loadFlags & Ci.nsIChannel.LOAD_DOCUMENT_URI))
channel.setRequestHeader("User-Agent", this.DESKTOP_UA, false);
break;
}
}
}
@ -1895,6 +1922,8 @@ function Tab(aURL, aParams) {
this.pluginDoorhangerTimeout = null;
this.shouldShowPluginDoorhanger = true;
this.clickToPlayPluginsActivated = false;
this.desktopMode = false;
this.originalURI = null;
}
Tab.prototype = {
@ -1987,6 +2016,53 @@ Tab.prototype = {
}
},
/**
* Reloads the tab with the desktop mode setting.
*/
reloadWithMode: function (aDesktopMode) {
// Set desktop mode for tab and send change to Java
if (this.desktopMode != aDesktopMode) {
this.desktopMode = aDesktopMode;
sendMessageToJava({
gecko: {
type: "DesktopMode:Changed",
desktopMode: aDesktopMode,
tabId: this.id
}
});
}
// Only reload the page for http/https schemes
let currentURI = this.browser.currentURI;
if (!currentURI.schemeIs("http") && !currentURI.schemeIs("https"))
return;
let url = currentURI.spec;
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE;
if (this.originalURI && !this.originalURI.equals(currentURI)) {
// We were redirected; reload the original URL
url = this.originalURI.spec;
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY;
} else {
// Many sites use mobile-specific URLs, such as:
// http://m.yahoo.com
// http://www.google.com/m
// If the user clicks "Request Desktop Site" while on a mobile site, it
// will appear to do nothing since the mobile URL is still being
// requested. To address this, we do the following:
// 1) Remove the path from the URL (http://www.google.com/m?q=query -> http://www.google.com)
// 2) If a host subdomain is "m", remove it (http://en.m.wikipedia.org -> http://en.wikipedia.org)
// This means the user is sent to site's home page, but this is better
// than the setting having no effect at all.
if (aDesktopMode)
url = currentURI.prePath.replace(/([\/\.])m\./g, "$1");
else
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY;
}
this.browser.docShell.loadURI(url, flags, null, null, null);
},
destroy: function() {
if (!this.browser)
return;
@ -2590,7 +2666,11 @@ Tab.prototype = {
let success = false;
let uri = "";
try {
uri = aRequest.QueryInterface(Components.interfaces.nsIChannel).originalURI.spec;
// Remember original URI for UA changes on redirected pages
this.originalURI = aRequest.QueryInterface(Components.interfaces.nsIChannel).originalURI;
if (this.originalURI != null)
uri = this.originalURI.spec;
} catch (e) { }
try {
success = aRequest.QueryInterface(Components.interfaces.nsIHttpChannel).requestSucceeded;