зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset d8a07729a34c (bug 1286663)
This commit is contained in:
Родитель
0e01bff3d3
Коммит
27ff1866d4
|
@ -68,6 +68,7 @@ public class GeckoEvent {
|
|||
MOTION_EVENT(2),
|
||||
NOOP(15),
|
||||
VIEWPORT(20),
|
||||
THUMBNAIL(25),
|
||||
NATIVE_GESTURE_EVENT(31),
|
||||
CALL_OBSERVER(33),
|
||||
REMOVE_OBSERVER(34),
|
||||
|
@ -339,6 +340,15 @@ public class GeckoEvent {
|
|||
return event;
|
||||
}
|
||||
|
||||
public static GeckoEvent createThumbnailEvent(int tabId, int bufw, int bufh, ByteBuffer buffer) {
|
||||
GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.THUMBNAIL);
|
||||
event.mPoints = new Point[1];
|
||||
event.mPoints[0] = new Point(bufw, bufh);
|
||||
event.mMetaState = tabId;
|
||||
event.mBuffer = buffer;
|
||||
return event;
|
||||
}
|
||||
|
||||
public static GeckoEvent createZoomedViewEvent(int tabId, int x, int y, int bufw, int bufh, float scaleFactor, ByteBuffer buffer) {
|
||||
GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.ZOOMEDVIEW);
|
||||
event.mPoints = new Point[2];
|
||||
|
|
|
@ -313,6 +313,68 @@ AutoGlobalWrappedJavaObject::~AutoGlobalWrappedJavaObject() {
|
|||
Dispose();
|
||||
}
|
||||
|
||||
// Decides if we should store thumbnails for a given docshell based on the presence
|
||||
// of a Cache-Control: no-store header and the "browser.cache.disk_cache_ssl" pref.
|
||||
static bool ShouldStoreThumbnail(nsIDocShell* docshell) {
|
||||
if (!docshell) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
|
||||
docshell->GetCurrentDocumentChannel(getter_AddRefs(channel));
|
||||
if (!channel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel;
|
||||
rv = channel->QueryInterface(NS_GET_IID(nsIHttpChannel), getter_AddRefs(httpChannel));
|
||||
if (!NS_SUCCEEDED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't store thumbnails for sites that didn't load
|
||||
uint32_t responseStatus;
|
||||
rv = httpChannel->GetResponseStatus(&responseStatus);
|
||||
if (!NS_SUCCEEDED(rv) || floor((double) (responseStatus / 100)) != 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cache-Control: no-store.
|
||||
bool isNoStoreResponse = false;
|
||||
httpChannel->IsNoStoreResponse(&isNoStoreResponse);
|
||||
if (isNoStoreResponse) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Deny storage if we're viewing a HTTPS page with a
|
||||
// 'Cache-Control' header having a value that is not 'public'.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = channel->GetURI(getter_AddRefs(uri));
|
||||
if (!NS_SUCCEEDED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't capture HTTPS pages unless the user enabled it
|
||||
// or the page has a Cache-Control:public header.
|
||||
bool isHttps = false;
|
||||
uri->SchemeIs("https", &isHttps);
|
||||
if (isHttps && !Preferences::GetBool("browser.cache.disk_cache_ssl", false)) {
|
||||
nsAutoCString cacheControl;
|
||||
rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Cache-Control"), cacheControl);
|
||||
if (!NS_SUCCEEDED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cacheControl.IsEmpty() && !cacheControl.LowerCaseEqualsLiteral("public")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
getHandlersFromStringArray(JNIEnv *aJNIEnv, jobjectArray jArr, jsize aLen,
|
||||
nsIMutableArray *aHandlersArray,
|
||||
|
@ -1782,6 +1844,110 @@ AndroidBridge::CaptureZoomedView(mozIDOMWindowProxy *window, nsIntRect zoomedVie
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult AndroidBridge::CaptureThumbnail(mozIDOMWindowProxy *window, int32_t bufW, int32_t bufH, int32_t tabId, ByteBuffer::Param buffer, bool &shouldStore)
|
||||
{
|
||||
nsresult rv;
|
||||
float scale = 1.0;
|
||||
|
||||
if (!buffer)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// take a screenshot, as wide as possible, proportional to the destination size
|
||||
nsCOMPtr<nsIDOMWindowUtils> utils = do_GetInterface(window);
|
||||
if (!utils)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMClientRect> rect;
|
||||
rv = utils->GetRootBounds(getter_AddRefs(rect));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!rect)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
float left, top, width, height;
|
||||
rect->GetLeft(&left);
|
||||
rect->GetTop(&top);
|
||||
rect->GetWidth(&width);
|
||||
rect->GetHeight(&height);
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
int32_t srcX = left;
|
||||
int32_t srcY = top;
|
||||
int32_t srcW;
|
||||
int32_t srcH;
|
||||
|
||||
float aspectRatio = ((float) bufW) / bufH;
|
||||
if (width / aspectRatio < height) {
|
||||
srcW = width;
|
||||
srcH = width / aspectRatio;
|
||||
} else {
|
||||
srcW = height * aspectRatio;
|
||||
srcH = height;
|
||||
}
|
||||
|
||||
JNIEnv* const env = jni::GetGeckoThreadEnv();
|
||||
|
||||
AutoLocalJNIFrame jniFrame(env, 0);
|
||||
|
||||
MOZ_ASSERT(window);
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win = nsPIDOMWindowOuter::From(window);
|
||||
RefPtr<nsPresContext> presContext;
|
||||
|
||||
nsIDocShell* docshell = win->GetDocShell();
|
||||
|
||||
// Decide if callers should store this thumbnail for later use.
|
||||
shouldStore = ShouldStoreThumbnail(docshell);
|
||||
|
||||
if (docshell) {
|
||||
docshell->GetPresContext(getter_AddRefs(presContext));
|
||||
}
|
||||
|
||||
if (!presContext)
|
||||
return NS_ERROR_FAILURE;
|
||||
nscolor bgColor = NS_RGB(255, 255, 255);
|
||||
nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
|
||||
uint32_t renderDocFlags = (nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING |
|
||||
nsIPresShell::RENDER_DOCUMENT_RELATIVE);
|
||||
nsRect r(nsPresContext::CSSPixelsToAppUnits(srcX / scale),
|
||||
nsPresContext::CSSPixelsToAppUnits(srcY / scale),
|
||||
nsPresContext::CSSPixelsToAppUnits(srcW / scale),
|
||||
nsPresContext::CSSPixelsToAppUnits(srcH / scale));
|
||||
|
||||
bool is24bit = (GetScreenDepth() == 24);
|
||||
uint32_t stride = bufW * (is24bit ? 4 : 2);
|
||||
|
||||
uint8_t* data = static_cast<uint8_t*>(buffer->Address());
|
||||
if (!data)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
MOZ_ASSERT(gfxPlatform::GetPlatform()->SupportsAzureContentForType(BackendType::CAIRO),
|
||||
"Need BackendType::CAIRO support");
|
||||
RefPtr<DrawTarget> dt =
|
||||
Factory::CreateDrawTargetForData(BackendType::CAIRO,
|
||||
data,
|
||||
IntSize(bufW, bufH),
|
||||
stride,
|
||||
is24bit ? SurfaceFormat::B8G8R8X8 :
|
||||
SurfaceFormat::R5G6B5_UINT16);
|
||||
if (!dt || !dt->IsValid()) {
|
||||
ALOG_BRIDGE("Error creating DrawTarget");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
RefPtr<gfxContext> context = gfxContext::CreateOrNull(dt);
|
||||
MOZ_ASSERT(context); // checked the draw target above
|
||||
|
||||
context->SetMatrix(
|
||||
context->CurrentMatrix().Scale(scale * bufW / srcW,
|
||||
scale * bufH / srcH));
|
||||
rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context);
|
||||
if (is24bit) {
|
||||
gfxUtils::ConvertBGRAtoRGBA(data, stride * bufH);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
AndroidBridge::GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort)
|
||||
{
|
||||
|
|
|
@ -148,6 +148,7 @@ public:
|
|||
bool GetFrameNameJavaProfiling(uint32_t aThreadId, uint32_t aSampleId, uint32_t aFrameId, nsCString & aResult);
|
||||
|
||||
nsresult CaptureZoomedView(mozIDOMWindowProxy *window, nsIntRect zoomedViewRect, jni::ByteBuffer::Param buffer, float zoomFactor);
|
||||
nsresult CaptureThumbnail(mozIDOMWindowProxy *window, int32_t bufW, int32_t bufH, int32_t tabId, jni::ByteBuffer::Param buffer, bool &shouldStore);
|
||||
void GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort);
|
||||
void ContentDocumentChanged();
|
||||
bool IsContentDocumentDisplayed();
|
||||
|
|
|
@ -310,6 +310,13 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj)
|
|||
break;
|
||||
}
|
||||
|
||||
case THUMBNAIL: {
|
||||
mMetaState = jenv->GetIntField(jobj, jMetaStateField);
|
||||
ReadPointArray(mPoints, jenv, jPoints, 1);
|
||||
mByteBuffer = new RefCountedJavaObject(jenv, jenv->GetObjectField(jobj, jByteBufferField));
|
||||
break;
|
||||
}
|
||||
|
||||
case ZOOMEDVIEW: {
|
||||
mX = jenv->GetDoubleField(jobj, jXField);
|
||||
mMetaState = jenv->GetIntField(jobj, jMetaStateField);
|
||||
|
|
|
@ -591,6 +591,7 @@ public:
|
|||
NOOP = 15,
|
||||
APZ_INPUT_EVENT = 17, // used internally in AndroidJNI/nsAppShell/nsWindow
|
||||
VIEWPORT = 20,
|
||||
THUMBNAIL = 25,
|
||||
NATIVE_GESTURE_EVENT = 31,
|
||||
CALL_OBSERVER = 33,
|
||||
REMOVE_OBSERVER = 34,
|
||||
|
|
|
@ -81,6 +81,42 @@ StaticAutoPtr<Mutex> nsAppShell::sAppShellLock;
|
|||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(nsAppShell, nsBaseAppShell, nsIObserver)
|
||||
|
||||
class ThumbnailRunnable : public Runnable {
|
||||
public:
|
||||
ThumbnailRunnable(nsIAndroidBrowserApp* aBrowserApp, int aTabId,
|
||||
const nsTArray<nsIntPoint>& aPoints, RefCountedJavaObject* aBuffer):
|
||||
mBrowserApp(aBrowserApp), mPoints(aPoints), mTabId(aTabId), mBuffer(aBuffer) {}
|
||||
|
||||
virtual nsresult Run() {
|
||||
const auto& buffer = jni::ByteBuffer::Ref::From(mBuffer->GetObject());
|
||||
nsCOMPtr<mozIDOMWindowProxy> domWindow;
|
||||
nsCOMPtr<nsIBrowserTab> tab;
|
||||
mBrowserApp->GetBrowserTab(mTabId, getter_AddRefs(tab));
|
||||
if (!tab) {
|
||||
widget::ThumbnailHelper::SendThumbnail(buffer, mTabId, false, false);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
tab->GetWindow(getter_AddRefs(domWindow));
|
||||
if (!domWindow) {
|
||||
widget::ThumbnailHelper::SendThumbnail(buffer, mTabId, false, false);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mPoints.Length() == 1, "Thumbnail event does not have enough coordinates");
|
||||
|
||||
bool shouldStore = true;
|
||||
nsresult rv = AndroidBridge::Bridge()->CaptureThumbnail(domWindow, mPoints[0].x, mPoints[0].y, mTabId, buffer, shouldStore);
|
||||
widget::ThumbnailHelper::SendThumbnail(buffer, mTabId, NS_SUCCEEDED(rv), shouldStore);
|
||||
return rv;
|
||||
}
|
||||
private:
|
||||
nsCOMPtr<nsIAndroidBrowserApp> mBrowserApp;
|
||||
nsTArray<nsIntPoint> mPoints;
|
||||
int mTabId;
|
||||
RefPtr<RefCountedJavaObject> mBuffer;
|
||||
};
|
||||
|
||||
class WakeLockListener final : public nsIDOMMozWakeLockListener {
|
||||
private:
|
||||
~WakeLockListener() {}
|
||||
|
@ -661,6 +697,18 @@ nsAppShell::LegacyGeckoEvent::Run()
|
|||
nsAppShell::Get()->NativeEventCallback();
|
||||
break;
|
||||
|
||||
case AndroidGeckoEvent::THUMBNAIL: {
|
||||
if (!nsAppShell::Get()->mBrowserApp)
|
||||
break;
|
||||
|
||||
int32_t tabId = curEvent->MetaState();
|
||||
const nsTArray<nsIntPoint>& points = curEvent->Points();
|
||||
RefCountedJavaObject* buffer = curEvent->ByteBuffer();
|
||||
RefPtr<ThumbnailRunnable> sr = new ThumbnailRunnable(nsAppShell::Get()->mBrowserApp, tabId, points, buffer);
|
||||
MessageLoop::current()->PostIdleTask(NewRunnableMethod(sr.get(), &ThumbnailRunnable::Run));
|
||||
break;
|
||||
}
|
||||
|
||||
case AndroidGeckoEvent::ZOOMEDVIEW: {
|
||||
if (!nsAppShell::Get()->mBrowserApp)
|
||||
break;
|
||||
|
|
Загрузка…
Ссылка в новой задаче